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 | 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 | 149 | static void config_item_cleanup(struct config_item *item) |
| 142 | 150 | { |
| 143 | 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 | 83 | ret = -ENOMEM; |
| 84 | 84 | sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); |
| 85 | 85 | if (sl) { |
| 86 | − sl->sl_target = config_item_get(item); | |
| 87 | 86 | spin_lock(&configfs_dirent_lock); |
| 88 | 87 | if (target_sd->s_type & CONFIGFS_USET_DROPPING) { |
| 89 | 88 | spin_unlock(&configfs_dirent_lock); |
| 90 | − config_item_put(item); | |
| 91 | 89 | kfree(sl); |
| 92 | 90 | return -ENOENT; |
| 93 | 91 | } |
| 92 | + sl->sl_target = config_item_get(item); | |
| 94 | 93 | list_add(&sl->sl_list, &target_sd->s_links); |
| 95 | 94 | spin_unlock(&configfs_dirent_lock); |
| 96 | 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 | 74 | const char *name, |
| 75 | 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 | 79 | extern void config_item_put(struct config_item *); |
| 79 | 80 | |
| 80 | 81 | struct config_item_type { |