mm: add unmap_mapping_pages()
Several users of unmap_mapping_range() would prefer to express their range in pages rather than bytes. Unfortuately, on a 32-bit kernel, you have to remember to cast your page number to a 64-bit type before shifting it, and four places in the current tree didn't remember to do that. That's a sign of a bad interface. Conveniently, unmap_mapping_range() actually converts from bytes into pages, so hoist the guts of unmap_mapping_range() into a new function unmap_mapping_pages() and convert the callers which want to use pages. Link: http://lkml.kernel.org/r/20171206142627.GD32044@bombadil.infradead.org Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com> Reported-by: "zhangyi (F)" <yi.zhang@huawei.com> Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
此提交包含在:
43
mm/memory.c
43
mm/memory.c
@@ -2798,9 +2798,38 @@ static inline void unmap_mapping_range_tree(struct rb_root_cached *root,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unmap_mapping_pages() - Unmap pages from processes.
|
||||
* @mapping: The address space containing pages to be unmapped.
|
||||
* @start: Index of first page to be unmapped.
|
||||
* @nr: Number of pages to be unmapped. 0 to unmap to end of file.
|
||||
* @even_cows: Whether to unmap even private COWed pages.
|
||||
*
|
||||
* Unmap the pages in this address space from any userspace process which
|
||||
* has them mmaped. Generally, you want to remove COWed pages as well when
|
||||
* a file is being truncated, but not when invalidating pages from the page
|
||||
* cache.
|
||||
*/
|
||||
void unmap_mapping_pages(struct address_space *mapping, pgoff_t start,
|
||||
pgoff_t nr, bool even_cows)
|
||||
{
|
||||
struct zap_details details = { };
|
||||
|
||||
details.check_mapping = even_cows ? NULL : mapping;
|
||||
details.first_index = start;
|
||||
details.last_index = start + nr - 1;
|
||||
if (details.last_index < details.first_index)
|
||||
details.last_index = ULONG_MAX;
|
||||
|
||||
i_mmap_lock_write(mapping);
|
||||
if (unlikely(!RB_EMPTY_ROOT(&mapping->i_mmap.rb_root)))
|
||||
unmap_mapping_range_tree(&mapping->i_mmap, &details);
|
||||
i_mmap_unlock_write(mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* unmap_mapping_range - unmap the portion of all mmaps in the specified
|
||||
* address_space corresponding to the specified page range in the underlying
|
||||
* address_space corresponding to the specified byte range in the underlying
|
||||
* file.
|
||||
*
|
||||
* @mapping: the address space containing mmaps to be unmapped.
|
||||
@@ -2818,7 +2847,6 @@ static inline void unmap_mapping_range_tree(struct rb_root_cached *root,
|
||||
void unmap_mapping_range(struct address_space *mapping,
|
||||
loff_t const holebegin, loff_t const holelen, int even_cows)
|
||||
{
|
||||
struct zap_details details = { };
|
||||
pgoff_t hba = holebegin >> PAGE_SHIFT;
|
||||
pgoff_t hlen = (holelen + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
|
||||
@@ -2830,16 +2858,7 @@ void unmap_mapping_range(struct address_space *mapping,
|
||||
hlen = ULONG_MAX - hba + 1;
|
||||
}
|
||||
|
||||
details.check_mapping = even_cows ? NULL : mapping;
|
||||
details.first_index = hba;
|
||||
details.last_index = hba + hlen - 1;
|
||||
if (details.last_index < details.first_index)
|
||||
details.last_index = ULONG_MAX;
|
||||
|
||||
i_mmap_lock_write(mapping);
|
||||
if (unlikely(!RB_EMPTY_ROOT(&mapping->i_mmap.rb_root)))
|
||||
unmap_mapping_range_tree(&mapping->i_mmap, &details);
|
||||
i_mmap_unlock_write(mapping);
|
||||
unmap_mapping_pages(mapping, hba, hlen, even_cows);
|
||||
}
|
||||
EXPORT_SYMBOL(unmap_mapping_range);
|
||||
|
||||
|
新增問題並參考
封鎖使用者