nfsd: make sure to balance get/put_write_access

Use a straight goto error label style in nfsd_setattr to make sure
we always do the put_write_access call after we got it earlier.

Note that the we have been failing to do that in the case
nfsd_break_lease() returns an error, a bug introduced into 2.6.38 with
6a76bebefe "nfsd4: break lease on nfsd
setattr".

Signed-off-by: Christoph Hellwig <hch@lst.de>
Cc: stable@vger.kernel.org
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
Christoph Hellwig 2013-11-18 05:07:47 -08:00 committed by J. Bruce Fields
parent 818e5a22e9
commit 987da47910
1 changed files with 15 additions and 14 deletions

View File

@ -444,27 +444,28 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
iap->ia_valid |= ATTR_CTIME;
err = nfserr_notsync;
if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
host_err = nfsd_break_lease(inode);
if (host_err)
goto out_nfserr;
fh_lock(fhp);
host_err = notify_change(dentry, iap, NULL);
err = nfserrno(host_err);
fh_unlock(fhp);
if (check_guard && guardtime != inode->i_ctime.tv_sec) {
err = nfserr_notsync;
goto out_put_write_access;
}
host_err = nfsd_break_lease(inode);
if (host_err)
goto out_put_write_access_nfserror;
fh_lock(fhp);
host_err = notify_change(dentry, iap, NULL);
fh_unlock(fhp);
out_put_write_access_nfserror:
err = nfserrno(host_err);
out_put_write_access:
if (size_change)
put_write_access(inode);
if (!err)
commit_metadata(fhp);
out:
return err;
out_nfserr:
err = nfserrno(host_err);
goto out;
}
#if defined(CONFIG_NFSD_V2_ACL) || \