Commit e924f251 authored by Al Viro's avatar Al Viro

[readdir] convert coda

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3704412b
...@@ -43,15 +43,14 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, ...@@ -43,15 +43,14 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry); struct inode *new_inode, struct dentry *new_dentry);
/* dir file-ops */ /* dir file-ops */
static int coda_readdir(struct file *file, void *buf, filldir_t filldir); static int coda_readdir(struct file *file, struct dir_context *ctx);
/* dentry ops */ /* dentry ops */
static int coda_dentry_revalidate(struct dentry *de, unsigned int flags); static int coda_dentry_revalidate(struct dentry *de, unsigned int flags);
static int coda_dentry_delete(const struct dentry *); static int coda_dentry_delete(const struct dentry *);
/* support routines */ /* support routines */
static int coda_venus_readdir(struct file *coda_file, void *buf, static int coda_venus_readdir(struct file *, struct dir_context *);
filldir_t filldir);
/* same as fs/bad_inode.c */ /* same as fs/bad_inode.c */
static int coda_return_EIO(void) static int coda_return_EIO(void)
...@@ -85,7 +84,7 @@ const struct inode_operations coda_dir_inode_operations = ...@@ -85,7 +84,7 @@ const struct inode_operations coda_dir_inode_operations =
const struct file_operations coda_dir_operations = { const struct file_operations coda_dir_operations = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = coda_readdir, .iterate = coda_readdir,
.open = coda_open, .open = coda_open,
.release = coda_release, .release = coda_release,
.fsync = coda_fsync, .fsync = coda_fsync,
...@@ -378,7 +377,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -378,7 +377,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
/* file operations for directories */ /* file operations for directories */
static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir) static int coda_readdir(struct file *coda_file, struct dir_context *ctx)
{ {
struct coda_file_info *cfi; struct coda_file_info *cfi;
struct file *host_file; struct file *host_file;
...@@ -391,28 +390,8 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir) ...@@ -391,28 +390,8 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
if (!host_file->f_op) if (!host_file->f_op)
return -ENOTDIR; return -ENOTDIR;
if (host_file->f_op->readdir) { if (host_file->f_op->iterate) {
/* potemkin case: we were handed a directory inode.
* We can't use vfs_readdir because we have to keep the file
* position in sync between the coda_file and the host_file.
* and as such we need grab the inode mutex. */
struct inode *host_inode = file_inode(host_file); struct inode *host_inode = file_inode(host_file);
mutex_lock(&host_inode->i_mutex);
host_file->f_pos = coda_file->f_pos;
ret = -ENOENT;
if (!IS_DEADDIR(host_inode)) {
ret = host_file->f_op->readdir(host_file, buf, filldir);
file_accessed(host_file);
}
coda_file->f_pos = host_file->f_pos;
mutex_unlock(&host_inode->i_mutex);
} else if (host_file->f_op->iterate) {
struct inode *host_inode = file_inode(host_file);
struct dir_context *ctx = buf;
mutex_lock(&host_inode->i_mutex); mutex_lock(&host_inode->i_mutex);
ret = -ENOENT; ret = -ENOENT;
if (!IS_DEADDIR(host_inode)) { if (!IS_DEADDIR(host_inode)) {
...@@ -420,12 +399,10 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir) ...@@ -420,12 +399,10 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
file_accessed(host_file); file_accessed(host_file);
} }
mutex_unlock(&host_inode->i_mutex); mutex_unlock(&host_inode->i_mutex);
coda_file->f_pos = ctx->pos;
} else /* Venus: we must read Venus dirents from a file */
ret = coda_venus_readdir(coda_file, buf, filldir);
return ret; return ret;
}
/* Venus: we must read Venus dirents from a file */
return coda_venus_readdir(coda_file, ctx);
} }
static inline unsigned int CDT2DT(unsigned char cdt) static inline unsigned int CDT2DT(unsigned char cdt)
...@@ -448,10 +425,8 @@ static inline unsigned int CDT2DT(unsigned char cdt) ...@@ -448,10 +425,8 @@ static inline unsigned int CDT2DT(unsigned char cdt)
} }
/* support routines */ /* support routines */
static int coda_venus_readdir(struct file *coda_file, void *buf, static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
filldir_t filldir)
{ {
int result = 0; /* # of entries returned */
struct coda_file_info *cfi; struct coda_file_info *cfi;
struct coda_inode_info *cii; struct coda_inode_info *cii;
struct file *host_file; struct file *host_file;
...@@ -473,23 +448,12 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, ...@@ -473,23 +448,12 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
vdir = kmalloc(sizeof(*vdir), GFP_KERNEL); vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
if (!vdir) return -ENOMEM; if (!vdir) return -ENOMEM;
if (coda_file->f_pos == 0) { if (!dir_emit_dots(coda_file, ctx))
ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR);
if (ret < 0)
goto out;
result++;
coda_file->f_pos++;
}
if (coda_file->f_pos == 1) {
ret = filldir(buf, "..", 2, 1, parent_ino(de), DT_DIR);
if (ret < 0)
goto out; goto out;
result++;
coda_file->f_pos++;
}
while (1) { while (1) {
/* read entries from the directory file */ /* read entries from the directory file */
ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir, ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir,
sizeof(*vdir)); sizeof(*vdir));
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "coda readdir: read dir %s failed %d\n", printk(KERN_ERR "coda readdir: read dir %s failed %d\n",
...@@ -518,7 +482,7 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, ...@@ -518,7 +482,7 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
/* Make sure we skip '.' and '..', we already got those */ /* Make sure we skip '.' and '..', we already got those */
if (name.name[0] == '.' && (name.len == 1 || if (name.name[0] == '.' && (name.len == 1 ||
(vdir->d_name[1] == '.' && name.len == 2))) (name.name[1] == '.' && name.len == 2)))
vdir->d_fileno = name.len = 0; vdir->d_fileno = name.len = 0;
/* skip null entries */ /* skip null entries */
...@@ -531,19 +495,16 @@ static int coda_venus_readdir(struct file *coda_file, void *buf, ...@@ -531,19 +495,16 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
if (!ino) ino = vdir->d_fileno; if (!ino) ino = vdir->d_fileno;
type = CDT2DT(vdir->d_type); type = CDT2DT(vdir->d_type);
ret = filldir(buf, name.name, name.len, if (!dir_emit(ctx, name.name, name.len, ino, type))
coda_file->f_pos, ino, type); break;
/* failure means no space for filling in this round */
if (ret < 0) break;
result++;
} }
/* we'll always have progress because d_reclen is unsigned and /* we'll always have progress because d_reclen is unsigned and
* we've already established it is non-zero. */ * we've already established it is non-zero. */
coda_file->f_pos += vdir->d_reclen; ctx->pos += vdir->d_reclen;
} }
out: out:
kfree(vdir); kfree(vdir);
return result ? result : ret; return 0;
} }
/* called when a cache lookup succeeds */ /* called when a cache lookup succeeds */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment