summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-05-14 20:15:04 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-05-14 20:15:04 -0700
commit9ca0507d7f249ae16cc29cfe4f7c1e8f7bbd73dd (patch)
tree184bf826b4a78099aa5fb6ca05a69ec6545d14a2
parent340a9772c8484ff4cff6e654c823dc4f267489b9 (diff)
[PATCH] autofs4: readdir futureproofing
From: Ian Kent <raven@themaw.net> Needed for support coming development plans.
-rw-r--r--fs/autofs4/autofs_i.h2
-rw-r--r--fs/autofs4/root.c73
-rw-r--r--include/linux/auto_fs4.h8
3 files changed, 79 insertions, 4 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index c7225d752adf..afb3456ccd2d 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -97,6 +97,8 @@ struct autofs_sb_info {
int version;
int sub_version;
unsigned long exp_timeout;
+ int reghost_enabled;
+ int needs_reghost;
struct super_block *sb;
struct autofs_wait_queue *queues; /* Wait queue pointer */
};
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index a5afb3104e79..98a63d3f8eb8 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -28,13 +28,15 @@ static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigne
static int autofs4_dir_open(struct inode *inode, struct file *file);
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_root_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,
.release = dcache_dir_close,
.read = generic_read_dir,
- .readdir = dcache_readdir,
+ .readdir = autofs4_root_readdir,
.ioctl = autofs4_root_ioctl,
};
@@ -61,12 +63,37 @@ struct inode_operations autofs4_dir_inode_operations = {
.rmdir = autofs4_dir_rmdir,
};
+static int autofs4_root_readdir(struct file *file, void *dirent,
+ filldir_t filldir)
+{
+ struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb);
+ int oz_mode = autofs4_oz_mode(sbi);
+
+ DPRINTK(("autofs4_root_readdir called, filp->f_pos = %lld\n",
+ file->f_pos));
+
+ /*
+ * Don't set reghost flag if:
+ * 1) f_pos is larger than zero -- we've already been here.
+ * 2) we haven't even enabled reghosting in the 1st place.
+ * 3) this is the daemon doing a readdir
+ */
+ if (oz_mode && file->f_pos == 0 && sbi->reghost_enabled)
+ sbi->needs_reghost = 1;
+
+ DPRINTK(("autofs4_root_readdir: needs_reghost = %d\n",
+ sbi->needs_reghost));
+
+ return autofs4_dcache_readdir(file, dirent, filldir);
+}
+
/* Update usage from here to top of tree, so that scan of
top-level directories will give a useful result */
static void autofs4_update_usage(struct dentry *dentry)
{
struct dentry *top = dentry->d_sb->s_root;
+ spin_lock(&dcache_lock);
for(; dentry != top; dentry = dentry->d_parent) {
struct autofs_info *ino = autofs4_dentry_ino(dentry);
@@ -75,6 +102,7 @@ static void autofs4_update_usage(struct dentry *dentry)
ino->last_used = jiffies;
}
}
+ spin_unlock(&dcache_lock);
}
/*
@@ -674,6 +702,44 @@ static inline int autofs4_get_protosubver(struct autofs_sb_info *sbi, int *p)
}
/*
+ * Tells the daemon whether we need to reghost or not. Also, clears
+ * the reghost_needed flag.
+ */
+static inline int autofs4_ask_reghost(struct autofs_sb_info *sbi, int *p)
+{
+ int status;
+
+ DPRINTK(("autofs_ask_reghost: returning %d\n", sbi->needs_reghost));
+
+ status = put_user(sbi->needs_reghost, p);
+ if ( status )
+ return status;
+
+ sbi->needs_reghost = 0;
+ return 0;
+}
+
+/*
+ * Enable / Disable reghosting ioctl() operation
+ */
+static inline int autofs4_toggle_reghost(struct autofs_sb_info *sbi, int *p)
+{
+ int status;
+ int val;
+
+ status = get_user(val, p);
+
+ DPRINTK(("autofs4_toggle_reghost: reghost = %d\n", val));
+
+ if (status)
+ return status;
+
+ /* turn on/off reghosting, with the val */
+ sbi->reghost_enabled = val;
+ return 0;
+}
+
+/*
* Tells the daemon whether it can umount the autofs mount.
*/
static inline int autofs4_ask_umount(struct vfsmount *mnt, int *p)
@@ -736,6 +802,11 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp,
case AUTOFS_IOC_SETTIMEOUT:
return autofs4_get_set_timeout(sbi,(unsigned long *)arg);
+ case AUTOFS_IOC_TOGGLEREGHOST:
+ return autofs4_toggle_reghost(sbi, (int *) arg);
+ case AUTOFS_IOC_ASKREGHOST:
+ return autofs4_ask_reghost(sbi, (int *) arg);
+
case AUTOFS_IOC_ASKUMOUNT:
return autofs4_ask_umount(filp->f_vfsmnt, (int *) arg);
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index b7ca600efa99..d1c7b0ec7c22 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -47,9 +47,11 @@ union autofs_packet_union {
struct autofs_packet_expire_multi expire_multi;
};
-#define AUTOFS_IOC_EXPIRE_MULTI _IOW(0x93,0x66,int)
-#define AUTOFS_IOC_PROTOSUBVER _IOR(0x93,0x67,int)
-#define AUTOFS_IOC_ASKUMOUNT _IOR(0x93,0x70,int)
+#define AUTOFS_IOC_EXPIRE_MULTI _IOW(0x93,0x66,int)
+#define AUTOFS_IOC_PROTOSUBVER _IOR(0x93,0x67,int)
+#define AUTOFS_IOC_ASKREGHOST _IOR(0x93,0x68,int)
+#define AUTOFS_IOC_TOGGLEREGHOST _IOR(0x93,0x69,int)
+#define AUTOFS_IOC_ASKUMOUNT _IOR(0x93,0x70,int)
#endif /* _LINUX_AUTO_FS4_H */