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
Unified · Split
| @@ -138,6 +138,14 @@ struct config_item *config_item_get(struct config_item *item) · 137 unmodified lines | |||
| 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; |
| @@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item, · 82 unmodified lines | |||
| 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, |
| @@ -74,7 +74,8 @@ extern void config_item_init_type_name(struct config_item *item, · 73 unmodified lines | |||
| 74 | const char *name, | 74 | const char *name, |
| 75 | struct config_item_type *type); | 75 | struct config_item_type *type); |
| 76 | 76 | ||
| 77 | extern struct config_item * config_item_get(struct config_item *); | 77 | extern struct config_item *config_item_get(struct config_item *); |
| 78 | extern struct config_item *config_item_get_unless_zero(struct config_item *); | ||
| 78 | extern void config_item_put(struct config_item *); | 79 | extern void config_item_put(struct config_item *); |
| 79 | 80 | ||
| 80 | struct config_item_type { | 81 | struct config_item_type { |