aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-05-15 13:52:59 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-06-29 04:46:46 -0400
commit5c0ba4e0762e6dabd14a5c276652e2defec38de7 (patch)
treecc2c94d81a631b0656782e1f8299da3267871964 /fs
parent83a8761142cb38536e9e88dfc2432d331ea4e257 (diff)
[readdir] introduce iterate_dir() and dir_context
iterate_dir(): new helper, replacing vfs_readdir(). struct dir_context: contains the readdir callback (and will get more stuff in it), embedded into whatever data that callback wants to deal with; eventually, we'll be passing it to ->readdir() replacement instead of (data,filldir) pair. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/compat.c12
-rw-r--r--fs/ecryptfs/file.c4
-rw-r--r--fs/exportfs/expfs.c4
-rw-r--r--fs/nfsd/nfs4recover.c13
-rw-r--r--fs/nfsd/vfs.c4
-rw-r--r--fs/readdir.c21
6 files changed, 40 insertions, 18 deletions
diff --git a/fs/compat.c b/fs/compat.c
index fc3b55dce184..2279b59e81f2 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -832,6 +832,7 @@ struct compat_old_linux_dirent {
832}; 832};
833 833
834struct compat_readdir_callback { 834struct compat_readdir_callback {
835 struct dir_context ctx;
835 struct compat_old_linux_dirent __user *dirent; 836 struct compat_old_linux_dirent __user *dirent;
836 int result; 837 int result;
837}; 838};
@@ -880,8 +881,9 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
880 881
881 buf.result = 0; 882 buf.result = 0;
882 buf.dirent = dirent; 883 buf.dirent = dirent;
884 buf.ctx.actor = compat_fillonedir;
883 885
884 error = vfs_readdir(f.file, compat_fillonedir, &buf); 886 error = iterate_dir(f.file, &buf.ctx);
885 if (buf.result) 887 if (buf.result)
886 error = buf.result; 888 error = buf.result;
887 889
@@ -897,6 +899,7 @@ struct compat_linux_dirent {
897}; 899};
898 900
899struct compat_getdents_callback { 901struct compat_getdents_callback {
902 struct dir_context ctx;
900 struct compat_linux_dirent __user *current_dir; 903 struct compat_linux_dirent __user *current_dir;
901 struct compat_linux_dirent __user *previous; 904 struct compat_linux_dirent __user *previous;
902 int count; 905 int count;
@@ -965,8 +968,9 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
965 buf.previous = NULL; 968 buf.previous = NULL;
966 buf.count = count; 969 buf.count = count;
967 buf.error = 0; 970 buf.error = 0;
971 buf.ctx.actor = compat_filldir;
968 972
969 error = vfs_readdir(f.file, compat_filldir, &buf); 973 error = iterate_dir(f.file, &buf.ctx);
970 if (error >= 0) 974 if (error >= 0)
971 error = buf.error; 975 error = buf.error;
972 lastdirent = buf.previous; 976 lastdirent = buf.previous;
@@ -983,6 +987,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
983#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64 987#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64
984 988
985struct compat_getdents_callback64 { 989struct compat_getdents_callback64 {
990 struct dir_context ctx;
986 struct linux_dirent64 __user *current_dir; 991 struct linux_dirent64 __user *current_dir;
987 struct linux_dirent64 __user *previous; 992 struct linux_dirent64 __user *previous;
988 int count; 993 int count;
@@ -1050,8 +1055,9 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
1050 buf.previous = NULL; 1055 buf.previous = NULL;
1051 buf.count = count; 1056 buf.count = count;
1052 buf.error = 0; 1057 buf.error = 0;
1058 buf.ctx.actor = compat_filldir64;
1053 1059
1054 error = vfs_readdir(f.file, compat_filldir64, &buf); 1060 error = iterate_dir(f.file, &buf.ctx);
1055 if (error >= 0) 1061 if (error >= 0)
1056 error = buf.error; 1062 error = buf.error;
1057 lastdirent = buf.previous; 1063 lastdirent = buf.previous;
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index a7abbea2c096..041379a646b3 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -68,6 +68,7 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
68} 68}
69 69
70struct ecryptfs_getdents_callback { 70struct ecryptfs_getdents_callback {
71 struct dir_context ctx;
71 void *dirent; 72 void *dirent;
72 struct dentry *dentry; 73 struct dentry *dentry;
73 filldir_t filldir; 74 filldir_t filldir;
@@ -126,7 +127,8 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
126 buf.filldir = filldir; 127 buf.filldir = filldir;
127 buf.filldir_called = 0; 128 buf.filldir_called = 0;
128 buf.entries_written = 0; 129 buf.entries_written = 0;
129 rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf); 130 buf.ctx.actor = ecryptfs_filldir;
131 rc = iterate_dir(lower_file, &buf.ctx);
130 file->f_pos = lower_file->f_pos; 132 file->f_pos = lower_file->f_pos;
131 if (rc < 0) 133 if (rc < 0)
132 goto out; 134 goto out;
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 262fc9940982..7cb190426cec 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -212,6 +212,7 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf)
212} 212}
213 213
214struct getdents_callback { 214struct getdents_callback {
215 struct dir_context ctx;
215 char *name; /* name that was found. It already points to a 216 char *name; /* name that was found. It already points to a
216 buffer NAME_MAX+1 is size */ 217 buffer NAME_MAX+1 is size */
217 unsigned long ino; /* the inum we are looking for */ 218 unsigned long ino; /* the inum we are looking for */
@@ -278,10 +279,11 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
278 buffer.ino = child->d_inode->i_ino; 279 buffer.ino = child->d_inode->i_ino;
279 buffer.found = 0; 280 buffer.found = 0;
280 buffer.sequence = 0; 281 buffer.sequence = 0;
282 buffer.ctx.actor = filldir_one;
281 while (1) { 283 while (1) {
282 int old_seq = buffer.sequence; 284 int old_seq = buffer.sequence;
283 285
284 error = vfs_readdir(file, filldir_one, &buffer); 286 error = iterate_dir(file, &buffer.ctx);
285 if (buffer.found) { 287 if (buffer.found) {
286 error = 0; 288 error = 0;
287 break; 289 break;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 4e9a21db867a..4f8cc6ba7c28 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -263,7 +263,10 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
263{ 263{
264 const struct cred *original_cred; 264 const struct cred *original_cred;
265 struct dentry *dir = nn->rec_file->f_path.dentry; 265 struct dentry *dir = nn->rec_file->f_path.dentry;
266 LIST_HEAD(names); 266 struct {
267 struct dir_context ctx;
268 struct list_head names;
269 } ctx;
267 int status; 270 int status;
268 271
269 status = nfs4_save_creds(&original_cred); 272 status = nfs4_save_creds(&original_cred);
@@ -276,11 +279,13 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
276 return status; 279 return status;
277 } 280 }
278 281
279 status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names); 282 INIT_LIST_HEAD(&ctx.names);
283 ctx.ctx.actor = nfsd4_build_namelist;
284 status = iterate_dir(nn->rec_file, &ctx.ctx);
280 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 285 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
281 while (!list_empty(&names)) { 286 while (!list_empty(&ctx.names)) {
282 struct name_list *entry; 287 struct name_list *entry;
283 entry = list_entry(names.next, struct name_list, list); 288 entry = list_entry(ctx.names.next, struct name_list, list);
284 if (!status) { 289 if (!status) {
285 struct dentry *dentry; 290 struct dentry *dentry;
286 dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); 291 dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 84ce601d8063..f939ba9bf8e8 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1912,6 +1912,7 @@ struct buffered_dirent {
1912}; 1912};
1913 1913
1914struct readdir_data { 1914struct readdir_data {
1915 struct dir_context ctx;
1915 char *dirent; 1916 char *dirent;
1916 size_t used; 1917 size_t used;
1917 int full; 1918 int full;
@@ -1949,6 +1950,7 @@ static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func,
1949 int size; 1950 int size;
1950 loff_t offset; 1951 loff_t offset;
1951 1952
1953 buf.ctx.actor = nfsd_buffered_filldir;
1952 buf.dirent = (void *)__get_free_page(GFP_KERNEL); 1954 buf.dirent = (void *)__get_free_page(GFP_KERNEL);
1953 if (!buf.dirent) 1955 if (!buf.dirent)
1954 return nfserrno(-ENOMEM); 1956 return nfserrno(-ENOMEM);
@@ -1963,7 +1965,7 @@ static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func,
1963 buf.used = 0; 1965 buf.used = 0;
1964 buf.full = 0; 1966 buf.full = 0;
1965 1967
1966 host_err = vfs_readdir(file, nfsd_buffered_filldir, &buf); 1968 host_err = iterate_dir(file, &buf.ctx);
1967 if (buf.full) 1969 if (buf.full)
1968 host_err = 0; 1970 host_err = 0;
1969 1971
diff --git a/fs/readdir.c b/fs/readdir.c
index fee38e04fae4..5b620a2b45e6 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -20,7 +20,7 @@
20 20
21#include <asm/uaccess.h> 21#include <asm/uaccess.h>
22 22
23int vfs_readdir(struct file *file, filldir_t filler, void *buf) 23int iterate_dir(struct file *file, struct dir_context *ctx)
24{ 24{
25 struct inode *inode = file_inode(file); 25 struct inode *inode = file_inode(file);
26 int res = -ENOTDIR; 26 int res = -ENOTDIR;
@@ -37,15 +37,14 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf)
37 37
38 res = -ENOENT; 38 res = -ENOENT;
39 if (!IS_DEADDIR(inode)) { 39 if (!IS_DEADDIR(inode)) {
40 res = file->f_op->readdir(file, buf, filler); 40 res = file->f_op->readdir(file, ctx, ctx->actor);
41 file_accessed(file); 41 file_accessed(file);
42 } 42 }
43 mutex_unlock(&inode->i_mutex); 43 mutex_unlock(&inode->i_mutex);
44out: 44out:
45 return res; 45 return res;
46} 46}
47 47EXPORT_SYMBOL(iterate_dir);
48EXPORT_SYMBOL(vfs_readdir);
49 48
50/* 49/*
51 * Traditional linux readdir() handling.. 50 * Traditional linux readdir() handling..
@@ -66,6 +65,7 @@ struct old_linux_dirent {
66}; 65};
67 66
68struct readdir_callback { 67struct readdir_callback {
68 struct dir_context ctx;
69 struct old_linux_dirent __user * dirent; 69 struct old_linux_dirent __user * dirent;
70 int result; 70 int result;
71}; 71};
@@ -73,7 +73,7 @@ struct readdir_callback {
73static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, 73static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset,
74 u64 ino, unsigned int d_type) 74 u64 ino, unsigned int d_type)
75{ 75{
76 struct readdir_callback * buf = (struct readdir_callback *) __buf; 76 struct readdir_callback *buf = (struct readdir_callback *) __buf;
77 struct old_linux_dirent __user * dirent; 77 struct old_linux_dirent __user * dirent;
78 unsigned long d_ino; 78 unsigned long d_ino;
79 79
@@ -112,10 +112,11 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
112 if (!f.file) 112 if (!f.file)
113 return -EBADF; 113 return -EBADF;
114 114
115 buf.ctx.actor = fillonedir;
115 buf.result = 0; 116 buf.result = 0;
116 buf.dirent = dirent; 117 buf.dirent = dirent;
117 118
118 error = vfs_readdir(f.file, fillonedir, &buf); 119 error = iterate_dir(f.file, &buf.ctx);
119 if (buf.result) 120 if (buf.result)
120 error = buf.result; 121 error = buf.result;
121 122
@@ -137,6 +138,7 @@ struct linux_dirent {
137}; 138};
138 139
139struct getdents_callback { 140struct getdents_callback {
141 struct dir_context ctx;
140 struct linux_dirent __user * current_dir; 142 struct linux_dirent __user * current_dir;
141 struct linux_dirent __user * previous; 143 struct linux_dirent __user * previous;
142 int count; 144 int count;
@@ -205,8 +207,9 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
205 buf.previous = NULL; 207 buf.previous = NULL;
206 buf.count = count; 208 buf.count = count;
207 buf.error = 0; 209 buf.error = 0;
210 buf.ctx.actor = filldir;
208 211
209 error = vfs_readdir(f.file, filldir, &buf); 212 error = iterate_dir(f.file, &buf.ctx);
210 if (error >= 0) 213 if (error >= 0)
211 error = buf.error; 214 error = buf.error;
212 lastdirent = buf.previous; 215 lastdirent = buf.previous;
@@ -221,6 +224,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
221} 224}
222 225
223struct getdents_callback64 { 226struct getdents_callback64 {
227 struct dir_context ctx;
224 struct linux_dirent64 __user * current_dir; 228 struct linux_dirent64 __user * current_dir;
225 struct linux_dirent64 __user * previous; 229 struct linux_dirent64 __user * previous;
226 int count; 230 int count;
@@ -285,8 +289,9 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
285 buf.previous = NULL; 289 buf.previous = NULL;
286 buf.count = count; 290 buf.count = count;
287 buf.error = 0; 291 buf.error = 0;
292 buf.ctx.actor = filldir64;
288 293
289 error = vfs_readdir(f.file, filldir64, &buf); 294 error = iterate_dir(f.file, &buf.ctx);
290 if (error >= 0) 295 if (error >= 0)
291 error = buf.error; 296 error = buf.error;
292 lastdirent = buf.previous; 297 lastdirent = buf.previous;