diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-24 11:32:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-24 11:32:11 -0400 |
commit | 6c5daf012c9155aafd2c7973e4278766c30dfad0 (patch) | |
tree | 33959d7b36d03e1610615641a2940cb2de5e8603 /fs/nfs | |
parent | 6d39b27f0ac7e805ae3bd9efa51d7da04bec0360 (diff) | |
parent | c08d3b0e33edce28e9cfa7b64f7fe5bdeeb29248 (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.c | 54 |
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 | */ |
459 | static int nfs_vmtruncate(struct inode * inode, loff_t offset) | 459 | static 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 | 474 | out: |
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; | ||
500 | out_sig: | ||
501 | send_sig(SIGXFSZ, current, 0); | ||
502 | out_big: | ||
503 | return -EFBIG; | ||
504 | } | 476 | } |
505 | 477 | ||
506 | /** | 478 | /** |