Merge tag 'nfsd-6.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Jan 2023 21:03:06 +0000 (15:03 -0600)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Jan 2023 21:03:06 +0000 (15:03 -0600)
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

12 files changed:
fs/nfsd/filecache.c
fs/nfsd/filecache.h
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsproc.c
fs/nfsd/trace.h
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/svc.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
net/sunrpc/xprtrdma/svc_rdma_transport.c

index 45b2c9e3f6360038e0d41191f61e8cd7497577df..0ef0703490144b4017583b26d24547c66f3d9480 100644 (file)
@@ -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,8 +1147,7 @@ wait_for_construction:
        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);
+               this_cpu_inc(nfsd_file_acquisitions);
                *pnf = nf;
        } else {
                if (refcount_dec_and_test(&nf->nf_ref))
@@ -1158,20 +1157,23 @@ out:
 
 out_status:
        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;
 
 open_file:
        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);
 }
 
 /*
index b7efb2c3ddb18527d503322a792fc21dd8f8be7e..41516a4263ea519c8af05e85d82f8ca87a248e4f 100644 (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);
 __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 */
index bd880d55f565b0eb8a97b63bcceab144e4a59ecf..9b81d012666e2c408495c6505553991a15a4a8e7 100644 (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:
         */
        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 @@ encode_op:
 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;
 }
 
index 7b2ee535ade83235e0acaf5b4c6a9d1e75ecdd56..4809ae0f013850928898ee32a5cac845db8d7156 100644 (file)
@@ -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);
-                       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);
-               }
+               status = nfsd_file_acquire_opened(rqstp, cur_fh, access,
+                                                 open->op_filp, &nf);
+               if (status != nfs_ok)
+                       goto out_put_access;
 
                spin_lock(&fp->fi_lock);
                if (!fp->fi_fds[oflag]) {
index ebb4d02a42ce68110c564b09245202228f6f2864..97edb32be77f187832c479a76ea3a29ffd7c80a6 100644 (file)
@@ -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;
 }
index a5570cf75f3fd550a38b6b82fffdba4039fa9503..9744443c396522af6bf9ae34eca57c60a133cc8f 100644 (file)
@@ -211,7 +211,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
        if (resp->status == nfs_ok)
                resp->status = fh_getattr(&resp->fh, &resp->stat);
        else if (resp->status == nfserr_jukebox)
-               __set_bit(RQ_DROPME, &rqstp->rq_flags);
+               set_bit(RQ_DROPME, &rqstp->rq_flags);
        return rpc_success;
 }
 
@@ -246,7 +246,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)
        if (resp->status == nfs_ok)
                resp->status = fh_getattr(&resp->fh, &resp->stat);
        else if (resp->status == nfserr_jukebox)
-               __set_bit(RQ_DROPME, &rqstp->rq_flags);
+               set_bit(RQ_DROPME, &rqstp->rq_flags);
        return rpc_success;
 }
 
index c852ae8eaf3714bcdc084492c1f7208928f388bb..8f9c82d9e075b286ac875ae36fb26d3d249174a4 100644 (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,
        TP_PROTO(
                const struct svc_rqst *rqstp,
@@ -1079,8 +1042,8 @@ TRACE_EVENT(nfsd_file_cons_err,
        )
 );
 
-TRACE_EVENT(nfsd_file_open,
-       TP_PROTO(struct nfsd_file *nf, __be32 status),
+DECLARE_EVENT_CLASS(nfsd_file_open_class,
+       TP_PROTO(const struct nfsd_file *nf, __be32 status),
        TP_ARGS(nf, status),
        TP_STRUCT__entry(
                __field(void *, nf_inode)       /* cannot be dereferenced */
@@ -1104,6 +1067,17 @@ TRACE_EVENT(nfsd_file_open,
                __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,
        TP_PROTO(
                const struct inode *inode,
index 148bb0a7fa5b4aae7f67bace1f43c9501d2841cb..acb822b23af1b01cd0b30d8346813bb671920901 100644 (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,
         * 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? */
        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;
        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]);
        if (rqstp->rq_deferred) {
index 85f0c3cfc87745f26aa3f8d869c71f136be22997..f06622814a958a5248d8407dd60024360c9019c9 100644 (file)
@@ -1243,10 +1243,10 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
                goto err_short_len;
 
        /* 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 */
-       __set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
-       __clear_bit(RQ_DROPME, &rqstp->rq_flags);
+       set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
+       clear_bit(RQ_DROPME, &rqstp->rq_flags);
 
        svc_putu32(resv, rqstp->rq_xid);
 
index 2106003645a78d7a441efc839f3e31c58af186d1..c2ce12538008070e6d56bb0cdc24d727e9a9c487 100644 (file)
@@ -1238,7 +1238,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
        trace_svc_defer(rqstp);
        svc_xprt_get(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;
        return &dr->handle;
index 015714398007aef28bcf5957a0994dc7cc5f4f5c..815baf308236a9d20ed7103603cfbc2af1fa1bd9 100644 (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)
 {
        if (svc_port_is_privileged(svc_addr(rqstp)))
-               __set_bit(RQ_SECURE, &rqstp->rq_flags);
+               set_bit(RQ_SECURE, &rqstp->rq_flags);
        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_prot        = IPPROTO_TCP;
        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
-               __clear_bit(RQ_LOCAL, &rqstp->rq_flags);
+               clear_bit(RQ_LOCAL, &rqstp->rq_flags);
 
        p = (__be32 *)rqstp->rq_arg.head[0].iov_base;
        calldir = p[1];
index 199fa012f18a879a6d3389dfc3b125cc12d14678..94b20fb471356356885da1b482750f387c82c9ab 100644 (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)
 {
-       __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)