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
This commit is contained in:
@@ -138,6 +138,14 @@ struct config_item *config_item_get(struct config_item *item)
|
||||
}
|
||||
EXPORT_SYMBOL(config_item_get);
|
||||
|
||||
struct config_item *config_item_get_unless_zero(struct config_item *item)
|
||||
{
|
||||
if (item && kref_get_unless_zero(&item->ci_kref))
|
||||
return item;
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(config_item_get_unless_zero);
|
||||
|
||||
static void config_item_cleanup(struct config_item *item)
|
||||
{
|
||||
struct config_item_type *t = item->ci_type;
|
||||
|
||||
@@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item,
|
||||
ret = -ENOMEM;
|
||||
sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
|
||||
if (sl) {
|
||||
sl->sl_target = config_item_get(item);
|
||||
spin_lock(&configfs_dirent_lock);
|
||||
if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
|
||||
spin_unlock(&configfs_dirent_lock);
|
||||
config_item_put(item);
|
||||
kfree(sl);
|
||||
return -ENOENT;
|
||||
}
|
||||
sl->sl_target = config_item_get(item);
|
||||
list_add(&sl->sl_list, &target_sd->s_links);
|
||||
spin_unlock(&configfs_dirent_lock);
|
||||
ret = configfs_create_link(sl, parent_item->ci_dentry,
|
||||
|
||||
@@ -74,7 +74,8 @@ extern void config_item_init_type_name(struct config_item *item,
|
||||
const char *name,
|
||||
struct config_item_type *type);
|
||||
|
||||
extern struct config_item * config_item_get(struct config_item *);
|
||||
extern struct config_item *config_item_get(struct config_item *);
|
||||
extern struct config_item *config_item_get_unless_zero(struct config_item *);
|
||||
extern void config_item_put(struct config_item *);
|
||||
|
||||
struct config_item_type {
|
||||
|
||||
Reference in New Issue
Block a user