diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 43 |
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); |