X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=fs%2Fnfsd%2Fvfs.c;fp=fs%2Fnfsd%2Fvfs.c;h=acabafd9d0e037e76be1ec2fd5637605432244e2;hp=56bdccc9df968c2ee259455fc240804127d71984;hb=604a3c407026d6162d15300478e63f901e435efc;hpb=b138627842f7cd4b948e29a7a365f0382d32f842 diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 56bdccc9df96..acabafd9d0e0 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -446,13 +446,23 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, /* * The size case is special, it changes the file in addition to the - * attributes. + * attributes, and file systems don't expect it to be mixed with + * "random" attribute changes. We thus split out the size change + * into a separate call to ->setattr, and do the rest as a separate + * setattr call. */ if (size_change) { err = nfsd_get_write_access(rqstp, fhp, iap); if (err) return err; + } + + host_err = nfsd_break_lease(inode); + if (host_err) + goto out_put_write_access_nfserror; + fh_lock(fhp); + if (size_change) { /* * RFC5661, Section 18.30.4: * Changing the size of a file with SETATTR indirectly @@ -460,20 +470,30 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, * * (and similar for the older RFCs) */ - if (iap->ia_size != i_size_read(inode)) - iap->ia_valid |= ATTR_MTIME; - } + struct iattr size_attr = { + .ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME, + .ia_size = iap->ia_size, + }; - iap->ia_valid |= ATTR_CTIME; + host_err = notify_change(dentry, &size_attr); + if (host_err) + goto out_unlock; + iap->ia_valid &= ~ATTR_SIZE; - host_err = nfsd_break_lease(inode); - if (host_err) - goto out_put_write_access_nfserror; + /* + * Avoid the additional setattr call below if the only other + * attribute that the client sends is the mtime, as we update + * it as part of the size change above. + */ + if ((iap->ia_valid & ~ATTR_MTIME) == 0) + goto out_unlock; + } - fh_lock(fhp); + iap->ia_valid |= ATTR_CTIME; host_err = notify_change(dentry, iap); - fh_unlock(fhp); +out_unlock: + fh_unlock(fhp); out_put_write_access_nfserror: if (size_change) put_write_access(inode);