mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-22 06:32:08 +00:00
Merge branch 'akpm' (patches from Andrew Morton)
Merge first patch-bomb from Andrew Morton: "Quite a lot of other stuff is banked up awaiting further next->mainline merging, but this batch contains: - Lots of random misc patches - OCFS2 - Most of MM - backlight updates - lib/ updates - printk updates - checkpatch updates - epoll tweaking - rtc updates - hfs - hfsplus - documentation - procfs - update gcov to gcc-4.7 format - IPC" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (269 commits) ipc, msg: fix message length check for negative values ipc/util.c: remove unnecessary work pending test devpts: plug the memory leak in kill_sb ./Makefile: export initial ramdisk compression config option init/Kconfig: add option to disable kernel compression drivers: w1: make w1_slave::flags long to avoid memory corruption drivers/w1/masters/ds1wm.cuse dev_get_platdata() drivers/memstick/core/ms_block.c: fix unreachable state in h_msb_read_page() drivers/memstick/core/mspro_block.c: fix attributes array allocation drivers/pps/clients/pps-gpio.c: remove redundant of_match_ptr kernel/panic.c: reduce 1 byte usage for print tainted buffer gcov: reuse kbasename helper kernel/gcov/fs.c: use pr_warn() kernel/module.c: use pr_foo() gcov: compile specific gcov implementation based on gcc version gcov: add support for gcc 4.7 gcov format gcov: move gcov structs definitions to a gcc version specific file kernel/taskstats.c: return -ENOMEM when alloc memory fails in add_del_listener() kernel/taskstats.c: add nla_nest_cancel() for failure processing between nla_nest_start() and nla_nest_end() kernel/sysctl_binary.c: use scnprintf() instead of snprintf() ...
This commit is contained in:
commit
5cbb3d216e
287 changed files with 5004 additions and 2378 deletions
149
fs/eventpoll.c
149
fs/eventpoll.c
|
@ -41,6 +41,7 @@
|
|||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/rculist.h>
|
||||
|
||||
/*
|
||||
* LOCKING:
|
||||
|
@ -133,8 +134,12 @@ struct nested_calls {
|
|||
* of these on a server and we do not want this to take another cache line.
|
||||
*/
|
||||
struct epitem {
|
||||
/* RB tree node used to link this structure to the eventpoll RB tree */
|
||||
struct rb_node rbn;
|
||||
union {
|
||||
/* RB tree node links this structure to the eventpoll RB tree */
|
||||
struct rb_node rbn;
|
||||
/* Used to free the struct epitem */
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
/* List header used to link this structure to the eventpoll ready list */
|
||||
struct list_head rdllink;
|
||||
|
@ -580,14 +585,14 @@ static inline void ep_pm_stay_awake_rcu(struct epitem *epi)
|
|||
* @sproc: Pointer to the scan callback.
|
||||
* @priv: Private opaque data passed to the @sproc callback.
|
||||
* @depth: The current depth of recursive f_op->poll calls.
|
||||
* @ep_locked: caller already holds ep->mtx
|
||||
*
|
||||
* Returns: The same integer error code returned by the @sproc callback.
|
||||
*/
|
||||
static int ep_scan_ready_list(struct eventpoll *ep,
|
||||
int (*sproc)(struct eventpoll *,
|
||||
struct list_head *, void *),
|
||||
void *priv,
|
||||
int depth)
|
||||
void *priv, int depth, bool ep_locked)
|
||||
{
|
||||
int error, pwake = 0;
|
||||
unsigned long flags;
|
||||
|
@ -598,7 +603,9 @@ static int ep_scan_ready_list(struct eventpoll *ep,
|
|||
* We need to lock this because we could be hit by
|
||||
* eventpoll_release_file() and epoll_ctl().
|
||||
*/
|
||||
mutex_lock_nested(&ep->mtx, depth);
|
||||
|
||||
if (!ep_locked)
|
||||
mutex_lock_nested(&ep->mtx, depth);
|
||||
|
||||
/*
|
||||
* Steal the ready list, and re-init the original one to the
|
||||
|
@ -662,7 +669,8 @@ static int ep_scan_ready_list(struct eventpoll *ep,
|
|||
}
|
||||
spin_unlock_irqrestore(&ep->lock, flags);
|
||||
|
||||
mutex_unlock(&ep->mtx);
|
||||
if (!ep_locked)
|
||||
mutex_unlock(&ep->mtx);
|
||||
|
||||
/* We have to call this outside the lock */
|
||||
if (pwake)
|
||||
|
@ -671,6 +679,12 @@ static int ep_scan_ready_list(struct eventpoll *ep,
|
|||
return error;
|
||||
}
|
||||
|
||||
static void epi_rcu_free(struct rcu_head *head)
|
||||
{
|
||||
struct epitem *epi = container_of(head, struct epitem, rcu);
|
||||
kmem_cache_free(epi_cache, epi);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes a "struct epitem" from the eventpoll RB tree and deallocates
|
||||
* all the associated resources. Must be called with "mtx" held.
|
||||
|
@ -692,8 +706,7 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
|
|||
|
||||
/* Remove the current item from the list of epoll hooks */
|
||||
spin_lock(&file->f_lock);
|
||||
if (ep_is_linked(&epi->fllink))
|
||||
list_del_init(&epi->fllink);
|
||||
list_del_rcu(&epi->fllink);
|
||||
spin_unlock(&file->f_lock);
|
||||
|
||||
rb_erase(&epi->rbn, &ep->rbr);
|
||||
|
@ -704,9 +717,14 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
|
|||
spin_unlock_irqrestore(&ep->lock, flags);
|
||||
|
||||
wakeup_source_unregister(ep_wakeup_source(epi));
|
||||
|
||||
/* At this point it is safe to free the eventpoll item */
|
||||
kmem_cache_free(epi_cache, epi);
|
||||
/*
|
||||
* At this point it is safe to free the eventpoll item. Use the union
|
||||
* field epi->rcu, since we are trying to minimize the size of
|
||||
* 'struct epitem'. The 'rbn' field is no longer in use. Protected by
|
||||
* ep->mtx. The rcu read side, reverse_path_check_proc(), does not make
|
||||
* use of the rbn field.
|
||||
*/
|
||||
call_rcu(&epi->rcu, epi_rcu_free);
|
||||
|
||||
atomic_long_dec(&ep->user->epoll_watches);
|
||||
|
||||
|
@ -807,15 +825,34 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
|
||||
poll_table *pt);
|
||||
|
||||
struct readyevents_arg {
|
||||
struct eventpoll *ep;
|
||||
bool locked;
|
||||
};
|
||||
|
||||
static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests)
|
||||
{
|
||||
return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1);
|
||||
struct readyevents_arg *arg = priv;
|
||||
|
||||
return ep_scan_ready_list(arg->ep, ep_read_events_proc, NULL,
|
||||
call_nests + 1, arg->locked);
|
||||
}
|
||||
|
||||
static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
int pollflags;
|
||||
struct eventpoll *ep = file->private_data;
|
||||
struct readyevents_arg arg;
|
||||
|
||||
/*
|
||||
* During ep_insert() we already hold the ep->mtx for the tfile.
|
||||
* Prevent re-aquisition.
|
||||
*/
|
||||
arg.locked = wait && (wait->_qproc == ep_ptable_queue_proc);
|
||||
arg.ep = ep;
|
||||
|
||||
/* Insert inside our poll wait queue */
|
||||
poll_wait(file, &ep->poll_wait, wait);
|
||||
|
@ -827,7 +864,7 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
|
|||
* could re-enter here.
|
||||
*/
|
||||
pollflags = ep_call_nested(&poll_readywalk_ncalls, EP_MAX_NESTS,
|
||||
ep_poll_readyevents_proc, ep, ep, current);
|
||||
ep_poll_readyevents_proc, &arg, ep, current);
|
||||
|
||||
return pollflags != -1 ? pollflags : 0;
|
||||
}
|
||||
|
@ -872,7 +909,6 @@ static const struct file_operations eventpoll_fops = {
|
|||
*/
|
||||
void eventpoll_release_file(struct file *file)
|
||||
{
|
||||
struct list_head *lsthead = &file->f_ep_links;
|
||||
struct eventpoll *ep;
|
||||
struct epitem *epi;
|
||||
|
||||
|
@ -890,17 +926,12 @@ void eventpoll_release_file(struct file *file)
|
|||
* Besides, ep_remove() acquires the lock, so we can't hold it here.
|
||||
*/
|
||||
mutex_lock(&epmutex);
|
||||
|
||||
while (!list_empty(lsthead)) {
|
||||
epi = list_first_entry(lsthead, struct epitem, fllink);
|
||||
|
||||
list_for_each_entry_rcu(epi, &file->f_ep_links, fllink) {
|
||||
ep = epi->ep;
|
||||
list_del_init(&epi->fllink);
|
||||
mutex_lock_nested(&ep->mtx, 0);
|
||||
ep_remove(ep, epi);
|
||||
mutex_unlock(&ep->mtx);
|
||||
}
|
||||
|
||||
mutex_unlock(&epmutex);
|
||||
}
|
||||
|
||||
|
@ -1138,7 +1169,9 @@ static int reverse_path_check_proc(void *priv, void *cookie, int call_nests)
|
|||
struct file *child_file;
|
||||
struct epitem *epi;
|
||||
|
||||
list_for_each_entry(epi, &file->f_ep_links, fllink) {
|
||||
/* CTL_DEL can remove links here, but that can't increase our count */
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(epi, &file->f_ep_links, fllink) {
|
||||
child_file = epi->ep->file;
|
||||
if (is_file_epoll(child_file)) {
|
||||
if (list_empty(&child_file->f_ep_links)) {
|
||||
|
@ -1160,6 +1193,7 @@ static int reverse_path_check_proc(void *priv, void *cookie, int call_nests)
|
|||
"file is not an ep!\n");
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1231,7 +1265,7 @@ static noinline void ep_destroy_wakeup_source(struct epitem *epi)
|
|||
* Must be called with "mtx" held.
|
||||
*/
|
||||
static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
|
||||
struct file *tfile, int fd)
|
||||
struct file *tfile, int fd, int full_check)
|
||||
{
|
||||
int error, revents, pwake = 0;
|
||||
unsigned long flags;
|
||||
|
@ -1286,7 +1320,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
|
|||
|
||||
/* Add the current item to the list of active epoll hook for this file */
|
||||
spin_lock(&tfile->f_lock);
|
||||
list_add_tail(&epi->fllink, &tfile->f_ep_links);
|
||||
list_add_tail_rcu(&epi->fllink, &tfile->f_ep_links);
|
||||
spin_unlock(&tfile->f_lock);
|
||||
|
||||
/*
|
||||
|
@ -1297,7 +1331,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
|
|||
|
||||
/* now check if we've created too many backpaths */
|
||||
error = -EINVAL;
|
||||
if (reverse_path_check())
|
||||
if (full_check && reverse_path_check())
|
||||
goto error_remove_epi;
|
||||
|
||||
/* We have to drop the new item inside our item list to keep track of it */
|
||||
|
@ -1327,8 +1361,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
|
|||
|
||||
error_remove_epi:
|
||||
spin_lock(&tfile->f_lock);
|
||||
if (ep_is_linked(&epi->fllink))
|
||||
list_del_init(&epi->fllink);
|
||||
list_del_rcu(&epi->fllink);
|
||||
spin_unlock(&tfile->f_lock);
|
||||
|
||||
rb_erase(&epi->rbn, &ep->rbr);
|
||||
|
@ -1521,7 +1554,7 @@ static int ep_send_events(struct eventpoll *ep,
|
|||
esed.maxevents = maxevents;
|
||||
esed.events = events;
|
||||
|
||||
return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0);
|
||||
return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0, false);
|
||||
}
|
||||
|
||||
static inline struct timespec ep_set_mstimeout(long ms)
|
||||
|
@ -1791,11 +1824,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
|||
struct epoll_event __user *, event)
|
||||
{
|
||||
int error;
|
||||
int did_lock_epmutex = 0;
|
||||
int full_check = 0;
|
||||
struct fd f, tf;
|
||||
struct eventpoll *ep;
|
||||
struct epitem *epi;
|
||||
struct epoll_event epds;
|
||||
struct eventpoll *tep = NULL;
|
||||
|
||||
error = -EFAULT;
|
||||
if (ep_op_has_event(op) &&
|
||||
|
@ -1844,26 +1878,40 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
|||
* and hang them on the tfile_check_list, so we can check that we
|
||||
* haven't created too many possible wakeup paths.
|
||||
*
|
||||
* We need to hold the epmutex across both ep_insert and ep_remove
|
||||
* b/c we want to make sure we are looking at a coherent view of
|
||||
* epoll network.
|
||||
* We do not need to take the global 'epumutex' on EPOLL_CTL_ADD when
|
||||
* the epoll file descriptor is attaching directly to a wakeup source,
|
||||
* unless the epoll file descriptor is nested. The purpose of taking the
|
||||
* 'epmutex' on add is to prevent complex toplogies such as loops and
|
||||
* deep wakeup paths from forming in parallel through multiple
|
||||
* EPOLL_CTL_ADD operations.
|
||||
*/
|
||||
if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) {
|
||||
mutex_lock(&epmutex);
|
||||
did_lock_epmutex = 1;
|
||||
}
|
||||
if (op == EPOLL_CTL_ADD) {
|
||||
if (is_file_epoll(tf.file)) {
|
||||
error = -ELOOP;
|
||||
if (ep_loop_check(ep, tf.file) != 0) {
|
||||
clear_tfile_check_list();
|
||||
goto error_tgt_fput;
|
||||
}
|
||||
} else
|
||||
list_add(&tf.file->f_tfile_llink, &tfile_check_list);
|
||||
}
|
||||
|
||||
mutex_lock_nested(&ep->mtx, 0);
|
||||
if (op == EPOLL_CTL_ADD) {
|
||||
if (!list_empty(&f.file->f_ep_links) ||
|
||||
is_file_epoll(tf.file)) {
|
||||
full_check = 1;
|
||||
mutex_unlock(&ep->mtx);
|
||||
mutex_lock(&epmutex);
|
||||
if (is_file_epoll(tf.file)) {
|
||||
error = -ELOOP;
|
||||
if (ep_loop_check(ep, tf.file) != 0) {
|
||||
clear_tfile_check_list();
|
||||
goto error_tgt_fput;
|
||||
}
|
||||
} else
|
||||
list_add(&tf.file->f_tfile_llink,
|
||||
&tfile_check_list);
|
||||
mutex_lock_nested(&ep->mtx, 0);
|
||||
if (is_file_epoll(tf.file)) {
|
||||
tep = tf.file->private_data;
|
||||
mutex_lock_nested(&tep->mtx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) {
|
||||
tep = tf.file->private_data;
|
||||
mutex_lock_nested(&tep->mtx, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to lookup the file inside our RB tree, Since we grabbed "mtx"
|
||||
|
@ -1877,10 +1925,11 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
|||
case EPOLL_CTL_ADD:
|
||||
if (!epi) {
|
||||
epds.events |= POLLERR | POLLHUP;
|
||||
error = ep_insert(ep, &epds, tf.file, fd);
|
||||
error = ep_insert(ep, &epds, tf.file, fd, full_check);
|
||||
} else
|
||||
error = -EEXIST;
|
||||
clear_tfile_check_list();
|
||||
if (full_check)
|
||||
clear_tfile_check_list();
|
||||
break;
|
||||
case EPOLL_CTL_DEL:
|
||||
if (epi)
|
||||
|
@ -1896,10 +1945,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
|||
error = -ENOENT;
|
||||
break;
|
||||
}
|
||||
if (tep != NULL)
|
||||
mutex_unlock(&tep->mtx);
|
||||
mutex_unlock(&ep->mtx);
|
||||
|
||||
error_tgt_fput:
|
||||
if (did_lock_epmutex)
|
||||
if (full_check)
|
||||
mutex_unlock(&epmutex);
|
||||
|
||||
fdput(tf);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue