|
@@ -135,60 +135,40 @@ static inline unsigned char dt_type(struct inode *inode)
|
|
|
* both impossible due to the lock on directory.
|
|
|
*/
|
|
|
|
|
|
-int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
|
|
+int dcache_readdir(struct file *file, struct dir_context *ctx)
|
|
|
{
|
|
|
- struct dentry *dentry = filp->f_path.dentry;
|
|
|
- struct dentry *cursor = filp->private_data;
|
|
|
+ struct dentry *dentry = file->f_path.dentry;
|
|
|
+ struct dentry *cursor = file->private_data;
|
|
|
struct list_head *p, *q = &cursor->d_u.d_child;
|
|
|
- ino_t ino;
|
|
|
- int i = filp->f_pos;
|
|
|
|
|
|
- switch (i) {
|
|
|
- case 0:
|
|
|
- ino = dentry->d_inode->i_ino;
|
|
|
- if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
|
|
|
- break;
|
|
|
- filp->f_pos++;
|
|
|
- i++;
|
|
|
- /* fallthrough */
|
|
|
- case 1:
|
|
|
- ino = parent_ino(dentry);
|
|
|
- if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
|
|
|
- break;
|
|
|
- filp->f_pos++;
|
|
|
- i++;
|
|
|
- /* fallthrough */
|
|
|
- default:
|
|
|
- spin_lock(&dentry->d_lock);
|
|
|
- if (filp->f_pos == 2)
|
|
|
- list_move(q, &dentry->d_subdirs);
|
|
|
-
|
|
|
- for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
|
|
|
- struct dentry *next;
|
|
|
- next = list_entry(p, struct dentry, d_u.d_child);
|
|
|
- spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
|
|
|
- if (!simple_positive(next)) {
|
|
|
- spin_unlock(&next->d_lock);
|
|
|
- continue;
|
|
|
- }
|
|
|
+ if (!dir_emit_dots(file, ctx))
|
|
|
+ return 0;
|
|
|
+ spin_lock(&dentry->d_lock);
|
|
|
+ if (ctx->pos == 2)
|
|
|
+ list_move(q, &dentry->d_subdirs);
|
|
|
+
|
|
|
+ for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
|
|
|
+ struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
|
|
|
+ spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
|
|
|
+ if (!simple_positive(next)) {
|
|
|
+ spin_unlock(&next->d_lock);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- spin_unlock(&next->d_lock);
|
|
|
- spin_unlock(&dentry->d_lock);
|
|
|
- if (filldir(dirent, next->d_name.name,
|
|
|
- next->d_name.len, filp->f_pos,
|
|
|
- next->d_inode->i_ino,
|
|
|
- dt_type(next->d_inode)) < 0)
|
|
|
- return 0;
|
|
|
- spin_lock(&dentry->d_lock);
|
|
|
- spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
|
|
|
- /* next is still alive */
|
|
|
- list_move(q, p);
|
|
|
- spin_unlock(&next->d_lock);
|
|
|
- p = q;
|
|
|
- filp->f_pos++;
|
|
|
- }
|
|
|
- spin_unlock(&dentry->d_lock);
|
|
|
+ spin_unlock(&next->d_lock);
|
|
|
+ spin_unlock(&dentry->d_lock);
|
|
|
+ if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
|
|
|
+ next->d_inode->i_ino, dt_type(next->d_inode)))
|
|
|
+ return 0;
|
|
|
+ spin_lock(&dentry->d_lock);
|
|
|
+ spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
|
|
|
+ /* next is still alive */
|
|
|
+ list_move(q, p);
|
|
|
+ spin_unlock(&next->d_lock);
|
|
|
+ p = q;
|
|
|
+ ctx->pos++;
|
|
|
}
|
|
|
+ spin_unlock(&dentry->d_lock);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -202,7 +182,7 @@ const struct file_operations simple_dir_operations = {
|
|
|
.release = dcache_dir_close,
|
|
|
.llseek = dcache_dir_lseek,
|
|
|
.read = generic_read_dir,
|
|
|
- .readdir = dcache_readdir,
|
|
|
+ .iterate = dcache_readdir,
|
|
|
.fsync = noop_fsync,
|
|
|
};
|
|
|
|