Signed-off-by: Pavel Boldin <pboldin at mirantis.com> --- lib/librte_vhost/eventfd_link/eventfd_link.c | 61 ++++++++++++++++++++++++++++ lib/librte_vhost/eventfd_link/eventfd_link.h | 28 ++++++++++--- 2 files changed, 84 insertions(+), 5 deletions(-)
diff --git a/lib/librte_vhost/eventfd_link/eventfd_link.c b/lib/librte_vhost/eventfd_link/eventfd_link.c index 5ba1068..0264365 100644 --- a/lib/librte_vhost/eventfd_link/eventfd_link.c +++ b/lib/librte_vhost/eventfd_link/eventfd_link.c @@ -77,6 +77,64 @@ fget_from_files(struct files_struct *files, unsigned fd) } static long +eventfd_link_ioctl_copy2(unsigned long arg) +{ + void __user *argp = (void __user *) arg; + struct task_struct *task_target = NULL; + struct file *file; + struct files_struct *files; + struct eventfd_copy2 eventfd_copy2; + long ret = -EFAULT; + + if (copy_from_user(&eventfd_copy2, argp, sizeof(struct eventfd_copy2))) + goto out; + + /* + * Find the task struct for the target pid + */ + ret = -ESRCH; + + task_target = + get_pid_task(find_vpid(eventfd_copy2.pid), PIDTYPE_PID); + if (task_target == NULL) { + pr_info("Unable to find pid %d\n", eventfd_copy2.pid); + goto out; + } + + ret = -ESTALE; + files = get_files_struct(task_target); + if (files == NULL) { + pr_info("Failed to get target files struct\n"); + goto out_task; + } + + ret = -EBADF; + file = fget_from_files(files, eventfd_copy2.fd); + put_files_struct(files); + + if (file == NULL) { + pr_info("Failed to get fd %d from target\n", eventfd_copy2.fd); + goto out_task; + } + + /* + * Install the file struct from the target process into the + * newly allocated file desciptor of the source process. + */ + ret = get_unused_fd_flags(eventfd_copy2.flags); + if (ret < 0) { + fput(file); + goto out_task; + } + fd_install(ret, file); + +out_task: + put_task_struct(task_target); +out: + return ret; +} + +static long eventfd_link_ioctl_copy(unsigned long arg) { void __user *argp = (void __user *) arg; @@ -175,6 +233,9 @@ eventfd_link_ioctl(struct file *f, unsigned int ioctl, unsigned long arg) case EVENTFD_COPY: ret = eventfd_link_ioctl_copy(arg); break; + case EVENTFD_COPY2: + ret = eventfd_link_ioctl_copy2(arg); + break; } return ret; diff --git a/lib/librte_vhost/eventfd_link/eventfd_link.h b/lib/librte_vhost/eventfd_link/eventfd_link.h index ea619ec..5ebc20b 100644 --- a/lib/librte_vhost/eventfd_link/eventfd_link.h +++ b/lib/librte_vhost/eventfd_link/eventfd_link.h @@ -61,11 +61,6 @@ #define _EVENTFD_LINK_H_ /* - * ioctl to copy an fd entry in calling process to an fd in a target process - */ -#define EVENTFD_COPY 1 - -/* * arguements for the EVENTFD_COPY ioctl */ struct eventfd_copy { @@ -73,4 +68,27 @@ struct eventfd_copy { unsigned source_fd; /* fd in the calling pid */ pid_t target_pid; /* pid of the target pid */ }; + +/* + * ioctl to copy an fd entry in calling process to an fd in a target process + * NOTE: this one should be + * #define EVENTFD_COPY _IOWR('D', 1, struct eventfd_copy) actually + */ +#define EVENTFD_COPY 1 + +/* + * arguments for the EVENTFD_COPY2 ioctl + */ +struct eventfd_copy2 { + unsigned fd; /* fd to steal */ + pid_t pid; /* pid of the process to steal from */ + unsigned flags; /* flags to allocate new fd with */ +}; + +/* + * ioctl to copy an fd entry from the target process into newly allocated + * fd in the calling process + */ +#define EVENTFD_COPY2 _IOW('D', 2, struct eventfd_copy2) + #endif /* _EVENTFD_LINK_H_ */ -- 1.9.1