[PATCH] prepare vfs_readdir() callers to returning filldir result
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 24 Aug 2008 11:29:52 +0000 (07:29 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 23 Oct 2008 09:13:10 +0000 (05:13 -0400)
It's not the final state, but it allows moving ->readdir() instances
to passing filldir return value to caller of vfs_readdir().

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/alpha/kernel/osf_sys.c
arch/parisc/hpux/fs.c
fs/compat.c
fs/exportfs/expfs.c
fs/nfsd/vfs.c
fs/readdir.c

index 8509dad312044ede7039ef35846b24ffe49a6582..f25f6c490952f79d55aab060e5e9c8d9abed9bed 100644 (file)
@@ -165,14 +165,11 @@ osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
        buf.error = 0;
 
        error = vfs_readdir(file, osf_filldir, &buf);
-       if (error < 0)
-               goto out_putf;
-
-       error = buf.error;
+       if (error >= 0)
+               error = buf.error;
        if (count != buf.count)
                error = count - buf.count;
 
- out_putf:
        fput(file);
  out:
        return error;
index 12c04c5e558be01c1a219214721bfbd1901c1b4e..bd9a4db3bd4cd1ab14ddb6c7aadcdd44afc37dcd 100644 (file)
@@ -127,9 +127,8 @@ int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned i
        buf.error = 0;
 
        error = vfs_readdir(file, filldir, &buf);
-       if (error < 0)
-               goto out_putf;
-       error = buf.error;
+       if (error >= 0)
+               error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
                if (put_user(file->f_pos, &lastdirent->d_off))
index 5f9ec449c799854e19a9190b489ccf4a23fc0b03..cb36245f9fe0af7b7df70f54cd6f601ff10f9f51 100644 (file)
@@ -869,7 +869,7 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
        buf.dirent = dirent;
 
        error = vfs_readdir(file, compat_fillonedir, &buf);
-       if (error >= 0)
+       if (buf.result)
                error = buf.result;
 
        fput(file);
@@ -956,9 +956,8 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
        buf.error = 0;
 
        error = vfs_readdir(file, compat_filldir, &buf);
-       if (error < 0)
-               goto out_putf;
-       error = buf.error;
+       if (error >= 0)
+               error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
                if (put_user(file->f_pos, &lastdirent->d_off))
@@ -966,8 +965,6 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
                else
                        error = count - buf.count;
        }
-
-out_putf:
        fput(file);
 out:
        return error;
@@ -1047,19 +1044,16 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
        buf.error = 0;
 
        error = vfs_readdir(file, compat_filldir64, &buf);
-       if (error < 0)
-               goto out_putf;
-       error = buf.error;
+       if (error >= 0)
+               error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
                typeof(lastdirent->d_off) d_off = file->f_pos;
-               error = -EFAULT;
                if (__put_user_unaligned(d_off, &lastdirent->d_off))
-                       goto out_putf;
-               error = count - buf.count;
+                       error = -EFAULT;
+               else
+                       error = count - buf.count;
        }
-
-out_putf:
        fput(file);
 out:
        return error;
index 51bdc5cab06996709a6649a597536871642a3bbe..80246bad1b7fe513a7da15f4d6ac057cad3d7e54 100644 (file)
@@ -280,13 +280,14 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry,
                int old_seq = buffer.sequence;
 
                error = vfs_readdir(file, filldir_one, &buffer);
+               if (buffer.found) {
+                       error = 0;
+                       break;
+               }
 
                if (error < 0)
                        break;
 
-               error = 0;
-               if (buffer.found)
-                       break;
                error = -ENOENT;
                if (old_seq == buffer.sequence)
                        break;
index 93b22f661d9da05c658cf064d1e12ea8cfb38785..e3e37f7c84775cfb350750d96db4e598d9f54bde 100644 (file)
@@ -1831,6 +1831,7 @@ struct buffered_dirent {
 struct readdir_data {
        char            *dirent;
        size_t          used;
+       int             full;
 };
 
 static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen,
@@ -1841,8 +1842,10 @@ static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen,
        unsigned int reclen;
 
        reclen = ALIGN(sizeof(struct buffered_dirent) + namlen, sizeof(u64));
-       if (buf->used + reclen > PAGE_SIZE)
+       if (buf->used + reclen > PAGE_SIZE) {
+               buf->full = 1;
                return -EINVAL;
+       }
 
        de->namlen = namlen;
        de->offset = offset;
@@ -1874,9 +1877,13 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
                unsigned int reclen;
 
                buf.used = 0;
+               buf.full = 0;
 
                host_err = vfs_readdir(file, nfsd_buffered_filldir, &buf);
-               if (host_err)
+               if (buf.full)
+                       host_err = 0;
+
+               if (host_err < 0)
                        break;
 
                size = buf.used;
index 93a7559bbfd8c6a265d2824058c00612d1aabe1c..b318d9b5af2e9c5d24a325ece38acac3027a2ef8 100644 (file)
@@ -117,7 +117,7 @@ asmlinkage long old_readdir(unsigned int fd, struct old_linux_dirent __user * di
        buf.dirent = dirent;
 
        error = vfs_readdir(file, fillonedir, &buf);
-       if (error >= 0)
+       if (buf.result)
                error = buf.result;
 
        fput(file);
@@ -209,9 +209,8 @@ asmlinkage long sys_getdents(unsigned int fd, struct linux_dirent __user * diren
        buf.error = 0;
 
        error = vfs_readdir(file, filldir, &buf);
-       if (error < 0)
-               goto out_putf;
-       error = buf.error;
+       if (error >= 0)
+               error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
                if (put_user(file->f_pos, &lastdirent->d_off))
@@ -219,8 +218,6 @@ asmlinkage long sys_getdents(unsigned int fd, struct linux_dirent __user * diren
                else
                        error = count - buf.count;
        }
-
-out_putf:
        fput(file);
 out:
        return error;
@@ -293,19 +290,16 @@ asmlinkage long sys_getdents64(unsigned int fd, struct linux_dirent64 __user * d
        buf.error = 0;
 
        error = vfs_readdir(file, filldir64, &buf);
-       if (error < 0)
-               goto out_putf;
-       error = buf.error;
+       if (error >= 0)
+               error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
                typeof(lastdirent->d_off) d_off = file->f_pos;
-               error = -EFAULT;
                if (__put_user(d_off, &lastdirent->d_off))
-                       goto out_putf;
-               error = count - buf.count;
+                       error = -EFAULT;
+               else
+                       error = count - buf.count;
        }
-
-out_putf:
        fput(file);
 out:
        return error;