Skip to content

Commit

Permalink
nfsd4: fix delegation cleanup on error
Browse files Browse the repository at this point in the history
We're not cleaning up everything we need to on error.  In particular,
we're not removing our lease.  Among other problems this can cause the
struct nfs4_file used as fl_owner to be referenced after it has been
destroyed.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
  • Loading branch information
J. Bruce Fields committed May 21, 2014
1 parent 368fe39 commit cbf7a75
Showing 1 changed file with 12 additions and 20 deletions.
32 changes: 12 additions & 20 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ nfs4_put_delegation(struct nfs4_delegation *dp)

static void nfs4_put_deleg_lease(struct nfs4_file *fp)
{
if (!fp->fi_lease)
return;
if (atomic_dec_and_test(&fp->fi_delegees)) {
vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease);
fp->fi_lease = NULL;
Expand All @@ -440,9 +442,11 @@ unhash_delegation(struct nfs4_delegation *dp)
list_del_init(&dp->dl_perfile);
list_del_init(&dp->dl_recall_lru);
spin_unlock(&recall_lock);
nfs4_put_deleg_lease(dp->dl_file);
put_nfs4_file(dp->dl_file);
dp->dl_file = NULL;
if (dp->dl_file) {
nfs4_put_deleg_lease(dp->dl_file);
put_nfs4_file(dp->dl_file);
dp->dl_file = NULL;
}
}


Expand Down Expand Up @@ -3060,33 +3064,22 @@ static int nfs4_setlease(struct nfs4_delegation *dp)

static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp)
{
int status;

if (fp->fi_had_conflict)
return -EAGAIN;
get_nfs4_file(fp);
dp->dl_file = fp;
if (!fp->fi_lease) {
status = nfs4_setlease(dp);
if (status)
goto out_free;
return 0;
}
if (!fp->fi_lease)
return nfs4_setlease(dp);
spin_lock(&recall_lock);
atomic_inc(&fp->fi_delegees);
if (fp->fi_had_conflict) {
spin_unlock(&recall_lock);
status = -EAGAIN;
goto out_free;
return -EAGAIN;
}
atomic_inc(&fp->fi_delegees);
list_add(&dp->dl_perfile, &fp->fi_delegations);
spin_unlock(&recall_lock);
list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
return 0;
out_free:
put_nfs4_file(fp);
dp->dl_file = fp;
return status;
}

static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
Expand Down Expand Up @@ -3173,8 +3166,7 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
return;
out_free:
remove_stid(&dp->dl_stid);
nfs4_put_delegation(dp);
destroy_delegation(dp);
out_no_deleg:
open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
Expand Down

0 comments on commit cbf7a75

Please sign in to comment.