aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/configfs/dir.c122
1 files changed, 52 insertions, 70 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 7aabc6ad4e9b..64e5323cbbb0 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1532,84 +1532,66 @@ static inline unsigned char dt_type(struct configfs_dirent *sd)
1532 return (sd->s_mode >> 12) & 15; 1532 return (sd->s_mode >> 12) & 15;
1533} 1533}
1534 1534
1535static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir) 1535static int configfs_readdir(struct file *file, struct dir_context *ctx)
1536{ 1536{
1537 struct dentry *dentry = filp->f_path.dentry; 1537 struct dentry *dentry = file->f_path.dentry;
1538 struct super_block *sb = dentry->d_sb; 1538 struct super_block *sb = dentry->d_sb;
1539 struct configfs_dirent * parent_sd = dentry->d_fsdata; 1539 struct configfs_dirent * parent_sd = dentry->d_fsdata;
1540 struct configfs_dirent *cursor = filp->private_data; 1540 struct configfs_dirent *cursor = file->private_data;
1541 struct list_head *p, *q = &cursor->s_sibling; 1541 struct list_head *p, *q = &cursor->s_sibling;
1542 ino_t ino = 0; 1542 ino_t ino = 0;
1543 int i = filp->f_pos;
1544 1543
1545 switch (i) { 1544 if (!dir_emit_dots(file, ctx))
1546 case 0: 1545 return 0;
1547 ino = dentry->d_inode->i_ino; 1546 if (ctx->pos == 2) {
1548 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) 1547 spin_lock(&configfs_dirent_lock);
1549 break; 1548 list_move(q, &parent_sd->s_children);
1550 filp->f_pos++; 1549 spin_unlock(&configfs_dirent_lock);
1551 i++; 1550 }
1552 /* fallthrough */ 1551 for (p = q->next; p != &parent_sd->s_children; p = p->next) {
1553 case 1: 1552 struct configfs_dirent *next;
1554 ino = parent_ino(dentry); 1553 const char *name;
1555 if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) 1554 int len;
1556 break; 1555 struct inode *inode = NULL;
1557 filp->f_pos++; 1556
1558 i++; 1557 next = list_entry(p, struct configfs_dirent, s_sibling);
1559 /* fallthrough */ 1558 if (!next->s_element)
1560 default: 1559 continue;
1561 if (filp->f_pos == 2) {
1562 spin_lock(&configfs_dirent_lock);
1563 list_move(q, &parent_sd->s_children);
1564 spin_unlock(&configfs_dirent_lock);
1565 }
1566 for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
1567 struct configfs_dirent *next;
1568 const char * name;
1569 int len;
1570 struct inode *inode = NULL;
1571 1560
1572 next = list_entry(p, struct configfs_dirent, 1561 name = configfs_get_name(next);
1573 s_sibling); 1562 len = strlen(name);
1574 if (!next->s_element) 1563
1575 continue; 1564 /*
1576 1565 * We'll have a dentry and an inode for
1577 name = configfs_get_name(next); 1566 * PINNED items and for open attribute
1578 len = strlen(name); 1567 * files. We lock here to prevent a race
1579 1568 * with configfs_d_iput() clearing
1580 /* 1569 * s_dentry before calling iput().
1581 * We'll have a dentry and an inode for 1570 *
1582 * PINNED items and for open attribute 1571 * Why do we go to the trouble? If
1583 * files. We lock here to prevent a race 1572 * someone has an attribute file open,
1584 * with configfs_d_iput() clearing 1573 * the inode number should match until
1585 * s_dentry before calling iput(). 1574 * they close it. Beyond that, we don't
1586 * 1575 * care.
1587 * Why do we go to the trouble? If 1576 */
1588 * someone has an attribute file open, 1577 spin_lock(&configfs_dirent_lock);
1589 * the inode number should match until 1578 dentry = next->s_dentry;
1590 * they close it. Beyond that, we don't 1579 if (dentry)
1591 * care. 1580 inode = dentry->d_inode;
1592 */ 1581 if (inode)
1593 spin_lock(&configfs_dirent_lock); 1582 ino = inode->i_ino;
1594 dentry = next->s_dentry; 1583 spin_unlock(&configfs_dirent_lock);
1595 if (dentry) 1584 if (!inode)
1596 inode = dentry->d_inode; 1585 ino = iunique(sb, 2);
1597 if (inode)
1598 ino = inode->i_ino;
1599 spin_unlock(&configfs_dirent_lock);
1600 if (!inode)
1601 ino = iunique(sb, 2);
1602 1586
1603 if (filldir(dirent, name, len, filp->f_pos, ino, 1587 if (!dir_emit(ctx, name, len, ino, dt_type(next)))
1604 dt_type(next)) < 0) 1588 return 0;
1605 return 0;
1606 1589
1607 spin_lock(&configfs_dirent_lock); 1590 spin_lock(&configfs_dirent_lock);
1608 list_move(q, p); 1591 list_move(q, p);
1609 spin_unlock(&configfs_dirent_lock); 1592 spin_unlock(&configfs_dirent_lock);
1610 p = q; 1593 p = q;
1611 filp->f_pos++; 1594 ctx->pos++;
1612 }
1613 } 1595 }
1614 return 0; 1596 return 0;
1615} 1597}
@@ -1661,7 +1643,7 @@ const struct file_operations configfs_dir_operations = {
1661 .release = configfs_dir_close, 1643 .release = configfs_dir_close,
1662 .llseek = configfs_dir_lseek, 1644 .llseek = configfs_dir_lseek,
1663 .read = generic_read_dir, 1645 .read = generic_read_dir,
1664 .readdir = configfs_readdir, 1646 .iterate = configfs_readdir,
1665}; 1647};
1666 1648
1667int configfs_register_subsystem(struct configfs_subsystem *subsys) 1649int configfs_register_subsystem(struct configfs_subsystem *subsys)