diff options
Diffstat (limited to 'fs/autofs4/root.c')
-rw-r--r-- | fs/autofs4/root.c | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 109a6c606d92..cb1bd38dc08c 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -18,13 +18,17 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/param.h> | 19 | #include <linux/param.h> |
20 | #include <linux/time.h> | 20 | #include <linux/time.h> |
21 | #include <linux/compat.h> | ||
22 | #include <linux/smp_lock.h> | ||
23 | |||
21 | #include "autofs_i.h" | 24 | #include "autofs_i.h" |
22 | 25 | ||
23 | static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *); | 26 | static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *); |
24 | static int autofs4_dir_unlink(struct inode *,struct dentry *); | 27 | static int autofs4_dir_unlink(struct inode *,struct dentry *); |
25 | static int autofs4_dir_rmdir(struct inode *,struct dentry *); | 28 | static int autofs4_dir_rmdir(struct inode *,struct dentry *); |
26 | static int autofs4_dir_mkdir(struct inode *,struct dentry *,int); | 29 | static int autofs4_dir_mkdir(struct inode *,struct dentry *,int); |
27 | static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); | 30 | static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long); |
31 | static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long); | ||
28 | static int autofs4_dir_open(struct inode *inode, struct file *file); | 32 | static int autofs4_dir_open(struct inode *inode, struct file *file); |
29 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 33 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
30 | static void *autofs4_follow_link(struct dentry *, struct nameidata *); | 34 | static void *autofs4_follow_link(struct dentry *, struct nameidata *); |
@@ -38,7 +42,10 @@ const struct file_operations autofs4_root_operations = { | |||
38 | .read = generic_read_dir, | 42 | .read = generic_read_dir, |
39 | .readdir = dcache_readdir, | 43 | .readdir = dcache_readdir, |
40 | .llseek = dcache_dir_lseek, | 44 | .llseek = dcache_dir_lseek, |
41 | .ioctl = autofs4_root_ioctl, | 45 | .unlocked_ioctl = autofs4_root_ioctl, |
46 | #ifdef CONFIG_COMPAT | ||
47 | .compat_ioctl = autofs4_root_compat_ioctl, | ||
48 | #endif | ||
42 | }; | 49 | }; |
43 | 50 | ||
44 | const struct file_operations autofs4_dir_operations = { | 51 | const struct file_operations autofs4_dir_operations = { |
@@ -177,8 +184,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
177 | } | 184 | } |
178 | /* Trigger mount for path component or follow link */ | 185 | /* Trigger mount for path component or follow link */ |
179 | } else if (ino->flags & AUTOFS_INF_PENDING || | 186 | } else if (ino->flags & AUTOFS_INF_PENDING || |
180 | autofs4_need_mount(flags) || | 187 | autofs4_need_mount(flags)) { |
181 | current->link_count) { | ||
182 | DPRINTK("waiting for mount name=%.*s", | 188 | DPRINTK("waiting for mount name=%.*s", |
183 | dentry->d_name.len, dentry->d_name.name); | 189 | dentry->d_name.len, dentry->d_name.name); |
184 | 190 | ||
@@ -198,8 +204,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
198 | } | 204 | } |
199 | 205 | ||
200 | /* Initialize expiry counter after successful mount */ | 206 | /* Initialize expiry counter after successful mount */ |
201 | if (ino) | 207 | ino->last_used = jiffies; |
202 | ino->last_used = jiffies; | ||
203 | 208 | ||
204 | spin_lock(&sbi->fs_lock); | 209 | spin_lock(&sbi->fs_lock); |
205 | ino->flags &= ~AUTOFS_INF_PENDING; | 210 | ino->flags &= ~AUTOFS_INF_PENDING; |
@@ -262,7 +267,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
262 | spin_unlock(&dcache_lock); | 267 | spin_unlock(&dcache_lock); |
263 | spin_unlock(&sbi->fs_lock); | 268 | spin_unlock(&sbi->fs_lock); |
264 | 269 | ||
265 | status = try_to_fill_dentry(dentry, 0); | 270 | status = try_to_fill_dentry(dentry, nd->flags); |
266 | if (status) | 271 | if (status) |
267 | goto out_error; | 272 | goto out_error; |
268 | 273 | ||
@@ -840,6 +845,26 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
840 | } | 845 | } |
841 | 846 | ||
842 | /* Get/set timeout ioctl() operation */ | 847 | /* Get/set timeout ioctl() operation */ |
848 | #ifdef CONFIG_COMPAT | ||
849 | static inline int autofs4_compat_get_set_timeout(struct autofs_sb_info *sbi, | ||
850 | compat_ulong_t __user *p) | ||
851 | { | ||
852 | int rv; | ||
853 | unsigned long ntimeout; | ||
854 | |||
855 | if ((rv = get_user(ntimeout, p)) || | ||
856 | (rv = put_user(sbi->exp_timeout/HZ, p))) | ||
857 | return rv; | ||
858 | |||
859 | if (ntimeout > UINT_MAX/HZ) | ||
860 | sbi->exp_timeout = 0; | ||
861 | else | ||
862 | sbi->exp_timeout = ntimeout * HZ; | ||
863 | |||
864 | return 0; | ||
865 | } | ||
866 | #endif | ||
867 | |||
843 | static inline int autofs4_get_set_timeout(struct autofs_sb_info *sbi, | 868 | static inline int autofs4_get_set_timeout(struct autofs_sb_info *sbi, |
844 | unsigned long __user *p) | 869 | unsigned long __user *p) |
845 | { | 870 | { |
@@ -903,8 +928,8 @@ int is_autofs4_dentry(struct dentry *dentry) | |||
903 | * ioctl()'s on the root directory is the chief method for the daemon to | 928 | * ioctl()'s on the root directory is the chief method for the daemon to |
904 | * generate kernel reactions | 929 | * generate kernel reactions |
905 | */ | 930 | */ |
906 | static int autofs4_root_ioctl(struct inode *inode, struct file *filp, | 931 | static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp, |
907 | unsigned int cmd, unsigned long arg) | 932 | unsigned int cmd, unsigned long arg) |
908 | { | 933 | { |
909 | struct autofs_sb_info *sbi = autofs4_sbi(inode->i_sb); | 934 | struct autofs_sb_info *sbi = autofs4_sbi(inode->i_sb); |
910 | void __user *p = (void __user *)arg; | 935 | void __user *p = (void __user *)arg; |
@@ -933,6 +958,10 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, | |||
933 | return autofs4_get_protosubver(sbi, p); | 958 | return autofs4_get_protosubver(sbi, p); |
934 | case AUTOFS_IOC_SETTIMEOUT: | 959 | case AUTOFS_IOC_SETTIMEOUT: |
935 | return autofs4_get_set_timeout(sbi, p); | 960 | return autofs4_get_set_timeout(sbi, p); |
961 | #ifdef CONFIG_COMPAT | ||
962 | case AUTOFS_IOC_SETTIMEOUT32: | ||
963 | return autofs4_compat_get_set_timeout(sbi, p); | ||
964 | #endif | ||
936 | 965 | ||
937 | case AUTOFS_IOC_ASKUMOUNT: | 966 | case AUTOFS_IOC_ASKUMOUNT: |
938 | return autofs4_ask_umount(filp->f_path.mnt, p); | 967 | return autofs4_ask_umount(filp->f_path.mnt, p); |
@@ -948,3 +977,35 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, | |||
948 | return -ENOSYS; | 977 | return -ENOSYS; |
949 | } | 978 | } |
950 | } | 979 | } |
980 | |||
981 | static long autofs4_root_ioctl(struct file *filp, | ||
982 | unsigned int cmd, unsigned long arg) | ||
983 | { | ||
984 | long ret; | ||
985 | struct inode *inode = filp->f_dentry->d_inode; | ||
986 | |||
987 | lock_kernel(); | ||
988 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | ||
989 | unlock_kernel(); | ||
990 | |||
991 | return ret; | ||
992 | } | ||
993 | |||
994 | #ifdef CONFIG_COMPAT | ||
995 | static long autofs4_root_compat_ioctl(struct file *filp, | ||
996 | unsigned int cmd, unsigned long arg) | ||
997 | { | ||
998 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
999 | int ret; | ||
1000 | |||
1001 | lock_kernel(); | ||
1002 | if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) | ||
1003 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | ||
1004 | else | ||
1005 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, | ||
1006 | (unsigned long)compat_ptr(arg)); | ||
1007 | unlock_kernel(); | ||
1008 | |||
1009 | return ret; | ||
1010 | } | ||
1011 | #endif | ||