[readdir] convert coda
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
3704412bdb
Коммит
e924f25126
|
@ -43,15 +43,14 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
|
|||
struct inode *new_inode, struct dentry *new_dentry);
|
||||
|
||||
/* 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 */
|
||||
static int coda_dentry_revalidate(struct dentry *de, unsigned int flags);
|
||||
static int coda_dentry_delete(const struct dentry *);
|
||||
|
||||
/* support routines */
|
||||
static int coda_venus_readdir(struct file *coda_file, void *buf,
|
||||
filldir_t filldir);
|
||||
static int coda_venus_readdir(struct file *, struct dir_context *);
|
||||
|
||||
/* same as fs/bad_inode.c */
|
||||
static int coda_return_EIO(void)
|
||||
|
@ -85,7 +84,7 @@ const struct inode_operations coda_dir_inode_operations =
|
|||
const struct file_operations coda_dir_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = generic_read_dir,
|
||||
.readdir = coda_readdir,
|
||||
.iterate = coda_readdir,
|
||||
.open = coda_open,
|
||||
.release = coda_release,
|
||||
.fsync = coda_fsync,
|
||||
|
@ -378,7 +377,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
|
||||
|
||||
/* 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 file *host_file;
|
||||
|
@ -391,28 +390,8 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
|
|||
if (!host_file->f_op)
|
||||
return -ENOTDIR;
|
||||
|
||||
if (host_file->f_op->readdir) {
|
||||
/* 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. */
|
||||
if (host_file->f_op->iterate) {
|
||||
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);
|
||||
ret = -ENOENT;
|
||||
if (!IS_DEADDIR(host_inode)) {
|
||||
|
@ -420,12 +399,10 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
|
|||
file_accessed(host_file);
|
||||
}
|
||||
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)
|
||||
|
@ -448,10 +425,8 @@ static inline unsigned int CDT2DT(unsigned char cdt)
|
|||
}
|
||||
|
||||
/* support routines */
|
||||
static int coda_venus_readdir(struct file *coda_file, void *buf,
|
||||
filldir_t filldir)
|
||||
static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
|
||||
{
|
||||
int result = 0; /* # of entries returned */
|
||||
struct coda_file_info *cfi;
|
||||
struct coda_inode_info *cii;
|
||||
struct file *host_file;
|
||||
|
@ -473,23 +448,12 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
|
|||
vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
|
||||
if (!vdir) return -ENOMEM;
|
||||
|
||||
if (coda_file->f_pos == 0) {
|
||||
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;
|
||||
result++;
|
||||
coda_file->f_pos++;
|
||||
}
|
||||
if (!dir_emit_dots(coda_file, ctx))
|
||||
goto out;
|
||||
|
||||
while (1) {
|
||||
/* 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));
|
||||
if (ret < 0) {
|
||||
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,
|
|||
|
||||
/* Make sure we skip '.' and '..', we already got those */
|
||||
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;
|
||||
|
||||
/* skip null entries */
|
||||
|
@ -531,19 +495,16 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
|
|||
if (!ino) ino = vdir->d_fileno;
|
||||
|
||||
type = CDT2DT(vdir->d_type);
|
||||
ret = filldir(buf, name.name, name.len,
|
||||
coda_file->f_pos, ino, type);
|
||||
/* failure means no space for filling in this round */
|
||||
if (ret < 0) break;
|
||||
result++;
|
||||
if (!dir_emit(ctx, name.name, name.len, ino, type))
|
||||
break;
|
||||
}
|
||||
/* we'll always have progress because d_reclen is unsigned and
|
||||
* we've already established it is non-zero. */
|
||||
coda_file->f_pos += vdir->d_reclen;
|
||||
ctx->pos += vdir->d_reclen;
|
||||
}
|
||||
out:
|
||||
kfree(vdir);
|
||||
return result ? result : ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called when a cache lookup succeeds */
|
||||
|
|
Загрузка…
Ссылка в новой задаче