diff --git a/Makefile b/Makefile
index 49e8be1..85fb935 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 11
-EXTRAVERSION = -ckt13
+EXTRAVERSION = -ckt14
 NAME = King of Alienated Frog Porn
 
 # *DOCUMENTATION*
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c 
b/arch/powerpc/platforms/cell/spufs/inode.c
index 87ba7cf..65d633f 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -164,7 +164,7 @@ static void spufs_prune_dir(struct dentry *dir)
        struct dentry *dentry, *tmp;
 
        mutex_lock(&dir->d_inode->i_mutex);
-       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
                spin_lock(&dentry->d_lock);
                if (!(d_unhashed(dentry)) && dentry->d_inode) {
                        dget_dlock(dentry);
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index e030d2b..b67da3b 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -245,7 +245,7 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 
__user *grouplist)
        struct group_info *group_info;
        int retval;
 
-       if (!capable(CAP_SETGID))
+       if (!may_setgroups())
                return -EPERM;
        if ((unsigned)gidsetsize > NGROUPS_MAX)
                return -EINVAL;
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 9c0280f..e2d26ce 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -286,24 +286,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct 
*next_p)
 
        fpu = switch_fpu_prepare(prev_p, next_p, cpu);
 
-       /*
-        * Reload esp0, LDT and the page table pointer:
-        */
+       /* Reload esp0 and ss1. */
        load_sp0(tss, next);
 
-       /*
-        * Switch DS and ES.
-        * This won't pick up thread selector changes, but I guess that is ok.
-        */
-       savesegment(es, prev->es);
-       if (unlikely(next->es | prev->es))
-               loadsegment(es, next->es);
-
-       savesegment(ds, prev->ds);
-       if (unlikely(next->ds | prev->ds))
-               loadsegment(ds, next->ds);
-
-
        /* We must save %fs and %gs before load_TLS() because
         * %fs and %gs may be cleared by load_TLS().
         *
@@ -312,41 +297,101 @@ __switch_to(struct task_struct *prev_p, struct 
task_struct *next_p)
        savesegment(fs, fsindex);
        savesegment(gs, gsindex);
 
+       /*
+        * Load TLS before restoring any segments so that segment loads
+        * reference the correct GDT entries.
+        */
        load_TLS(next, cpu);
 
        /*
-        * Leave lazy mode, flushing any hypercalls made here.
-        * This must be done before restoring TLS segments so
-        * the GDT and LDT are properly updated, and must be
-        * done before math_state_restore, so the TS bit is up
-        * to date.
+        * Leave lazy mode, flushing any hypercalls made here.  This
+        * must be done after loading TLS entries in the GDT but before
+        * loading segments that might reference them, and and it must
+        * be done before math_state_restore, so the TS bit is up to
+        * date.
         */
        arch_end_context_switch(next_p);
 
+       /* Switch DS and ES.
+        *
+        * Reading them only returns the selectors, but writing them (if
+        * nonzero) loads the full descriptor from the GDT or LDT.  The
+        * LDT for next is loaded in switch_mm, and the GDT is loaded
+        * above.
+        *
+        * We therefore need to write new values to the segment
+        * registers on every context switch unless both the new and old
+        * values are zero.
+        *
+        * Note that we don't need to do anything for CS and SS, as
+        * those are saved and restored as part of pt_regs.
+        */
+       savesegment(es, prev->es);
+       if (unlikely(next->es | prev->es))
+               loadsegment(es, next->es);
+
+       savesegment(ds, prev->ds);
+       if (unlikely(next->ds | prev->ds))
+               loadsegment(ds, next->ds);
+
        /*
         * Switch FS and GS.
         *
-        * Segment register != 0 always requires a reload.  Also
-        * reload when it has changed.  When prev process used 64bit
-        * base always reload to avoid an information leak.
+        * These are even more complicated than FS and GS: they have
+        * 64-bit bases are that controlled by arch_prctl.  Those bases
+        * only differ from the values in the GDT or LDT if the selector
+        * is 0.
+        *
+        * Loading the segment register resets the hidden base part of
+        * the register to 0 or the value from the GDT / LDT.  If the
+        * next base address zero, writing 0 to the segment register is
+        * much faster than using wrmsr to explicitly zero the base.
+        *
+        * The thread_struct.fs and thread_struct.gs values are 0
+        * if the fs and gs bases respectively are not overridden
+        * from the values implied by fsindex and gsindex.  They
+        * are nonzero, and store the nonzero base addresses, if
+        * the bases are overridden.
+        *
+        * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should
+        * be impossible.
+        *
+        * Therefore we need to reload the segment registers if either
+        * the old or new selector is nonzero, and we need to override
+        * the base address if next thread expects it to be overridden.
+        *
+        * This code is unnecessarily slow in the case where the old and
+        * new indexes are zero and the new base is nonzero -- it will
+        * unnecessarily write 0 to the selector before writing the new
+        * base address.
+        *
+        * Note: This all depends on arch_prctl being the only way that
+        * user code can override the segment base.  Once wrfsbase and
+        * wrgsbase are enabled, most of this code will need to change.
         */
        if (unlikely(fsindex | next->fsindex | prev->fs)) {
                loadsegment(fs, next->fsindex);
+
                /*
-                * Check if the user used a selector != 0; if yes
-                *  clear 64bit base, since overloaded base is always
-                *  mapped to the Null selector
+                * If user code wrote a nonzero value to FS, then it also
+                * cleared the overridden base address.
+                *
+                * XXX: if user code wrote 0 to FS and cleared the base
+                * address itself, we won't notice and we'll incorrectly
+                * restore the prior base address next time we reschdule
+                * the process.
                 */
                if (fsindex)
                        prev->fs = 0;
        }
-       /* when next process has a 64bit base use it */
        if (next->fs)
                wrmsrl(MSR_FS_BASE, next->fs);
        prev->fsindex = fsindex;
 
        if (unlikely(gsindex | next->gsindex | prev->gs)) {
                load_gs_index(next->gsindex);
+
+               /* This works (and fails) the same way as fsindex above. */
                if (gsindex)
                        prev->gs = 0;
        }
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index f7fec09..e7650bd 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -27,6 +27,21 @@ static int get_free_idx(void)
        return -ESRCH;
 }
 
+static bool tls_desc_okay(const struct user_desc *info)
+{
+       if (LDT_empty(info))
+               return true;
+
+       /*
+        * espfix is required for 16-bit data segments, but espfix
+        * only works for LDT segments.
+        */
+       if (!info->seg_32bit)
+               return false;
+
+       return true;
+}
+
 static void set_tls_desc(struct task_struct *p, int idx,
                         const struct user_desc *info, int n)
 {
@@ -66,6 +81,9 @@ int do_set_thread_area(struct task_struct *p, int idx,
        if (copy_from_user(&info, u_info, sizeof(info)))
                return -EFAULT;
 
+       if (!tls_desc_okay(&info))
+               return -EINVAL;
+
        if (idx == -1)
                idx = info.entry_number;
 
@@ -192,6 +210,7 @@ int regset_tls_set(struct task_struct *target, const struct 
user_regset *regset,
 {
        struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
        const struct user_desc *info;
+       int i;
 
        if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
            (pos % sizeof(struct user_desc)) != 0 ||
@@ -205,6 +224,10 @@ int regset_tls_set(struct task_struct *target, const 
struct user_regset *regset,
        else
                info = infobuf;
 
+       for (i = 0; i < count / sizeof(struct user_desc); i++)
+               if (!tls_desc_okay(info + i))
+                       return -EINVAL;
+
        set_tls_desc(target,
                     GDT_ENTRY_TLS_MIN + (pos / sizeof(struct user_desc)),
                     info, count / sizeof(struct user_desc));
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 97e766b..4919b95 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1994,7 +1994,7 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
 
        rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
        if (rc != X86EMUL_CONTINUE) {
-               WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64);
+               WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
                /* assigning eip failed; restore the old cs */
                ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
                return rc;
@@ -2088,7 +2088,7 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
                return rc;
        rc = assign_eip_far(ctxt, eip, new_desc.l);
        if (rc != X86EMUL_CONTINUE) {
-               WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64);
+               WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
                ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
        }
        return rc;
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 431e875..ab6ba35 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -117,30 +117,45 @@ subsys_initcall(init_vdso);
 
 struct linux_binprm;
 
-/* Put the vdso above the (randomized) stack with another randomized offset.
-   This way there is no hole in the middle of address space.
-   To save memory make sure it is still in the same PTE as the stack top.
-   This doesn't give that many random bits */
+/*
+ * Put the vdso above the (randomized) stack with another randomized
+ * offset.  This way there is no hole in the middle of address space.
+ * To save memory make sure it is still in the same PTE as the stack
+ * top.  This doesn't give that many random bits.
+ *
+ * Note that this algorithm is imperfect: the distribution of the vdso
+ * start address within a PMD is biased toward the end.
+ *
+ * Only used for the 64-bit and x32 vdsos.
+ */
 static unsigned long vdso_addr(unsigned long start, unsigned len)
 {
        unsigned long addr, end;
        unsigned offset;
-       end = (start + PMD_SIZE - 1) & PMD_MASK;
+
+       /*
+        * Round up the start address.  It can start out unaligned as a result
+        * of stack start randomization.
+        */
+       start = PAGE_ALIGN(start);
+
+       /* Round the lowest possible end address up to a PMD boundary. */
+       end = (start + len + PMD_SIZE - 1) & PMD_MASK;
        if (end >= TASK_SIZE_MAX)
                end = TASK_SIZE_MAX;
        end -= len;
-       /* This loses some more bits than a modulo, but is cheaper */
-       offset = get_random_int() & (PTRS_PER_PTE - 1);
-       addr = start + (offset << PAGE_SHIFT);
-       if (addr >= end)
-               addr = end;
+
+       if (end > start) {
+               offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
+               addr = start + (offset << PAGE_SHIFT);
+       } else {
+               addr = start;
+       }
 
        /*
-        * page-align it here so that get_unmapped_area doesn't
-        * align it wrongfully again to the next page. addr can come in 4K
-        * unaligned here as a result of stack start randomization.
+        * Forcibly align the final address in case we have a hardware
+        * issue that requires alignment for performance reasons.
         */
-       addr = PAGE_ALIGN(addr);
        addr = align_vdso_addr(addr);
 
        return addr;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c 
b/drivers/net/ethernet/intel/e1000e/netdev.c
index 6d14eea..a205f8d 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -2976,11 +2976,21 @@ static void e1000_setup_rctl(struct e1000_adapter 
*adapter)
        u32 rctl, rfctl;
        u32 pages = 0;
 
-       /* Workaround Si errata on PCHx - configure jumbo frame flow */
-       if ((hw->mac.type >= e1000_pch2lan) &&
-           (adapter->netdev->mtu > ETH_DATA_LEN) &&
-           e1000_lv_jumbo_workaround_ich8lan(hw, true))
-               e_dbg("failed to enable jumbo frame workaround mode\n");
+       /* Workaround Si errata on PCHx - configure jumbo frame flow.
+        * If jumbo frames not set, program related MAC/PHY registers
+        * to h/w defaults
+        */
+       if (hw->mac.type >= e1000_pch2lan) {
+               s32 ret_val;
+
+               if (adapter->netdev->mtu > ETH_DATA_LEN)
+                       ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
+               else
+                       ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
+
+               if (ret_val)
+                       e_dbg("failed to enable|disable jumbo frame workaround 
mode\n");
+       }
 
        /* Program MC offset vector base */
        rctl = er32(RCTL);
diff --git a/drivers/staging/lustre/lustre/llite/dcache.c 
b/drivers/staging/lustre/lustre/llite/dcache.c
index e7629be..c6ca9ca 100644
--- a/drivers/staging/lustre/lustre/llite/dcache.c
+++ b/drivers/staging/lustre/lustre/llite/dcache.c
@@ -278,7 +278,7 @@ void ll_invalidate_aliases(struct inode *inode)
               inode->i_ino, inode->i_generation, inode);
 
        ll_lock_dcache(inode);
-       ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
+       ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) {
                CDEBUG(D_DENTRY, "dentry in drop %.*s (%p) parent %p "
                       "inode %p flags %d\n", dentry->d_name.len,
                       dentry->d_name.name, dentry, dentry->d_parent,
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c 
b/drivers/staging/lustre/lustre/llite/llite_lib.c
index fd584ff..78092f6 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -665,7 +665,7 @@ void lustre_dump_dentry(struct dentry *dentry, int recur)
                return;
 
        list_for_each(tmp, &dentry->d_subdirs) {
-               struct dentry *d = list_entry(tmp, struct dentry, d_u.d_child);
+               struct dentry *d = list_entry(tmp, struct dentry, d_child);
                lustre_dump_dentry(d, recur - 1);
        }
 }
diff --git a/drivers/staging/lustre/lustre/llite/namei.c 
b/drivers/staging/lustre/lustre/llite/namei.c
index 90bbdae..98b3cd6 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -175,14 +175,14 @@ static void ll_invalidate_negative_children(struct inode 
*dir)
        struct ll_d_hlist_node *p;
 
        ll_lock_dcache(dir);
-       ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_alias) {
+       ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (!list_empty(&dentry->d_subdirs)) {
                        struct dentry *child;
 
                        list_for_each_entry_safe(child, tmp_subdir,
                                                 &dentry->d_subdirs,
-                                                d_u.d_child) {
+                                                d_child) {
                                if (child->d_inode == NULL)
                                        d_lustre_invalidate(child, 1);
                        }
@@ -363,7 +363,7 @@ static struct dentry *ll_find_alias(struct inode *inode, 
struct dentry *dentry)
        discon_alias = invalid_alias = NULL;
 
        ll_lock_dcache(inode);
-       ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
+       ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_u.d_alias) {
                LASSERT(alias != dentry);
 
                spin_lock(&alias->d_lock);
@@ -953,7 +953,7 @@ static void ll_get_child_fid(struct inode * dir, struct 
qstr *name,
 {
        struct dentry *parent, *child;
 
-       parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_alias);
+       parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_u.d_alias);
        child = d_lookup(parent, name);
        if (child) {
                if (child->d_inode)
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 4cc4fd6..4e8fa75 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -871,12 +871,10 @@ static void clk_on(struct at91_udc *udc)
                return;
        udc->clocked = 1;
 
-       if (IS_ENABLED(CONFIG_COMMON_CLK)) {
-               clk_set_rate(udc->uclk, 48000000);
-               clk_prepare_enable(udc->uclk);
-       }
-       clk_prepare_enable(udc->iclk);
-       clk_prepare_enable(udc->fclk);
+       if (IS_ENABLED(CONFIG_COMMON_CLK))
+               clk_enable(udc->uclk);
+       clk_enable(udc->iclk);
+       clk_enable(udc->fclk);
 }
 
 static void clk_off(struct at91_udc *udc)
@@ -885,10 +883,10 @@ static void clk_off(struct at91_udc *udc)
                return;
        udc->clocked = 0;
        udc->gadget.speed = USB_SPEED_UNKNOWN;
-       clk_disable_unprepare(udc->fclk);
-       clk_disable_unprepare(udc->iclk);
+       clk_disable(udc->fclk);
+       clk_disable(udc->iclk);
        if (IS_ENABLED(CONFIG_COMMON_CLK))
-               clk_disable_unprepare(udc->uclk);
+               clk_disable(udc->uclk);
 }
 
 /*
@@ -1791,14 +1789,24 @@ static int at91udc_probe(struct platform_device *pdev)
        }
 
        /* don't do anything until we have both gadget driver and VBUS */
+       if (IS_ENABLED(CONFIG_COMMON_CLK)) {
+               clk_set_rate(udc->uclk, 48000000);
+               retval = clk_prepare(udc->uclk);
+               if (retval)
+                       goto fail1;
+       }
+       retval = clk_prepare(udc->fclk);
+       if (retval)
+               goto fail1a;
+
        retval = clk_prepare_enable(udc->iclk);
        if (retval)
-               goto fail1;
+               goto fail1b;
        at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
        at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
        /* Clear all pending interrupts - UDP may be used by bootloader. */
        at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
-       clk_disable_unprepare(udc->iclk);
+       clk_disable(udc->iclk);
 
        /* request UDC and maybe VBUS irqs */
        udc->udp_irq = platform_get_irq(pdev, 0);
@@ -1806,7 +1814,7 @@ static int at91udc_probe(struct platform_device *pdev)
                        0, driver_name, udc);
        if (retval < 0) {
                DBG("request irq %d failed\n", udc->udp_irq);
-               goto fail1;
+               goto fail1c;
        }
        if (gpio_is_valid(udc->board.vbus_pin)) {
                retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
@@ -1859,6 +1867,13 @@ fail3:
                gpio_free(udc->board.vbus_pin);
 fail2:
        free_irq(udc->udp_irq, udc);
+fail1c:
+       clk_unprepare(udc->iclk);
+fail1b:
+       clk_unprepare(udc->fclk);
+fail1a:
+       if (IS_ENABLED(CONFIG_COMMON_CLK))
+               clk_unprepare(udc->uclk);
 fail1:
        if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
                clk_put(udc->uclk);
@@ -1907,6 +1922,11 @@ static int __exit at91udc_remove(struct platform_device 
*pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, resource_size(res));
 
+       if (IS_ENABLED(CONFIG_COMMON_CLK))
+               clk_unprepare(udc->uclk);
+       clk_unprepare(udc->fclk);
+       clk_unprepare(udc->iclk);
+
        clk_put(udc->iclk);
        clk_put(udc->fclk);
        if (IS_ENABLED(CONFIG_COMMON_CLK))
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index d9a4367..9cca0ea 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -126,7 +126,7 @@ affs_fix_dcache(struct inode *inode, u32 entry_ino)
 {
        struct dentry *dentry;
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                if (entry_ino == (u32)(long)dentry->d_fsdata) {
                        dentry->d_fsdata = (void *)inode->i_ino;
                        break;
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 3d9d3f5..d096316 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -91,7 +91,7 @@ static struct dentry *get_next_positive_subdir(struct dentry 
*prev,
        spin_lock(&root->d_lock);
 
        if (prev)
-               next = prev->d_u.d_child.next;
+               next = prev->d_child.next;
        else {
                prev = dget_dlock(root);
                next = prev->d_subdirs.next;
@@ -105,13 +105,13 @@ cont:
                return NULL;
        }
 
-       q = list_entry(next, struct dentry, d_u.d_child);
+       q = list_entry(next, struct dentry, d_child);
 
        spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
        /* Already gone or negative dentry (under construction) - try next */
        if (!d_count(q) || !simple_positive(q)) {
                spin_unlock(&q->d_lock);
-               next = q->d_u.d_child.next;
+               next = q->d_child.next;
                goto cont;
        }
        dget_dlock(q);
@@ -161,13 +161,13 @@ again:
                                goto relock;
                        }
                        spin_unlock(&p->d_lock);
-                       next = p->d_u.d_child.next;
+                       next = p->d_child.next;
                        p = parent;
                        if (next != &parent->d_subdirs)
                                break;
                }
        }
-       ret = list_entry(next, struct dentry, d_u.d_child);
+       ret = list_entry(next, struct dentry, d_child);
 
        spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
        /* Negative dentry - try next */
@@ -447,7 +447,7 @@ found:
        spin_lock(&sbi->lookup_lock);
        spin_lock(&expired->d_parent->d_lock);
        spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
-       list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
+       list_move(&expired->d_parent->d_subdirs, &expired->d_child);
        spin_unlock(&expired->d_lock);
        spin_unlock(&expired->d_parent->d_lock);
        spin_unlock(&sbi->lookup_lock);
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 2a69bde..b3f4794 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -655,7 +655,7 @@ static void autofs_clear_leaf_automount_flags(struct dentry 
*dentry)
        /* only consider parents below dentrys in the root */
        if (IS_ROOT(parent->d_parent))
                return;
-       d_child = &dentry->d_u.d_child;
+       d_child = &dentry->d_child;
        /* Set parent managed if it's becoming empty */
        if (d_child->next == &parent->d_subdirs &&
            d_child->prev == &parent->d_subdirs)
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 2a0bcae..57bd52d 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -103,7 +103,7 @@ static unsigned fpos_off(loff_t p)
 /*
  * When possible, we try to satisfy a readdir by peeking at the
  * dcache.  We make this work by carefully ordering dentries on
- * d_u.d_child when we initially get results back from the MDS, and
+ * d_child when we initially get results back from the MDS, and
  * falling back to a "normal" sync readdir if any dentries in the dir
  * are dropped.
  *
@@ -138,11 +138,11 @@ static int __dcache_readdir(struct file *file, struct 
dir_context *ctx)
                p = parent->d_subdirs.prev;
                dout(" initial p %p/%p\n", p->prev, p->next);
        } else {
-               p = last->d_u.d_child.prev;
+               p = last->d_child.prev;
        }
 
 more:
-       dentry = list_entry(p, struct dentry, d_u.d_child);
+       dentry = list_entry(p, struct dentry, d_child);
        di = ceph_dentry(dentry);
        while (1) {
                dout(" p %p/%p %s d_subdirs %p/%p\n", p->prev, p->next,
@@ -164,7 +164,7 @@ more:
                     !dentry->d_inode ? " null" : "");
                spin_unlock(&dentry->d_lock);
                p = p->prev;
-               dentry = list_entry(p, struct dentry, d_u.d_child);
+               dentry = list_entry(p, struct dentry, d_child);
                di = ceph_dentry(dentry);
        }
 
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 278fd28..9d4d486 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -905,9 +905,9 @@ static void ceph_set_dentry_offset(struct dentry *dn)
 
        spin_lock(&dir->d_lock);
        spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
-       list_move(&dn->d_u.d_child, &dir->d_subdirs);
+       list_move(&dn->d_child, &dir->d_subdirs);
        dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
-            dn->d_u.d_child.prev, dn->d_u.d_child.next);
+            dn->d_child.prev, dn->d_child.next);
        spin_unlock(&dn->d_lock);
        spin_unlock(&dir->d_lock);
 }
@@ -1316,7 +1316,7 @@ retry_lookup:
                        /* reorder parent's d_subdirs */
                        spin_lock(&parent->d_lock);
                        spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
-                       list_move(&dn->d_u.d_child, &parent->d_subdirs);
+                       list_move(&dn->d_child, &parent->d_subdirs);
                        spin_unlock(&dn->d_lock);
                        spin_unlock(&parent->d_lock);
                }
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 3be49dd..a8546aa 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -874,7 +874,7 @@ inode_has_hashed_dentries(struct inode *inode)
        struct dentry *dentry;
 
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
                        spin_unlock(&inode->i_lock);
                        return true;
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 1da168c..9bc1147 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -92,7 +92,7 @@ static void coda_flag_children(struct dentry *parent, int 
flag)
        struct dentry *de;
 
        spin_lock(&parent->d_lock);
-       list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) {
+       list_for_each_entry(de, &parent->d_subdirs, d_child) {
                /* don't know what to do with negative dentries */
                if (de->d_inode ) 
                        coda_flag_inode(de->d_inode, flag);
diff --git a/fs/dcache.c b/fs/dcache.c
index 2e3c637..6ef3f68 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -44,7 +44,7 @@
 /*
  * Usage:
  * dcache->d_inode->i_lock protects:
- *   - i_dentry, d_alias, d_inode of aliases
+ *   - i_dentry, d_u.d_alias, d_inode of aliases
  * dcache_hash_bucket lock protects:
  *   - the dcache hash table
  * s_anon bl list spinlock protects:
@@ -59,7 +59,7 @@
  *   - d_unhashed()
  *   - d_parent and d_subdirs
  *   - childrens' d_child and d_parent
- *   - d_alias, d_inode
+ *   - d_u.d_alias, d_inode
  *
  * Ordering:
  * dentry->d_inode->i_lock
@@ -240,7 +240,6 @@ static void __d_free(struct rcu_head *head)
 {
        struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
 
-       WARN_ON(!hlist_unhashed(&dentry->d_alias));
        if (dname_external(dentry))
                kfree(dentry->d_name.name);
        kmem_cache_free(dentry_cache, dentry); 
@@ -251,6 +250,8 @@ static void __d_free(struct rcu_head *head)
  */
 static void d_free(struct dentry *dentry)
 {
+       WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias));
+
        BUG_ON((int)dentry->d_lockref.count > 0);
        this_cpu_dec(nr_dentry);
        if (dentry->d_op && dentry->d_op->d_release)
@@ -289,7 +290,7 @@ static void dentry_iput(struct dentry * dentry)
        struct inode *inode = dentry->d_inode;
        if (inode) {
                dentry->d_inode = NULL;
-               hlist_del_init(&dentry->d_alias);
+               hlist_del_init(&dentry->d_u.d_alias);
                spin_unlock(&dentry->d_lock);
                spin_unlock(&inode->i_lock);
                if (!inode->i_nlink)
@@ -314,7 +315,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
        struct inode *inode = dentry->d_inode;
        __d_clear_type(dentry);
        dentry->d_inode = NULL;
-       hlist_del_init(&dentry->d_alias);
+       hlist_del_init(&dentry->d_u.d_alias);
        dentry_rcuwalk_barrier(dentry);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&inode->i_lock);
@@ -436,7 +437,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct 
dentry *parent)
        __releases(parent->d_lock)
        __releases(dentry->d_inode->i_lock)
 {
-       list_del(&dentry->d_u.d_child);
+       __list_del_entry(&dentry->d_child);
        /*
         * Inform d_walk() that we are no longer attached to the
         * dentry tree
@@ -738,7 +739,7 @@ static struct dentry *__d_find_alias(struct inode *inode, 
int want_discon)
 
 again:
        discon_alias = NULL;
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&alias->d_lock);
                if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
                        if (IS_ROOT(alias) &&
@@ -791,7 +792,7 @@ void d_prune_aliases(struct inode *inode)
        struct dentry *dentry;
 restart:
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (!dentry->d_lockref.count) {
                        /*
@@ -1092,7 +1093,7 @@ repeat:
 resume:
        while (next != &this_parent->d_subdirs) {
                struct list_head *tmp = next;
-               struct dentry *dentry = list_entry(tmp, struct dentry, 
d_u.d_child);
+               struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
                next = tmp->next;
 
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
@@ -1124,33 +1125,31 @@ resume:
        /*
         * All done at this level ... ascend and resume the search.
         */
+       rcu_read_lock();
+ascend:
        if (this_parent != parent) {
                struct dentry *child = this_parent;
                this_parent = child->d_parent;
 
-               rcu_read_lock();
                spin_unlock(&child->d_lock);
                spin_lock(&this_parent->d_lock);
 
-               /*
-                * might go back up the wrong parent if we have had a rename
-                * or deletion
-                */
-               if (this_parent != child->d_parent ||
-                        (child->d_flags & DCACHE_DENTRY_KILLED) ||
-                        need_seqretry(&rename_lock, seq)) {
-                       spin_unlock(&this_parent->d_lock);
-                       rcu_read_unlock();
+               /* might go back up the wrong parent if we have had a rename. */
+               if (need_seqretry(&rename_lock, seq))
                        goto rename_retry;
+               next = child->d_child.next;
+               while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+                       if (next == &this_parent->d_subdirs)
+                               goto ascend;
+                       child = list_entry(next, struct dentry, d_child);
+                       next = next->next;
                }
                rcu_read_unlock();
-               next = child->d_u.d_child.next;
                goto resume;
        }
-       if (need_seqretry(&rename_lock, seq)) {
-               spin_unlock(&this_parent->d_lock);
+       if (need_seqretry(&rename_lock, seq))
                goto rename_retry;
-       }
+       rcu_read_unlock();
        if (finish)
                finish(data);
 
@@ -1160,6 +1159,9 @@ out_unlock:
        return;
 
 rename_retry:
+       spin_unlock(&this_parent->d_lock);
+       rcu_read_unlock();
+       BUG_ON(seq & 1);
        if (!retry)
                return;
        seq = 1;
@@ -1525,8 +1527,8 @@ struct dentry *__d_alloc(struct super_block *sb, const 
struct qstr *name)
        INIT_HLIST_BL_NODE(&dentry->d_hash);
        INIT_LIST_HEAD(&dentry->d_lru);
        INIT_LIST_HEAD(&dentry->d_subdirs);
-       INIT_HLIST_NODE(&dentry->d_alias);
-       INIT_LIST_HEAD(&dentry->d_u.d_child);
+       INIT_HLIST_NODE(&dentry->d_u.d_alias);
+       INIT_LIST_HEAD(&dentry->d_child);
        d_set_d_op(dentry, dentry->d_sb->s_d_op);
 
        this_cpu_inc(nr_dentry);
@@ -1556,7 +1558,7 @@ struct dentry *d_alloc(struct dentry * parent, const 
struct qstr *name)
         */
        __dget_dlock(parent);
        dentry->d_parent = parent;
-       list_add(&dentry->d_u.d_child, &parent->d_subdirs);
+       list_add(&dentry->d_child, &parent->d_subdirs);
        spin_unlock(&parent->d_lock);
 
        return dentry;
@@ -1649,7 +1651,7 @@ static void __d_instantiate(struct dentry *dentry, struct 
inode *inode)
        spin_lock(&dentry->d_lock);
        __d_set_type(dentry, add_flags);
        if (inode)
-               hlist_add_head(&dentry->d_alias, &inode->i_dentry);
+               hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
        dentry->d_inode = inode;
        dentry_rcuwalk_barrier(dentry);
        spin_unlock(&dentry->d_lock);
@@ -1673,7 +1675,7 @@ static void __d_instantiate(struct dentry *dentry, struct 
inode *inode)
  
 void d_instantiate(struct dentry *entry, struct inode * inode)
 {
-       BUG_ON(!hlist_unhashed(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
        if (inode)
                spin_lock(&inode->i_lock);
        __d_instantiate(entry, inode);
@@ -1712,7 +1714,7 @@ static struct dentry *__d_instantiate_unique(struct 
dentry *entry,
                return NULL;
        }
 
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                /*
                 * Don't need alias->d_lock here, because aliases with
                 * d_parent == entry->d_parent are not subject to name or
@@ -1738,7 +1740,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, 
struct inode *inode)
 {
        struct dentry *result;
 
-       BUG_ON(!hlist_unhashed(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
 
        if (inode)
                spin_lock(&inode->i_lock);
@@ -1769,7 +1771,7 @@ EXPORT_SYMBOL(d_instantiate_unique);
  */
 int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode)
 {
-       BUG_ON(!hlist_unhashed(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
 
        spin_lock(&inode->i_lock);
        if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) {
@@ -1808,7 +1810,7 @@ static struct dentry * __d_find_any_alias(struct inode 
*inode)
 
        if (hlist_empty(&inode->i_dentry))
                return NULL;
-       alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        __dget(alias);
        return alias;
 }
@@ -1885,7 +1887,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
        spin_lock(&tmp->d_lock);
        tmp->d_inode = inode;
        tmp->d_flags |= add_flags;
-       hlist_add_head(&tmp->d_alias, &inode->i_dentry);
+       hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry);
        hlist_bl_lock(&tmp->d_sb->s_anon);
        hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
        hlist_bl_unlock(&tmp->d_sb->s_anon);
@@ -2328,7 +2330,7 @@ int d_validate(struct dentry *dentry, struct dentry 
*dparent)
        struct dentry *child;
 
        spin_lock(&dparent->d_lock);
-       list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) {
+       list_for_each_entry(child, &dparent->d_subdirs, d_child) {
                if (dentry == child) {
                        spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
                        __dget_dlock(dentry);
@@ -2575,8 +2577,8 @@ static void __d_move(struct dentry * dentry, struct 
dentry * target)
        /* Unhash the target: dput() will then get rid of it */
        __d_drop(target);
 
-       list_del(&dentry->d_u.d_child);
-       list_del(&target->d_u.d_child);
+       list_del(&dentry->d_child);
+       list_del(&target->d_child);
 
        /* Switch the names.. */
        switch_names(dentry, target);
@@ -2586,15 +2588,15 @@ static void __d_move(struct dentry * dentry, struct 
dentry * target)
        if (IS_ROOT(dentry)) {
                dentry->d_parent = target->d_parent;
                target->d_parent = target;
-               INIT_LIST_HEAD(&target->d_u.d_child);
+               INIT_LIST_HEAD(&target->d_child);
        } else {
                swap(dentry->d_parent, target->d_parent);
 
                /* And add them back to the (new) parent lists */
-               list_add(&target->d_u.d_child, &target->d_parent->d_subdirs);
+               list_add(&target->d_child, &target->d_parent->d_subdirs);
        }
 
-       list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
+       list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
 
        write_seqcount_end(&target->d_seq);
        write_seqcount_end(&dentry->d_seq);
@@ -2701,9 +2703,9 @@ static void __d_materialise_dentry(struct dentry *dentry, 
struct dentry *anon)
        swap(dentry->d_name.hash, anon->d_name.hash);
 
        dentry->d_parent = dentry;
-       list_del_init(&dentry->d_u.d_child);
+       list_del_init(&dentry->d_child);
        anon->d_parent = dparent;
-       list_move(&anon->d_u.d_child, &dparent->d_subdirs);
+       list_move(&anon->d_child, &dparent->d_subdirs);
 
        write_seqcount_end(&dentry->d_seq);
        write_seqcount_end(&anon->d_seq);
@@ -3334,7 +3336,7 @@ void d_tmpfile(struct dentry *dentry, struct inode *inode)
 {
        inode_dec_link_count(inode);
        BUG_ON(dentry->d_name.name != dentry->d_iname ||
-               !hlist_unhashed(&dentry->d_alias) ||
+               !hlist_unhashed(&dentry->d_u.d_alias) ||
                !d_unlinked(dentry));
        spin_lock(&dentry->d_parent->d_lock);
        spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 1576195..d7bf631 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -552,7 +552,7 @@ void debugfs_remove_recursive(struct dentry *dentry)
         * use the d_u.d_child as the rcu head and corrupt this list.
         */
        spin_lock(&parent->d_lock);
-       list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) {
+       list_for_each_entry(child, &parent->d_subdirs, d_child) {
                if (!debugfs_positive(child))
                        continue;
 
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 48a359d..831d4f0 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -50,7 +50,7 @@ find_acceptable_alias(struct dentry *result,
 
        inode = result->d_inode;
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                dget(dentry);
                spin_unlock(&inode->i_lock);
                if (toput)
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index f488bba..735d752 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -30,6 +30,7 @@ struct rock_state {
        int cont_size;
        int cont_extent;
        int cont_offset;
+       int cont_loops;
        struct inode *inode;
 };
 
@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct 
inode *inode)
        rs->inode = inode;
 }
 
+/* Maximum number of Rock Ridge continuation entries */
+#define RR_MAX_CE_ENTRIES 32
+
 /*
  * Returns 0 if the caller should continue scanning, 1 if the scan must end
  * and -ve on error.
@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs)
                        goto out;
                }
                ret = -EIO;
+               if (++rs->cont_loops >= RR_MAX_CE_ENTRIES)
+                       goto out;
                bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
                if (bh) {
                        memcpy(rs->buffer, bh->b_data + rs->cont_offset,
@@ -356,6 +362,9 @@ repeat:
                        rs.cont_size = isonum_733(rr->u.CE.size);
                        break;
                case SIG('E', 'R'):
+                       /* Invalid length of ER tag id? */
+                       if (rr->u.ER.len_id + offsetof(struct rock_ridge, 
u.ER.data) > rr->len)
+                               goto out;
                        ISOFS_SB(inode->i_sb)->s_rock = 1;
                        printk(KERN_DEBUG "ISO 9660 Extensions: ");
                        {
diff --git a/fs/libfs.c b/fs/libfs.c
index a184424..868c0b7 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -113,18 +113,18 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, 
int whence)
 
                        spin_lock(&dentry->d_lock);
                        /* d_lock not required for cursor */
-                       list_del(&cursor->d_u.d_child);
+                       list_del(&cursor->d_child);
                        p = dentry->d_subdirs.next;
                        while (n && p != &dentry->d_subdirs) {
                                struct dentry *next;
-                               next = list_entry(p, struct dentry, 
d_u.d_child);
+                               next = list_entry(p, struct dentry, d_child);
                                spin_lock_nested(&next->d_lock, 
DENTRY_D_LOCK_NESTED);
                                if (simple_positive(next))
                                        n--;
                                spin_unlock(&next->d_lock);
                                p = p->next;
                        }
-                       list_add_tail(&cursor->d_u.d_child, p);
+                       list_add_tail(&cursor->d_child, p);
                        spin_unlock(&dentry->d_lock);
                }
        }
@@ -149,7 +149,7 @@ int dcache_readdir(struct file *file, struct dir_context 
*ctx)
 {
        struct dentry *dentry = file->f_path.dentry;
        struct dentry *cursor = file->private_data;
-       struct list_head *p, *q = &cursor->d_u.d_child;
+       struct list_head *p, *q = &cursor->d_child;
 
        if (!dir_emit_dots(file, ctx))
                return 0;
@@ -158,7 +158,7 @@ int dcache_readdir(struct file *file, struct dir_context 
*ctx)
                list_move(q, &dentry->d_subdirs);
 
        for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
-               struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
+               struct dentry *next = list_entry(p, struct dentry, d_child);
                spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
                if (!simple_positive(next)) {
                        spin_unlock(&next->d_lock);
@@ -286,7 +286,7 @@ int simple_empty(struct dentry *dentry)
        int ret = 0;
 
        spin_lock(&dentry->d_lock);
-       list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+       list_for_each_entry(child, &dentry->d_subdirs, d_child) {
                spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
                if (simple_positive(child)) {
                        spin_unlock(&child->d_lock);
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index c320ac5..dc9747d 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -406,7 +406,7 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, 
unsigned long fpos)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dent = list_entry(next, struct dentry, d_u.d_child);
+               dent = list_entry(next, struct dentry, d_child);
                if ((unsigned long)dent->d_fsdata == fpos) {
                        if (dent->d_inode)
                                dget(dent);
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 32c0658..6d5e7c5 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -194,7 +194,7 @@ ncp_renew_dentries(struct dentry *parent)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dentry = list_entry(next, struct dentry, d_u.d_child);
+               dentry = list_entry(next, struct dentry, d_child);
 
                if (dentry->d_fsdata == NULL)
                        ncp_age_dentry(server, dentry);
@@ -216,7 +216,7 @@ ncp_invalidate_dircache_entries(struct dentry *parent)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dentry = list_entry(next, struct dentry, d_u.d_child);
+               dentry = list_entry(next, struct dentry, d_child);
                dentry->d_fsdata = NULL;
                ncp_age_dentry(server, dentry);
                next = next->next;
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index 66984a9..5b8ab0e 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -58,7 +58,7 @@ static int nfs_superblock_set_dummy_root(struct super_block 
*sb, struct inode *i
                 */
                spin_lock(&sb->s_root->d_inode->i_lock);
                spin_lock(&sb->s_root->d_lock);
-               hlist_del_init(&sb->s_root->d_alias);
+               hlist_del_init(&sb->s_root->d_u.d_alias);
                spin_unlock(&sb->s_root->d_lock);
                spin_unlock(&sb->s_root->d_inode->i_lock);
        }
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 4bb21d6..a3153e2 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -63,14 +63,14 @@ void __fsnotify_update_child_dentry_flags(struct inode 
*inode)
        spin_lock(&inode->i_lock);
        /* run all of the dentries associated with this inode.  Since this is a
         * directory, there damn well better only be one item on this list */
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                struct dentry *child;
 
                /* run all of the children of the original inode and fix their
                 * d_flags to indicate parental interest (their parent is the
                 * original inode) */
                spin_lock(&alias->d_lock);
-               list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) {
+               list_for_each_entry(child, &alias->d_subdirs, d_child) {
                        if (!child->d_inode)
                                continue;
 
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index 0d3a97d..1167485 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -173,7 +173,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
        struct dentry *dentry;
 
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
                        trace_ocfs2_find_local_alias(dentry->d_name.len,
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 04421e8..6c58dd7 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -68,6 +68,7 @@ extern void groups_free(struct group_info *);
 extern int set_current_groups(struct group_info *);
 extern int set_groups(struct cred *, struct group_info *);
 extern int groups_search(const struct group_info *, kgid_t);
+extern bool may_setgroups(void);
 
 /* access the groups "array" with this macro */
 #define GROUP_AT(gi, i) \
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 3b50cac..0f0eb1c 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -124,15 +124,15 @@ struct dentry {
        void *d_fsdata;                 /* fs-specific data */
 
        struct list_head d_lru;         /* LRU list */
+       struct list_head d_child;       /* child of parent list */
+       struct list_head d_subdirs;     /* our children */
        /*
-        * d_child and d_rcu can share memory
+        * d_alias and d_rcu can share memory
         */
        union {
-               struct list_head d_child;       /* child of parent list */
+               struct hlist_node d_alias;      /* inode alias list */
                struct rcu_head d_rcu;
        } d_u;
-       struct list_head d_subdirs;     /* our children */
-       struct hlist_node d_alias;      /* inode alias list */
 };
 
 /*
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 4836ba3..dd4f91b 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -63,6 +63,7 @@ extern struct seq_operations proc_projid_seq_operations;
 extern ssize_t proc_uid_map_write(struct file *, const char __user *, size_t, 
loff_t *);
 extern ssize_t proc_gid_map_write(struct file *, const char __user *, size_t, 
loff_t *);
 extern ssize_t proc_projid_map_write(struct file *, const char __user *, 
size_t, loff_t *);
+extern bool userns_may_setgroups(const struct user_namespace *ns);
 #else
 
 static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
@@ -87,6 +88,10 @@ static inline void put_user_ns(struct user_namespace *ns)
 {
 }
 
+static inline bool userns_may_setgroups(const struct user_namespace *ns)
+{
+       return true;
+}
 #endif
 
 #endif /* _LINUX_USER_H */
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 8e5e0a9..6f2aae9 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -980,7 +980,7 @@ static void cgroup_d_remove_dir(struct dentry *dentry)
        parent = dentry->d_parent;
        spin_lock(&parent->d_lock);
        spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-       list_del_init(&dentry->d_u.d_child);
+       list_del_init(&dentry->d_child);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&parent->d_lock);
        remove_dir(dentry);
diff --git a/kernel/groups.c b/kernel/groups.c
index 90cf1c3..67b4ba3 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -6,6 +6,7 @@
 #include <linux/slab.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/user_namespace.h>
 #include <asm/uaccess.h>
 
 /* init to 2 - one for init_task, one to ensure it is never freed */
@@ -223,6 +224,14 @@ out:
        return i;
 }
 
+bool may_setgroups(void)
+{
+       struct user_namespace *user_ns = current_user_ns();
+
+       return ns_capable(user_ns, CAP_SETGID) &&
+               userns_may_setgroups(user_ns);
+}
+
 /*
  *     SMP: Our groups are copy-on-write. We can set them safely
  *     without another task interfering.
@@ -233,7 +242,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, 
grouplist)
        struct group_info *group_info;
        int retval;
 
-       if (!ns_capable(current_user_ns(), CAP_SETGID))
+       if (!may_setgroups())
                return -EPERM;
        if ((unsigned)gidsetsize > NGROUPS_MAX)
                return -EINVAL;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 9270fbc..111cc34 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6062,7 +6062,7 @@ static int instance_mkdir (struct inode *inode, struct 
dentry *dentry, umode_t m
        int ret;
 
        /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
 
@@ -6089,7 +6089,7 @@ static int instance_rmdir(struct inode *inode, struct 
dentry *dentry)
        int ret;
 
        /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
 
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index ba983dc..396c823 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -427,7 +427,7 @@ static void remove_event_file_dir(struct ftrace_event_file 
*file)
 
        if (dir) {
                spin_lock(&dir->d_lock);        /* probably unneeded */
-               list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
+               list_for_each_entry(child, &dir->d_subdirs, d_child) {
                        if (child->d_inode)     /* probably unneeded */
                                child->d_inode->i_private = NULL;
                }
diff --git a/kernel/uid16.c b/kernel/uid16.c
index 602e5bb..d58cc4d 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -176,7 +176,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t 
__user *, grouplist)
        struct group_info *group_info;
        int retval;
 
-       if (!ns_capable(current_user_ns(), CAP_SETGID))
+       if (!may_setgroups())
                return -EPERM;
        if ((unsigned)gidsetsize > NGROUPS_MAX)
                return -EINVAL;
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 4612096..8ee5170 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -804,17 +804,16 @@ static bool new_idmap_permitted(const struct file *file,
                                struct user_namespace *ns, int cap_setid,
                                struct uid_gid_map *new_map)
 {
-       /* Allow mapping to your own filesystem ids */
-       if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1)) {
+       const struct cred *cred = file->f_cred;
+       /* Don't allow mappings that would allow anything that wouldn't
+        * be allowed without the establishment of unprivileged mappings.
+        */
+       if ((new_map->nr_extents == 1) && (new_map->extent[0].count == 1) &&
+           uid_eq(ns->owner, cred->euid)) {
                u32 id = new_map->extent[0].lower_first;
                if (cap_setid == CAP_SETUID) {
                        kuid_t uid = make_kuid(ns->parent, id);
-                       if (uid_eq(uid, file->f_cred->fsuid))
-                               return true;
-               }
-               else if (cap_setid == CAP_SETGID) {
-                       kgid_t gid = make_kgid(ns->parent, id);
-                       if (gid_eq(gid, file->f_cred->fsgid))
+                       if (uid_eq(uid, cred->euid))
                                return true;
                }
        }
@@ -834,6 +833,20 @@ static bool new_idmap_permitted(const struct file *file,
        return false;
 }
 
+bool userns_may_setgroups(const struct user_namespace *ns)
+{
+       bool allowed;
+
+       mutex_lock(&id_map_mutex);
+       /* It is not safe to use setgroups until a gid mapping in
+        * the user namespace has been established.
+        */
+       allowed = ns->gid_map.nr_extents != 0;
+       mutex_unlock(&id_map_mutex);
+
+       return allowed;
+}
+
 static void *userns_get(struct task_struct *task)
 {
        struct user_namespace *user_ns;
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index 8a1d4b54..b3c4223 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -253,7 +253,7 @@ batadv_frag_merge_packets(struct hlist_head *chain, struct 
sk_buff *skb)
        kfree(entry);
 
        /* Make room for the rest of the fragments. */
-       if (pskb_expand_head(skb_out, 0, size - skb->len, GFP_ATOMIC) < 0) {
+       if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) {
                kfree_skb(skb_out);
                skb_out = NULL;
                goto free;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index d83045c..d540da2 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1640,7 +1640,7 @@ static const struct inet_connection_sock_af_ops 
ipv6_specific = {
        .compat_setsockopt = compat_ipv6_setsockopt,
        .compat_getsockopt = compat_ipv6_getsockopt,
 #endif
-       .mtu_reduced       = tcp_v4_mtu_reduced,
+       .mtu_reduced       = tcp_v6_mtu_reduced,
 };
 
 #ifdef CONFIG_TCP_MD5SIG
@@ -1672,7 +1672,7 @@ static const struct inet_connection_sock_af_ops 
ipv6_mapped = {
        .compat_setsockopt = compat_ipv6_setsockopt,
        .compat_getsockopt = compat_ipv6_getsockopt,
 #endif
-       .mtu_reduced       = tcp_v6_mtu_reduced,
+       .mtu_reduced       = tcp_v4_mtu_reduced,
 };
 
 #ifdef CONFIG_TCP_MD5SIG
diff --git a/security/keys/gc.c b/security/keys/gc.c
index d3222b6..009d937 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -157,12 +157,12 @@ static noinline void key_gc_unused_keys(struct list_head 
*keys)
                if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
                        atomic_dec(&key->user->nikeys);
 
-               key_user_put(key->user);
-
                /* now throw away the key memory */
                if (key->type->destroy)
                        key->type->destroy(key);
 
+               key_user_put(key->user);
+
                kfree(key->description);
 
 #ifdef KEY_DEBUGGING
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 5122aff..392ab0f 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1192,7 +1192,7 @@ static void sel_remove_entries(struct dentry *de)
        spin_lock(&de->d_lock);
        node = de->d_subdirs.next;
        while (node != &de->d_subdirs) {
-               struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
+               struct dentry *d = list_entry(node, struct dentry, d_child);
 
                spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
                list_del_init(node);
@@ -1666,12 +1666,12 @@ static void sel_remove_classes(void)
 
        list_for_each(class_node, &class_dir->d_subdirs) {
                struct dentry *class_subdir = list_entry(class_node,
-                                       struct dentry, d_u.d_child);
+                                       struct dentry, d_child);
                struct list_head *class_subdir_node;
 
                list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
                        struct dentry *d = list_entry(class_subdir_node,
-                                               struct dentry, d_u.d_child);
+                                               struct dentry, d_child);
 
                        if (d->d_inode)
                                if (d->d_inode->i_mode & S_IFDIR)
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to