aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-24 11:32:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-24 11:32:11 -0400
commit6c5daf012c9155aafd2c7973e4278766c30dfad0 (patch)
tree33959d7b36d03e1610615641a2940cb2de5e8603 /fs/nfs
parent6d39b27f0ac7e805ae3bd9efa51d7da04bec0360 (diff)
parentc08d3b0e33edce28e9cfa7b64f7fe5bdeeb29248 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: truncate: use new helpers truncate: new helpers fs: fix overflow in sys_mount() for in-kernel calls fs: Make unload_nls() NULL pointer safe freeze_bdev: grab active reference to frozen superblocks freeze_bdev: kill bd_mount_sem exofs: remove BKL from super operations fs/romfs: correct error-handling code vfs: seq_file: add helpers for data filling vfs: remove redundant position check in do_sendfile vfs: change sb->s_maxbytes to a loff_t vfs: explicitly cast s_maxbytes in fiemap_check_ranges libfs: return error code on failed attr set seq_file: return a negative error code when seq_path_root() fails. vfs: optimize touch_time() too vfs: optimization for touch_atime() vfs: split generic_forget_inode() so that hugetlbfs does not have to copy it fs/inode.c: add dev-id and inode number for debugging in init_special_inode() libfs: make simple_read_from_buffer conventional
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/inode.c54
1 files changed, 13 insertions, 41 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 060022b4651c..faa091865ad0 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -458,49 +458,21 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
458 */ 458 */
459static int nfs_vmtruncate(struct inode * inode, loff_t offset) 459static int nfs_vmtruncate(struct inode * inode, loff_t offset)
460{ 460{
461 if (i_size_read(inode) < offset) { 461 loff_t oldsize;
462 unsigned long limit; 462 int err;
463
464 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
465 if (limit != RLIM_INFINITY && offset > limit)
466 goto out_sig;
467 if (offset > inode->i_sb->s_maxbytes)
468 goto out_big;
469 spin_lock(&inode->i_lock);
470 i_size_write(inode, offset);
471 spin_unlock(&inode->i_lock);
472 } else {
473 struct address_space *mapping = inode->i_mapping;
474 463
475 /* 464 err = inode_newsize_ok(inode, offset);
476 * truncation of in-use swapfiles is disallowed - it would 465 if (err)
477 * cause subsequent swapout to scribble on the now-freed 466 goto out;
478 * blocks.
479 */
480 if (IS_SWAPFILE(inode))
481 return -ETXTBSY;
482 spin_lock(&inode->i_lock);
483 i_size_write(inode, offset);
484 spin_unlock(&inode->i_lock);
485 467
486 /* 468 spin_lock(&inode->i_lock);
487 * unmap_mapping_range is called twice, first simply for 469 oldsize = inode->i_size;
488 * efficiency so that truncate_inode_pages does fewer 470 i_size_write(inode, offset);
489 * single-page unmaps. However after this first call, and 471 spin_unlock(&inode->i_lock);
490 * before truncate_inode_pages finishes, it is possible for 472
491 * private pages to be COWed, which remain after 473 truncate_pagecache(inode, oldsize, offset);
492 * truncate_inode_pages finishes, hence the second 474out:
493 * unmap_mapping_range call must be made for correctness. 475 return err;
494 */
495 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
496 truncate_inode_pages(mapping, offset);
497 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
498 }
499 return 0;
500out_sig:
501 send_sig(SIGXFSZ, current, 0);
502out_big:
503 return -EFBIG;
504} 476}
505 477
506/** 478/**