nfsd-6.2 fixes:

- Fix a race when creating NFSv4 files
 - Revert the use of relaxed bitops
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEKLLlsBKG3yQ88j7+M2qzM29mf5cFAmO9twgACgkQM2qzM29m
 f5cQ/A//SSv/eZl2cnAMZtN1zd7wIMfI6E9y8Ccv49aebUXGmGDKSwz/CUns2sgO
 avWentInUYg2cexIjaQnQeGkiQt0Do+3u/cdT86h2e8q3UhvctYWO5uRCqbP+36H
 JRLfNUUbic4P8Yp/LZ5DvwOWae4PLdZq71mxJkaTXGHt8zLn/yEntCY8jb6V7D2L
 SxMXAoO05bdzfPc8lXKmaGi4JMsANEOMh5ZMRpKxKTEFQG352db17MqwOAW/Qe+t
 mMXY2jRfeufFwimmwLK06EzItgcs6D9g7dM3oIwDUNiPL4l3lOYeynbYOref7fD3
 4u11LwZdzZ5LYIZ0HoTpRu3ZxAbrTtmd1FiT7SwN9jjq1vu0Zx0sfqk0R9VixY3c
 jP+wYKEDTQUkIVdbG6g/u6yQZvwM281+GiAXoD3FJWKJDwAaqwxd6cphCn314RKY
 hlgG4DGhAi0BYbiLVu5ObQwRb1yPgCP2pXqguAdAKbTM2DVC2+hAW3NDUcIKrR1U
 JoXmGBaWeuJU9/0JbfVzddXUCs227hnovj1nmGW7E8JUegW4m+3oscEP8tsC5H5S
 J3Jr9ovxyYGQE1qxM5909hjPjrZxI3NszKIpgWoo9/jJLUWfGtnS2BclrXUxQrdl
 rvbKHvmSLyOsFYnZ5Nt7uj1l7LtWMljrjOjPqe02iU6pRDNHa9Y=
 =/7AX
 -----END PGP SIGNATURE-----

Merge tag 'nfsd-6.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

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
This commit is contained in:
Linus Torvalds 2023-01-10 15:03:06 -06:00
commit 7dd4b804e0
12 changed files with 59 additions and 89 deletions

View File

@ -1071,8 +1071,8 @@ nfsd_file_is_cached(struct inode *inode)
static __be32 static __be32
nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
unsigned int may_flags, struct nfsd_file **pnf, unsigned int may_flags, struct file *file,
bool open, bool want_gc) struct nfsd_file **pnf, bool want_gc)
{ {
struct nfsd_file_lookup_key key = { struct nfsd_file_lookup_key key = {
.type = NFSD_FILE_KEY_FULL, .type = NFSD_FILE_KEY_FULL,
@ -1147,8 +1147,7 @@ wait_for_construction:
status = nfserrno(nfsd_open_break_lease(file_inode(nf->nf_file), may_flags)); status = nfserrno(nfsd_open_break_lease(file_inode(nf->nf_file), may_flags));
out: out:
if (status == nfs_ok) { if (status == nfs_ok) {
if (open) this_cpu_inc(nfsd_file_acquisitions);
this_cpu_inc(nfsd_file_acquisitions);
*pnf = nf; *pnf = nf;
} else { } else {
if (refcount_dec_and_test(&nf->nf_ref)) if (refcount_dec_and_test(&nf->nf_ref))
@ -1158,20 +1157,23 @@ out:
out_status: out_status:
put_cred(key.cred); put_cred(key.cred);
if (open) trace_nfsd_file_acquire(rqstp, key.inode, may_flags, nf, status);
trace_nfsd_file_acquire(rqstp, key.inode, may_flags, nf, status);
return status; return status;
open_file: open_file:
trace_nfsd_file_alloc(nf); trace_nfsd_file_alloc(nf);
nf->nf_mark = nfsd_file_mark_find_or_create(nf, key.inode); nf->nf_mark = nfsd_file_mark_find_or_create(nf, key.inode);
if (nf->nf_mark) { 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, status = nfsd_open_verified(rqstp, fhp, may_flags,
&nf->nf_file); &nf->nf_file);
trace_nfsd_file_open(nf, status); trace_nfsd_file_open(nf, status);
} else }
status = nfs_ok;
} else } else
status = nfserr_jukebox; status = nfserr_jukebox;
/* /*
@ -1207,7 +1209,7 @@ __be32
nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp, nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp,
unsigned int may_flags, struct nfsd_file **pnf) 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, nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
unsigned int may_flags, struct nfsd_file **pnf) 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 * @rqstp: the RPC transaction being executed
* @fhp: the NFS filehandle of the file just created * @fhp: the NFS filehandle of the file just created
* @may_flags: NFSD_MAY_ settings for the file * @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 * @pnf: OUT: new or found "struct nfsd_file" object
* *
* The nfsd_file_object returned by this API is reference-counted * Acquire a nfsd_file object that is not GC'ed. If one doesn't already exist,
* but not garbage-collected. The object is released immediately * and @file is non-NULL, use it to instantiate a new nfsd_file instead of
* one RCU grace period after the final nfsd_file_put(). * opening a new one.
* *
* Returns nfs_ok and sets @pnf on success; otherwise an nfsstat in * Returns nfs_ok and sets @pnf on success; otherwise an nfsstat in
* network byte order is returned. * network byte order is returned.
*/ */
__be32 __be32
nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp, nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp,
unsigned int may_flags, struct nfsd_file **pnf) 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);
} }
/* /*

View File

@ -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); unsigned int may_flags, struct nfsd_file **nfp);
__be32 nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, __be32 nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
unsigned int may_flags, struct nfsd_file **nfp); unsigned int may_flags, struct nfsd_file **nfp);
__be32 nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp, __be32 nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp,
unsigned int may_flags, struct nfsd_file **nfp); unsigned int may_flags, struct file *file,
struct nfsd_file **nfp);
int nfsd_file_cache_stats_show(struct seq_file *m, void *v); int nfsd_file_cache_stats_show(struct seq_file *m, void *v);
#endif /* _FS_NFSD_FILECACHE_H */ #endif /* _FS_NFSD_FILECACHE_H */

View File

@ -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: * the client wants us to do more in this compound:
*/ */
if (!nfsd4_last_compound_op(rqstp)) if (!nfsd4_last_compound_op(rqstp))
__clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags); clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
/* check stateid */ /* check stateid */
status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh, 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; cstate->minorversion = args->minorversion;
fh_init(current_fh, NFS4_FHSIZE); fh_init(current_fh, NFS4_FHSIZE);
fh_init(save_fh, NFS4_FHSIZE); fh_init(save_fh, NFS4_FHSIZE);
/* /*
* Don't use the deferral mechanism for NFSv4; compounds make it * Don't use the deferral mechanism for NFSv4; compounds make it
* too hard to avoid non-idempotency problems. * 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. * According to RFC3010, this takes precedence over all other errors.
@ -2734,7 +2733,7 @@ encode_op:
out: out:
cstate->status = status; cstate->status = status;
/* Reset deferral mechanism for RPC deferrals */ /* Reset deferral mechanism for RPC deferrals */
__set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
return rpc_success; return rpc_success;
} }

View File

@ -5262,18 +5262,10 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
if (!fp->fi_fds[oflag]) { if (!fp->fi_fds[oflag]) {
spin_unlock(&fp->fi_lock); spin_unlock(&fp->fi_lock);
if (!open->op_filp) { status = nfsd_file_acquire_opened(rqstp, cur_fh, access,
status = nfsd_file_acquire(rqstp, cur_fh, access, &nf); open->op_filp, &nf);
if (status != nfs_ok) if (status != nfs_ok)
goto out_put_access; 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); spin_lock(&fp->fi_lock);
if (!fp->fi_fds[oflag]) { if (!fp->fi_fds[oflag]) {

View File

@ -2523,7 +2523,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack) 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; return true;
} }

View File

@ -211,7 +211,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
if (resp->status == nfs_ok) if (resp->status == nfs_ok)
resp->status = fh_getattr(&resp->fh, &resp->stat); resp->status = fh_getattr(&resp->fh, &resp->stat);
else if (resp->status == nfserr_jukebox) else if (resp->status == nfserr_jukebox)
__set_bit(RQ_DROPME, &rqstp->rq_flags); set_bit(RQ_DROPME, &rqstp->rq_flags);
return rpc_success; return rpc_success;
} }
@ -246,7 +246,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
if (resp->status == nfs_ok) if (resp->status == nfs_ok)
resp->status = fh_getattr(&resp->fh, &resp->stat); resp->status = fh_getattr(&resp->fh, &resp->stat);
else if (resp->status == nfserr_jukebox) else if (resp->status == nfserr_jukebox)
__set_bit(RQ_DROPME, &rqstp->rq_flags); set_bit(RQ_DROPME, &rqstp->rq_flags);
return rpc_success; return rpc_success;
} }

View File

@ -981,43 +981,6 @@ TRACE_EVENT(nfsd_file_acquire,
) )
); );
TRACE_EVENT(nfsd_file_create,
TP_PROTO(
const struct svc_rqst *rqstp,
unsigned int may_flags,
const struct nfsd_file *nf
),
TP_ARGS(rqstp, may_flags, nf),
TP_STRUCT__entry(
__field(const void *, nf_inode)
__field(const void *, nf_file)
__field(unsigned long, may_flags)
__field(unsigned long, nf_flags)
__field(unsigned long, nf_may)
__field(unsigned int, nf_ref)
__field(u32, xid)
),
TP_fast_assign(
__entry->nf_inode = nf->nf_inode;
__entry->nf_file = nf->nf_file;
__entry->may_flags = may_flags;
__entry->nf_flags = nf->nf_flags;
__entry->nf_may = nf->nf_may;
__entry->nf_ref = refcount_read(&nf->nf_ref);
__entry->xid = be32_to_cpu(rqstp->rq_xid);
),
TP_printk("xid=0x%x inode=%p may_flags=%s ref=%u nf_flags=%s nf_may=%s nf_file=%p",
__entry->xid, __entry->nf_inode,
show_nfsd_may_flags(__entry->may_flags),
__entry->nf_ref, show_nf_flags(__entry->nf_flags),
show_nfsd_may_flags(__entry->nf_may), __entry->nf_file
)
);
TRACE_EVENT(nfsd_file_insert_err, TRACE_EVENT(nfsd_file_insert_err,
TP_PROTO( TP_PROTO(
const struct svc_rqst *rqstp, const struct svc_rqst *rqstp,
@ -1079,8 +1042,8 @@ TRACE_EVENT(nfsd_file_cons_err,
) )
); );
TRACE_EVENT(nfsd_file_open, DECLARE_EVENT_CLASS(nfsd_file_open_class,
TP_PROTO(struct nfsd_file *nf, __be32 status), TP_PROTO(const struct nfsd_file *nf, __be32 status),
TP_ARGS(nf, status), TP_ARGS(nf, status),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(void *, nf_inode) /* cannot be dereferenced */ __field(void *, nf_inode) /* cannot be dereferenced */
@ -1104,6 +1067,17 @@ TRACE_EVENT(nfsd_file_open,
__entry->nf_file) __entry->nf_file)
) )
#define DEFINE_NFSD_FILE_OPEN_EVENT(name) \
DEFINE_EVENT(nfsd_file_open_class, name, \
TP_PROTO( \
const struct nfsd_file *nf, \
__be32 status \
), \
TP_ARGS(nf, status))
DEFINE_NFSD_FILE_OPEN_EVENT(nfsd_file_open);
DEFINE_NFSD_FILE_OPEN_EVENT(nfsd_file_opened);
TRACE_EVENT(nfsd_file_is_cached, TRACE_EVENT(nfsd_file_is_cached,
TP_PROTO( TP_PROTO(
const struct inode *inode, const struct inode *inode,

View File

@ -923,7 +923,7 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g
* rejecting the server-computed MIC in this somewhat rare case, * rejecting the server-computed MIC in this somewhat rare case,
* do not use splice with the GSS integrity service. * do not use splice with the GSS integrity service.
*/ */
__clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags); clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
/* Did we already verify the signature on the original pass through? */ /* Did we already verify the signature on the original pass through? */
if (rqstp->rq_deferred) if (rqstp->rq_deferred)
@ -990,7 +990,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
int pad, remaining_len, offset; int pad, remaining_len, offset;
u32 rseqno; u32 rseqno;
__clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags); clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
priv_len = svc_getnl(&buf->head[0]); priv_len = svc_getnl(&buf->head[0]);
if (rqstp->rq_deferred) { if (rqstp->rq_deferred) {

View File

@ -1243,10 +1243,10 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
goto err_short_len; goto err_short_len;
/* Will be turned off by GSS integrity and privacy services */ /* Will be turned off by GSS integrity and privacy services */
__set_bit(RQ_SPLICE_OK, &rqstp->rq_flags); set_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
/* Will be turned off only when NFSv4 Sessions are used */ /* Will be turned off only when NFSv4 Sessions are used */
__set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags); set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
__clear_bit(RQ_DROPME, &rqstp->rq_flags); clear_bit(RQ_DROPME, &rqstp->rq_flags);
svc_putu32(resv, rqstp->rq_xid); svc_putu32(resv, rqstp->rq_xid);

View File

@ -1238,7 +1238,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
trace_svc_defer(rqstp); trace_svc_defer(rqstp);
svc_xprt_get(rqstp->rq_xprt); svc_xprt_get(rqstp->rq_xprt);
dr->xprt = rqstp->rq_xprt; dr->xprt = rqstp->rq_xprt;
__set_bit(RQ_DROPME, &rqstp->rq_flags); set_bit(RQ_DROPME, &rqstp->rq_flags);
dr->handle.revisit = svc_revisit; dr->handle.revisit = svc_revisit;
return &dr->handle; return &dr->handle;

View File

@ -298,9 +298,9 @@ static void svc_sock_setbufsize(struct svc_sock *svsk, unsigned int nreqs)
static void svc_sock_secure_port(struct svc_rqst *rqstp) static void svc_sock_secure_port(struct svc_rqst *rqstp)
{ {
if (svc_port_is_privileged(svc_addr(rqstp))) if (svc_port_is_privileged(svc_addr(rqstp)))
__set_bit(RQ_SECURE, &rqstp->rq_flags); set_bit(RQ_SECURE, &rqstp->rq_flags);
else else
__clear_bit(RQ_SECURE, &rqstp->rq_flags); clear_bit(RQ_SECURE, &rqstp->rq_flags);
} }
/* /*
@ -1008,9 +1008,9 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
rqstp->rq_xprt_ctxt = NULL; rqstp->rq_xprt_ctxt = NULL;
rqstp->rq_prot = IPPROTO_TCP; rqstp->rq_prot = IPPROTO_TCP;
if (test_bit(XPT_LOCAL, &svsk->sk_xprt.xpt_flags)) if (test_bit(XPT_LOCAL, &svsk->sk_xprt.xpt_flags))
__set_bit(RQ_LOCAL, &rqstp->rq_flags); set_bit(RQ_LOCAL, &rqstp->rq_flags);
else else
__clear_bit(RQ_LOCAL, &rqstp->rq_flags); clear_bit(RQ_LOCAL, &rqstp->rq_flags);
p = (__be32 *)rqstp->rq_arg.head[0].iov_base; p = (__be32 *)rqstp->rq_arg.head[0].iov_base;
calldir = p[1]; calldir = p[1];

View File

@ -602,7 +602,7 @@ static int svc_rdma_has_wspace(struct svc_xprt *xprt)
static void svc_rdma_secure_port(struct svc_rqst *rqstp) static void svc_rdma_secure_port(struct svc_rqst *rqstp)
{ {
__set_bit(RQ_SECURE, &rqstp->rq_flags); set_bit(RQ_SECURE, &rqstp->rq_flags);
} }
static void svc_rdma_kill_temp_xprt(struct svc_xprt *xprt) static void svc_rdma_kill_temp_xprt(struct svc_xprt *xprt)