diff options
author | Ross Zwisler <ross.zwisler@linux.intel.com> | 2016-01-22 18:10:44 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-22 20:02:18 -0500 |
commit | 7e7f774984cd88c45c18e7ffaf0256c3e9118043 (patch) | |
tree | 661a5f505dee94f89e12e493f995bda19906cf67 /mm | |
parent | f9fe48bece3af2d60e1bad65db4825f5a025dd36 (diff) |
mm: add find_get_entries_tag()
Add find_get_entries_tag() to the family of functions that include
find_get_entries(), find_get_pages() and find_get_pages_tag(). This is
needed for DAX dirty page handling because we need a list of both page
offsets and radix tree entries ('indices' and 'entries' in this
function) that are marked with the PAGECACHE_TAG_TOWRITE tag.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jeff Layton <jlayton@poochiereds.net>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Matthew Wilcox <matthew.r.wilcox@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/filemap.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 7b8be78cfd9e..1e215fc36c83 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1499,6 +1499,74 @@ repeat: | |||
1499 | } | 1499 | } |
1500 | EXPORT_SYMBOL(find_get_pages_tag); | 1500 | EXPORT_SYMBOL(find_get_pages_tag); |
1501 | 1501 | ||
1502 | /** | ||
1503 | * find_get_entries_tag - find and return entries that match @tag | ||
1504 | * @mapping: the address_space to search | ||
1505 | * @start: the starting page cache index | ||
1506 | * @tag: the tag index | ||
1507 | * @nr_entries: the maximum number of entries | ||
1508 | * @entries: where the resulting entries are placed | ||
1509 | * @indices: the cache indices corresponding to the entries in @entries | ||
1510 | * | ||
1511 | * Like find_get_entries, except we only return entries which are tagged with | ||
1512 | * @tag. | ||
1513 | */ | ||
1514 | unsigned find_get_entries_tag(struct address_space *mapping, pgoff_t start, | ||
1515 | int tag, unsigned int nr_entries, | ||
1516 | struct page **entries, pgoff_t *indices) | ||
1517 | { | ||
1518 | void **slot; | ||
1519 | unsigned int ret = 0; | ||
1520 | struct radix_tree_iter iter; | ||
1521 | |||
1522 | if (!nr_entries) | ||
1523 | return 0; | ||
1524 | |||
1525 | rcu_read_lock(); | ||
1526 | restart: | ||
1527 | radix_tree_for_each_tagged(slot, &mapping->page_tree, | ||
1528 | &iter, start, tag) { | ||
1529 | struct page *page; | ||
1530 | repeat: | ||
1531 | page = radix_tree_deref_slot(slot); | ||
1532 | if (unlikely(!page)) | ||
1533 | continue; | ||
1534 | if (radix_tree_exception(page)) { | ||
1535 | if (radix_tree_deref_retry(page)) { | ||
1536 | /* | ||
1537 | * Transient condition which can only trigger | ||
1538 | * when entry at index 0 moves out of or back | ||
1539 | * to root: none yet gotten, safe to restart. | ||
1540 | */ | ||
1541 | goto restart; | ||
1542 | } | ||
1543 | |||
1544 | /* | ||
1545 | * A shadow entry of a recently evicted page, a swap | ||
1546 | * entry from shmem/tmpfs or a DAX entry. Return it | ||
1547 | * without attempting to raise page count. | ||
1548 | */ | ||
1549 | goto export; | ||
1550 | } | ||
1551 | if (!page_cache_get_speculative(page)) | ||
1552 | goto repeat; | ||
1553 | |||
1554 | /* Has the page moved? */ | ||
1555 | if (unlikely(page != *slot)) { | ||
1556 | page_cache_release(page); | ||
1557 | goto repeat; | ||
1558 | } | ||
1559 | export: | ||
1560 | indices[ret] = iter.index; | ||
1561 | entries[ret] = page; | ||
1562 | if (++ret == nr_entries) | ||
1563 | break; | ||
1564 | } | ||
1565 | rcu_read_unlock(); | ||
1566 | return ret; | ||
1567 | } | ||
1568 | EXPORT_SYMBOL(find_get_entries_tag); | ||
1569 | |||
1502 | /* | 1570 | /* |
1503 | * CD/DVDs are error prone. When a medium error occurs, the driver may fail | 1571 | * CD/DVDs are error prone. When a medium error occurs, the driver may fail |
1504 | * a _large_ part of the i/o request. Imagine the worst scenario: | 1572 | * a _large_ part of the i/o request. Imagine the worst scenario: |