diff options
-rw-r--r-- | fs/configfs/dir.c | 122 |
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 | ||
1535 | static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | 1535 | static 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 | ||
1667 | int configfs_register_subsystem(struct configfs_subsystem *subsys) | 1649 | int configfs_register_subsystem(struct configfs_subsystem *subsys) |