aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory.c
diff options
context:
space:
mode:
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;