Merge tag 'fs.idmapped.mount_setattr.v5.13-rc3' of gitolite.kernel.org:pub/scm/linux...
[linux-2.6-microblaze.git] / mm / z3fold.c
index b5dafa7..7fe7ada 100644 (file)
@@ -391,7 +391,7 @@ static void z3fold_unregister_migration(struct z3fold_pool *pool)
 {
        if (pool->inode)
                iput(pool->inode);
- }
+}
 
 /* Initializes the z3fold header of a newly allocated z3fold page */
 static struct z3fold_header *init_z3fold_page(struct page *page, bool headless,
@@ -1346,8 +1346,22 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
                        page = list_entry(pos, struct page, lru);
 
                        zhdr = page_address(page);
-                       if (test_bit(PAGE_HEADLESS, &page->private))
+                       if (test_bit(PAGE_HEADLESS, &page->private)) {
+                               /*
+                                * For non-headless pages, we wait to do this
+                                * until we have the page lock to avoid racing
+                                * with __z3fold_alloc(). Headless pages don't
+                                * have a lock (and __z3fold_alloc() will never
+                                * see them), but we still need to test and set
+                                * PAGE_CLAIMED to avoid racing with
+                                * z3fold_free(), so just do it now before
+                                * leaving the loop.
+                                */
+                               if (test_and_set_bit(PAGE_CLAIMED, &page->private))
+                                       continue;
+
                                break;
+                       }
 
                        if (kref_get_unless_zero(&zhdr->refcount) == 0) {
                                zhdr = NULL;