aboutsummaryrefslogtreecommitdiffstats
path: root/fs/configfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/configfs')
-rw-r--r--fs/configfs/dir.c39
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);
53static void configfs_d_iput(struct dentry * dentry, 53static 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);