summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-08-23 00:12:16 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2020-05-06 17:14:15 -0400
commitd2e0f799bec259aa7feec69659ba702ef1c1a014 (patch)
tree65f97364b07751f6cb41933118eaa9ab37b6e147
parent0295110274a0c299373919c7e02c47cd0174080b (diff)
page_cache_tree_insert_vec()
-rw-r--r--mm/filemap.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 4b091be17905..0b05f376c71e 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -178,32 +178,65 @@ void pagecache_block_get(struct pagecache_lock *lock)
}
EXPORT_SYMBOL(pagecache_block_get);
-static int page_cache_tree_insert(struct address_space *mapping,
- struct page *page, void **shadowp)
+static int page_cache_tree_insert_vec(struct address_space *mapping,
+ struct page *pages[],
+ unsigned nr_pages,
+ void *shadow[],
+ pgoff_t index)
{
- struct radix_tree_node *node;
- void **slot;
- int error;
+ struct radix_tree_iter iter;
+ void *p, **slot;
+ int i = 0, error = 0;
- error = __radix_tree_create(&mapping->i_pages, page->index, 0,
- &node, &slot);
- if (error)
- return error;
- if (*slot) {
- void *p;
+ if (!nr_pages)
+ return 0;
+
+ radix_tree_iter_init(&iter, index);
+
+ while (1) {
+ error = __radix_tree_create2(&mapping->i_pages,
+ &iter, 0, &slot);
+ if (error)
+ break;
+have_slot:
+ BUG_ON(iter.index != index + i);
p = radix_tree_deref_slot_protected(slot,
- &mapping->i_pages.xa_lock);
- if (!radix_tree_exceptional_entry(p))
- return -EEXIST;
+ &mapping->i_pages.xa_lock);
+ if (shadow)
+ shadow[i] = p;
+
+ if (radix_tree_exceptional_entry(p)) {
+ mapping->nrexceptional--;
+ } else if (p) {
+ error = -EEXIST;
+ break;
+ }
+
+ __radix_tree_replace(&mapping->i_pages, iter.node, slot, pages[i],
+ workingset_lookup_update(mapping));
+ mapping->nrpages++;
+
+ if (++i == nr_pages)
+ break;
+
+ slot++;
+ iter.index++;
- mapping->nrexceptional--;
- if (shadowp)
- *shadowp = p;
+ if (radix_tree_chunk_size(&iter))
+ goto have_slot;
}
- __radix_tree_replace(&mapping->i_pages, node, slot, page,
- workingset_lookup_update(mapping));
- mapping->nrpages++;
+
+ return i ?: error;
+}
+
+static int page_cache_tree_insert(struct address_space *mapping,
+ struct page *page, void **shadowp)
+{
+ int ret = page_cache_tree_insert_vec(mapping, &page, 1,
+ shadowp, page->index);
+ if (ret < 0)
+ return ret;
return 0;
}