]> Git Repo - linux.git/commitdiff
Merge branch 'akpm' (patches from Andrew Morton)
authorLinus Torvalds <[email protected]>
Wed, 13 Nov 2013 06:45:43 +0000 (15:45 +0900)
committerLinus Torvalds <[email protected]>
Wed, 13 Nov 2013 06:45:43 +0000 (15:45 +0900)
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 <[email protected]>: (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()
  ...

1  2 
fs/eventpoll.c
fs/exec.c
fs/fs-writeback.c
fs/sync.c
include/linux/binfmts.h
include/linux/compat.h
mm/memcontrol.c
mm/memory.c
mm/mmap.c
mm/nommu.c

diff --combined fs/eventpoll.c
index 983e3960abffc4a36f901092f5aae5cc55d58e30,f7fe7e3ce664037694cf1c1d6f341267d4de941c..79b65c3b9e876f1087ccbcf7908a47c18efbbad9
@@@ -41,6 -41,7 +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 +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 +585,14 @@@ static inline void ep_pm_stay_awake_rcu
   * @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;
         * 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
        }
        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)
        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 +706,7 @@@ static int ep_remove(struct eventpoll *
  
        /* 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);
        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 +825,34 @@@ static int ep_read_events_proc(struct e
        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);
         * 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 +909,6 @@@ static const struct file_operations eve
   */
  void eventpoll_release_file(struct file *file)
  {
-       struct list_head *lsthead = &file->f_ep_links;
        struct eventpoll *ep;
        struct epitem *epi;
  
         * 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 +1169,9 @@@ static int reverse_path_check_proc(voi
        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)) {
                                "file is not an ep!\n");
                }
        }
+       rcu_read_unlock();
        return error;
  }
  
@@@ -1231,7 -1265,7 +1265,7 @@@ static noinline void ep_destroy_wakeup_
   * 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;
  
        /* 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);
  
        /*
  
        /* 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 */
  
  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 +1554,7 @@@ static int ep_send_events(struct eventp
        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 +1824,12 @@@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, i
                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) &&
  
        /* The target file descriptor must support poll */
        error = -EPERM;
 -      if (!tf.file->f_op || !tf.file->f_op->poll)
 +      if (!tf.file->f_op->poll)
                goto error_tgt_fput;
  
        /* Check if EPOLLWAKEUP is allowed */
         * 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;
-       }
+       mutex_lock_nested(&ep->mtx, 0);
        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;
+               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);
                        }
-               } else
-                       list_add(&tf.file->f_tfile_llink, &tfile_check_list);
+               }
+       }
+       if (op == EPOLL_CTL_DEL && is_file_epoll(tf.file)) {
+               tep = tf.file->private_data;
+               mutex_lock_nested(&tep->mtx, 1);
        }
-       mutex_lock_nested(&ep->mtx, 0);
  
        /*
         * Try to lookup the file inside our RB tree, Since we grabbed "mtx"
        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)
                        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);
diff --combined fs/exec.c
index be4c81c7251c4b832b40980483bedf340456e954,12120620f0409660555aec739e5c0441abb995ee..977319fd77f39de88ef66979d1de95f7d846f9a6
+++ b/fs/exec.c
@@@ -106,7 -106,6 +106,7 @@@ static inline void put_binfmt(struct li
   */
  SYSCALL_DEFINE1(uselib, const char __user *, library)
  {
 +      struct linux_binfmt *fmt;
        struct file *file;
        struct filename *tmp = getname(library);
        int error = PTR_ERR(tmp);
        fsnotify_open(file);
  
        error = -ENOEXEC;
 -      if(file->f_op) {
 -              struct linux_binfmt * fmt;
  
 -              read_lock(&binfmt_lock);
 -              list_for_each_entry(fmt, &formats, lh) {
 -                      if (!fmt->load_shlib)
 -                              continue;
 -                      if (!try_module_get(fmt->module))
 -                              continue;
 -                      read_unlock(&binfmt_lock);
 -                      error = fmt->load_shlib(file);
 -                      read_lock(&binfmt_lock);
 -                      put_binfmt(fmt);
 -                      if (error != -ENOEXEC)
 -                              break;
 -              }
 +      read_lock(&binfmt_lock);
 +      list_for_each_entry(fmt, &formats, lh) {
 +              if (!fmt->load_shlib)
 +                      continue;
 +              if (!try_module_get(fmt->module))
 +                      continue;
                read_unlock(&binfmt_lock);
 +              error = fmt->load_shlib(file);
 +              read_lock(&binfmt_lock);
 +              put_binfmt(fmt);
 +              if (error != -ENOEXEC)
 +                      break;
        }
 +      read_unlock(&binfmt_lock);
  exit:
        fput(file);
  out:
@@@ -1275,10 -1277,13 +1275,10 @@@ static int check_unsafe_exec(struct lin
   */
  int prepare_binprm(struct linux_binprm *bprm)
  {
 -      umode_t mode;
 -      struct inode * inode = file_inode(bprm->file);
 +      struct inode *inode = file_inode(bprm->file);
 +      umode_t mode = inode->i_mode;
        int retval;
  
 -      mode = inode->i_mode;
 -      if (bprm->file->f_op == NULL)
 -              return -EACCES;
  
        /* clear any previous set[ug]id data from a previous binary */
        bprm->cred->euid = current_euid();
@@@ -1664,6 -1669,12 +1664,12 @@@ int __get_dumpable(unsigned long mm_fla
        return (ret > SUID_DUMP_USER) ? SUID_DUMP_ROOT : ret;
  }
  
+ /*
+  * This returns the actual value of the suid_dumpable flag. For things
+  * that are using this for checking for privilege transitions, it must
+  * test against SUID_DUMP_USER rather than treating it as a boolean
+  * value.
+  */
  int get_dumpable(struct mm_struct *mm)
  {
        return __get_dumpable(mm->flags);
diff --combined fs/fs-writeback.c
index 09c11329a17c6b3b6d4e2297faff09103e21e55c,4afdbd6d96786c10df5e79db68eea9dace54be46..1f4a10ece2f1249d5ae9991bfdde4874019b3462
@@@ -26,7 -26,6 +26,7 @@@
  #include <linux/blkdev.h>
  #include <linux/backing-dev.h>
  #include <linux/tracepoint.h>
 +#include <linux/device.h>
  #include "internal.h"
  
  /*
  struct wb_writeback_work {
        long nr_pages;
        struct super_block *sb;
-       unsigned long *older_than_this;
+       /*
+        * Write only inodes dirtied before this time. Don't forget to set
+        * older_than_this_is_set when you set this.
+        */
+       unsigned long older_than_this;
        enum writeback_sync_modes sync_mode;
        unsigned int tagged_writepages:1;
        unsigned int for_kupdate:1;
        unsigned int range_cyclic:1;
        unsigned int for_background:1;
        unsigned int for_sync:1;        /* sync(2) WB_SYNC_ALL writeback */
+       unsigned int older_than_this_is_set:1;
        enum wb_reason reason;          /* why was writeback initiated? */
  
        struct list_head list;          /* pending work list */
@@@ -247,10 -251,10 +252,10 @@@ static int move_expired_inodes(struct l
        int do_sb_sort = 0;
        int moved = 0;
  
+       WARN_ON_ONCE(!work->older_than_this_is_set);
        while (!list_empty(delaying_queue)) {
                inode = wb_inode(delaying_queue->prev);
-               if (work->older_than_this &&
-                   inode_dirtied_after(inode, *work->older_than_this))
+               if (inode_dirtied_after(inode, work->older_than_this))
                        break;
                list_move(&inode->i_wb_list, &tmp);
                moved++;
@@@ -734,6 -738,8 +739,8 @@@ static long writeback_inodes_wb(struct 
                .sync_mode      = WB_SYNC_NONE,
                .range_cyclic   = 1,
                .reason         = reason,
+               .older_than_this = jiffies,
+               .older_than_this_is_set = 1,
        };
  
        spin_lock(&wb->list_lock);
@@@ -792,12 -798,13 +799,13 @@@ static long wb_writeback(struct bdi_wri
  {
        unsigned long wb_start = jiffies;
        long nr_pages = work->nr_pages;
-       unsigned long oldest_jif;
        struct inode *inode;
        long progress;
  
-       oldest_jif = jiffies;
-       work->older_than_this = &oldest_jif;
+       if (!work->older_than_this_is_set) {
+               work->older_than_this = jiffies;
+               work->older_than_this_is_set = 1;
+       }
  
        spin_lock(&wb->list_lock);
        for (;;) {
                 * safe.
                 */
                if (work->for_kupdate) {
-                       oldest_jif = jiffies -
+                       work->older_than_this = jiffies -
                                msecs_to_jiffies(dirty_expire_interval * 10);
                } else if (work->for_background)
-                       oldest_jif = jiffies;
+                       work->older_than_this = jiffies;
  
                trace_writeback_start(wb->bdi, work);
                if (list_empty(&wb->b_io))
@@@ -1346,18 -1353,21 +1354,21 @@@ EXPORT_SYMBOL(try_to_writeback_inodes_s
  
  /**
   * sync_inodes_sb     -       sync sb inode pages
-  * @sb: the superblock
+  * @sb:                       the superblock
+  * @older_than_this:  timestamp
   *
   * This function writes and waits on any dirty inode belonging to this
-  * super_block.
+  * superblock that has been dirtied before given timestamp.
   */
- void sync_inodes_sb(struct super_block *sb)
+ void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this)
  {
        DECLARE_COMPLETION_ONSTACK(done);
        struct wb_writeback_work work = {
                .sb             = sb,
                .sync_mode      = WB_SYNC_ALL,
                .nr_pages       = LONG_MAX,
+               .older_than_this = older_than_this,
+               .older_than_this_is_set = 1,
                .range_cyclic   = 0,
                .done           = &done,
                .reason         = WB_REASON_SYNC,
diff --combined fs/sync.c
index 6c0ca3b75758dac589160158968a14518231810a,ff96f99fef645c38f34bd985b1a2be2184415774..f15537452231d003a05f99b6b28d3c63b85dc8f0
+++ b/fs/sync.c
   * wait == 1 case since in that case write_inode() functions do
   * sync_dirty_buffer() and thus effectively write one block at a time.
   */
- static int __sync_filesystem(struct super_block *sb, int wait)
+ static int __sync_filesystem(struct super_block *sb, int wait,
+                            unsigned long start)
  {
        if (wait)
-               sync_inodes_sb(sb);
+               sync_inodes_sb(sb, start);
        else
                writeback_inodes_sb(sb, WB_REASON_SYNC);
  
@@@ -47,6 -48,7 +48,7 @@@
  int sync_filesystem(struct super_block *sb)
  {
        int ret;
+       unsigned long start = jiffies;
  
        /*
         * We need to be protected against the filesystem going from
        if (sb->s_flags & MS_RDONLY)
                return 0;
  
-       ret = __sync_filesystem(sb, 0);
+       ret = __sync_filesystem(sb, 0, start);
        if (ret < 0)
                return ret;
-       return __sync_filesystem(sb, 1);
+       return __sync_filesystem(sb, 1, start);
  }
  EXPORT_SYMBOL_GPL(sync_filesystem);
  
  static void sync_inodes_one_sb(struct super_block *sb, void *arg)
  {
        if (!(sb->s_flags & MS_RDONLY))
-               sync_inodes_sb(sb);
+               sync_inodes_sb(sb, *((unsigned long *)arg));
  }
  
  static void sync_fs_one_sb(struct super_block *sb, void *arg)
@@@ -102,9 -104,10 +104,10 @@@ static void fdatawait_one_bdev(struct b
  SYSCALL_DEFINE0(sync)
  {
        int nowait = 0, wait = 1;
+       unsigned long start = jiffies;
  
        wakeup_flusher_threads(0, WB_REASON_SYNC);
-       iterate_supers(sync_inodes_one_sb, NULL);
+       iterate_supers(sync_inodes_one_sb, &start);
        iterate_supers(sync_fs_one_sb, &nowait);
        iterate_supers(sync_fs_one_sb, &wait);
        iterate_bdevs(fdatawrite_one_bdev, NULL);
@@@ -177,7 -180,7 +180,7 @@@ SYSCALL_DEFINE1(syncfs, int, fd
   */
  int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
  {
 -      if (!file->f_op || !file->f_op->fsync)
 +      if (!file->f_op->fsync)
                return -EINVAL;
        return file->f_op->fsync(file, start, end, datasync);
  }
diff --combined include/linux/binfmts.h
index 790d3305a5a7ace2f0c363341b4a2da743d53f5d,7554fd410bcc35ff1a4d56e1e3ae99c62a78bcad..fd8bf3219ef7bbc9af53a05e391215a978de1a19
@@@ -56,12 -56,11 +56,12 @@@ struct linux_binprm 
  
  /* Function parameter for binfmt->coredump */
  struct coredump_params {
 -      siginfo_t *siginfo;
 +      const siginfo_t *siginfo;
        struct pt_regs *regs;
        struct file *file;
        unsigned long limit;
        unsigned long mm_flags;
 +      loff_t written;
  };
  
  /*
@@@ -100,9 -99,6 +100,6 @@@ extern void setup_new_exec(struct linux
  extern void would_dump(struct linux_binprm *, struct file *);
  
  extern int suid_dumpable;
- #define SUID_DUMP_DISABLE     0       /* No setuid dumping */
- #define SUID_DUMP_USER                1       /* Dump as user of process */
- #define SUID_DUMP_ROOT                2       /* Dump as root */
  
  /* Stack area protections */
  #define EXSTACK_DEFAULT   0   /* Whatever the arch defaults to */
diff --combined include/linux/compat.h
index 78cdf51ff5ba57bb49ee7288601e55c07d648d69,ada34c92b6843c72b87221781f2b610ebfac325e..eb8a49d75ab3155bb6910eab585e5dfed9f64dee
        COMPAT_SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
  
  #define COMPAT_SYSCALL_DEFINEx(x, name, ...)                          \
-       asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
+       asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))\
+               __attribute__((alias(__stringify(compat_SyS##name))));  \
        static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
        asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));\
        asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\
        {                                                               \
                return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \
        }                                                               \
-       SYSCALL_ALIAS(compat_sys##name, compat_SyS##name);              \
        static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
  
  #ifndef compat_user_stack_pointer
@@@ -362,7 -362,7 +362,7 @@@ long compat_get_bitmap(unsigned long *m
  long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
                       unsigned long bitmap_size);
  int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from);
 -int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from);
 +int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from);
  int get_compat_sigevent(struct sigevent *event,
                const struct compat_sigevent __user *u_event);
  long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig,
diff --combined mm/memcontrol.c
index 796820925de0b758c5eea87a4e3484de07e0e56f,3d4bb07c76798bae6c0e825ba606e9f522867d2d..f20a57b7faf2f3bd8faf5b8676ffd7a6adbf7fc7
@@@ -59,6 -59,7 +59,7 @@@
  #include <net/sock.h>
  #include <net/ip.h>
  #include <net/tcp_memcontrol.h>
+ #include "slab.h"
  
  #include <asm/uaccess.h>
  
@@@ -499,29 -500,6 +500,29 @@@ static inline bool mem_cgroup_is_root(s
        return (memcg == root_mem_cgroup);
  }
  
 +/*
 + * We restrict the id in the range of [1, 65535], so it can fit into
 + * an unsigned short.
 + */
 +#define MEM_CGROUP_ID_MAX     USHRT_MAX
 +
 +static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
 +{
 +      /*
 +       * The ID of the root cgroup is 0, but memcg treat 0 as an
 +       * invalid ID, so we return (cgroup_id + 1).
 +       */
 +      return memcg->css.cgroup->id + 1;
 +}
 +
 +static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
 +{
 +      struct cgroup_subsys_state *css;
 +
 +      css = css_from_id(id - 1, &mem_cgroup_subsys);
 +      return mem_cgroup_from_css(css);
 +}
 +
  /* Writing them here to avoid exposing memcg's inner layout */
  #if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
  
@@@ -593,11 -571,16 +594,11 @@@ static void disarm_sock_keys(struct mem
  #ifdef CONFIG_MEMCG_KMEM
  /*
   * This will be the memcg's index in each cache's ->memcg_params->memcg_caches.
 - * There are two main reasons for not using the css_id for this:
 - *  1) this works better in sparse environments, where we have a lot of memcgs,
 - *     but only a few kmem-limited. Or also, if we have, for instance, 200
 - *     memcgs, and none but the 200th is kmem-limited, we'd have to have a
 - *     200 entry array for that.
 - *
 - *  2) In order not to violate the cgroup API, we would like to do all memory
 - *     allocation in ->create(). At that point, we haven't yet allocated the
 - *     css_id. Having a separate index prevents us from messing with the cgroup
 - *     core for this
 + * The main reason for not using cgroup id for this:
 + *  this works better in sparse environments, where we have a lot of memcgs,
 + *  but only a few kmem-limited. Or also, if we have, for instance, 200
 + *  memcgs, and none but the 200th is kmem-limited, we'd have to have a
 + *  200 entry array for that.
   *
   * The current size of the caches array is stored in
   * memcg_limited_groups_array_size.  It will double each time we have to
@@@ -612,14 -595,14 +613,14 @@@ int memcg_limited_groups_array_size
   * cgroups is a reasonable guess. In the future, it could be a parameter or
   * tunable, but that is strictly not necessary.
   *
 - * MAX_SIZE should be as large as the number of css_ids. Ideally, we could get
 + * MAX_SIZE should be as large as the number of cgrp_ids. Ideally, we could get
   * this constant directly from cgroup, but it is understandable that this is
   * better kept as an internal representation in cgroup.c. In any case, the
 - * css_id space is not getting any smaller, and we don't have to necessarily
 + * cgrp_id space is not getting any smaller, and we don't have to necessarily
   * increase ours as well if it increases.
   */
  #define MEMCG_CACHES_MIN_SIZE 4
 -#define MEMCG_CACHES_MAX_SIZE 65535
 +#define MEMCG_CACHES_MAX_SIZE MEM_CGROUP_ID_MAX
  
  /*
   * A lot of the calls to the cache allocation functions are expected to be
@@@ -1426,7 -1409,7 +1427,7 @@@ bool __mem_cgroup_same_or_subtree(cons
                return true;
        if (!root_memcg->use_hierarchy || !memcg)
                return false;
 -      return css_is_ancestor(&memcg->css, &root_memcg->css);
 +      return cgroup_is_descendant(memcg->css.cgroup, root_memcg->css.cgroup);
  }
  
  static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
@@@ -2844,10 -2827,15 +2845,10 @@@ static void __mem_cgroup_cancel_local_c
   */
  static struct mem_cgroup *mem_cgroup_lookup(unsigned short id)
  {
 -      struct cgroup_subsys_state *css;
 -
        /* ID 0 is unused ID */
        if (!id)
                return NULL;
 -      css = css_lookup(&mem_cgroup_subsys, id);
 -      if (!css)
 -              return NULL;
 -      return mem_cgroup_from_css(css);
 +      return mem_cgroup_from_id(id);
  }
  
  struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
@@@ -2968,7 -2956,7 +2969,7 @@@ static struct kmem_cache *memcg_params_
  
        VM_BUG_ON(p->is_root_cache);
        cachep = p->root_cache;
-       return cachep->memcg_params->memcg_caches[memcg_cache_id(p->memcg)];
+       return cache_from_memcg_idx(cachep, memcg_cache_id(p->memcg));
  }
  
  #ifdef CONFIG_SLABINFO
@@@ -2997,21 -2985,14 +2998,14 @@@ static int memcg_charge_kmem(struct mem
        struct res_counter *fail_res;
        struct mem_cgroup *_memcg;
        int ret = 0;
-       bool may_oom;
  
        ret = res_counter_charge(&memcg->kmem, size, &fail_res);
        if (ret)
                return ret;
  
-       /*
-        * Conditions under which we can wait for the oom_killer. Those are
-        * the same conditions tested by the core page allocator
-        */
-       may_oom = (gfp & __GFP_FS) && !(gfp & __GFP_NORETRY);
        _memcg = memcg;
        ret = __mem_cgroup_try_charge(NULL, gfp, size >> PAGE_SHIFT,
-                                     &_memcg, may_oom);
+                                     &_memcg, oom_gfp_allowed(gfp));
  
        if (ret == -EINTR)  {
                /*
@@@ -3151,7 -3132,7 +3145,7 @@@ int memcg_update_cache_size(struct kmem
  {
        struct memcg_cache_params *cur_params = s->memcg_params;
  
-       VM_BUG_ON(s->memcg_params && !s->memcg_params->is_root_cache);
+       VM_BUG_ON(!is_root_cache(s));
  
        if (num_groups > memcg_limited_groups_array_size) {
                int i;
@@@ -3412,7 -3393,7 +3406,7 @@@ static struct kmem_cache *memcg_create_
        idx = memcg_cache_id(memcg);
  
        mutex_lock(&memcg_cache_mutex);
-       new_cachep = cachep->memcg_params->memcg_caches[idx];
+       new_cachep = cache_from_memcg_idx(cachep, idx);
        if (new_cachep) {
                css_put(&memcg->css);
                goto out;
@@@ -3458,8 -3439,8 +3452,8 @@@ void kmem_cache_destroy_memcg_children(
         * we'll take the set_limit_mutex to protect ourselves against this.
         */
        mutex_lock(&set_limit_mutex);
-       for (i = 0; i < memcg_limited_groups_array_size; i++) {
-               c = s->memcg_params->memcg_caches[i];
+       for_each_memcg_cache_index(i) {
+               c = cache_from_memcg_idx(s, i);
                if (!c)
                        continue;
  
@@@ -3592,8 -3573,8 +3586,8 @@@ struct kmem_cache *__memcg_kmem_get_cac
         * code updating memcg_caches will issue a write barrier to match this.
         */
        read_barrier_depends();
-       if (likely(cachep->memcg_params->memcg_caches[idx])) {
-               cachep = cachep->memcg_params->memcg_caches[idx];
+       if (likely(cache_from_memcg_idx(cachep, idx))) {
+               cachep = cache_from_memcg_idx(cachep, idx);
                goto out;
        }
  
@@@ -4363,7 -4344,7 +4357,7 @@@ mem_cgroup_uncharge_swapcache(struct pa
         * css_get() was called in uncharge().
         */
        if (do_swap_account && swapout && memcg)
 -              swap_cgroup_record(ent, css_id(&memcg->css));
 +              swap_cgroup_record(ent, mem_cgroup_id(memcg));
  }
  #endif
  
@@@ -4415,8 -4396,8 +4409,8 @@@ static int mem_cgroup_move_swap_account
  {
        unsigned short old_id, new_id;
  
 -      old_id = css_id(&from->css);
 -      new_id = css_id(&to->css);
 +      old_id = mem_cgroup_id(from);
 +      new_id = mem_cgroup_id(to);
  
        if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) {
                mem_cgroup_swap_statistics(from, false);
@@@ -5389,45 -5370,50 +5383,50 @@@ static int mem_cgroup_move_charge_write
  static int memcg_numa_stat_show(struct cgroup_subsys_state *css,
                                struct cftype *cft, struct seq_file *m)
  {
+       struct numa_stat {
+               const char *name;
+               unsigned int lru_mask;
+       };
+       static const struct numa_stat stats[] = {
+               { "total", LRU_ALL },
+               { "file", LRU_ALL_FILE },
+               { "anon", LRU_ALL_ANON },
+               { "unevictable", BIT(LRU_UNEVICTABLE) },
+       };
+       const struct numa_stat *stat;
        int nid;
-       unsigned long total_nr, file_nr, anon_nr, unevictable_nr;
-       unsigned long node_nr;
+       unsigned long nr;
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
  
-       total_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL);
-       seq_printf(m, "total=%lu", total_nr);
-       for_each_node_state(nid, N_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL);
-               seq_printf(m, " N%d=%lu", nid, node_nr);
-       }
-       seq_putc(m, '\n');
-       file_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_FILE);
-       seq_printf(m, "file=%lu", file_nr);
-       for_each_node_state(nid, N_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
-                               LRU_ALL_FILE);
-               seq_printf(m, " N%d=%lu", nid, node_nr);
+       for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) {
+               nr = mem_cgroup_nr_lru_pages(memcg, stat->lru_mask);
+               seq_printf(m, "%s=%lu", stat->name, nr);
+               for_each_node_state(nid, N_MEMORY) {
+                       nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
+                                                         stat->lru_mask);
+                       seq_printf(m, " N%d=%lu", nid, nr);
+               }
+               seq_putc(m, '\n');
        }
-       seq_putc(m, '\n');
  
-       anon_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_ANON);
-       seq_printf(m, "anon=%lu", anon_nr);
-       for_each_node_state(nid, N_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
-                               LRU_ALL_ANON);
-               seq_printf(m, " N%d=%lu", nid, node_nr);
+       for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) {
+               struct mem_cgroup *iter;
+               nr = 0;
+               for_each_mem_cgroup_tree(iter, memcg)
+                       nr += mem_cgroup_nr_lru_pages(iter, stat->lru_mask);
+               seq_printf(m, "hierarchical_%s=%lu", stat->name, nr);
+               for_each_node_state(nid, N_MEMORY) {
+                       nr = 0;
+                       for_each_mem_cgroup_tree(iter, memcg)
+                               nr += mem_cgroup_node_nr_lru_pages(
+                                       iter, nid, stat->lru_mask);
+                       seq_printf(m, " N%d=%lu", nid, nr);
+               }
+               seq_putc(m, '\n');
        }
-       seq_putc(m, '\n');
  
-       unevictable_nr = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE));
-       seq_printf(m, "unevictable=%lu", unevictable_nr);
-       for_each_node_state(nid, N_MEMORY) {
-               node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
-                               BIT(LRU_UNEVICTABLE));
-               seq_printf(m, " N%d=%lu", nid, node_nr);
-       }
-       seq_putc(m, '\n');
        return 0;
  }
  #endif /* CONFIG_NUMA */
@@@ -6179,6 -6165,7 +6178,6 @@@ static void __mem_cgroup_free(struct me
        size_t size = memcg_size();
  
        mem_cgroup_remove_from_trees(memcg);
 -      free_css_id(&mem_cgroup_subsys, &memcg->css);
  
        for_each_node(node)
                free_mem_cgroup_per_zone_info(memcg, node);
@@@ -6281,9 -6268,6 +6280,9 @@@ mem_cgroup_css_online(struct cgroup_sub
        struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(css));
        int error = 0;
  
 +      if (css->cgroup->id > MEM_CGROUP_ID_MAX)
 +              return -ENOSPC;
 +
        if (!parent)
                return 0;
  
@@@ -6555,7 -6539,7 +6554,7 @@@ static enum mc_target_type get_mctgt_ty
        }
        /* There is a swap entry and a page doesn't exist or isn't charged */
        if (ent.val && !ret &&
 -                      css_id(&mc.from->css) == lookup_swap_cgroup_id(ent)) {
 +          mem_cgroup_id(mc.from) == lookup_swap_cgroup_id(ent)) {
                ret = MC_TARGET_SWAP;
                if (target)
                        target->ent = ent;
@@@ -6975,6 -6959,7 +6974,6 @@@ struct cgroup_subsys mem_cgroup_subsys 
        .bind = mem_cgroup_bind,
        .base_cftypes = mem_cgroup_files,
        .early_init = 0,
 -      .use_id = 1,
  };
  
  #ifdef CONFIG_MEMCG_SWAP
diff --combined mm/memory.c
index 33a3dbec3cc87bca1ccea07841496897929ed0bd,15744b2cf919528f7ca813997ceaf34295c584d8..bf8665849a5fed0b93f6022670c7c571e7eea8c6
@@@ -453,8 -453,6 +453,6 @@@ static inline void free_pud_range(struc
  
  /*
   * This function frees user-level page tables of a process.
-  *
-  * Must be called with pagetable lock held.
   */
  void free_pgd_range(struct mmu_gather *tlb,
                        unsigned long addr, unsigned long end,
@@@ -681,7 -679,7 +679,7 @@@ static void print_bad_pte(struct vm_are
        if (vma->vm_ops)
                printk(KERN_ALERT "vma->vm_ops->fault: %pSR\n",
                       vma->vm_ops->fault);
 -      if (vma->vm_file && vma->vm_file->f_op)
 +      if (vma->vm_file)
                printk(KERN_ALERT "vma->vm_file->f_op->mmap: %pSR\n",
                       vma->vm_file->f_op->mmap);
        dump_stack();
diff --combined mm/mmap.c
index ab199dfc9e26889fbba305ba09b2ab517dd591f7,803048e9c5686caef931c4634c901fa80152e6a9..5a6baddde15d955e72e674e5bd468b9e95eceeb0
+++ b/mm/mmap.c
@@@ -179,14 -179,12 +179,12 @@@ int __vm_enough_memory(struct mm_struc
                goto error;
        }
  
-       allowed = (totalram_pages - hugetlb_total_pages())
-               * sysctl_overcommit_ratio / 100;
+       allowed = vm_commit_limit();
        /*
         * Reserve some for root
         */
        if (!cap_sys_admin)
                allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
-       allowed += total_swap_pages;
  
        /*
         * Don't let a single process grow so big a user can't recover
@@@ -1299,7 -1297,7 +1297,7 @@@ unsigned long do_mmap_pgoff(struct fil
                                vm_flags &= ~VM_MAYEXEC;
                        }
  
 -                      if (!file->f_op || !file->f_op->mmap)
 +                      if (!file->f_op->mmap)
                                return -ENODEV;
                        if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
                                return -EINVAL;
@@@ -1856,7 -1854,7 +1854,7 @@@ arch_get_unmapped_area(struct file *fil
        struct vm_area_struct *vma;
        struct vm_unmapped_area_info info;
  
-       if (len > TASK_SIZE)
+       if (len > TASK_SIZE - mmap_min_addr)
                return -ENOMEM;
  
        if (flags & MAP_FIXED)
        if (addr) {
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
-               if (TASK_SIZE - len >= addr &&
+               if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
  
        info.flags = 0;
        info.length = len;
-       info.low_limit = TASK_UNMAPPED_BASE;
+       info.low_limit = mm->mmap_base;
        info.high_limit = TASK_SIZE;
        info.align_mask = 0;
        return vm_unmapped_area(&info);
@@@ -1895,7 -1893,7 +1893,7 @@@ arch_get_unmapped_area_topdown(struct f
        struct vm_unmapped_area_info info;
  
        /* requested length too big for entire address space */
-       if (len > TASK_SIZE)
+       if (len > TASK_SIZE - mmap_min_addr)
                return -ENOMEM;
  
        if (flags & MAP_FIXED)
        if (addr) {
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
-               if (TASK_SIZE - len >= addr &&
+               if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
                                (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
  
        info.flags = VM_UNMAPPED_AREA_TOPDOWN;
        info.length = len;
-       info.low_limit = PAGE_SIZE;
+       info.low_limit = max(PAGE_SIZE, mmap_min_addr);
        info.high_limit = mm->mmap_base;
        info.align_mask = 0;
        addr = vm_unmapped_area(&info);
@@@ -1951,7 -1949,7 +1949,7 @@@ get_unmapped_area(struct file *file, un
                return -ENOMEM;
  
        get_area = current->mm->get_unmapped_area;
 -      if (file && file->f_op && file->f_op->get_unmapped_area)
 +      if (file && file->f_op->get_unmapped_area)
                get_area = file->f_op->get_unmapped_area;
        addr = get_area(file, addr, len, pgoff, flags);
        if (IS_ERR_VALUE(addr))
diff --combined mm/nommu.c
index 9e6cb02cba644c4ec357775e2acb22c5451f2ee7,d8a957bb9e3160dc4d4f943deb020ec8279887d6..fec093adad9c1d65799206805f3d95fe19a1da88
@@@ -937,7 -937,7 +937,7 @@@ static int validate_mmap_request(struc
                struct address_space *mapping;
  
                /* files must support mmap */
 -              if (!file->f_op || !file->f_op->mmap)
 +              if (!file->f_op->mmap)
                        return -ENODEV;
  
                /* work out if what we've got could possibly be shared
@@@ -1948,13 -1948,12 +1948,12 @@@ int __vm_enough_memory(struct mm_struc
                goto error;
        }
  
-       allowed = totalram_pages * sysctl_overcommit_ratio / 100;
+       allowed = vm_commit_limit();
        /*
         * Reserve some 3% for root
         */
        if (!cap_sys_admin)
                allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
-       allowed += total_swap_pages;
  
        /*
         * Don't let a single process grow so big a user can't recover
This page took 0.134481 seconds and 4 git commands to generate.