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 /mm/memory.c | |
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 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 62 |
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 | } |
2460 | EXPORT_SYMBOL(unmap_mapping_range); | 2461 | EXPORT_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 | */ | ||
2471 | int 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 | |||
2512 | out_sig: | ||
2513 | send_sig(SIGXFSZ, current, 0); | ||
2514 | out_big: | ||
2515 | return -EFBIG; | ||
2516 | } | ||
2517 | EXPORT_SYMBOL(vmtruncate); | ||
2518 | |||
2519 | int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) | 2463 | int 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; |