diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-04-20 19:50:05 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-05-09 11:41:13 -0400 |
commit | a01b3007ffb9be0180e744f0d15b130b0a76a29f (patch) | |
tree | 5ccfce3fe8e64828e99303133278c9d075817503 /fs/configfs | |
parent | 884be175351e73c515303118150f195dd611787c (diff) |
configfs_readdir(): make safe under shared lock
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/configfs')
-rw-r--r-- | fs/configfs/dir.c | 20 |
1 files changed, 7 insertions, 13 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 48929c408e04..56fb26127fef 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -1633,11 +1633,9 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx) | |||
1633 | 1633 | ||
1634 | if (!dir_emit_dots(file, ctx)) | 1634 | if (!dir_emit_dots(file, ctx)) |
1635 | return 0; | 1635 | return 0; |
1636 | if (ctx->pos == 2) { | 1636 | spin_lock(&configfs_dirent_lock); |
1637 | spin_lock(&configfs_dirent_lock); | 1637 | if (ctx->pos == 2) |
1638 | list_move(q, &parent_sd->s_children); | 1638 | list_move(q, &parent_sd->s_children); |
1639 | spin_unlock(&configfs_dirent_lock); | ||
1640 | } | ||
1641 | for (p = q->next; p != &parent_sd->s_children; p = p->next) { | 1639 | for (p = q->next; p != &parent_sd->s_children; p = p->next) { |
1642 | struct configfs_dirent *next; | 1640 | struct configfs_dirent *next; |
1643 | const char *name; | 1641 | const char *name; |
@@ -1648,9 +1646,6 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx) | |||
1648 | if (!next->s_element) | 1646 | if (!next->s_element) |
1649 | continue; | 1647 | continue; |
1650 | 1648 | ||
1651 | name = configfs_get_name(next); | ||
1652 | len = strlen(name); | ||
1653 | |||
1654 | /* | 1649 | /* |
1655 | * We'll have a dentry and an inode for | 1650 | * We'll have a dentry and an inode for |
1656 | * PINNED items and for open attribute | 1651 | * PINNED items and for open attribute |
@@ -1664,7 +1659,6 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx) | |||
1664 | * they close it. Beyond that, we don't | 1659 | * they close it. Beyond that, we don't |
1665 | * care. | 1660 | * care. |
1666 | */ | 1661 | */ |
1667 | spin_lock(&configfs_dirent_lock); | ||
1668 | dentry = next->s_dentry; | 1662 | dentry = next->s_dentry; |
1669 | if (dentry) | 1663 | if (dentry) |
1670 | inode = d_inode(dentry); | 1664 | inode = d_inode(dentry); |
@@ -1674,15 +1668,18 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx) | |||
1674 | if (!inode) | 1668 | if (!inode) |
1675 | ino = iunique(sb, 2); | 1669 | ino = iunique(sb, 2); |
1676 | 1670 | ||
1671 | name = configfs_get_name(next); | ||
1672 | len = strlen(name); | ||
1673 | |||
1677 | if (!dir_emit(ctx, name, len, ino, dt_type(next))) | 1674 | if (!dir_emit(ctx, name, len, ino, dt_type(next))) |
1678 | return 0; | 1675 | return 0; |
1679 | 1676 | ||
1680 | spin_lock(&configfs_dirent_lock); | 1677 | spin_lock(&configfs_dirent_lock); |
1681 | list_move(q, p); | 1678 | list_move(q, p); |
1682 | spin_unlock(&configfs_dirent_lock); | ||
1683 | p = q; | 1679 | p = q; |
1684 | ctx->pos++; | 1680 | ctx->pos++; |
1685 | } | 1681 | } |
1682 | spin_unlock(&configfs_dirent_lock); | ||
1686 | return 0; | 1683 | return 0; |
1687 | } | 1684 | } |
1688 | 1685 | ||
@@ -1690,7 +1687,6 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence) | |||
1690 | { | 1687 | { |
1691 | struct dentry * dentry = file->f_path.dentry; | 1688 | struct dentry * dentry = file->f_path.dentry; |
1692 | 1689 | ||
1693 | inode_lock(d_inode(dentry)); | ||
1694 | switch (whence) { | 1690 | switch (whence) { |
1695 | case 1: | 1691 | case 1: |
1696 | offset += file->f_pos; | 1692 | offset += file->f_pos; |
@@ -1698,7 +1694,6 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence) | |||
1698 | if (offset >= 0) | 1694 | if (offset >= 0) |
1699 | break; | 1695 | break; |
1700 | default: | 1696 | default: |
1701 | inode_unlock(d_inode(dentry)); | ||
1702 | return -EINVAL; | 1697 | return -EINVAL; |
1703 | } | 1698 | } |
1704 | if (offset != file->f_pos) { | 1699 | if (offset != file->f_pos) { |
@@ -1724,7 +1719,6 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence) | |||
1724 | spin_unlock(&configfs_dirent_lock); | 1719 | spin_unlock(&configfs_dirent_lock); |
1725 | } | 1720 | } |
1726 | } | 1721 | } |
1727 | inode_unlock(d_inode(dentry)); | ||
1728 | return offset; | 1722 | return offset; |
1729 | } | 1723 | } |
1730 | 1724 | ||
@@ -1733,7 +1727,7 @@ const struct file_operations configfs_dir_operations = { | |||
1733 | .release = configfs_dir_close, | 1727 | .release = configfs_dir_close, |
1734 | .llseek = configfs_dir_lseek, | 1728 | .llseek = configfs_dir_lseek, |
1735 | .read = generic_read_dir, | 1729 | .read = generic_read_dir, |
1736 | .iterate = configfs_readdir, | 1730 | .iterate_shared = configfs_readdir, |
1737 | }; | 1731 | }; |
1738 | 1732 | ||
1739 | /** | 1733 | /** |