privcmd.c (c005e2f62f8421b13b9a31adb9db7281f1a19e68) | privcmd.c (e997b357b13a7d95de31681fc54fcc34235fa527) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/****************************************************************************** 3 * privcmd.c 4 * 5 * Interface to privileged domain-0 commands. 6 * 7 * Copyright (c) 2002-2004, K A Fraser, B Dragovic 8 */ 9 10#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt 11 12#include <linux/eventfd.h> 13#include <linux/file.h> 14#include <linux/kernel.h> 15#include <linux/module.h> 16#include <linux/mutex.h> 17#include <linux/poll.h> 18#include <linux/sched.h> 19#include <linux/slab.h> | 1// SPDX-License-Identifier: GPL-2.0-only 2/****************************************************************************** 3 * privcmd.c 4 * 5 * Interface to privileged domain-0 commands. 6 * 7 * Copyright (c) 2002-2004, K A Fraser, B Dragovic 8 */ 9 10#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt 11 12#include <linux/eventfd.h> 13#include <linux/file.h> 14#include <linux/kernel.h> 15#include <linux/module.h> 16#include <linux/mutex.h> 17#include <linux/poll.h> 18#include <linux/sched.h> 19#include <linux/slab.h> |
20#include <linux/srcu.h> |
|
20#include <linux/string.h> 21#include <linux/workqueue.h> 22#include <linux/errno.h> 23#include <linux/mm.h> 24#include <linux/mman.h> 25#include <linux/uaccess.h> 26#include <linux/swap.h> 27#include <linux/highmem.h> --- 809 unchanged lines hidden (view full) --- 837 838 return rc; 839} 840 841#ifdef CONFIG_XEN_PRIVCMD_IRQFD 842/* Irqfd support */ 843static struct workqueue_struct *irqfd_cleanup_wq; 844static DEFINE_SPINLOCK(irqfds_lock); | 21#include <linux/string.h> 22#include <linux/workqueue.h> 23#include <linux/errno.h> 24#include <linux/mm.h> 25#include <linux/mman.h> 26#include <linux/uaccess.h> 27#include <linux/swap.h> 28#include <linux/highmem.h> --- 809 unchanged lines hidden (view full) --- 838 839 return rc; 840} 841 842#ifdef CONFIG_XEN_PRIVCMD_IRQFD 843/* Irqfd support */ 844static struct workqueue_struct *irqfd_cleanup_wq; 845static DEFINE_SPINLOCK(irqfds_lock); |
846DEFINE_STATIC_SRCU(irqfds_srcu); |
|
845static LIST_HEAD(irqfds_list); 846 847struct privcmd_kernel_irqfd { 848 struct xen_dm_op_buf xbufs; 849 domid_t dom; 850 bool error; 851 struct eventfd_ctx *eventfd; 852 struct work_struct shutdown; --- 11 unchanged lines hidden (view full) --- 864} 865 866static void irqfd_shutdown(struct work_struct *work) 867{ 868 struct privcmd_kernel_irqfd *kirqfd = 869 container_of(work, struct privcmd_kernel_irqfd, shutdown); 870 u64 cnt; 871 | 847static LIST_HEAD(irqfds_list); 848 849struct privcmd_kernel_irqfd { 850 struct xen_dm_op_buf xbufs; 851 domid_t dom; 852 bool error; 853 struct eventfd_ctx *eventfd; 854 struct work_struct shutdown; --- 11 unchanged lines hidden (view full) --- 866} 867 868static void irqfd_shutdown(struct work_struct *work) 869{ 870 struct privcmd_kernel_irqfd *kirqfd = 871 container_of(work, struct privcmd_kernel_irqfd, shutdown); 872 u64 cnt; 873 |
874 /* Make sure irqfd has been initialized in assign path */ 875 synchronize_srcu(&irqfds_srcu); 876 |
|
872 eventfd_ctx_remove_wait_queue(kirqfd->eventfd, &kirqfd->wait, &cnt); 873 eventfd_ctx_put(kirqfd->eventfd); 874 kfree(kirqfd); 875} 876 877static void irqfd_inject(struct privcmd_kernel_irqfd *kirqfd) 878{ 879 u64 cnt; --- 46 unchanged lines hidden (view full) --- 926 927static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd) 928{ 929 struct privcmd_kernel_irqfd *kirqfd, *tmp; 930 unsigned long flags; 931 __poll_t events; 932 struct fd f; 933 void *dm_op; | 877 eventfd_ctx_remove_wait_queue(kirqfd->eventfd, &kirqfd->wait, &cnt); 878 eventfd_ctx_put(kirqfd->eventfd); 879 kfree(kirqfd); 880} 881 882static void irqfd_inject(struct privcmd_kernel_irqfd *kirqfd) 883{ 884 u64 cnt; --- 46 unchanged lines hidden (view full) --- 931 932static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd) 933{ 934 struct privcmd_kernel_irqfd *kirqfd, *tmp; 935 unsigned long flags; 936 __poll_t events; 937 struct fd f; 938 void *dm_op; |
934 int ret; | 939 int ret, idx; |
935 936 kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL); 937 if (!kirqfd) 938 return -ENOMEM; 939 dm_op = kirqfd + 1; 940 941 if (copy_from_user(dm_op, u64_to_user_ptr(irqfd->dm_op), irqfd->size)) { 942 ret = -EFAULT; --- 29 unchanged lines hidden (view full) --- 972 list_for_each_entry(tmp, &irqfds_list, list) { 973 if (kirqfd->eventfd == tmp->eventfd) { 974 ret = -EBUSY; 975 spin_unlock_irqrestore(&irqfds_lock, flags); 976 goto error_eventfd; 977 } 978 } 979 | 940 941 kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL); 942 if (!kirqfd) 943 return -ENOMEM; 944 dm_op = kirqfd + 1; 945 946 if (copy_from_user(dm_op, u64_to_user_ptr(irqfd->dm_op), irqfd->size)) { 947 ret = -EFAULT; --- 29 unchanged lines hidden (view full) --- 977 list_for_each_entry(tmp, &irqfds_list, list) { 978 if (kirqfd->eventfd == tmp->eventfd) { 979 ret = -EBUSY; 980 spin_unlock_irqrestore(&irqfds_lock, flags); 981 goto error_eventfd; 982 } 983 } 984 |
985 idx = srcu_read_lock(&irqfds_srcu); |
|
980 list_add_tail(&kirqfd->list, &irqfds_list); 981 spin_unlock_irqrestore(&irqfds_lock, flags); 982 983 /* 984 * Check if there was an event already pending on the eventfd before we 985 * registered, and trigger it as if we didn't miss it. 986 */ 987 events = vfs_poll(f.file, &kirqfd->pt); 988 if (events & EPOLLIN) 989 irqfd_inject(kirqfd); 990 | 986 list_add_tail(&kirqfd->list, &irqfds_list); 987 spin_unlock_irqrestore(&irqfds_lock, flags); 988 989 /* 990 * Check if there was an event already pending on the eventfd before we 991 * registered, and trigger it as if we didn't miss it. 992 */ 993 events = vfs_poll(f.file, &kirqfd->pt); 994 if (events & EPOLLIN) 995 irqfd_inject(kirqfd); 996 |
997 srcu_read_unlock(&irqfds_srcu, idx); 998 |
|
991 /* 992 * Do not drop the file until the kirqfd is fully initialized, otherwise 993 * we might race against the EPOLLHUP. 994 */ 995 fdput(f); 996 return 0; 997 998error_eventfd: --- 294 unchanged lines hidden --- | 999 /* 1000 * Do not drop the file until the kirqfd is fully initialized, otherwise 1001 * we might race against the EPOLLHUP. 1002 */ 1003 fdput(f); 1004 return 0; 1005 1006error_eventfd: --- 294 unchanged lines hidden --- |