diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/configfs/dir.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/configfs/dir.c')
-rw-r--r-- | fs/configfs/dir.c | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 0b502f80c691..9a37a9b6de3a 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -53,11 +53,14 @@ DEFINE_SPINLOCK(configfs_dirent_lock); | |||
53 | static void configfs_d_iput(struct dentry * dentry, | 53 | static void configfs_d_iput(struct dentry * dentry, |
54 | struct inode * inode) | 54 | struct inode * inode) |
55 | { | 55 | { |
56 | struct configfs_dirent * sd = dentry->d_fsdata; | 56 | struct configfs_dirent *sd = dentry->d_fsdata; |
57 | 57 | ||
58 | if (sd) { | 58 | if (sd) { |
59 | BUG_ON(sd->s_dentry != dentry); | 59 | BUG_ON(sd->s_dentry != dentry); |
60 | /* Coordinate with configfs_readdir */ | ||
61 | spin_lock(&configfs_dirent_lock); | ||
60 | sd->s_dentry = NULL; | 62 | sd->s_dentry = NULL; |
63 | spin_unlock(&configfs_dirent_lock); | ||
61 | configfs_put(sd); | 64 | configfs_put(sd); |
62 | } | 65 | } |
63 | iput(inode); | 66 | iput(inode); |
@@ -67,12 +70,12 @@ static void configfs_d_iput(struct dentry * dentry, | |||
67 | * We _must_ delete our dentries on last dput, as the chain-to-parent | 70 | * We _must_ delete our dentries on last dput, as the chain-to-parent |
68 | * behavior is required to clear the parents of default_groups. | 71 | * behavior is required to clear the parents of default_groups. |
69 | */ | 72 | */ |
70 | static int configfs_d_delete(struct dentry *dentry) | 73 | static int configfs_d_delete(const struct dentry *dentry) |
71 | { | 74 | { |
72 | return 1; | 75 | return 1; |
73 | } | 76 | } |
74 | 77 | ||
75 | static const struct dentry_operations configfs_dentry_ops = { | 78 | const struct dentry_operations configfs_dentry_ops = { |
76 | .d_iput = configfs_d_iput, | 79 | .d_iput = configfs_d_iput, |
77 | /* simple_delete_dentry() isn't exported */ | 80 | /* simple_delete_dentry() isn't exported */ |
78 | .d_delete = configfs_d_delete, | 81 | .d_delete = configfs_d_delete, |
@@ -232,10 +235,8 @@ int configfs_make_dirent(struct configfs_dirent * parent_sd, | |||
232 | 235 | ||
233 | sd->s_mode = mode; | 236 | sd->s_mode = mode; |
234 | sd->s_dentry = dentry; | 237 | sd->s_dentry = dentry; |
235 | if (dentry) { | 238 | if (dentry) |
236 | dentry->d_fsdata = configfs_get(sd); | 239 | dentry->d_fsdata = configfs_get(sd); |
237 | dentry->d_op = &configfs_dentry_ops; | ||
238 | } | ||
239 | 240 | ||
240 | return 0; | 241 | return 0; |
241 | } | 242 | } |
@@ -278,7 +279,6 @@ static int create_dir(struct config_item * k, struct dentry * p, | |||
278 | error = configfs_create(d, mode, init_dir); | 279 | error = configfs_create(d, mode, init_dir); |
279 | if (!error) { | 280 | if (!error) { |
280 | inc_nlink(p->d_inode); | 281 | inc_nlink(p->d_inode); |
281 | (d)->d_op = &configfs_dentry_ops; | ||
282 | } else { | 282 | } else { |
283 | struct configfs_dirent *sd = d->d_fsdata; | 283 | struct configfs_dirent *sd = d->d_fsdata; |
284 | if (sd) { | 284 | if (sd) { |
@@ -371,9 +371,7 @@ int configfs_create_link(struct configfs_symlink *sl, | |||
371 | CONFIGFS_ITEM_LINK); | 371 | CONFIGFS_ITEM_LINK); |
372 | if (!err) { | 372 | if (!err) { |
373 | err = configfs_create(dentry, mode, init_symlink); | 373 | err = configfs_create(dentry, mode, init_symlink); |
374 | if (!err) | 374 | if (err) { |
375 | dentry->d_op = &configfs_dentry_ops; | ||
376 | else { | ||
377 | struct configfs_dirent *sd = dentry->d_fsdata; | 375 | struct configfs_dirent *sd = dentry->d_fsdata; |
378 | if (sd) { | 376 | if (sd) { |
379 | spin_lock(&configfs_dirent_lock); | 377 | spin_lock(&configfs_dirent_lock); |
@@ -399,8 +397,7 @@ static void remove_dir(struct dentry * d) | |||
399 | if (d->d_inode) | 397 | if (d->d_inode) |
400 | simple_rmdir(parent->d_inode,d); | 398 | simple_rmdir(parent->d_inode,d); |
401 | 399 | ||
402 | pr_debug(" o %s removing done (%d)\n",d->d_name.name, | 400 | pr_debug(" o %s removing done (%d)\n",d->d_name.name, d->d_count); |
403 | atomic_read(&d->d_count)); | ||
404 | 401 | ||
405 | dput(parent); | 402 | dput(parent); |
406 | } | 403 | } |
@@ -448,7 +445,6 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den | |||
448 | return error; | 445 | return error; |
449 | } | 446 | } |
450 | 447 | ||
451 | dentry->d_op = &configfs_dentry_ops; | ||
452 | d_rehash(dentry); | 448 | d_rehash(dentry); |
453 | 449 | ||
454 | return 0; | 450 | return 0; |
@@ -493,7 +489,10 @@ static struct dentry * configfs_lookup(struct inode *dir, | |||
493 | * If it doesn't exist and it isn't a NOT_PINNED item, | 489 | * If it doesn't exist and it isn't a NOT_PINNED item, |
494 | * it must be negative. | 490 | * it must be negative. |
495 | */ | 491 | */ |
496 | return simple_lookup(dir, dentry, nd); | 492 | if (dentry->d_name.len > NAME_MAX) |
493 | return ERR_PTR(-ENAMETOOLONG); | ||
494 | d_add(dentry, NULL); | ||
495 | return NULL; | ||
497 | } | 496 | } |
498 | 497 | ||
499 | out: | 498 | out: |
@@ -693,7 +692,8 @@ static int create_default_group(struct config_group *parent_group, | |||
693 | sd = child->d_fsdata; | 692 | sd = child->d_fsdata; |
694 | sd->s_type |= CONFIGFS_USET_DEFAULT; | 693 | sd->s_type |= CONFIGFS_USET_DEFAULT; |
695 | } else { | 694 | } else { |
696 | d_delete(child); | 695 | BUG_ON(child->d_inode); |
696 | d_drop(child); | ||
697 | dput(child); | 697 | dput(child); |
698 | } | 698 | } |
699 | } | 699 | } |
@@ -994,7 +994,7 @@ static int configfs_dump(struct configfs_dirent *sd, int level) | |||
994 | * This describes these functions and their helpers. | 994 | * This describes these functions and their helpers. |
995 | * | 995 | * |
996 | * Allow another kernel system to depend on a config_item. If this | 996 | * Allow another kernel system to depend on a config_item. If this |
997 | * happens, the item cannot go away until the dependant can live without | 997 | * happens, the item cannot go away until the dependent can live without |
998 | * it. The idea is to give client modules as simple an interface as | 998 | * it. The idea is to give client modules as simple an interface as |
999 | * possible. When a system asks them to depend on an item, they just | 999 | * possible. When a system asks them to depend on an item, they just |
1000 | * call configfs_depend_item(). If the item is live and the client | 1000 | * call configfs_depend_item(). If the item is live and the client |
@@ -1549,7 +1549,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1549 | struct configfs_dirent * parent_sd = dentry->d_fsdata; | 1549 | struct configfs_dirent * parent_sd = dentry->d_fsdata; |
1550 | struct configfs_dirent *cursor = filp->private_data; | 1550 | struct configfs_dirent *cursor = filp->private_data; |
1551 | struct list_head *p, *q = &cursor->s_sibling; | 1551 | struct list_head *p, *q = &cursor->s_sibling; |
1552 | ino_t ino; | 1552 | ino_t ino = 0; |
1553 | int i = filp->f_pos; | 1553 | int i = filp->f_pos; |
1554 | 1554 | ||
1555 | switch (i) { | 1555 | switch (i) { |
@@ -1577,6 +1577,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1577 | struct configfs_dirent *next; | 1577 | struct configfs_dirent *next; |
1578 | const char * name; | 1578 | const char * name; |
1579 | int len; | 1579 | int len; |
1580 | struct inode *inode = NULL; | ||
1580 | 1581 | ||
1581 | next = list_entry(p, struct configfs_dirent, | 1582 | next = list_entry(p, struct configfs_dirent, |
1582 | s_sibling); | 1583 | s_sibling); |
@@ -1585,9 +1586,28 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1585 | 1586 | ||
1586 | name = configfs_get_name(next); | 1587 | name = configfs_get_name(next); |
1587 | len = strlen(name); | 1588 | len = strlen(name); |
1588 | if (next->s_dentry) | 1589 | |
1589 | ino = next->s_dentry->d_inode->i_ino; | 1590 | /* |
1590 | else | 1591 | * We'll have a dentry and an inode for |
1592 | * PINNED items and for open attribute | ||
1593 | * files. We lock here to prevent a race | ||
1594 | * with configfs_d_iput() clearing | ||
1595 | * s_dentry before calling iput(). | ||
1596 | * | ||
1597 | * Why do we go to the trouble? If | ||
1598 | * someone has an attribute file open, | ||
1599 | * the inode number should match until | ||
1600 | * they close it. Beyond that, we don't | ||
1601 | * care. | ||
1602 | */ | ||
1603 | spin_lock(&configfs_dirent_lock); | ||
1604 | dentry = next->s_dentry; | ||
1605 | if (dentry) | ||
1606 | inode = dentry->d_inode; | ||
1607 | if (inode) | ||
1608 | ino = inode->i_ino; | ||
1609 | spin_unlock(&configfs_dirent_lock); | ||
1610 | if (!inode) | ||
1591 | ino = iunique(configfs_sb, 2); | 1611 | ino = iunique(configfs_sb, 2); |
1592 | 1612 | ||
1593 | if (filldir(dirent, name, len, filp->f_pos, ino, | 1613 | if (filldir(dirent, name, len, filp->f_pos, ino, |
@@ -1687,7 +1707,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) | |||
1687 | err = configfs_attach_group(sd->s_element, &group->cg_item, | 1707 | err = configfs_attach_group(sd->s_element, &group->cg_item, |
1688 | dentry); | 1708 | dentry); |
1689 | if (err) { | 1709 | if (err) { |
1690 | d_delete(dentry); | 1710 | BUG_ON(dentry->d_inode); |
1711 | d_drop(dentry); | ||
1691 | dput(dentry); | 1712 | dput(dentry); |
1692 | } else { | 1713 | } else { |
1693 | spin_lock(&configfs_dirent_lock); | 1714 | spin_lock(&configfs_dirent_lock); |