From: Jeff Mahoney <jeffm@suse.com>
To: linux-btrfs <linux-btrfs@vger.kernel.org>,
Josef Bacik <jbacik@fusionio.com>
Cc: Filipe David Borba Manana <fdmanana@gmail.com>
Subject: [PATCH] btrfs: fix leaks during sysfs teardown
Date: Wed, 20 Nov 2013 16:59:46 -0500 [thread overview]
Message-ID: <528D30D2.6070107@suse.com> (raw)
Filipe noticed that we were leaking the features attribute group
after umount. His fix of just calling sysfs_remove_group() wasn't enough
since that removes just the supported features and not the unknown
features (but a regular test wouldn't show that).
This patch changes the unknown feature handling to add them individually
so we can skip the kmalloc and uses the same iteration to tear them down
later.
We also fix the error handling during mount so that we catch the
failing creation of the per-super kobject, and handle proper teardown
of a half-setup sysfs context.
Reported-by: Filipe David Borba Manana <fdmanana@gmail.com>
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
fs/btrfs/sysfs.c | 132 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 72 insertions(+), 60 deletions(-)
--- a/fs/btrfs/sysfs.c 2013-11-20 14:58:40.907456459 -0500
+++ b/fs/btrfs/sysfs.c 2013-11-20 16:59:02.359951682 -0500
@@ -417,28 +417,83 @@ static inline struct btrfs_fs_info *to_f
return container_of(kobj, struct btrfs_fs_info, super_kobj);
}
-void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
+#define NUM_FEATURE_BITS 64
+static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
+static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
+
+static u64 supported_feature_masks[3] = {
+ [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP,
+ [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP,
+ [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP,
+};
+
+static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add)
+{
+ int set;
+
+ for (set = 0; set < FEAT_MAX; set++) {
+ int i;
+ struct attribute *attrs[2];
+ struct attribute_group agroup = {
+ .name = "features",
+ .attrs = attrs,
+ };
+ u64 features = get_features(fs_info, set);
+ features &= ~supported_feature_masks[set];
+
+ if (!features)
+ continue;
+
+ attrs[1] = NULL;
+ for (i = 0; i < NUM_FEATURE_BITS; i++) {
+ struct btrfs_feature_attr *fa;
+
+ if (!(features & (1ULL << i)))
+ continue;
+
+ fa = &btrfs_feature_attrs[set][i];
+ attrs[0] = &fa->kobj_attr.attr;
+ if (add) {
+ int ret;
+ ret = sysfs_merge_group(&fs_info->super_kobj,
+ &agroup);
+ if (ret)
+ return ret;
+ } else
+ sysfs_unmerge_group(&fs_info->super_kobj,
+ &agroup);
+ }
+
+ }
+ return 0;
+}
+
+static void __btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
{
- sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
- kobject_del(fs_info->device_dir_kobj);
- kobject_put(fs_info->device_dir_kobj);
- kobject_del(fs_info->space_info_kobj);
- kobject_put(fs_info->space_info_kobj);
kobject_del(&fs_info->super_kobj);
kobject_put(&fs_info->super_kobj);
wait_for_completion(&fs_info->kobj_unregister);
}
+void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
+{
+ if (fs_info->space_info_kobj) {
+ sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
+ kobject_del(fs_info->space_info_kobj);
+ kobject_put(fs_info->space_info_kobj);
+ }
+ kobject_del(fs_info->device_dir_kobj);
+ kobject_put(fs_info->device_dir_kobj);
+ addrm_unknown_feature_attrs(fs_info, false);
+ __btrfs_sysfs_remove_one(fs_info);
+}
+
const char * const btrfs_feature_set_names[3] = {
[FEAT_COMPAT] = "compat",
[FEAT_COMPAT_RO] = "compat_ro",
[FEAT_INCOMPAT] = "incompat",
};
-#define NUM_FEATURE_BITS 64
-static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
-static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
-
char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags)
{
size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */
@@ -508,53 +563,6 @@ static void init_feature_attrs(void)
}
}
-static u64 supported_feature_masks[3] = {
- [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP,
- [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP,
- [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP,
-};
-
-static int add_unknown_feature_attrs(struct btrfs_fs_info *fs_info)
-{
- int set;
-
- for (set = 0; set < FEAT_MAX; set++) {
- int i, count, ret, index = 0;
- struct attribute **attrs;
- struct attribute_group agroup = {
- .name = "features",
- };
- u64 features = get_features(fs_info, set);
- features &= ~supported_feature_masks[set];
-
- count = hweight64(features);
-
- if (!count)
- continue;
-
- attrs = kcalloc(count + 1, sizeof(void *), GFP_KERNEL);
-
- for (i = 0; i < NUM_FEATURE_BITS; i++) {
- struct btrfs_feature_attr *fa;
-
- if (!(features & (1ULL << i)))
- continue;
-
- fa = &btrfs_feature_attrs[set][i];
- attrs[index++] = &fa->kobj_attr.attr;
- }
-
- attrs[index] = NULL;
- agroup.attrs = attrs;
-
- ret = sysfs_merge_group(&fs_info->super_kobj, &agroup);
- kfree(attrs);
- if (ret)
- return ret;
- }
- return 0;
-}
-
static int add_device_membership(struct btrfs_fs_info *fs_info)
{
int error = 0;
@@ -590,13 +598,17 @@ int btrfs_sysfs_add_one(struct btrfs_fs_
fs_info->super_kobj.kset = btrfs_kset;
error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL,
"%pU", fs_info->fsid);
+ if (error)
+ return error;
error = sysfs_create_group(&fs_info->super_kobj,
&btrfs_feature_attr_group);
- if (error)
- goto failure;
+ if (error) {
+ __btrfs_sysfs_remove_one(fs_info);
+ return error;
+ }
- error = add_unknown_feature_attrs(fs_info);
+ error = addrm_unknown_feature_attrs(fs_info, true);
if (error)
goto failure;
--
Jeff Mahoney
SUSE Labs
next reply other threads:[~2013-11-20 22:00 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-20 21:59 Jeff Mahoney [this message]
2013-11-21 13:07 ` [PATCH] btrfs: fix leaks during sysfs teardown Filipe David Manana
2013-11-21 15:05 ` Jeff Mahoney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=528D30D2.6070107@suse.com \
--to=jeffm@suse.com \
--cc=fdmanana@gmail.com \
--cc=jbacik@fusionio.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).