gfs2: don't allow releasepage to free bd still used for revokes
authorBob Peterson <rpeterso@redhat.com>
Mon, 17 Feb 2020 20:14:13 +0000 (14:14 -0600)
committerBob Peterson <rpeterso@redhat.com>
Thu, 27 Feb 2020 13:53:18 +0000 (07:53 -0600)
Before this patch, function gfs2_releasepage would free any bd
elements that had been used for the page being released. However,
those bd elements may still be queued to the sd_log_revokes list,
in which case we cannot free them until the revoke has been issued.

This patch adds additional checks for bds that are still being
used for revokes.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
fs/gfs2/aops.c

index ba83b49ce18c41b8182cb35163c5c6dc684a5ad2..786c1ce8f03051130ec55a7ac2a7970e3ebe97cf 100644 (file)
@@ -805,11 +805,16 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
                bd = bh->b_private;
                if (bd) {
                        gfs2_assert_warn(sdp, bd->bd_bh == bh);
-                       if (!list_empty(&bd->bd_list))
-                               list_del_init(&bd->bd_list);
                        bd->bd_bh = NULL;
                        bh->b_private = NULL;
-                       kmem_cache_free(gfs2_bufdata_cachep, bd);
+                       /*
+                        * The bd may still be queued as a revoke, in which
+                        * case we must not dequeue nor free it.
+                        */
+                       if (!bd->bd_blkno && !list_empty(&bd->bd_list))
+                               list_del_init(&bd->bd_list);
+                       if (list_empty(&bd->bd_list))
+                               kmem_cache_free(gfs2_bufdata_cachep, bd);
                }
 
                bh = bh->b_this_page;