]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
nfsd: Make init_open_stateid() a bit more whole
authorOleg Drokin <green@linuxhacker.ru>
Wed, 15 Jun 2016 03:28:06 +0000 (23:28 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Dec 2017 10:22:52 +0000 (11:22 +0100)
commit 8c7245abda877d4689b3371db8ae2a4400d7d9ce upstream.

Move the state selection logic inside from the caller,
always making it return correct stp to use.

Signed-off-by: J . Bruce Fields <bfields@fieldses.org>
Signed-off-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/nfsd/nfs4state.c

index 421935f3d90956ebba16fa00b3a878be84a9ee40..76caee97d2cdd50f08017182e3741a29fc01f602 100644 (file)
@@ -3420,13 +3420,14 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
 }
 
 static struct nfs4_ol_stateid *
-init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
-               struct nfsd4_open *open)
+init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
 {
 
        struct nfs4_openowner *oo = open->op_openowner;
        struct nfs4_ol_stateid *retstp = NULL;
+       struct nfs4_ol_stateid *stp;
 
+       stp = open->op_stp;
        /* We are moving these outside of the spinlocks to avoid the warnings */
        mutex_init(&stp->st_mutex);
        mutex_lock(&stp->st_mutex);
@@ -3437,6 +3438,8 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
        retstp = nfsd4_find_existing_open(fp, open);
        if (retstp)
                goto out_unlock;
+
+       open->op_stp = NULL;
        atomic_inc(&stp->st_stid.sc_count);
        stp->st_stid.sc_type = NFS4_OPEN_STID;
        INIT_LIST_HEAD(&stp->st_locks);
@@ -3454,10 +3457,11 @@ out_unlock:
        spin_unlock(&oo->oo_owner.so_client->cl_lock);
        if (retstp) {
                mutex_lock(&retstp->st_mutex);
-               /* Not that we need to, just for neatness */
+               /* To keep mutex tracking happy */
                mutex_unlock(&stp->st_mutex);
+               stp = retstp;
        }
-       return retstp;
+       return stp;
 }
 
 /*
@@ -4260,7 +4264,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
        struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
        struct nfs4_file *fp = NULL;
        struct nfs4_ol_stateid *stp = NULL;
-       struct nfs4_ol_stateid *swapstp = NULL;
        struct nfs4_delegation *dp = NULL;
        __be32 status;
 
@@ -4297,16 +4300,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
                        goto out;
                }
        } else {
-               stp = open->op_stp;
-               open->op_stp = NULL;
-               /*
-                * init_open_stateid() either returns a locked stateid
-                * it found, or initializes and locks the new one we passed in
-                */
-               swapstp = init_open_stateid(stp, fp, open);
-               if (swapstp) {
-                       nfs4_put_stid(&stp->st_stid);
-                       stp = swapstp;
+               /* stp is returned locked. */
+               stp = init_open_stateid(fp, open);
+               /* See if we lost the race to some other thread */
+               if (stp->st_access_bmap != 0) {
                        status = nfs4_upgrade_open(rqstp, fp, current_fh,
                                                stp, open);
                        if (status) {