]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFSD: release read access of nfs4_file when a write delegation is returned
authorDai Ngo <dai.ngo@oracle.com>
Tue, 13 May 2025 16:10:51 +0000 (09:10 -0700)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 14 Jul 2025 16:46:36 +0000 (12:46 -0400)
When a write delegation is returned, check if read access was added
to nfs4_file when client opens file with WRONLY, and release it.

Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4state.c
fs/nfsd/state.h

index 54fb323598ea24981894d1a2dd4758934cbd41c3..a0e3fa2718c7ef331925e9ba8f2a66f331c76db5 100644 (file)
@@ -1206,15 +1206,20 @@ nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid)
 
 static void put_deleg_file(struct nfs4_file *fp)
 {
+       struct nfsd_file *rnf = NULL;
        struct nfsd_file *nf = NULL;
 
        spin_lock(&fp->fi_lock);
-       if (--fp->fi_delegees == 0)
+       if (--fp->fi_delegees == 0) {
                swap(nf, fp->fi_deleg_file);
+               swap(rnf, fp->fi_rdeleg_file);
+       }
        spin_unlock(&fp->fi_lock);
 
        if (nf)
                nfsd_file_put(nf);
+       if (rnf)
+               nfs4_file_put_access(fp, NFS4_SHARE_ACCESS_READ);
 }
 
 static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
@@ -4738,6 +4743,7 @@ static void nfsd4_file_init(const struct svc_fh *fh, struct nfs4_file *fp)
        INIT_LIST_HEAD(&fp->fi_clnt_odstate);
        fh_copy_shallow(&fp->fi_fhandle, &fh->fh_handle);
        fp->fi_deleg_file = NULL;
+       fp->fi_rdeleg_file = NULL;
        fp->fi_had_conflict = false;
        fp->fi_share_deny = 0;
        memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
@@ -6171,6 +6177,7 @@ nfsd4_add_rdaccess_to_wrdeleg(struct svc_rqst *rqstp, struct nfsd4_open *open,
                __nfs4_file_get_access(fp, NFS4_SHARE_ACCESS_READ);
                fp = stp->st_stid.sc_file;
                fp->fi_fds[O_RDONLY] = nf;
+               fp->fi_rdeleg_file = nf;
                spin_unlock(&fp->fi_lock);
        }
        return true;
index 1995bca158b8b7eb7cef6aefa13bc1d5e7cf6093..8adc2550129e67a4e6646395fa2811e1c2acb98e 100644 (file)
@@ -665,6 +665,7 @@ struct nfs4_file {
        atomic_t                fi_access[2];
        u32                     fi_share_deny;
        struct nfsd_file        *fi_deleg_file;
+       struct nfsd_file        *fi_rdeleg_file;
        int                     fi_delegees;
        struct knfsd_fh         fi_fhandle;
        bool                    fi_had_conflict;