[readdir] simple local unixlike: switch to ->iterate()
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 15 May 2013 22:51:49 +0000 (18:51 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 29 Jun 2013 08:46:47 +0000 (12:46 +0400)
ext2, ufs, minix, sysv

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

index 4237722bfd27173c34c9835cb1e28deeaa2e72f6..6e1d4ab09d7226e4e519ea00a2e1941dd793ca39 100644 (file)
@@ -287,17 +287,17 @@ static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)
 }
 
 static int
-ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
+ext2_readdir(struct file *file, struct dir_context *ctx)
 {
-       loff_t pos = filp->f_pos;
-       struct inode *inode = file_inode(filp);
+       loff_t pos = ctx->pos;
+       struct inode *inode = file_inode(file);
        struct super_block *sb = inode->i_sb;
        unsigned int offset = pos & ~PAGE_CACHE_MASK;
        unsigned long n = pos >> PAGE_CACHE_SHIFT;
        unsigned long npages = dir_pages(inode);
        unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
        unsigned char *types = NULL;
-       int need_revalidate = filp->f_version != inode->i_version;
+       int need_revalidate = file->f_version != inode->i_version;
 
        if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
                return 0;
@@ -314,16 +314,16 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
                        ext2_error(sb, __func__,
                                   "bad page in #%lu",
                                   inode->i_ino);
-                       filp->f_pos += PAGE_CACHE_SIZE - offset;
+                       ctx->pos += PAGE_CACHE_SIZE - offset;
                        return PTR_ERR(page);
                }
                kaddr = page_address(page);
                if (unlikely(need_revalidate)) {
                        if (offset) {
                                offset = ext2_validate_entry(kaddr, offset, chunk_mask);
-                               filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
+                               ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset;
                        }
-                       filp->f_version = inode->i_version;
+                       file->f_version = inode->i_version;
                        need_revalidate = 0;
                }
                de = (ext2_dirent *)(kaddr+offset);
@@ -336,22 +336,19 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
                                return -EIO;
                        }
                        if (de->inode) {
-                               int over;
                                unsigned char d_type = DT_UNKNOWN;
 
                                if (types && de->file_type < EXT2_FT_MAX)
                                        d_type = types[de->file_type];
 
-                               offset = (char *)de - kaddr;
-                               over = filldir(dirent, de->name, de->name_len,
-                                               (n<<PAGE_CACHE_SHIFT) | offset,
-                                               le32_to_cpu(de->inode), d_type);
-                               if (over) {
+                               if (!dir_emit(ctx, de->name, de->name_len,
+                                               le32_to_cpu(de->inode),
+                                               d_type)) {
                                        ext2_put_page(page);
                                        return 0;
                                }
                        }
-                       filp->f_pos += ext2_rec_len_from_disk(de->rec_len);
+                       ctx->pos += ext2_rec_len_from_disk(de->rec_len);
                }
                ext2_put_page(page);
        }
@@ -724,7 +721,7 @@ not_empty:
 const struct file_operations ext2_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .readdir        = ext2_readdir,
+       .iterate        = ext2_readdir,
        .unlocked_ioctl = ext2_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = ext2_compat_ioctl,
index a9ed6f36e6ead1d32bf754b50d5eaed3068d6cf2..08c442902fcdbf9ec5a9039621f8b8900ea6bf0e 100644 (file)
 typedef struct minix_dir_entry minix_dirent;
 typedef struct minix3_dir_entry minix3_dirent;
 
-static int minix_readdir(struct file *, void *, filldir_t);
+static int minix_readdir(struct file *, struct dir_context *);
 
 const struct file_operations minix_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .readdir        = minix_readdir,
+       .iterate        = minix_readdir,
        .fsync          = generic_file_fsync,
 };
 
@@ -82,22 +82,23 @@ static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
        return (void*)((char*)de + sbi->s_dirsize);
 }
 
-static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
+static int minix_readdir(struct file *file, struct dir_context *ctx)
 {
-       unsigned long pos = filp->f_pos;
-       struct inode *inode = file_inode(filp);
+       struct inode *inode = file_inode(file);
        struct super_block *sb = inode->i_sb;
-       unsigned offset = pos & ~PAGE_CACHE_MASK;
-       unsigned long n = pos >> PAGE_CACHE_SHIFT;
-       unsigned long npages = dir_pages(inode);
        struct minix_sb_info *sbi = minix_sb(sb);
        unsigned chunk_size = sbi->s_dirsize;
-       char *name;
-       __u32 inumber;
+       unsigned long npages = dir_pages(inode);
+       unsigned long pos = ctx->pos;
+       unsigned offset;
+       unsigned long n;
 
-       pos = (pos + chunk_size-1) & ~(chunk_size-1);
+       ctx->pos = pos = (pos + chunk_size-1) & ~(chunk_size-1);
        if (pos >= inode->i_size)
-               goto done;
+               return 0;
+
+       offset = pos & ~PAGE_CACHE_MASK;
+       n = pos >> PAGE_CACHE_SHIFT;
 
        for ( ; n < npages; n++, offset = 0) {
                char *p, *kaddr, *limit;
@@ -109,6 +110,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
                p = kaddr+offset;
                limit = kaddr + minix_last_byte(inode, n) - chunk_size;
                for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
+                       const char *name;
+                       __u32 inumber;
                        if (sbi->s_version == MINIX_V3) {
                                minix3_dirent *de3 = (minix3_dirent *)p;
                                name = de3->name;
@@ -119,24 +122,17 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
                                inumber = de->inode;
                        }
                        if (inumber) {
-                               int over;
-
                                unsigned l = strnlen(name, sbi->s_namelen);
-                               offset = p - kaddr;
-                               over = filldir(dirent, name, l,
-                                       (n << PAGE_CACHE_SHIFT) | offset,
-                                       inumber, DT_UNKNOWN);
-                               if (over) {
+                               if (!dir_emit(ctx, name, l,
+                                             inumber, DT_UNKNOWN)) {
                                        dir_put_page(page);
-                                       goto done;
+                                       return 0;
                                }
                        }
+                       ctx->pos += chunk_size;
                }
                dir_put_page(page);
        }
-
-done:
-       filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
        return 0;
 }
 
index 3799e8dac3ebf26e288a80086bc97adf136ff06b..d42291d08215abd016d4e3b5aac03fa753ce70b6 100644 (file)
 #include <linux/swap.h>
 #include "sysv.h"
 
-static int sysv_readdir(struct file *, void *, filldir_t);
+static int sysv_readdir(struct file *, struct dir_context *);
 
 const struct file_operations sysv_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .readdir        = sysv_readdir,
+       .iterate        = sysv_readdir,
        .fsync          = generic_file_fsync,
 };
 
@@ -65,18 +65,21 @@ static struct page * dir_get_page(struct inode *dir, unsigned long n)
        return page;
 }
 
-static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
+static int sysv_readdir(struct file *file, struct dir_context *ctx)
 {
-       unsigned long pos = filp->f_pos;
-       struct inode *inode = file_inode(filp);
+       unsigned long pos = ctx->pos;
+       struct inode *inode = file_inode(file);
        struct super_block *sb = inode->i_sb;
-       unsigned offset = pos & ~PAGE_CACHE_MASK;
-       unsigned long n = pos >> PAGE_CACHE_SHIFT;
        unsigned long npages = dir_pages(inode);
+       unsigned offset;
+       unsigned long n;
 
-       pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
+       ctx->pos = pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
        if (pos >= inode->i_size)
-               goto done;
+               return 0;
+
+       offset = pos & ~PAGE_CACHE_MASK;
+       n = pos >> PAGE_CACHE_SHIFT;
 
        for ( ; n < npages; n++, offset = 0) {
                char *kaddr, *limit;
@@ -88,29 +91,21 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
                kaddr = (char *)page_address(page);
                de = (struct sysv_dir_entry *)(kaddr+offset);
                limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE;
-               for ( ;(char*)de <= limit; de++) {
+               for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) {
                        char *name = de->name;
-                       int over;
 
                        if (!de->inode)
                                continue;
 
-                       offset = (char *)de - kaddr;
-
-                       over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
-                                       ((loff_t)n<<PAGE_CACHE_SHIFT) | offset,
+                       if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
                                        fs16_to_cpu(SYSV_SB(sb), de->inode),
-                                       DT_UNKNOWN);
-                       if (over) {
+                                       DT_UNKNOWN)) {
                                dir_put_page(page);
-                               goto done;
+                               return 0;
                        }
                }
                dir_put_page(page);
        }
-
-done:
-       filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset;
        return 0;
 }
 
index 3a75ca09c506591910e45a5bad970e80382b970c..0ecc2cebed8ffec60bc9ccdb408519253d7fc3a6 100644 (file)
@@ -430,16 +430,16 @@ ufs_validate_entry(struct super_block *sb, char *base,
  * This is blatantly stolen from ext2fs
  */
 static int
-ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+ufs_readdir(struct file *file, struct dir_context *ctx)
 {
-       loff_t pos = filp->f_pos;
-       struct inode *inode = file_inode(filp);
+       loff_t pos = ctx->pos;
+       struct inode *inode = file_inode(file);
        struct super_block *sb = inode->i_sb;
        unsigned int offset = pos & ~PAGE_CACHE_MASK;
        unsigned long n = pos >> PAGE_CACHE_SHIFT;
        unsigned long npages = ufs_dir_pages(inode);
        unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
-       int need_revalidate = filp->f_version != inode->i_version;
+       int need_revalidate = file->f_version != inode->i_version;
        unsigned flags = UFS_SB(sb)->s_flags;
 
        UFSD("BEGIN\n");
@@ -457,16 +457,16 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        ufs_error(sb, __func__,
                                  "bad page in #%lu",
                                  inode->i_ino);
-                       filp->f_pos += PAGE_CACHE_SIZE - offset;
+                       ctx->pos += PAGE_CACHE_SIZE - offset;
                        return -EIO;
                }
                kaddr = page_address(page);
                if (unlikely(need_revalidate)) {
                        if (offset) {
                                offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask);
-                               filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
+                               ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset;
                        }
-                       filp->f_version = inode->i_version;
+                       file->f_version = inode->i_version;
                        need_revalidate = 0;
                }
                de = (struct ufs_dir_entry *)(kaddr+offset);
@@ -479,11 +479,8 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                return -EIO;
                        }
                        if (de->d_ino) {
-                               int over;
                                unsigned char d_type = DT_UNKNOWN;
 
-                               offset = (char *)de - kaddr;
-
                                UFSD("filldir(%s,%u)\n", de->d_name,
                                      fs32_to_cpu(sb, de->d_ino));
                                UFSD("namlen %u\n", ufs_get_de_namlen(sb, de));
@@ -491,16 +488,15 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
                                        d_type = de->d_u.d_44.d_type;
 
-                               over = filldir(dirent, de->d_name,
+                               if (!dir_emit(ctx, de->d_name,
                                               ufs_get_de_namlen(sb, de),
-                                               (n<<PAGE_CACHE_SHIFT) | offset,
-                                              fs32_to_cpu(sb, de->d_ino), d_type);
-                               if (over) {
+                                              fs32_to_cpu(sb, de->d_ino),
+                                              d_type)) {
                                        ufs_put_page(page);
                                        return 0;
                                }
                        }
-                       filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
+                       ctx->pos += fs16_to_cpu(sb, de->d_reclen);
                }
                ufs_put_page(page);
        }
@@ -660,7 +656,7 @@ not_empty:
 
 const struct file_operations ufs_dir_operations = {
        .read           = generic_read_dir,
-       .readdir        = ufs_readdir,
+       .iterate        = ufs_readdir,
        .fsync          = generic_file_fsync,
        .llseek         = generic_file_llseek,
 };