Author: mpagano
Date: 2014-04-04 00:13:19 +0000 (Fri, 04 Apr 2014)
New Revision: 2735

Added:
   genpatches-2.6/trunk/3.13/1008_linux-3.13.9.patch
Modified:
   genpatches-2.6/trunk/3.13/0000_README
Log:
Linux patch 3.13.9

Modified: genpatches-2.6/trunk/3.13/0000_README
===================================================================
--- genpatches-2.6/trunk/3.13/0000_README       2014-04-02 14:23:41 UTC (rev 
2734)
+++ genpatches-2.6/trunk/3.13/0000_README       2014-04-04 00:13:19 UTC (rev 
2735)
@@ -74,6 +74,10 @@
 From:   http://www.kernel.org
 Desc:   Linux 3.13.8
 
+Patch:  1008_linux-3.13.9.patch
+From:   http://www.kernel.org
+Desc:   Linux 3.13.9
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

Added: genpatches-2.6/trunk/3.13/1008_linux-3.13.9.patch
===================================================================
--- genpatches-2.6/trunk/3.13/1008_linux-3.13.9.patch                           
(rev 0)
+++ genpatches-2.6/trunk/3.13/1008_linux-3.13.9.patch   2014-04-04 00:13:19 UTC 
(rev 2735)
@@ -0,0 +1,1425 @@
+diff --git a/Makefile b/Makefile
+index 4cab13b605c1..652f97296a40 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 3
+ PATCHLEVEL = 13
+-SUBLEVEL = 8
++SUBLEVEL = 9
+ EXTRAVERSION =
+ NAME = One Giant Leap for Frogkind
+ 
+diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
+index 5ad38ad07890..bbc8b12fa443 100644
+--- a/arch/x86/include/asm/pgtable.h
++++ b/arch/x86/include/asm/pgtable.h
+@@ -445,20 +445,10 @@ static inline int pte_same(pte_t a, pte_t b)
+       return a.pte == b.pte;
+ }
+ 
+-static inline int pteval_present(pteval_t pteval)
+-{
+-      /*
+-       * Yes Linus, _PAGE_PROTNONE == _PAGE_NUMA. Expressing it this
+-       * way clearly states that the intent is that protnone and numa
+-       * hinting ptes are considered present for the purposes of
+-       * pagetable operations like zapping, protection changes, gup etc.
+-       */
+-      return pteval & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_NUMA);
+-}
+-
+ static inline int pte_present(pte_t a)
+ {
+-      return pteval_present(pte_flags(a));
++      return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE |
++                             _PAGE_NUMA);
+ }
+ 
+ #define pte_accessible pte_accessible
+diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
+index d35f24e231cd..1306d117967d 100644
+--- a/arch/x86/include/asm/topology.h
++++ b/arch/x86/include/asm/topology.h
+@@ -119,9 +119,10 @@ static inline void setup_node_to_cpumask_map(void) { }
+ 
+ extern const struct cpumask *cpu_coregroup_mask(int cpu);
+ 
+-#ifdef ENABLE_TOPO_DEFINES
+ #define topology_physical_package_id(cpu)     (cpu_data(cpu).phys_proc_id)
+ #define topology_core_id(cpu)                 (cpu_data(cpu).cpu_core_id)
++
++#ifdef ENABLE_TOPO_DEFINES
+ #define topology_core_cpumask(cpu)            (per_cpu(cpu_core_map, cpu))
+ #define topology_thread_cpumask(cpu)          (per_cpu(cpu_sibling_map, cpu))
+ #endif
+diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
+index 3c76c3d50471..ce563be09cc1 100644
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -365,7 +365,7 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, 
unsigned long addr,
+ /* Assume pteval_t is equivalent to all the other *val_t types. */
+ static pteval_t pte_mfn_to_pfn(pteval_t val)
+ {
+-      if (pteval_present(val)) {
++      if (val & _PAGE_PRESENT) {
+               unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+               unsigned long pfn = mfn_to_pfn(mfn);
+ 
+@@ -381,7 +381,7 @@ static pteval_t pte_mfn_to_pfn(pteval_t val)
+ 
+ static pteval_t pte_pfn_to_mfn(pteval_t val)
+ {
+-      if (pteval_present(val)) {
++      if (val & _PAGE_PRESENT) {
+               unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+               pteval_t flags = val & PTE_FLAGS_MASK;
+               unsigned long mfn;
+diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
+index d2515435e23f..8fb295350efb 100644
+--- a/drivers/block/aoe/aoecmd.c
++++ b/drivers/block/aoe/aoecmd.c
+@@ -905,7 +905,7 @@ bio_pageinc(struct bio *bio)
+               /* Non-zero page count for non-head members of
+                * compound pages is no longer allowed by the kernel.
+                */
+-              page = compound_trans_head(bv->bv_page);
++              page = compound_head(bv->bv_page);
+               atomic_inc(&page->_count);
+       }
+ }
+@@ -918,7 +918,7 @@ bio_pagedec(struct bio *bio)
+       int i;
+ 
+       bio_for_each_segment(bv, bio, i) {
+-              page = compound_trans_head(bv->bv_page);
++              page = compound_head(bv->bv_page);
+               atomic_dec(&page->_count);
+       }
+ }
+diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c 
b/drivers/gpu/drm/i915/i915_gem_gtt.c
+index d3c3b5b15824..e79720d5ceff 100644
+--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
++++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
+@@ -828,7 +828,7 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
+       dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
+                                      dev_priv->gtt.base.start / PAGE_SIZE,
+                                      dev_priv->gtt.base.total / PAGE_SIZE,
+-                                     false);
++                                     true);
+ }
+ 
+ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
+diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
+index 3e5ea2c87a6e..886778a60d35 100644
+--- a/drivers/i2c/busses/i2c-cpm.c
++++ b/drivers/i2c/busses/i2c-cpm.c
+@@ -40,7 +40,9 @@
+ #include <linux/i2c.h>
+ #include <linux/io.h>
+ #include <linux/dma-mapping.h>
++#include <linux/of_address.h>
+ #include <linux/of_device.h>
++#include <linux/of_irq.h>
+ #include <linux/of_platform.h>
+ #include <sysdev/fsl_soc.h>
+ #include <asm/cpm.h>
+diff --git a/drivers/input/mouse/cypress_ps2.c 
b/drivers/input/mouse/cypress_ps2.c
+index a5869a856ea5..bba656a3336e 100644
+--- a/drivers/input/mouse/cypress_ps2.c
++++ b/drivers/input/mouse/cypress_ps2.c
+@@ -410,7 +410,6 @@ static int cypress_set_input_params(struct input_dev 
*input,
+       __clear_bit(REL_X, input->relbit);
+       __clear_bit(REL_Y, input->relbit);
+ 
+-      __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+       __set_bit(EV_KEY, input->evbit);
+       __set_bit(BTN_LEFT, input->keybit);
+       __set_bit(BTN_RIGHT, input->keybit);
+diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
+index 26386f9d2569..d8d49d10f9bb 100644
+--- a/drivers/input/mouse/synaptics.c
++++ b/drivers/input/mouse/synaptics.c
+@@ -265,11 +265,22 @@ static int synaptics_identify(struct psmouse *psmouse)
+  * Read touchpad resolution and maximum reported coordinates
+  * Resolution is left zero if touchpad does not support the query
+  */
++
++static const int *quirk_min_max;
++
+ static int synaptics_resolution(struct psmouse *psmouse)
+ {
+       struct synaptics_data *priv = psmouse->private;
+       unsigned char resp[3];
+ 
++      if (quirk_min_max) {
++              priv->x_min = quirk_min_max[0];
++              priv->x_max = quirk_min_max[1];
++              priv->y_min = quirk_min_max[2];
++              priv->y_max = quirk_min_max[3];
++              return 0;
++      }
++
+       if (SYN_ID_MAJOR(priv->identity) < 4)
+               return 0;
+ 
+@@ -1485,10 +1496,54 @@ static const struct dmi_system_id olpc_dmi_table[] 
__initconst = {
+       { }
+ };
+ 
++static const struct dmi_system_id min_max_dmi_table[] __initconst = {
++#if defined(CONFIG_DMI)
++      {
++              /* Lenovo ThinkPad Helix */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++                      DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
++              },
++              .driver_data = (int []){1024, 5052, 2258, 4832},
++      },
++      {
++              /* Lenovo ThinkPad X240 */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++                      DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X240"),
++              },
++              .driver_data = (int []){1232, 5710, 1156, 4696},
++      },
++      {
++              /* Lenovo ThinkPad T440s */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++                      DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
++              },
++              .driver_data = (int []){1024, 5112, 2024, 4832},
++      },
++      {
++              /* Lenovo ThinkPad T540p */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++                      DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"),
++              },
++              .driver_data = (int []){1024, 5056, 2058, 4832},
++      },
++#endif
++      { }
++};
++
+ void __init synaptics_module_init(void)
+ {
++      const struct dmi_system_id *min_max_dmi;
++
+       impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
+       broken_olpc_ec = dmi_check_system(olpc_dmi_table);
++
++      min_max_dmi = dmi_first_match(min_max_dmi_table);
++      if (min_max_dmi)
++              quirk_min_max = min_max_dmi->driver_data;
+ }
+ 
+ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
+diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
+index 4c842c320c2e..b604564dec5c 100644
+--- a/drivers/input/mousedev.c
++++ b/drivers/input/mousedev.c
+@@ -67,7 +67,6 @@ struct mousedev {
+       struct device dev;
+       struct cdev cdev;
+       bool exist;
+-      bool is_mixdev;
+ 
+       struct list_head mixdev_node;
+       bool opened_by_mixdev;
+@@ -77,6 +76,9 @@ struct mousedev {
+       int old_x[4], old_y[4];
+       int frac_dx, frac_dy;
+       unsigned long touch;
++
++      int (*open_device)(struct mousedev *mousedev);
++      void (*close_device)(struct mousedev *mousedev);
+ };
+ 
+ enum mousedev_emul {
+@@ -116,9 +118,6 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 
0xf3, 200, 0xf3, 80 };
+ static struct mousedev *mousedev_mix;
+ static LIST_HEAD(mousedev_mix_list);
+ 
+-static void mixdev_open_devices(void);
+-static void mixdev_close_devices(void);
+-
+ #define fx(i)  (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
+ #define fy(i)  (mousedev->old_y[(mousedev->pkt_count - (i)) & 03])
+ 
+@@ -428,9 +427,7 @@ static int mousedev_open_device(struct mousedev *mousedev)
+       if (retval)
+               return retval;
+ 
+-      if (mousedev->is_mixdev)
+-              mixdev_open_devices();
+-      else if (!mousedev->exist)
++      if (!mousedev->exist)
+               retval = -ENODEV;
+       else if (!mousedev->open++) {
+               retval = input_open_device(&mousedev->handle);
+@@ -446,9 +443,7 @@ static void mousedev_close_device(struct mousedev 
*mousedev)
+ {
+       mutex_lock(&mousedev->mutex);
+ 
+-      if (mousedev->is_mixdev)
+-              mixdev_close_devices();
+-      else if (mousedev->exist && !--mousedev->open)
++      if (mousedev->exist && !--mousedev->open)
+               input_close_device(&mousedev->handle);
+ 
+       mutex_unlock(&mousedev->mutex);
+@@ -459,21 +454,29 @@ static void mousedev_close_device(struct mousedev 
*mousedev)
+  * stream. Note that this function is called with mousedev_mix->mutex
+  * held.
+  */
+-static void mixdev_open_devices(void)
++static int mixdev_open_devices(struct mousedev *mixdev)
+ {
+-      struct mousedev *mousedev;
++      int error;
++
++      error = mutex_lock_interruptible(&mixdev->mutex);
++      if (error)
++              return error;
+ 
+-      if (mousedev_mix->open++)
+-              return;
++      if (!mixdev->open++) {
++              struct mousedev *mousedev;
+ 
+-      list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
+-              if (!mousedev->opened_by_mixdev) {
+-                      if (mousedev_open_device(mousedev))
+-                              continue;
++              list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
++                      if (!mousedev->opened_by_mixdev) {
++                              if (mousedev_open_device(mousedev))
++                                      continue;
+ 
+-                      mousedev->opened_by_mixdev = true;
++                              mousedev->opened_by_mixdev = true;
++                      }
+               }
+       }
++
++      mutex_unlock(&mixdev->mutex);
++      return 0;
+ }
+ 
+ /*
+@@ -481,19 +484,22 @@ static void mixdev_open_devices(void)
+  * device. Note that this function is called with mousedev_mix->mutex
+  * held.
+  */
+-static void mixdev_close_devices(void)
++static void mixdev_close_devices(struct mousedev *mixdev)
+ {
+-      struct mousedev *mousedev;
++      mutex_lock(&mixdev->mutex);
+ 
+-      if (--mousedev_mix->open)
+-              return;
++      if (!--mixdev->open) {
++              struct mousedev *mousedev;
+ 
+-      list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
+-              if (mousedev->opened_by_mixdev) {
+-                      mousedev->opened_by_mixdev = false;
+-                      mousedev_close_device(mousedev);
++              list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
++                      if (mousedev->opened_by_mixdev) {
++                              mousedev->opened_by_mixdev = false;
++                              mousedev_close_device(mousedev);
++                      }
+               }
+       }
++
++      mutex_unlock(&mixdev->mutex);
+ }
+ 
+ 
+@@ -522,7 +528,7 @@ static int mousedev_release(struct inode *inode, struct 
file *file)
+       mousedev_detach_client(mousedev, client);
+       kfree(client);
+ 
+-      mousedev_close_device(mousedev);
++      mousedev->close_device(mousedev);
+ 
+       return 0;
+ }
+@@ -550,7 +556,7 @@ static int mousedev_open(struct inode *inode, struct file 
*file)
+       client->mousedev = mousedev;
+       mousedev_attach_client(mousedev, client);
+ 
+-      error = mousedev_open_device(mousedev);
++      error = mousedev->open_device(mousedev);
+       if (error)
+               goto err_free_client;
+ 
+@@ -861,16 +867,21 @@ static struct mousedev *mousedev_create(struct input_dev 
*dev,
+ 
+       if (mixdev) {
+               dev_set_name(&mousedev->dev, "mice");
++
++              mousedev->open_device = mixdev_open_devices;
++              mousedev->close_device = mixdev_close_devices;
+       } else {
+               int dev_no = minor;
+               /* Normalize device number if it falls into legacy range */
+               if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS)
+                       dev_no -= MOUSEDEV_MINOR_BASE;
+               dev_set_name(&mousedev->dev, "mouse%d", dev_no);
++
++              mousedev->open_device = mousedev_open_device;
++              mousedev->close_device = mousedev_close_device;
+       }
+ 
+       mousedev->exist = true;
+-      mousedev->is_mixdev = mixdev;
+       mousedev->handle.dev = input_get_device(dev);
+       mousedev->handle.name = dev_name(&mousedev->dev);
+       mousedev->handle.handler = handler;
+@@ -919,7 +930,7 @@ static void mousedev_destroy(struct mousedev *mousedev)
+       device_del(&mousedev->dev);
+       mousedev_cleanup(mousedev);
+       input_free_minor(MINOR(mousedev->dev.devt));
+-      if (!mousedev->is_mixdev)
++      if (mousedev != mousedev_mix)
+               input_unregister_handle(&mousedev->handle);
+       put_device(&mousedev->dev);
+ }
+diff --git a/drivers/net/ethernet/marvell/mvneta.c 
b/drivers/net/ethernet/marvell/mvneta.c
+index df75a2302740..bb2021e48344 100644
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -88,8 +88,9 @@
+ #define      MVNETA_TX_IN_PRGRS                  BIT(1)
+ #define      MVNETA_TX_FIFO_EMPTY                BIT(8)
+ #define MVNETA_RX_MIN_FRAME_SIZE                 0x247c
+-#define MVNETA_SGMII_SERDES_CFG                        0x24A0
++#define MVNETA_SERDES_CFG                      0x24A0
+ #define      MVNETA_SGMII_SERDES_PROTO                 0x0cc7
++#define      MVNETA_RGMII_SERDES_PROTO                 0x0667
+ #define MVNETA_TYPE_PRIO                         0x24bc
+ #define      MVNETA_FORCE_UNI                    BIT(21)
+ #define MVNETA_TXQ_CMD_1                         0x24e4
+@@ -161,7 +162,7 @@
+ #define      MVNETA_GMAC_MAX_RX_SIZE_MASK        0x7ffc
+ #define      MVNETA_GMAC0_PORT_ENABLE            BIT(0)
+ #define MVNETA_GMAC_CTRL_2                       0x2c08
+-#define      MVNETA_GMAC2_PSC_ENABLE             BIT(3)
++#define      MVNETA_GMAC2_PCS_ENABLE             BIT(3)
+ #define      MVNETA_GMAC2_PORT_RGMII             BIT(4)
+ #define      MVNETA_GMAC2_PORT_RESET             BIT(6)
+ #define MVNETA_GMAC_STATUS                       0x2c10
+@@ -706,35 +707,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp,
+       mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val);
+ }
+ 
+-
+-
+-/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */
+-static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable)
+-{
+-      u32  val;
+-
+-      val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+-
+-      if (enable)
+-              val |= MVNETA_GMAC2_PORT_RGMII;
+-      else
+-              val &= ~MVNETA_GMAC2_PORT_RGMII;
+-
+-      mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+-}
+-
+-/* Config SGMII port */
+-static void mvneta_port_sgmii_config(struct mvneta_port *pp)
+-{
+-      u32 val;
+-
+-      val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+-      val |= MVNETA_GMAC2_PSC_ENABLE;
+-      mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+-
+-      mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
+-}
+-
+ /* Start the Ethernet port RX and TX activity */
+ static void mvneta_port_up(struct mvneta_port *pp)
+ {
+@@ -2729,12 +2701,15 @@ static void mvneta_port_power_up(struct mvneta_port 
*pp, int phy_mode)
+       mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
+ 
+       if (phy_mode == PHY_INTERFACE_MODE_SGMII)
+-              mvneta_port_sgmii_config(pp);
++              mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
++      else
++              mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_RGMII_SERDES_PROTO);
+ 
+-      mvneta_gmac_rgmii_set(pp, 1);
++      val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
++
++      val |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII;
+ 
+       /* Cancel Port Reset */
+-      val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
+       val &= ~MVNETA_GMAC2_PORT_RESET;
+       mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
+ 
+diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
+index 4fb7a8f83c8a..54af4e933695 100644
+--- a/drivers/vfio/vfio_iommu_type1.c
++++ b/drivers/vfio/vfio_iommu_type1.c
+@@ -186,12 +186,12 @@ static bool is_invalid_reserved_pfn(unsigned long pfn)
+       if (pfn_valid(pfn)) {
+               bool reserved;
+               struct page *tail = pfn_to_page(pfn);
+-              struct page *head = compound_trans_head(tail);
++              struct page *head = compound_head(tail);
+               reserved = !!(PageReserved(head));
+               if (head != tail) {
+                       /*
+                        * "head" is not a dangling pointer
+-                       * (compound_trans_head takes care of that)
++                       * (compound_head takes care of that)
+                        * but the hugepage may have been split
+                        * from under us (and we may not hold a
+                        * reference count on the head page so it can
+diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
+index 4c02e2b94103..2c85267668fc 100644
+--- a/drivers/xen/balloon.c
++++ b/drivers/xen/balloon.c
+@@ -406,11 +406,25 @@ static enum bp_state decrease_reservation(unsigned long 
nr_pages, gfp_t gfp)
+                       state = BP_EAGAIN;
+                       break;
+               }
++              scrub_page(page);
+ 
+-              pfn = page_to_pfn(page);
+-              frame_list[i] = pfn_to_mfn(pfn);
++              frame_list[i] = page_to_pfn(page);
++      }
+ 
+-              scrub_page(page);
++      /*
++       * Ensure that ballooned highmem pages don't have kmaps.
++       *
++       * Do this before changing the p2m as kmap_flush_unused()
++       * reads PTEs to obtain pages (and hence needs the original
++       * p2m entry).
++       */
++      kmap_flush_unused();
++
++      /* Update direct mapping, invalidate P2M, and add to balloon. */
++      for (i = 0; i < nr_pages; i++) {
++              pfn = frame_list[i];
++              frame_list[i] = pfn_to_mfn(pfn);
++              page = pfn_to_page(pfn);
+ 
+ #ifdef CONFIG_XEN_HAVE_PVMMU
+               /*
+@@ -436,11 +450,9 @@ static enum bp_state decrease_reservation(unsigned long 
nr_pages, gfp_t gfp)
+               }
+ #endif
+ 
+-              balloon_append(pfn_to_page(pfn));
++              balloon_append(page);
+       }
+ 
+-      /* Ensure that ballooned highmem pages don't have kmaps. */
+-      kmap_flush_unused();
+       flush_tlb_all();
+ 
+       set_xen_guest_handle(reservation.extent_start, frame_list);
+diff --git a/fs/dcache.c b/fs/dcache.c
+index fdbe23027810..f7ad6d71b1c1 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -2833,9 +2833,9 @@ static int prepend_name(char **buffer, int *buflen, 
struct qstr *name)
+       u32 dlen = ACCESS_ONCE(name->len);
+       char *p;
+ 
+-      if (*buflen < dlen + 1)
+-              return -ENAMETOOLONG;
+       *buflen -= dlen + 1;
++      if (*buflen < 0)
++              return -ENAMETOOLONG;
+       p = *buffer -= dlen + 1;
+       *p++ = '/';
+       while (dlen--) {
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 31fa964742bc..3617e33257a3 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -38,6 +38,7 @@
+ #include <linux/slab.h>
+ #include <linux/ratelimit.h>
+ #include <linux/aio.h>
++#include <linux/bitops.h>
+ 
+ #include "ext4_jbd2.h"
+ #include "xattr.h"
+@@ -3926,18 +3927,20 @@ int ext4_get_inode_loc(struct inode *inode, struct 
ext4_iloc *iloc)
+ void ext4_set_inode_flags(struct inode *inode)
+ {
+       unsigned int flags = EXT4_I(inode)->i_flags;
++      unsigned int new_fl = 0;
+ 
+-      inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
+       if (flags & EXT4_SYNC_FL)
+-              inode->i_flags |= S_SYNC;
++              new_fl |= S_SYNC;
+       if (flags & EXT4_APPEND_FL)
+-              inode->i_flags |= S_APPEND;
++              new_fl |= S_APPEND;
+       if (flags & EXT4_IMMUTABLE_FL)
+-              inode->i_flags |= S_IMMUTABLE;
++              new_fl |= S_IMMUTABLE;
+       if (flags & EXT4_NOATIME_FL)
+-              inode->i_flags |= S_NOATIME;
++              new_fl |= S_NOATIME;
+       if (flags & EXT4_DIRSYNC_FL)
+-              inode->i_flags |= S_DIRSYNC;
++              new_fl |= S_DIRSYNC;
++      set_mask_bits(&inode->i_flags,
++                    S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC, new_fl);
+ }
+ 
+ /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */
+diff --git a/fs/mount.h b/fs/mount.h
+index a17458ca6f29..b29e42f05f34 100644
+--- a/fs/mount.h
++++ b/fs/mount.h
+@@ -19,13 +19,13 @@ struct mnt_pcp {
+ };
+ 
+ struct mountpoint {
+-      struct list_head m_hash;
++      struct hlist_node m_hash;
+       struct dentry *m_dentry;
+       int m_count;
+ };
+ 
+ struct mount {
+-      struct list_head mnt_hash;
++      struct hlist_node mnt_hash;
+       struct mount *mnt_parent;
+       struct dentry *mnt_mountpoint;
+       struct vfsmount mnt;
+diff --git a/fs/namei.c b/fs/namei.c
+index cfe660870251..399f6378de54 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1098,7 +1098,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, 
struct path *path,
+                       return false;
+ 
+               if (!d_mountpoint(path->dentry))
+-                      break;
++                      return true;
+ 
+               mounted = __lookup_mnt(path->mnt, path->dentry);
+               if (!mounted)
+@@ -1114,20 +1114,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, 
struct path *path,
+                */
+               *inode = path->dentry->d_inode;
+       }
+-      return true;
+-}
+-
+-static void follow_mount_rcu(struct nameidata *nd)
+-{
+-      while (d_mountpoint(nd->path.dentry)) {
+-              struct mount *mounted;
+-              mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
+-              if (!mounted)
+-                      break;
+-              nd->path.mnt = &mounted->mnt;
+-              nd->path.dentry = mounted->mnt.mnt_root;
+-              nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
+-      }
++      return read_seqretry(&mount_lock, nd->m_seq);
+ }
+ 
+ static int follow_dotdot_rcu(struct nameidata *nd)
+@@ -1155,7 +1142,17 @@ static int follow_dotdot_rcu(struct nameidata *nd)
+                       break;
+               nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
+       }
+-      follow_mount_rcu(nd);
++      while (d_mountpoint(nd->path.dentry)) {
++              struct mount *mounted;
++              mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
++              if (!mounted)
++                      break;
++              nd->path.mnt = &mounted->mnt;
++              nd->path.dentry = mounted->mnt.mnt_root;
++              nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
++              if (!read_seqretry(&mount_lock, nd->m_seq))
++                      goto failed;
++      }
+       nd->inode = nd->path.dentry->d_inode;
+       return 0;
+ 
+diff --git a/fs/namespace.c b/fs/namespace.c
+index be32ebccdeb1..6d0e54e27d33 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -23,11 +23,34 @@
+ #include <linux/uaccess.h>
+ #include <linux/proc_ns.h>
+ #include <linux/magic.h>
++#include <linux/bootmem.h>
+ #include "pnode.h"
+ #include "internal.h"
+ 
+-#define HASH_SHIFT ilog2(PAGE_SIZE / sizeof(struct list_head))
+-#define HASH_SIZE (1UL << HASH_SHIFT)
++static unsigned int m_hash_mask __read_mostly;
++static unsigned int m_hash_shift __read_mostly;
++static unsigned int mp_hash_mask __read_mostly;
++static unsigned int mp_hash_shift __read_mostly;
++
++static __initdata unsigned long mhash_entries;
++static int __init set_mhash_entries(char *str)
++{
++      if (!str)
++              return 0;
++      mhash_entries = simple_strtoul(str, &str, 0);
++      return 1;
++}
++__setup("mhash_entries=", set_mhash_entries);
++
++static __initdata unsigned long mphash_entries;
++static int __init set_mphash_entries(char *str)
++{
++      if (!str)
++              return 0;
++      mphash_entries = simple_strtoul(str, &str, 0);
++      return 1;
++}
++__setup("mphash_entries=", set_mphash_entries);
+ 
+ static int event;
+ static DEFINE_IDA(mnt_id_ida);
+@@ -36,8 +59,8 @@ static DEFINE_SPINLOCK(mnt_id_lock);
+ static int mnt_id_start = 0;
+ static int mnt_group_start = 1;
+ 
+-static struct list_head *mount_hashtable __read_mostly;
+-static struct list_head *mountpoint_hashtable __read_mostly;
++static struct hlist_head *mount_hashtable __read_mostly;
++static struct hlist_head *mountpoint_hashtable __read_mostly;
+ static struct kmem_cache *mnt_cache __read_mostly;
+ static DECLARE_RWSEM(namespace_sem);
+ 
+@@ -55,12 +78,19 @@ EXPORT_SYMBOL_GPL(fs_kobj);
+  */
+ __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
+ 
+-static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
++static inline struct hlist_head *m_hash(struct vfsmount *mnt, struct dentry 
*dentry)
+ {
+       unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES);
+       tmp += ((unsigned long)dentry / L1_CACHE_BYTES);
+-      tmp = tmp + (tmp >> HASH_SHIFT);
+-      return tmp & (HASH_SIZE - 1);
++      tmp = tmp + (tmp >> m_hash_shift);
++      return &mount_hashtable[tmp & m_hash_mask];
++}
++
++static inline struct hlist_head *mp_hash(struct dentry *dentry)
++{
++      unsigned long tmp = ((unsigned long)dentry / L1_CACHE_BYTES);
++      tmp = tmp + (tmp >> mp_hash_shift);
++      return &mountpoint_hashtable[tmp & mp_hash_mask];
+ }
+ 
+ /*
+@@ -187,7 +217,7 @@ static struct mount *alloc_vfsmnt(const char *name)
+               mnt->mnt_writers = 0;
+ #endif
+ 
+-              INIT_LIST_HEAD(&mnt->mnt_hash);
++              INIT_HLIST_NODE(&mnt->mnt_hash);
+               INIT_LIST_HEAD(&mnt->mnt_child);
+               INIT_LIST_HEAD(&mnt->mnt_mounts);
+               INIT_LIST_HEAD(&mnt->mnt_list);
+@@ -575,10 +605,10 @@ bool legitimize_mnt(struct vfsmount *bastard, unsigned 
seq)
+  */
+ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
+ {
+-      struct list_head *head = mount_hashtable + hash(mnt, dentry);
++      struct hlist_head *head = m_hash(mnt, dentry);
+       struct mount *p;
+ 
+-      list_for_each_entry_rcu(p, head, mnt_hash)
++      hlist_for_each_entry_rcu(p, head, mnt_hash)
+               if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
+                       return p;
+       return NULL;
+@@ -590,13 +620,17 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct 
dentry *dentry)
+  */
+ struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry)
+ {
+-      struct list_head *head = mount_hashtable + hash(mnt, dentry);
+-      struct mount *p;
+-
+-      list_for_each_entry_reverse(p, head, mnt_hash)
+-              if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
+-                      return p;
+-      return NULL;
++      struct mount *p, *res;
++      res = p = __lookup_mnt(mnt, dentry);
++      if (!p)
++              goto out;
++      hlist_for_each_entry_continue(p, mnt_hash) {
++              if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry)
++                      break;
++              res = p;
++      }
++out:
++      return res;
+ }
+ 
+ /*
+@@ -633,11 +667,11 @@ struct vfsmount *lookup_mnt(struct path *path)
+ 
+ static struct mountpoint *new_mountpoint(struct dentry *dentry)
+ {
+-      struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry);
++      struct hlist_head *chain = mp_hash(dentry);
+       struct mountpoint *mp;
+       int ret;
+ 
+-      list_for_each_entry(mp, chain, m_hash) {
++      hlist_for_each_entry(mp, chain, m_hash) {
+               if (mp->m_dentry == dentry) {
+                       /* might be worth a WARN_ON() */
+                       if (d_unlinked(dentry))
+@@ -659,7 +693,7 @@ static struct mountpoint *new_mountpoint(struct dentry 
*dentry)
+ 
+       mp->m_dentry = dentry;
+       mp->m_count = 1;
+-      list_add(&mp->m_hash, chain);
++      hlist_add_head(&mp->m_hash, chain);
+       return mp;
+ }
+ 
+@@ -670,7 +704,7 @@ static void put_mountpoint(struct mountpoint *mp)
+               spin_lock(&dentry->d_lock);
+               dentry->d_flags &= ~DCACHE_MOUNTED;
+               spin_unlock(&dentry->d_lock);
+-              list_del(&mp->m_hash);
++              hlist_del(&mp->m_hash);
+               kfree(mp);
+       }
+ }
+@@ -712,7 +746,7 @@ static void detach_mnt(struct mount *mnt, struct path 
*old_path)
+       mnt->mnt_parent = mnt;
+       mnt->mnt_mountpoint = mnt->mnt.mnt_root;
+       list_del_init(&mnt->mnt_child);
+-      list_del_init(&mnt->mnt_hash);
++      hlist_del_init_rcu(&mnt->mnt_hash);
+       put_mountpoint(mnt->mnt_mp);
+       mnt->mnt_mp = NULL;
+ }
+@@ -739,15 +773,14 @@ static void attach_mnt(struct mount *mnt,
+                       struct mountpoint *mp)
+ {
+       mnt_set_mountpoint(parent, mp, mnt);
+-      list_add_tail(&mnt->mnt_hash, mount_hashtable +
+-                      hash(&parent->mnt, mp->m_dentry));
++      hlist_add_head_rcu(&mnt->mnt_hash, m_hash(&parent->mnt, mp->m_dentry));
+       list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
+ }
+ 
+ /*
+  * vfsmount lock must be held for write
+  */
+-static void commit_tree(struct mount *mnt)
++static void commit_tree(struct mount *mnt, struct mount *shadows)
+ {
+       struct mount *parent = mnt->mnt_parent;
+       struct mount *m;
+@@ -762,8 +795,11 @@ static void commit_tree(struct mount *mnt)
+ 
+       list_splice(&head, n->list.prev);
+ 
+-      list_add_tail(&mnt->mnt_hash, mount_hashtable +
+-                              hash(&parent->mnt, mnt->mnt_mountpoint));
++      if (shadows)
++              hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash);
++      else
++              hlist_add_head_rcu(&mnt->mnt_hash,
++                              m_hash(&parent->mnt, mnt->mnt_mountpoint));
+       list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
+       touch_mnt_namespace(n);
+ }
+@@ -1153,26 +1189,28 @@ int may_umount(struct vfsmount *mnt)
+ 
+ EXPORT_SYMBOL(may_umount);
+ 
+-static LIST_HEAD(unmounted);  /* protected by namespace_sem */
++static HLIST_HEAD(unmounted); /* protected by namespace_sem */
+ 
+ static void namespace_unlock(void)
+ {
+       struct mount *mnt;
+-      LIST_HEAD(head);
++      struct hlist_head head = unmounted;
+ 
+-      if (likely(list_empty(&unmounted))) {
++      if (likely(hlist_empty(&head))) {
+               up_write(&namespace_sem);
+               return;
+       }
+ 
+-      list_splice_init(&unmounted, &head);
++      head.first->pprev = &head.first;
++      INIT_HLIST_HEAD(&unmounted);
++
+       up_write(&namespace_sem);
+ 
+       synchronize_rcu();
+ 
+-      while (!list_empty(&head)) {
+-              mnt = list_first_entry(&head, struct mount, mnt_hash);
+-              list_del_init(&mnt->mnt_hash);
++      while (!hlist_empty(&head)) {
++              mnt = hlist_entry(head.first, struct mount, mnt_hash);
++              hlist_del_init(&mnt->mnt_hash);
+               if (mnt->mnt_ex_mountpoint.mnt)
+                       path_put(&mnt->mnt_ex_mountpoint);
+               mntput(&mnt->mnt);
+@@ -1193,16 +1231,19 @@ static inline void namespace_lock(void)
+  */
+ void umount_tree(struct mount *mnt, int how)
+ {
+-      LIST_HEAD(tmp_list);
++      HLIST_HEAD(tmp_list);
+       struct mount *p;
++      struct mount *last = NULL;
+ 
+-      for (p = mnt; p; p = next_mnt(p, mnt))
+-              list_move(&p->mnt_hash, &tmp_list);
++      for (p = mnt; p; p = next_mnt(p, mnt)) {
++              hlist_del_init_rcu(&p->mnt_hash);
++              hlist_add_head(&p->mnt_hash, &tmp_list);
++      }
+ 
+       if (how)
+               propagate_umount(&tmp_list);
+ 
+-      list_for_each_entry(p, &tmp_list, mnt_hash) {
++      hlist_for_each_entry(p, &tmp_list, mnt_hash) {
+               list_del_init(&p->mnt_expire);
+               list_del_init(&p->mnt_list);
+               __touch_mnt_namespace(p->mnt_ns);
+@@ -1220,8 +1261,13 @@ void umount_tree(struct mount *mnt, int how)
+                       p->mnt_mp = NULL;
+               }
+               change_mnt_propagation(p, MS_PRIVATE);
++              last = p;
++      }
++      if (last) {
++              last->mnt_hash.next = unmounted.first;
++              unmounted.first = tmp_list.first;
++              unmounted.first->pprev = &unmounted.first;
+       }
+-      list_splice(&tmp_list, &unmounted);
+ }
+ 
+ static void shrink_submounts(struct mount *mnt);
+@@ -1605,24 +1651,23 @@ static int attach_recursive_mnt(struct mount 
*source_mnt,
+                       struct mountpoint *dest_mp,
+                       struct path *parent_path)
+ {
+-      LIST_HEAD(tree_list);
++      HLIST_HEAD(tree_list);
+       struct mount *child, *p;
++      struct hlist_node *n;
+       int err;
+ 
+       if (IS_MNT_SHARED(dest_mnt)) {
+               err = invent_group_ids(source_mnt, true);
+               if (err)
+                       goto out;
+-      }
+-      err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
+-      if (err)
+-              goto out_cleanup_ids;
+-
+-      lock_mount_hash();
+-
+-      if (IS_MNT_SHARED(dest_mnt)) {
++              err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
++              if (err)
++                      goto out_cleanup_ids;
++              lock_mount_hash();
+               for (p = source_mnt; p; p = next_mnt(p, source_mnt))
+                       set_mnt_shared(p);
++      } else {
++              lock_mount_hash();
+       }
+       if (parent_path) {
+               detach_mnt(source_mnt, parent_path);
+@@ -1630,20 +1675,22 @@ static int attach_recursive_mnt(struct mount 
*source_mnt,
+               touch_mnt_namespace(source_mnt->mnt_ns);
+       } else {
+               mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
+-              commit_tree(source_mnt);
++              commit_tree(source_mnt, NULL);
+       }
+ 
+-      list_for_each_entry_safe(child, p, &tree_list, mnt_hash) {
+-              list_del_init(&child->mnt_hash);
+-              commit_tree(child);
++      hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) {
++              struct mount *q;
++              hlist_del_init(&child->mnt_hash);
++              q = __lookup_mnt_last(&child->mnt_parent->mnt,
++                                    child->mnt_mountpoint);
++              commit_tree(child, q);
+       }
+       unlock_mount_hash();
+ 
+       return 0;
+ 
+  out_cleanup_ids:
+-      if (IS_MNT_SHARED(dest_mnt))
+-              cleanup_group_ids(source_mnt, NULL);
++      cleanup_group_ids(source_mnt, NULL);
+  out:
+       return err;
+ }
+@@ -2777,18 +2824,24 @@ void __init mnt_init(void)
+       mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
+                       0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
+ 
+-      mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
+-      mountpoint_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
++      mount_hashtable = alloc_large_system_hash("Mount-cache",
++                              sizeof(struct hlist_head),
++                              mhash_entries, 19,
++                              0,
++                              &m_hash_shift, &m_hash_mask, 0, 0);
++      mountpoint_hashtable = alloc_large_system_hash("Mountpoint-cache",
++                              sizeof(struct hlist_head),
++                              mphash_entries, 19,
++                              0,
++                              &mp_hash_shift, &mp_hash_mask, 0, 0);
+ 
+       if (!mount_hashtable || !mountpoint_hashtable)
+               panic("Failed to allocate mount hash table\n");
+ 
+-      printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE);
+-
+-      for (u = 0; u < HASH_SIZE; u++)
+-              INIT_LIST_HEAD(&mount_hashtable[u]);
+-      for (u = 0; u < HASH_SIZE; u++)
+-              INIT_LIST_HEAD(&mountpoint_hashtable[u]);
++      for (u = 0; u <= m_hash_mask; u++)
++              INIT_HLIST_HEAD(&mount_hashtable[u]);
++      for (u = 0; u <= mp_hash_mask; u++)
++              INIT_HLIST_HEAD(&mountpoint_hashtable[u]);
+ 
+       err = sysfs_init();
+       if (err)
+diff --git a/fs/pnode.c b/fs/pnode.c
+index c7221bb19801..88396df725b4 100644
+--- a/fs/pnode.c
++++ b/fs/pnode.c
+@@ -220,14 +220,14 @@ static struct mount *get_source(struct mount *dest,
+  * @tree_list : list of heads of trees to be attached.
+  */
+ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
+-                  struct mount *source_mnt, struct list_head *tree_list)
++                  struct mount *source_mnt, struct hlist_head *tree_list)
+ {
+       struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
+       struct mount *m, *child;
+       int ret = 0;
+       struct mount *prev_dest_mnt = dest_mnt;
+       struct mount *prev_src_mnt  = source_mnt;
+-      LIST_HEAD(tmp_list);
++      HLIST_HEAD(tmp_list);
+ 
+       for (m = propagation_next(dest_mnt, dest_mnt); m;
+                       m = propagation_next(m, dest_mnt)) {
+@@ -246,27 +246,29 @@ int propagate_mnt(struct mount *dest_mnt, struct 
mountpoint *dest_mp,
+               child = copy_tree(source, source->mnt.mnt_root, type);
+               if (IS_ERR(child)) {
+                       ret = PTR_ERR(child);
+-                      list_splice(tree_list, tmp_list.prev);
++                      tmp_list = *tree_list;
++                      tmp_list.first->pprev = &tmp_list.first;
++                      INIT_HLIST_HEAD(tree_list);
+                       goto out;
+               }
+ 
+               if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) {
+                       mnt_set_mountpoint(m, dest_mp, child);
+-                      list_add_tail(&child->mnt_hash, tree_list);
++                      hlist_add_head(&child->mnt_hash, tree_list);
+               } else {
+                       /*
+                        * This can happen if the parent mount was bind mounted
+                        * on some subdirectory of a shared/slave mount.
+                        */
+-                      list_add_tail(&child->mnt_hash, &tmp_list);
++                      hlist_add_head(&child->mnt_hash, &tmp_list);
+               }
+               prev_dest_mnt = m;
+               prev_src_mnt  = child;
+       }
+ out:
+       lock_mount_hash();
+-      while (!list_empty(&tmp_list)) {
+-              child = list_first_entry(&tmp_list, struct mount, mnt_hash);
++      while (!hlist_empty(&tmp_list)) {
++              child = hlist_entry(tmp_list.first, struct mount, mnt_hash);
+               umount_tree(child, 0);
+       }
+       unlock_mount_hash();
+@@ -338,8 +340,10 @@ static void __propagate_umount(struct mount *mnt)
+                * umount the child only if the child has no
+                * other children
+                */
+-              if (child && list_empty(&child->mnt_mounts))
+-                      list_move_tail(&child->mnt_hash, &mnt->mnt_hash);
++              if (child && list_empty(&child->mnt_mounts)) {
++                      hlist_del_init_rcu(&child->mnt_hash);
++                      hlist_add_before_rcu(&child->mnt_hash, &mnt->mnt_hash);
++              }
+       }
+ }
+ 
+@@ -350,11 +354,11 @@ static void __propagate_umount(struct mount *mnt)
+  *
+  * vfsmount lock must be held for write
+  */
+-int propagate_umount(struct list_head *list)
++int propagate_umount(struct hlist_head *list)
+ {
+       struct mount *mnt;
+ 
+-      list_for_each_entry(mnt, list, mnt_hash)
++      hlist_for_each_entry(mnt, list, mnt_hash)
+               __propagate_umount(mnt);
+       return 0;
+ }
+diff --git a/fs/pnode.h b/fs/pnode.h
+index 59e7eda1851e..fc28a27fa892 100644
+--- a/fs/pnode.h
++++ b/fs/pnode.h
+@@ -36,8 +36,8 @@ static inline void set_mnt_shared(struct mount *mnt)
+ 
+ void change_mnt_propagation(struct mount *, int);
+ int propagate_mnt(struct mount *, struct mountpoint *, struct mount *,
+-              struct list_head *);
+-int propagate_umount(struct list_head *);
++              struct hlist_head *);
++int propagate_umount(struct hlist_head *);
+ int propagate_mount_busy(struct mount *, int);
+ void mnt_release_group_id(struct mount *);
+ int get_dominating_id(struct mount *mnt, const struct path *root);
+diff --git a/fs/proc/page.c b/fs/proc/page.c
+index b8730d9ebaee..2a8cc94bb641 100644
+--- a/fs/proc/page.c
++++ b/fs/proc/page.c
+@@ -121,7 +121,7 @@ u64 stable_page_flags(struct page *page)
+        * just checks PG_head/PG_tail, so we need to check PageLRU to make
+        * sure a given page is a thp, not a non-huge compound page.
+        */
+-      else if (PageTransCompound(page) && PageLRU(compound_trans_head(page)))
++      else if (PageTransCompound(page) && PageLRU(compound_head(page)))
+               u |= 1 << KPF_THP;
+ 
+       /*
+diff --git a/include/linux/bitops.h b/include/linux/bitops.h
+index abc9ca778456..be5fd38bd5a0 100644
+--- a/include/linux/bitops.h
++++ b/include/linux/bitops.h
+@@ -196,6 +196,21 @@ static inline unsigned long __ffs64(u64 word)
+ 
+ #ifdef __KERNEL__
+ 
++#ifndef set_mask_bits
++#define set_mask_bits(ptr, _mask, _bits)      \
++({                                                            \
++      const typeof(*ptr) mask = (_mask), bits = (_bits);      \
++      typeof(*ptr) old, new;                                  \
++                                                              \
++      do {                                                    \
++              old = ACCESS_ONCE(*ptr);                        \
++              new = (old & ~mask) | bits;                     \
++      } while (cmpxchg(ptr, old, new) != old);                \
++                                                              \
++      new;                                                    \
++})
++#endif
++
+ #ifndef find_last_bit
+ /**
+  * find_last_bit - find the last set bit in a memory region
+diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
+index 39c1d9469677..10d59f3a5ebd 100644
+--- a/include/linux/cgroup.h
++++ b/include/linux/cgroup.h
+@@ -169,6 +169,8 @@ struct cgroup {
+        *
+        * The ID of the root cgroup is always 0, and a new cgroup
+        * will be assigned with a smallest available ID.
++       *
++       * Allocating/Removing ID must be protected by cgroup_mutex.
+        */
+       int id;
+ 
+diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
+index 91672e2deec3..b826239bdce0 100644
+--- a/include/linux/huge_mm.h
++++ b/include/linux/huge_mm.h
+@@ -157,23 +157,6 @@ static inline int hpage_nr_pages(struct page *page)
+               return HPAGE_PMD_NR;
+       return 1;
+ }
+-static inline struct page *compound_trans_head(struct page *page)
+-{
+-      if (PageTail(page)) {
+-              struct page *head;
+-              head = page->first_page;
+-              smp_rmb();
+-              /*
+-               * head may be a dangling pointer.
+-               * __split_huge_page_refcount clears PageTail before
+-               * overwriting first_page, so if PageTail is still
+-               * there it means the head pointer isn't dangling.
+-               */
+-              if (PageTail(page))
+-                      return head;
+-      }
+-      return page;
+-}
+ 
+ extern int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct 
*vma,
+                               unsigned long addr, pmd_t pmd, pmd_t *pmdp);
+@@ -203,7 +186,6 @@ static inline int split_huge_page(struct page *page)
+       do { } while (0)
+ #define split_huge_page_pmd_mm(__mm, __address, __pmd)        \
+       do { } while (0)
+-#define compound_trans_head(page) compound_head(page)
+ static inline int hugepage_madvise(struct vm_area_struct *vma,
+                                  unsigned long *vm_flags, int advice)
+ {
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index 0ab54390a63b..5360b8245109 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -389,8 +389,18 @@ static inline void compound_unlock_irqrestore(struct page 
*page,
+ 
+ static inline struct page *compound_head(struct page *page)
+ {
+-      if (unlikely(PageTail(page)))
+-              return page->first_page;
++      if (unlikely(PageTail(page))) {
++              struct page *head = page->first_page;
++
++              /*
++               * page->first_page may be a dangling pointer to an old
++               * compound page, so recheck that it is still a tail
++               * page before returning.
++               */
++              smp_rmb();
++              if (likely(PageTail(page)))
++                      return head;
++      }
+       return page;
+ }
+ 
+diff --git a/kernel/cgroup.c b/kernel/cgroup.c
+index 271acd834913..b44dd4989bc1 100644
+--- a/kernel/cgroup.c
++++ b/kernel/cgroup.c
+@@ -4363,16 +4363,6 @@ static long cgroup_create(struct cgroup *parent, struct 
dentry *dentry,
+       rcu_assign_pointer(cgrp->name, name);
+ 
+       /*
+-       * Temporarily set the pointer to NULL, so idr_find() won't return
+-       * a half-baked cgroup.
+-       */
+-      cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
+-      if (cgrp->id < 0) {
+-              err = -ENOMEM;
+-              goto err_free_name;
+-      }
+-
+-      /*
+        * Only live parents can have children.  Note that the liveliness
+        * check isn't strictly necessary because cgroup_mkdir() and
+        * cgroup_rmdir() are fully synchronized by i_mutex; however, do it
+@@ -4381,7 +4371,7 @@ static long cgroup_create(struct cgroup *parent, struct 
dentry *dentry,
+        */
+       if (!cgroup_lock_live_group(parent)) {
+               err = -ENODEV;
+-              goto err_free_id;
++              goto err_free_name;
+       }
+ 
+       /* Grab a reference on the superblock so the hierarchy doesn't
+@@ -4391,6 +4381,16 @@ static long cgroup_create(struct cgroup *parent, struct 
dentry *dentry,
+        * fs */
+       atomic_inc(&sb->s_active);
+ 
++      /*
++       * Temporarily set the pointer to NULL, so idr_find() won't return
++       * a half-baked cgroup.
++       */
++      cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL);
++      if (cgrp->id < 0) {
++              err = -ENOMEM;
++              goto err_unlock;
++      }
++
+       init_cgroup_housekeeping(cgrp);
+ 
+       dentry->d_fsdata = cgrp;
+@@ -4491,11 +4491,11 @@ err_free_all:
+                       ss->css_free(css);
+               }
+       }
++      idr_remove(&root->cgroup_idr, cgrp->id);
++err_unlock:
+       mutex_unlock(&cgroup_mutex);
+       /* Release the reference count that we took on the superblock */
+       deactivate_super(sb);
+-err_free_id:
+-      idr_remove(&root->cgroup_idr, cgrp->id);
+ err_free_name:
+       kfree(rcu_dereference_raw(cgrp->name));
+ err_free_cgrp:
+diff --git a/lib/random32.c b/lib/random32.c
+index 1e5b2df44291..614896778700 100644
+--- a/lib/random32.c
++++ b/lib/random32.c
+@@ -244,8 +244,19 @@ static void __prandom_reseed(bool late)
+       static bool latch = false;
+       static DEFINE_SPINLOCK(lock);
+ 
++      /* Asking for random bytes might result in bytes getting
++       * moved into the nonblocking pool and thus marking it
++       * as initialized. In this case we would double back into
++       * this function and attempt to do a late reseed.
++       * Ignore the pointless attempt to reseed again if we're
++       * already waiting for bytes when the nonblocking pool
++       * got initialized.
++       */
++
+       /* only allow initial seeding (late == false) once */
+-      spin_lock_irqsave(&lock, flags);
++      if (!spin_trylock_irqsave(&lock, flags))
++              return;
++
+       if (latch && !late)
+               goto out;
+       latch = true;
+diff --git a/mm/ksm.c b/mm/ksm.c
+index 175fff79dc95..418b8cad8b01 100644
+--- a/mm/ksm.c
++++ b/mm/ksm.c
+@@ -444,7 +444,7 @@ static void break_cow(struct rmap_item *rmap_item)
+ static struct page *page_trans_compound_anon(struct page *page)
+ {
+       if (PageTransCompound(page)) {
+-              struct page *head = compound_trans_head(page);
++              struct page *head = compound_head(page);
+               /*
+                * head may actually be splitted and freed from under
+                * us but it's ok here.
+diff --git a/mm/memory-failure.c b/mm/memory-failure.c
+index 90977ac8bed8..4566e8fa7b71 100644
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -1645,7 +1645,7 @@ int soft_offline_page(struct page *page, int flags)
+ {
+       int ret;
+       unsigned long pfn = page_to_pfn(page);
+-      struct page *hpage = compound_trans_head(page);
++      struct page *hpage = compound_head(page);
+ 
+       if (PageHWPoison(page)) {
+               pr_info("soft offline: %#lx page already poisoned\n", pfn);
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 56f268de3d41..589521d432d8 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -369,9 +369,11 @@ void prep_compound_page(struct page *page, unsigned long 
order)
+       __SetPageHead(page);
+       for (i = 1; i < nr_pages; i++) {
+               struct page *p = page + i;
+-              __SetPageTail(p);
+               set_page_count(p, 0);
+               p->first_page = page;
++              /* Make sure p->first_page is always valid for PageTail() */
++              smp_wmb();
++              __SetPageTail(p);
+       }
+ }
+ 
+diff --git a/mm/swap.c b/mm/swap.c
+index 84b26aaabd03..7010cf417fdf 100644
+--- a/mm/swap.c
++++ b/mm/swap.c
+@@ -84,7 +84,7 @@ static void put_compound_page(struct page *page)
+ {
+       if (unlikely(PageTail(page))) {
+               /* __split_huge_page_refcount can run under us */
+-              struct page *page_head = compound_trans_head(page);
++              struct page *page_head = compound_head(page);
+ 
+               if (likely(page != page_head &&
+                          get_page_unless_zero(page_head))) {
+@@ -222,7 +222,7 @@ bool __get_page_tail(struct page *page)
+        */
+       unsigned long flags;
+       bool got = false;
+-      struct page *page_head = compound_trans_head(page);
++      struct page *page_head = compound_head(page);
+ 
+       if (likely(page != page_head && get_page_unless_zero(page_head))) {
+               /* Ref to put_compound_page() comment. */
+diff --git a/net/netfilter/nf_conntrack_proto_dccp.c 
b/net/netfilter/nf_conntrack_proto_dccp.c
+index a99b6c3427b0..59359bec328a 100644
+--- a/net/netfilter/nf_conntrack_proto_dccp.c
++++ b/net/netfilter/nf_conntrack_proto_dccp.c
+@@ -428,7 +428,7 @@ static bool dccp_new(struct nf_conn *ct, const struct 
sk_buff *skb,
+       const char *msg;
+       u_int8_t state;
+ 
+-      dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++      dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
+       BUG_ON(dh == NULL);
+ 
+       state = 
dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
+@@ -486,7 +486,7 @@ static int dccp_packet(struct nf_conn *ct, const struct 
sk_buff *skb,
+       u_int8_t type, old_state, new_state;
+       enum ct_dccp_roles role;
+ 
+-      dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++      dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
+       BUG_ON(dh == NULL);
+       type = dh->dccph_type;
+ 
+@@ -577,7 +577,7 @@ static int dccp_error(struct net *net, struct nf_conn 
*tmpl,
+       unsigned int cscov;
+       const char *msg;
+ 
+-      dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh);
++      dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
+       if (dh == NULL) {
+               msg = "nf_ct_dccp: short packet ";
+               goto out_invalid;


Reply via email to