From aebe17f6844488ff0b824fbac28d9f342f7b078e Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Fri, 8 Aug 2014 14:20:37 -0700 Subject: nilfs2: add /sys/fs/nilfs2/features group This patchset implements creation of sysfs groups and attributes with the purpose to show NILFS2 volume details, internal state of the driver and to manage internal state of NILFS2 driver. Sysfs is a virtual file system that exports information about devices and drivers from the kernel device model to user space, and is also used for configuration. NILFS2 is a complex file system that has segctor thread, GC thread, checkpoint/snapshot model and so on. Sysfs namespace provides native and easy way for: (1) getting info and statistics about volume state; (2) getting info and configuration of internal subsystems (segctor thread); (3) snapshots management. Suggested patchset provides basis for managing segctor thread behaviour and manipulation by snapshots. Currently, it informs only about segctor thread's internal parameters and about mounted snapshots. But sysfs interface can provide easy and simple way for deep management of segctor thread and snapshots. This patchset provides opportunity to manage interval of periodical update of superblock (in seconds). Default value is 10 seconds. Now a user can increase this value by means of nilfs2//superblock/sb_update_frequency attribute in the case of necessity. Also the patchset provides opportunity to get information easily about key volumes's parameters (free blocks, superblock write count, superblock update frequency, latest segment info, dirty data blocks count, count of clean segments, count of dirty segments and so on) in real time manner. Such information can be used in scripts for subtle management of filesystem. Implemented functionality creates such groups: (1) /sys/fs/nilfs2 - root group (2) /sys/fs/nilfs2/features - group contains attributes that describe NILFS file system driver features (3) /sys/fs/nilfs2/ - group contains attributes that describe file system partition's details (4) /sys/fs/nilfs2//superblock - group contains attributes that describe superblock's details (5) /sys/fs/nilfs2//segctor - group contains attributes that describe segctor thread activity details (6) /sys/fs/nilfs2//segments - group contains attributes that describe details about volume's segments (7) /sys/fs/nilfs2//checkpoints - group contains attributes that describe details about volume's checkpoints (8) /sys/fs/nilfs2//mounted_snapshots - group contains group for every mounted snapshot (9) /sys/fs/nilfs2//mounted_snapshots/ - group contains details about mounted snapshot This patch (of 9): This patch adds code of creation /sys/fs/nilfs2 group and /sys/fs/nilfs2/features group. The features group contains attributes that describe NILFS file system driver features: (1) revision - show current revision of NILFS file system driver. There are two formats of timestamp output - seconds and human-readable format. Every showed timestamp has two sysfs files (time- and time--secs). One sysfs file (time-) shows time in human-readable format. Another sysfs file (time--secs) shows time in seconds. It was reported by Michael Semon that timestamp output in human-readable format should be changed from "2014-4-12 14:5:38" to "2014-04-12 14:05:38". Second version of the patch fixes this issue. Reported-by: Michael L. Semon Signed-off-by: Vyacheslav Dubeyko Cc: Vyacheslav Dubeyko Cc: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-fs-nilfs2 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-fs-nilfs2 (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 new file mode 100644 index 000000000000..71b4fd39f74d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 @@ -0,0 +1,14 @@ + +What: /sys/fs/nilfs2/features/revision +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show current revision of NILFS file system driver. + This value informs about file system revision that + driver is ready to support. + +What: /sys/fs/nilfs2/features/README +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Describe attributes of /sys/fs/nilfs2/features group. -- cgit v1.2.3 From da7141fb78db915680616e15677539fc8140cf53 Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Fri, 8 Aug 2014 14:20:39 -0700 Subject: nilfs2: add /sys/fs/nilfs2/ group This patch adds creation of /sys/fs/nilfs2/ group. The group contains attributes that describe file system partition's details: (1) revision - show NILFS file system revision. (2) blocksize - show volume block size in bytes. (3) device_size - show volume size in bytes. (4) free_blocks - show count of free blocks on volume. (5) uuid - show volume's UUID. (6) volume_name - show volume's name. Signed-off-by: Vyacheslav Dubeyko Cc: Vyacheslav Dubeyko Cc: Ryusuke Konishi Cc: Michael L. Semon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-fs-nilfs2 | 44 ++++++++ fs/nilfs2/sysfs.c | 168 ++++++++++++++++++++++++++++++ fs/nilfs2/sysfs.h | 20 ++++ fs/nilfs2/the_nilfs.h | 6 ++ 4 files changed, 238 insertions(+) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 index 71b4fd39f74d..0a521d03539a 100644 --- a/Documentation/ABI/testing/sysfs-fs-nilfs2 +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 @@ -12,3 +12,47 @@ Date: April 2014 Contact: "Vyacheslav Dubeyko" Description: Describe attributes of /sys/fs/nilfs2/features group. + +What: /sys/fs/nilfs2//revision +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show NILFS file system revision on volume. + This value informs about metadata structures' + revision on mounted volume. + +What: /sys/fs/nilfs2//blocksize +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show volume's block size in bytes. + +What: /sys/fs/nilfs2//device_size +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show volume size in bytes. + +What: /sys/fs/nilfs2//free_blocks +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show count of free blocks on volume. + +What: /sys/fs/nilfs2//uuid +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show volume's UUID (Universally Unique Identifier). + +What: /sys/fs/nilfs2//volume_name +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show volume's label. + +What: /sys/fs/nilfs2//README +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Describe attributes of /sys/fs/nilfs2/ group. diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c index 41b8f7039657..780d0f5bbe88 100644 --- a/fs/nilfs2/sysfs.c +++ b/fs/nilfs2/sysfs.c @@ -41,6 +41,174 @@ static struct kset *nilfs_kset; count; \ }) +/************************************************************************ + * NILFS device attrs * + ************************************************************************/ + +static +ssize_t nilfs_dev_revision_show(struct nilfs_dev_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + struct nilfs_super_block **sbp = nilfs->ns_sbp; + u32 major = le32_to_cpu(sbp[0]->s_rev_level); + u16 minor = le16_to_cpu(sbp[0]->s_minor_rev_level); + + return snprintf(buf, PAGE_SIZE, "%d.%d\n", major, minor); +} + +static +ssize_t nilfs_dev_blocksize_show(struct nilfs_dev_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", nilfs->ns_blocksize); +} + +static +ssize_t nilfs_dev_device_size_show(struct nilfs_dev_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + struct nilfs_super_block **sbp = nilfs->ns_sbp; + u64 dev_size = le64_to_cpu(sbp[0]->s_dev_size); + + return snprintf(buf, PAGE_SIZE, "%llu\n", dev_size); +} + +static +ssize_t nilfs_dev_free_blocks_show(struct nilfs_dev_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + sector_t free_blocks = 0; + + nilfs_count_free_blocks(nilfs, &free_blocks); + return snprintf(buf, PAGE_SIZE, "%llu\n", + (unsigned long long)free_blocks); +} + +static +ssize_t nilfs_dev_uuid_show(struct nilfs_dev_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + struct nilfs_super_block **sbp = nilfs->ns_sbp; + + return snprintf(buf, PAGE_SIZE, "%pUb\n", sbp[0]->s_uuid); +} + +static +ssize_t nilfs_dev_volume_name_show(struct nilfs_dev_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + struct nilfs_super_block **sbp = nilfs->ns_sbp; + + return scnprintf(buf, sizeof(sbp[0]->s_volume_name), "%s\n", + sbp[0]->s_volume_name); +} + +static const char dev_readme_str[] = + "The group contains attributes that describe file system\n" + "partition's details.\n\n" + "(1) revision\n\tshow NILFS file system revision.\n\n" + "(2) blocksize\n\tshow volume block size in bytes.\n\n" + "(3) device_size\n\tshow volume size in bytes.\n\n" + "(4) free_blocks\n\tshow count of free blocks on volume.\n\n" + "(5) uuid\n\tshow volume's UUID.\n\n" + "(6) volume_name\n\tshow volume's name.\n\n"; + +static ssize_t nilfs_dev_README_show(struct nilfs_dev_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, dev_readme_str); +} + +NILFS_DEV_RO_ATTR(revision); +NILFS_DEV_RO_ATTR(blocksize); +NILFS_DEV_RO_ATTR(device_size); +NILFS_DEV_RO_ATTR(free_blocks); +NILFS_DEV_RO_ATTR(uuid); +NILFS_DEV_RO_ATTR(volume_name); +NILFS_DEV_RO_ATTR(README); + +static struct attribute *nilfs_dev_attrs[] = { + NILFS_DEV_ATTR_LIST(revision), + NILFS_DEV_ATTR_LIST(blocksize), + NILFS_DEV_ATTR_LIST(device_size), + NILFS_DEV_ATTR_LIST(free_blocks), + NILFS_DEV_ATTR_LIST(uuid), + NILFS_DEV_ATTR_LIST(volume_name), + NILFS_DEV_ATTR_LIST(README), + NULL, +}; + +static ssize_t nilfs_dev_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs, + ns_dev_kobj); + struct nilfs_dev_attr *a = container_of(attr, struct nilfs_dev_attr, + attr); + + return a->show ? a->show(a, nilfs, buf) : 0; +} + +static ssize_t nilfs_dev_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t len) +{ + struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs, + ns_dev_kobj); + struct nilfs_dev_attr *a = container_of(attr, struct nilfs_dev_attr, + attr); + + return a->store ? a->store(a, nilfs, buf, len) : 0; +} + +static void nilfs_dev_attr_release(struct kobject *kobj) +{ + struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs, + ns_dev_kobj); + complete(&nilfs->ns_dev_kobj_unregister); +} + +static const struct sysfs_ops nilfs_dev_attr_ops = { + .show = nilfs_dev_attr_show, + .store = nilfs_dev_attr_store, +}; + +static struct kobj_type nilfs_dev_ktype = { + .default_attrs = nilfs_dev_attrs, + .sysfs_ops = &nilfs_dev_attr_ops, + .release = nilfs_dev_attr_release, +}; + +int nilfs_sysfs_create_device_group(struct super_block *sb) +{ + struct the_nilfs *nilfs = sb->s_fs_info; + int err; + + nilfs->ns_dev_kobj.kset = nilfs_kset; + init_completion(&nilfs->ns_dev_kobj_unregister); + err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL, + "%s", sb->s_id); + if (err) + goto failed_create_device_group; + + return 0; + +failed_create_device_group: + return err; +} + +void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) +{ + kobject_del(&nilfs->ns_dev_kobj); +} + /************************************************************************ * NILFS feature attrs * ************************************************************************/ diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h index 0aed24661052..2353b28c2796 100644 --- a/fs/nilfs2/sysfs.h +++ b/fs/nilfs2/sysfs.h @@ -35,6 +35,17 @@ struct nilfs_##name##_attr { \ NILFS_COMMON_ATTR_STRUCT(feature); +#define NILFS_DEV_ATTR_STRUCT(name) \ +struct nilfs_##name##_attr { \ + struct attribute attr; \ + ssize_t (*show)(struct nilfs_##name##_attr *, struct the_nilfs *, \ + char *); \ + ssize_t (*store)(struct nilfs_##name##_attr *, struct the_nilfs *, \ + const char *, size_t); \ +}; + +NILFS_DEV_ATTR_STRUCT(dev); + #define NILFS_ATTR(type, name, mode, show, store) \ static struct nilfs_##type##_attr nilfs_##type##_attr_##name = \ __ATTR(name, mode, show, store) @@ -55,7 +66,16 @@ NILFS_COMMON_ATTR_STRUCT(feature); #define NILFS_FEATURE_RW_ATTR(name) \ NILFS_RW_ATTR(feature, name) +#define NILFS_DEV_INFO_ATTR(name) \ + NILFS_INFO_ATTR(dev, name) +#define NILFS_DEV_RO_ATTR(name) \ + NILFS_RO_ATTR(dev, name) +#define NILFS_DEV_RW_ATTR(name) \ + NILFS_RW_ATTR(dev, name) + #define NILFS_FEATURE_ATTR_LIST(name) \ (&nilfs_feature_attr_##name.attr) +#define NILFS_DEV_ATTR_LIST(name) \ + (&nilfs_dev_attr_##name.attr) #endif /* _NILFS_SYSFS_H */ diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index de8cc53b4a5c..34bc7bd57b0b 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -95,6 +95,8 @@ enum { * @ns_inode_size: size of on-disk inode * @ns_first_ino: first not-special inode number * @ns_crc_seed: seed value of CRC32 calculation + * @ns_dev_kobj: /sys/fs// + * @ns_dev_kobj_unregister: completion state */ struct the_nilfs { unsigned long ns_flags; @@ -188,6 +190,10 @@ struct the_nilfs { int ns_inode_size; int ns_first_ino; u32 ns_crc_seed; + + /* /sys/fs// */ + struct kobject ns_dev_kobj; + struct completion ns_dev_kobj_unregister; }; #define THE_NILFS_FNS(bit, name) \ -- cgit v1.2.3 From caa05d49dfd7fe04820ba8b7e424343d5426a7f3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Fri, 8 Aug 2014 14:20:42 -0700 Subject: nilfs2: add /sys/fs/nilfs2//superblock group This patch adds creation of /sys/fs/nilfs2//superblock group. The superblock group contains attributes that describe superblock's details: (1) sb_write_time - show previous write time of super block in human-readable format. (2) sb_write_time_secs - show previous write time of super block in seconds. (3) sb_write_count - show write count of super block. (4) sb_update_frequency - show/set interval of periodical update of superblock (in seconds). You can set preferable frequency of superblock update by command: echo > /sys/fs/nilfs2//superblock/sb_update_frequency Signed-off-by: Vyacheslav Dubeyko Cc: Vyacheslav Dubeyko Cc: Ryusuke Konishi Cc: Michael L. Semon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-fs-nilfs2 | 33 +++++ fs/nilfs2/sysfs.c | 218 +++++++++++++++++++++++++++++- fs/nilfs2/sysfs.h | 19 +++ fs/nilfs2/the_nilfs.c | 1 + fs/nilfs2/the_nilfs.h | 8 +- 5 files changed, 277 insertions(+), 2 deletions(-) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 index 0a521d03539a..e9b4c61aa88a 100644 --- a/Documentation/ABI/testing/sysfs-fs-nilfs2 +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 @@ -56,3 +56,36 @@ Date: April 2014 Contact: "Vyacheslav Dubeyko" Description: Describe attributes of /sys/fs/nilfs2/ group. + +What: /sys/fs/nilfs2//superblock/sb_write_time +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show last write time of super block in human-readable + format. + +What: /sys/fs/nilfs2//superblock/sb_write_time_secs +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show last write time of super block in seconds. + +What: /sys/fs/nilfs2//superblock/sb_write_count +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show current write count of super block. + +What: /sys/fs/nilfs2//superblock/sb_update_frequency +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show/Set interval of periodical update of superblock + (in seconds). + +What: /sys/fs/nilfs2//superblock/README +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Describe attributes of /sys/fs/nilfs2//superblock + group. diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c index 780d0f5bbe88..239f239da8ae 100644 --- a/fs/nilfs2/sysfs.c +++ b/fs/nilfs2/sysfs.c @@ -41,6 +41,202 @@ static struct kset *nilfs_kset; count; \ }) +#define NILFS_DEV_INT_GROUP_OPS(name, parent_name) \ +static ssize_t nilfs_##name##_attr_show(struct kobject *kobj, \ + struct attribute *attr, char *buf) \ +{ \ + struct the_nilfs *nilfs = container_of(kobj->parent, \ + struct the_nilfs, \ + ns_##parent_name##_kobj); \ + struct nilfs_##name##_attr *a = container_of(attr, \ + struct nilfs_##name##_attr, \ + attr); \ + return a->show ? a->show(a, nilfs, buf) : 0; \ +} \ +static ssize_t nilfs_##name##_attr_store(struct kobject *kobj, \ + struct attribute *attr, \ + const char *buf, size_t len) \ +{ \ + struct the_nilfs *nilfs = container_of(kobj->parent, \ + struct the_nilfs, \ + ns_##parent_name##_kobj); \ + struct nilfs_##name##_attr *a = container_of(attr, \ + struct nilfs_##name##_attr, \ + attr); \ + return a->store ? a->store(a, nilfs, buf, len) : 0; \ +} \ +static const struct sysfs_ops nilfs_##name##_attr_ops = { \ + .show = nilfs_##name##_attr_show, \ + .store = nilfs_##name##_attr_store, \ +}; + +#define NILFS_DEV_INT_GROUP_TYPE(name, parent_name) \ +static void nilfs_##name##_attr_release(struct kobject *kobj) \ +{ \ + struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \ + struct the_nilfs *nilfs = container_of(kobj->parent, \ + struct the_nilfs, \ + ns_##parent_name##_kobj); \ + subgroups = nilfs->ns_##parent_name##_subgroups; \ + complete(&subgroups->sg_##name##_kobj_unregister); \ +} \ +static struct kobj_type nilfs_##name##_ktype = { \ + .default_attrs = nilfs_##name##_attrs, \ + .sysfs_ops = &nilfs_##name##_attr_ops, \ + .release = nilfs_##name##_attr_release, \ +}; + +#define NILFS_DEV_INT_GROUP_FNS(name, parent_name) \ +int nilfs_sysfs_create_##name##_group(struct the_nilfs *nilfs) \ +{ \ + struct kobject *parent; \ + struct kobject *kobj; \ + struct completion *kobj_unregister; \ + struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \ + int err; \ + subgroups = nilfs->ns_##parent_name##_subgroups; \ + kobj = &subgroups->sg_##name##_kobj; \ + kobj_unregister = &subgroups->sg_##name##_kobj_unregister; \ + parent = &nilfs->ns_##parent_name##_kobj; \ + kobj->kset = nilfs_kset; \ + init_completion(kobj_unregister); \ + err = kobject_init_and_add(kobj, &nilfs_##name##_ktype, parent, \ + #name); \ + if (err) \ + return err; \ + return 0; \ +} \ +void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \ +{ \ + kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \ +} + +/************************************************************************ + * NILFS superblock attrs * + ************************************************************************/ + +static ssize_t +nilfs_superblock_sb_write_time_show(struct nilfs_superblock_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + time_t sbwtime; + + down_read(&nilfs->ns_sem); + sbwtime = nilfs->ns_sbwtime; + up_read(&nilfs->ns_sem); + + return NILFS_SHOW_TIME(sbwtime, buf); +} + +static ssize_t +nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + time_t sbwtime; + + down_read(&nilfs->ns_sem); + sbwtime = nilfs->ns_sbwtime; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)sbwtime); +} + +static ssize_t +nilfs_superblock_sb_write_count_show(struct nilfs_superblock_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + unsigned sbwcount; + + down_read(&nilfs->ns_sem); + sbwcount = nilfs->ns_sbwcount; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%u\n", sbwcount); +} + +static ssize_t +nilfs_superblock_sb_update_frequency_show(struct nilfs_superblock_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + unsigned sb_update_freq; + + down_read(&nilfs->ns_sem); + sb_update_freq = nilfs->ns_sb_update_freq; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%u\n", sb_update_freq); +} + +static ssize_t +nilfs_superblock_sb_update_frequency_store(struct nilfs_superblock_attr *attr, + struct the_nilfs *nilfs, + const char *buf, size_t count) +{ + unsigned val; + int err; + + err = kstrtouint(skip_spaces(buf), 0, &val); + if (err) { + printk(KERN_ERR "NILFS: unable to convert string: err=%d\n", + err); + return err; + } + + if (val < NILFS_SB_FREQ) { + val = NILFS_SB_FREQ; + printk(KERN_WARNING "NILFS: superblock update frequency cannot be lesser than 10 seconds\n"); + } + + down_write(&nilfs->ns_sem); + nilfs->ns_sb_update_freq = val; + up_write(&nilfs->ns_sem); + + return count; +} + +static const char sb_readme_str[] = + "The superblock group contains attributes that describe\n" + "superblock's details.\n\n" + "(1) sb_write_time\n\tshow previous write time of super block " + "in human-readable format.\n\n" + "(2) sb_write_time_secs\n\tshow previous write time of super block " + "in seconds.\n\n" + "(3) sb_write_count\n\tshow write count of super block.\n\n" + "(4) sb_update_frequency\n" + "\tshow/set interval of periodical update of superblock (in seconds).\n\n" + "\tYou can set preferable frequency of superblock update by command:\n\n" + "\t'echo > /sys/fs///superblock/sb_update_frequency'\n"; + +static ssize_t +nilfs_superblock_README_show(struct nilfs_superblock_attr *attr, + struct the_nilfs *nilfs, char *buf) +{ + return snprintf(buf, PAGE_SIZE, sb_readme_str); +} + +NILFS_SUPERBLOCK_RO_ATTR(sb_write_time); +NILFS_SUPERBLOCK_RO_ATTR(sb_write_time_secs); +NILFS_SUPERBLOCK_RO_ATTR(sb_write_count); +NILFS_SUPERBLOCK_RW_ATTR(sb_update_frequency); +NILFS_SUPERBLOCK_RO_ATTR(README); + +static struct attribute *nilfs_superblock_attrs[] = { + NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time), + NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time_secs), + NILFS_SUPERBLOCK_ATTR_LIST(sb_write_count), + NILFS_SUPERBLOCK_ATTR_LIST(sb_update_frequency), + NILFS_SUPERBLOCK_ATTR_LIST(README), + NULL, +}; + +NILFS_DEV_INT_GROUP_OPS(superblock, dev); +NILFS_DEV_INT_GROUP_TYPE(superblock, dev); +NILFS_DEV_INT_GROUP_FNS(superblock, dev); + /************************************************************************ * NILFS device attrs * ************************************************************************/ @@ -189,24 +385,44 @@ static struct kobj_type nilfs_dev_ktype = { int nilfs_sysfs_create_device_group(struct super_block *sb) { struct the_nilfs *nilfs = sb->s_fs_info; + size_t devgrp_size = sizeof(struct nilfs_sysfs_dev_subgroups); int err; + nilfs->ns_dev_subgroups = kzalloc(devgrp_size, GFP_KERNEL); + if (unlikely(!nilfs->ns_dev_subgroups)) { + err = -ENOMEM; + printk(KERN_ERR "NILFS: unable to allocate memory for device group\n"); + goto failed_create_device_group; + } + nilfs->ns_dev_kobj.kset = nilfs_kset; init_completion(&nilfs->ns_dev_kobj_unregister); err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL, "%s", sb->s_id); if (err) - goto failed_create_device_group; + goto free_dev_subgroups; + + err = nilfs_sysfs_create_superblock_group(nilfs); + if (err) + goto cleanup_dev_kobject; return 0; +cleanup_dev_kobject: + kobject_del(&nilfs->ns_dev_kobj); + +free_dev_subgroups: + kfree(nilfs->ns_dev_subgroups); + failed_create_device_group: return err; } void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) { + nilfs_sysfs_delete_superblock_group(nilfs); kobject_del(&nilfs->ns_dev_kobj); + kfree(nilfs->ns_dev_subgroups); } /************************************************************************ diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h index 2353b28c2796..1d76af59238c 100644 --- a/fs/nilfs2/sysfs.h +++ b/fs/nilfs2/sysfs.h @@ -24,6 +24,17 @@ #define NILFS_ROOT_GROUP_NAME "nilfs2" +/* + * struct nilfs_sysfs_dev_subgroups - device subgroup kernel objects + * @sg_superblock_kobj: /sys/fs///superblock + * @sg_superblock_kobj_unregister: completion state + */ +struct nilfs_sysfs_dev_subgroups { + /* /sys/fs///superblock */ + struct kobject sg_superblock_kobj; + struct completion sg_superblock_kobj_unregister; +}; + #define NILFS_COMMON_ATTR_STRUCT(name) \ struct nilfs_##name##_attr { \ struct attribute attr; \ @@ -45,6 +56,7 @@ struct nilfs_##name##_attr { \ }; NILFS_DEV_ATTR_STRUCT(dev); +NILFS_DEV_ATTR_STRUCT(superblock); #define NILFS_ATTR(type, name, mode, show, store) \ static struct nilfs_##type##_attr nilfs_##type##_attr_##name = \ @@ -73,9 +85,16 @@ NILFS_DEV_ATTR_STRUCT(dev); #define NILFS_DEV_RW_ATTR(name) \ NILFS_RW_ATTR(dev, name) +#define NILFS_SUPERBLOCK_RO_ATTR(name) \ + NILFS_RO_ATTR(superblock, name) +#define NILFS_SUPERBLOCK_RW_ATTR(name) \ + NILFS_RW_ATTR(superblock, name) + #define NILFS_FEATURE_ATTR_LIST(name) \ (&nilfs_feature_attr_##name.attr) #define NILFS_DEV_ATTR_LIST(name) \ (&nilfs_dev_attr_##name.attr) +#define NILFS_SUPERBLOCK_ATTR_LIST(name) \ + (&nilfs_superblock_attr_##name.attr) #endif /* _NILFS_SYSFS_H */ diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 8ba8229ba076..59d50088b886 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -85,6 +85,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) nilfs->ns_cptree = RB_ROOT; spin_lock_init(&nilfs->ns_cptree_lock); init_rwsem(&nilfs->ns_segctor_sem); + nilfs->ns_sb_update_freq = NILFS_SB_FREQ; return nilfs; } diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 34bc7bd57b0b..7fe822307f98 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -33,6 +33,7 @@ #include struct nilfs_sc_info; +struct nilfs_sysfs_dev_subgroups; /* the_nilfs struct */ enum { @@ -54,6 +55,7 @@ enum { * @ns_sbwcount: write count of super block * @ns_sbsize: size of valid data in super block * @ns_mount_state: file system state + * @ns_sb_update_freq: interval of periodical update of superblocks (in seconds) * @ns_seg_seq: segment sequence counter * @ns_segnum: index number of the latest full segment. * @ns_nextnum: index number of the full segment index to be used next @@ -97,6 +99,7 @@ enum { * @ns_crc_seed: seed value of CRC32 calculation * @ns_dev_kobj: /sys/fs// * @ns_dev_kobj_unregister: completion state + * @ns_dev_subgroups: subgroups pointer */ struct the_nilfs { unsigned long ns_flags; @@ -116,6 +119,7 @@ struct the_nilfs { unsigned ns_sbwcount; unsigned ns_sbsize; unsigned ns_mount_state; + unsigned ns_sb_update_freq; /* * Following fields are dedicated to a writable FS-instance. @@ -194,6 +198,7 @@ struct the_nilfs { /* /sys/fs// */ struct kobject ns_dev_kobj; struct completion ns_dev_kobj_unregister; + struct nilfs_sysfs_dev_subgroups *ns_dev_subgroups; }; #define THE_NILFS_FNS(bit, name) \ @@ -260,7 +265,8 @@ struct nilfs_root { static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) { u64 t = get_seconds(); - return t < nilfs->ns_sbwtime || t > nilfs->ns_sbwtime + NILFS_SB_FREQ; + return t < nilfs->ns_sbwtime || + t > nilfs->ns_sbwtime + nilfs->ns_sb_update_freq; } static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) -- cgit v1.2.3 From abc968dbf291955ac750ecf59e3baf2b529a8257 Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Fri, 8 Aug 2014 14:20:44 -0700 Subject: nilfs2: add /sys/fs/nilfs2//segctor group This patch adds creation of /sys/fs/nilfs2//segctor group. The segctor group contains attributes that describe segctor thread activity details: (1) last_pseg_block - show start block number of the latest segment. (2) last_seg_sequence - show sequence value of the latest segment. (3) last_seg_checkpoint - show checkpoint number of the latest segment. (4) current_seg_sequence - show segment sequence counter. (5) current_last_full_seg - show index number of the latest full segment. (6) next_full_seg - show index number of the full segment index to be used next. (7) next_pseg_offset - show offset of next partial segment in the current full segment. (8) next_checkpoint - show next checkpoint number. (9) last_seg_write_time - show write time of the last segment in human-readable format. (10) last_seg_write_time_secs - show write time of the last segment in seconds. (11) last_nongc_write_time - show write time of the last segment not for cleaner operation in human-readable format. (12) last_nongc_write_time_secs - show write time of the last segment not for cleaner operation in seconds. (13) dirty_data_blocks_count - show number of dirty data blocks. Signed-off-by: Vyacheslav Dubeyko Cc: Vyacheslav Dubeyko Cc: Ryusuke Konishi Cc: Michael L. Semon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-fs-nilfs2 | 90 ++++++++++ fs/nilfs2/sysfs.c | 270 ++++++++++++++++++++++++++++++ fs/nilfs2/sysfs.h | 16 ++ 3 files changed, 376 insertions(+) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 index e9b4c61aa88a..c9952f4071e7 100644 --- a/Documentation/ABI/testing/sysfs-fs-nilfs2 +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 @@ -89,3 +89,93 @@ Contact: "Vyacheslav Dubeyko" Description: Describe attributes of /sys/fs/nilfs2//superblock group. + +What: /sys/fs/nilfs2//segctor/last_pseg_block +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show start block number of the latest segment. + +What: /sys/fs/nilfs2//segctor/last_seg_sequence +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show sequence value of the latest segment. + +What: /sys/fs/nilfs2//segctor/last_seg_checkpoint +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show checkpoint number of the latest segment. + +What: /sys/fs/nilfs2//segctor/current_seg_sequence +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show segment sequence counter. + +What: /sys/fs/nilfs2//segctor/current_last_full_seg +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show index number of the latest full segment. + +What: /sys/fs/nilfs2//segctor/next_full_seg +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show index number of the full segment index + to be used next. + +What: /sys/fs/nilfs2//segctor/next_pseg_offset +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show offset of next partial segment in the current + full segment. + +What: /sys/fs/nilfs2//segctor/next_checkpoint +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show next checkpoint number. + +What: /sys/fs/nilfs2//segctor/last_seg_write_time +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show write time of the last segment in + human-readable format. + +What: /sys/fs/nilfs2//segctor/last_seg_write_time_secs +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show write time of the last segment in seconds. + +What: /sys/fs/nilfs2//segctor/last_nongc_write_time +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show write time of the last segment not for cleaner + operation in human-readable format. + +What: /sys/fs/nilfs2//segctor/last_nongc_write_time_secs +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show write time of the last segment not for cleaner + operation in seconds. + +What: /sys/fs/nilfs2//segctor/dirty_data_blocks_count +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show number of dirty data blocks. + +What: /sys/fs/nilfs2//segctor/README +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Describe attributes of /sys/fs/nilfs2//segctor + group. diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c index 239f239da8ae..61454a859e81 100644 --- a/fs/nilfs2/sysfs.c +++ b/fs/nilfs2/sysfs.c @@ -111,6 +111,268 @@ void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \ kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \ } +/************************************************************************ + * NILFS segctor attrs * + ************************************************************************/ + +static ssize_t +nilfs_segctor_last_pseg_block_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + sector_t last_pseg; + + spin_lock(&nilfs->ns_last_segment_lock); + last_pseg = nilfs->ns_last_pseg; + spin_unlock(&nilfs->ns_last_segment_lock); + + return snprintf(buf, PAGE_SIZE, "%llu\n", + (unsigned long long)last_pseg); +} + +static ssize_t +nilfs_segctor_last_seg_sequence_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + u64 last_seq; + + spin_lock(&nilfs->ns_last_segment_lock); + last_seq = nilfs->ns_last_seq; + spin_unlock(&nilfs->ns_last_segment_lock); + + return snprintf(buf, PAGE_SIZE, "%llu\n", last_seq); +} + +static ssize_t +nilfs_segctor_last_seg_checkpoint_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + __u64 last_cno; + + spin_lock(&nilfs->ns_last_segment_lock); + last_cno = nilfs->ns_last_cno; + spin_unlock(&nilfs->ns_last_segment_lock); + + return snprintf(buf, PAGE_SIZE, "%llu\n", last_cno); +} + +static ssize_t +nilfs_segctor_current_seg_sequence_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + u64 seg_seq; + + down_read(&nilfs->ns_sem); + seg_seq = nilfs->ns_seg_seq; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%llu\n", seg_seq); +} + +static ssize_t +nilfs_segctor_current_last_full_seg_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + __u64 segnum; + + down_read(&nilfs->ns_sem); + segnum = nilfs->ns_segnum; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%llu\n", segnum); +} + +static ssize_t +nilfs_segctor_next_full_seg_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + __u64 nextnum; + + down_read(&nilfs->ns_sem); + nextnum = nilfs->ns_nextnum; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%llu\n", nextnum); +} + +static ssize_t +nilfs_segctor_next_pseg_offset_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + unsigned long pseg_offset; + + down_read(&nilfs->ns_sem); + pseg_offset = nilfs->ns_pseg_offset; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%lu\n", pseg_offset); +} + +static ssize_t +nilfs_segctor_next_checkpoint_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + __u64 cno; + + down_read(&nilfs->ns_sem); + cno = nilfs->ns_cno; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%llu\n", cno); +} + +static ssize_t +nilfs_segctor_last_seg_write_time_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + time_t ctime; + + down_read(&nilfs->ns_sem); + ctime = nilfs->ns_ctime; + up_read(&nilfs->ns_sem); + + return NILFS_SHOW_TIME(ctime, buf); +} + +static ssize_t +nilfs_segctor_last_seg_write_time_secs_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + time_t ctime; + + down_read(&nilfs->ns_sem); + ctime = nilfs->ns_ctime; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)ctime); +} + +static ssize_t +nilfs_segctor_last_nongc_write_time_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + time_t nongc_ctime; + + down_read(&nilfs->ns_sem); + nongc_ctime = nilfs->ns_nongc_ctime; + up_read(&nilfs->ns_sem); + + return NILFS_SHOW_TIME(nongc_ctime, buf); +} + +static ssize_t +nilfs_segctor_last_nongc_write_time_secs_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + time_t nongc_ctime; + + down_read(&nilfs->ns_sem); + nongc_ctime = nilfs->ns_nongc_ctime; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%llu\n", + (unsigned long long)nongc_ctime); +} + +static ssize_t +nilfs_segctor_dirty_data_blocks_count_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + u32 ndirtyblks; + + down_read(&nilfs->ns_sem); + ndirtyblks = atomic_read(&nilfs->ns_ndirtyblks); + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%u\n", ndirtyblks); +} + +static const char segctor_readme_str[] = + "The segctor group contains attributes that describe\n" + "segctor thread activity details.\n\n" + "(1) last_pseg_block\n" + "\tshow start block number of the latest segment.\n\n" + "(2) last_seg_sequence\n" + "\tshow sequence value of the latest segment.\n\n" + "(3) last_seg_checkpoint\n" + "\tshow checkpoint number of the latest segment.\n\n" + "(4) current_seg_sequence\n\tshow segment sequence counter.\n\n" + "(5) current_last_full_seg\n" + "\tshow index number of the latest full segment.\n\n" + "(6) next_full_seg\n" + "\tshow index number of the full segment index to be used next.\n\n" + "(7) next_pseg_offset\n" + "\tshow offset of next partial segment in the current full segment.\n\n" + "(8) next_checkpoint\n\tshow next checkpoint number.\n\n" + "(9) last_seg_write_time\n" + "\tshow write time of the last segment in human-readable format.\n\n" + "(10) last_seg_write_time_secs\n" + "\tshow write time of the last segment in seconds.\n\n" + "(11) last_nongc_write_time\n" + "\tshow write time of the last segment not for cleaner operation " + "in human-readable format.\n\n" + "(12) last_nongc_write_time_secs\n" + "\tshow write time of the last segment not for cleaner operation " + "in seconds.\n\n" + "(13) dirty_data_blocks_count\n" + "\tshow number of dirty data blocks.\n\n"; + +static ssize_t +nilfs_segctor_README_show(struct nilfs_segctor_attr *attr, + struct the_nilfs *nilfs, char *buf) +{ + return snprintf(buf, PAGE_SIZE, segctor_readme_str); +} + +NILFS_SEGCTOR_RO_ATTR(last_pseg_block); +NILFS_SEGCTOR_RO_ATTR(last_seg_sequence); +NILFS_SEGCTOR_RO_ATTR(last_seg_checkpoint); +NILFS_SEGCTOR_RO_ATTR(current_seg_sequence); +NILFS_SEGCTOR_RO_ATTR(current_last_full_seg); +NILFS_SEGCTOR_RO_ATTR(next_full_seg); +NILFS_SEGCTOR_RO_ATTR(next_pseg_offset); +NILFS_SEGCTOR_RO_ATTR(next_checkpoint); +NILFS_SEGCTOR_RO_ATTR(last_seg_write_time); +NILFS_SEGCTOR_RO_ATTR(last_seg_write_time_secs); +NILFS_SEGCTOR_RO_ATTR(last_nongc_write_time); +NILFS_SEGCTOR_RO_ATTR(last_nongc_write_time_secs); +NILFS_SEGCTOR_RO_ATTR(dirty_data_blocks_count); +NILFS_SEGCTOR_RO_ATTR(README); + +static struct attribute *nilfs_segctor_attrs[] = { + NILFS_SEGCTOR_ATTR_LIST(last_pseg_block), + NILFS_SEGCTOR_ATTR_LIST(last_seg_sequence), + NILFS_SEGCTOR_ATTR_LIST(last_seg_checkpoint), + NILFS_SEGCTOR_ATTR_LIST(current_seg_sequence), + NILFS_SEGCTOR_ATTR_LIST(current_last_full_seg), + NILFS_SEGCTOR_ATTR_LIST(next_full_seg), + NILFS_SEGCTOR_ATTR_LIST(next_pseg_offset), + NILFS_SEGCTOR_ATTR_LIST(next_checkpoint), + NILFS_SEGCTOR_ATTR_LIST(last_seg_write_time), + NILFS_SEGCTOR_ATTR_LIST(last_seg_write_time_secs), + NILFS_SEGCTOR_ATTR_LIST(last_nongc_write_time), + NILFS_SEGCTOR_ATTR_LIST(last_nongc_write_time_secs), + NILFS_SEGCTOR_ATTR_LIST(dirty_data_blocks_count), + NILFS_SEGCTOR_ATTR_LIST(README), + NULL, +}; + +NILFS_DEV_INT_GROUP_OPS(segctor, dev); +NILFS_DEV_INT_GROUP_TYPE(segctor, dev); +NILFS_DEV_INT_GROUP_FNS(segctor, dev); + /************************************************************************ * NILFS superblock attrs * ************************************************************************/ @@ -406,8 +668,15 @@ int nilfs_sysfs_create_device_group(struct super_block *sb) if (err) goto cleanup_dev_kobject; + err = nilfs_sysfs_create_segctor_group(nilfs); + if (err) + goto delete_superblock_group; + return 0; +delete_superblock_group: + nilfs_sysfs_delete_superblock_group(nilfs); + cleanup_dev_kobject: kobject_del(&nilfs->ns_dev_kobj); @@ -421,6 +690,7 @@ failed_create_device_group: void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) { nilfs_sysfs_delete_superblock_group(nilfs); + nilfs_sysfs_delete_segctor_group(nilfs); kobject_del(&nilfs->ns_dev_kobj); kfree(nilfs->ns_dev_subgroups); } diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h index 1d76af59238c..ad4d5bcc16f5 100644 --- a/fs/nilfs2/sysfs.h +++ b/fs/nilfs2/sysfs.h @@ -28,11 +28,17 @@ * struct nilfs_sysfs_dev_subgroups - device subgroup kernel objects * @sg_superblock_kobj: /sys/fs///superblock * @sg_superblock_kobj_unregister: completion state + * @sg_segctor_kobj: /sys/fs///segctor + * @sg_segctor_kobj_unregister: completion state */ struct nilfs_sysfs_dev_subgroups { /* /sys/fs///superblock */ struct kobject sg_superblock_kobj; struct completion sg_superblock_kobj_unregister; + + /* /sys/fs///segctor */ + struct kobject sg_segctor_kobj; + struct completion sg_segctor_kobj_unregister; }; #define NILFS_COMMON_ATTR_STRUCT(name) \ @@ -57,6 +63,7 @@ struct nilfs_##name##_attr { \ NILFS_DEV_ATTR_STRUCT(dev); NILFS_DEV_ATTR_STRUCT(superblock); +NILFS_DEV_ATTR_STRUCT(segctor); #define NILFS_ATTR(type, name, mode, show, store) \ static struct nilfs_##type##_attr nilfs_##type##_attr_##name = \ @@ -90,11 +97,20 @@ NILFS_DEV_ATTR_STRUCT(superblock); #define NILFS_SUPERBLOCK_RW_ATTR(name) \ NILFS_RW_ATTR(superblock, name) +#define NILFS_SEGCTOR_INFO_ATTR(name) \ + NILFS_INFO_ATTR(segctor, name) +#define NILFS_SEGCTOR_RO_ATTR(name) \ + NILFS_RO_ATTR(segctor, name) +#define NILFS_SEGCTOR_RW_ATTR(name) \ + NILFS_RW_ATTR(segctor, name) + #define NILFS_FEATURE_ATTR_LIST(name) \ (&nilfs_feature_attr_##name.attr) #define NILFS_DEV_ATTR_LIST(name) \ (&nilfs_dev_attr_##name.attr) #define NILFS_SUPERBLOCK_ATTR_LIST(name) \ (&nilfs_superblock_attr_##name.attr) +#define NILFS_SEGCTOR_ATTR_LIST(name) \ + (&nilfs_segctor_attr_##name.attr) #endif /* _NILFS_SYSFS_H */ -- cgit v1.2.3 From ef43d5cd84b7d2ea09846de34e14be7d74be3e6f Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Fri, 8 Aug 2014 14:20:46 -0700 Subject: nilfs2: add /sys/fs/nilfs2//segments group This patch adds creation of /sys/fs/nilfs2//segments group. The segments group contains attributes that describe details about volume's segments: (1) segments_number - show number of segments on volume. (2) blocks_per_segment - show number of blocks in segment. (3) clean_segments - show count of clean segments. (4) dirty_segments - show count of dirty segments. Signed-off-by: Vyacheslav Dubeyko Cc: Vyacheslav Dubeyko Cc: Ryusuke Konishi Cc: Michael L. Semon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-fs-nilfs2 | 31 ++++++++++ fs/nilfs2/sysfs.c | 99 ++++++++++++++++++++++++++++++- fs/nilfs2/sysfs.h | 14 +++++ 3 files changed, 143 insertions(+), 1 deletion(-) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 index c9952f4071e7..d39e0768171e 100644 --- a/Documentation/ABI/testing/sysfs-fs-nilfs2 +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 @@ -179,3 +179,34 @@ Contact: "Vyacheslav Dubeyko" Description: Describe attributes of /sys/fs/nilfs2//segctor group. + +What: /sys/fs/nilfs2//segments/segments_number +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show number of segments on a volume. + +What: /sys/fs/nilfs2//segments/blocks_per_segment +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show number of blocks in segment. + +What: /sys/fs/nilfs2//segments/clean_segments +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show count of clean segments. + +What: /sys/fs/nilfs2//segments/dirty_segments +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show count of dirty segments. + +What: /sys/fs/nilfs2//segments/README +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Describe attributes of /sys/fs/nilfs2//segments + group. diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c index 61454a859e81..fe8e1411dc6a 100644 --- a/fs/nilfs2/sysfs.c +++ b/fs/nilfs2/sysfs.c @@ -111,6 +111,95 @@ void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \ kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \ } +/************************************************************************ + * NILFS segments attrs * + ************************************************************************/ + +static ssize_t +nilfs_segments_segments_number_show(struct nilfs_segments_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%lu\n", nilfs->ns_nsegments); +} + +static ssize_t +nilfs_segments_blocks_per_segment_show(struct nilfs_segments_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%lu\n", nilfs->ns_blocks_per_segment); +} + +static ssize_t +nilfs_segments_clean_segments_show(struct nilfs_segments_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + unsigned long ncleansegs; + + down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); + ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); + up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); + + return snprintf(buf, PAGE_SIZE, "%lu\n", ncleansegs); +} + +static ssize_t +nilfs_segments_dirty_segments_show(struct nilfs_segments_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + struct nilfs_sustat sustat; + int err; + + down_read(&nilfs->ns_segctor_sem); + err = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat); + up_read(&nilfs->ns_segctor_sem); + if (err < 0) { + printk(KERN_ERR "NILFS: unable to get segment stat: err=%d\n", + err); + return err; + } + + return snprintf(buf, PAGE_SIZE, "%llu\n", sustat.ss_ndirtysegs); +} + +static const char segments_readme_str[] = + "The segments group contains attributes that describe\n" + "details about volume's segments.\n\n" + "(1) segments_number\n\tshow number of segments on volume.\n\n" + "(2) blocks_per_segment\n\tshow number of blocks in segment.\n\n" + "(3) clean_segments\n\tshow count of clean segments.\n\n" + "(4) dirty_segments\n\tshow count of dirty segments.\n\n"; + +static ssize_t +nilfs_segments_README_show(struct nilfs_segments_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, segments_readme_str); +} + +NILFS_SEGMENTS_RO_ATTR(segments_number); +NILFS_SEGMENTS_RO_ATTR(blocks_per_segment); +NILFS_SEGMENTS_RO_ATTR(clean_segments); +NILFS_SEGMENTS_RO_ATTR(dirty_segments); +NILFS_SEGMENTS_RO_ATTR(README); + +static struct attribute *nilfs_segments_attrs[] = { + NILFS_SEGMENTS_ATTR_LIST(segments_number), + NILFS_SEGMENTS_ATTR_LIST(blocks_per_segment), + NILFS_SEGMENTS_ATTR_LIST(clean_segments), + NILFS_SEGMENTS_ATTR_LIST(dirty_segments), + NILFS_SEGMENTS_ATTR_LIST(README), + NULL, +}; + +NILFS_DEV_INT_GROUP_OPS(segments, dev); +NILFS_DEV_INT_GROUP_TYPE(segments, dev); +NILFS_DEV_INT_GROUP_FNS(segments, dev); + /************************************************************************ * NILFS segctor attrs * ************************************************************************/ @@ -664,10 +753,14 @@ int nilfs_sysfs_create_device_group(struct super_block *sb) if (err) goto free_dev_subgroups; - err = nilfs_sysfs_create_superblock_group(nilfs); + err = nilfs_sysfs_create_segments_group(nilfs); if (err) goto cleanup_dev_kobject; + err = nilfs_sysfs_create_superblock_group(nilfs); + if (err) + goto delete_segments_group; + err = nilfs_sysfs_create_segctor_group(nilfs); if (err) goto delete_superblock_group; @@ -677,6 +770,9 @@ int nilfs_sysfs_create_device_group(struct super_block *sb) delete_superblock_group: nilfs_sysfs_delete_superblock_group(nilfs); +delete_segments_group: + nilfs_sysfs_delete_segments_group(nilfs); + cleanup_dev_kobject: kobject_del(&nilfs->ns_dev_kobj); @@ -689,6 +785,7 @@ failed_create_device_group: void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) { + nilfs_sysfs_delete_segments_group(nilfs); nilfs_sysfs_delete_superblock_group(nilfs); nilfs_sysfs_delete_segctor_group(nilfs); kobject_del(&nilfs->ns_dev_kobj); diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h index ad4d5bcc16f5..228bdd14f945 100644 --- a/fs/nilfs2/sysfs.h +++ b/fs/nilfs2/sysfs.h @@ -30,6 +30,8 @@ * @sg_superblock_kobj_unregister: completion state * @sg_segctor_kobj: /sys/fs///segctor * @sg_segctor_kobj_unregister: completion state + * @sg_segments_kobj: /sys/fs///segments + * @sg_segments_kobj_unregister: completion state */ struct nilfs_sysfs_dev_subgroups { /* /sys/fs///superblock */ @@ -39,6 +41,10 @@ struct nilfs_sysfs_dev_subgroups { /* /sys/fs///segctor */ struct kobject sg_segctor_kobj; struct completion sg_segctor_kobj_unregister; + + /* /sys/fs///segments */ + struct kobject sg_segments_kobj; + struct completion sg_segments_kobj_unregister; }; #define NILFS_COMMON_ATTR_STRUCT(name) \ @@ -62,6 +68,7 @@ struct nilfs_##name##_attr { \ }; NILFS_DEV_ATTR_STRUCT(dev); +NILFS_DEV_ATTR_STRUCT(segments); NILFS_DEV_ATTR_STRUCT(superblock); NILFS_DEV_ATTR_STRUCT(segctor); @@ -92,6 +99,11 @@ NILFS_DEV_ATTR_STRUCT(segctor); #define NILFS_DEV_RW_ATTR(name) \ NILFS_RW_ATTR(dev, name) +#define NILFS_SEGMENTS_RO_ATTR(name) \ + NILFS_RO_ATTR(segments, name) +#define NILFS_SEGMENTS_RW_ATTR(name) \ + NILFS_RW_ATTR(segs_info, name) + #define NILFS_SUPERBLOCK_RO_ATTR(name) \ NILFS_RO_ATTR(superblock, name) #define NILFS_SUPERBLOCK_RW_ATTR(name) \ @@ -108,6 +120,8 @@ NILFS_DEV_ATTR_STRUCT(segctor); (&nilfs_feature_attr_##name.attr) #define NILFS_DEV_ATTR_LIST(name) \ (&nilfs_dev_attr_##name.attr) +#define NILFS_SEGMENTS_ATTR_LIST(name) \ + (&nilfs_segments_attr_##name.attr) #define NILFS_SUPERBLOCK_ATTR_LIST(name) \ (&nilfs_superblock_attr_##name.attr) #define NILFS_SEGCTOR_ATTR_LIST(name) \ -- cgit v1.2.3 From 02a0ba1c60c2ad532322089a60256c8b0f46678c Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Fri, 8 Aug 2014 14:20:48 -0700 Subject: nilfs2: add /sys/fs/nilfs2//checkpoints group This patch adds creation of /sys/fs/nilfs2//checkpoints group. The checkpoints group contains attributes that describe details about volume's checkpoints: (1) checkpoints_number - show number of checkpoints on volume. (2) snapshots_number - show number of snapshots on volume. (3) last_seg_checkpoint - show checkpoint number of the latest segment. (4) next_checkpoint - show next checkpoint number. Signed-off-by: Vyacheslav Dubeyko Cc: Vyacheslav Dubeyko Cc: Ryusuke Konishi Cc: Michael L. Semon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-fs-nilfs2 | 31 ++++++++ fs/nilfs2/sysfs.c | 123 +++++++++++++++++++++++++++++- fs/nilfs2/sysfs.h | 14 ++++ 3 files changed, 167 insertions(+), 1 deletion(-) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 index d39e0768171e..7b820d65d3f0 100644 --- a/Documentation/ABI/testing/sysfs-fs-nilfs2 +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 @@ -210,3 +210,34 @@ Contact: "Vyacheslav Dubeyko" Description: Describe attributes of /sys/fs/nilfs2//segments group. + +What: /sys/fs/nilfs2//checkpoints/checkpoints_number +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show number of checkpoints on volume. + +What: /sys/fs/nilfs2//checkpoints/snapshots_number +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show number of snapshots on volume. + +What: /sys/fs/nilfs2//checkpoints/last_seg_checkpoint +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show checkpoint number of the latest segment. + +What: /sys/fs/nilfs2//checkpoints/next_checkpoint +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show next checkpoint number. + +What: /sys/fs/nilfs2//checkpoints/README +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Describe attributes of /sys/fs/nilfs2//checkpoints + group. diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c index fe8e1411dc6a..5cc735fcc1d5 100644 --- a/fs/nilfs2/sysfs.c +++ b/fs/nilfs2/sysfs.c @@ -111,6 +111,119 @@ void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \ kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \ } +/************************************************************************ + * NILFS checkpoints attrs * + ************************************************************************/ + +static ssize_t +nilfs_checkpoints_checkpoints_number_show(struct nilfs_checkpoints_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + __u64 ncheckpoints; + struct nilfs_cpstat cpstat; + int err; + + down_read(&nilfs->ns_segctor_sem); + err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); + up_read(&nilfs->ns_segctor_sem); + if (err < 0) { + printk(KERN_ERR "NILFS: unable to get checkpoint stat: err=%d\n", + err); + return err; + } + + ncheckpoints = cpstat.cs_ncps; + + return snprintf(buf, PAGE_SIZE, "%llu\n", ncheckpoints); +} + +static ssize_t +nilfs_checkpoints_snapshots_number_show(struct nilfs_checkpoints_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + __u64 nsnapshots; + struct nilfs_cpstat cpstat; + int err; + + down_read(&nilfs->ns_segctor_sem); + err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); + up_read(&nilfs->ns_segctor_sem); + if (err < 0) { + printk(KERN_ERR "NILFS: unable to get checkpoint stat: err=%d\n", + err); + return err; + } + + nsnapshots = cpstat.cs_nsss; + + return snprintf(buf, PAGE_SIZE, "%llu\n", nsnapshots); +} + +static ssize_t +nilfs_checkpoints_last_seg_checkpoint_show(struct nilfs_checkpoints_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + __u64 last_cno; + + spin_lock(&nilfs->ns_last_segment_lock); + last_cno = nilfs->ns_last_cno; + spin_unlock(&nilfs->ns_last_segment_lock); + + return snprintf(buf, PAGE_SIZE, "%llu\n", last_cno); +} + +static ssize_t +nilfs_checkpoints_next_checkpoint_show(struct nilfs_checkpoints_attr *attr, + struct the_nilfs *nilfs, + char *buf) +{ + __u64 cno; + + down_read(&nilfs->ns_sem); + cno = nilfs->ns_cno; + up_read(&nilfs->ns_sem); + + return snprintf(buf, PAGE_SIZE, "%llu\n", cno); +} + +static const char checkpoints_readme_str[] = + "The checkpoints group contains attributes that describe\n" + "details about volume's checkpoints.\n\n" + "(1) checkpoints_number\n\tshow number of checkpoints on volume.\n\n" + "(2) snapshots_number\n\tshow number of snapshots on volume.\n\n" + "(3) last_seg_checkpoint\n" + "\tshow checkpoint number of the latest segment.\n\n" + "(4) next_checkpoint\n\tshow next checkpoint number.\n\n"; + +static ssize_t +nilfs_checkpoints_README_show(struct nilfs_checkpoints_attr *attr, + struct the_nilfs *nilfs, char *buf) +{ + return snprintf(buf, PAGE_SIZE, checkpoints_readme_str); +} + +NILFS_CHECKPOINTS_RO_ATTR(checkpoints_number); +NILFS_CHECKPOINTS_RO_ATTR(snapshots_number); +NILFS_CHECKPOINTS_RO_ATTR(last_seg_checkpoint); +NILFS_CHECKPOINTS_RO_ATTR(next_checkpoint); +NILFS_CHECKPOINTS_RO_ATTR(README); + +static struct attribute *nilfs_checkpoints_attrs[] = { + NILFS_CHECKPOINTS_ATTR_LIST(checkpoints_number), + NILFS_CHECKPOINTS_ATTR_LIST(snapshots_number), + NILFS_CHECKPOINTS_ATTR_LIST(last_seg_checkpoint), + NILFS_CHECKPOINTS_ATTR_LIST(next_checkpoint), + NILFS_CHECKPOINTS_ATTR_LIST(README), + NULL, +}; + +NILFS_DEV_INT_GROUP_OPS(checkpoints, dev); +NILFS_DEV_INT_GROUP_TYPE(checkpoints, dev); +NILFS_DEV_INT_GROUP_FNS(checkpoints, dev); + /************************************************************************ * NILFS segments attrs * ************************************************************************/ @@ -753,10 +866,14 @@ int nilfs_sysfs_create_device_group(struct super_block *sb) if (err) goto free_dev_subgroups; - err = nilfs_sysfs_create_segments_group(nilfs); + err = nilfs_sysfs_create_checkpoints_group(nilfs); if (err) goto cleanup_dev_kobject; + err = nilfs_sysfs_create_segments_group(nilfs); + if (err) + goto delete_checkpoints_group; + err = nilfs_sysfs_create_superblock_group(nilfs); if (err) goto delete_segments_group; @@ -773,6 +890,9 @@ delete_superblock_group: delete_segments_group: nilfs_sysfs_delete_segments_group(nilfs); +delete_checkpoints_group: + nilfs_sysfs_delete_checkpoints_group(nilfs); + cleanup_dev_kobject: kobject_del(&nilfs->ns_dev_kobj); @@ -785,6 +905,7 @@ failed_create_device_group: void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) { + nilfs_sysfs_delete_checkpoints_group(nilfs); nilfs_sysfs_delete_segments_group(nilfs); nilfs_sysfs_delete_superblock_group(nilfs); nilfs_sysfs_delete_segctor_group(nilfs); diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h index 228bdd14f945..62f0a0dc78ca 100644 --- a/fs/nilfs2/sysfs.h +++ b/fs/nilfs2/sysfs.h @@ -30,6 +30,8 @@ * @sg_superblock_kobj_unregister: completion state * @sg_segctor_kobj: /sys/fs///segctor * @sg_segctor_kobj_unregister: completion state + * @sg_checkpoints_kobj: /sys/fs///checkpoints + * @sg_checkpoints_kobj_unregister: completion state * @sg_segments_kobj: /sys/fs///segments * @sg_segments_kobj_unregister: completion state */ @@ -42,6 +44,10 @@ struct nilfs_sysfs_dev_subgroups { struct kobject sg_segctor_kobj; struct completion sg_segctor_kobj_unregister; + /* /sys/fs///checkpoints */ + struct kobject sg_checkpoints_kobj; + struct completion sg_checkpoints_kobj_unregister; + /* /sys/fs///segments */ struct kobject sg_segments_kobj; struct completion sg_segments_kobj_unregister; @@ -69,6 +75,7 @@ struct nilfs_##name##_attr { \ NILFS_DEV_ATTR_STRUCT(dev); NILFS_DEV_ATTR_STRUCT(segments); +NILFS_DEV_ATTR_STRUCT(checkpoints); NILFS_DEV_ATTR_STRUCT(superblock); NILFS_DEV_ATTR_STRUCT(segctor); @@ -104,6 +111,11 @@ NILFS_DEV_ATTR_STRUCT(segctor); #define NILFS_SEGMENTS_RW_ATTR(name) \ NILFS_RW_ATTR(segs_info, name) +#define NILFS_CHECKPOINTS_RO_ATTR(name) \ + NILFS_RO_ATTR(checkpoints, name) +#define NILFS_CHECKPOINTS_RW_ATTR(name) \ + NILFS_RW_ATTR(checkpoints, name) + #define NILFS_SUPERBLOCK_RO_ATTR(name) \ NILFS_RO_ATTR(superblock, name) #define NILFS_SUPERBLOCK_RW_ATTR(name) \ @@ -122,6 +134,8 @@ NILFS_DEV_ATTR_STRUCT(segctor); (&nilfs_dev_attr_##name.attr) #define NILFS_SEGMENTS_ATTR_LIST(name) \ (&nilfs_segments_attr_##name.attr) +#define NILFS_CHECKPOINTS_ATTR_LIST(name) \ + (&nilfs_checkpoints_attr_##name.attr) #define NILFS_SUPERBLOCK_ATTR_LIST(name) \ (&nilfs_superblock_attr_##name.attr) #define NILFS_SEGCTOR_ATTR_LIST(name) \ -- cgit v1.2.3 From a2ecb791a9d6e71a2d37d66034475a92ebc7e02c Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Fri, 8 Aug 2014 14:20:50 -0700 Subject: nilfs2: add /sys/fs/nilfs2//mounted_snapshots group This patch adds creation of /sys/fs/nilfs2//mounted_snapshots group. The mounted_snapshots group contains group for every mounted snapshot. Signed-off-by: Vyacheslav Dubeyko Cc: Vyacheslav Dubeyko Cc: Ryusuke Konishi Cc: Michael L. Semon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-fs-nilfs2 | 7 ++++++ fs/nilfs2/sysfs.c | 36 ++++++++++++++++++++++++++++++- fs/nilfs2/sysfs.h | 12 +++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 index 7b820d65d3f0..29dbc8f8bcbd 100644 --- a/Documentation/ABI/testing/sysfs-fs-nilfs2 +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 @@ -241,3 +241,10 @@ Contact: "Vyacheslav Dubeyko" Description: Describe attributes of /sys/fs/nilfs2//checkpoints group. + +What: /sys/fs/nilfs2//mounted_snapshots/README +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Describe content of /sys/fs/nilfs2//mounted_snapshots + group. diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c index 5cc735fcc1d5..fc0c961d486a 100644 --- a/fs/nilfs2/sysfs.c +++ b/fs/nilfs2/sysfs.c @@ -111,6 +111,32 @@ void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \ kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \ } +/************************************************************************ + * NILFS mounted snapshots attrs * + ************************************************************************/ + +static const char mounted_snapshots_readme_str[] = + "The mounted_snapshots group contains group for\n" + "every mounted snapshot.\n"; + +static ssize_t +nilfs_mounted_snapshots_README_show(struct nilfs_mounted_snapshots_attr *attr, + struct the_nilfs *nilfs, char *buf) +{ + return snprintf(buf, PAGE_SIZE, mounted_snapshots_readme_str); +} + +NILFS_MOUNTED_SNAPSHOTS_RO_ATTR(README); + +static struct attribute *nilfs_mounted_snapshots_attrs[] = { + NILFS_MOUNTED_SNAPSHOTS_ATTR_LIST(README), + NULL, +}; + +NILFS_DEV_INT_GROUP_OPS(mounted_snapshots, dev); +NILFS_DEV_INT_GROUP_TYPE(mounted_snapshots, dev); +NILFS_DEV_INT_GROUP_FNS(mounted_snapshots, dev); + /************************************************************************ * NILFS checkpoints attrs * ************************************************************************/ @@ -866,10 +892,14 @@ int nilfs_sysfs_create_device_group(struct super_block *sb) if (err) goto free_dev_subgroups; - err = nilfs_sysfs_create_checkpoints_group(nilfs); + err = nilfs_sysfs_create_mounted_snapshots_group(nilfs); if (err) goto cleanup_dev_kobject; + err = nilfs_sysfs_create_checkpoints_group(nilfs); + if (err) + goto delete_mounted_snapshots_group; + err = nilfs_sysfs_create_segments_group(nilfs); if (err) goto delete_checkpoints_group; @@ -893,6 +923,9 @@ delete_segments_group: delete_checkpoints_group: nilfs_sysfs_delete_checkpoints_group(nilfs); +delete_mounted_snapshots_group: + nilfs_sysfs_delete_mounted_snapshots_group(nilfs); + cleanup_dev_kobject: kobject_del(&nilfs->ns_dev_kobj); @@ -905,6 +938,7 @@ failed_create_device_group: void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) { + nilfs_sysfs_delete_mounted_snapshots_group(nilfs); nilfs_sysfs_delete_checkpoints_group(nilfs); nilfs_sysfs_delete_segments_group(nilfs); nilfs_sysfs_delete_superblock_group(nilfs); diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h index 62f0a0dc78ca..4e84e230e9dd 100644 --- a/fs/nilfs2/sysfs.h +++ b/fs/nilfs2/sysfs.h @@ -30,6 +30,8 @@ * @sg_superblock_kobj_unregister: completion state * @sg_segctor_kobj: /sys/fs///segctor * @sg_segctor_kobj_unregister: completion state + * @sg_mounted_snapshots_kobj: /sys/fs///mounted_snapshots + * @sg_mounted_snapshots_kobj_unregister: completion state * @sg_checkpoints_kobj: /sys/fs///checkpoints * @sg_checkpoints_kobj_unregister: completion state * @sg_segments_kobj: /sys/fs///segments @@ -44,6 +46,10 @@ struct nilfs_sysfs_dev_subgroups { struct kobject sg_segctor_kobj; struct completion sg_segctor_kobj_unregister; + /* /sys/fs///mounted_snapshots */ + struct kobject sg_mounted_snapshots_kobj; + struct completion sg_mounted_snapshots_kobj_unregister; + /* /sys/fs///checkpoints */ struct kobject sg_checkpoints_kobj; struct completion sg_checkpoints_kobj_unregister; @@ -75,6 +81,7 @@ struct nilfs_##name##_attr { \ NILFS_DEV_ATTR_STRUCT(dev); NILFS_DEV_ATTR_STRUCT(segments); +NILFS_DEV_ATTR_STRUCT(mounted_snapshots); NILFS_DEV_ATTR_STRUCT(checkpoints); NILFS_DEV_ATTR_STRUCT(superblock); NILFS_DEV_ATTR_STRUCT(segctor); @@ -111,6 +118,9 @@ NILFS_DEV_ATTR_STRUCT(segctor); #define NILFS_SEGMENTS_RW_ATTR(name) \ NILFS_RW_ATTR(segs_info, name) +#define NILFS_MOUNTED_SNAPSHOTS_RO_ATTR(name) \ + NILFS_RO_ATTR(mounted_snapshots, name) + #define NILFS_CHECKPOINTS_RO_ATTR(name) \ NILFS_RO_ATTR(checkpoints, name) #define NILFS_CHECKPOINTS_RW_ATTR(name) \ @@ -134,6 +144,8 @@ NILFS_DEV_ATTR_STRUCT(segctor); (&nilfs_dev_attr_##name.attr) #define NILFS_SEGMENTS_ATTR_LIST(name) \ (&nilfs_segments_attr_##name.attr) +#define NILFS_MOUNTED_SNAPSHOTS_ATTR_LIST(name) \ + (&nilfs_mounted_snapshots_attr_##name.attr) #define NILFS_CHECKPOINTS_ATTR_LIST(name) \ (&nilfs_checkpoints_attr_##name.attr) #define NILFS_SUPERBLOCK_ATTR_LIST(name) \ -- cgit v1.2.3 From a5a7332a291b55beb0863b119816d12ffc04dfb0 Mon Sep 17 00:00:00 2001 From: Vyacheslav Dubeyko Date: Fri, 8 Aug 2014 14:20:52 -0700 Subject: nilfs2: add /sys/fs/nilfs2//mounted_snapshots/ group This patch adds creation of group for every mounted snapshot in /sys/fs/nilfs2//mounted_snapshots group. The group contains details about mounted snapshot: (1) inodes_count - show number of inodes for snapshot. (2) blocks_count - show number of blocks for snapshot. Signed-off-by: Vyacheslav Dubeyko Cc: Vyacheslav Dubeyko Cc: Ryusuke Konishi Cc: Michael L. Semon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/sysfs-fs-nilfs2 | 19 +++++ fs/nilfs2/sysfs.c | 118 ++++++++++++++++++++++++++++++ fs/nilfs2/sysfs.h | 20 +++++ fs/nilfs2/the_nilfs.h | 6 ++ 4 files changed, 163 insertions(+) (limited to 'Documentation/ABI') diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2 index 29dbc8f8bcbd..304ba84a973a 100644 --- a/Documentation/ABI/testing/sysfs-fs-nilfs2 +++ b/Documentation/ABI/testing/sysfs-fs-nilfs2 @@ -248,3 +248,22 @@ Contact: "Vyacheslav Dubeyko" Description: Describe content of /sys/fs/nilfs2//mounted_snapshots group. + +What: /sys/fs/nilfs2//mounted_snapshots//inodes_count +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show number of inodes for snapshot. + +What: /sys/fs/nilfs2//mounted_snapshots//blocks_count +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Show number of blocks for snapshot. + +What: /sys/fs/nilfs2//mounted_snapshots//README +Date: April 2014 +Contact: "Vyacheslav Dubeyko" +Description: + Describe attributes of /sys/fs/nilfs2//mounted_snapshots/ + group. diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c index fc0c961d486a..0f6148c8121a 100644 --- a/fs/nilfs2/sysfs.c +++ b/fs/nilfs2/sysfs.c @@ -111,6 +111,124 @@ void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \ kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \ } +/************************************************************************ + * NILFS snapshot attrs * + ************************************************************************/ + +static ssize_t +nilfs_snapshot_inodes_count_show(struct nilfs_snapshot_attr *attr, + struct nilfs_root *root, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%llu\n", + (unsigned long long)atomic64_read(&root->inodes_count)); +} + +static ssize_t +nilfs_snapshot_blocks_count_show(struct nilfs_snapshot_attr *attr, + struct nilfs_root *root, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%llu\n", + (unsigned long long)atomic64_read(&root->blocks_count)); +} + +static const char snapshot_readme_str[] = + "The group contains details about mounted snapshot.\n\n" + "(1) inodes_count\n\tshow number of inodes for snapshot.\n\n" + "(2) blocks_count\n\tshow number of blocks for snapshot.\n\n"; + +static ssize_t +nilfs_snapshot_README_show(struct nilfs_snapshot_attr *attr, + struct nilfs_root *root, char *buf) +{ + return snprintf(buf, PAGE_SIZE, snapshot_readme_str); +} + +NILFS_SNAPSHOT_RO_ATTR(inodes_count); +NILFS_SNAPSHOT_RO_ATTR(blocks_count); +NILFS_SNAPSHOT_RO_ATTR(README); + +static struct attribute *nilfs_snapshot_attrs[] = { + NILFS_SNAPSHOT_ATTR_LIST(inodes_count), + NILFS_SNAPSHOT_ATTR_LIST(blocks_count), + NILFS_SNAPSHOT_ATTR_LIST(README), + NULL, +}; + +static ssize_t nilfs_snapshot_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct nilfs_root *root = + container_of(kobj, struct nilfs_root, snapshot_kobj); + struct nilfs_snapshot_attr *a = + container_of(attr, struct nilfs_snapshot_attr, attr); + + return a->show ? a->show(a, root, buf) : 0; +} + +static ssize_t nilfs_snapshot_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t len) +{ + struct nilfs_root *root = + container_of(kobj, struct nilfs_root, snapshot_kobj); + struct nilfs_snapshot_attr *a = + container_of(attr, struct nilfs_snapshot_attr, attr); + + return a->store ? a->store(a, root, buf, len) : 0; +} + +static void nilfs_snapshot_attr_release(struct kobject *kobj) +{ + struct nilfs_root *root = container_of(kobj, struct nilfs_root, + snapshot_kobj); + complete(&root->snapshot_kobj_unregister); +} + +static const struct sysfs_ops nilfs_snapshot_attr_ops = { + .show = nilfs_snapshot_attr_show, + .store = nilfs_snapshot_attr_store, +}; + +static struct kobj_type nilfs_snapshot_ktype = { + .default_attrs = nilfs_snapshot_attrs, + .sysfs_ops = &nilfs_snapshot_attr_ops, + .release = nilfs_snapshot_attr_release, +}; + +int nilfs_sysfs_create_snapshot_group(struct nilfs_root *root) +{ + struct the_nilfs *nilfs; + struct kobject *parent; + int err; + + nilfs = root->nilfs; + parent = &nilfs->ns_dev_subgroups->sg_mounted_snapshots_kobj; + root->snapshot_kobj.kset = nilfs_kset; + init_completion(&root->snapshot_kobj_unregister); + + if (root->cno == NILFS_CPTREE_CURRENT_CNO) { + err = kobject_init_and_add(&root->snapshot_kobj, + &nilfs_snapshot_ktype, + &nilfs->ns_dev_kobj, + "current_checkpoint"); + } else { + err = kobject_init_and_add(&root->snapshot_kobj, + &nilfs_snapshot_ktype, + parent, + "%llu", root->cno); + } + + if (err) + return err; + + return 0; +} + +void nilfs_sysfs_delete_snapshot_group(struct nilfs_root *root) +{ + kobject_del(&root->snapshot_kobj); +} + /************************************************************************ * NILFS mounted snapshots attrs * ************************************************************************/ diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h index 4e84e230e9dd..677e3a1a8370 100644 --- a/fs/nilfs2/sysfs.h +++ b/fs/nilfs2/sysfs.h @@ -86,6 +86,17 @@ NILFS_DEV_ATTR_STRUCT(checkpoints); NILFS_DEV_ATTR_STRUCT(superblock); NILFS_DEV_ATTR_STRUCT(segctor); +#define NILFS_CP_ATTR_STRUCT(name) \ +struct nilfs_##name##_attr { \ + struct attribute attr; \ + ssize_t (*show)(struct nilfs_##name##_attr *, struct nilfs_root *, \ + char *); \ + ssize_t (*store)(struct nilfs_##name##_attr *, struct nilfs_root *, \ + const char *, size_t); \ +}; + +NILFS_CP_ATTR_STRUCT(snapshot); + #define NILFS_ATTR(type, name, mode, show, store) \ static struct nilfs_##type##_attr nilfs_##type##_attr_##name = \ __ATTR(name, mode, show, store) @@ -126,6 +137,13 @@ NILFS_DEV_ATTR_STRUCT(segctor); #define NILFS_CHECKPOINTS_RW_ATTR(name) \ NILFS_RW_ATTR(checkpoints, name) +#define NILFS_SNAPSHOT_INFO_ATTR(name) \ + NILFS_INFO_ATTR(snapshot, name) +#define NILFS_SNAPSHOT_RO_ATTR(name) \ + NILFS_RO_ATTR(snapshot, name) +#define NILFS_SNAPSHOT_RW_ATTR(name) \ + NILFS_RW_ATTR(snapshot, name) + #define NILFS_SUPERBLOCK_RO_ATTR(name) \ NILFS_RO_ATTR(superblock, name) #define NILFS_SUPERBLOCK_RW_ATTR(name) \ @@ -148,6 +166,8 @@ NILFS_DEV_ATTR_STRUCT(segctor); (&nilfs_mounted_snapshots_attr_##name.attr) #define NILFS_CHECKPOINTS_ATTR_LIST(name) \ (&nilfs_checkpoints_attr_##name.attr) +#define NILFS_SNAPSHOT_ATTR_LIST(name) \ + (&nilfs_snapshot_attr_##name.attr) #define NILFS_SUPERBLOCK_ATTR_LIST(name) \ (&nilfs_superblock_attr_##name.attr) #define NILFS_SEGCTOR_ATTR_LIST(name) \ diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 7fe822307f98..d01ead1bea9a 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -243,6 +243,8 @@ THE_NILFS_FNS(SB_DIRTY, sb_dirty) * @ifile: inode file * @inodes_count: number of inodes * @blocks_count: number of blocks + * @snapshot_kobj: /sys/fs///mounted_snapshots/ + * @snapshot_kobj_unregister: completion state for kernel object */ struct nilfs_root { __u64 cno; @@ -254,6 +256,10 @@ struct nilfs_root { atomic64_t inodes_count; atomic64_t blocks_count; + + /* /sys/fs///mounted_snapshots/ */ + struct kobject snapshot_kobj; + struct completion snapshot_kobj_unregister; }; /* Special checkpoint number */ -- cgit v1.2.3