Loading fs/eventpoll.c +33 −13 Original line number Original line Diff line number Diff line Loading @@ -354,12 +354,6 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p) return container_of(p, struct ep_pqueue, pt)->epi; return container_of(p, struct ep_pqueue, pt)->epi; } } /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */ static inline int ep_op_has_event(int op) { return op != EPOLL_CTL_DEL; } /* Initialize the poll safe wake up structure */ /* Initialize the poll safe wake up structure */ static void ep_nested_calls_init(struct nested_calls *ncalls) static void ep_nested_calls_init(struct nested_calls *ncalls) { { Loading Loading @@ -2074,7 +2068,20 @@ SYSCALL_DEFINE1(epoll_create, int, size) return do_epoll_create(0); return do_epoll_create(0); } } static int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds) static inline int epoll_mutex_lock(struct mutex *mutex, int depth, bool nonblock) { if (!nonblock) { mutex_lock_nested(mutex, depth); return 0; } if (mutex_trylock(mutex)) return 0; return -EAGAIN; } int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds, bool nonblock) { { int error; int error; int full_check = 0; int full_check = 0; Loading Loading @@ -2145,13 +2152,17 @@ static int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds) * deep wakeup paths from forming in parallel through multiple * deep wakeup paths from forming in parallel through multiple * EPOLL_CTL_ADD operations. * EPOLL_CTL_ADD operations. */ */ mutex_lock_nested(&ep->mtx, 0); error = epoll_mutex_lock(&ep->mtx, 0, nonblock); if (error) goto error_tgt_fput; if (op == EPOLL_CTL_ADD) { if (op == EPOLL_CTL_ADD) { if (!list_empty(&f.file->f_ep_links) || if (!list_empty(&f.file->f_ep_links) || is_file_epoll(tf.file)) { is_file_epoll(tf.file)) { full_check = 1; mutex_unlock(&ep->mtx); mutex_unlock(&ep->mtx); mutex_lock(&epmutex); error = epoll_mutex_lock(&epmutex, 0, nonblock); if (error) goto error_tgt_fput; full_check = 1; if (is_file_epoll(tf.file)) { if (is_file_epoll(tf.file)) { error = -ELOOP; error = -ELOOP; if (ep_loop_check(ep, tf.file) != 0) { if (ep_loop_check(ep, tf.file) != 0) { Loading @@ -2161,10 +2172,19 @@ static int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds) } else } else list_add(&tf.file->f_tfile_llink, list_add(&tf.file->f_tfile_llink, &tfile_check_list); &tfile_check_list); mutex_lock_nested(&ep->mtx, 0); error = epoll_mutex_lock(&ep->mtx, 0, nonblock); if (error) { out_del: list_del(&tf.file->f_tfile_llink); goto error_tgt_fput; } if (is_file_epoll(tf.file)) { if (is_file_epoll(tf.file)) { tep = tf.file->private_data; tep = tf.file->private_data; mutex_lock_nested(&tep->mtx, 1); error = epoll_mutex_lock(&tep->mtx, 1, nonblock); if (error) { mutex_unlock(&ep->mtx); goto out_del; } } } } } } } Loading Loading @@ -2233,7 +2253,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, copy_from_user(&epds, event, sizeof(struct epoll_event))) copy_from_user(&epds, event, sizeof(struct epoll_event))) return -EFAULT; return -EFAULT; return do_epoll_ctl(epfd, op, fd, &epds); return do_epoll_ctl(epfd, op, fd, &epds, false); } } /* /* Loading include/linux/eventpoll.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,15 @@ static inline void eventpoll_release(struct file *file) eventpoll_release_file(file); eventpoll_release_file(file); } } int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds, bool nonblock); /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */ static inline int ep_op_has_event(int op) { return op != EPOLL_CTL_DEL; } #else #else static inline void eventpoll_init_file(struct file *file) {} static inline void eventpoll_init_file(struct file *file) {} Loading Loading
fs/eventpoll.c +33 −13 Original line number Original line Diff line number Diff line Loading @@ -354,12 +354,6 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p) return container_of(p, struct ep_pqueue, pt)->epi; return container_of(p, struct ep_pqueue, pt)->epi; } } /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */ static inline int ep_op_has_event(int op) { return op != EPOLL_CTL_DEL; } /* Initialize the poll safe wake up structure */ /* Initialize the poll safe wake up structure */ static void ep_nested_calls_init(struct nested_calls *ncalls) static void ep_nested_calls_init(struct nested_calls *ncalls) { { Loading Loading @@ -2074,7 +2068,20 @@ SYSCALL_DEFINE1(epoll_create, int, size) return do_epoll_create(0); return do_epoll_create(0); } } static int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds) static inline int epoll_mutex_lock(struct mutex *mutex, int depth, bool nonblock) { if (!nonblock) { mutex_lock_nested(mutex, depth); return 0; } if (mutex_trylock(mutex)) return 0; return -EAGAIN; } int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds, bool nonblock) { { int error; int error; int full_check = 0; int full_check = 0; Loading Loading @@ -2145,13 +2152,17 @@ static int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds) * deep wakeup paths from forming in parallel through multiple * deep wakeup paths from forming in parallel through multiple * EPOLL_CTL_ADD operations. * EPOLL_CTL_ADD operations. */ */ mutex_lock_nested(&ep->mtx, 0); error = epoll_mutex_lock(&ep->mtx, 0, nonblock); if (error) goto error_tgt_fput; if (op == EPOLL_CTL_ADD) { if (op == EPOLL_CTL_ADD) { if (!list_empty(&f.file->f_ep_links) || if (!list_empty(&f.file->f_ep_links) || is_file_epoll(tf.file)) { is_file_epoll(tf.file)) { full_check = 1; mutex_unlock(&ep->mtx); mutex_unlock(&ep->mtx); mutex_lock(&epmutex); error = epoll_mutex_lock(&epmutex, 0, nonblock); if (error) goto error_tgt_fput; full_check = 1; if (is_file_epoll(tf.file)) { if (is_file_epoll(tf.file)) { error = -ELOOP; error = -ELOOP; if (ep_loop_check(ep, tf.file) != 0) { if (ep_loop_check(ep, tf.file) != 0) { Loading @@ -2161,10 +2172,19 @@ static int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds) } else } else list_add(&tf.file->f_tfile_llink, list_add(&tf.file->f_tfile_llink, &tfile_check_list); &tfile_check_list); mutex_lock_nested(&ep->mtx, 0); error = epoll_mutex_lock(&ep->mtx, 0, nonblock); if (error) { out_del: list_del(&tf.file->f_tfile_llink); goto error_tgt_fput; } if (is_file_epoll(tf.file)) { if (is_file_epoll(tf.file)) { tep = tf.file->private_data; tep = tf.file->private_data; mutex_lock_nested(&tep->mtx, 1); error = epoll_mutex_lock(&tep->mtx, 1, nonblock); if (error) { mutex_unlock(&ep->mtx); goto out_del; } } } } } } } Loading Loading @@ -2233,7 +2253,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, copy_from_user(&epds, event, sizeof(struct epoll_event))) copy_from_user(&epds, event, sizeof(struct epoll_event))) return -EFAULT; return -EFAULT; return do_epoll_ctl(epfd, op, fd, &epds); return do_epoll_ctl(epfd, op, fd, &epds, false); } } /* /* Loading
include/linux/eventpoll.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,15 @@ static inline void eventpoll_release(struct file *file) eventpoll_release_file(file); eventpoll_release_file(file); } } int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds, bool nonblock); /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */ static inline int ep_op_has_event(int op) { return op != EPOLL_CTL_DEL; } #else #else static inline void eventpoll_init_file(struct file *file) {} static inline void eventpoll_init_file(struct file *file) {} Loading