aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 085ded6f6d3a..2a8d665b134b 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -289,7 +289,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
289 if (!iap->ia_valid) 289 if (!iap->ia_valid)
290 goto out; 290 goto out;
291 291
292 /* NFSv2 does not differentiate between "set-[ac]time-to-now" 292 /*
293 * NFSv2 does not differentiate between "set-[ac]time-to-now"
293 * which only requires access, and "set-[ac]time-to-X" which 294 * which only requires access, and "set-[ac]time-to-X" which
294 * requires ownership. 295 * requires ownership.
295 * So if it looks like it might be "set both to the same time which 296 * So if it looks like it might be "set both to the same time which
@@ -302,25 +303,33 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
302 */ 303 */
303#define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) 304#define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
304#define MAX_TOUCH_TIME_ERROR (30*60) 305#define MAX_TOUCH_TIME_ERROR (30*60)
305 if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET 306 if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET &&
306 && iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec 307 iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) {
307 ) { 308 /*
308 /* Looks probable. Now just make sure time is in the right ballpark. 309 * Looks probable.
309 * Solaris, at least, doesn't seem to care what the time request is. 310 *
310 * We require it be within 30 minutes of now. 311 * Now just make sure time is in the right ballpark.
311 */ 312 * Solaris, at least, doesn't seem to care what the time
312 time_t delta = iap->ia_atime.tv_sec - get_seconds(); 313 * request is. We require it be within 30 minutes of now.
313 if (delta<0) delta = -delta;
314 if (delta < MAX_TOUCH_TIME_ERROR &&
315 inode_change_ok(inode, iap) != 0) {
316 /* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME
317 * this will cause notify_change to set these times to "now"
318 */ 314 */
319 iap->ia_valid &= ~BOTH_TIME_SET; 315 time_t delta = iap->ia_atime.tv_sec - get_seconds();
320 } 316 if (delta < 0)
317 delta = -delta;
318 if (delta < MAX_TOUCH_TIME_ERROR &&
319 inode_change_ok(inode, iap) != 0) {
320 /*
321 * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME.
322 * This will cause notify_change to set these times
323 * to "now"
324 */
325 iap->ia_valid &= ~BOTH_TIME_SET;
326 }
321 } 327 }
322 328
323 /* The size case is special. It changes the file as well as the attributes. */ 329 /*
330 * The size case is special.
331 * It changes the file as well as the attributes.
332 */
324 if (iap->ia_valid & ATTR_SIZE) { 333 if (iap->ia_valid & ATTR_SIZE) {
325 if (iap->ia_size < inode->i_size) { 334 if (iap->ia_size < inode->i_size) {
326 err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE); 335 err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);