From bf30c2c3dc20b2b5e9562313a4c50541ebe313de Mon Sep 17 00:00:00 2001 From: liqiang Date: Sat, 10 Jun 2023 11:30:37 +0800 Subject: ioctl enhance and rewrite duplicate code Signed-off-by: liqiang --- qtfs/include/req.h | 2 + qtfs/qtfs/sb.c | 43 +++++++++----- qtfs/qtfs_server/fsops.c | 122 ++++++++++++++++----------------------- 3 files changed, 81 insertions(+), 86 deletions(-) diff --git a/qtfs/include/req.h b/qtfs/include/req.h index 7e0a4b2..407faef 100644 --- a/qtfs/include/req.h +++ b/qtfs/include/req.h @@ -135,6 +135,8 @@ struct qtreq_ioctl { unsigned int cmd; unsigned int size; int fd; + int argtype; // 0--use pointer arg, 1--use long arg + unsigned long arg; // for long type arg } d; char path[QTFS_TAIL_LEN(struct qtreq_ioctl_len)]; diff --git a/qtfs/qtfs/sb.c b/qtfs/qtfs/sb.c index 2038c55..9c03219 100644 --- a/qtfs/qtfs/sb.c +++ b/qtfs/qtfs/sb.c @@ -20,7 +20,7 @@ #include #include #include - +#include #include "conn.h" #include "qtfs-mod.h" @@ -561,7 +561,7 @@ int qtfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) return 0; } -long qtfs_do_ioctl(struct file *filp, unsigned int cmd, unsigned long arg, unsigned int size) +long qtfs_do_ioctl(struct file *filp, unsigned int cmd, unsigned long arg, unsigned int size, int argtype) { struct qtfs_conn_var_s *pvar = qtfs_conn_get_param(); struct qtreq_ioctl *req; @@ -575,19 +575,22 @@ long qtfs_do_ioctl(struct file *filp, unsigned int cmd, unsigned long arg, unsig return -EINVAL; } - if (size >= MAX_PATH_LEN) { - WARN_ON(1); + req = pvar->conn_ops->get_conn_msg_buf(pvar, QTFS_SEND); + rsp = pvar->conn_ops->get_conn_msg_buf(pvar, QTFS_RECV); + if (size >= sizeof(req->path)) { + qtfs_err("do ioctl failed, size:%u too big:%u", size, sizeof(req->path)); qtfs_conn_put_param(pvar); return -EINVAL; } - req = pvar->conn_ops->get_conn_msg_buf(pvar, QTFS_SEND); - rsp = pvar->conn_ops->get_conn_msg_buf(pvar, QTFS_RECV); priv = (struct private_data *)filp->private_data; req->d.fd = priv->fd; - + req->d.argtype = argtype; req->d.cmd = cmd; - if (size > 0) { + if (argtype) { + req->d.arg = arg; + len = sizeof(struct qtreq_ioctl) - sizeof(req->path); + } else if (size > 0) { ret = copy_from_user(req->path, (char __user *)arg, size); if (ret) { qtfs_err("%s: copy_from_user, size %u failed.", __func__, size); @@ -597,7 +600,7 @@ long qtfs_do_ioctl(struct file *filp, unsigned int cmd, unsigned long arg, unsig len = sizeof(struct qtreq_ioctl) - sizeof(req->path) + size; req->d.size = size; } else { - len = sizeof(struct qtreq_ioctl) - sizeof(req->path) + strlen(req->path) + 1; + len = sizeof(struct qtreq_ioctl) - sizeof(req->path); } rsp = qtfs_remote_run(pvar, QTFS_REQ_IOCTL, len); @@ -623,27 +626,41 @@ out: return (long)ret; } +#define QTFS_IOCTL_CASE_WITH_BREAK(size, argtype)\ + {\ + ret = qtfs_do_ioctl(filp, cmd, arg, size, argtype);\ + break;\ + } long qtfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + unsigned int size; + long ret; switch(cmd) { + // all case of size 0 type 0 enter here case FS_IOC_FSGETXATTR: case TCGETS: - return qtfs_do_ioctl(filp, cmd, arg, 0); + QTFS_IOCTL_CASE_WITH_BREAK(0, 0); + // all case of size 0 type 1 enter here + case TUNSETPERSIST: + QTFS_IOCTL_CASE_WITH_BREAK(0, 1); case FS_IOC_FSSETXATTR: - return qtfs_do_ioctl(filp, cmd, arg, sizeof(struct fsxattr)); + QTFS_IOCTL_CASE_WITH_BREAK(sizeof(struct fsxattr), 0); case TCSETS: - return qtfs_do_ioctl(filp, cmd, arg, sizeof(struct ktermios)); + QTFS_IOCTL_CASE_WITH_BREAK(sizeof(struct ktermios), 0); + case TUNSETIFF: + QTFS_IOCTL_CASE_WITH_BREAK(sizeof(struct ifreq), 0); default: { char *fullname = kmalloc(MAX_PATH_LEN, GFP_KERNEL); if (!fullname) return -ENOMEM; memset(fullname, 0, MAX_PATH_LEN); qtfs_fullname(fullname, filp->f_path.dentry, MAX_PATH_LEN); - qtfs_err("qtfs ioctl get not support cmd:%d file:%s TCGETS:%d", cmd, fullname, TCGETS); + qtfs_err("qtfs ioctl get not support cmd:%d file:%s", cmd, fullname); kfree(fullname); return -EOPNOTSUPP; } } + return ret; } loff_t qtfs_dir_file_llseek(struct file *file, loff_t offset, int whence) diff --git a/qtfs/qtfs_server/fsops.c b/qtfs/qtfs_server/fsops.c index 0ae95f3..e8e5742 100644 --- a/qtfs/qtfs_server/fsops.c +++ b/qtfs/qtfs_server/fsops.c @@ -29,6 +29,7 @@ #include #include #include +#include #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0)) #include #endif @@ -105,8 +106,20 @@ static inline void qtfs_inode_info_fill(struct inode_info *ii, struct inode *ino return; } +#define QTFS_IOCTL_HANDLE_WITH_BREAK(rspsize)\ + {\ + ret = copy_from_user(rsp->buf, userp->userp, rspsize);\ + if (ret) {\ + qtfs_err("cmd:%d copy_from_user failed with:%d\n", req->d.cmd, ret);\ + rsp->errno = -EFAULT;\ + goto err;\ + }\ + rsp->size = rspsize;\ + break;\ + } static int handle_ioctl(struct qtserver_arg *arg) { + unsigned long ioctl_arg; int ret; int iret; struct qtreq_ioctl *req = (struct qtreq_ioctl *)REQ(arg); @@ -123,82 +136,45 @@ static int handle_ioctl(struct qtserver_arg *arg) } mutex_unlock(&fd_bitmap_lock); - switch (req->d.cmd) { - case FS_IOC_FSGETXATTR: - iret = qtfs_syscall_ioctl(req->d.fd, req->d.cmd, (unsigned long)userp->userp); - if (iret) { - qtfs_err("fsgetxattr ioctl failed with %d\n", iret); - rsp->errno = iret; - goto err; - } - ret = copy_from_user(rsp->buf, userp->userp, sizeof(struct fsxattr)); - if (ret) { - qtfs_err("fsgetxattr copy_from_user failed with %d\n", ret); - rsp->errno = -EFAULT; - goto err; - } - rsp->size = sizeof(struct fsxattr); - break; - case FS_IOC_FSSETXATTR: - if (req->d.size <= 0 || req->d.size > sizeof(req->path) || req->d.size >= userp->size) { - rsp->errno = -EINVAL; - goto err; - } - ret = copy_to_user(userp->userp, req->path, req->d.size); - if (ret) { - qtfs_err("fssetxattr copy_to_user failed with %d\n", ret); - rsp->errno = -EFAULT; - goto err; - } - iret = qtfs_syscall_ioctl(req->d.fd, req->d.cmd, (unsigned long)userp->userp); - if (iret) { - qtfs_err("fssetxattr ioctl failed with %d\n", iret); - rsp->errno = iret; - goto err; - } - rsp->size = 0; - break; - case TCGETS: - iret = qtfs_syscall_ioctl(req->d.fd, req->d.cmd, (unsigned long)userp->userp); - if (iret) { - qtfs_err("ioctl TCGETS failed with %d\n", iret); - rsp->errno = iret; - goto err; - } - qtfs_info("ioctl TCGETS ret:%d", iret); - - ret = copy_from_user(rsp->buf, userp->userp, sizeof(struct ktermios)); - if (ret) { - qtfs_err("fsgetxattr copy_from_user failed with %d\n", ret); - rsp->errno = -EFAULT; - goto err; - } - rsp->size = sizeof(struct ktermios); - break; - case TCSETS: - if (req->d.size <= 0 || req->d.size > sizeof(req->path)) { - rsp->errno = -EINVAL; - goto err; - } - ret = copy_to_user(userp->userp, req->path, req->d.size); - if (ret) { - qtfs_err("tcsets copy_to_user failed with %d\n", ret); - rsp->errno = -EFAULT; - goto err; - } - qtfs_info("tcsets size:%u sizeof ktermios:%lu", req->d.size, sizeof(struct ktermios)); - iret = qtfs_syscall_ioctl(req->d.fd, req->d.cmd, (unsigned long)userp->userp); - if (iret) { - qtfs_err("tcsets ioctl failed with %d\n", iret); - rsp->errno = iret; - goto err; + if (req->d.argtype) { + ioctl_arg = req->d.arg; + } else { + if (req->d.size) { + if (req->d.size <= 0 || req->d.size > sizeof(req->path) || req->d.size >= userp->size) { + rsp->errno = -EINVAL; + goto err; + } + ret = copy_to_user(userp->userp, req->path, req->d.size); + if (ret) { + qtfs_err("cmd:%d copy_to_user failed with:%d", req->d.cmd, ret); + rsp->errno = -EFAULT; + goto err; + } } - rsp->size = 0; - break; - default: - rsp->errno = -EOPNOTSUPP; + ioctl_arg = (unsigned long)userp->userp; + } + iret = qtfs_syscall_ioctl(req->d.fd, req->d.cmd, ioctl_arg); + if (iret) { + qtfs_err("ioctl fd:%d cmd:%d failed with %d", req->d.fd, req->d.cmd, iret); + rsp->errno = iret; goto err; } + qtfs_info("ioctl fd:%d cmd:%d argtype:%d arg:%lx size:%u successed", req->d.fd, req->d.cmd, req->d.argtype, req->d.arg, req->d.size); + switch (req->d.cmd) { + case TUNSETPERSIST: + case TUNSETIFF: + case TCSETS: + case FS_IOC_FSSETXATTR: + rsp->size = 0; + break; + case FS_IOC_FSGETXATTR: + QTFS_IOCTL_HANDLE_WITH_BREAK(sizeof(struct fsxattr)); + case TCGETS: + QTFS_IOCTL_HANDLE_WITH_BREAK(sizeof(struct ktermios)); + default: + rsp->errno = -EOPNOTSUPP; + goto err; + } rsp->ret = QTFS_OK; rsp->errno = iret; return sizeof(struct qtrsp_ioctl) - sizeof(rsp->buf) + rsp->size; -- 2.33.0