diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-16 05:45:47 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-06-16 05:45:47 -0400 |
| commit | ab2789b72df3cf7a01e30636ea86cbbf44ba2e99 (patch) | |
| tree | 98f5359551b9497c51e8429b1dc489a440e30c3f /fs | |
| parent | 20223f0f39ea9d31ece08f04ac79f8c4e8d98246 (diff) | |
| parent | 19e72d3abb63cb16d021a4066ce1a18880509e99 (diff) | |
Merge tag 'configfs-for-4.12' of git://git.infradead.org/users/hch/configfs
Pull configfs updates from Christoph Hellwig:
"A fix from Nic for a race seen in production (including a stable tag).
And while I'm sending you this I'm also sneaking in a trivial new
helper from Bart so that we don't need inter-tree dependencies for the
next merge window"
* tag 'configfs-for-4.12' of git://git.infradead.org/users/hch/configfs:
configfs: Introduce config_item_get_unless_zero()
configfs: Fix race between create_link and configfs_rmdir
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/configfs/item.c | 8 | ||||
| -rw-r--r-- | fs/configfs/symlink.c | 3 |
2 files changed, 9 insertions, 2 deletions
diff --git a/fs/configfs/item.c b/fs/configfs/item.c index 8b2a994042dd..a66f6624d899 100644 --- a/fs/configfs/item.c +++ b/fs/configfs/item.c | |||
| @@ -138,6 +138,14 @@ struct config_item *config_item_get(struct config_item *item) | |||
| 138 | } | 138 | } |
| 139 | EXPORT_SYMBOL(config_item_get); | 139 | EXPORT_SYMBOL(config_item_get); |
| 140 | 140 | ||
| 141 | struct config_item *config_item_get_unless_zero(struct config_item *item) | ||
| 142 | { | ||
| 143 | if (item && kref_get_unless_zero(&item->ci_kref)) | ||
| 144 | return item; | ||
| 145 | return NULL; | ||
| 146 | } | ||
| 147 | EXPORT_SYMBOL(config_item_get_unless_zero); | ||
| 148 | |||
| 141 | static void config_item_cleanup(struct config_item *item) | 149 | static void config_item_cleanup(struct config_item *item) |
| 142 | { | 150 | { |
| 143 | struct config_item_type *t = item->ci_type; | 151 | struct config_item_type *t = item->ci_type; |
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index a6ab012a2c6a..c8aabba502f6 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c | |||
| @@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item, | |||
| 83 | ret = -ENOMEM; | 83 | ret = -ENOMEM; |
| 84 | sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); | 84 | sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); |
| 85 | if (sl) { | 85 | if (sl) { |
| 86 | sl->sl_target = config_item_get(item); | ||
| 87 | spin_lock(&configfs_dirent_lock); | 86 | spin_lock(&configfs_dirent_lock); |
| 88 | if (target_sd->s_type & CONFIGFS_USET_DROPPING) { | 87 | if (target_sd->s_type & CONFIGFS_USET_DROPPING) { |
| 89 | spin_unlock(&configfs_dirent_lock); | 88 | spin_unlock(&configfs_dirent_lock); |
| 90 | config_item_put(item); | ||
| 91 | kfree(sl); | 89 | kfree(sl); |
| 92 | return -ENOENT; | 90 | return -ENOENT; |
| 93 | } | 91 | } |
| 92 | sl->sl_target = config_item_get(item); | ||
| 94 | list_add(&sl->sl_list, &target_sd->s_links); | 93 | list_add(&sl->sl_list, &target_sd->s_links); |
| 95 | spin_unlock(&configfs_dirent_lock); | 94 | spin_unlock(&configfs_dirent_lock); |
| 96 | ret = configfs_create_link(sl, parent_item->ci_dentry, | 95 | ret = configfs_create_link(sl, parent_item->ci_dentry, |
