return NULL;
}
+static void zswap_invalidate_entry(struct zswap_tree *tree,
+ struct zswap_entry *entry)
+{
+ /* remove from rbtree */
+ zswap_rb_erase(&tree->rbroot, entry);
+
+ /* drop the initial reference from entry creation */
+ zswap_entry_put(tree, entry);
+}
+
static int zswap_reclaim_entry(struct zswap_pool *pool)
{
struct zswap_entry *entry;
goto put_unlock;
}
- /* Check for invalidate() race */
- if (entry != zswap_rb_search(&tree->rbroot, swpoffset))
- goto put_unlock;
-
- /* Drop base reference */
- zswap_entry_put(tree, entry);
+ /*
+ * Writeback started successfully, the page now belongs to the
+ * swapcache. Drop the entry from zswap - unless invalidate already
+ * took it out while we had the tree->lock released for IO.
+ */
+ if (entry == zswap_rb_search(&tree->rbroot, swpoffset))
+ zswap_invalidate_entry(tree, entry);
put_unlock:
/* Drop local reference */
goto reject;
}
-static void zswap_invalidate_entry(struct zswap_tree *tree,
- struct zswap_entry *entry)
-{
- /* remove from rbtree */
- zswap_rb_erase(&tree->rbroot, entry);
-
- /* drop the initial reference from entry creation */
- zswap_entry_put(tree, entry);
-}
-
/*
* returns 0 if the page was successfully decompressed
* return -1 on entry not found or error