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.
 -----BEGIN PGP SIGNATURE-----
 
 iQI/BAABCAApFiEEgdbnc3r/njty3Iq9D55TZVIEUYMFAllDnicLHGhjaEBsc3Qu
 ZGUACgkQD55TZVIEUYOkPA//TMmDanqxLjjz12m9TiQoCjo/iFCtv9KpuJH/rdCz
 EnWK1GdGtWhR3Z1uk/Ss3zbBA/CwfUR/urVdc1P/aefLoVmsYOWQi1jsPHCHtFG6
 zkDYHr7qYqu91otaO0HgFrcOpuJe+LdbhwZndvUiTYJN8vNMRnQAnKdiEUEKmArq
 dBUj/H0JTbQwSXHZat2ZS9PwHsm7RGO+0qeixxc/HE730LF0TEwnteoy9jlu5d7U
 v1RZs9/zszmvQpWU34vPHCVH/sNfTMdVGPzc9+WNrOoxjM9vmhEOE0jTiclOcsCK
 sMAYHCG7woxkCPVZmxqgLx6P/9zZav6L2NZFPcT3z4jFq5Um+ugJ691f1oHaTq+L
 Bnn1DJdTl50wtMnb7yS1Uux+Y0OswKAXvDdC6NFPGJWwEnG41K3oL78Pq/vN7bKV
 ynKxRZciIsy/9S/Oyzp0oYV+l/cyScPVe/KfUN4zvIALi/mltMkAXYaZMEZDp7Vo
 w2TeJO7Nr3O75ghw/yCFHTWMAVbrTJg/ma1rkdUeekKYXix+4Bpr2XYqA3HHZCQY
 06pvIH+fZs1XshFlCs3RoWXvjdfjDgIO8zjrvSkTs8WUK4AxVNXIDtPDA6fpzcGz
 yZEehpdbPWPDvdd1C7TzEAi6lgOV/W5AsPUfk5KbLOaFzKWRe+FYtzDykGwamYeP
 Ov8=
 =NGL4
 -----END PGP SIGNATURE-----

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:
Linus Torvalds 2017-06-16 18:45:47 +09:00
commit ab2789b72d
3 changed files with 11 additions and 3 deletions

View File

@ -138,6 +138,14 @@ struct config_item *config_item_get(struct config_item *item)
} }
EXPORT_SYMBOL(config_item_get); 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) static void config_item_cleanup(struct config_item *item)
{ {
struct config_item_type *t = item->ci_type; struct config_item_type *t = item->ci_type;

View File

@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item,
ret = -ENOMEM; ret = -ENOMEM;
sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
if (sl) { if (sl) {
sl->sl_target = config_item_get(item);
spin_lock(&configfs_dirent_lock); spin_lock(&configfs_dirent_lock);
if (target_sd->s_type & CONFIGFS_USET_DROPPING) { if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
spin_unlock(&configfs_dirent_lock); spin_unlock(&configfs_dirent_lock);
config_item_put(item);
kfree(sl); kfree(sl);
return -ENOENT; return -ENOENT;
} }
sl->sl_target = config_item_get(item);
list_add(&sl->sl_list, &target_sd->s_links); list_add(&sl->sl_list, &target_sd->s_links);
spin_unlock(&configfs_dirent_lock); spin_unlock(&configfs_dirent_lock);
ret = configfs_create_link(sl, parent_item->ci_dentry, ret = configfs_create_link(sl, parent_item->ci_dentry,

View File

@ -74,7 +74,8 @@ extern void config_item_init_type_name(struct config_item *item,
const char *name, const char *name,
struct config_item_type *type); 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 *); extern void config_item_put(struct config_item *);
struct config_item_type { struct config_item_type {