]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 29 Jun 2015 21:23:16 +0000 (14:23 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 29 Jun 2015 21:23:16 +0000 (14:23 -0700)
added patches:
fput-turn-list_head-delayed_fput_list-into-llist_head.patch
get-rid-of-s_files-and-files_lock.patch

queue-3.10/fput-turn-list_head-delayed_fput_list-into-llist_head.patch [new file with mode: 0644]
queue-3.10/get-rid-of-s_files-and-files_lock.patch [new file with mode: 0644]
queue-3.10/series [new file with mode: 0644]

diff --git a/queue-3.10/fput-turn-list_head-delayed_fput_list-into-llist_head.patch b/queue-3.10/fput-turn-list_head-delayed_fput_list-into-llist_head.patch
new file mode 100644 (file)
index 0000000..433b128
--- /dev/null
@@ -0,0 +1,100 @@
+From 4f5e65a1cc90bbb15b9f6cdc362922af1bcc155a Mon Sep 17 00:00:00 2001
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Mon, 8 Jul 2013 14:24:16 -0700
+Subject: fput: turn "list_head delayed_fput_list" into llist_head
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+commit 4f5e65a1cc90bbb15b9f6cdc362922af1bcc155a upstream.
+
+fput() and delayed_fput() can use llist and avoid the locking.
+
+This is unlikely path, it is not that this change can improve
+the performance, but this way the code looks simpler.
+
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Suggested-by: Andrew Morton <akpm@linux-foundation.org>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Andrey Vagin <avagin@openvz.org>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: David Howells <dhowells@redhat.com>
+Cc: Huang Ying <ying.huang@intel.com>
+Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Wang Kai <morgan.wang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/file_table.c    |   25 ++++++++++---------------
+ include/linux/fs.h |    2 ++
+ 2 files changed, 12 insertions(+), 15 deletions(-)
+
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -265,18 +265,15 @@ static void __fput(struct file *file)
+       mntput(mnt);
+ }
+-static DEFINE_SPINLOCK(delayed_fput_lock);
+-static LIST_HEAD(delayed_fput_list);
++static LLIST_HEAD(delayed_fput_list);
+ static void delayed_fput(struct work_struct *unused)
+ {
+-      LIST_HEAD(head);
+-      spin_lock_irq(&delayed_fput_lock);
+-      list_splice_init(&delayed_fput_list, &head);
+-      spin_unlock_irq(&delayed_fput_lock);
+-      while (!list_empty(&head)) {
+-              struct file *f = list_first_entry(&head, struct file, f_u.fu_list);
+-              list_del_init(&f->f_u.fu_list);
+-              __fput(f);
++      struct llist_node *node = llist_del_all(&delayed_fput_list);
++      struct llist_node *next;
++
++      for (; node; node = next) {
++              next = llist_next(node);
++              __fput(llist_entry(node, struct file, f_u.fu_llist));
+       }
+ }
+@@ -306,7 +303,6 @@ void fput(struct file *file)
+ {
+       if (atomic_long_dec_and_test(&file->f_count)) {
+               struct task_struct *task = current;
+-              unsigned long flags;
+               file_sb_list_del(file);
+               if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) {
+@@ -314,10 +310,9 @@ void fput(struct file *file)
+                       if (!task_work_add(task, &file->f_u.fu_rcuhead, true))
+                               return;
+               }
+-              spin_lock_irqsave(&delayed_fput_lock, flags);
+-              list_add(&file->f_u.fu_list, &delayed_fput_list);
+-              schedule_work(&delayed_fput_work);
+-              spin_unlock_irqrestore(&delayed_fput_lock, flags);
++
++              if (llist_add(&file->f_u.fu_llist, &delayed_fput_list))
++                      schedule_work(&delayed_fput_work);
+       }
+ }
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -10,6 +10,7 @@
+ #include <linux/stat.h>
+ #include <linux/cache.h>
+ #include <linux/list.h>
++#include <linux/llist.h>
+ #include <linux/radix-tree.h>
+ #include <linux/rbtree.h>
+ #include <linux/init.h>
+@@ -767,6 +768,7 @@ struct file {
+        */
+       union {
+               struct list_head        fu_list;
++              struct llist_node       fu_llist;
+               struct rcu_head         fu_rcuhead;
+       } f_u;
+       struct path             f_path;
diff --git a/queue-3.10/get-rid-of-s_files-and-files_lock.patch b/queue-3.10/get-rid-of-s_files-and-files_lock.patch
new file mode 100644 (file)
index 0000000..cec0765
--- /dev/null
@@ -0,0 +1,315 @@
+From eee5cc2702929fd41cce28058dc6d6717f723f87 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Fri, 4 Oct 2013 11:06:42 -0400
+Subject: get rid of s_files and files_lock
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit eee5cc2702929fd41cce28058dc6d6717f723f87 upstream.
+
+The only thing we need it for is alt-sysrq-r (emergency remount r/o)
+and these days we can do just as well without going through the
+list of files.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+[wangkai: backport to 3.10: adjust context]
+Signed-off-by: Wang Kai <morgan.wang@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/file_table.c    |  123 -----------------------------------------------------
+ fs/internal.h      |    3 -
+ fs/open.c          |    2 
+ fs/super.c         |   23 ---------
+ include/linux/fs.h |   13 -----
+ 5 files changed, 2 insertions(+), 162 deletions(-)
+
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -36,8 +36,6 @@ struct files_stat_struct files_stat = {
+       .max_files = NR_FILE
+ };
+-DEFINE_STATIC_LGLOCK(files_lglock);
+-
+ /* SLAB cache for file structures */
+ static struct kmem_cache *filp_cachep __read_mostly;
+@@ -134,7 +132,6 @@ struct file *get_empty_filp(void)
+               return ERR_PTR(error);
+       }
+-      INIT_LIST_HEAD(&f->f_u.fu_list);
+       atomic_long_set(&f->f_count, 1);
+       rwlock_init(&f->f_owner.lock);
+       spin_lock_init(&f->f_lock);
+@@ -304,7 +301,6 @@ void fput(struct file *file)
+       if (atomic_long_dec_and_test(&file->f_count)) {
+               struct task_struct *task = current;
+-              file_sb_list_del(file);
+               if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) {
+                       init_task_work(&file->f_u.fu_rcuhead, ____fput);
+                       if (!task_work_add(task, &file->f_u.fu_rcuhead, true))
+@@ -328,7 +324,6 @@ void __fput_sync(struct file *file)
+ {
+       if (atomic_long_dec_and_test(&file->f_count)) {
+               struct task_struct *task = current;
+-              file_sb_list_del(file);
+               BUG_ON(!(task->flags & PF_KTHREAD));
+               __fput(file);
+       }
+@@ -340,127 +335,10 @@ void put_filp(struct file *file)
+ {
+       if (atomic_long_dec_and_test(&file->f_count)) {
+               security_file_free(file);
+-              file_sb_list_del(file);
+               file_free(file);
+       }
+ }
+-static inline int file_list_cpu(struct file *file)
+-{
+-#ifdef CONFIG_SMP
+-      return file->f_sb_list_cpu;
+-#else
+-      return smp_processor_id();
+-#endif
+-}
+-
+-/* helper for file_sb_list_add to reduce ifdefs */
+-static inline void __file_sb_list_add(struct file *file, struct super_block *sb)
+-{
+-      struct list_head *list;
+-#ifdef CONFIG_SMP
+-      int cpu;
+-      cpu = smp_processor_id();
+-      file->f_sb_list_cpu = cpu;
+-      list = per_cpu_ptr(sb->s_files, cpu);
+-#else
+-      list = &sb->s_files;
+-#endif
+-      list_add(&file->f_u.fu_list, list);
+-}
+-
+-/**
+- * file_sb_list_add - add a file to the sb's file list
+- * @file: file to add
+- * @sb: sb to add it to
+- *
+- * Use this function to associate a file with the superblock of the inode it
+- * refers to.
+- */
+-void file_sb_list_add(struct file *file, struct super_block *sb)
+-{
+-      lg_local_lock(&files_lglock);
+-      __file_sb_list_add(file, sb);
+-      lg_local_unlock(&files_lglock);
+-}
+-
+-/**
+- * file_sb_list_del - remove a file from the sb's file list
+- * @file: file to remove
+- * @sb: sb to remove it from
+- *
+- * Use this function to remove a file from its superblock.
+- */
+-void file_sb_list_del(struct file *file)
+-{
+-      if (!list_empty(&file->f_u.fu_list)) {
+-              lg_local_lock_cpu(&files_lglock, file_list_cpu(file));
+-              list_del_init(&file->f_u.fu_list);
+-              lg_local_unlock_cpu(&files_lglock, file_list_cpu(file));
+-      }
+-}
+-
+-#ifdef CONFIG_SMP
+-
+-/*
+- * These macros iterate all files on all CPUs for a given superblock.
+- * files_lglock must be held globally.
+- */
+-#define do_file_list_for_each_entry(__sb, __file)             \
+-{                                                             \
+-      int i;                                                  \
+-      for_each_possible_cpu(i) {                              \
+-              struct list_head *list;                         \
+-              list = per_cpu_ptr((__sb)->s_files, i);         \
+-              list_for_each_entry((__file), list, f_u.fu_list)
+-
+-#define while_file_list_for_each_entry                                \
+-      }                                                       \
+-}
+-
+-#else
+-
+-#define do_file_list_for_each_entry(__sb, __file)             \
+-{                                                             \
+-      struct list_head *list;                                 \
+-      list = &(sb)->s_files;                                  \
+-      list_for_each_entry((__file), list, f_u.fu_list)
+-
+-#define while_file_list_for_each_entry                                \
+-}
+-
+-#endif
+-
+-/**
+- *    mark_files_ro - mark all files read-only
+- *    @sb: superblock in question
+- *
+- *    All files are marked read-only.  We don't care about pending
+- *    delete files so this should be used in 'force' mode only.
+- */
+-void mark_files_ro(struct super_block *sb)
+-{
+-      struct file *f;
+-
+-      lg_global_lock(&files_lglock);
+-      do_file_list_for_each_entry(sb, f) {
+-              if (!S_ISREG(file_inode(f)->i_mode))
+-                     continue;
+-              if (!file_count(f))
+-                      continue;
+-              if (!(f->f_mode & FMODE_WRITE))
+-                      continue;
+-              spin_lock(&f->f_lock);
+-              f->f_mode &= ~FMODE_WRITE;
+-              spin_unlock(&f->f_lock);
+-              if (file_check_writeable(f) != 0)
+-                      continue;
+-              __mnt_drop_write(f->f_path.mnt);
+-              file_release_write(f);
+-      } while_file_list_for_each_entry;
+-      lg_global_unlock(&files_lglock);
+-}
+-
+ void __init files_init(unsigned long mempages)
+ { 
+       unsigned long n;
+@@ -476,6 +354,5 @@ void __init files_init(unsigned long mem
+       n = (mempages * (PAGE_SIZE / 1024)) / 10;
+       files_stat.max_files = max_t(unsigned long, n, NR_FILE);
+       files_defer_init();
+-      lg_lock_init(&files_lglock, "files_lglock");
+       percpu_counter_init(&nr_files, 0);
+ } 
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -74,9 +74,6 @@ extern void chroot_fs_refs(const struct
+ /*
+  * file_table.c
+  */
+-extern void file_sb_list_add(struct file *f, struct super_block *sb);
+-extern void file_sb_list_del(struct file *f);
+-extern void mark_files_ro(struct super_block *);
+ extern struct file *get_empty_filp(void);
+ /*
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -674,7 +674,6 @@ static int do_dentry_open(struct file *f
+       }
+       f->f_mapping = inode->i_mapping;
+-      file_sb_list_add(f, inode->i_sb);
+       if (unlikely(f->f_mode & FMODE_PATH)) {
+               f->f_op = &empty_fops;
+@@ -709,7 +708,6 @@ static int do_dentry_open(struct file *f
+ cleanup_all:
+       fops_put(f->f_op);
+-      file_sb_list_del(f);
+       if (f->f_mode & FMODE_WRITE) {
+               if (!special_file(inode->i_mode)) {
+                       /*
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -163,19 +163,6 @@ static struct super_block *alloc_super(s
+                       s = NULL;
+                       goto out;
+               }
+-#ifdef CONFIG_SMP
+-              s->s_files = alloc_percpu(struct list_head);
+-              if (!s->s_files)
+-                      goto err_out;
+-              else {
+-                      int i;
+-
+-                      for_each_possible_cpu(i)
+-                              INIT_LIST_HEAD(per_cpu_ptr(s->s_files, i));
+-              }
+-#else
+-              INIT_LIST_HEAD(&s->s_files);
+-#endif
+               if (init_sb_writers(s, type))
+                       goto err_out;
+               s->s_flags = flags;
+@@ -225,10 +212,6 @@ out:
+       return s;
+ err_out:
+       security_sb_free(s);
+-#ifdef CONFIG_SMP
+-      if (s->s_files)
+-              free_percpu(s->s_files);
+-#endif
+       destroy_sb_writers(s);
+       kfree(s);
+       s = NULL;
+@@ -243,9 +226,6 @@ err_out:
+  */
+ static inline void destroy_super(struct super_block *s)
+ {
+-#ifdef CONFIG_SMP
+-      free_percpu(s->s_files);
+-#endif
+       destroy_sb_writers(s);
+       security_sb_free(s);
+       WARN_ON(!list_empty(&s->s_mounts));
+@@ -727,7 +707,8 @@ int do_remount_sb(struct super_block *sb
+          make sure there are no rw files opened */
+       if (remount_ro) {
+               if (force) {
+-                      mark_files_ro(sb);
++                      sb->s_readonly_remount = 1;
++                      smp_wmb();
+               } else {
+                       retval = sb_prepare_remount_readonly(sb);
+                       if (retval)
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -762,12 +762,7 @@ static inline int ra_has_index(struct fi
+ #define FILE_MNT_WRITE_RELEASED       2
+ struct file {
+-      /*
+-       * fu_list becomes invalid after file_free is called and queued via
+-       * fu_rcuhead for RCU freeing
+-       */
+       union {
+-              struct list_head        fu_list;
+               struct llist_node       fu_llist;
+               struct rcu_head         fu_rcuhead;
+       } f_u;
+@@ -781,9 +776,6 @@ struct file {
+        * Must not be taken from IRQ context.
+        */
+       spinlock_t              f_lock;
+-#ifdef CONFIG_SMP
+-      int                     f_sb_list_cpu;
+-#endif
+       atomic_long_t           f_count;
+       unsigned int            f_flags;
+       fmode_t                 f_mode;
+@@ -1259,11 +1251,6 @@ struct super_block {
+       struct list_head        s_inodes;       /* all inodes */
+       struct hlist_bl_head    s_anon;         /* anonymous dentries for (nfs) exporting */
+-#ifdef CONFIG_SMP
+-      struct list_head __percpu *s_files;
+-#else
+-      struct list_head        s_files;
+-#endif
+       struct list_head        s_mounts;       /* list of mounts; _not_ for fs use */
+       /* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */
+       struct list_head        s_dentry_lru;   /* unused dentry lru */
diff --git a/queue-3.10/series b/queue-3.10/series
new file mode 100644 (file)
index 0000000..ccf01f7
--- /dev/null
@@ -0,0 +1,2 @@
+fput-turn-list_head-delayed_fput_list-into-llist_head.patch
+get-rid-of-s_files-and-files_lock.patch