diff --git a/Makefile b/Makefile
index a36dada..6dd1ffb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 4
-SUBLEVEL = 49
+SUBLEVEL = 50
 EXTRAVERSION =
 NAME = Saber-toothed Squirrel
 
diff --git a/arch/powerpc/include/asm/exception-64s.h 
b/arch/powerpc/include/asm/exception-64s.h
index d58fc4e..6afb13a 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -320,7 +320,7 @@ label##_common:                                             
        \
  */
 #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr)            \
        EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \
-                        FINISH_NAP;RUNLATCH_ON;DISABLE_INTS)
+                        FINISH_NAP;DISABLE_INTS;RUNLATCH_ON)
 
 /*
  * When the idle code in power4_idle puts the CPU into NAP mode,
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index d7ebc58..071592b 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -162,7 +162,7 @@ notrace unsigned int __check_irq_replay(void)
         * in case we also had a rollover while hard disabled
         */
        local_paca->irq_happened &= ~PACA_IRQ_DEC;
-       if (decrementer_check_overflow())
+       if ((happened & PACA_IRQ_DEC) || decrementer_check_overflow())
                return 0x900;
 
        /* Finally check if an external interrupt happened */
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 94178e5..c1aef40 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1218,7 +1218,7 @@ EXPORT_SYMBOL(dump_stack);
 
 #ifdef CONFIG_PPC64
 /* Called with hard IRQs off */
-void __ppc64_runlatch_on(void)
+void notrace __ppc64_runlatch_on(void)
 {
        struct thread_info *ti = current_thread_info();
        unsigned long ctrl;
@@ -1231,7 +1231,7 @@ void __ppc64_runlatch_on(void)
 }
 
 /* Called with hard IRQs off */
-void __ppc64_runlatch_off(void)
+void notrace __ppc64_runlatch_off(void)
 {
        struct thread_info *ti = current_thread_info();
        unsigned long ctrl;
diff --git a/arch/x86/kernel/relocate_kernel_64.S 
b/arch/x86/kernel/relocate_kernel_64.S
index 7a6f3b3..f2bb9c9 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -160,7 +160,7 @@ identity_mapped:
        xorq    %rbp, %rbp
        xorq    %r8,  %r8
        xorq    %r9,  %r9
-       xorq    %r10, %r9
+       xorq    %r10, %r10
        xorq    %r11, %r11
        xorq    %r12, %r12
        xorq    %r13, %r13
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index b0f553b..d3446f6 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -161,8 +161,6 @@ static irqreturn_t do_cciss_msix_intr(int irq, void 
*dev_id);
 static int cciss_open(struct block_device *bdev, fmode_t mode);
 static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode);
 static int cciss_release(struct gendisk *disk, fmode_t mode);
-static int do_ioctl(struct block_device *bdev, fmode_t mode,
-                   unsigned int cmd, unsigned long arg);
 static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
                       unsigned int cmd, unsigned long arg);
 static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
@@ -229,7 +227,7 @@ static const struct block_device_operations cciss_fops = {
        .owner = THIS_MODULE,
        .open = cciss_unlocked_open,
        .release = cciss_release,
-       .ioctl = do_ioctl,
+       .ioctl = cciss_ioctl,
        .getgeo = cciss_getgeo,
 #ifdef CONFIG_COMPAT
        .compat_ioctl = cciss_compat_ioctl,
@@ -1140,16 +1138,6 @@ static int cciss_release(struct gendisk *disk, fmode_t 
mode)
        return 0;
 }
 
-static int do_ioctl(struct block_device *bdev, fmode_t mode,
-                   unsigned cmd, unsigned long arg)
-{
-       int ret;
-       mutex_lock(&cciss_mutex);
-       ret = cciss_ioctl(bdev, mode, cmd, arg);
-       mutex_unlock(&cciss_mutex);
-       return ret;
-}
-
 #ifdef CONFIG_COMPAT
 
 static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode,
@@ -1176,7 +1164,7 @@ static int cciss_compat_ioctl(struct block_device *bdev, 
fmode_t mode,
        case CCISS_REGNEWD:
        case CCISS_RESCANDISK:
        case CCISS_GETLUNINFO:
-               return do_ioctl(bdev, mode, cmd, arg);
+               return cciss_ioctl(bdev, mode, cmd, arg);
 
        case CCISS_PASSTHRU32:
                return cciss_ioctl32_passthru(bdev, mode, cmd, arg);
@@ -1216,7 +1204,7 @@ static int cciss_ioctl32_passthru(struct block_device 
*bdev, fmode_t mode,
        if (err)
                return -EFAULT;
 
-       err = do_ioctl(bdev, mode, CCISS_PASSTHRU, (unsigned long)p);
+       err = cciss_ioctl(bdev, mode, CCISS_PASSTHRU, (unsigned long)p);
        if (err)
                return err;
        err |=
@@ -1258,7 +1246,7 @@ static int cciss_ioctl32_big_passthru(struct block_device 
*bdev, fmode_t mode,
        if (err)
                return -EFAULT;
 
-       err = do_ioctl(bdev, mode, CCISS_BIG_PASSTHRU, (unsigned long)p);
+       err = cciss_ioctl(bdev, mode, CCISS_BIG_PASSTHRU, (unsigned long)p);
        if (err)
                return err;
        err |=
@@ -1308,11 +1296,14 @@ static int cciss_getpciinfo(ctlr_info_t *h, void __user 
*argp)
 static int cciss_getintinfo(ctlr_info_t *h, void __user *argp)
 {
        cciss_coalint_struct intinfo;
+       unsigned long flags;
 
        if (!argp)
                return -EINVAL;
+       spin_lock_irqsave(&h->lock, flags);
        intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay);
        intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount);
+       spin_unlock_irqrestore(&h->lock, flags);
        if (copy_to_user
            (argp, &intinfo, sizeof(cciss_coalint_struct)))
                return -EFAULT;
@@ -1353,12 +1344,15 @@ static int cciss_setintinfo(ctlr_info_t *h, void __user 
*argp)
 static int cciss_getnodename(ctlr_info_t *h, void __user *argp)
 {
        NodeName_type NodeName;
+       unsigned long flags;
        int i;
 
        if (!argp)
                return -EINVAL;
+       spin_lock_irqsave(&h->lock, flags);
        for (i = 0; i < 16; i++)
                NodeName[i] = readb(&h->cfgtable->ServerName[i]);
+       spin_unlock_irqrestore(&h->lock, flags);
        if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
                return -EFAULT;
        return 0;
@@ -1395,10 +1389,13 @@ static int cciss_setnodename(ctlr_info_t *h, void 
__user *argp)
 static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp)
 {
        Heartbeat_type heartbeat;
+       unsigned long flags;
 
        if (!argp)
                return -EINVAL;
+       spin_lock_irqsave(&h->lock, flags);
        heartbeat = readl(&h->cfgtable->HeartBeat);
+       spin_unlock_irqrestore(&h->lock, flags);
        if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type)))
                return -EFAULT;
        return 0;
@@ -1407,10 +1404,13 @@ static int cciss_getheartbeat(ctlr_info_t *h, void 
__user *argp)
 static int cciss_getbustypes(ctlr_info_t *h, void __user *argp)
 {
        BusTypes_type BusTypes;
+       unsigned long flags;
 
        if (!argp)
                return -EINVAL;
+       spin_lock_irqsave(&h->lock, flags);
        BusTypes = readl(&h->cfgtable->BusTypes);
+       spin_unlock_irqrestore(&h->lock, flags);
        if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type)))
                return -EFAULT;
        return 0;
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c 
b/drivers/gpu/drm/gma500/cdv_intel_display.c
index be84559..1ee297b 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_display.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -1439,6 +1439,19 @@ static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
        kfree(psb_intel_crtc);
 }
 
+static void cdv_intel_crtc_disable(struct drm_crtc *crtc)
+{
+       struct gtt_range *gt;
+       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+
+       if (crtc->fb) {
+               gt = to_psb_fb(crtc->fb)->gtt;
+               psb_gtt_unpin(gt);
+       }
+}
+
 const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
        .dpms = cdv_intel_crtc_dpms,
        .mode_fixup = cdv_intel_crtc_mode_fixup,
@@ -1446,6 +1459,7 @@ const struct drm_crtc_helper_funcs cdv_intel_helper_funcs 
= {
        .mode_set_base = cdv_intel_pipe_set_base,
        .prepare = cdv_intel_crtc_prepare,
        .commit = cdv_intel_crtc_commit,
+       .disable = cdv_intel_crtc_disable,
 };
 
 const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c 
b/drivers/gpu/drm/gma500/psb_intel_display.c
index 2616558..454a9d8 100644
--- a/drivers/gpu/drm/gma500/psb_intel_display.c
+++ b/drivers/gpu/drm/gma500/psb_intel_display.c
@@ -1262,6 +1262,19 @@ void psb_intel_crtc_destroy(struct drm_crtc *crtc)
        kfree(psb_intel_crtc);
 }
 
+static void psb_intel_crtc_disable(struct drm_crtc *crtc)
+{
+       struct gtt_range *gt;
+       struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+       crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+
+       if (crtc->fb) {
+               gt = to_psb_fb(crtc->fb)->gtt;
+               psb_gtt_unpin(gt);
+       }
+}
+
 const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
        .dpms = psb_intel_crtc_dpms,
        .mode_fixup = psb_intel_crtc_mode_fixup,
@@ -1269,6 +1282,7 @@ const struct drm_crtc_helper_funcs psb_intel_helper_funcs 
= {
        .mode_set_base = psb_intel_pipe_set_base,
        .prepare = psb_intel_crtc_prepare,
        .commit = psb_intel_crtc_commit,
+       .disable = psb_intel_crtc_disable,
 };
 
 const struct drm_crtc_funcs psb_intel_crtc_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
b/drivers/gpu/drm/i915/intel_sdvo.c
index aeb9d6e..c0ba260 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1582,10 +1582,13 @@ static void intel_sdvo_get_lvds_modes(struct 
drm_connector *connector)
         * arranged in priority order.
         */
        intel_ddc_get_modes(connector, &intel_sdvo->ddc);
-       if (list_empty(&connector->probed_modes) == false)
-               goto end;
 
-       /* Fetch modes from VBT */
+       /*
+        * Fetch modes from VBT. For SDVO prefer the VBT mode since some
+        * SDVO->LVDS transcoders can't cope with the EDID mode. Since
+        * drm_mode_probed_add adds the mode at the head of the list we add it
+        * last.
+        */
        if (dev_priv->sdvo_lvds_vbt_mode != NULL) {
                newmode = drm_mode_duplicate(connector->dev,
                                             dev_priv->sdvo_lvds_vbt_mode);
@@ -1597,7 +1600,6 @@ static void intel_sdvo_get_lvds_modes(struct 
drm_connector *connector)
                }
        }
 
-end:
        list_for_each_entry(newmode, &connector->probed_modes, head) {
                if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
                        intel_sdvo->sdvo_lvds_fixed_mode =
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index df44509..b424a20 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -413,7 +413,17 @@ static void raid1_end_write_request(struct bio *bio, int 
error)
 
                r1_bio->bios[mirror] = NULL;
                to_put = bio;
-               set_bit(R1BIO_Uptodate, &r1_bio->state);
+               /*
+                * Do not set R1BIO_Uptodate if the current device is
+                * rebuilding or Faulty. This is because we cannot use
+                * such device for properly reading the data back (we could
+                * potentially use it, if the current write would have felt
+                * before rdev->recovery_offset, but for simplicity we don't
+                * check this here.
+                */
+               if (test_bit(In_sync, &conf->mirrors[mirror].rdev->flags) &&
+                   !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))
+                       set_bit(R1BIO_Uptodate, &r1_bio->state);
 
                /* Maybe we can clear some bad blocks. */
                if (is_badblock(conf->mirrors[mirror].rdev,
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 6137d00..0cc7985 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -452,7 +452,17 @@ static void raid10_end_write_request(struct bio *bio, int 
error)
                sector_t first_bad;
                int bad_sectors;
 
-               set_bit(R10BIO_Uptodate, &r10_bio->state);
+               /*
+                * Do not set R10BIO_Uptodate if the current device is
+                * rebuilding or Faulty. This is because we cannot use
+                * such device for properly reading the data back (we could
+                * potentially use it, if the current write would have felt
+                * before rdev->recovery_offset, but for simplicity we don't
+                * check this here.
+                */
+               if (test_bit(In_sync, &rdev->flags) &&
+                   !test_bit(Faulty, &rdev->flags))
+                       set_bit(R10BIO_Uptodate, &r10_bio->state);
 
                /* Maybe we can clear some bad blocks. */
                if (is_badblock(rdev,
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig 
b/drivers/net/wireless/ath/ath9k/Kconfig
index e507e78..3b8c930 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -89,13 +89,17 @@ config ATH9K_MAC_DEBUG
          This option enables collection of statistics for Rx/Tx status
          data and some other MAC related statistics
 
-config ATH9K_RATE_CONTROL
+config ATH9K_LEGACY_RATE_CONTROL
        bool "Atheros ath9k rate control"
        depends on ATH9K
-       default y
+       default n
        ---help---
          Say Y, if you want to use the ath9k specific rate control
-         module instead of minstrel_ht.
+         module instead of minstrel_ht. Be warned that there are various
+         issues with the ath9k RC and minstrel is a more robust algorithm.
+         Note that even if this option is selected, "ath9k_rate_control"
+         has to be passed to mac80211 using the module parameter,
+         ieee80211_default_rc_algo.
 
 config ATH9K_HTC
        tristate "Atheros HTC based wireless cards support"
diff --git a/drivers/net/wireless/ath/ath9k/Makefile 
b/drivers/net/wireless/ath/ath9k/Makefile
index 27d95fe..24ae2e6 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -6,7 +6,7 @@ ath9k-y +=      beacon.o \
                xmit.o
 
 ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
-ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
+ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_ATH9K_PCI) += pci.o
 ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
 ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
diff --git a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
index cb00645..cac5b25 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -671,8 +671,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct 
ieee80211_hw *hw)
                BIT(NL80211_IFTYPE_ADHOC) |
                BIT(NL80211_IFTYPE_MESH_POINT);
 
-       if (AR_SREV_5416(sc->sc_ah))
-               hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
        hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
@@ -695,10 +694,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct 
ieee80211_hw *hw)
        sc->ant_rx = hw->wiphy->available_antennas_rx;
        sc->ant_tx = hw->wiphy->available_antennas_tx;
 
-#ifdef CONFIG_ATH9K_RATE_CONTROL
-       hw->rate_control_algorithm = "ath9k_rate_control";
-#endif
-
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
                hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
                        &sc->sbands[IEEE80211_BAND_2GHZ];
diff --git a/drivers/net/wireless/ath/ath9k/rc.h 
b/drivers/net/wireless/ath/ath9k/rc.h
index 75f8e9b..12cf122 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -219,7 +219,7 @@ struct ath_rate_priv {
        struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
 };
 
-#ifdef CONFIG_ATH9K_RATE_CONTROL
+#ifdef CONFIG_ATH9K_LEGACY_RATE_CONTROL
 int ath_rate_control_register(void);
 void ath_rate_control_unregister(void);
 #else
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index b54c750..f8c4499 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2449,7 +2449,7 @@ static void b43_request_firmware(struct work_struct *work)
        for (i = 0; i < B43_NR_FWTYPES; i++) {
                errmsg = ctx->errors[i];
                if (strlen(errmsg))
-                       b43err(dev->wl, errmsg);
+                       b43err(dev->wl, "%s", errmsg);
        }
        b43_print_fw_helptext(dev->wl, 1);
        goto out;
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 63ccc0f..c5ce195 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -523,6 +523,7 @@ static int __devinit twl_rtc_probe(struct platform_device 
*pdev)
        }
 
        platform_set_drvdata(pdev, rtc);
+       device_init_wakeup(&pdev->dev, 1);
        return 0;
 
 out2:
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index 80576d05..bb5fb3d 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -191,27 +191,23 @@ void ceph_count_locks(struct inode *inode, int 
*fcntl_count, int *flock_count)
 }
 
 /**
- * Encode the flock and fcntl locks for the given inode into the pagelist.
- * Format is: #fcntl locks, sequential fcntl locks, #flock locks,
- * sequential flock locks.
- * Must be called with lock_flocks() already held.
- * If we encounter more of a specific lock type than expected,
- * we return the value 1.
+ * Encode the flock and fcntl locks for the given inode into the ceph_filelock
+ * array. Must be called with lock_flocks() already held.
+ * If we encounter more of a specific lock type than expected, return -ENOSPC.
  */
-int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist,
-                     int num_fcntl_locks, int num_flock_locks)
+int ceph_encode_locks_to_buffer(struct inode *inode,
+                               struct ceph_filelock *flocks,
+                               int num_fcntl_locks, int num_flock_locks)
 {
        struct file_lock *lock;
-       struct ceph_filelock cephlock;
        int err = 0;
        int seen_fcntl = 0;
        int seen_flock = 0;
+       int l = 0;
 
        dout("encoding %d flock and %d fcntl locks", num_flock_locks,
             num_fcntl_locks);
-       err = ceph_pagelist_append(pagelist, &num_fcntl_locks, sizeof(u32));
-       if (err)
-               goto fail;
+
        for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
                if (lock->fl_flags & FL_POSIX) {
                        ++seen_fcntl;
@@ -219,19 +215,12 @@ int ceph_encode_locks(struct inode *inode, struct 
ceph_pagelist *pagelist,
                                err = -ENOSPC;
                                goto fail;
                        }
-                       err = lock_to_ceph_filelock(lock, &cephlock);
+                       err = lock_to_ceph_filelock(lock, &flocks[l]);
                        if (err)
                                goto fail;
-                       err = ceph_pagelist_append(pagelist, &cephlock,
-                                          sizeof(struct ceph_filelock));
+                       ++l;
                }
-               if (err)
-                       goto fail;
        }
-
-       err = ceph_pagelist_append(pagelist, &num_flock_locks, sizeof(u32));
-       if (err)
-               goto fail;
        for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) {
                if (lock->fl_flags & FL_FLOCK) {
                        ++seen_flock;
@@ -239,19 +228,51 @@ int ceph_encode_locks(struct inode *inode, struct 
ceph_pagelist *pagelist,
                                err = -ENOSPC;
                                goto fail;
                        }
-                       err = lock_to_ceph_filelock(lock, &cephlock);
+                       err = lock_to_ceph_filelock(lock, &flocks[l]);
                        if (err)
                                goto fail;
-                       err = ceph_pagelist_append(pagelist, &cephlock,
-                                          sizeof(struct ceph_filelock));
+                       ++l;
                }
-               if (err)
-                       goto fail;
        }
 fail:
        return err;
 }
 
+/**
+ * Copy the encoded flock and fcntl locks into the pagelist.
+ * Format is: #fcntl locks, sequential fcntl locks, #flock locks,
+ * sequential flock locks.
+ * Returns zero on success.
+ */
+int ceph_locks_to_pagelist(struct ceph_filelock *flocks,
+                          struct ceph_pagelist *pagelist,
+                          int num_fcntl_locks, int num_flock_locks)
+{
+       int err = 0;
+       __le32 nlocks;
+
+       nlocks = cpu_to_le32(num_fcntl_locks);
+       err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks));
+       if (err)
+               goto out_fail;
+
+       err = ceph_pagelist_append(pagelist, flocks,
+                                  num_fcntl_locks * sizeof(*flocks));
+       if (err)
+               goto out_fail;
+
+       nlocks = cpu_to_le32(num_flock_locks);
+       err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks));
+       if (err)
+               goto out_fail;
+
+       err = ceph_pagelist_append(pagelist,
+                                  &flocks[num_fcntl_locks],
+                                  num_flock_locks * sizeof(*flocks));
+out_fail:
+       return err;
+}
+
 /*
  * Given a pointer to a lock, convert it to a ceph filelock
  */
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 3fd08ad..cf1b9e0 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -335,9 +335,9 @@ void ceph_put_mds_session(struct ceph_mds_session *s)
             atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1);
        if (atomic_dec_and_test(&s->s_ref)) {
                if (s->s_auth.authorizer)
-                    s->s_mdsc->fsc->client->monc.auth->ops->destroy_authorizer(
-                            s->s_mdsc->fsc->client->monc.auth,
-                            s->s_auth.authorizer);
+                       ceph_auth_destroy_authorizer(
+                               s->s_mdsc->fsc->client->monc.auth,
+                               s->s_auth.authorizer);
                kfree(s);
        }
 }
@@ -2455,39 +2455,44 @@ static int encode_caps_cb(struct inode *inode, struct 
ceph_cap *cap,
 
        if (recon_state->flock) {
                int num_fcntl_locks, num_flock_locks;
-               struct ceph_pagelist_cursor trunc_point;
-
-               ceph_pagelist_set_cursor(pagelist, &trunc_point);
-               do {
-                       lock_flocks();
-                       ceph_count_locks(inode, &num_fcntl_locks,
-                                        &num_flock_locks);
-                       rec.v2.flock_len = (2*sizeof(u32) +
-                                           (num_fcntl_locks+num_flock_locks) *
-                                           sizeof(struct ceph_filelock));
-                       unlock_flocks();
-
-                       /* pre-alloc pagelist */
-                       ceph_pagelist_truncate(pagelist, &trunc_point);
-                       err = ceph_pagelist_append(pagelist, &rec, reclen);
-                       if (!err)
-                               err = ceph_pagelist_reserve(pagelist,
-                                                           rec.v2.flock_len);
-
-                       /* encode locks */
-                       if (!err) {
-                               lock_flocks();
-                               err = ceph_encode_locks(inode,
-                                                       pagelist,
-                                                       num_fcntl_locks,
-                                                       num_flock_locks);
-                               unlock_flocks();
-                       }
-               } while (err == -ENOSPC);
+               struct ceph_filelock *flocks;
+
+encode_again:
+               lock_flocks();
+               ceph_count_locks(inode, &num_fcntl_locks, &num_flock_locks);
+               unlock_flocks();
+               flocks = kmalloc((num_fcntl_locks+num_flock_locks) *
+                                sizeof(struct ceph_filelock), GFP_NOFS);
+               if (!flocks) {
+                       err = -ENOMEM;
+                       goto out_free;
+               }
+               lock_flocks();
+               err = ceph_encode_locks_to_buffer(inode, flocks,
+                                                 num_fcntl_locks,
+                                                 num_flock_locks);
+               unlock_flocks();
+               if (err) {
+                       kfree(flocks);
+                       if (err == -ENOSPC)
+                               goto encode_again;
+                       goto out_free;
+               }
+               /*
+                * number of encoded locks is stable, so copy to pagelist
+                */
+               rec.v2.flock_len = cpu_to_le32(2*sizeof(u32) +
+                                   (num_fcntl_locks+num_flock_locks) *
+                                   sizeof(struct ceph_filelock));
+               err = ceph_pagelist_append(pagelist, &rec, reclen);
+               if (!err)
+                       err = ceph_locks_to_pagelist(flocks, pagelist,
+                                                    num_fcntl_locks,
+                                                    num_flock_locks);
+               kfree(flocks);
        } else {
                err = ceph_pagelist_append(pagelist, &rec, reclen);
        }
-
 out_free:
        kfree(path);
 out_dput:
@@ -3414,13 +3419,17 @@ static struct ceph_auth_handshake 
*get_authorizer(struct ceph_connection *con,
        struct ceph_auth_handshake *auth = &s->s_auth;
 
        if (force_new && auth->authorizer) {
-               if (ac->ops && ac->ops->destroy_authorizer)
-                       ac->ops->destroy_authorizer(ac, auth->authorizer);
+               ceph_auth_destroy_authorizer(ac, auth->authorizer);
                auth->authorizer = NULL;
        }
-       if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
-               int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS,
-                                                       auth);
+       if (!auth->authorizer) {
+               int ret = ceph_auth_create_authorizer(ac, CEPH_ENTITY_TYPE_MDS,
+                                                     auth);
+               if (ret)
+                       return ERR_PTR(ret);
+       } else {
+               int ret = ceph_auth_update_authorizer(ac, CEPH_ENTITY_TYPE_MDS,
+                                                     auth);
                if (ret)
                        return ERR_PTR(ret);
        }
@@ -3436,7 +3445,7 @@ static int verify_authorizer_reply(struct ceph_connection 
*con, int len)
        struct ceph_mds_client *mdsc = s->s_mdsc;
        struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
 
-       return ac->ops->verify_authorizer_reply(ac, s->s_auth.authorizer, len);
+       return ceph_auth_verify_authorizer_reply(ac, s->s_auth.authorizer, len);
 }
 
 static int invalidate_authorizer(struct ceph_connection *con)
@@ -3445,8 +3454,7 @@ static int invalidate_authorizer(struct ceph_connection 
*con)
        struct ceph_mds_client *mdsc = s->s_mdsc;
        struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
 
-       if (ac->ops->invalidate_authorizer)
-               ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_MDS);
+       ceph_auth_invalidate_authorizer(ac, CEPH_ENTITY_TYPE_MDS);
 
        return ceph_monc_validate_auth(&mdsc->fsc->client->monc);
 }
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index f363918..f4fa5cf 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -70,8 +70,14 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs 
*buf)
        /*
         * express utilization in terms of large blocks to avoid
         * overflow on 32-bit machines.
+        *
+        * NOTE: for the time being, we make bsize == frsize to humor
+        * not-yet-ancient versions of glibc that are broken.
+        * Someday, we will probably want to report a real block
+        * size...  whatever that may mean for a network file system!
         */
        buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
+       buf->f_frsize = 1 << CEPH_BLOCK_SHIFT;
        buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
        buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
        buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
@@ -79,7 +85,6 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs 
*buf)
        buf->f_files = le64_to_cpu(st.num_objects);
        buf->f_ffree = -1;
        buf->f_namelen = NAME_MAX;
-       buf->f_frsize = PAGE_CACHE_SIZE;
 
        /* leave fsid little-endian, regardless of host endianness */
        fsid = *(u64 *)(&monmap->fsid) ^ *((u64 *)&monmap->fsid + 1);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index fc35036..d2e01a6 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -21,7 +21,7 @@
 
 /* large granularity for statfs utilization stats to facilitate
  * large volume sizes on 32-bit machines. */
-#define CEPH_BLOCK_SHIFT   20  /* 1 MB */
+#define CEPH_BLOCK_SHIFT   22  /* 4 MB */
 #define CEPH_BLOCK         (1 << CEPH_BLOCK_SHIFT)
 
 #define CEPH_MOUNT_OPT_DIRSTAT         (1<<4) /* `cat dirname` for stats */
@@ -847,8 +847,13 @@ extern const struct export_operations ceph_export_ops;
 extern int ceph_lock(struct file *file, int cmd, struct file_lock *fl);
 extern int ceph_flock(struct file *file, int cmd, struct file_lock *fl);
 extern void ceph_count_locks(struct inode *inode, int *p_num, int *f_num);
-extern int ceph_encode_locks(struct inode *i, struct ceph_pagelist *p,
-                            int p_locks, int f_locks);
+extern int ceph_encode_locks_to_buffer(struct inode *inode,
+                                      struct ceph_filelock *flocks,
+                                      int num_fcntl_locks,
+                                      int num_flock_locks);
+extern int ceph_locks_to_pagelist(struct ceph_filelock *flocks,
+                                 struct ceph_pagelist *pagelist,
+                                 int num_fcntl_locks, int num_flock_locks);
 extern int lock_to_ceph_filelock(struct file_lock *fl, struct ceph_filelock 
*c);
 
 /* debugfs.c */
diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h
index d4080f3..5f33868 100644
--- a/include/linux/ceph/auth.h
+++ b/include/linux/ceph/auth.h
@@ -52,6 +52,9 @@ struct ceph_auth_client_ops {
         */
        int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type,
                                 struct ceph_auth_handshake *auth);
+       /* ensure that an existing authorizer is up to date */
+       int (*update_authorizer)(struct ceph_auth_client *ac, int peer_type,
+                                struct ceph_auth_handshake *auth);
        int (*verify_authorizer_reply)(struct ceph_auth_client *ac,
                                       struct ceph_authorizer *a, size_t len);
        void (*destroy_authorizer)(struct ceph_auth_client *ac,
@@ -75,6 +78,8 @@ struct ceph_auth_client {
        u64 global_id;          /* our unique id in system */
        const struct ceph_crypto_key *key;     /* our secret key */
        unsigned want_keys;     /* which services we want */
+
+       struct mutex mutex;
 };
 
 extern struct ceph_auth_client *ceph_auth_init(const char *name,
@@ -94,5 +99,18 @@ extern int ceph_build_auth(struct ceph_auth_client *ac,
                    void *msg_buf, size_t msg_len);
 
 extern int ceph_auth_is_authenticated(struct ceph_auth_client *ac);
+extern int ceph_auth_create_authorizer(struct ceph_auth_client *ac,
+                                      int peer_type,
+                                      struct ceph_auth_handshake *auth);
+extern void ceph_auth_destroy_authorizer(struct ceph_auth_client *ac,
+                                        struct ceph_authorizer *a);
+extern int ceph_auth_update_authorizer(struct ceph_auth_client *ac,
+                                      int peer_type,
+                                      struct ceph_auth_handshake *a);
+extern int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
+                                            struct ceph_authorizer *a,
+                                            size_t len);
+extern void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac,
+                                           int peer_type);
 
 #endif
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 78ed62f..25fd741 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -177,6 +177,8 @@ extern struct bus_type cpu_subsys;
 
 extern void get_online_cpus(void);
 extern void put_online_cpus(void);
+extern void cpu_hotplug_disable(void);
+extern void cpu_hotplug_enable(void);
 #define hotcpu_notifier(fn, pri)       cpu_notifier(fn, pri)
 #define register_hotcpu_notifier(nb)   register_cpu_notifier(nb)
 #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
@@ -199,6 +201,8 @@ static inline void cpu_hotplug_driver_unlock(void)
 
 #define get_online_cpus()      do { } while (0)
 #define put_online_cpus()      do { } while (0)
+#define cpu_hotplug_disable()  do { } while (0)
+#define cpu_hotplug_enable()   do { } while (0)
 #define hotcpu_notifier(fn, pri)       do { (void)(fn); } while (0)
 /* These aren't inline functions due to a GCC bug. */
 #define register_hotcpu_notifier(nb)   ({ (void)(nb); 0; })
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index 47ead51..c5fd30d 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -137,6 +137,7 @@ static inline void make_migration_entry_read(swp_entry_t 
*entry)
 
 extern void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
                                        unsigned long address);
+extern void migration_entry_wait_huge(struct mm_struct *mm, pte_t *pte);
 #else
 
 #define make_migration_entry(page, write) swp_entry(0, 0)
@@ -148,6 +149,8 @@ static inline int is_migration_entry(swp_entry_t swp)
 static inline void make_migration_entry_read(swp_entry_t *entryp) { }
 static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
                                         unsigned long address) { }
+static inline void migration_entry_wait_huge(struct mm_struct *mm,
+                                       pte_t *pte) { }
 static inline int is_write_migration_entry(swp_entry_t entry)
 {
        return 0;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index db1c5df..4886c11 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -976,6 +976,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
 int mgmt_index_added(struct hci_dev *hdev);
 int mgmt_index_removed(struct hci_dev *hdev);
+int mgmt_set_powered_failed(struct hci_dev *hdev, int err);
 int mgmt_powered(struct hci_dev *hdev, u8 powered);
 int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
 int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index ebfd91f..8098e87 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -42,6 +42,7 @@
 #define MGMT_STATUS_NOT_POWERED                0x0f
 #define MGMT_STATUS_CANCELLED          0x10
 #define MGMT_STATUS_INVALID_INDEX      0x11
+#define MGMT_STATUS_RFKILLED           0x12
 
 struct mgmt_hdr {
        __le16  opcode;
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 2060c6e..26feaa9 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -124,6 +124,27 @@ static void cpu_hotplug_done(void)
        mutex_unlock(&cpu_hotplug.lock);
 }
 
+/*
+ * Wait for currently running CPU hotplug operations to complete (if any) and
+ * disable future CPU hotplug (from sysfs). The 'cpu_add_remove_lock' protects
+ * the 'cpu_hotplug_disabled' flag. The same lock is also acquired by the
+ * hotplug path before performing hotplug operations. So acquiring that lock
+ * guarantees mutual exclusion from any currently running hotplug operations.
+ */
+void cpu_hotplug_disable(void)
+{
+       cpu_maps_update_begin();
+       cpu_hotplug_disabled = 1;
+       cpu_maps_update_done();
+}
+
+void cpu_hotplug_enable(void)
+{
+       cpu_maps_update_begin();
+       cpu_hotplug_disabled = 0;
+       cpu_maps_update_done();
+}
+
 #else /* #if CONFIG_HOTPLUG_CPU */
 static void cpu_hotplug_begin(void) {}
 static void cpu_hotplug_done(void) {}
@@ -479,36 +500,6 @@ static int __init alloc_frozen_cpus(void)
 core_initcall(alloc_frozen_cpus);
 
 /*
- * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU
- * hotplug when tasks are about to be frozen. Also, don't allow the freezer
- * to continue until any currently running CPU hotplug operation gets
- * completed.
- * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
- * 'cpu_add_remove_lock'. And this same lock is also taken by the regular
- * CPU hotplug path and released only after it is complete. Thus, we
- * (and hence the freezer) will block here until any currently running CPU
- * hotplug operation gets completed.
- */
-void cpu_hotplug_disable_before_freeze(void)
-{
-       cpu_maps_update_begin();
-       cpu_hotplug_disabled = 1;
-       cpu_maps_update_done();
-}
-
-
-/*
- * When tasks have been thawed, re-enable regular CPU hotplug (which had been
- * disabled while beginning to freeze tasks).
- */
-void cpu_hotplug_enable_after_thaw(void)
-{
-       cpu_maps_update_begin();
-       cpu_hotplug_disabled = 0;
-       cpu_maps_update_done();
-}
-
-/*
  * When callbacks for CPU hotplug notifications are being executed, we must
  * ensure that the state of the system with respect to the tasks being frozen
  * or not, as reported by the notification, remains unchanged *throughout the
@@ -527,12 +518,12 @@ cpu_hotplug_pm_callback(struct notifier_block *nb,
 
        case PM_SUSPEND_PREPARE:
        case PM_HIBERNATION_PREPARE:
-               cpu_hotplug_disable_before_freeze();
+               cpu_hotplug_disable();
                break;
 
        case PM_POST_SUSPEND:
        case PM_POST_HIBERNATION:
-               cpu_hotplug_enable_after_thaw();
+               cpu_hotplug_enable();
                break;
 
        default:
diff --git a/kernel/sys.c b/kernel/sys.c
index 6a74b83..3449d26 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -353,6 +353,29 @@ int unregister_reboot_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_reboot_notifier);
 
+/* Add backwards compatibility for stable trees. */
+#ifndef PF_NO_SETAFFINITY
+#define PF_NO_SETAFFINITY              PF_THREAD_BOUND
+#endif
+
+static void migrate_to_reboot_cpu(void)
+{
+       /* The boot cpu is always logical cpu 0 */
+       int cpu = 0;
+
+       cpu_hotplug_disable();
+
+       /* Make certain the cpu I'm about to reboot on is online */
+       if (!cpu_online(cpu))
+               cpu = cpumask_first(cpu_online_mask);
+
+       /* Prevent races with other tasks migrating this task */
+       current->flags |= PF_NO_SETAFFINITY;
+
+       /* Make certain I only run on the appropriate processor */
+       set_cpus_allowed_ptr(current, cpumask_of(cpu));
+}
+
 /**
  *     kernel_restart - reboot the system
  *     @cmd: pointer to buffer containing command to execute for restart
@@ -364,7 +387,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier);
 void kernel_restart(char *cmd)
 {
        kernel_restart_prepare(cmd);
-       disable_nonboot_cpus();
+       migrate_to_reboot_cpu();
        syscore_shutdown();
        if (!cmd)
                printk(KERN_EMERG "Restarting system.\n");
@@ -391,7 +414,7 @@ static void kernel_shutdown_prepare(enum system_states 
state)
 void kernel_halt(void)
 {
        kernel_shutdown_prepare(SYSTEM_HALT);
-       disable_nonboot_cpus();
+       migrate_to_reboot_cpu();
        syscore_shutdown();
        printk(KERN_EMERG "System halted.\n");
        kmsg_dump(KMSG_DUMP_HALT);
@@ -410,7 +433,7 @@ void kernel_power_off(void)
        kernel_shutdown_prepare(SYSTEM_POWER_OFF);
        if (pm_power_off_prepare)
                pm_power_off_prepare();
-       disable_nonboot_cpus();
+       migrate_to_reboot_cpu();
        syscore_shutdown();
        printk(KERN_EMERG "Power down.\n");
        kmsg_dump(KMSG_DUMP_POWEROFF);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 69b21bb..a692439 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2768,7 +2768,7 @@ int hugetlb_fault(struct mm_struct *mm, struct 
vm_area_struct *vma,
        if (ptep) {
                entry = huge_ptep_get(ptep);
                if (unlikely(is_hugetlb_entry_migration(entry))) {
-                       migration_entry_wait(mm, (pmd_t *)ptep, address);
+                       migration_entry_wait_huge(mm, ptep);
                        return 0;
                } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
                        return VM_FAULT_HWPOISON_LARGE |
diff --git a/mm/migrate.c b/mm/migrate.c
index 37cd07b..5f588b1 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -180,15 +180,14 @@ static void remove_migration_ptes(struct page *old, 
struct page *new)
  * get to the page and wait until migration is finished.
  * When we return from this function the fault will be retried.
  */
-void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
-                               unsigned long address)
+static void __migration_entry_wait(struct mm_struct *mm, pte_t *ptep,
+                               spinlock_t *ptl)
 {
-       pte_t *ptep, pte;
-       spinlock_t *ptl;
+       pte_t pte;
        swp_entry_t entry;
        struct page *page;
 
-       ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+       spin_lock(ptl);
        pte = *ptep;
        if (!is_swap_pte(pte))
                goto out;
@@ -216,6 +215,20 @@ out:
        pte_unmap_unlock(ptep, ptl);
 }
 
+void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
+                               unsigned long address)
+{
+       spinlock_t *ptl = pte_lockptr(mm, pmd);
+       pte_t *ptep = pte_offset_map(pmd, address);
+       __migration_entry_wait(mm, ptep, ptl);
+}
+
+void migration_entry_wait_huge(struct mm_struct *mm, pte_t *pte)
+{
+       spinlock_t *ptl = &(mm)->page_table_lock;
+       __migration_entry_wait(mm, pte, ptl);
+}
+
 #ifdef CONFIG_BLOCK
 /* Returns true if all buffers are successfully locked */
 static bool buffer_migrate_lock_buffers(struct buffer_head *head,
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 4c5ff7f..1fa9220 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -313,8 +313,24 @@ struct page *read_swap_cache_async(swp_entry_t entry, 
gfp_t gfp_mask,
                 * Swap entry may have been freed since our caller observed it.
                 */
                err = swapcache_prepare(entry);
-               if (err == -EEXIST) {   /* seems racy */
+               if (err == -EEXIST) {
                        radix_tree_preload_end();
+                       /*
+                        * We might race against get_swap_page() and stumble
+                        * across a SWAP_HAS_CACHE swap_map entry whose page
+                        * has not been brought into the swapcache yet, while
+                        * the other end is scheduled away waiting on discard
+                        * I/O completion at scan_swap_map().
+                        *
+                        * In order to avoid turning this transitory state
+                        * into a permanent loop around this -EEXIST case
+                        * if !CONFIG_PREEMPT and the I/O completion happens
+                        * to be waiting on the CPU waitqueue where we are now
+                        * busy looping, we just conditionally invoke the
+                        * scheduler here, if there are some more important
+                        * tasks to run.
+                        */
+                       cond_resched();
                        continue;
                }
                if (err) {              /* swp entry is obsolete ? */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 13b6c28..9197ae7 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1120,11 +1120,15 @@ EXPORT_SYMBOL(hci_free_dev);
 static void hci_power_on(struct work_struct *work)
 {
        struct hci_dev *hdev = container_of(work, struct hci_dev, power_on);
+       int err;
 
        BT_DBG("%s", hdev->name);
 
-       if (hci_dev_open(hdev->id) < 0)
+       err = hci_dev_open(hdev->id);
+       if (err < 0) {
+               mgmt_set_powered_failed(hdev, err);
                return;
+       }
 
        if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
                schedule_delayed_work(&hdev->power_off,
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8f3d9dc..9f2f206 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2833,6 +2833,27 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
        return err;
 }
 
+int mgmt_set_powered_failed(struct hci_dev *hdev, int err)
+{
+       struct pending_cmd *cmd;
+       u8 status;
+
+       cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
+       if (!cmd)
+               return -ENOENT;
+
+       if (err == -ERFKILL)
+               status = MGMT_STATUS_RFKILLED;
+       else
+               status = MGMT_STATUS_FAILED;
+
+       err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
+
+       mgmt_pending_remove(cmd);
+
+       return err;
+}
+
 int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
 {
        struct cmd_lookup match = { NULL, hdev };
diff --git a/net/ceph/auth.c b/net/ceph/auth.c
index b4bf4ac..6b923bc 100644
--- a/net/ceph/auth.c
+++ b/net/ceph/auth.c
@@ -47,6 +47,7 @@ struct ceph_auth_client *ceph_auth_init(const char *name, 
const struct ceph_cryp
        if (!ac)
                goto out;
 
+       mutex_init(&ac->mutex);
        ac->negotiating = true;
        if (name)
                ac->name = name;
@@ -73,10 +74,12 @@ void ceph_auth_destroy(struct ceph_auth_client *ac)
  */
 void ceph_auth_reset(struct ceph_auth_client *ac)
 {
+       mutex_lock(&ac->mutex);
        dout("auth_reset %p\n", ac);
        if (ac->ops && !ac->negotiating)
                ac->ops->reset(ac);
        ac->negotiating = true;
+       mutex_unlock(&ac->mutex);
 }
 
 int ceph_entity_name_encode(const char *name, void **p, void *end)
@@ -102,6 +105,7 @@ int ceph_auth_build_hello(struct ceph_auth_client *ac, void 
*buf, size_t len)
        int i, num;
        int ret;
 
+       mutex_lock(&ac->mutex);
        dout("auth_build_hello\n");
        monhdr->have_version = 0;
        monhdr->session_mon = cpu_to_le16(-1);
@@ -122,15 +126,19 @@ int ceph_auth_build_hello(struct ceph_auth_client *ac, 
void *buf, size_t len)
 
        ret = ceph_entity_name_encode(ac->name, &p, end);
        if (ret < 0)
-               return ret;
+               goto out;
        ceph_decode_need(&p, end, sizeof(u64), bad);
        ceph_encode_64(&p, ac->global_id);
 
        ceph_encode_32(&lenp, p - lenp - sizeof(u32));
-       return p - buf;
+       ret = p - buf;
+out:
+       mutex_unlock(&ac->mutex);
+       return ret;
 
 bad:
-       return -ERANGE;
+       ret = -ERANGE;
+       goto out;
 }
 
 static int ceph_build_auth_request(struct ceph_auth_client *ac,
@@ -151,11 +159,13 @@ static int ceph_build_auth_request(struct 
ceph_auth_client *ac,
        if (ret < 0) {
                pr_err("error %d building auth method %s request\n", ret,
                       ac->ops->name);
-               return ret;
+               goto out;
        }
        dout(" built request %d bytes\n", ret);
        ceph_encode_32(&p, ret);
-       return p + ret - msg_buf;
+       ret = p + ret - msg_buf;
+out:
+       return ret;
 }
 
 /*
@@ -176,6 +186,7 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac,
        int result_msg_len;
        int ret = -EINVAL;
 
+       mutex_lock(&ac->mutex);
        dout("handle_auth_reply %p %p\n", p, end);
        ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
        protocol = ceph_decode_32(&p);
@@ -227,33 +238,103 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac,
 
        ret = ac->ops->handle_reply(ac, result, payload, payload_end);
        if (ret == -EAGAIN) {
-               return ceph_build_auth_request(ac, reply_buf, reply_len);
+               ret = ceph_build_auth_request(ac, reply_buf, reply_len);
        } else if (ret) {
                pr_err("auth method '%s' error %d\n", ac->ops->name, ret);
-               return ret;
        }
-       return 0;
 
-bad:
-       pr_err("failed to decode auth msg\n");
 out:
+       mutex_unlock(&ac->mutex);
        return ret;
+
+bad:
+       pr_err("failed to decode auth msg\n");
+       ret = -EINVAL;
+       goto out;
 }
 
 int ceph_build_auth(struct ceph_auth_client *ac,
                    void *msg_buf, size_t msg_len)
 {
+       int ret = 0;
+
+       mutex_lock(&ac->mutex);
        if (!ac->protocol)
-               return ceph_auth_build_hello(ac, msg_buf, msg_len);
-       BUG_ON(!ac->ops);
-       if (ac->ops->should_authenticate(ac))
-               return ceph_build_auth_request(ac, msg_buf, msg_len);
-       return 0;
+               ret = ceph_auth_build_hello(ac, msg_buf, msg_len);
+       else if (ac->ops->should_authenticate(ac))
+               ret = ceph_build_auth_request(ac, msg_buf, msg_len);
+       mutex_unlock(&ac->mutex);
+       return ret;
 }
 
 int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
 {
-       if (!ac->ops)
-               return 0;
-       return ac->ops->is_authenticated(ac);
+       int ret = 0;
+
+       mutex_lock(&ac->mutex);
+       if (ac->ops)
+               ret = ac->ops->is_authenticated(ac);
+       mutex_unlock(&ac->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(ceph_auth_is_authenticated);
+
+int ceph_auth_create_authorizer(struct ceph_auth_client *ac,
+                               int peer_type,
+                               struct ceph_auth_handshake *auth)
+{
+       int ret = 0;
+
+       mutex_lock(&ac->mutex);
+       if (ac->ops && ac->ops->create_authorizer)
+               ret = ac->ops->create_authorizer(ac, peer_type, auth);
+       mutex_unlock(&ac->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(ceph_auth_create_authorizer);
+
+void ceph_auth_destroy_authorizer(struct ceph_auth_client *ac,
+                                 struct ceph_authorizer *a)
+{
+       mutex_lock(&ac->mutex);
+       if (ac->ops && ac->ops->destroy_authorizer)
+               ac->ops->destroy_authorizer(ac, a);
+       mutex_unlock(&ac->mutex);
+}
+EXPORT_SYMBOL(ceph_auth_destroy_authorizer);
+
+int ceph_auth_update_authorizer(struct ceph_auth_client *ac,
+                               int peer_type,
+                               struct ceph_auth_handshake *a)
+{
+       int ret = 0;
+
+       mutex_lock(&ac->mutex);
+       if (ac->ops && ac->ops->update_authorizer)
+               ret = ac->ops->update_authorizer(ac, peer_type, a);
+       mutex_unlock(&ac->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(ceph_auth_update_authorizer);
+
+int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
+                                     struct ceph_authorizer *a, size_t len)
+{
+       int ret = 0;
+
+       mutex_lock(&ac->mutex);
+       if (ac->ops && ac->ops->verify_authorizer_reply)
+               ret = ac->ops->verify_authorizer_reply(ac, a, len);
+       mutex_unlock(&ac->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply);
+
+void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int 
peer_type)
+{
+       mutex_lock(&ac->mutex);
+       if (ac->ops && ac->ops->invalidate_authorizer)
+               ac->ops->invalidate_authorizer(ac, peer_type);
+       mutex_unlock(&ac->mutex);
 }
+EXPORT_SYMBOL(ceph_auth_invalidate_authorizer);
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
index a16bf14..96238ba 100644
--- a/net/ceph/auth_x.c
+++ b/net/ceph/auth_x.c
@@ -298,6 +298,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client 
*ac,
                        return -ENOMEM;
        }
        au->service = th->service;
+       au->secret_id = th->secret_id;
 
        msg_a = au->buf->vec.iov_base;
        msg_a->struct_v = 1;
@@ -555,6 +556,26 @@ static int ceph_x_create_authorizer(
        return 0;
 }
 
+static int ceph_x_update_authorizer(
+       struct ceph_auth_client *ac, int peer_type,
+       struct ceph_auth_handshake *auth)
+{
+       struct ceph_x_authorizer *au;
+       struct ceph_x_ticket_handler *th;
+
+       th = get_ticket_handler(ac, peer_type);
+       if (IS_ERR(th))
+               return PTR_ERR(th);
+
+       au = (struct ceph_x_authorizer *)auth->authorizer;
+       if (au->secret_id < th->secret_id) {
+               dout("ceph_x_update_authorizer service %u secret %llu < %llu\n",
+                    au->service, au->secret_id, th->secret_id);
+               return ceph_x_build_authorizer(ac, th, au);
+       }
+       return 0;
+}
+
 static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
                                          struct ceph_authorizer *a, size_t len)
 {
@@ -630,7 +651,7 @@ static void ceph_x_invalidate_authorizer(struct 
ceph_auth_client *ac,
 
        th = get_ticket_handler(ac, peer_type);
        if (!IS_ERR(th))
-               remove_ticket_handler(ac, th);
+               memset(&th->validity, 0, sizeof(th->validity));
 }
 
 
@@ -641,6 +662,7 @@ static const struct ceph_auth_client_ops ceph_x_ops = {
        .build_request = ceph_x_build_request,
        .handle_reply = ceph_x_handle_reply,
        .create_authorizer = ceph_x_create_authorizer,
+       .update_authorizer = ceph_x_update_authorizer,
        .verify_authorizer_reply = ceph_x_verify_authorizer_reply,
        .destroy_authorizer = ceph_x_destroy_authorizer,
        .invalidate_authorizer = ceph_x_invalidate_authorizer,
diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h
index e02da7a..5c2ad4e 100644
--- a/net/ceph/auth_x.h
+++ b/net/ceph/auth_x.h
@@ -29,6 +29,7 @@ struct ceph_x_authorizer {
        struct ceph_buffer *buf;
        unsigned service;
        u64 nonce;
+       u64 secret_id;
        char reply_buf[128];  /* big enough for encrypted blob */
 };
 
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index ba1037c..7f703ae 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1542,7 +1542,6 @@ static int process_connect(struct ceph_connection *con)
                        con->error_msg = "connect authorization failure";
                        return -1;
                }
-               con->auth_retry = 1;
                con_out_kvec_reset(con);
                ret = prepare_write_connect(con);
                if (ret < 0)
@@ -1627,7 +1626,7 @@ static int process_connect(struct ceph_connection *con)
 
                WARN_ON(con->state != CON_STATE_NEGOTIATING);
                con->state = CON_STATE_OPEN;
-
+               con->auth_retry = 0;    /* we authenticated; clear flag */
                con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
                con->connect_seq++;
                con->peer_features = server_feat;
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index 89a6409..6765da3 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -737,7 +737,7 @@ static void delayed_work(struct work_struct *work)
 
                __validate_auth(monc);
 
-               if (monc->auth->ops->is_authenticated(monc->auth))
+               if (ceph_auth_is_authenticated(monc->auth))
                        __send_subscribe(monc);
        }
        __schedule_delayed(monc);
@@ -893,8 +893,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
 
        mutex_lock(&monc->mutex);
        had_debugfs_info = have_debugfs_info(monc);
-       if (monc->auth->ops)
-               was_auth = monc->auth->ops->is_authenticated(monc->auth);
+       was_auth = ceph_auth_is_authenticated(monc->auth);
        monc->pending_auth = 0;
        ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
                                     msg->front.iov_len,
@@ -905,7 +904,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc,
                wake_up_all(&monc->client->auth_wq);
        } else if (ret > 0) {
                __send_prepared_auth_request(monc, ret);
-       } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) {
+       } else if (!was_auth && ceph_auth_is_authenticated(monc->auth)) {
                dout("authenticated, starting session\n");
 
                monc->client->msgr.inst.name.type = CEPH_ENTITY_TYPE_CLIENT;
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index b16dfa2..8e3aa4d 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -671,8 +671,7 @@ static void put_osd(struct ceph_osd *osd)
        if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) {
                struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth;
 
-               if (ac->ops && ac->ops->destroy_authorizer)
-                       ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer);
+               ceph_auth_destroy_authorizer(ac, osd->o_auth.authorizer);
                kfree(osd);
        }
 }
@@ -1337,13 +1336,13 @@ static void kick_requests(struct ceph_osd_client *osdc, 
int force_resend)
                __register_request(osdc, req);
                __unregister_linger_request(osdc, req);
        }
+       reset_changed_osds(osdc);
        mutex_unlock(&osdc->request_mutex);
 
        if (needmap) {
                dout("%d requests for down osds, need new map\n", needmap);
                ceph_monc_request_next_osdmap(&osdc->client->monc);
        }
-       reset_changed_osds(osdc);
 }
 
 
@@ -2127,13 +2126,17 @@ static struct ceph_auth_handshake 
*get_authorizer(struct ceph_connection *con,
        struct ceph_auth_handshake *auth = &o->o_auth;
 
        if (force_new && auth->authorizer) {
-               if (ac->ops && ac->ops->destroy_authorizer)
-                       ac->ops->destroy_authorizer(ac, auth->authorizer);
+               ceph_auth_destroy_authorizer(ac, auth->authorizer);
                auth->authorizer = NULL;
        }
-       if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
-               int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD,
-                                                       auth);
+       if (!auth->authorizer) {
+               int ret = ceph_auth_create_authorizer(ac, CEPH_ENTITY_TYPE_OSD,
+                                                     auth);
+               if (ret)
+                       return ERR_PTR(ret);
+       } else {
+               int ret = ceph_auth_update_authorizer(ac, CEPH_ENTITY_TYPE_OSD,
+                                                    auth);
                if (ret)
                        return ERR_PTR(ret);
        }
@@ -2149,11 +2152,7 @@ static int verify_authorizer_reply(struct 
ceph_connection *con, int len)
        struct ceph_osd_client *osdc = o->o_osdc;
        struct ceph_auth_client *ac = osdc->client->monc.auth;
 
-       /*
-        * XXX If ac->ops or ac->ops->verify_authorizer_reply is null,
-        * XXX which do we do:  succeed or fail?
-        */
-       return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len);
+       return ceph_auth_verify_authorizer_reply(ac, o->o_auth.authorizer, len);
 }
 
 static int invalidate_authorizer(struct ceph_connection *con)
@@ -2162,9 +2161,7 @@ static int invalidate_authorizer(struct ceph_connection 
*con)
        struct ceph_osd_client *osdc = o->o_osdc;
        struct ceph_auth_client *ac = osdc->client->monc.auth;
 
-       if (ac->ops && ac->ops->invalidate_authorizer)
-               ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD);
-
+       ceph_auth_invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD);
        return ceph_monc_validate_auth(&osdc->client->monc);
 }
 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to