From: Greg Kroah-Hartman Date: Wed, 8 Aug 2012 15:53:08 +0000 (-0700) Subject: 3.5-stable patches X-Git-Tag: v3.5.1~2^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c709d549caf989bae0239937e2380404de0e0bc2;p=thirdparty%2Fkernel%2Fstable-queue.git 3.5-stable patches added patches: asus-wmi-use-asus_wmi_methodid_dsts2-as-default-dsts-id.patch lib-vsprintf.c-kptr_restrict-fix-pk-error-in-sysrq-show-all-timers-q.patch misdn-bugfix-only-few-bytes-are-transfered-on-a-connection.patch redefine-atomic_init-and-atomic64_init-to-drop-the-casts.patch selinux-fix-selinux_inode_setxattr-oops.patch sunrpc-clnt-add-missing-braces.patch sunrpc-return-negative-value-in-case-rpcbind-client-creation-error.patch virtio-blk-call-del_gendisk-before-disable-guest-kick.patch virtio-blk-reset-device-after-blk_cleanup_queue.patch virtio-blk-use-block-layer-provided-spinlock.patch --- diff --git a/queue-3.5/asus-wmi-use-asus_wmi_methodid_dsts2-as-default-dsts-id.patch b/queue-3.5/asus-wmi-use-asus_wmi_methodid_dsts2-as-default-dsts-id.patch new file mode 100644 index 00000000000..d4dac5d3ede --- /dev/null +++ b/queue-3.5/asus-wmi-use-asus_wmi_methodid_dsts2-as-default-dsts-id.patch @@ -0,0 +1,41 @@ +From 63a78bb1051b240417daad3a3fa9c1bb10646dca Mon Sep 17 00:00:00 2001 +From: Alex Hung +Date: Wed, 20 Jun 2012 11:47:35 +0800 +Subject: asus-wmi: use ASUS_WMI_METHODID_DSTS2 as default DSTS ID. + +From: Alex Hung + +commit 63a78bb1051b240417daad3a3fa9c1bb10646dca upstream. + +According to responses from the BIOS team, ASUS_WMI_METHODID_DSTS2 +(0x53545344) will be used as future DSTS ID. In addition, calling +asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL) returns +ASUS_WMI_UNSUPPORTED_METHOD in new ASUS laptop PCs. This patch fixes +no DSTS ID will be assigned in this case. + +Signed-off-by: Alex Hung +Signed-off-by: Matthew Garrett +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/asus-wmi.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -1467,14 +1467,9 @@ static int asus_wmi_platform_init(struct + */ + if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL)) + asus->dsts_id = ASUS_WMI_METHODID_DSTS; +- else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL)) ++ else + asus->dsts_id = ASUS_WMI_METHODID_DSTS2; + +- if (!asus->dsts_id) { +- pr_err("Can't find DSTS"); +- return -ENODEV; +- } +- + /* CWAP allow to define the behavior of the Fn+F2 key, + * this method doesn't seems to be present on Eee PCs */ + if (asus->driver->quirks->wapf >= 0) diff --git a/queue-3.5/lib-vsprintf.c-kptr_restrict-fix-pk-error-in-sysrq-show-all-timers-q.patch b/queue-3.5/lib-vsprintf.c-kptr_restrict-fix-pk-error-in-sysrq-show-all-timers-q.patch new file mode 100644 index 00000000000..3f1c1dbf8a0 --- /dev/null +++ b/queue-3.5/lib-vsprintf.c-kptr_restrict-fix-pk-error-in-sysrq-show-all-timers-q.patch @@ -0,0 +1,45 @@ +From 3715c5309f6d175c3053672b73fd4f73be16fd07 Mon Sep 17 00:00:00 2001 +From: Dan Rosenberg +Date: Mon, 30 Jul 2012 14:40:26 -0700 +Subject: lib/vsprintf.c: kptr_restrict: fix pK-error in SysRq show-all-timers(Q) + +From: Dan Rosenberg + +commit 3715c5309f6d175c3053672b73fd4f73be16fd07 upstream. + +When using ALT+SysRq+Q all the pointers are replaced with "pK-error" like +this: + + [23153.208033] .base: pK-error + +with echo h > /proc/sysrq-trigger it works: + + [23107.776363] .base: ffff88023e60d540 + +The intent behind this behavior was to return "pK-error" in cases where +the %pK format specifier was used in interrupt context, because the +CAP_SYSLOG check wouldn't be meaningful. Clearly this should only apply +when kptr_restrict is actually enabled though. + +Reported-by: Stevie Trujillo +Signed-off-by: Dan Rosenberg +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + lib/vsprintf.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/lib/vsprintf.c ++++ b/lib/vsprintf.c +@@ -1030,7 +1030,8 @@ char *pointer(const char *fmt, char *buf + * %pK cannot be used in IRQ context because its test + * for CAP_SYSLOG would be meaningless. + */ +- if (in_irq() || in_serving_softirq() || in_nmi()) { ++ if (kptr_restrict && (in_irq() || in_serving_softirq() || ++ in_nmi())) { + if (spec.field_width == -1) + spec.field_width = default_width; + return string(buf, end, "pK-error", spec); diff --git a/queue-3.5/misdn-bugfix-only-few-bytes-are-transfered-on-a-connection.patch b/queue-3.5/misdn-bugfix-only-few-bytes-are-transfered-on-a-connection.patch new file mode 100644 index 00000000000..afb90606fea --- /dev/null +++ b/queue-3.5/misdn-bugfix-only-few-bytes-are-transfered-on-a-connection.patch @@ -0,0 +1,50 @@ +From b41a9a66f67817f8acd85bd650e012a14da39faa Mon Sep 17 00:00:00 2001 +From: Karsten Keil +Date: Sun, 29 Jul 2012 07:15:13 +0000 +Subject: mISDN: Bugfix only few bytes are transfered on a connection + +From: Karsten Keil + +commit b41a9a66f67817f8acd85bd650e012a14da39faa upstream. + +The test for the fillempty condition was wrong in one place. +Changed the variable to the right boolean type. + +Signed-off-by: Karsten Keil +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/isdn/hardware/mISDN/avmfritz.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/isdn/hardware/mISDN/avmfritz.c ++++ b/drivers/isdn/hardware/mISDN/avmfritz.c +@@ -449,7 +449,8 @@ hdlc_fill_fifo(struct bchannel *bch) + { + struct fritzcard *fc = bch->hw; + struct hdlc_hw *hdlc; +- int count, fs, cnt = 0, idx, fillempty = 0; ++ int count, fs, cnt = 0, idx; ++ bool fillempty = false; + u8 *p; + u32 *ptr, val, addr; + +@@ -462,7 +463,7 @@ hdlc_fill_fifo(struct bchannel *bch) + return; + count = fs; + p = bch->fill; +- fillempty = 1; ++ fillempty = true; + } else { + count = bch->tx_skb->len - bch->tx_idx; + if (count <= 0) +@@ -477,7 +478,7 @@ hdlc_fill_fifo(struct bchannel *bch) + hdlc->ctrl.sr.cmd |= HDLC_CMD_XME; + } + ptr = (u32 *)p; +- if (fillempty) { ++ if (!fillempty) { + pr_debug("%s.B%d: %d/%d/%d", fc->name, bch->nr, count, + bch->tx_idx, bch->tx_skb->len); + bch->tx_idx += count; diff --git a/queue-3.5/redefine-atomic_init-and-atomic64_init-to-drop-the-casts.patch b/queue-3.5/redefine-atomic_init-and-atomic64_init-to-drop-the-casts.patch new file mode 100644 index 00000000000..84743599f9d --- /dev/null +++ b/queue-3.5/redefine-atomic_init-and-atomic64_init-to-drop-the-casts.patch @@ -0,0 +1,68 @@ +From a119365586b0130dfea06457f584953e0ff6481d Mon Sep 17 00:00:00 2001 +From: Tony Luck +Date: Thu, 26 Jul 2012 10:55:26 -0700 +Subject: [IA64] Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts + +From: Tony Luck + +commit a119365586b0130dfea06457f584953e0ff6481d upstream. + +The following build error occured during a ia64 build with +swap-over-NFS patches applied. + +net/core/sock.c:274:36: error: initializer element is not constant +net/core/sock.c:274:36: error: (near initialization for 'memalloc_socks') +net/core/sock.c:274:36: error: initializer element is not constant + +This is identical to a parisc build error. Fengguang Wu, Mel Gorman +and James Bottomley did all the legwork to track the root cause of +the problem. This fix and entire commit log is shamelessly copied +from them with one extra detail to change a dubious runtime use of +ATOMIC_INIT() to atomic_set() in drivers/char/mspec.c + +Dave Anglin says: +> Here is the line in sock.i: +> +> struct static_key memalloc_socks = ((struct static_key) { .enabled = +> ((atomic_t) { (0) }) }); + +The above line contains two compound literals. It also uses a designated +initializer to initialize the field enabled. A compound literal is not a +constant expression. + +The location of the above statement isn't fully clear, but if a compound +literal occurs outside the body of a function, the initializer list must +consist of constant expressions. + +Signed-off-by: Tony Luck +Signed-off-by: Greg Kroah-Hartman + +--- + arch/ia64/include/asm/atomic.h | 4 ++-- + drivers/char/mspec.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/ia64/include/asm/atomic.h ++++ b/arch/ia64/include/asm/atomic.h +@@ -17,8 +17,8 @@ + #include + + +-#define ATOMIC_INIT(i) ((atomic_t) { (i) }) +-#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) ++#define ATOMIC_INIT(i) { (i) } ++#define ATOMIC64_INIT(i) { (i) } + + #define atomic_read(v) (*(volatile int *)&(v)->counter) + #define atomic64_read(v) (*(volatile long *)&(v)->counter) +--- a/drivers/char/mspec.c ++++ b/drivers/char/mspec.c +@@ -283,7 +283,7 @@ mspec_mmap(struct file *file, struct vm_ + vdata->flags = flags; + vdata->type = type; + spin_lock_init(&vdata->lock); +- vdata->refcnt = ATOMIC_INIT(1); ++ atomic_set(&vdata->refcnt, 1); + vma->vm_private_data = vdata; + + vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND); diff --git a/queue-3.5/selinux-fix-selinux_inode_setxattr-oops.patch b/queue-3.5/selinux-fix-selinux_inode_setxattr-oops.patch new file mode 100644 index 00000000000..f5c5dc9066e --- /dev/null +++ b/queue-3.5/selinux-fix-selinux_inode_setxattr-oops.patch @@ -0,0 +1,65 @@ +From e3fea3f70fd68af0574a5f24246cdb4ed07f2b74 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sat, 9 Jun 2012 08:15:16 +0100 +Subject: selinux: fix selinux_inode_setxattr oops + +From: Al Viro + +commit e3fea3f70fd68af0574a5f24246cdb4ed07f2b74 upstream. + +OK, what we have so far is e.g. + setxattr(path, name, whatever, 0, XATTR_REPLACE) +with name being good enough to get through xattr_permission(). +Then we reach security_inode_setxattr() with the desired value and size. +Aha. name should begin with "security.selinux", or we won't get that +far in selinux_inode_setxattr(). Suppose we got there and have enough +permissions to relabel that sucker. We call security_context_to_sid() +with value == NULL, size == 0. OK, we want ss_initialized to be non-zero. +I.e. after everything had been set up and running. No problem... + +We do 1-byte kmalloc(), zero-length memcpy() (which doesn't oops, even +thought the source is NULL) and put a NUL there. I.e. form an empty +string. string_to_context_struct() is called and looks for the first +':' in there. Not found, -EINVAL we get. OK, security_context_to_sid_core() +has rc == -EINVAL, force == 0, so it silently returns -EINVAL. +All it takes now is not having CAP_MAC_ADMIN and we are fucked. + +All right, it might be a different bug (modulo strange code quoted in the +report), but it's real. Easily fixed, AFAICS: + +Deal with size == 0, value == NULL case in selinux_inode_setxattr() + +Signed-off-by: Al Viro +Tested-by: Dave Jones +Reported-by: Dave Jones +Signed-off-by: James Morris +Signed-off-by: Greg Kroah-Hartman + +--- + security/selinux/hooks.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -2792,11 +2792,16 @@ static int selinux_inode_setxattr(struct + + /* We strip a nul only if it is at the end, otherwise the + * context contains a nul and we should audit that */ +- str = value; +- if (str[size - 1] == '\0') +- audit_size = size - 1; +- else +- audit_size = size; ++ if (value) { ++ str = value; ++ if (str[size - 1] == '\0') ++ audit_size = size - 1; ++ else ++ audit_size = size; ++ } else { ++ str = ""; ++ audit_size = 0; ++ } + ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); + audit_log_format(ab, "op=setxattr invalid_context="); + audit_log_n_untrustedstring(ab, value, audit_size); diff --git a/queue-3.5/series b/queue-3.5/series new file mode 100644 index 00000000000..6993322c484 --- /dev/null +++ b/queue-3.5/series @@ -0,0 +1,10 @@ +virtio-blk-call-del_gendisk-before-disable-guest-kick.patch +virtio-blk-reset-device-after-blk_cleanup_queue.patch +virtio-blk-use-block-layer-provided-spinlock.patch +redefine-atomic_init-and-atomic64_init-to-drop-the-casts.patch +asus-wmi-use-asus_wmi_methodid_dsts2-as-default-dsts-id.patch +selinux-fix-selinux_inode_setxattr-oops.patch +lib-vsprintf.c-kptr_restrict-fix-pk-error-in-sysrq-show-all-timers-q.patch +sunrpc-clnt-add-missing-braces.patch +sunrpc-return-negative-value-in-case-rpcbind-client-creation-error.patch +misdn-bugfix-only-few-bytes-are-transfered-on-a-connection.patch diff --git a/queue-3.5/sunrpc-clnt-add-missing-braces.patch b/queue-3.5/sunrpc-clnt-add-missing-braces.patch new file mode 100644 index 00000000000..b05eadfe311 --- /dev/null +++ b/queue-3.5/sunrpc-clnt-add-missing-braces.patch @@ -0,0 +1,38 @@ +From cac5d07e3ca696dcacfb123553cf6c722111cfd3 Mon Sep 17 00:00:00 2001 +From: Joe Perches +Date: Wed, 18 Jul 2012 11:17:11 -0700 +Subject: sunrpc: clnt: Add missing braces + +From: Joe Perches + +commit cac5d07e3ca696dcacfb123553cf6c722111cfd3 upstream. + +Add a missing set of braces that commit 4e0038b6b24 +("SUNRPC: Move clnt->cl_server into struct rpc_xprt") +forgot. + +Signed-off-by: Joe Perches +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/clnt.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -1844,12 +1844,13 @@ call_timeout(struct rpc_task *task) + return; + } + if (RPC_IS_SOFT(task)) { +- if (clnt->cl_chatty) ++ if (clnt->cl_chatty) { + rcu_read_lock(); + printk(KERN_NOTICE "%s: server %s not responding, timed out\n", + clnt->cl_protname, + rcu_dereference(clnt->cl_xprt)->servername); + rcu_read_unlock(); ++ } + if (task->tk_flags & RPC_TASK_TIMEOUT) + rpc_exit(task, -ETIMEDOUT); + else diff --git a/queue-3.5/sunrpc-return-negative-value-in-case-rpcbind-client-creation-error.patch b/queue-3.5/sunrpc-return-negative-value-in-case-rpcbind-client-creation-error.patch new file mode 100644 index 00000000000..893b77bdd20 --- /dev/null +++ b/queue-3.5/sunrpc-return-negative-value-in-case-rpcbind-client-creation-error.patch @@ -0,0 +1,42 @@ +From caea33da898e4e14f0ba58173e3b7689981d2c0b Mon Sep 17 00:00:00 2001 +From: Stanislav Kinsbursky +Date: Fri, 20 Jul 2012 15:57:48 +0400 +Subject: SUNRPC: return negative value in case rpcbind client creation error + +From: Stanislav Kinsbursky + +commit caea33da898e4e14f0ba58173e3b7689981d2c0b upstream. + +Without this patch kernel will panic on LockD start, because lockd_up() checks +lockd_up_net() result for negative value. +From my pow it's better to return negative value from rpcbind routines instead +of replacing all such checks like in lockd_up(). + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/rpcb_clnt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/sunrpc/rpcb_clnt.c ++++ b/net/sunrpc/rpcb_clnt.c +@@ -251,7 +251,7 @@ static int rpcb_create_local_unix(struct + if (IS_ERR(clnt)) { + dprintk("RPC: failed to create AF_LOCAL rpcbind " + "client (errno %ld).\n", PTR_ERR(clnt)); +- result = -PTR_ERR(clnt); ++ result = PTR_ERR(clnt); + goto out; + } + +@@ -298,7 +298,7 @@ static int rpcb_create_local_net(struct + if (IS_ERR(clnt)) { + dprintk("RPC: failed to create local rpcbind " + "client (errno %ld).\n", PTR_ERR(clnt)); +- result = -PTR_ERR(clnt); ++ result = PTR_ERR(clnt); + goto out; + } + diff --git a/queue-3.5/virtio-blk-call-del_gendisk-before-disable-guest-kick.patch b/queue-3.5/virtio-blk-call-del_gendisk-before-disable-guest-kick.patch new file mode 100644 index 00000000000..ca7c34f7fe2 --- /dev/null +++ b/queue-3.5/virtio-blk-call-del_gendisk-before-disable-guest-kick.patch @@ -0,0 +1,65 @@ +From 02e2b124943648fba0a2ccee5c3656a5653e0151 Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Fri, 25 May 2012 10:34:47 +0800 +Subject: virtio-blk: Call del_gendisk() before disable guest kick + +From: Asias He + +commit 02e2b124943648fba0a2ccee5c3656a5653e0151 upstream. + +del_gendisk() might not return due to failing to remove the +/sys/block/vda/serial sysfs entry when another thread (udev) is +trying to read it. + +virtblk_remove() + vdev->config->reset() : guest will not kick us through interrupt + del_gendisk() + device_del() + kobject_del(): got stuck, sysfs entry ref count non zero + +sysfs_open_file(): user space process read /sys/block/vda/serial + sysfs_get_active() : got sysfs entry ref count + dev_attr_show() + virtblk_serial_show() + blk_execute_rq() : got stuck, interrupt is disabled + request cannot be finished + +This patch fixes it by calling del_gendisk() before we disable guest's +interrupt so that the request sent in virtblk_serial_show() will be +finished and del_gendisk() will success. + +This fixes another race in hot-unplug process. + +It is save to call del_gendisk(vblk->disk) before +flush_work(&vblk->config_work) which might access vblk->disk, because +vblk->disk is not freed until put_disk(vblk->disk). + +Signed-off-by: Asias He +Cc: virtualization@lists.linux-foundation.org +Cc: kvm@vger.kernel.org +Acked-by: Michael S. Tsirkin +Signed-off-by: Rusty Russell +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/virtio_blk.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -584,13 +584,13 @@ static void __devexit virtblk_remove(str + vblk->config_enable = false; + mutex_unlock(&vblk->config_lock); + ++ del_gendisk(vblk->disk); ++ + /* Stop all the virtqueues. */ + vdev->config->reset(vdev); + + flush_work(&vblk->config_work); + +- del_gendisk(vblk->disk); +- + /* Abort requests dispatched to driver. */ + spin_lock_irqsave(&vblk->lock, flags); + while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) { diff --git a/queue-3.5/virtio-blk-reset-device-after-blk_cleanup_queue.patch b/queue-3.5/virtio-blk-reset-device-after-blk_cleanup_queue.patch new file mode 100644 index 00000000000..b607b66b465 --- /dev/null +++ b/queue-3.5/virtio-blk-reset-device-after-blk_cleanup_queue.patch @@ -0,0 +1,85 @@ +From 483001c765af6892b3fc3726576cb42f17d1d6b5 Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Fri, 25 May 2012 10:34:48 +0800 +Subject: virtio-blk: Reset device after blk_cleanup_queue() + +From: Asias He + +commit 483001c765af6892b3fc3726576cb42f17d1d6b5 upstream. + +blk_cleanup_queue() will call blk_drian_queue() to drain all the +requests before queue DEAD marking. If we reset the device before +blk_cleanup_queue() the drain would fail. + +1) if the queue is stopped in do_virtblk_request() because device is +full, the q->request_fn() will not be called. + +blk_drain_queue() { + while(true) { + ... + if (!list_empty(&q->queue_head)) + __blk_run_queue(q) { + if (queue is not stoped) + q->request_fn() + } + ... + } +} + +Do no reset the device before blk_cleanup_queue() gives the chance to +start the queue in interrupt handler blk_done(). + +2) In commit b79d866c8b7014a51f611a64c40546109beaf24a, We abort requests +dispatched to driver before blk_cleanup_queue(). There is a race if +requests are dispatched to driver after the abort and before the queue +DEAD mark. To fix this, instead of aborting the requests explicitly, we +can just reset the device after after blk_cleanup_queue so that the +device can complete all the requests before queue DEAD marking in the +drain process. + +Signed-off-by: Asias He +Cc: Rusty Russell +Cc: virtualization@lists.linux-foundation.org +Cc: kvm@vger.kernel.org +Acked-by: Michael S. Tsirkin +Signed-off-by: Rusty Russell +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/virtio_blk.c | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -576,8 +576,6 @@ static void __devexit virtblk_remove(str + { + struct virtio_blk *vblk = vdev->priv; + int index = vblk->index; +- struct virtblk_req *vbr; +- unsigned long flags; + + /* Prevent config work handler from accessing the device. */ + mutex_lock(&vblk->config_lock); +@@ -585,21 +583,13 @@ static void __devexit virtblk_remove(str + mutex_unlock(&vblk->config_lock); + + del_gendisk(vblk->disk); ++ blk_cleanup_queue(vblk->disk->queue); + + /* Stop all the virtqueues. */ + vdev->config->reset(vdev); + + flush_work(&vblk->config_work); + +- /* Abort requests dispatched to driver. */ +- spin_lock_irqsave(&vblk->lock, flags); +- while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) { +- __blk_end_request_all(vbr->req, -EIO); +- mempool_free(vbr, vblk->pool); +- } +- spin_unlock_irqrestore(&vblk->lock, flags); +- +- blk_cleanup_queue(vblk->disk->queue); + put_disk(vblk->disk); + mempool_destroy(vblk->pool); + vdev->config->del_vqs(vdev); diff --git a/queue-3.5/virtio-blk-use-block-layer-provided-spinlock.patch b/queue-3.5/virtio-blk-use-block-layer-provided-spinlock.patch new file mode 100644 index 00000000000..199ce344483 --- /dev/null +++ b/queue-3.5/virtio-blk-use-block-layer-provided-spinlock.patch @@ -0,0 +1,100 @@ +From 2c95a3290919541b846bee3e0fbaa75860929f53 Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Fri, 25 May 2012 16:03:27 +0800 +Subject: virtio-blk: Use block layer provided spinlock + +From: Asias He + +commit 2c95a3290919541b846bee3e0fbaa75860929f53 upstream. + +Block layer will allocate a spinlock for the queue if the driver does +not provide one in blk_init_queue(). + +The reason to use the internal spinlock is that blk_cleanup_queue() will +switch to use the internal spinlock in the cleanup code path. + + if (q->queue_lock != &q->__queue_lock) + q->queue_lock = &q->__queue_lock; + +However, processes which are in D state might have taken the driver +provided spinlock, when the processes wake up, they would release the +block provided spinlock. + +===================================== +[ BUG: bad unlock balance detected! ] +3.4.0-rc7+ #238 Not tainted +------------------------------------- +fio/3587 is trying to release lock (&(&q->__queue_lock)->rlock) at: +[] blk_queue_bio+0x2a2/0x380 +but there are no more locks to release! + +other info that might help us debug this: +1 lock held by fio/3587: + #0: (&(&vblk->lock)->rlock){......}, at: +[] get_request_wait+0x19a/0x250 + +Other drivers use block layer provided spinlock as well, e.g. SCSI. + +Switching to the block layer provided spinlock saves a bit of memory and +does not increase lock contention. Performance test shows no real +difference is observed before and after this patch. + +Changes in v2: Improve commit log as Michael suggested. + +Signed-off-by: Asias He +Cc: virtualization@lists.linux-foundation.org +Cc: kvm@vger.kernel.org +Acked-by: Michael S. Tsirkin +Signed-off-by: Rusty Russell +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/virtio_blk.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -21,8 +21,6 @@ struct workqueue_struct *virtblk_wq; + + struct virtio_blk + { +- spinlock_t lock; +- + struct virtio_device *vdev; + struct virtqueue *vq; + +@@ -65,7 +63,7 @@ static void blk_done(struct virtqueue *v + unsigned int len; + unsigned long flags; + +- spin_lock_irqsave(&vblk->lock, flags); ++ spin_lock_irqsave(vblk->disk->queue->queue_lock, flags); + while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) { + int error; + +@@ -99,7 +97,7 @@ static void blk_done(struct virtqueue *v + } + /* In case queue is stopped waiting for more buffers. */ + blk_start_queue(vblk->disk->queue); +- spin_unlock_irqrestore(&vblk->lock, flags); ++ spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags); + } + + static bool do_req(struct request_queue *q, struct virtio_blk *vblk, +@@ -431,7 +429,6 @@ static int __devinit virtblk_probe(struc + goto out_free_index; + } + +- spin_lock_init(&vblk->lock); + vblk->vdev = vdev; + vblk->sg_elems = sg_elems; + sg_init_table(vblk->sg, vblk->sg_elems); +@@ -456,7 +453,7 @@ static int __devinit virtblk_probe(struc + goto out_mempool; + } + +- q = vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); ++ q = vblk->disk->queue = blk_init_queue(do_virtblk_request, NULL); + if (!q) { + err = -ENOMEM; + goto out_put_disk;