Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfsd-4.10-3' of git://linux-nfs.org/~bfields/linux

Pull nfsd revert from Bruce Fields:
"This patch turned out to have a couple problems. The problems are
fixable, but at least one of the fixes is a little ugly. The original
bug has always been there, so we can wait another week or two to get
this right"

* tag 'nfsd-4.10-3' of git://linux-nfs.org/~bfields/linux:
nfsd: Revert "nfsd: special case truncates some more"

+60 -37
+60 -37
fs/nfsd/vfs.c
··· 332 332 } 333 333 } 334 334 335 + static __be32 336 + nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp, 337 + struct iattr *iap) 338 + { 339 + struct inode *inode = d_inode(fhp->fh_dentry); 340 + int host_err; 341 + 342 + if (iap->ia_size < inode->i_size) { 343 + __be32 err; 344 + 345 + err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, 346 + NFSD_MAY_TRUNC | NFSD_MAY_OWNER_OVERRIDE); 347 + if (err) 348 + return err; 349 + } 350 + 351 + host_err = get_write_access(inode); 352 + if (host_err) 353 + goto out_nfserrno; 354 + 355 + host_err = locks_verify_truncate(inode, NULL, iap->ia_size); 356 + if (host_err) 357 + goto out_put_write_access; 358 + return 0; 359 + 360 + out_put_write_access: 361 + put_write_access(inode); 362 + out_nfserrno: 363 + return nfserrno(host_err); 364 + } 365 + 335 366 /* 336 367 * Set various file attributes. After this call fhp needs an fh_put. 337 368 */ ··· 377 346 __be32 err; 378 347 int host_err; 379 348 bool get_write_count; 349 + int size_change = 0; 380 350 381 351 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) 382 352 accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; ··· 390 358 /* Get inode */ 391 359 err = fh_verify(rqstp, fhp, ftype, accmode); 392 360 if (err) 393 - return err; 361 + goto out; 394 362 if (get_write_count) { 395 363 host_err = fh_want_write(fhp); 396 364 if (host_err) 397 - goto out_host_err; 365 + return nfserrno(host_err); 398 366 } 399 367 400 368 dentry = fhp->fh_dentry; ··· 405 373 iap->ia_valid &= ~ATTR_MODE; 406 374 407 375 if (!iap->ia_valid) 408 - return 0; 376 + goto out; 409 377 410 378 nfsd_sanitize_attrs(inode, iap); 411 379 412 - if (check_guard && guardtime != inode->i_ctime.tv_sec) 413 - return nfserr_notsync; 414 - 415 380 /* 416 381 * The size case is special, it changes the file in addition to the 417 - * attributes, and file systems don't expect it to be mixed with 418 - * "random" attribute changes. We thus split out the size change 419 - * into a separate call for vfs_truncate, and do the rest as a 420 - * a separate setattr call. 382 + * attributes. 421 383 */ 422 384 if (iap->ia_valid & ATTR_SIZE) { 423 - struct path path = { 424 - .mnt = fhp->fh_export->ex_path.mnt, 425 - .dentry = dentry, 426 - }; 427 - bool implicit_mtime = false; 385 + err = nfsd_get_write_access(rqstp, fhp, iap); 386 + if (err) 387 + goto out; 388 + size_change = 1; 428 389 429 390 /* 430 - * vfs_truncate implicity updates the mtime IFF the file size 431 - * actually changes. Avoid the additional seattr call below if 432 - * the only other attribute that the client sends is the mtime. 391 + * RFC5661, Section 18.30.4: 392 + * Changing the size of a file with SETATTR indirectly 393 + * changes the time_modify and change attributes. 394 + * 395 + * (and similar for the older RFCs) 433 396 */ 434 - if (iap->ia_size != i_size_read(inode) && 435 - ((iap->ia_valid & ~(ATTR_SIZE | ATTR_MTIME)) == 0)) 436 - implicit_mtime = true; 437 - 438 - host_err = vfs_truncate(&path, iap->ia_size); 439 - if (host_err) 440 - goto out_host_err; 441 - 442 - iap->ia_valid &= ~ATTR_SIZE; 443 - if (implicit_mtime) 444 - iap->ia_valid &= ~ATTR_MTIME; 445 - if (!iap->ia_valid) 446 - goto done; 397 + if (iap->ia_size != i_size_read(inode)) 398 + iap->ia_valid |= ATTR_MTIME; 447 399 } 448 400 449 401 iap->ia_valid |= ATTR_CTIME; 450 402 403 + if (check_guard && guardtime != inode->i_ctime.tv_sec) { 404 + err = nfserr_notsync; 405 + goto out_put_write_access; 406 + } 407 + 451 408 fh_lock(fhp); 452 409 host_err = notify_change(dentry, iap, NULL); 453 410 fh_unlock(fhp); 454 - if (host_err) 455 - goto out_host_err; 411 + err = nfserrno(host_err); 456 412 457 - done: 458 - host_err = commit_metadata(fhp); 459 - out_host_err: 460 - return nfserrno(host_err); 413 + out_put_write_access: 414 + if (size_change) 415 + put_write_access(inode); 416 + if (!err) 417 + err = nfserrno(commit_metadata(fhp)); 418 + out: 419 + return err; 461 420 } 462 421 463 422 #if defined(CONFIG_NFSD_V4)