From 43592c46375a056b411b065acf2d37fc1e3ab251 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 4 Jan 2023 17:20:55 +0900 Subject: [PATCH] zonefs: Cache zone group directory inodes Since looking up any zone file inode requires looking up first the inode for the directory representing the zone group of the file, ensuring that the zone group inodes are always cached is desired. To do so, take an extra reference on the zone groups directory inodes on mount, thus avoiding the eviction of these inodes from the inode cache until the volume is unmounted. Signed-off-by: Damien Le Moal Reviewed-by: Johannes Thumshirn --- fs/zonefs/super.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ fs/zonefs/zonefs.h | 1 + 2 files changed, 49 insertions(+) diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index 7d70c327883e..010b53545e5b 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -1199,6 +1199,42 @@ static const struct super_operations zonefs_sops = { .show_options = zonefs_show_options, }; +static int zonefs_get_zgroup_inodes(struct super_block *sb) +{ + struct zonefs_sb_info *sbi = ZONEFS_SB(sb); + struct inode *dir_inode; + enum zonefs_ztype ztype; + + for (ztype = 0; ztype < ZONEFS_ZTYPE_MAX; ztype++) { + if (!sbi->s_zgroup[ztype].g_nr_zones) + continue; + + dir_inode = zonefs_get_zgroup_inode(sb, ztype); + if (IS_ERR(dir_inode)) + return PTR_ERR(dir_inode); + + sbi->s_zgroup[ztype].g_inode = dir_inode; + } + + return 0; +} + +static void zonefs_release_zgroup_inodes(struct super_block *sb) +{ + struct zonefs_sb_info *sbi = ZONEFS_SB(sb); + enum zonefs_ztype ztype; + + if (!sbi) + return; + + for (ztype = 0; ztype < ZONEFS_ZTYPE_MAX; ztype++) { + if (sbi->s_zgroup[ztype].g_inode) { + iput(sbi->s_zgroup[ztype].g_inode); + sbi->s_zgroup[ztype].g_inode = NULL; + } + } +} + /* * Check that the device is zoned. If it is, get the list of zones and create * sub-directories and files according to the device zone configuration and @@ -1297,6 +1333,14 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent) if (!sb->s_root) goto cleanup; + /* + * Take a reference on the zone groups directory inodes + * to keep them in the inode cache. + */ + ret = zonefs_get_zgroup_inodes(sb); + if (ret) + goto cleanup; + ret = zonefs_sysfs_register(sb); if (ret) goto cleanup; @@ -1304,6 +1348,7 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent) return 0; cleanup: + zonefs_release_zgroup_inodes(sb); zonefs_free_zgroups(sb); return ret; @@ -1319,6 +1364,9 @@ static void zonefs_kill_super(struct super_block *sb) { struct zonefs_sb_info *sbi = ZONEFS_SB(sb); + /* Release the reference on the zone group directory inodes */ + zonefs_release_zgroup_inodes(sb); + kill_block_super(sb); zonefs_sysfs_unregister(sb); diff --git a/fs/zonefs/zonefs.h b/fs/zonefs/zonefs.h index f88466a4158b..8175652241b5 100644 --- a/fs/zonefs/zonefs.h +++ b/fs/zonefs/zonefs.h @@ -76,6 +76,7 @@ struct zonefs_zone { * as files, one file per zone. */ struct zonefs_zone_group { + struct inode *g_inode; unsigned int g_nr_zones; struct zonefs_zone *g_zones; };