diff options
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r-- | fs/sysfs/dir.c | 66 |
1 files changed, 18 insertions, 48 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e8e0e71b29d5..4cfd742d260d 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -998,68 +998,38 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, | |||
998 | return pos; | 998 | return pos; |
999 | } | 999 | } |
1000 | 1000 | ||
1001 | static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | 1001 | static int sysfs_readdir(struct file *file, struct dir_context *ctx) |
1002 | { | 1002 | { |
1003 | struct dentry *dentry = filp->f_path.dentry; | 1003 | struct dentry *dentry = file->f_path.dentry; |
1004 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 1004 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
1005 | struct sysfs_dirent *pos = filp->private_data; | 1005 | struct sysfs_dirent *pos = file->private_data; |
1006 | enum kobj_ns_type type; | 1006 | enum kobj_ns_type type; |
1007 | const void *ns; | 1007 | const void *ns; |
1008 | ino_t ino; | ||
1009 | loff_t off; | ||
1010 | 1008 | ||
1011 | type = sysfs_ns_type(parent_sd); | 1009 | type = sysfs_ns_type(parent_sd); |
1012 | ns = sysfs_info(dentry->d_sb)->ns[type]; | 1010 | ns = sysfs_info(dentry->d_sb)->ns[type]; |
1013 | 1011 | ||
1014 | if (filp->f_pos == 0) { | 1012 | if (!dir_emit_dots(file, ctx)) |
1015 | ino = parent_sd->s_ino; | 1013 | return 0; |
1016 | if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) | ||
1017 | filp->f_pos++; | ||
1018 | else | ||
1019 | return 0; | ||
1020 | } | ||
1021 | if (filp->f_pos == 1) { | ||
1022 | if (parent_sd->s_parent) | ||
1023 | ino = parent_sd->s_parent->s_ino; | ||
1024 | else | ||
1025 | ino = parent_sd->s_ino; | ||
1026 | if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) | ||
1027 | filp->f_pos++; | ||
1028 | else | ||
1029 | return 0; | ||
1030 | } | ||
1031 | mutex_lock(&sysfs_mutex); | 1014 | mutex_lock(&sysfs_mutex); |
1032 | off = filp->f_pos; | 1015 | for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos); |
1033 | for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos); | ||
1034 | pos; | 1016 | pos; |
1035 | pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) { | 1017 | pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) { |
1036 | const char * name; | 1018 | const char *name = pos->s_name; |
1037 | unsigned int type; | 1019 | unsigned int type = dt_type(pos); |
1038 | int len, ret; | 1020 | int len = strlen(name); |
1039 | 1021 | ino_t ino = pos->s_ino; | |
1040 | name = pos->s_name; | 1022 | ctx->pos = pos->s_hash; |
1041 | len = strlen(name); | 1023 | file->private_data = sysfs_get(pos); |
1042 | ino = pos->s_ino; | ||
1043 | type = dt_type(pos); | ||
1044 | off = filp->f_pos = pos->s_hash; | ||
1045 | filp->private_data = sysfs_get(pos); | ||
1046 | 1024 | ||
1047 | mutex_unlock(&sysfs_mutex); | 1025 | mutex_unlock(&sysfs_mutex); |
1048 | ret = filldir(dirent, name, len, off, ino, type); | 1026 | if (!dir_emit(ctx, name, len, ino, type)) |
1027 | return 0; | ||
1049 | mutex_lock(&sysfs_mutex); | 1028 | mutex_lock(&sysfs_mutex); |
1050 | if (ret < 0) | ||
1051 | break; | ||
1052 | } | 1029 | } |
1053 | mutex_unlock(&sysfs_mutex); | 1030 | mutex_unlock(&sysfs_mutex); |
1054 | 1031 | file->private_data = NULL; | |
1055 | /* don't reference last entry if its refcount is dropped */ | 1032 | ctx->pos = INT_MAX; |
1056 | if (!pos) { | ||
1057 | filp->private_data = NULL; | ||
1058 | |||
1059 | /* EOF and not changed as 0 or 1 in read/write path */ | ||
1060 | if (off == filp->f_pos && off > 1) | ||
1061 | filp->f_pos = INT_MAX; | ||
1062 | } | ||
1063 | return 0; | 1033 | return 0; |
1064 | } | 1034 | } |
1065 | 1035 | ||
@@ -1077,7 +1047,7 @@ static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence) | |||
1077 | 1047 | ||
1078 | const struct file_operations sysfs_dir_operations = { | 1048 | const struct file_operations sysfs_dir_operations = { |
1079 | .read = generic_read_dir, | 1049 | .read = generic_read_dir, |
1080 | .readdir = sysfs_readdir, | 1050 | .iterate = sysfs_readdir, |
1081 | .release = sysfs_dir_release, | 1051 | .release = sysfs_dir_release, |
1082 | .llseek = sysfs_dir_llseek, | 1052 | .llseek = sysfs_dir_llseek, |
1083 | }; | 1053 | }; |