summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/disk-io.c9
-rw-r--r--fs/btrfs/sysfs.c36
-rw-r--r--fs/btrfs/sysfs.h10
4 files changed, 57 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 498452ebfd37..c5c888fbf033 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3780,6 +3780,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
/* sysfs.c */
int btrfs_init_sysfs(void);
void btrfs_exit_sysfs(void);
+int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info);
+void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info);
/* xattr.c */
ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 435ef132b800..81f3433fe4fd 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -48,6 +48,7 @@
#include "rcu-string.h"
#include "dev-replace.h"
#include "raid56.h"
+#include "sysfs.h"
#ifdef CONFIG_X86
#include <asm/cpufeature.h>
@@ -2743,6 +2744,12 @@ retry_root_backup:
btrfs_close_extra_devices(fs_info, fs_devices, 1);
+ ret = btrfs_sysfs_add_one(fs_info);
+ if (ret) {
+ pr_err("btrfs: failed to init sysfs interface: %d\n", ret);
+ goto fail_block_groups;
+ }
+
ret = btrfs_init_space_info(fs_info);
if (ret) {
printk(KERN_ERR "Failed to initial space info: %d\n", ret);
@@ -3584,6 +3591,8 @@ int close_ctree(struct btrfs_root *root)
percpu_counter_sum(&fs_info->delalloc_bytes));
}
+ btrfs_sysfs_remove_one(fs_info);
+
del_fs_roots(fs_info);
btrfs_free_block_groups(fs_info);
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 9e217b581903..79be4a187af9 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -28,6 +28,25 @@
#include "transaction.h"
#include "sysfs.h"
+static void btrfs_release_super_kobj(struct kobject *kobj);
+static struct kobj_type btrfs_ktype = {
+ .sysfs_ops = &kobj_sysfs_ops,
+ .release = btrfs_release_super_kobj,
+};
+
+static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
+{
+ if (kobj->ktype != &btrfs_ktype)
+ return NULL;
+ return container_of(kobj, struct btrfs_fs_info, super_kobj);
+}
+
+static void btrfs_release_super_kobj(struct kobject *kobj)
+{
+ struct btrfs_fs_info *fs_info = to_fs_info(kobj);
+ complete(&fs_info->kobj_unregister);
+}
+
static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
struct kobj_attribute *a, char *buf)
{
@@ -65,6 +84,23 @@ static const struct attribute_group btrfs_feature_attr_group = {
/* /sys/fs/btrfs/ entry */
static struct kset *btrfs_kset;
+void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
+{
+ kobject_del(&fs_info->super_kobj);
+ kobject_put(&fs_info->super_kobj);
+ wait_for_completion(&fs_info->kobj_unregister);
+}
+
+int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
+{
+ int error;
+
+ init_completion(&fs_info->kobj_unregister);
+ error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL,
+ "%pU", fs_info->fsid);
+ return error;
+}
+
int btrfs_init_sysfs(void)
{
int ret;
diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h
index 863e031ed1c1..d7c61bdf04ba 100644
--- a/fs/btrfs/sysfs.h
+++ b/fs/btrfs/sysfs.h
@@ -15,6 +15,13 @@ enum btrfs_feature_set {
.store = _store, \
}
+#define BTRFS_ATTR_RW(_name, _mode, _show, _store) \
+static struct kobj_attribute btrfs_attr_##_name = \
+ __INIT_KOBJ_ATTR(_name, _mode, _show, _store)
+#define BTRFS_ATTR(_name, _mode, _show) \
+ BTRFS_ATTR_RW(_name, _mode, _show, NULL)
+#define BTRFS_ATTR_PTR(_name) (&btrfs_attr_##_name.attr)
+
struct btrfs_feature_attr {
struct kobj_attribute kobj_attr;
enum btrfs_feature_set feature_set;
@@ -40,4 +47,7 @@ static struct btrfs_feature_attr btrfs_attr_##_name = { \
/* convert from attribute */
#define to_btrfs_feature_attr(a) \
container_of(a, struct btrfs_feature_attr, kobj_attr)
+#define attr_to_btrfs_attr(a) container_of(a, struct kobj_attribute, attr)
+#define attr_to_btrfs_feature_attr(a) \
+ to_btrfs_feature_attr(attr_to_btrfs_attr(a))
#endif /* _BTRFS_SYSFS_H_ */