From c706f3b9c832a9b31e5c5147dd0cc682808883ec Mon Sep 17 00:00:00 2001 From: Pavel Boldin Date: Wed, 28 Oct 2015 20:33:48 +0200 Subject: [PATCH] vhost: add new eventfd copy ioctl Signed-off-by: Pavel Boldin Acked-by: Huawei Xie --- 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 7cbebd47fc..c54a938d32 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) return file; } +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) { @@ -176,6 +234,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 ea619ec03f..5ebc20b8e2 100644 --- a/lib/librte_vhost/eventfd_link/eventfd_link.h +++ b/lib/librte_vhost/eventfd_link/eventfd_link.h @@ -60,11 +60,6 @@ #ifndef _EVENTFD_LINK_H_ #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 */ @@ -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_ */ -- 2.20.1