| From 987da4791052fa298b7cfcde4dea9f6f2bbc786b Mon Sep 17 00:00:00 2001 |
| From: Christoph Hellwig <hch@infradead.org> |
| Date: Mon, 18 Nov 2013 05:07:47 -0800 |
| Subject: nfsd: make sure to balance get/put_write_access |
| |
| From: Christoph Hellwig <hch@infradead.org> |
| |
| commit 987da4791052fa298b7cfcde4dea9f6f2bbc786b upstream. |
| |
| 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 |
| 6a76bebefe15d9a08864f824d7f8d5beaf37c997 "nfsd4: break lease on nfsd |
| setattr". |
| |
| Signed-off-by: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: J. Bruce Fields <bfields@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/nfsd/vfs.c | 29 +++++++++++++++-------------- |
| 1 file changed, 15 insertions(+), 14 deletions(-) |
| |
| --- a/fs/nfsd/vfs.c |
| +++ b/fs/nfsd/vfs.c |
| @@ -443,27 +443,28 @@ nfsd_setattr(struct svc_rqst *rqstp, str |
| |
| 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); |
| - 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); |
| + 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) || \ |