Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

configfs: new object reprsenting tree fragments

Refcounted, hangs of configfs_dirent, created by operations that add
fragments to configfs tree (mkdir and configfs_register_{subsystem,group}).
Will be used in the next commit to provide exclusion between fragment
removal and ->show/->store calls.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christoph Hellwig <hch@lst.de>

authored by

Al Viro and committed by
Christoph Hellwig
47320fbe f19e4ed1

+97 -27
+13 -2
fs/configfs/configfs_internal.h
··· 20 20 #include <linux/list.h> 21 21 #include <linux/spinlock.h> 22 22 23 + struct configfs_fragment { 24 + atomic_t frag_count; 25 + struct rw_semaphore frag_sem; 26 + bool frag_dead; 27 + }; 28 + 29 + void put_fragment(struct configfs_fragment *); 30 + struct configfs_fragment *get_fragment(struct configfs_fragment *); 31 + 23 32 struct configfs_dirent { 24 33 atomic_t s_count; 25 34 int s_dependent_count; ··· 43 34 #ifdef CONFIG_LOCKDEP 44 35 int s_depth; 45 36 #endif 37 + struct configfs_fragment *s_frag; 46 38 }; 47 39 48 40 #define CONFIGFS_ROOT 0x0001 ··· 71 61 extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); 72 62 extern int configfs_create_bin_file(struct config_item *, 73 63 const struct configfs_bin_attribute *); 74 - extern int configfs_make_dirent(struct configfs_dirent *, 75 - struct dentry *, void *, umode_t, int); 64 + extern int configfs_make_dirent(struct configfs_dirent *, struct dentry *, 65 + void *, umode_t, int, struct configfs_fragment *); 76 66 extern int configfs_dirent_is_ready(struct configfs_dirent *); 77 67 78 68 extern void configfs_hash_and_remove(struct dentry * dir, const char * name); ··· 147 137 { 148 138 if (!(sd->s_type & CONFIGFS_ROOT)) { 149 139 kfree(sd->s_iattr); 140 + put_fragment(sd->s_frag); 150 141 kmem_cache_free(configfs_dir_cachep, sd); 151 142 } 152 143 }
+82 -23
fs/configfs/dir.c
··· 151 151 152 152 #endif /* CONFIG_LOCKDEP */ 153 153 154 + static struct configfs_fragment *new_fragment(void) 155 + { 156 + struct configfs_fragment *p; 157 + 158 + p = kmalloc(sizeof(struct configfs_fragment), GFP_KERNEL); 159 + if (p) { 160 + atomic_set(&p->frag_count, 1); 161 + init_rwsem(&p->frag_sem); 162 + p->frag_dead = false; 163 + } 164 + return p; 165 + } 166 + 167 + void put_fragment(struct configfs_fragment *frag) 168 + { 169 + if (frag && atomic_dec_and_test(&frag->frag_count)) 170 + kfree(frag); 171 + } 172 + 173 + struct configfs_fragment *get_fragment(struct configfs_fragment *frag) 174 + { 175 + if (likely(frag)) 176 + atomic_inc(&frag->frag_count); 177 + return frag; 178 + } 179 + 154 180 /* 155 181 * Allocates a new configfs_dirent and links it to the parent configfs_dirent 156 182 */ 157 183 static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent *parent_sd, 158 - void *element, int type) 184 + void *element, int type, 185 + struct configfs_fragment *frag) 159 186 { 160 187 struct configfs_dirent * sd; 161 188 ··· 202 175 kmem_cache_free(configfs_dir_cachep, sd); 203 176 return ERR_PTR(-ENOENT); 204 177 } 178 + sd->s_frag = get_fragment(frag); 205 179 list_add(&sd->s_sibling, &parent_sd->s_children); 206 180 spin_unlock(&configfs_dirent_lock); 207 181 ··· 237 209 238 210 int configfs_make_dirent(struct configfs_dirent * parent_sd, 239 211 struct dentry * dentry, void * element, 240 - umode_t mode, int type) 212 + umode_t mode, int type, struct configfs_fragment *frag) 241 213 { 242 214 struct configfs_dirent * sd; 243 215 244 - sd = configfs_new_dirent(parent_sd, element, type); 216 + sd = configfs_new_dirent(parent_sd, element, type, frag); 245 217 if (IS_ERR(sd)) 246 218 return PTR_ERR(sd); 247 219 ··· 288 260 * until it is validated by configfs_dir_set_ready() 289 261 */ 290 262 291 - static int configfs_create_dir(struct config_item *item, struct dentry *dentry) 263 + static int configfs_create_dir(struct config_item *item, struct dentry *dentry, 264 + struct configfs_fragment *frag) 292 265 { 293 266 int error; 294 267 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; ··· 302 273 return error; 303 274 304 275 error = configfs_make_dirent(p->d_fsdata, dentry, item, mode, 305 - CONFIGFS_DIR | CONFIGFS_USET_CREATING); 276 + CONFIGFS_DIR | CONFIGFS_USET_CREATING, 277 + frag); 306 278 if (unlikely(error)) 307 279 return error; 308 280 ··· 368 338 { 369 339 int err = 0; 370 340 umode_t mode = S_IFLNK | S_IRWXUGO; 341 + struct configfs_dirent *p = parent->d_fsdata; 371 342 372 - err = configfs_make_dirent(parent->d_fsdata, dentry, sl, mode, 373 - CONFIGFS_ITEM_LINK); 343 + err = configfs_make_dirent(p, dentry, sl, mode, 344 + CONFIGFS_ITEM_LINK, p->s_frag); 374 345 if (!err) { 375 346 err = configfs_create(dentry, mode, init_symlink); 376 347 if (err) { ··· 630 599 631 600 static int configfs_attach_group(struct config_item *parent_item, 632 601 struct config_item *item, 633 - struct dentry *dentry); 602 + struct dentry *dentry, 603 + struct configfs_fragment *frag); 634 604 static void configfs_detach_group(struct config_item *item); 635 605 636 606 static void detach_groups(struct config_group *group) ··· 679 647 * try using vfs_mkdir. Just a thought. 680 648 */ 681 649 static int create_default_group(struct config_group *parent_group, 682 - struct config_group *group) 650 + struct config_group *group, 651 + struct configfs_fragment *frag) 683 652 { 684 653 int ret; 685 654 struct configfs_dirent *sd; ··· 696 663 d_add(child, NULL); 697 664 698 665 ret = configfs_attach_group(&parent_group->cg_item, 699 - &group->cg_item, child); 666 + &group->cg_item, child, frag); 700 667 if (!ret) { 701 668 sd = child->d_fsdata; 702 669 sd->s_type |= CONFIGFS_USET_DEFAULT; ··· 710 677 return ret; 711 678 } 712 679 713 - static int populate_groups(struct config_group *group) 680 + static int populate_groups(struct config_group *group, 681 + struct configfs_fragment *frag) 714 682 { 715 683 struct config_group *new_group; 716 684 int ret = 0; 717 685 718 686 list_for_each_entry(new_group, &group->default_groups, group_entry) { 719 - ret = create_default_group(group, new_group); 687 + ret = create_default_group(group, new_group, frag); 720 688 if (ret) { 721 689 detach_groups(group); 722 690 break; ··· 831 797 */ 832 798 static int configfs_attach_item(struct config_item *parent_item, 833 799 struct config_item *item, 834 - struct dentry *dentry) 800 + struct dentry *dentry, 801 + struct configfs_fragment *frag) 835 802 { 836 803 int ret; 837 804 838 - ret = configfs_create_dir(item, dentry); 805 + ret = configfs_create_dir(item, dentry, frag); 839 806 if (!ret) { 840 807 ret = populate_attrs(item); 841 808 if (ret) { ··· 866 831 867 832 static int configfs_attach_group(struct config_item *parent_item, 868 833 struct config_item *item, 869 - struct dentry *dentry) 834 + struct dentry *dentry, 835 + struct configfs_fragment *frag) 870 836 { 871 837 int ret; 872 838 struct configfs_dirent *sd; 873 839 874 - ret = configfs_attach_item(parent_item, item, dentry); 840 + ret = configfs_attach_item(parent_item, item, dentry, frag); 875 841 if (!ret) { 876 842 sd = dentry->d_fsdata; 877 843 sd->s_type |= CONFIGFS_USET_DIR; ··· 888 852 */ 889 853 inode_lock_nested(d_inode(dentry), I_MUTEX_CHILD); 890 854 configfs_adjust_dir_dirent_depth_before_populate(sd); 891 - ret = populate_groups(to_config_group(item)); 855 + ret = populate_groups(to_config_group(item), frag); 892 856 if (ret) { 893 857 configfs_detach_item(item); 894 858 d_inode(dentry)->i_flags |= S_DEAD; ··· 1283 1247 struct configfs_dirent *sd; 1284 1248 const struct config_item_type *type; 1285 1249 struct module *subsys_owner = NULL, *new_item_owner = NULL; 1250 + struct configfs_fragment *frag; 1286 1251 char *name; 1287 1252 1288 1253 sd = dentry->d_parent->d_fsdata; ··· 1299 1262 1300 1263 if (!(sd->s_type & CONFIGFS_USET_DIR)) { 1301 1264 ret = -EPERM; 1265 + goto out; 1266 + } 1267 + 1268 + frag = new_fragment(); 1269 + if (!frag) { 1270 + ret = -ENOMEM; 1302 1271 goto out; 1303 1272 } 1304 1273 ··· 1410 1367 spin_unlock(&configfs_dirent_lock); 1411 1368 1412 1369 if (group) 1413 - ret = configfs_attach_group(parent_item, item, dentry); 1370 + ret = configfs_attach_group(parent_item, item, dentry, frag); 1414 1371 else 1415 - ret = configfs_attach_item(parent_item, item, dentry); 1372 + ret = configfs_attach_item(parent_item, item, dentry, frag); 1416 1373 1417 1374 spin_lock(&configfs_dirent_lock); 1418 1375 sd->s_type &= ~CONFIGFS_USET_IN_MKDIR; ··· 1449 1406 * reference. 1450 1407 */ 1451 1408 config_item_put(parent_item); 1409 + put_fragment(frag); 1452 1410 1453 1411 out: 1454 1412 return ret; ··· 1618 1574 */ 1619 1575 err = -ENOENT; 1620 1576 if (configfs_dirent_is_ready(parent_sd)) { 1621 - file->private_data = configfs_new_dirent(parent_sd, NULL, 0); 1577 + file->private_data = configfs_new_dirent(parent_sd, NULL, 0, NULL); 1622 1578 if (IS_ERR(file->private_data)) 1623 1579 err = PTR_ERR(file->private_data); 1624 1580 else ··· 1776 1732 { 1777 1733 struct configfs_subsystem *subsys = parent_group->cg_subsys; 1778 1734 struct dentry *parent; 1735 + struct configfs_fragment *frag; 1779 1736 int ret; 1737 + 1738 + frag = new_fragment(); 1739 + if (!frag) 1740 + return -ENOMEM; 1780 1741 1781 1742 mutex_lock(&subsys->su_mutex); 1782 1743 link_group(parent_group, group); ··· 1790 1741 parent = parent_group->cg_item.ci_dentry; 1791 1742 1792 1743 inode_lock_nested(d_inode(parent), I_MUTEX_PARENT); 1793 - ret = create_default_group(parent_group, group); 1744 + ret = create_default_group(parent_group, group, frag); 1794 1745 if (ret) 1795 1746 goto err_out; 1796 1747 ··· 1798 1749 configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata); 1799 1750 spin_unlock(&configfs_dirent_lock); 1800 1751 inode_unlock(d_inode(parent)); 1752 + put_fragment(frag); 1801 1753 return 0; 1802 1754 err_out: 1803 1755 inode_unlock(d_inode(parent)); 1804 1756 mutex_lock(&subsys->su_mutex); 1805 1757 unlink_group(group); 1806 1758 mutex_unlock(&subsys->su_mutex); 1759 + put_fragment(frag); 1807 1760 return ret; 1808 1761 } 1809 1762 EXPORT_SYMBOL(configfs_register_group); ··· 1893 1842 struct dentry *dentry; 1894 1843 struct dentry *root; 1895 1844 struct configfs_dirent *sd; 1845 + struct configfs_fragment *frag; 1846 + 1847 + frag = new_fragment(); 1848 + if (!frag) 1849 + return -ENOMEM; 1896 1850 1897 1851 root = configfs_pin_fs(); 1898 - if (IS_ERR(root)) 1852 + if (IS_ERR(root)) { 1853 + put_fragment(frag); 1899 1854 return PTR_ERR(root); 1855 + } 1900 1856 1901 1857 if (!group->cg_item.ci_name) 1902 1858 group->cg_item.ci_name = group->cg_item.ci_namebuf; ··· 1919 1861 d_add(dentry, NULL); 1920 1862 1921 1863 err = configfs_attach_group(sd->s_element, &group->cg_item, 1922 - dentry); 1864 + dentry, frag); 1923 1865 if (err) { 1924 1866 BUG_ON(d_inode(dentry)); 1925 1867 d_drop(dentry); ··· 1937 1879 unlink_group(group); 1938 1880 configfs_release_fs(); 1939 1881 } 1882 + put_fragment(frag); 1940 1883 1941 1884 return err; 1942 1885 }
+2 -2
fs/configfs/file.c
··· 488 488 489 489 inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL); 490 490 error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, 491 - CONFIGFS_ITEM_ATTR); 491 + CONFIGFS_ITEM_ATTR, parent_sd->s_frag); 492 492 inode_unlock(d_inode(dir)); 493 493 494 494 return error; ··· 510 510 511 511 inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL); 512 512 error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode, 513 - CONFIGFS_ITEM_BIN_ATTR); 513 + CONFIGFS_ITEM_BIN_ATTR, parent_sd->s_frag); 514 514 inode_unlock(dir->d_inode); 515 515 516 516 return error;