]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 4 Feb 2014 18:13:29 +0000 (10:13 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 4 Feb 2014 18:13:29 +0000 (10:13 -0800)
added patches:
hpfs-remember-free-space.patch
iscsi-target-pre-allocate-more-tags-to-avoid-ack-starvation.patch
scsi-bfa-chinook-quad-port-16g-fc-hba-claim-issue.patch
target-iscsi-fix-network-portal-creation-race.patch
usb-core-get-config-and-string-descriptors-for-unauthorized-devices.patch
virtio-scsi-fix-hotcpu_notifier-use-after-free-with-virtscsi_freeze.patch

queue-3.12/hpfs-remember-free-space.patch [new file with mode: 0644]
queue-3.12/iscsi-target-pre-allocate-more-tags-to-avoid-ack-starvation.patch [new file with mode: 0644]
queue-3.12/scsi-bfa-chinook-quad-port-16g-fc-hba-claim-issue.patch [new file with mode: 0644]
queue-3.12/series
queue-3.12/target-iscsi-fix-network-portal-creation-race.patch [new file with mode: 0644]
queue-3.12/usb-core-get-config-and-string-descriptors-for-unauthorized-devices.patch [new file with mode: 0644]
queue-3.12/virtio-scsi-fix-hotcpu_notifier-use-after-free-with-virtscsi_freeze.patch [new file with mode: 0644]

diff --git a/queue-3.12/hpfs-remember-free-space.patch b/queue-3.12/hpfs-remember-free-space.patch
new file mode 100644 (file)
index 0000000..9ebb444
--- /dev/null
@@ -0,0 +1,232 @@
+From 2cbe5c76fc5e38e9af4b709593146e4b8272b69e Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
+Date: Wed, 29 Jan 2014 00:10:44 +0100
+Subject: hpfs: remember free space
+
+From: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
+
+commit 2cbe5c76fc5e38e9af4b709593146e4b8272b69e upstream.
+
+Previously, hpfs scanned all bitmaps each time the user asked for free
+space using statfs.  This patch changes it so that hpfs scans the
+bitmaps only once, remembes the free space and on next invocation of
+statfs it returns the value instantly.
+
+New versions of wine are hammering on the statfs syscall very heavily,
+making some games unplayable when they're stored on hpfs, with load
+times in minutes.
+
+This should be backported to the stable kernels because it fixes
+user-visible problem (excessive level load times in wine).
+
+Signed-off-by: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/hpfs/alloc.c   |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
+ fs/hpfs/hpfs_fn.h |    2 -
+ fs/hpfs/super.c   |   29 ++++++++++++++++++-----
+ 3 files changed, 87 insertions(+), 10 deletions(-)
+
+--- a/fs/hpfs/alloc.c
++++ b/fs/hpfs/alloc.c
+@@ -8,6 +8,58 @@
+ #include "hpfs_fn.h"
++static void hpfs_claim_alloc(struct super_block *s, secno sec)
++{
++      struct hpfs_sb_info *sbi = hpfs_sb(s);
++      if (sbi->sb_n_free != (unsigned)-1) {
++              if (unlikely(!sbi->sb_n_free)) {
++                      hpfs_error(s, "free count underflow, allocating sector %08x", sec);
++                      sbi->sb_n_free = -1;
++                      return;
++              }
++              sbi->sb_n_free--;
++      }
++}
++
++static void hpfs_claim_free(struct super_block *s, secno sec)
++{
++      struct hpfs_sb_info *sbi = hpfs_sb(s);
++      if (sbi->sb_n_free != (unsigned)-1) {
++              if (unlikely(sbi->sb_n_free >= sbi->sb_fs_size)) {
++                      hpfs_error(s, "free count overflow, freeing sector %08x", sec);
++                      sbi->sb_n_free = -1;
++                      return;
++              }
++              sbi->sb_n_free++;
++      }
++}
++
++static void hpfs_claim_dirband_alloc(struct super_block *s, secno sec)
++{
++      struct hpfs_sb_info *sbi = hpfs_sb(s);
++      if (sbi->sb_n_free_dnodes != (unsigned)-1) {
++              if (unlikely(!sbi->sb_n_free_dnodes)) {
++                      hpfs_error(s, "dirband free count underflow, allocating sector %08x", sec);
++                      sbi->sb_n_free_dnodes = -1;
++                      return;
++              }
++              sbi->sb_n_free_dnodes--;
++      }
++}
++
++static void hpfs_claim_dirband_free(struct super_block *s, secno sec)
++{
++      struct hpfs_sb_info *sbi = hpfs_sb(s);
++      if (sbi->sb_n_free_dnodes != (unsigned)-1) {
++              if (unlikely(sbi->sb_n_free_dnodes >= sbi->sb_dirband_size / 4)) {
++                      hpfs_error(s, "dirband free count overflow, freeing sector %08x", sec);
++                      sbi->sb_n_free_dnodes = -1;
++                      return;
++              }
++              sbi->sb_n_free_dnodes++;
++      }
++}
++
+ /*
+  * Check if a sector is allocated in bitmap
+  * This is really slow. Turned on only if chk==2
+@@ -203,9 +255,15 @@ secno hpfs_alloc_sector(struct super_blo
+       }
+       sec = 0;
+       ret:
++      if (sec) {
++              i = 0;
++              do
++                      hpfs_claim_alloc(s, sec + i);
++              while (unlikely(++i < n));
++      }
+       if (sec && f_p) {
+               for (i = 0; i < forward; i++) {
+-                      if (!hpfs_alloc_if_possible(s, sec + i + 1)) {
++                      if (!hpfs_alloc_if_possible(s, sec + n + i)) {
+                               hpfs_error(s, "Prealloc doesn't work! Wanted %d, allocated at %08x, can't allocate %d", forward, sec, i);
+                               sec = 0;
+                               break;
+@@ -228,6 +286,7 @@ static secno alloc_in_dirband(struct sup
+       nr >>= 2;
+       sec = alloc_in_bmp(s, (~0x3fff) | nr, 1, 0);
+       if (!sec) return 0;
++      hpfs_claim_dirband_alloc(s, sec);
+       return ((sec & 0x3fff) << 2) + sbi->sb_dirband_start;
+ }
+@@ -242,6 +301,7 @@ int hpfs_alloc_if_possible(struct super_
+               bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f)));
+               hpfs_mark_4buffers_dirty(&qbh);
+               hpfs_brelse4(&qbh);
++              hpfs_claim_alloc(s, sec);
+               return 1;
+       }
+       hpfs_brelse4(&qbh);
+@@ -275,6 +335,7 @@ void hpfs_free_sectors(struct super_bloc
+               return;
+       }
+       bmp[(sec & 0x3fff) >> 5] |= cpu_to_le32(1 << (sec & 0x1f));
++      hpfs_claim_free(s, sec);
+       if (!--n) {
+               hpfs_mark_4buffers_dirty(&qbh);
+               hpfs_brelse4(&qbh);
+@@ -359,6 +420,7 @@ void hpfs_free_dnode(struct super_block
+               bmp[ssec >> 5] |= cpu_to_le32(1 << (ssec & 0x1f));
+               hpfs_mark_4buffers_dirty(&qbh);
+               hpfs_brelse4(&qbh);
++              hpfs_claim_dirband_free(s, dno);
+       }
+ }
+@@ -366,7 +428,7 @@ struct dnode *hpfs_alloc_dnode(struct su
+                        dnode_secno *dno, struct quad_buffer_head *qbh)
+ {
+       struct dnode *d;
+-      if (hpfs_count_one_bitmap(s, hpfs_sb(s)->sb_dmap) > FREE_DNODES_ADD) {
++      if (hpfs_get_free_dnodes(s) > FREE_DNODES_ADD) {
+               if (!(*dno = alloc_in_dirband(s, near)))
+                       if (!(*dno = hpfs_alloc_sector(s, near, 4, 0))) return NULL;
+       } else {
+--- a/fs/hpfs/hpfs_fn.h
++++ b/fs/hpfs/hpfs_fn.h
+@@ -311,7 +311,7 @@ static inline struct hpfs_sb_info *hpfs_
+ __printf(2, 3)
+ void hpfs_error(struct super_block *, const char *, ...);
+ int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *);
+-unsigned hpfs_count_one_bitmap(struct super_block *, secno);
++unsigned hpfs_get_free_dnodes(struct super_block *);
+ /*
+  * local time (HPFS) to GMT (Unix)
+--- a/fs/hpfs/super.c
++++ b/fs/hpfs/super.c
+@@ -115,7 +115,7 @@ static void hpfs_put_super(struct super_
+       kfree(sbi);
+ }
+-unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
++static unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
+ {
+       struct quad_buffer_head qbh;
+       unsigned long *bits;
+@@ -123,7 +123,7 @@ unsigned hpfs_count_one_bitmap(struct su
+       bits = hpfs_map_4sectors(s, secno, &qbh, 0);
+       if (!bits)
+-              return 0;
++              return (unsigned)-1;
+       count = bitmap_weight(bits, 2048 * BITS_PER_BYTE);
+       hpfs_brelse4(&qbh);
+       return count;
+@@ -138,30 +138,45 @@ static unsigned count_bitmaps(struct sup
+               hpfs_prefetch_bitmap(s, n);
+       }
+       for (n = 0; n < n_bands; n++) {
++              unsigned c;
+               hpfs_prefetch_bitmap(s, n + COUNT_RD_AHEAD);
+-              count += hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
++              c = hpfs_count_one_bitmap(s, le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[n]));
++              if (c != (unsigned)-1)
++                      count += c;
+       }
+       return count;
+ }
++unsigned hpfs_get_free_dnodes(struct super_block *s)
++{
++      struct hpfs_sb_info *sbi = hpfs_sb(s);
++      if (sbi->sb_n_free_dnodes == (unsigned)-1) {
++              unsigned c = hpfs_count_one_bitmap(s, sbi->sb_dmap);
++              if (c == (unsigned)-1)
++                      return 0;
++              sbi->sb_n_free_dnodes = c;
++      }
++      return sbi->sb_n_free_dnodes;
++}
++
+ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+ {
+       struct super_block *s = dentry->d_sb;
+       struct hpfs_sb_info *sbi = hpfs_sb(s);
+       u64 id = huge_encode_dev(s->s_bdev->bd_dev);
++
+       hpfs_lock(s);
+-      /*if (sbi->sb_n_free == -1) {*/
++      if (sbi->sb_n_free == (unsigned)-1)
+               sbi->sb_n_free = count_bitmaps(s);
+-              sbi->sb_n_free_dnodes = hpfs_count_one_bitmap(s, sbi->sb_dmap);
+-      /*}*/
++
+       buf->f_type = s->s_magic;
+       buf->f_bsize = 512;
+       buf->f_blocks = sbi->sb_fs_size;
+       buf->f_bfree = sbi->sb_n_free;
+       buf->f_bavail = sbi->sb_n_free;
+       buf->f_files = sbi->sb_dirband_size / 4;
+-      buf->f_ffree = sbi->sb_n_free_dnodes;
++      buf->f_ffree = hpfs_get_free_dnodes(s);
+       buf->f_fsid.val[0] = (u32)id;
+       buf->f_fsid.val[1] = (u32)(id >> 32);
+       buf->f_namelen = 254;
diff --git a/queue-3.12/iscsi-target-pre-allocate-more-tags-to-avoid-ack-starvation.patch b/queue-3.12/iscsi-target-pre-allocate-more-tags-to-avoid-ack-starvation.patch
new file mode 100644 (file)
index 0000000..4c1f4c7
--- /dev/null
@@ -0,0 +1,44 @@
+From 4a4caa29f1abcb14377e05d57c0793d338fb945d Mon Sep 17 00:00:00 2001
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+Date: Fri, 10 Jan 2014 02:06:59 +0000
+Subject: iscsi-target: Pre-allocate more tags to avoid ack starvation
+
+From: Nicholas Bellinger <nab@linux-iscsi.org>
+
+commit 4a4caa29f1abcb14377e05d57c0793d338fb945d upstream.
+
+This patch addresses an traditional iscsi-target fabric ack starvation
+issue where iscsit_allocate_cmd() -> percpu_ida_alloc_state() ends up
+hitting slow path percpu-ida code, because iscsit_ack_from_expstatsn()
+is expected to free ack'ed tags after tag allocation.
+
+This is done to take into account the tags waiting to be acknowledged
+and released in iscsit_ack_from_expstatsn(), but who's number are not
+directly limited by the CmdSN Window queue_depth being enforced by
+the target.
+
+So that said, this patch bumps up the pre-allocated number of
+per session tags to:
+
+  (max(queue_depth, ISCSIT_MIN_TAGS) * 2) + ISCSIT_EXTRA_TAGS
+
+for good measure to avoid the percpu_ida_alloc_state() slow path.
+
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/iscsi/iscsi_target_nego.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/target/iscsi/iscsi_target_nego.c
++++ b/drivers/target/iscsi/iscsi_target_nego.c
+@@ -1192,7 +1192,7 @@ get_target:
+        */
+ alloc_tags:
+       tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth);
+-      tag_num += (tag_num / 2) + ISCSIT_EXTRA_TAGS;
++      tag_num = (tag_num * 2) + ISCSIT_EXTRA_TAGS;
+       tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;
+       ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size);
diff --git a/queue-3.12/scsi-bfa-chinook-quad-port-16g-fc-hba-claim-issue.patch b/queue-3.12/scsi-bfa-chinook-quad-port-16g-fc-hba-claim-issue.patch
new file mode 100644 (file)
index 0000000..02a6980
--- /dev/null
@@ -0,0 +1,54 @@
+From dcaf9aed995c2b2a49fb86bbbcfa2f92c797ab5d Mon Sep 17 00:00:00 2001
+From: Vijaya Mohan Guvva <vmohan@brocade.com>
+Date: Wed, 4 Dec 2013 05:43:58 -0800
+Subject: SCSI: bfa: Chinook quad port 16G FC HBA claim issue
+
+From: Vijaya Mohan Guvva <vmohan@brocade.com>
+
+commit dcaf9aed995c2b2a49fb86bbbcfa2f92c797ab5d upstream.
+
+Bfa driver crash is observed while pushing the firmware on to chinook
+quad port card due to uninitialized bfi_image_ct2 access which gets
+initialized only for CT2 ASIC based cards after request_firmware().
+For quard port chinook (CT2 ASIC based), bfi_image_ct2 is not getting
+initialized as there is no check for chinook PCI device ID before
+request_firmware and instead bfi_image_cb is initialized as it is the
+default case for card type check.
+
+This patch includes changes to read the right firmware for quad port chinook.
+
+Signed-off-by: Vijaya Mohan Guvva <vmohan@brocade.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/bfa/bfad.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/bfa/bfad.c
++++ b/drivers/scsi/bfa/bfad.c
+@@ -1832,7 +1832,7 @@ out:
+ static u32 *
+ bfad_load_fwimg(struct pci_dev *pdev)
+ {
+-      if (pdev->device == BFA_PCI_DEVICE_ID_CT2) {
++      if (bfa_asic_id_ct2(pdev->device)) {
+               if (bfi_image_ct2_size == 0)
+                       bfad_read_firmware(pdev, &bfi_image_ct2,
+                               &bfi_image_ct2_size, BFAD_FW_FILE_CT2);
+@@ -1842,12 +1842,14 @@ bfad_load_fwimg(struct pci_dev *pdev)
+                       bfad_read_firmware(pdev, &bfi_image_ct,
+                               &bfi_image_ct_size, BFAD_FW_FILE_CT);
+               return bfi_image_ct;
+-      } else {
++      } else if (bfa_asic_id_cb(pdev->device)) {
+               if (bfi_image_cb_size == 0)
+                       bfad_read_firmware(pdev, &bfi_image_cb,
+                               &bfi_image_cb_size, BFAD_FW_FILE_CB);
+               return bfi_image_cb;
+       }
++
++      return NULL;
+ }
+ static void
index 67bbeaf7734be4f9630d97461ed21593393d138c..25d47c660cc3639f28e5323a68d1ef15bd7285ac 100644 (file)
@@ -121,3 +121,9 @@ kvm-ppc-e500-fix-bad-address-type-in-deliver_tlb_misss.patch
 alsa-hda-don-t-set-indep_hp-flag-for-old-ad-codecs.patch
 alsa-hda-hdmi-introduce-patch_nvhdmi.patch
 alsa-hda-hdmi-allow-pin_out-to-be-dynamically-enabled.patch
+hpfs-remember-free-space.patch
+usb-core-get-config-and-string-descriptors-for-unauthorized-devices.patch
+scsi-bfa-chinook-quad-port-16g-fc-hba-claim-issue.patch
+virtio-scsi-fix-hotcpu_notifier-use-after-free-with-virtscsi_freeze.patch
+iscsi-target-pre-allocate-more-tags-to-avoid-ack-starvation.patch
+target-iscsi-fix-network-portal-creation-race.patch
diff --git a/queue-3.12/target-iscsi-fix-network-portal-creation-race.patch b/queue-3.12/target-iscsi-fix-network-portal-creation-race.patch
new file mode 100644 (file)
index 0000000..048e9ea
--- /dev/null
@@ -0,0 +1,150 @@
+From ee291e63293146db64668e8d65eb35c97e8324f4 Mon Sep 17 00:00:00 2001
+From: Andy Grover <agrover@redhat.com>
+Date: Fri, 24 Jan 2014 16:18:54 -0800
+Subject: target/iscsi: Fix network portal creation race
+
+From: Andy Grover <agrover@redhat.com>
+
+commit ee291e63293146db64668e8d65eb35c97e8324f4 upstream.
+
+When creating network portals rapidly, such as when restoring a
+configuration, LIO's code to reuse existing portals can return a false
+negative if the thread hasn't run yet and set np_thread_state to
+ISCSI_NP_THREAD_ACTIVE. This causes an error in the network stack
+when attempting to bind to the same address/port.
+
+This patch sets NP_THREAD_ACTIVE before the np is placed on g_np_list,
+so even if the thread hasn't run yet, iscsit_get_np will return the
+existing np.
+
+Also, convert np_lock -> np_mutex + hold across adding new net portal
+to g_np_list to prevent a race where two threads may attempt to create
+the same network portal, resulting in one of them failing.
+
+(nab: Add missing mutex_unlocks in iscsit_add_np failure paths)
+(DanC: Fix incorrect spin_unlock -> spin_unlock_bh)
+
+Signed-off-by: Andy Grover <agrover@redhat.com>
+Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/target/iscsi/iscsi_target.c |   34 +++++++++++++++++++++-------------
+ 1 file changed, 21 insertions(+), 13 deletions(-)
+
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -52,7 +52,7 @@
+ static LIST_HEAD(g_tiqn_list);
+ static LIST_HEAD(g_np_list);
+ static DEFINE_SPINLOCK(tiqn_lock);
+-static DEFINE_SPINLOCK(np_lock);
++static DEFINE_MUTEX(np_lock);
+ static struct idr tiqn_idr;
+ struct idr sess_idr;
+@@ -307,6 +307,9 @@ bool iscsit_check_np_match(
+       return false;
+ }
++/*
++ * Called with mutex np_lock held
++ */
+ static struct iscsi_np *iscsit_get_np(
+       struct __kernel_sockaddr_storage *sockaddr,
+       int network_transport)
+@@ -314,11 +317,10 @@ static struct iscsi_np *iscsit_get_np(
+       struct iscsi_np *np;
+       bool match;
+-      spin_lock_bh(&np_lock);
+       list_for_each_entry(np, &g_np_list, np_list) {
+-              spin_lock(&np->np_thread_lock);
++              spin_lock_bh(&np->np_thread_lock);
+               if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
+-                      spin_unlock(&np->np_thread_lock);
++                      spin_unlock_bh(&np->np_thread_lock);
+                       continue;
+               }
+@@ -330,13 +332,11 @@ static struct iscsi_np *iscsit_get_np(
+                        * while iscsi_tpg_add_network_portal() is called.
+                        */
+                       np->np_exports++;
+-                      spin_unlock(&np->np_thread_lock);
+-                      spin_unlock_bh(&np_lock);
++                      spin_unlock_bh(&np->np_thread_lock);
+                       return np;
+               }
+-              spin_unlock(&np->np_thread_lock);
++              spin_unlock_bh(&np->np_thread_lock);
+       }
+-      spin_unlock_bh(&np_lock);
+       return NULL;
+ }
+@@ -350,16 +350,22 @@ struct iscsi_np *iscsit_add_np(
+       struct sockaddr_in6 *sock_in6;
+       struct iscsi_np *np;
+       int ret;
++
++      mutex_lock(&np_lock);
++
+       /*
+        * Locate the existing struct iscsi_np if already active..
+        */
+       np = iscsit_get_np(sockaddr, network_transport);
+-      if (np)
++      if (np) {
++              mutex_unlock(&np_lock);
+               return np;
++      }
+       np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL);
+       if (!np) {
+               pr_err("Unable to allocate memory for struct iscsi_np\n");
++              mutex_unlock(&np_lock);
+               return ERR_PTR(-ENOMEM);
+       }
+@@ -382,6 +388,7 @@ struct iscsi_np *iscsit_add_np(
+       ret = iscsi_target_setup_login_socket(np, sockaddr);
+       if (ret != 0) {
+               kfree(np);
++              mutex_unlock(&np_lock);
+               return ERR_PTR(ret);
+       }
+@@ -390,6 +397,7 @@ struct iscsi_np *iscsit_add_np(
+               pr_err("Unable to create kthread: iscsi_np\n");
+               ret = PTR_ERR(np->np_thread);
+               kfree(np);
++              mutex_unlock(&np_lock);
+               return ERR_PTR(ret);
+       }
+       /*
+@@ -400,10 +408,10 @@ struct iscsi_np *iscsit_add_np(
+        * point because iscsi_np has not been added to g_np_list yet.
+        */
+       np->np_exports = 1;
++      np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
+-      spin_lock_bh(&np_lock);
+       list_add_tail(&np->np_list, &g_np_list);
+-      spin_unlock_bh(&np_lock);
++      mutex_unlock(&np_lock);
+       pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n",
+               np->np_ip, np->np_port, np->np_transport->name);
+@@ -470,9 +478,9 @@ int iscsit_del_np(struct iscsi_np *np)
+       np->np_transport->iscsit_free_np(np);
+-      spin_lock_bh(&np_lock);
++      mutex_lock(&np_lock);
+       list_del(&np->np_list);
+-      spin_unlock_bh(&np_lock);
++      mutex_unlock(&np_lock);
+       pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n",
+               np->np_ip, np->np_port, np->np_transport->name);
diff --git a/queue-3.12/usb-core-get-config-and-string-descriptors-for-unauthorized-devices.patch b/queue-3.12/usb-core-get-config-and-string-descriptors-for-unauthorized-devices.patch
new file mode 100644 (file)
index 0000000..2d82ba5
--- /dev/null
@@ -0,0 +1,127 @@
+From 83e83ecb79a8225e79bc8e54e9aff3e0e27658a2 Mon Sep 17 00:00:00 2001
+From: Thomas Pugliese <thomas.pugliese@gmail.com>
+Date: Mon, 9 Dec 2013 13:40:29 -0600
+Subject: usb: core: get config and string descriptors for unauthorized devices
+
+From: Thomas Pugliese <thomas.pugliese@gmail.com>
+
+commit 83e83ecb79a8225e79bc8e54e9aff3e0e27658a2 upstream.
+
+There is no need to skip querying the config and string descriptors for
+unauthorized WUSB devices when usb_new_device is called.  It is allowed
+by WUSB spec.  The only action that needs to be delayed until
+authorization time is the set config.  This change allows user mode
+tools to see the config and string descriptors earlier in enumeration
+which is needed for some WUSB devices to function properly on Android
+systems.  It also reduces the amount of divergent code paths needed
+for WUSB devices.
+
+Signed-off-by: Thomas Pugliese <thomas.pugliese@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/config.c |    7 -------
+ drivers/usb/core/hub.c    |   40 +++++++---------------------------------
+ 2 files changed, 7 insertions(+), 40 deletions(-)
+
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -651,10 +651,6 @@ void usb_destroy_configuration(struct us
+  *
+  * hub-only!! ... and only in reset path, or usb_new_device()
+  * (used by real hubs and virtual root hubs)
+- *
+- * NOTE: if this is a WUSB device and is not authorized, we skip the
+- *       whole thing. A non-authorized USB device has no
+- *       configurations.
+  */
+ int usb_get_configuration(struct usb_device *dev)
+ {
+@@ -666,8 +662,6 @@ int usb_get_configuration(struct usb_dev
+       struct usb_config_descriptor *desc;
+       cfgno = 0;
+-      if (dev->authorized == 0)       /* Not really an error */
+-              goto out_not_authorized;
+       result = -ENOMEM;
+       if (ncfg > USB_MAXCONFIG) {
+               dev_warn(ddev, "too many configurations: %d, "
+@@ -751,7 +745,6 @@ int usb_get_configuration(struct usb_dev
+ err:
+       kfree(desc);
+-out_not_authorized:
+       dev->descriptor.bNumConfigurations = cfgno;
+ err2:
+       if (result == -ENOMEM)
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2242,18 +2242,13 @@ static int usb_enumerate_device(struct u
+                       return err;
+               }
+       }
+-      if (udev->wusb == 1 && udev->authorized == 0) {
+-              udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+-              udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+-              udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+-      }
+-      else {
+-              /* read the standard strings and cache them if present */
+-              udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
+-              udev->manufacturer = usb_cache_string(udev,
+-                                                    udev->descriptor.iManufacturer);
+-              udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
+-      }
++
++      /* read the standard strings and cache them if present */
++      udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
++      udev->manufacturer = usb_cache_string(udev,
++                                            udev->descriptor.iManufacturer);
++      udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber);
++
+       err = usb_enumerate_device_otg(udev);
+       if (err < 0)
+               return err;
+@@ -2435,16 +2430,6 @@ int usb_deauthorize_device(struct usb_de
+       usb_dev->authorized = 0;
+       usb_set_configuration(usb_dev, -1);
+-      kfree(usb_dev->product);
+-      usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+-      kfree(usb_dev->manufacturer);
+-      usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+-      kfree(usb_dev->serial);
+-      usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
+-
+-      usb_destroy_configuration(usb_dev);
+-      usb_dev->descriptor.bNumConfigurations = 0;
+-
+ out_unauthorized:
+       usb_unlock_device(usb_dev);
+       return 0;
+@@ -2472,17 +2457,7 @@ int usb_authorize_device(struct usb_devi
+               goto error_device_descriptor;
+       }
+-      kfree(usb_dev->product);
+-      usb_dev->product = NULL;
+-      kfree(usb_dev->manufacturer);
+-      usb_dev->manufacturer = NULL;
+-      kfree(usb_dev->serial);
+-      usb_dev->serial = NULL;
+-
+       usb_dev->authorized = 1;
+-      result = usb_enumerate_device(usb_dev);
+-      if (result < 0)
+-              goto error_enumerate;
+       /* Choose and set the configuration.  This registers the interfaces
+        * with the driver core and lets interface drivers bind to them.
+        */
+@@ -2498,7 +2473,6 @@ int usb_authorize_device(struct usb_devi
+       }
+       dev_info(&usb_dev->dev, "authorized to connect\n");
+-error_enumerate:
+ error_device_descriptor:
+       usb_autosuspend_device(usb_dev);
+ error_autoresume:
diff --git a/queue-3.12/virtio-scsi-fix-hotcpu_notifier-use-after-free-with-virtscsi_freeze.patch b/queue-3.12/virtio-scsi-fix-hotcpu_notifier-use-after-free-with-virtscsi_freeze.patch
new file mode 100644 (file)
index 0000000..663871b
--- /dev/null
@@ -0,0 +1,58 @@
+From f466f75385369a181409e46da272db3de6f5c5cb Mon Sep 17 00:00:00 2001
+From: Asias He <asias.hejun@gmail.com>
+Date: Thu, 16 Jan 2014 10:18:48 +1030
+Subject: virtio-scsi: Fix hotcpu_notifier use-after-free with virtscsi_freeze
+
+From: Asias He <asias.hejun@gmail.com>
+
+commit f466f75385369a181409e46da272db3de6f5c5cb upstream.
+
+vqs are freed in virtscsi_freeze but the hotcpu_notifier is not
+unregistered. We will have a use-after-free usage when the notifier
+callback is called after virtscsi_freeze.
+
+Fixes: 285e71ea6f3583a85e27cb2b9a7d8c35d4c0d558
+("virtio-scsi: reset virtqueue affinity when doing cpu hotplug")
+
+Signed-off-by: Asias He <asias.hejun@gmail.com>
+Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/virtio_scsi.c |   15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/virtio_scsi.c
++++ b/drivers/scsi/virtio_scsi.c
+@@ -957,6 +957,10 @@ static void virtscsi_remove(struct virti
+ #ifdef CONFIG_PM
+ static int virtscsi_freeze(struct virtio_device *vdev)
+ {
++      struct Scsi_Host *sh = virtio_scsi_host(vdev);
++      struct virtio_scsi *vscsi = shost_priv(sh);
++
++      unregister_hotcpu_notifier(&vscsi->nb);
+       virtscsi_remove_vqs(vdev);
+       return 0;
+ }
+@@ -965,8 +969,17 @@ static int virtscsi_restore(struct virti
+ {
+       struct Scsi_Host *sh = virtio_scsi_host(vdev);
+       struct virtio_scsi *vscsi = shost_priv(sh);
++      int err;
++
++      err = virtscsi_init(vdev, vscsi);
++      if (err)
++              return err;
++
++      err = register_hotcpu_notifier(&vscsi->nb);
++      if (err)
++              vdev->config->del_vqs(vdev);
+-      return virtscsi_init(vdev, vscsi);
++      return err;
+ }
+ #endif