summaryrefslogtreecommitdiff
path: root/fs/nfsd/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r--fs/nfsd/nfs4proc.c41
1 files changed, 18 insertions, 23 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 5d99e8810b85..b7bc6e1a85ac 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -354,6 +354,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct svc_fh *resfh = NULL;
struct net *net = SVC_NET(rqstp);
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+ bool reclaim = false;
dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
(int)open->op_fname.len, open->op_fname.data,
@@ -424,6 +425,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (status)
goto out;
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
+ reclaim = true;
case NFS4_OPEN_CLAIM_FH:
case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
status = do_open_fhandle(rqstp, cstate, open);
@@ -452,6 +454,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
WARN(status && open->op_created,
"nfsd4_process_open2 failed to open newly-created file! status=%u\n",
be32_to_cpu(status));
+ if (reclaim && !status)
+ nn->somebody_reclaimed = true;
out:
if (resfh && resfh != &cstate->current_fh) {
fh_dup2(&cstate->current_fh, resfh);
@@ -982,24 +986,6 @@ out:
return status;
}
-static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
-{
- int i = 1;
- int buflen = write->wr_buflen;
-
- vec[0].iov_base = write->wr_head.iov_base;
- vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len);
- buflen -= vec[0].iov_len;
-
- while (buflen) {
- vec[i].iov_base = page_address(write->wr_pagelist[i - 1]);
- vec[i].iov_len = min_t(int, PAGE_SIZE, buflen);
- buflen -= vec[i].iov_len;
- i++;
- }
- return i;
-}
-
static __be32
nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
union nfsd4_op_u *u)
@@ -1027,7 +1013,10 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
write->wr_how_written = write->wr_stable_how;
gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp));
- nvecs = fill_in_write_vector(rqstp->rq_vec, write);
+ nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
+ &write->wr_head, write->wr_buflen);
+ if (!nvecs)
+ return nfserr_io;
WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp,
@@ -1599,7 +1588,7 @@ static const char *nfsd4_op_name(unsigned opnum);
*/
static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
{
- struct nfsd4_op *op = &args->ops[0];
+ struct nfsd4_op *first_op = &args->ops[0];
/* These ordering requirements don't apply to NFSv4.0: */
if (args->minorversion == 0)
@@ -1607,12 +1596,17 @@ static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
/* This is weird, but OK, not our problem: */
if (args->opcnt == 0)
return nfs_ok;
- if (op->status == nfserr_op_illegal)
+ if (first_op->status == nfserr_op_illegal)
return nfs_ok;
- if (!(nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
+ if (!(nfsd4_ops[first_op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
return nfserr_op_not_in_session;
- if (op->opnum == OP_SEQUENCE)
+ if (first_op->opnum == OP_SEQUENCE)
return nfs_ok;
+ /*
+ * So first_op is something allowed outside a session, like
+ * EXCHANGE_ID; but then it has to be the only op in the
+ * compound:
+ */
if (args->opcnt != 1)
return nfserr_not_only_op;
return nfs_ok;
@@ -1726,6 +1720,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
if (status) {
op = &args->ops[0];
op->status = status;
+ resp->opcnt = 1;
goto encode_op;
}