aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-05-15 20:23:06 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-06-29 04:46:48 -0400
commit5f99f4e79abc64ed9d93a4b0158b21c64ff7f478 (patch)
treebb76629861592bee919344521fb2d55ce866a17f
parent80886298c07234331458e963b5f9f57c68edd700 (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.c2
-rw-r--r--fs/autofs4/root.c4
-rw-r--r--fs/libfs.c80
-rw-r--r--include/linux/fs.h39
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};
244EXPORT_SYMBOL_GPL(spufs_context_fops); 244EXPORT_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
138int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) 138int 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
1514static 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}
1520struct block_device_operations; 1514struct 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 *,
2537extern int dcache_dir_open(struct inode *, struct file *); 2531extern int dcache_dir_open(struct inode *, struct file *);
2538extern int dcache_dir_close(struct inode *, struct file *); 2532extern int dcache_dir_close(struct inode *, struct file *);
2539extern loff_t dcache_dir_lseek(struct file *, loff_t, int); 2533extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
2540extern int dcache_readdir(struct file *, void *, filldir_t); 2534extern int dcache_readdir(struct file *, struct dir_context *);
2541extern int simple_setattr(struct dentry *, struct iattr *); 2535extern int simple_setattr(struct dentry *, struct iattr *);
2542extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); 2536extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
2543extern int simple_statfs(struct dentry *, struct kstatfs *); 2537extern 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
2698static 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}
2704static 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}
2709static 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}
2714static 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 */