diff options
Diffstat (limited to 'fs/configfs')
-rw-r--r-- | fs/configfs/dir.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 9908c20bb1a5..9d17d350abc5 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); |
@@ -689,7 +692,8 @@ static int create_default_group(struct config_group *parent_group, | |||
689 | sd = child->d_fsdata; | 692 | sd = child->d_fsdata; |
690 | sd->s_type |= CONFIGFS_USET_DEFAULT; | 693 | sd->s_type |= CONFIGFS_USET_DEFAULT; |
691 | } else { | 694 | } else { |
692 | d_delete(child); | 695 | BUG_ON(child->d_inode); |
696 | d_drop(child); | ||
693 | dput(child); | 697 | dput(child); |
694 | } | 698 | } |
695 | } | 699 | } |
@@ -1547,7 +1551,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1547 | struct configfs_dirent * parent_sd = dentry->d_fsdata; | 1551 | struct configfs_dirent * parent_sd = dentry->d_fsdata; |
1548 | struct configfs_dirent *cursor = filp->private_data; | 1552 | struct configfs_dirent *cursor = filp->private_data; |
1549 | struct list_head *p, *q = &cursor->s_sibling; | 1553 | struct list_head *p, *q = &cursor->s_sibling; |
1550 | ino_t ino; | 1554 | ino_t ino = 0; |
1551 | int i = filp->f_pos; | 1555 | int i = filp->f_pos; |
1552 | 1556 | ||
1553 | switch (i) { | 1557 | switch (i) { |
@@ -1575,6 +1579,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1575 | struct configfs_dirent *next; | 1579 | struct configfs_dirent *next; |
1576 | const char * name; | 1580 | const char * name; |
1577 | int len; | 1581 | int len; |
1582 | struct inode *inode = NULL; | ||
1578 | 1583 | ||
1579 | next = list_entry(p, struct configfs_dirent, | 1584 | next = list_entry(p, struct configfs_dirent, |
1580 | s_sibling); | 1585 | s_sibling); |
@@ -1583,9 +1588,28 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
1583 | 1588 | ||
1584 | name = configfs_get_name(next); | 1589 | name = configfs_get_name(next); |
1585 | len = strlen(name); | 1590 | len = strlen(name); |
1586 | if (next->s_dentry) | 1591 | |
1587 | ino = next->s_dentry->d_inode->i_ino; | 1592 | /* |
1588 | else | 1593 | * We'll have a dentry and an inode for |
1594 | * PINNED items and for open attribute | ||
1595 | * files. We lock here to prevent a race | ||
1596 | * with configfs_d_iput() clearing | ||
1597 | * s_dentry before calling iput(). | ||
1598 | * | ||
1599 | * Why do we go to the trouble? If | ||
1600 | * someone has an attribute file open, | ||
1601 | * the inode number should match until | ||
1602 | * they close it. Beyond that, we don't | ||
1603 | * care. | ||
1604 | */ | ||
1605 | spin_lock(&configfs_dirent_lock); | ||
1606 | dentry = next->s_dentry; | ||
1607 | if (dentry) | ||
1608 | inode = dentry->d_inode; | ||
1609 | if (inode) | ||
1610 | ino = inode->i_ino; | ||
1611 | spin_unlock(&configfs_dirent_lock); | ||
1612 | if (!inode) | ||
1589 | ino = iunique(configfs_sb, 2); | 1613 | ino = iunique(configfs_sb, 2); |
1590 | 1614 | ||
1591 | if (filldir(dirent, name, len, filp->f_pos, ino, | 1615 | if (filldir(dirent, name, len, filp->f_pos, ino, |
@@ -1685,7 +1709,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) | |||
1685 | err = configfs_attach_group(sd->s_element, &group->cg_item, | 1709 | err = configfs_attach_group(sd->s_element, &group->cg_item, |
1686 | dentry); | 1710 | dentry); |
1687 | if (err) { | 1711 | if (err) { |
1688 | d_delete(dentry); | 1712 | BUG_ON(dentry->d_inode); |
1713 | d_drop(dentry); | ||
1689 | dput(dentry); | 1714 | dput(dentry); |
1690 | } else { | 1715 | } else { |
1691 | spin_lock(&configfs_dirent_lock); | 1716 | spin_lock(&configfs_dirent_lock); |