diff options
Diffstat (limited to 'fs/autofs/root.c')
| -rw-r--r-- | fs/autofs/root.c | 67 | 
1 files changed, 64 insertions, 3 deletions
| diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 9a0520b5066..11b1ea786d0 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -16,6 +16,7 @@  #include <linux/slab.h>  #include <linux/param.h>  #include <linux/time.h> +#include <linux/compat.h>  #include <linux/smp_lock.h>  #include "autofs_i.h" @@ -25,13 +26,17 @@ static int autofs_root_symlink(struct inode *,struct dentry *,const char *);  static int autofs_root_unlink(struct inode *,struct dentry *);  static int autofs_root_rmdir(struct inode *,struct dentry *);  static int autofs_root_mkdir(struct inode *,struct dentry *,int); -static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); +static long autofs_root_ioctl(struct file *,unsigned int,unsigned long); +static long autofs_root_compat_ioctl(struct file *,unsigned int,unsigned long);  const struct file_operations autofs_root_operations = {  	.llseek		= generic_file_llseek,  	.read		= generic_read_dir,  	.readdir	= autofs_root_readdir, -	.ioctl		= autofs_root_ioctl, +	.unlocked_ioctl	= autofs_root_ioctl, +#ifdef CONFIG_COMPAT +	.compat_ioctl	= autofs_root_compat_ioctl, +#endif  };  const struct inode_operations autofs_root_inode_operations = { @@ -492,6 +497,25 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)  }  /* Get/set timeout ioctl() operation */ +#ifdef CONFIG_COMPAT +static inline int autofs_compat_get_set_timeout(struct autofs_sb_info *sbi, +					 unsigned int __user *p) +{ +	unsigned long ntimeout; + +	if (get_user(ntimeout, p) || +	    put_user(sbi->exp_timeout / HZ, p)) +		return -EFAULT; + +	if (ntimeout > UINT_MAX/HZ) +		sbi->exp_timeout = 0; +	else +		sbi->exp_timeout = ntimeout * HZ; + +	return 0; +} +#endif +  static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,  					 unsigned long __user *p)  { @@ -546,7 +570,7 @@ static inline int autofs_expire_run(struct super_block *sb,   * ioctl()'s on the root directory is the chief method for the daemon to   * generate kernel reactions   */ -static int autofs_root_ioctl(struct inode *inode, struct file *filp, +static int autofs_do_root_ioctl(struct inode *inode, struct file *filp,  			     unsigned int cmd, unsigned long arg)  {  	struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); @@ -571,6 +595,10 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,  		return 0;  	case AUTOFS_IOC_PROTOVER: /* Get protocol version */  		return autofs_get_protover(argp); +#ifdef CONFIG_COMPAT +	case AUTOFS_IOC_SETTIMEOUT32: +		return autofs_compat_get_set_timeout(sbi, argp); +#endif  	case AUTOFS_IOC_SETTIMEOUT:  		return autofs_get_set_timeout(sbi, argp);  	case AUTOFS_IOC_EXPIRE: @@ -579,4 +607,37 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,  	default:  		return -ENOSYS;  	} + +} + +static long autofs_root_ioctl(struct file *filp, +			     unsigned int cmd, unsigned long arg) +{ +	int ret; + +	lock_kernel(); +	ret = autofs_do_root_ioctl(filp->f_path.dentry->d_inode, +				   filp, cmd, arg); +	unlock_kernel(); + +	return ret; +} + +#ifdef CONFIG_COMPAT +static long autofs_root_compat_ioctl(struct file *filp, +			     unsigned int cmd, unsigned long arg) +{ +	struct inode *inode = filp->f_path.dentry->d_inode; +	int ret; + +	lock_kernel(); +	if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) +		ret = autofs_do_root_ioctl(inode, filp, cmd, arg); +	else +		ret = autofs_do_root_ioctl(inode, filp, cmd, +			(unsigned long)compat_ptr(arg)); +	unlock_kernel(); + +	return ret;  } +#endif | 
