aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
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 /mm/memory.c
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 'mm/memory.c')
-rw-r--r--mm/memory.c62
1 files changed, 3 insertions, 59 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 987389a809e7..7e91b5f9f690 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -297,7 +297,8 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *vma,
297 unsigned long addr = vma->vm_start; 297 unsigned long addr = vma->vm_start;
298 298
299 /* 299 /*
300 * Hide vma from rmap and vmtruncate before freeing pgtables 300 * Hide vma from rmap and truncate_pagecache before freeing
301 * pgtables
301 */ 302 */
302 anon_vma_unlink(vma); 303 anon_vma_unlink(vma);
303 unlink_file_vma(vma); 304 unlink_file_vma(vma);
@@ -2408,7 +2409,7 @@ restart:
2408 * @mapping: the address space containing mmaps to be unmapped. 2409 * @mapping: the address space containing mmaps to be unmapped.
2409 * @holebegin: byte in first page to unmap, relative to the start of 2410 * @holebegin: byte in first page to unmap, relative to the start of
2410 * the underlying file. This will be rounded down to a PAGE_SIZE 2411 * the underlying file. This will be rounded down to a PAGE_SIZE
2411 * boundary. Note that this is different from vmtruncate(), which 2412 * boundary. Note that this is different from truncate_pagecache(), which
2412 * must keep the partial page. In contrast, we must get rid of 2413 * must keep the partial page. In contrast, we must get rid of
2413 * partial pages. 2414 * partial pages.
2414 * @holelen: size of prospective hole in bytes. This will be rounded 2415 * @holelen: size of prospective hole in bytes. This will be rounded
@@ -2459,63 +2460,6 @@ void unmap_mapping_range(struct address_space *mapping,
2459} 2460}
2460EXPORT_SYMBOL(unmap_mapping_range); 2461EXPORT_SYMBOL(unmap_mapping_range);
2461 2462
2462/**
2463 * vmtruncate - unmap mappings "freed" by truncate() syscall
2464 * @inode: inode of the file used
2465 * @offset: file offset to start truncating
2466 *
2467 * NOTE! We have to be ready to update the memory sharing
2468 * between the file and the memory map for a potential last
2469 * incomplete page. Ugly, but necessary.
2470 */
2471int vmtruncate(struct inode * inode, loff_t offset)
2472{
2473 if (inode->i_size < offset) {
2474 unsigned long limit;
2475
2476 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
2477 if (limit != RLIM_INFINITY && offset > limit)
2478 goto out_sig;
2479 if (offset > inode->i_sb->s_maxbytes)
2480 goto out_big;
2481 i_size_write(inode, offset);
2482 } else {
2483 struct address_space *mapping = inode->i_mapping;
2484
2485 /*
2486 * truncation of in-use swapfiles is disallowed - it would
2487 * cause subsequent swapout to scribble on the now-freed
2488 * blocks.
2489 */
2490 if (IS_SWAPFILE(inode))
2491 return -ETXTBSY;
2492 i_size_write(inode, offset);
2493
2494 /*
2495 * unmap_mapping_range is called twice, first simply for
2496 * efficiency so that truncate_inode_pages does fewer
2497 * single-page unmaps. However after this first call, and
2498 * before truncate_inode_pages finishes, it is possible for
2499 * private pages to be COWed, which remain after
2500 * truncate_inode_pages finishes, hence the second
2501 * unmap_mapping_range call must be made for correctness.
2502 */
2503 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
2504 truncate_inode_pages(mapping, offset);
2505 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
2506 }
2507
2508 if (inode->i_op->truncate)
2509 inode->i_op->truncate(inode);
2510 return 0;
2511
2512out_sig:
2513 send_sig(SIGXFSZ, current, 0);
2514out_big:
2515 return -EFBIG;
2516}
2517EXPORT_SYMBOL(vmtruncate);
2518
2519int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) 2463int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
2520{ 2464{
2521 struct address_space *mapping = inode->i_mapping; 2465 struct address_space *mapping = inode->i_mapping;