Skip to content

Commit

Permalink
[PATCH] autofs4: use libfs routines for readdir
Browse files Browse the repository at this point in the history
Change readdir routines to use the cursor based routines in libfs.c.  This
removes reliance on old readdir code from 2.4 and should improve efficiency of
readdir in autofs4.

Signed-off-by: Ian Kent <raven@themaw.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Ian Kent authored and Linus Torvalds committed Mar 27, 2006
1 parent 718c604 commit f360ce3
Showing 1 changed file with 40 additions and 86 deletions.
126 changes: 40 additions & 86 deletions fs/autofs4/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ static int autofs4_dir_close(struct inode *inode, struct file *file);
static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir);
static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir);
static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
static int autofs4_dcache_readdir(struct file *, void *, filldir_t);

struct file_operations autofs4_root_operations = {
.open = dcache_dir_open,
Expand Down Expand Up @@ -82,7 +81,7 @@ static int autofs4_root_readdir(struct file *file, void *dirent,

DPRINTK("needs_reghost = %d", sbi->needs_reghost);

return autofs4_dcache_readdir(file, dirent, filldir);
return dcache_readdir(file, dirent, filldir);
}

/* Update usage from here to top of tree, so that scan of
Expand All @@ -103,75 +102,21 @@ static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry)
spin_unlock(&dcache_lock);
}

/*
* From 2.4 kernel readdir.c
*/
static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
int i;
struct dentry *dentry = filp->f_dentry;

i = filp->f_pos;
switch (i) {
case 0:
if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino, DT_DIR) < 0)
break;
i++;
filp->f_pos++;
/* fallthrough */
case 1:
if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
break;
i++;
filp->f_pos++;
/* fallthrough */
default: {
struct list_head *list;
int j = i-2;

spin_lock(&dcache_lock);
list = dentry->d_subdirs.next;

for (;;) {
if (list == &dentry->d_subdirs) {
spin_unlock(&dcache_lock);
return 0;
}
if (!j)
break;
j--;
list = list->next;
}

while(1) {
struct dentry *de = list_entry(list,
struct dentry, d_u.d_child);

if (!d_unhashed(de) && de->d_inode) {
spin_unlock(&dcache_lock);
if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0)
break;
spin_lock(&dcache_lock);
}
filp->f_pos++;
list = list->next;
if (list != &dentry->d_subdirs)
continue;
spin_unlock(&dcache_lock);
break;
}
}
}
return 0;
}

static int autofs4_dir_open(struct inode *inode, struct file *file)
{
struct dentry *dentry = file->f_dentry;
struct vfsmount *mnt = file->f_vfsmnt;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *cursor;
int status;

status = dcache_dir_open(inode, file);
if (status)
goto out;

cursor = file->private_data;
cursor->d_fsdata = NULL;

DPRINTK("file=%p dentry=%p %.*s",
file, dentry, dentry->d_name.len, dentry->d_name.name);

Expand All @@ -180,12 +125,15 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)

if (autofs4_ispending(dentry)) {
DPRINTK("dentry busy");
return -EBUSY;
dcache_dir_close(inode, file);
status = -EBUSY;
goto out;
}

status = -ENOENT;
if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
struct nameidata nd;
int empty;
int empty, ret;

/* In case there are stale directory dentrys from a failed mount */
spin_lock(&dcache_lock);
Expand All @@ -195,13 +143,13 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (!empty)
d_invalidate(dentry);

nd.dentry = dentry;
nd.mnt = mnt;
nd.flags = LOOKUP_DIRECTORY;
status = (dentry->d_op->d_revalidate)(dentry, &nd);
ret = (dentry->d_op->d_revalidate)(dentry, &nd);

if (!status)
return -ENOENT;
if (!ret) {
dcache_dir_close(inode, file);
goto out;
}
}

if (d_mountpoint(dentry)) {
Expand All @@ -212,25 +160,29 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
dput(fp_dentry);
mntput(fp_mnt);
return -ENOENT;
dcache_dir_close(inode, file);
goto out;
}

fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
status = PTR_ERR(fp);
if (IS_ERR(fp)) {
file->private_data = NULL;
return status;
dcache_dir_close(inode, file);
goto out;
}
file->private_data = fp;
cursor->d_fsdata = fp;
}
out:
return 0;
out:
return status;
}

static int autofs4_dir_close(struct inode *inode, struct file *file)
{
struct dentry *dentry = file->f_dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *cursor = file->private_data;
int status = 0;

DPRINTK("file=%p dentry=%p %.*s",
file, dentry, dentry->d_name.len, dentry->d_name.name);
Expand All @@ -240,26 +192,28 @@ static int autofs4_dir_close(struct inode *inode, struct file *file)

if (autofs4_ispending(dentry)) {
DPRINTK("dentry busy");
return -EBUSY;
status = -EBUSY;
goto out;
}

if (d_mountpoint(dentry)) {
struct file *fp = file->private_data;

if (!fp)
return -ENOENT;

struct file *fp = cursor->d_fsdata;
if (!fp) {
status = -ENOENT;
goto out;
}
filp_close(fp, current->files);
file->private_data = NULL;
}
out:
return 0;
dcache_dir_close(inode, file);
return status;
}

static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir)
{
struct dentry *dentry = file->f_dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *cursor = file->private_data;
int status;

DPRINTK("file=%p dentry=%p %.*s",
Expand All @@ -274,7 +228,7 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi
}

if (d_mountpoint(dentry)) {
struct file *fp = file->private_data;
struct file *fp = cursor->d_fsdata;

if (!fp)
return -ENOENT;
Expand All @@ -289,7 +243,7 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi
return status;
}
out:
return autofs4_dcache_readdir(file, dirent, filldir);
return dcache_readdir(file, dirent, filldir);
}

static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags)
Expand Down

0 comments on commit f360ce3

Please sign in to comment.