aboutsummaryrefslogtreecommitdiffstats
path: root/mm
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
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')
-rw-r--r--mm/filemap.c2
-rw-r--r--mm/memory.c62
-rw-r--r--mm/mremap.c4
-rw-r--r--mm/nommu.c40
-rw-r--r--mm/truncate.c64
5 files changed, 70 insertions, 102 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index c1fc205a92c6..6c84e598b4a9 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -58,7 +58,7 @@
58/* 58/*
59 * Lock ordering: 59 * Lock ordering:
60 * 60 *
61 * ->i_mmap_lock (vmtruncate) 61 * ->i_mmap_lock (truncate_pagecache)
62 * ->private_lock (__free_pte->__set_page_dirty_buffers) 62 * ->private_lock (__free_pte->__set_page_dirty_buffers)
63 * ->swap_lock (exclusive_swap_page, others) 63 * ->swap_lock (exclusive_swap_page, others)
64 * ->mapping->tree_lock 64 * ->mapping->tree_lock
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;
diff --git a/mm/mremap.c b/mm/mremap.c
index 20a07dba6be0..97bff2547719 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -86,8 +86,8 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
86 if (vma->vm_file) { 86 if (vma->vm_file) {
87 /* 87 /*
88 * Subtle point from Rajesh Venkatasubramanian: before 88 * Subtle point from Rajesh Venkatasubramanian: before
89 * moving file-based ptes, we must lock vmtruncate out, 89 * moving file-based ptes, we must lock truncate_pagecache
90 * since it might clean the dst vma before the src vma, 90 * out, since it might clean the dst vma before the src vma,
91 * and we propagate stale pages into the dst afterward. 91 * and we propagate stale pages into the dst afterward.
92 */ 92 */
93 mapping = vma->vm_file->f_mapping; 93 mapping = vma->vm_file->f_mapping;
diff --git a/mm/nommu.c b/mm/nommu.c
index 8d484241d034..56a446f05971 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -83,46 +83,6 @@ struct vm_operations_struct generic_file_vm_ops = {
83}; 83};
84 84
85/* 85/*
86 * Handle all mappings that got truncated by a "truncate()"
87 * system call.
88 *
89 * NOTE! We have to be ready to update the memory sharing
90 * between the file and the memory map for a potential last
91 * incomplete page. Ugly, but necessary.
92 */
93int vmtruncate(struct inode *inode, loff_t offset)
94{
95 struct address_space *mapping = inode->i_mapping;
96 unsigned long limit;
97
98 if (inode->i_size < offset)
99 goto do_expand;
100 i_size_write(inode, offset);
101
102 truncate_inode_pages(mapping, offset);
103 goto out_truncate;
104
105do_expand:
106 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
107 if (limit != RLIM_INFINITY && offset > limit)
108 goto out_sig;
109 if (offset > inode->i_sb->s_maxbytes)
110 goto out;
111 i_size_write(inode, offset);
112
113out_truncate:
114 if (inode->i_op->truncate)
115 inode->i_op->truncate(inode);
116 return 0;
117out_sig:
118 send_sig(SIGXFSZ, current, 0);
119out:
120 return -EFBIG;
121}
122
123EXPORT_SYMBOL(vmtruncate);
124
125/*
126 * Return the total memory allocated for this pointer, not 86 * Return the total memory allocated for this pointer, not
127 * just what the caller asked for. 87 * just what the caller asked for.
128 * 88 *
diff --git a/mm/truncate.c b/mm/truncate.c
index a17b3977cfdf..450cebdabfc0 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -497,3 +497,67 @@ int invalidate_inode_pages2(struct address_space *mapping)
497 return invalidate_inode_pages2_range(mapping, 0, -1); 497 return invalidate_inode_pages2_range(mapping, 0, -1);
498} 498}
499EXPORT_SYMBOL_GPL(invalidate_inode_pages2); 499EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
500
501/**
502 * truncate_pagecache - unmap and remove pagecache that has been truncated
503 * @inode: inode
504 * @old: old file offset
505 * @new: new file offset
506 *
507 * inode's new i_size must already be written before truncate_pagecache
508 * is called.
509 *
510 * This function should typically be called before the filesystem
511 * releases resources associated with the freed range (eg. deallocates
512 * blocks). This way, pagecache will always stay logically coherent
513 * with on-disk format, and the filesystem would not have to deal with
514 * situations such as writepage being called for a page that has already
515 * had its underlying blocks deallocated.
516 */
517void truncate_pagecache(struct inode *inode, loff_t old, loff_t new)
518{
519 if (new < old) {
520 struct address_space *mapping = inode->i_mapping;
521
522 /*
523 * unmap_mapping_range is called twice, first simply for
524 * efficiency so that truncate_inode_pages does fewer
525 * single-page unmaps. However after this first call, and
526 * before truncate_inode_pages finishes, it is possible for
527 * private pages to be COWed, which remain after
528 * truncate_inode_pages finishes, hence the second
529 * unmap_mapping_range call must be made for correctness.
530 */
531 unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1);
532 truncate_inode_pages(mapping, new);
533 unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1);
534 }
535}
536EXPORT_SYMBOL(truncate_pagecache);
537
538/**
539 * vmtruncate - unmap mappings "freed" by truncate() syscall
540 * @inode: inode of the file used
541 * @offset: file offset to start truncating
542 *
543 * NOTE! We have to be ready to update the memory sharing
544 * between the file and the memory map for a potential last
545 * incomplete page. Ugly, but necessary.
546 */
547int vmtruncate(struct inode *inode, loff_t offset)
548{
549 loff_t oldsize;
550 int error;
551
552 error = inode_newsize_ok(inode, offset);
553 if (error)
554 return error;
555 oldsize = inode->i_size;
556 i_size_write(inode, offset);
557 truncate_pagecache(inode, oldsize, offset);
558 if (inode->i_op->truncate)
559 inode->i_op->truncate(inode);
560
561 return error;
562}
563EXPORT_SYMBOL(vmtruncate);