zonefs: Export open zone resource information through sysfs
To allow applications to easily check the current usage status of the open zone resources of the mounted device, export through sysfs the counter of write open sequential files s_wro_seq_files field of struct zonefs_sb_info. The attribute is named nr_wro_seq_files and is read only. The maximum number of write open sequential files (zones) indicated by the s_max_wro_seq_files field of struct zonefs_sb_info is also exported as the read only attribute max_wro_seq_files. Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Hans Holmberg <hans.holmberg@wdc.com>
This commit is contained in:
parent
7d6dfbe03b
commit
9277a6d4fb
@ -3,4 +3,4 @@ ccflags-y += -I$(src)
|
||||
|
||||
obj-$(CONFIG_ZONEFS_FS) += zonefs.o
|
||||
|
||||
zonefs-y := super.o
|
||||
zonefs-y := super.o sysfs.o
|
||||
|
@ -1725,6 +1725,10 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
ret = zonefs_sysfs_register(sb);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
zonefs_info(sb, "Mounting %u zones",
|
||||
blkdev_nr_zones(sb->s_bdev->bd_disk));
|
||||
|
||||
@ -1770,6 +1774,8 @@ static void zonefs_kill_super(struct super_block *sb)
|
||||
|
||||
if (sb->s_root)
|
||||
d_genocide(sb->s_root);
|
||||
|
||||
zonefs_sysfs_unregister(sb);
|
||||
kill_block_super(sb);
|
||||
kfree(sbi);
|
||||
}
|
||||
@ -1817,16 +1823,26 @@ static int __init zonefs_init(void)
|
||||
return ret;
|
||||
|
||||
ret = register_filesystem(&zonefs_type);
|
||||
if (ret) {
|
||||
zonefs_destroy_inodecache();
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto destroy_inodecache;
|
||||
|
||||
ret = zonefs_sysfs_init();
|
||||
if (ret)
|
||||
goto unregister_fs;
|
||||
|
||||
return 0;
|
||||
|
||||
unregister_fs:
|
||||
unregister_filesystem(&zonefs_type);
|
||||
destroy_inodecache:
|
||||
zonefs_destroy_inodecache();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit zonefs_exit(void)
|
||||
{
|
||||
zonefs_sysfs_exit();
|
||||
zonefs_destroy_inodecache();
|
||||
unregister_filesystem(&zonefs_type);
|
||||
}
|
||||
|
125
fs/zonefs/sysfs.c
Normal file
125
fs/zonefs/sysfs.c
Normal file
@ -0,0 +1,125 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Simple file system for zoned block devices exposing zones as files.
|
||||
*
|
||||
* Copyright (C) 2022 Western Digital Corporation or its affiliates.
|
||||
*/
|
||||
#include <linux/fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
#include "zonefs.h"
|
||||
|
||||
struct zonefs_sysfs_attr {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct zonefs_sb_info *sbi, char *buf);
|
||||
};
|
||||
|
||||
static inline struct zonefs_sysfs_attr *to_attr(struct attribute *attr)
|
||||
{
|
||||
return container_of(attr, struct zonefs_sysfs_attr, attr);
|
||||
}
|
||||
|
||||
#define ZONEFS_SYSFS_ATTR_RO(name) \
|
||||
static struct zonefs_sysfs_attr zonefs_sysfs_attr_##name = __ATTR_RO(name)
|
||||
|
||||
#define ATTR_LIST(name) &zonefs_sysfs_attr_##name.attr
|
||||
|
||||
static ssize_t zonefs_sysfs_attr_show(struct kobject *kobj,
|
||||
struct attribute *attr, char *buf)
|
||||
{
|
||||
struct zonefs_sb_info *sbi =
|
||||
container_of(kobj, struct zonefs_sb_info, s_kobj);
|
||||
struct zonefs_sysfs_attr *zonefs_attr =
|
||||
container_of(attr, struct zonefs_sysfs_attr, attr);
|
||||
|
||||
if (!zonefs_attr->show)
|
||||
return 0;
|
||||
|
||||
return zonefs_attr->show(sbi, buf);
|
||||
}
|
||||
|
||||
static ssize_t max_wro_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%u\n", sbi->s_max_wro_seq_files);
|
||||
}
|
||||
ZONEFS_SYSFS_ATTR_RO(max_wro_seq_files);
|
||||
|
||||
static ssize_t nr_wro_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%d\n", atomic_read(&sbi->s_wro_seq_files));
|
||||
}
|
||||
ZONEFS_SYSFS_ATTR_RO(nr_wro_seq_files);
|
||||
|
||||
static struct attribute *zonefs_sysfs_attrs[] = {
|
||||
ATTR_LIST(max_wro_seq_files),
|
||||
ATTR_LIST(nr_wro_seq_files),
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(zonefs_sysfs);
|
||||
|
||||
static void zonefs_sysfs_sb_release(struct kobject *kobj)
|
||||
{
|
||||
struct zonefs_sb_info *sbi =
|
||||
container_of(kobj, struct zonefs_sb_info, s_kobj);
|
||||
|
||||
complete(&sbi->s_kobj_unregister);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops zonefs_sysfs_attr_ops = {
|
||||
.show = zonefs_sysfs_attr_show,
|
||||
};
|
||||
|
||||
static struct kobj_type zonefs_sb_ktype = {
|
||||
.default_groups = zonefs_sysfs_groups,
|
||||
.sysfs_ops = &zonefs_sysfs_attr_ops,
|
||||
.release = zonefs_sysfs_sb_release,
|
||||
};
|
||||
|
||||
static struct kobject *zonefs_sysfs_root;
|
||||
|
||||
int zonefs_sysfs_register(struct super_block *sb)
|
||||
{
|
||||
struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
|
||||
int ret;
|
||||
|
||||
init_completion(&sbi->s_kobj_unregister);
|
||||
ret = kobject_init_and_add(&sbi->s_kobj, &zonefs_sb_ktype,
|
||||
zonefs_sysfs_root, "%s", sb->s_id);
|
||||
if (ret) {
|
||||
kobject_put(&sbi->s_kobj);
|
||||
wait_for_completion(&sbi->s_kobj_unregister);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sbi->s_sysfs_registered = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zonefs_sysfs_unregister(struct super_block *sb)
|
||||
{
|
||||
struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
|
||||
|
||||
if (!sbi || !sbi->s_sysfs_registered)
|
||||
return;
|
||||
|
||||
kobject_del(&sbi->s_kobj);
|
||||
kobject_put(&sbi->s_kobj);
|
||||
wait_for_completion(&sbi->s_kobj_unregister);
|
||||
}
|
||||
|
||||
int __init zonefs_sysfs_init(void)
|
||||
{
|
||||
zonefs_sysfs_root = kobject_create_and_add("zonefs", fs_kobj);
|
||||
if (!zonefs_sysfs_root)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zonefs_sysfs_exit(void)
|
||||
{
|
||||
kobject_put(zonefs_sysfs_root);
|
||||
zonefs_sysfs_root = NULL;
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
#include <linux/uuid.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/kobject.h>
|
||||
|
||||
/*
|
||||
* Maximum length of file names: this only needs to be large enough to fit
|
||||
@ -184,6 +185,10 @@ struct zonefs_sb_info {
|
||||
|
||||
unsigned int s_max_wro_seq_files;
|
||||
atomic_t s_wro_seq_files;
|
||||
|
||||
bool s_sysfs_registered;
|
||||
struct kobject s_kobj;
|
||||
struct completion s_kobj_unregister;
|
||||
};
|
||||
|
||||
static inline struct zonefs_sb_info *ZONEFS_SB(struct super_block *sb)
|
||||
@ -198,4 +203,9 @@ static inline struct zonefs_sb_info *ZONEFS_SB(struct super_block *sb)
|
||||
#define zonefs_warn(sb, format, args...) \
|
||||
pr_warn("zonefs (%s) WARNING: " format, sb->s_id, ## args)
|
||||
|
||||
int zonefs_sysfs_register(struct super_block *sb);
|
||||
void zonefs_sysfs_unregister(struct super_block *sb);
|
||||
int zonefs_sysfs_init(void);
|
||||
void zonefs_sysfs_exit(void);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user