gfs2: per-filesystem bufdata
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index e79ad08..932c484b 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -693,7 +693,7 @@ bool gfs2_release_folio(struct folio *folio, gfp_t gfp_mask)
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);
+ kmem_cache_free(sdp->sd_bufdata, bd);
}
bh = bh->b_this_page;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 6146577..dec6bcc 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -847,6 +847,7 @@ struct gfs2_sbd {
unsigned long sd_last_warning;
struct dentry *debugfs_dir; /* debugfs directory */
+ struct kmem_cache *sd_bufdata;
};
#define glock_sbd(gl) ((gl)->gl_name.ln_sbd)
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 347df29..b730870 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -985,13 +985,14 @@ static void empty_ail1_list(struct gfs2_sbd *sdp)
/**
* trans_drain - drain the buf and databuf queue for a failed transaction
+ * @sdp: Pointer to GFS2 superblock
* @tr: the transaction to drain
*
* When this is called, we're taking an error exit for a log write that failed
* but since we bypassed the after_commit functions, we need to remove the
* items from the buf and databuf queue.
*/
-static void trans_drain(struct gfs2_trans *tr)
+static void trans_drain(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{
struct gfs2_bufdata *bd;
struct list_head *head;
@@ -1005,7 +1006,7 @@ static void trans_drain(struct gfs2_trans *tr)
list_del_init(&bd->bd_list);
if (!list_empty(&bd->bd_ail_st_list))
gfs2_remove_from_ail(bd);
- kmem_cache_free(gfs2_bufdata_cachep, bd);
+ kmem_cache_free(sdp->sd_bufdata, bd);
}
head = &tr->tr_databuf;
while (!list_empty(head)) {
@@ -1013,7 +1014,7 @@ static void trans_drain(struct gfs2_trans *tr)
list_del_init(&bd->bd_list);
if (!list_empty(&bd->bd_ail_st_list))
gfs2_remove_from_ail(bd);
- kmem_cache_free(gfs2_bufdata_cachep, bd);
+ kmem_cache_free(sdp->sd_bufdata, bd);
}
}
@@ -1151,7 +1152,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
return;
out_withdraw:
- trans_drain(tr);
+ trans_drain(sdp, tr);
/**
* If the tr_list is empty, we're withdrawing during a log
* flush that targets a transaction, but the transaction was
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index e03928d..d7e93668 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -894,7 +894,7 @@ void gfs2_drain_revokes(struct gfs2_sbd *sdp)
list_del_init(&bd->bd_list);
gl = bd->bd_gl;
gfs2_glock_remove_revoke(gl);
- kmem_cache_free(gfs2_bufdata_cachep, bd);
+ kmem_cache_free(sdp->sd_bufdata, bd);
}
}
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 9d65719..1b38d73 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -115,12 +115,6 @@ static int __init init_gfs2_fs(void)
if (!gfs2_inode_cachep)
goto fail_cachep3;
- gfs2_bufdata_cachep = kmem_cache_create("gfs2_bufdata",
- sizeof(struct gfs2_bufdata),
- 0, 0, NULL);
- if (!gfs2_bufdata_cachep)
- goto fail_cachep4;
-
gfs2_rgrpd_cachep = kmem_cache_create("gfs2_rgrpd",
sizeof(struct gfs2_rgrpd),
0, 0, NULL);
@@ -205,8 +199,6 @@ static int __init init_gfs2_fs(void)
fail_cachep6:
kmem_cache_destroy(gfs2_rgrpd_cachep);
fail_cachep5:
- kmem_cache_destroy(gfs2_bufdata_cachep);
-fail_cachep4:
kmem_cache_destroy(gfs2_inode_cachep);
fail_cachep3:
kmem_cache_destroy(gfs2_glock_aspace_cachep);
@@ -245,7 +237,6 @@ static void __exit exit_gfs2_fs(void)
kmem_cache_destroy(gfs2_qadata_cachep);
kmem_cache_destroy(gfs2_quotad_cachep);
kmem_cache_destroy(gfs2_rgrpd_cachep);
- kmem_cache_destroy(gfs2_bufdata_cachep);
kmem_cache_destroy(gfs2_inode_cachep);
kmem_cache_destroy(gfs2_glock_aspace_cachep);
kmem_cache_destroy(gfs2_glock_cachep);
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 3c8e455..7e90dec 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -363,7 +363,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, int meta)
gfs2_trans_add_revoke(sdp, bd);
} else if (was_pinned) {
bh->b_private = NULL;
- kmem_cache_free(gfs2_bufdata_cachep, bd);
+ kmem_cache_free(sdp->sd_bufdata, bd);
} else if (!list_empty(&bd->bd_ail_st_list) &&
!list_empty(&bd->bd_ail_gl_list)) {
gfs2_remove_from_ail(bd);
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index e7a88b7..2e4f3c6 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1198,9 +1198,19 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
if (!sdp->sd_delete_wq)
goto fail_glock_wq;
+ char *bufdata_name = kasprintf(GFP_KERNEL, "gfs2-bufdata/%s", sdp->sd_fsname);
+ if (!bufdata_name)
+ goto fail_delete_wq;
+ sdp->sd_bufdata = kmem_cache_create(bufdata_name,
+ sizeof(struct gfs2_bufdata),
+ 0, 0, NULL);
+ kfree(bufdata_name);
+ if (!sdp->sd_bufdata)
+ goto fail_delete_wq;
+
error = gfs2_sys_fs_add(sdp);
if (error)
- goto fail_delete_wq;
+ goto fail_bufdata;
gfs2_create_debugfs_file(sdp);
@@ -1305,6 +1315,8 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
fail_debug:
gfs2_delete_debugfs_file(sdp);
gfs2_sys_fs_del(sdp);
+fail_bufdata:
+ kmem_cache_destroy(sdp->sd_bufdata);
fail_delete_wq:
destroy_workqueue(sdp->sd_delete_wq);
fail_glock_wq:
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index f6cd907..0d847bf 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -638,6 +638,7 @@ static void gfs2_put_super(struct super_block *sb)
gfs2_gl_hash_clear(sdp);
iput(sdp->sd_inode);
gfs2_delete_debugfs_file(sdp);
+ kmem_cache_destroy(sdp->sd_bufdata);
gfs2_sys_fs_del(sdp);
free_sbd(sdp);
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 95f2632..742d061 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -168,9 +168,10 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
struct buffer_head *bh)
{
+ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct gfs2_bufdata *bd;
- bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL);
+ bd = kmem_cache_zalloc(sdp->sd_bufdata, GFP_NOFS | __GFP_NOFAIL);
bd->bd_bh = bh;
bd->bd_gl = gl;
INIT_LIST_HEAD(&bd->bd_list);
@@ -337,7 +338,7 @@ void gfs2_trans_remove_revoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
sdp->sd_log_num_revoke--;
if (bd->bd_gl)
gfs2_glock_remove_revoke(bd->bd_gl);
- kmem_cache_free(gfs2_bufdata_cachep, bd);
+ kmem_cache_free(sdp->sd_bufdata, bd);
gfs2_log_release_revokes(sdp, 1);
if (--n == 0)
break;
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 0260320..c35c882 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -29,7 +29,6 @@
struct kmem_cache *gfs2_glock_cachep __read_mostly;
struct kmem_cache *gfs2_glock_aspace_cachep __read_mostly;
struct kmem_cache *gfs2_inode_cachep __read_mostly;
-struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
struct kmem_cache *gfs2_quotad_cachep __read_mostly;
struct kmem_cache *gfs2_qadata_cachep __read_mostly;
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
index ffcc47d..940dc45 100644
--- a/fs/gfs2/util.h
+++ b/fs/gfs2/util.h
@@ -160,7 +160,6 @@ gfs2_io_error_bh_i((sdp), (bh), __func__, __FILE__, __LINE__)
extern struct kmem_cache *gfs2_glock_cachep;
extern struct kmem_cache *gfs2_glock_aspace_cachep;
extern struct kmem_cache *gfs2_inode_cachep;
-extern struct kmem_cache *gfs2_bufdata_cachep;
extern struct kmem_cache *gfs2_rgrpd_cachep;
extern struct kmem_cache *gfs2_quotad_cachep;
extern struct kmem_cache *gfs2_qadata_cachep;