diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-05-15 20:23:06 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-06-29 04:46:48 -0400 |
commit | 5f99f4e79abc64ed9d93a4b0158b21c64ff7f478 (patch) | |
tree | bb76629861592bee919344521fb2d55ce866a17f | |
parent | 80886298c07234331458e963b5f9f57c68edd700 (diff) |
[readdir] switch dcache_readdir() users to ->iterate()
new helpers - dir_emit_dot(file, ctx, dentry), dir_emit_dotdot(file, ctx),
dir_emit_dots(file, ctx).
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 2 | ||||
-rw-r--r-- | fs/autofs4/root.c | 4 | ||||
-rw-r--r-- | fs/libfs.c | 80 | ||||
-rw-r--r-- | include/linux/fs.h | 39 |
4 files changed, 65 insertions, 60 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 35f77a42bedf..f3900427ffab 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -238,7 +238,7 @@ const struct file_operations spufs_context_fops = { | |||
238 | .release = spufs_dir_close, | 238 | .release = spufs_dir_close, |
239 | .llseek = dcache_dir_lseek, | 239 | .llseek = dcache_dir_lseek, |
240 | .read = generic_read_dir, | 240 | .read = generic_read_dir, |
241 | .readdir = dcache_readdir, | 241 | .iterate = dcache_readdir, |
242 | .fsync = noop_fsync, | 242 | .fsync = noop_fsync, |
243 | }; | 243 | }; |
244 | EXPORT_SYMBOL_GPL(spufs_context_fops); | 244 | EXPORT_SYMBOL_GPL(spufs_context_fops); |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 085da86e07c2..ca8e55548d98 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -41,7 +41,7 @@ const struct file_operations autofs4_root_operations = { | |||
41 | .open = dcache_dir_open, | 41 | .open = dcache_dir_open, |
42 | .release = dcache_dir_close, | 42 | .release = dcache_dir_close, |
43 | .read = generic_read_dir, | 43 | .read = generic_read_dir, |
44 | .readdir = dcache_readdir, | 44 | .iterate = dcache_readdir, |
45 | .llseek = dcache_dir_lseek, | 45 | .llseek = dcache_dir_lseek, |
46 | .unlocked_ioctl = autofs4_root_ioctl, | 46 | .unlocked_ioctl = autofs4_root_ioctl, |
47 | #ifdef CONFIG_COMPAT | 47 | #ifdef CONFIG_COMPAT |
@@ -53,7 +53,7 @@ const struct file_operations autofs4_dir_operations = { | |||
53 | .open = autofs4_dir_open, | 53 | .open = autofs4_dir_open, |
54 | .release = dcache_dir_close, | 54 | .release = dcache_dir_close, |
55 | .read = generic_read_dir, | 55 | .read = generic_read_dir, |
56 | .readdir = dcache_readdir, | 56 | .iterate = dcache_readdir, |
57 | .llseek = dcache_dir_lseek, | 57 | .llseek = dcache_dir_lseek, |
58 | }; | 58 | }; |
59 | 59 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index 916da8c4158b..c3a0837fb861 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -135,60 +135,40 @@ static inline unsigned char dt_type(struct inode *inode) | |||
135 | * both impossible due to the lock on directory. | 135 | * both impossible due to the lock on directory. |
136 | */ | 136 | */ |
137 | 137 | ||
138 | int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) | 138 | int dcache_readdir(struct file *file, struct dir_context *ctx) |
139 | { | 139 | { |
140 | struct dentry *dentry = filp->f_path.dentry; | 140 | struct dentry *dentry = file->f_path.dentry; |
141 | struct dentry *cursor = filp->private_data; | 141 | struct dentry *cursor = file->private_data; |
142 | struct list_head *p, *q = &cursor->d_u.d_child; | 142 | struct list_head *p, *q = &cursor->d_u.d_child; |
143 | ino_t ino; | ||
144 | int i = filp->f_pos; | ||
145 | 143 | ||
146 | switch (i) { | 144 | if (!dir_emit_dots(file, ctx)) |
147 | case 0: | 145 | return 0; |
148 | ino = dentry->d_inode->i_ino; | 146 | spin_lock(&dentry->d_lock); |
149 | if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) | 147 | if (ctx->pos == 2) |
150 | break; | 148 | list_move(q, &dentry->d_subdirs); |
151 | filp->f_pos++; | 149 | |
152 | i++; | 150 | for (p = q->next; p != &dentry->d_subdirs; p = p->next) { |
153 | /* fallthrough */ | 151 | struct dentry *next = list_entry(p, struct dentry, d_u.d_child); |
154 | case 1: | 152 | spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); |
155 | ino = parent_ino(dentry); | 153 | if (!simple_positive(next)) { |
156 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | 154 | spin_unlock(&next->d_lock); |
157 | break; | 155 | continue; |
158 | filp->f_pos++; | 156 | } |
159 | i++; | ||
160 | /* fallthrough */ | ||
161 | default: | ||
162 | spin_lock(&dentry->d_lock); | ||
163 | if (filp->f_pos == 2) | ||
164 | list_move(q, &dentry->d_subdirs); | ||
165 | |||
166 | for (p=q->next; p != &dentry->d_subdirs; p=p->next) { | ||
167 | struct dentry *next; | ||
168 | next = list_entry(p, struct dentry, d_u.d_child); | ||
169 | spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); | ||
170 | if (!simple_positive(next)) { | ||
171 | spin_unlock(&next->d_lock); | ||
172 | continue; | ||
173 | } | ||
174 | 157 | ||
175 | spin_unlock(&next->d_lock); | 158 | spin_unlock(&next->d_lock); |
176 | spin_unlock(&dentry->d_lock); | 159 | spin_unlock(&dentry->d_lock); |
177 | if (filldir(dirent, next->d_name.name, | 160 | if (!dir_emit(ctx, next->d_name.name, next->d_name.len, |
178 | next->d_name.len, filp->f_pos, | 161 | next->d_inode->i_ino, dt_type(next->d_inode))) |
179 | next->d_inode->i_ino, | 162 | return 0; |
180 | dt_type(next->d_inode)) < 0) | 163 | spin_lock(&dentry->d_lock); |
181 | return 0; | 164 | spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); |
182 | spin_lock(&dentry->d_lock); | 165 | /* next is still alive */ |
183 | spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED); | 166 | list_move(q, p); |
184 | /* next is still alive */ | 167 | spin_unlock(&next->d_lock); |
185 | list_move(q, p); | 168 | p = q; |
186 | spin_unlock(&next->d_lock); | 169 | ctx->pos++; |
187 | p = q; | ||
188 | filp->f_pos++; | ||
189 | } | ||
190 | spin_unlock(&dentry->d_lock); | ||
191 | } | 170 | } |
171 | spin_unlock(&dentry->d_lock); | ||
192 | return 0; | 172 | return 0; |
193 | } | 173 | } |
194 | 174 | ||
@@ -202,7 +182,7 @@ const struct file_operations simple_dir_operations = { | |||
202 | .release = dcache_dir_close, | 182 | .release = dcache_dir_close, |
203 | .llseek = dcache_dir_lseek, | 183 | .llseek = dcache_dir_lseek, |
204 | .read = generic_read_dir, | 184 | .read = generic_read_dir, |
205 | .readdir = dcache_readdir, | 185 | .iterate = dcache_readdir, |
206 | .fsync = noop_fsync, | 186 | .fsync = noop_fsync, |
207 | }; | 187 | }; |
208 | 188 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index b9641ae68da8..40293a6ce804 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1511,12 +1511,6 @@ struct dir_context { | |||
1511 | loff_t pos; | 1511 | loff_t pos; |
1512 | }; | 1512 | }; |
1513 | 1513 | ||
1514 | static inline bool dir_emit(struct dir_context *ctx, | ||
1515 | const char *name, int namelen, | ||
1516 | u64 ino, unsigned type) | ||
1517 | { | ||
1518 | return ctx->actor(ctx, name, namelen, ctx->pos, ino, type) == 0; | ||
1519 | } | ||
1520 | struct block_device_operations; | 1514 | struct block_device_operations; |
1521 | 1515 | ||
1522 | /* These macros are for out of kernel modules to test that | 1516 | /* These macros are for out of kernel modules to test that |
@@ -2537,7 +2531,7 @@ extern void iterate_supers_type(struct file_system_type *, | |||
2537 | extern int dcache_dir_open(struct inode *, struct file *); | 2531 | extern int dcache_dir_open(struct inode *, struct file *); |
2538 | extern int dcache_dir_close(struct inode *, struct file *); | 2532 | extern int dcache_dir_close(struct inode *, struct file *); |
2539 | extern loff_t dcache_dir_lseek(struct file *, loff_t, int); | 2533 | extern loff_t dcache_dir_lseek(struct file *, loff_t, int); |
2540 | extern int dcache_readdir(struct file *, void *, filldir_t); | 2534 | extern int dcache_readdir(struct file *, struct dir_context *); |
2541 | extern int simple_setattr(struct dentry *, struct iattr *); | 2535 | extern int simple_setattr(struct dentry *, struct iattr *); |
2542 | extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 2536 | extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
2543 | extern int simple_statfs(struct dentry *, struct kstatfs *); | 2537 | extern int simple_statfs(struct dentry *, struct kstatfs *); |
@@ -2701,4 +2695,35 @@ static inline void inode_has_no_xattr(struct inode *inode) | |||
2701 | inode->i_flags |= S_NOSEC; | 2695 | inode->i_flags |= S_NOSEC; |
2702 | } | 2696 | } |
2703 | 2697 | ||
2698 | static inline bool dir_emit(struct dir_context *ctx, | ||
2699 | const char *name, int namelen, | ||
2700 | u64 ino, unsigned type) | ||
2701 | { | ||
2702 | return ctx->actor(ctx, name, namelen, ctx->pos, ino, type) == 0; | ||
2703 | } | ||
2704 | static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx) | ||
2705 | { | ||
2706 | return ctx->actor(ctx, ".", 1, ctx->pos, | ||
2707 | file->f_path.dentry->d_inode->i_ino, DT_DIR) == 0; | ||
2708 | } | ||
2709 | static inline bool dir_emit_dotdot(struct file *file, struct dir_context *ctx) | ||
2710 | { | ||
2711 | return ctx->actor(ctx, "..", 2, ctx->pos, | ||
2712 | parent_ino(file->f_path.dentry), DT_DIR) == 0; | ||
2713 | } | ||
2714 | static inline bool dir_emit_dots(struct file *file, struct dir_context *ctx) | ||
2715 | { | ||
2716 | if (ctx->pos == 0) { | ||
2717 | if (!dir_emit_dot(file, ctx)) | ||
2718 | return false; | ||
2719 | ctx->pos = 1; | ||
2720 | } | ||
2721 | if (ctx->pos == 1) { | ||
2722 | if (!dir_emit_dotdot(file, ctx)) | ||
2723 | return false; | ||
2724 | ctx->pos = 2; | ||
2725 | } | ||
2726 | return true; | ||
2727 | } | ||
2728 | |||
2704 | #endif /* _LINUX_FS_H */ | 2729 | #endif /* _LINUX_FS_H */ |