|
@@ -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
|