Commit 7dd4b804 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull nfsd fixes from Chuck Lever:

 - Fix a race when creating NFSv4 files

 - Revert the use of relaxed bitops

* tag 'nfsd-6.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  NFSD: Use set_bit(RQ_DROPME)
  Revert "SUNRPC: Use RMW bitops in single-threaded hot paths"
  nfsd: fix handling of cached open files in nfsd4_open codepath
parents 092f6239 5304930d
Loading
Loading
Loading
Loading
+22 −18
Original line number Diff line number Diff line
@@ -1071,8 +1071,8 @@ nfsd_file_is_cached(struct inode *inode)

static __be32
nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
		     unsigned int may_flags, struct nfsd_file **pnf,
		     bool open, bool want_gc)
		     unsigned int may_flags, struct file *file,
		     struct nfsd_file **pnf, bool want_gc)
{
	struct nfsd_file_lookup_key key = {
		.type	= NFSD_FILE_KEY_FULL,
@@ -1147,7 +1147,6 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
	status = nfserrno(nfsd_open_break_lease(file_inode(nf->nf_file), may_flags));
out:
	if (status == nfs_ok) {
		if (open)
		this_cpu_inc(nfsd_file_acquisitions);
		*pnf = nf;
	} else {
@@ -1158,7 +1157,6 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,

out_status:
	put_cred(key.cred);
	if (open)
	trace_nfsd_file_acquire(rqstp, key.inode, may_flags, nf, status);
	return status;

@@ -1166,12 +1164,16 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
	trace_nfsd_file_alloc(nf);
	nf->nf_mark = nfsd_file_mark_find_or_create(nf, key.inode);
	if (nf->nf_mark) {
		if (open) {
		if (file) {
			get_file(file);
			nf->nf_file = file;
			status = nfs_ok;
			trace_nfsd_file_opened(nf, status);
		} else {
			status = nfsd_open_verified(rqstp, fhp, may_flags,
						    &nf->nf_file);
			trace_nfsd_file_open(nf, status);
		} else
			status = nfs_ok;
		}
	} else
		status = nfserr_jukebox;
	/*
@@ -1207,7 +1209,7 @@ __be32
nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp,
		     unsigned int may_flags, struct nfsd_file **pnf)
{
	return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, true, true);
	return nfsd_file_do_acquire(rqstp, fhp, may_flags, NULL, pnf, true);
}

/**
@@ -1228,28 +1230,30 @@ __be32
nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
		  unsigned int may_flags, struct nfsd_file **pnf)
{
	return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, true, false);
	return nfsd_file_do_acquire(rqstp, fhp, may_flags, NULL, pnf, false);
}

/**
 * nfsd_file_create - Get a struct nfsd_file, do not open
 * nfsd_file_acquire_opened - Get a struct nfsd_file using existing open file
 * @rqstp: the RPC transaction being executed
 * @fhp: the NFS filehandle of the file just created
 * @may_flags: NFSD_MAY_ settings for the file
 * @file: cached, already-open file (may be NULL)
 * @pnf: OUT: new or found "struct nfsd_file" object
 *
 * The nfsd_file_object returned by this API is reference-counted
 * but not garbage-collected. The object is released immediately
 * one RCU grace period after the final nfsd_file_put().
 * Acquire a nfsd_file object that is not GC'ed. If one doesn't already exist,
 * and @file is non-NULL, use it to instantiate a new nfsd_file instead of
 * opening a new one.
 *
 * Returns nfs_ok and sets @pnf on success; otherwise an nfsstat in
 * network byte order is returned.
 */
__be32
nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
		 unsigned int may_flags, struct nfsd_file **pnf)
nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp,
			 unsigned int may_flags, struct file *file,
			 struct nfsd_file **pnf)
{
	return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, false, false);
	return nfsd_file_do_acquire(rqstp, fhp, may_flags, file, pnf, false);
}

/*
+3 −2
Original line number Diff line number Diff line
@@ -60,7 +60,8 @@ __be32 nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp,
		  unsigned int may_flags, struct nfsd_file **nfp);
__be32 nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
		  unsigned int may_flags, struct nfsd_file **nfp);
__be32 nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
		  unsigned int may_flags, struct nfsd_file **nfp);
__be32 nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp,
		  unsigned int may_flags, struct file *file,
		  struct nfsd_file **nfp);
int nfsd_file_cache_stats_show(struct seq_file *m, void *v);
#endif /* _FS_NFSD_FILECACHE_H */
+3 −4
Original line number Diff line number Diff line
@@ -937,7 +937,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	 * the client wants us to do more in this compound:
	 */
	if (!nfsd4_last_compound_op(rqstp))
		__clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
		clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);

	/* check stateid */
	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
@@ -2607,12 +2607,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
	cstate->minorversion = args->minorversion;
	fh_init(current_fh, NFS4_FHSIZE);
	fh_init(save_fh, NFS4_FHSIZE);

	/*
	 * Don't use the deferral mechanism for NFSv4; compounds make it
	 * too hard to avoid non-idempotency problems.
	 */
	__clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);

	/*
	 * According to RFC3010, this takes precedence over all other errors.
@@ -2734,7 +2733,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
out:
	cstate->status = status;
	/* Reset deferral mechanism for RPC deferrals */
	__set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
	return rpc_success;
}

+4 −12
Original line number Diff line number Diff line
@@ -5262,18 +5262,10 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
	if (!fp->fi_fds[oflag]) {
		spin_unlock(&fp->fi_lock);

		if (!open->op_filp) {
			status = nfsd_file_acquire(rqstp, cur_fh, access, &nf);
		status = nfsd_file_acquire_opened(rqstp, cur_fh, access,
						  open->op_filp, &nf);
		if (status != nfs_ok)
			goto out_put_access;
		} else {
			status = nfsd_file_create(rqstp, cur_fh, access, &nf);
			if (status != nfs_ok)
				goto out_put_access;
			nf->nf_file = open->op_filp;
			open->op_filp = NULL;
			trace_nfsd_file_create(rqstp, access, nf);
		}

		spin_lock(&fp->fi_lock);
		if (!fp->fi_fds[oflag]) {
+1 −1
Original line number Diff line number Diff line
@@ -2523,7 +2523,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
	argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;

	if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack)
		__clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags);
		clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags);

	return true;
}
Loading