diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-15 13:52:59 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:46:46 -0400 |
commit | 5c0ba4e0762e6dabd14a5c276652e2defec38de7 (patch) | |
tree | cc2c94d81a631b0656782e1f8299da3267871964 /fs | |
parent | 83a8761142cb38536e9e88dfc2432d331ea4e257 (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.c | 12 | ||||
-rw-r--r-- | fs/ecryptfs/file.c | 4 | ||||
-rw-r--r-- | fs/exportfs/expfs.c | 4 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 13 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 4 | ||||
-rw-r--r-- | fs/readdir.c | 21 |
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 | ||
834 | struct compat_readdir_callback { | 834 | struct 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 | ||
899 | struct compat_getdents_callback { | 901 | struct 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 | ||
985 | struct compat_getdents_callback64 { | 989 | struct 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 | ||
70 | struct ecryptfs_getdents_callback { | 70 | struct 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 | ||
214 | struct getdents_callback { | 214 | struct 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 | ||
1914 | struct readdir_data { | 1914 | struct 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 | ||
23 | int vfs_readdir(struct file *file, filldir_t filler, void *buf) | 23 | int 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); |
44 | out: | 44 | out: |
45 | return res; | 45 | return res; |
46 | } | 46 | } |
47 | 47 | EXPORT_SYMBOL(iterate_dir); | |
48 | EXPORT_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 | ||
68 | struct readdir_callback { | 67 | struct 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 { | |||
73 | static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, | 73 | static 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 | ||
139 | struct getdents_callback { | 140 | struct 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 | ||
223 | struct getdents_callback64 { | 226 | struct 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; |