[readdir] convert sysfs
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 16 May 2013 18:31:02 +0000 (14:31 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 29 Jun 2013 08:56:36 +0000 (12:56 +0400)
get rid of the kludges in sysfs_readdir()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/sysfs/dir.c

index e8e0e71..4cfd742 100644 (file)
@@ -998,68 +998,38 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns,
        return pos;
 }
 
-static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
+static int sysfs_readdir(struct file *file, struct dir_context *ctx)
 {
-       struct dentry *dentry = filp->f_path.dentry;
+       struct dentry *dentry = file->f_path.dentry;
        struct sysfs_dirent * parent_sd = dentry->d_fsdata;
-       struct sysfs_dirent *pos = filp->private_data;
+       struct sysfs_dirent *pos = file->private_data;
        enum kobj_ns_type type;
        const void *ns;
-       ino_t ino;
-       loff_t off;
 
        type = sysfs_ns_type(parent_sd);
        ns = sysfs_info(dentry->d_sb)->ns[type];
 
-       if (filp->f_pos == 0) {
-               ino = parent_sd->s_ino;
-               if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0)
-                       filp->f_pos++;
-               else
-                       return 0;
-       }
-       if (filp->f_pos == 1) {
-               if (parent_sd->s_parent)
-                       ino = parent_sd->s_parent->s_ino;
-               else
-                       ino = parent_sd->s_ino;
-               if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
-                       filp->f_pos++;
-               else
-                       return 0;
-       }
+       if (!dir_emit_dots(file, ctx))
+               return 0;
        mutex_lock(&sysfs_mutex);
-       off = filp->f_pos;
-       for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
+       for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos);
             pos;
-            pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) {
-               const char * name;
-               unsigned int type;
-               int len, ret;
-
-               name = pos->s_name;
-               len = strlen(name);
-               ino = pos->s_ino;
-               type = dt_type(pos);
-               off = filp->f_pos = pos->s_hash;
-               filp->private_data = sysfs_get(pos);
+            pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) {
+               const char *name = pos->s_name;
+               unsigned int type = dt_type(pos);
+               int len = strlen(name);
+               ino_t ino = pos->s_ino;
+               ctx->pos = pos->s_hash;
+               file->private_data = sysfs_get(pos);
 
                mutex_unlock(&sysfs_mutex);
-               ret = filldir(dirent, name, len, off, ino, type);
+               if (!dir_emit(ctx, name, len, ino, type))
+                       return 0;
                mutex_lock(&sysfs_mutex);
-               if (ret < 0)
-                       break;
        }
        mutex_unlock(&sysfs_mutex);
-
-       /* don't reference last entry if its refcount is dropped */
-       if (!pos) {
-               filp->private_data = NULL;
-
-               /* EOF and not changed as 0 or 1 in read/write path */
-               if (off == filp->f_pos && off > 1)
-                       filp->f_pos = INT_MAX;
-       }
+       file->private_data = NULL;
+       ctx->pos = INT_MAX;
        return 0;
 }
 
@@ -1077,7 +1047,7 @@ static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence)
 
 const struct file_operations sysfs_dir_operations = {
        .read           = generic_read_dir,
-       .readdir        = sysfs_readdir,
+       .iterate        = sysfs_readdir,
        .release        = sysfs_dir_release,
        .llseek         = sysfs_dir_llseek,
 };