nfsd: clean up nfs4_set_delegation
authorJeff Layton <jlayton@primarydata.com>
Fri, 25 Jul 2014 11:34:25 +0000 (07:34 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Tue, 29 Jul 2014 18:49:56 +0000 (14:49 -0400)
Move the alloc_init_deleg call into nfs4_set_delegation and change the
function to return a pointer to the delegation or an IS_ERR return. This
allows us to skip allocating a delegation if the file has already
experienced a lease conflict.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs4state.c

index 24065e1..85d7ac6 100644 (file)
@@ -3552,12 +3552,20 @@ out_fput:
        return status;
 }
 
-static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp)
+static struct nfs4_delegation *
+nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
+                   struct nfs4_file *fp)
 {
-       int status = 0;
+       int status;
+       struct nfs4_delegation *dp;
 
        if (fp->fi_had_conflict)
-               return -EAGAIN;
+               return ERR_PTR(-EAGAIN);
+
+       dp = alloc_init_deleg(clp, fh);
+       if (!dp)
+               return ERR_PTR(-ENOMEM);
+
        get_nfs4_file(fp);
        spin_lock(&state_lock);
        spin_lock(&fp->fi_lock);
@@ -3565,7 +3573,8 @@ static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp)
        if (!fp->fi_lease) {
                spin_unlock(&fp->fi_lock);
                spin_unlock(&state_lock);
-               return nfs4_setlease(dp);
+               status = nfs4_setlease(dp);
+               goto out;
        }
        atomic_inc(&fp->fi_delegees);
        if (fp->fi_had_conflict) {
@@ -3573,10 +3582,16 @@ static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp)
                goto out_unlock;
        }
        hash_delegation_locked(dp, fp);
+       status = 0;
 out_unlock:
        spin_unlock(&fp->fi_lock);
        spin_unlock(&state_lock);
-       return status;
+out:
+       if (status) {
+               nfs4_put_delegation(dp);
+               return ERR_PTR(status);
+       }
+       return dp;
 }
 
 static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
@@ -3650,12 +3665,9 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
                default:
                        goto out_no_deleg;
        }
-       dp = alloc_init_deleg(clp, fh);
-       if (dp == NULL)
+       dp = nfs4_set_delegation(clp, fh, stp->st_file);
+       if (IS_ERR(dp))
                goto out_no_deleg;
-       status = nfs4_set_delegation(dp, stp->st_file);
-       if (status)
-               goto out_free;
 
        memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
 
@@ -3663,8 +3675,6 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
                STATEID_VAL(&dp->dl_stid.sc_stateid));
        open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
        return;
-out_free:
-       nfs4_put_delegation(dp);
 out_no_deleg:
        open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
        if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&