]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Oct 2012 18:21:37 +0000 (11:21 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Oct 2012 18:21:37 +0000 (11:21 -0700)
added patches:
blkcg-fix-use-after-free-of-q-root_blkg-and-q-root_rl.blkg.patch
ceph-avoid-32-bit-page-index-overflow.patch
ceph-fix-dentry-reference-leak-in-encode_fh.patch
ceph-fix-oops-when-handling-mdsmap-that-decreases-max_mds.patch
ext4-fix-unjournaled-inode-bitmap-modification.patch
floppy-don-t-call-alloc_ordered_workqueue-inside-the-alloc_disk-loop.patch
floppy-do-put_disk-on-current-dr-if-blk_init_queue-fails.patch
floppy-properly-handle-failure-on-add_disk-loop.patch
gpiolib-don-t-return-eprobe_defer-to-sysfs-or-for-invalid-gpios.patch
gpio-timberdale-fix-a-potential-wrapping-issue.patch
libceph-avoid-null-kref_put-when-osd-reset-races-with-alloc_msg.patch
libceph-check-for-invalid-mapping.patch
md-raid1-fix-assembling-of-arrays-containing-replacements.patch
rbd-reset-backoff-if-unable-to-re-queue.patch

15 files changed:
queue-3.6/blkcg-fix-use-after-free-of-q-root_blkg-and-q-root_rl.blkg.patch [new file with mode: 0644]
queue-3.6/ceph-avoid-32-bit-page-index-overflow.patch [new file with mode: 0644]
queue-3.6/ceph-fix-dentry-reference-leak-in-encode_fh.patch [new file with mode: 0644]
queue-3.6/ceph-fix-oops-when-handling-mdsmap-that-decreases-max_mds.patch [new file with mode: 0644]
queue-3.6/ext4-fix-unjournaled-inode-bitmap-modification.patch [new file with mode: 0644]
queue-3.6/floppy-do-put_disk-on-current-dr-if-blk_init_queue-fails.patch [new file with mode: 0644]
queue-3.6/floppy-don-t-call-alloc_ordered_workqueue-inside-the-alloc_disk-loop.patch [new file with mode: 0644]
queue-3.6/floppy-properly-handle-failure-on-add_disk-loop.patch [new file with mode: 0644]
queue-3.6/gpio-timberdale-fix-a-potential-wrapping-issue.patch [new file with mode: 0644]
queue-3.6/gpiolib-don-t-return-eprobe_defer-to-sysfs-or-for-invalid-gpios.patch [new file with mode: 0644]
queue-3.6/libceph-avoid-null-kref_put-when-osd-reset-races-with-alloc_msg.patch [new file with mode: 0644]
queue-3.6/libceph-check-for-invalid-mapping.patch [new file with mode: 0644]
queue-3.6/md-raid1-fix-assembling-of-arrays-containing-replacements.patch [new file with mode: 0644]
queue-3.6/rbd-reset-backoff-if-unable-to-re-queue.patch [new file with mode: 0644]
queue-3.6/series [new file with mode: 0644]

diff --git a/queue-3.6/blkcg-fix-use-after-free-of-q-root_blkg-and-q-root_rl.blkg.patch b/queue-3.6/blkcg-fix-use-after-free-of-q-root_blkg-and-q-root_rl.blkg.patch
new file mode 100644 (file)
index 0000000..9582a12
--- /dev/null
@@ -0,0 +1,86 @@
+From 65635cbc37e011e71b208257a25e7c1078cd039b Mon Sep 17 00:00:00 2001
+From: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
+Date: Wed, 17 Oct 2012 17:45:36 +0900
+Subject: blkcg: Fix use-after-free of q->root_blkg and q->root_rl.blkg
+
+From: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
+
+commit 65635cbc37e011e71b208257a25e7c1078cd039b upstream.
+
+blk_put_rl() does not call blkg_put() for q->root_rl because we
+don't take request list reference on q->root_blkg.
+However, if root_blkg is once attached then detached (freed),
+blk_put_rl() is confused by the bogus pointer in q->root_blkg.
+
+For example, with !CONFIG_BLK_DEV_THROTTLING &&
+CONFIG_CFQ_GROUP_IOSCHED,
+switching IO scheduler from cfq to deadline will cause system stall
+after the following warning with 3.6:
+
+> WARNING: at /work/build/linux/block/blk-cgroup.h:250
+> blk_put_rl+0x4d/0x95()
+> Modules linked in: bridge stp llc sunrpc acpi_cpufreq freq_table mperf
+> ipt_REJECT nf_conntrack_ipv4 nf_defrag_ipv4
+> Pid: 0, comm: swapper/0 Not tainted 3.6.0 #1
+> Call Trace:
+>  <IRQ>  [<ffffffff810453bd>] warn_slowpath_common+0x85/0x9d
+>  [<ffffffff810453ef>] warn_slowpath_null+0x1a/0x1c
+>  [<ffffffff811d5f8d>] blk_put_rl+0x4d/0x95
+>  [<ffffffff811d614a>] __blk_put_request+0xc3/0xcb
+>  [<ffffffff811d71a3>] blk_finish_request+0x232/0x23f
+>  [<ffffffff811d76c3>] ? blk_end_bidi_request+0x34/0x5d
+>  [<ffffffff811d76d1>] blk_end_bidi_request+0x42/0x5d
+>  [<ffffffff811d7728>] blk_end_request+0x10/0x12
+>  [<ffffffff812cdf16>] scsi_io_completion+0x207/0x4d5
+>  [<ffffffff812c6fcf>] scsi_finish_command+0xfa/0x103
+>  [<ffffffff812ce2f8>] scsi_softirq_done+0xff/0x108
+>  [<ffffffff811dcea5>] blk_done_softirq+0x8d/0xa1
+>  [<ffffffff810915d5>] ?
+>  generic_smp_call_function_single_interrupt+0x9f/0xd7
+>  [<ffffffff8104cf5b>] __do_softirq+0x102/0x213
+>  [<ffffffff8108a5ec>] ? lock_release_holdtime+0xb6/0xbb
+>  [<ffffffff8104d2b4>] ? raise_softirq_irqoff+0x9/0x3d
+>  [<ffffffff81424dfc>] call_softirq+0x1c/0x30
+>  [<ffffffff81011beb>] do_softirq+0x4b/0xa3
+>  [<ffffffff8104cdb0>] irq_exit+0x53/0xd5
+>  [<ffffffff8102d865>] smp_call_function_single_interrupt+0x34/0x36
+>  [<ffffffff8142486f>] call_function_single_interrupt+0x6f/0x80
+>  <EOI>  [<ffffffff8101800b>] ? mwait_idle+0x94/0xcd
+>  [<ffffffff81018002>] ? mwait_idle+0x8b/0xcd
+>  [<ffffffff81017811>] cpu_idle+0xbb/0x114
+>  [<ffffffff81401fbd>] rest_init+0xc1/0xc8
+>  [<ffffffff81401efc>] ? csum_partial_copy_generic+0x16c/0x16c
+>  [<ffffffff81cdbd3d>] start_kernel+0x3d4/0x3e1
+>  [<ffffffff81cdb79e>] ? kernel_init+0x1f7/0x1f7
+>  [<ffffffff81cdb2dd>] x86_64_start_reservations+0xb8/0xbd
+>  [<ffffffff81cdb3e3>] x86_64_start_kernel+0x101/0x110
+
+This patch clears q->root_blkg and q->root_rl.blkg when root blkg
+is destroyed.
+
+Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
+Acked-by: Vivek Goyal <vgoyal@redhat.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/blk-cgroup.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -285,6 +285,13 @@ static void blkg_destroy_all(struct requ
+               blkg_destroy(blkg);
+               spin_unlock(&blkcg->lock);
+       }
++
++      /*
++       * root blkg is destroyed.  Just clear the pointer since
++       * root_rl does not take reference on root blkg.
++       */
++      q->root_blkg = NULL;
++      q->root_rl.blkg = NULL;
+ }
+ static void blkg_rcu_free(struct rcu_head *rcu_head)
diff --git a/queue-3.6/ceph-avoid-32-bit-page-index-overflow.patch b/queue-3.6/ceph-avoid-32-bit-page-index-overflow.patch
new file mode 100644 (file)
index 0000000..37e2993
--- /dev/null
@@ -0,0 +1,79 @@
+From 6285bc231277419255f3498d3eb5ddc9f8e7fe79 Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Tue, 2 Oct 2012 10:25:51 -0500
+Subject: ceph: avoid 32-bit page index overflow
+
+From: Alex Elder <elder@inktank.com>
+
+commit 6285bc231277419255f3498d3eb5ddc9f8e7fe79 upstream.
+
+A pgoff_t is defined (by default) to have type (unsigned long).  On
+architectures such as i686 that's a 32-bit type.  The ceph address
+space code was attempting to produce 64 bit offsets by shifting a
+page's index by PAGE_CACHE_SHIFT, but the result was not what was
+desired because the shift occurred before the result got promoted
+to 64 bits.
+
+Fix this by converting all uses of page->index used in this way to
+use the page_offset() macro, which ensures the 64-bit result has the
+intended value.
+
+This fixes http://tracker.newdream.net/issues/3112
+
+Reported-by:  Mohamed Pakkeer <pakkeer.mohideen@realimage.com>
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ceph/addr.c |   11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -205,7 +205,7 @@ static int readpage_nounlock(struct file
+       dout("readpage inode %p file %p page %p index %lu\n",
+            inode, filp, page, page->index);
+       err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout,
+-                                page->index << PAGE_CACHE_SHIFT, &len,
++                                (u64) page_offset(page), &len,
+                                 ci->i_truncate_seq, ci->i_truncate_size,
+                                 &page, 1, 0);
+       if (err == -ENOENT)
+@@ -286,7 +286,7 @@ static int start_read(struct inode *inod
+       int nr_pages = 0;
+       int ret;
+-      off = page->index << PAGE_CACHE_SHIFT;
++      off = (u64) page_offset(page);
+       /* count pages */
+       next_index = page->index;
+@@ -426,7 +426,7 @@ static int writepage_nounlock(struct pag
+       struct ceph_inode_info *ci;
+       struct ceph_fs_client *fsc;
+       struct ceph_osd_client *osdc;
+-      loff_t page_off = page->index << PAGE_CACHE_SHIFT;
++      loff_t page_off = page_offset(page);
+       int len = PAGE_CACHE_SIZE;
+       loff_t i_size;
+       int err = 0;
+@@ -817,8 +817,7 @@ get_more_pages:
+                       /* ok */
+                       if (locked_pages == 0) {
+                               /* prepare async write request */
+-                              offset = (unsigned long long)page->index
+-                                      << PAGE_CACHE_SHIFT;
++                              offset = (u64) page_offset(page);
+                               len = wsize;
+                               req = ceph_osdc_new_request(&fsc->client->osdc,
+                                           &ci->i_layout,
+@@ -1180,7 +1179,7 @@ static int ceph_page_mkwrite(struct vm_a
+       struct inode *inode = vma->vm_file->f_dentry->d_inode;
+       struct page *page = vmf->page;
+       struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+-      loff_t off = page->index << PAGE_CACHE_SHIFT;
++      loff_t off = page_offset(page);
+       loff_t size, len;
+       int ret;
diff --git a/queue-3.6/ceph-fix-dentry-reference-leak-in-encode_fh.patch b/queue-3.6/ceph-fix-dentry-reference-leak-in-encode_fh.patch
new file mode 100644 (file)
index 0000000..6677312
--- /dev/null
@@ -0,0 +1,32 @@
+From 52eb5a900a9863a8b77a895f770e5d825c8e02c6 Mon Sep 17 00:00:00 2001
+From: David Zafman <david.zafman@inktank.com>
+Date: Thu, 18 Oct 2012 14:01:43 -0700
+Subject: ceph: fix dentry reference leak in encode_fh()
+
+From: David Zafman <david.zafman@inktank.com>
+
+commit 52eb5a900a9863a8b77a895f770e5d825c8e02c6 upstream.
+
+Call to d_find_alias() needs a corresponding dput()
+
+This fixes http://tracker.newdream.net/issues/3271
+
+Signed-off-by: David Zafman <david.zafman@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ceph/export.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/ceph/export.c
++++ b/fs/ceph/export.c
+@@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *
+               *max_len = handle_length;
+               type = 255;
+       }
++      if (dentry)
++              dput(dentry);
+       return type;
+ }
diff --git a/queue-3.6/ceph-fix-oops-when-handling-mdsmap-that-decreases-max_mds.patch b/queue-3.6/ceph-fix-oops-when-handling-mdsmap-that-decreases-max_mds.patch
new file mode 100644 (file)
index 0000000..b61e411
--- /dev/null
@@ -0,0 +1,32 @@
+From 3e8f43a089f06279c5f76a9ccd42578eebf7bfa5 Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+Date: Thu, 20 Sep 2012 17:42:25 +0800
+Subject: ceph: Fix oops when handling mdsmap that decreases max_mds
+
+From: "Yan, Zheng" <zheng.z.yan@intel.com>
+
+commit 3e8f43a089f06279c5f76a9ccd42578eebf7bfa5 upstream.
+
+When i >= newmap->m_max_mds, ceph_mdsmap_get_addr(newmap, i) return
+NULL. Passing NULL to memcmp() triggers oops.
+
+Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ceph/mds_client.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -2625,7 +2625,8 @@ static void check_new_map(struct ceph_md
+                    ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "",
+                    session_state_name(s->s_state));
+-              if (memcmp(ceph_mdsmap_get_addr(oldmap, i),
++              if (i >= newmap->m_max_mds ||
++                  memcmp(ceph_mdsmap_get_addr(oldmap, i),
+                          ceph_mdsmap_get_addr(newmap, i),
+                          sizeof(struct ceph_entity_addr))) {
+                       if (s->s_state == CEPH_MDS_SESSION_OPENING) {
diff --git a/queue-3.6/ext4-fix-unjournaled-inode-bitmap-modification.patch b/queue-3.6/ext4-fix-unjournaled-inode-bitmap-modification.patch
new file mode 100644 (file)
index 0000000..efc9f54
--- /dev/null
@@ -0,0 +1,90 @@
+From ffb5387e85d528fb6d0d924abfa3fbf0fc484071 Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@redhat.com>
+Date: Sun, 28 Oct 2012 22:24:57 -0400
+Subject: ext4: fix unjournaled inode bitmap modification
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+commit ffb5387e85d528fb6d0d924abfa3fbf0fc484071 upstream.
+
+commit 119c0d4460b001e44b41dcf73dc6ee794b98bd31 changed
+ext4_new_inode() such that the inode bitmap was being modified
+outside a transaction, which could lead to corruption, and was
+discovered when journal_checksum found a bad checksum in the
+journal during log replay.
+
+Nix ran into this when using the journal_async_commit mount
+option, which enables journal checksumming.  The ensuing
+journal replay failures due to the bad checksums led to
+filesystem corruption reported as the now infamous
+"Apparent serious progressive ext4 data corruption bug"
+
+[ Changed by tytso to only call ext4_journal_get_write_access() only
+  when we're fairly certain that we're going to allocate the inode. ]
+
+I've tested this by mounting with journal_checksum and
+running fsstress then dropping power; I've also tested by
+hacking DM to create snapshots w/o first quiescing, which
+allows me to test journal replay repeatedly w/o actually
+power-cycling the box.  Without the patch I hit a journal
+checksum error every time.  With this fix it survives
+many iterations.
+
+Reported-by: Nix <nix@esperi.org.uk>
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ialloc.c |   19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -716,6 +716,10 @@ repeat_in_this_group:
+                                  "inode=%lu", ino + 1);
+                       continue;
+               }
++              BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
++              err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
++              if (err)
++                      goto fail;
+               ext4_lock_group(sb, group);
+               ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);
+               ext4_unlock_group(sb, group);
+@@ -729,6 +733,11 @@ repeat_in_this_group:
+       goto out;
+ got:
++      BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
++      err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
++      if (err)
++              goto fail;
++
+       /* We may have to initialize the block bitmap if it isn't already */
+       if (ext4_has_group_desc_csum(sb) &&
+           gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+@@ -762,11 +771,6 @@ got:
+                       goto fail;
+       }
+-      BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
+-      err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
+-      if (err)
+-              goto fail;
+-
+       BUFFER_TRACE(group_desc_bh, "get_write_access");
+       err = ext4_journal_get_write_access(handle, group_desc_bh);
+       if (err)
+@@ -814,11 +818,6 @@ got:
+       }
+       ext4_unlock_group(sb, group);
+-      BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
+-      err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
+-      if (err)
+-              goto fail;
+-
+       BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");
+       err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);
+       if (err)
diff --git a/queue-3.6/floppy-do-put_disk-on-current-dr-if-blk_init_queue-fails.patch b/queue-3.6/floppy-do-put_disk-on-current-dr-if-blk_init_queue-fails.patch
new file mode 100644 (file)
index 0000000..72ff0af
--- /dev/null
@@ -0,0 +1,32 @@
+From 238ab78469c6ab7845b43d5061cd3c92331b2452 Mon Sep 17 00:00:00 2001
+From: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+Date: Mon, 27 Aug 2012 20:56:52 -0300
+Subject: floppy: do put_disk on current dr if blk_init_queue fails
+
+From: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+
+commit 238ab78469c6ab7845b43d5061cd3c92331b2452 upstream.
+
+If blk_init_queue fails, we do not call put_disk on the current dr
+(dr is decremented first in the error handling loop).
+
+Reviewed-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/floppy.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -4151,6 +4151,7 @@ static int __init do_floppy_init(void)
+               disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+               if (!disks[dr]->queue) {
++                      put_disk(disks[dr]);
+                       err = -ENOMEM;
+                       goto out_put_disk;
+               }
diff --git a/queue-3.6/floppy-don-t-call-alloc_ordered_workqueue-inside-the-alloc_disk-loop.patch b/queue-3.6/floppy-don-t-call-alloc_ordered_workqueue-inside-the-alloc_disk-loop.patch
new file mode 100644 (file)
index 0000000..b1ac1b2
--- /dev/null
@@ -0,0 +1,77 @@
+From b54e1f88897bcacc2cd359f48ea3b39eaf55f084 Mon Sep 17 00:00:00 2001
+From: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+Date: Mon, 27 Aug 2012 20:56:51 -0300
+Subject: floppy: don't call alloc_ordered_workqueue inside the alloc_disk loop
+
+From: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+
+commit b54e1f88897bcacc2cd359f48ea3b39eaf55f084 upstream.
+
+Since commit 070ad7e ("floppy: convert to delayed work and single-thread
+wq"), we end up calling alloc_ordered_workqueue multiple times inside
+the loop, which shouldn't be intended. Besides the leak, other side
+effect in the current code is if blk_init_queue fails, we would end up
+calling unregister_blkdev even if we didn't call yet register_blkdev.
+
+Just moved the allocation of floppy_wq before the loop, and adjusted the
+code accordingly.
+
+Acked-by: Vivek Goyal <vgoyal@redhat.com>
+Reviewed-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/floppy.c |   15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -4138,6 +4138,10 @@ static int __init do_floppy_init(void)
+       raw_cmd = NULL;
++      floppy_wq = alloc_ordered_workqueue("floppy", 0);
++      if (!floppy_wq)
++              return -ENOMEM;
++
+       for (dr = 0; dr < N_DRIVE; dr++) {
+               disks[dr] = alloc_disk(1);
+               if (!disks[dr]) {
+@@ -4145,16 +4149,10 @@ static int __init do_floppy_init(void)
+                       goto out_put_disk;
+               }
+-              floppy_wq = alloc_ordered_workqueue("floppy", 0);
+-              if (!floppy_wq) {
+-                      err = -ENOMEM;
+-                      goto out_put_disk;
+-              }
+-
+               disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+               if (!disks[dr]->queue) {
+                       err = -ENOMEM;
+-                      goto out_destroy_workq;
++                      goto out_put_disk;
+               }
+               blk_queue_max_hw_sectors(disks[dr]->queue, 64);
+@@ -4318,8 +4316,6 @@ out_release_dma:
+ out_unreg_region:
+       blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
+       platform_driver_unregister(&floppy_driver);
+-out_destroy_workq:
+-      destroy_workqueue(floppy_wq);
+ out_unreg_blkdev:
+       unregister_blkdev(FLOPPY_MAJOR, "fd");
+ out_put_disk:
+@@ -4335,6 +4331,7 @@ out_put_disk:
+               }
+               put_disk(disks[dr]);
+       }
++      destroy_workqueue(floppy_wq);
+       return err;
+ }
diff --git a/queue-3.6/floppy-properly-handle-failure-on-add_disk-loop.patch b/queue-3.6/floppy-properly-handle-failure-on-add_disk-loop.patch
new file mode 100644 (file)
index 0000000..8766c32
--- /dev/null
@@ -0,0 +1,49 @@
+From d60e7ec18c3fb2cbf90969ccd42889eb2d03aef9 Mon Sep 17 00:00:00 2001
+From: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+Date: Mon, 27 Aug 2012 20:56:54 -0300
+Subject: floppy: properly handle failure on add_disk loop
+
+From: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+
+commit d60e7ec18c3fb2cbf90969ccd42889eb2d03aef9 upstream.
+
+On floppy initialization, if something failed inside the loop we call
+add_disk, there was no cleanup of previous iterations in the error
+handling.
+
+Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/floppy.c |   11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -4293,7 +4293,7 @@ static int __init do_floppy_init(void)
+               err = platform_device_register(&floppy_device[drive]);
+               if (err)
+-                      goto out_release_dma;
++                      goto out_remove_drives;
+               err = device_create_file(&floppy_device[drive].dev,
+                                        &dev_attr_cmos);
+@@ -4311,6 +4311,15 @@ static int __init do_floppy_init(void)
+ out_unreg_platform_dev:
+       platform_device_unregister(&floppy_device[drive]);
++out_remove_drives:
++      while (drive--) {
++              if ((allowed_drive_mask & (1 << drive)) &&
++                  fdc_state[FDC(drive)].version != FDC_NONE) {
++                      del_gendisk(disks[drive]);
++                      device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
++                      platform_device_unregister(&floppy_device[drive]);
++              }
++      }
+ out_release_dma:
+       if (atomic_read(&usage_count))
+               floppy_release_irq_and_dma();
diff --git a/queue-3.6/gpio-timberdale-fix-a-potential-wrapping-issue.patch b/queue-3.6/gpio-timberdale-fix-a-potential-wrapping-issue.patch
new file mode 100644 (file)
index 0000000..2e4381c
--- /dev/null
@@ -0,0 +1,40 @@
+From d79550a7bc35c16476ebdc27c78378d8093390ec Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Thu, 11 Oct 2012 09:56:35 +0300
+Subject: gpio-timberdale: fix a potential wrapping issue
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit d79550a7bc35c16476ebdc27c78378d8093390ec upstream.
+
+->last_ier is an unsigned long but the high bits can't be used int the
+original code because the shift wraps.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpio/gpio-timberdale.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpio/gpio-timberdale.c
++++ b/drivers/gpio/gpio-timberdale.c
+@@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct
+       unsigned long flags;
+       spin_lock_irqsave(&tgpio->lock, flags);
+-      tgpio->last_ier &= ~(1 << offset);
++      tgpio->last_ier &= ~(1UL << offset);
+       iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
+       spin_unlock_irqrestore(&tgpio->lock, flags);
+ }
+@@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct i
+       unsigned long flags;
+       spin_lock_irqsave(&tgpio->lock, flags);
+-      tgpio->last_ier |= 1 << offset;
++      tgpio->last_ier |= 1UL << offset;
+       iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
+       spin_unlock_irqrestore(&tgpio->lock, flags);
+ }
diff --git a/queue-3.6/gpiolib-don-t-return-eprobe_defer-to-sysfs-or-for-invalid-gpios.patch b/queue-3.6/gpiolib-don-t-return-eprobe_defer-to-sysfs-or-for-invalid-gpios.patch
new file mode 100644 (file)
index 0000000..63867a8
--- /dev/null
@@ -0,0 +1,48 @@
+From ad2fab36d7922401c4576fb7ea9b21a47a29a17f Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 25 Oct 2012 14:03:03 +0300
+Subject: gpiolib: Don't return -EPROBE_DEFER to sysfs, or for invalid gpios
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit ad2fab36d7922401c4576fb7ea9b21a47a29a17f upstream.
+
+gpios requested with invalid numbers, or gpios requested from userspace via sysfs
+should not try to be deferred on failure.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpio/gpiolib.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -623,9 +623,11 @@ static ssize_t export_store(struct class
+        */
+       status = gpio_request(gpio, "sysfs");
+-      if (status < 0)
++      if (status < 0) {
++              if (status == -EPROBE_DEFER)
++                      status = -ENODEV;
+               goto done;
+-
++      }
+       status = gpio_export(gpio, true);
+       if (status < 0)
+               gpio_free(gpio);
+@@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const ch
+       spin_lock_irqsave(&gpio_lock, flags);
+-      if (!gpio_is_valid(gpio))
++      if (!gpio_is_valid(gpio)) {
++              status = -EINVAL;
+               goto done;
++      }
+       desc = &gpio_desc[gpio];
+       chip = desc->chip;
+       if (chip == NULL)
diff --git a/queue-3.6/libceph-avoid-null-kref_put-when-osd-reset-races-with-alloc_msg.patch b/queue-3.6/libceph-avoid-null-kref_put-when-osd-reset-races-with-alloc_msg.patch
new file mode 100644 (file)
index 0000000..cf5f37e
--- /dev/null
@@ -0,0 +1,37 @@
+From 9bd952615a42d7e2ce3fa2c632e808e804637a1a Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Wed, 24 Oct 2012 16:12:58 -0700
+Subject: libceph: avoid NULL kref_put when osd reset races with alloc_msg
+
+From: Sage Weil <sage@inktank.com>
+
+commit 9bd952615a42d7e2ce3fa2c632e808e804637a1a upstream.
+
+The ceph_on_in_msg_alloc() method drops con->mutex while it allocates a
+message.  If that races with a timeout that resends a zillion messages and
+resets the connection, and the ->alloc_msg() method returns a NULL message,
+it will call ceph_msg_put(NULL) and BUG.
+
+Fix by only calling put if msg is non-NULL.
+
+Fixes http://tracker.newdream.net/issues/3142
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/messenger.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -2750,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct
+               msg = con->ops->alloc_msg(con, hdr, skip);
+               mutex_lock(&con->mutex);
+               if (con->state != CON_STATE_OPEN) {
+-                      ceph_msg_put(msg);
++                      if (msg)
++                              ceph_msg_put(msg);
+                       return -EAGAIN;
+               }
+               con->in_msg = msg;
diff --git a/queue-3.6/libceph-check-for-invalid-mapping.patch b/queue-3.6/libceph-check-for-invalid-mapping.patch
new file mode 100644 (file)
index 0000000..ea876b0
--- /dev/null
@@ -0,0 +1,166 @@
+From d63b77f4c552cc3a20506871046ab0fcbc332609 Mon Sep 17 00:00:00 2001
+From: Sage Weil <sage@inktank.com>
+Date: Mon, 24 Sep 2012 20:59:48 -0700
+Subject: libceph: check for invalid mapping
+
+From: Sage Weil <sage@inktank.com>
+
+commit d63b77f4c552cc3a20506871046ab0fcbc332609 upstream.
+
+If we encounter an invalid (e.g., zeroed) mapping, return an error
+and avoid a divide by zero.
+
+Signed-off-by: Sage Weil <sage@inktank.com>
+Reviewed-by: Alex Elder <elder@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/ceph/osd_client.h |    2 +-
+ include/linux/ceph/osdmap.h     |    6 +++---
+ net/ceph/osd_client.c           |   32 ++++++++++++++++++++------------
+ net/ceph/osdmap.c               |   18 ++++++++++++++++--
+ 4 files changed, 40 insertions(+), 18 deletions(-)
+
+--- a/include/linux/ceph/osd_client.h
++++ b/include/linux/ceph/osd_client.h
+@@ -207,7 +207,7 @@ extern void ceph_osdc_handle_reply(struc
+ extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc,
+                                struct ceph_msg *msg);
+-extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
++extern int ceph_calc_raw_layout(struct ceph_osd_client *osdc,
+                       struct ceph_file_layout *layout,
+                       u64 snapid,
+                       u64 off, u64 *plen, u64 *bno,
+--- a/include/linux/ceph/osdmap.h
++++ b/include/linux/ceph/osdmap.h
+@@ -109,9 +109,9 @@ extern struct ceph_osdmap *osdmap_apply_
+ extern void ceph_osdmap_destroy(struct ceph_osdmap *map);
+ /* calculate mapping of a file extent to an object */
+-extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
+-                                        u64 off, u64 *plen,
+-                                        u64 *bno, u64 *oxoff, u64 *oxlen);
++extern int ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
++                                       u64 off, u64 *plen,
++                                       u64 *bno, u64 *oxoff, u64 *oxlen);
+ /* calculate mapping of object to a placement group */
+ extern int ceph_calc_object_layout(struct ceph_object_layout *ol,
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -52,7 +52,7 @@ static int op_has_extent(int op)
+               op == CEPH_OSD_OP_WRITE);
+ }
+-void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
++int ceph_calc_raw_layout(struct ceph_osd_client *osdc,
+                       struct ceph_file_layout *layout,
+                       u64 snapid,
+                       u64 off, u64 *plen, u64 *bno,
+@@ -62,12 +62,15 @@ void ceph_calc_raw_layout(struct ceph_os
+       struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
+       u64 orig_len = *plen;
+       u64 objoff, objlen;    /* extent in object */
++      int r;
+       reqhead->snapid = cpu_to_le64(snapid);
+       /* object extent? */
+-      ceph_calc_file_object_mapping(layout, off, plen, bno,
+-                                    &objoff, &objlen);
++      r = ceph_calc_file_object_mapping(layout, off, plen, bno,
++                                        &objoff, &objlen);
++      if (r < 0)
++              return r;
+       if (*plen < orig_len)
+               dout(" skipping last %llu, final file extent %llu~%llu\n",
+                    orig_len - *plen, off, *plen);
+@@ -83,7 +86,7 @@ void ceph_calc_raw_layout(struct ceph_os
+       dout("calc_layout bno=%llx %llu~%llu (%d pages)\n",
+            *bno, objoff, objlen, req->r_num_pages);
+-
++      return 0;
+ }
+ EXPORT_SYMBOL(ceph_calc_raw_layout);
+@@ -112,20 +115,25 @@ EXPORT_SYMBOL(ceph_calc_raw_layout);
+  *
+  * fill osd op in request message.
+  */
+-static void calc_layout(struct ceph_osd_client *osdc,
+-                      struct ceph_vino vino,
+-                      struct ceph_file_layout *layout,
+-                      u64 off, u64 *plen,
+-                      struct ceph_osd_request *req,
+-                      struct ceph_osd_req_op *op)
++static int calc_layout(struct ceph_osd_client *osdc,
++                     struct ceph_vino vino,
++                     struct ceph_file_layout *layout,
++                     u64 off, u64 *plen,
++                     struct ceph_osd_request *req,
++                     struct ceph_osd_req_op *op)
+ {
+       u64 bno;
++      int r;
+-      ceph_calc_raw_layout(osdc, layout, vino.snap, off,
+-                           plen, &bno, req, op);
++      r = ceph_calc_raw_layout(osdc, layout, vino.snap, off,
++                               plen, &bno, req, op);
++      if (r < 0)
++              return r;
+       snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno);
+       req->r_oid_len = strlen(req->r_oid);
++
++      return r;
+ }
+ /*
+--- a/net/ceph/osdmap.c
++++ b/net/ceph/osdmap.c
+@@ -984,7 +984,7 @@ bad:
+  * for now, we write only a single su, until we can
+  * pass a stride back to the caller.
+  */
+-void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
++int ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
+                                  u64 off, u64 *plen,
+                                  u64 *ono,
+                                  u64 *oxoff, u64 *oxlen)
+@@ -998,11 +998,17 @@ void ceph_calc_file_object_mapping(struc
+       dout("mapping %llu~%llu  osize %u fl_su %u\n", off, *plen,
+            osize, su);
++      if (su == 0 || sc == 0)
++              goto invalid;
+       su_per_object = osize / su;
++      if (su_per_object == 0)
++              goto invalid;
+       dout("osize %u / su %u = su_per_object %u\n", osize, su,
+            su_per_object);
+-      BUG_ON((su & ~PAGE_MASK) != 0);
++      if ((su & ~PAGE_MASK) != 0)
++              goto invalid;
++
+       /* bl = *off / su; */
+       t = off;
+       do_div(t, su);
+@@ -1030,6 +1036,14 @@ void ceph_calc_file_object_mapping(struc
+       *plen = *oxlen;
+       dout(" obj extent %llu~%llu\n", *oxoff, *oxlen);
++      return 0;
++
++invalid:
++      dout(" invalid layout\n");
++      *ono = 0;
++      *oxoff = 0;
++      *oxlen = 0;
++      return -EINVAL;
+ }
+ EXPORT_SYMBOL(ceph_calc_file_object_mapping);
diff --git a/queue-3.6/md-raid1-fix-assembling-of-arrays-containing-replacements.patch b/queue-3.6/md-raid1-fix-assembling-of-arrays-containing-replacements.patch
new file mode 100644 (file)
index 0000000..46ddc68
--- /dev/null
@@ -0,0 +1,44 @@
+From 02b898f2f04e418094f0093a3ad0b415bcdbe8eb Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.de>
+Date: Wed, 31 Oct 2012 11:42:03 +1100
+Subject: md/raid1: Fix assembling of arrays containing Replacements.
+
+From: NeilBrown <neilb@suse.de>
+
+commit 02b898f2f04e418094f0093a3ad0b415bcdbe8eb upstream.
+
+setup_conf in raid1.c uses conf->raid_disks before assigning
+a value.  It is used when including 'Replacement' devices.
+
+The consequence is that assembling an array which contains a
+replacement will misbehave and either not include the replacement, or
+not include the device being replaced.
+
+Though this doesn't lead directly to data corruption, it could lead to
+reduced data safety.
+
+So use mddev->raid_disks, which is initialised, instead.
+
+Bug was introduced by commit c19d57980b38a5bb613a898937a1cf85f422fb9b
+      md/raid1: recognise replacements when assembling arrays.
+
+in 3.3, so fix is suitable for 3.3.y thru 3.6.y.
+
+Signed-off-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/raid1.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -2699,7 +2699,7 @@ static struct r1conf *setup_conf(struct
+                   || disk_idx < 0)
+                       continue;
+               if (test_bit(Replacement, &rdev->flags))
+-                      disk = conf->mirrors + conf->raid_disks + disk_idx;
++                      disk = conf->mirrors + mddev->raid_disks + disk_idx;
+               else
+                       disk = conf->mirrors + disk_idx;
diff --git a/queue-3.6/rbd-reset-backoff-if-unable-to-re-queue.patch b/queue-3.6/rbd-reset-backoff-if-unable-to-re-queue.patch
new file mode 100644 (file)
index 0000000..4879e34
--- /dev/null
@@ -0,0 +1,59 @@
+From 588377d6199034c36d335e7df5818b731fea072c Mon Sep 17 00:00:00 2001
+From: Alex Elder <elder@inktank.com>
+Date: Mon, 8 Oct 2012 20:37:30 -0700
+Subject: rbd: reset BACKOFF if unable to re-queue
+
+From: Alex Elder <elder@inktank.com>
+
+commit 588377d6199034c36d335e7df5818b731fea072c upstream.
+
+If ceph_fault() is unable to queue work after a delay, it sets the
+BACKOFF connection flag so con_work() will attempt to do so.
+
+In con_work(), when BACKOFF is set, if queue_delayed_work() doesn't
+result in newly-queued work, it simply ignores this condition and
+proceeds as if no backoff delay were desired.  There are two
+problems with this--one of which is a bug.
+
+The first problem is simply that the intended behavior is to back
+off, and if we aren't able queue the work item to run after a delay
+we're not doing that.
+
+The only reason queue_delayed_work() won't queue work is if the
+provided work item is already queued.  In the messenger, this
+means that con_work() is already scheduled to be run again.  So
+if we simply set the BACKOFF flag again when this occurs, we know
+the next con_work() call will again attempt to hold off activity
+on the connection until after the delay.
+
+The second problem--the bug--is a leak of a reference count.  If
+queue_delayed_work() returns 0 in con_work(), con->ops->put() drops
+the connection reference held on entry to con_work().  However,
+processing is (was) allowed to continue, and at the end of the
+function a second con->ops->put() is called.
+
+This patch fixes both problems.
+
+Signed-off-by: Alex Elder <elder@inktank.com>
+Reviewed-by: Sage Weil <sage@inktank.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ceph/messenger.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/ceph/messenger.c
++++ b/net/ceph/messenger.c
+@@ -2300,10 +2300,11 @@ restart:
+                       mutex_unlock(&con->mutex);
+                       return;
+               } else {
+-                      con->ops->put(con);
+                       dout("con_work %p FAILED to back off %lu\n", con,
+                            con->delay);
++                      set_bit(CON_FLAG_BACKOFF, &con->flags);
+               }
++              goto done;
+       }
+       if (con->state == CON_STATE_STANDBY) {
diff --git a/queue-3.6/series b/queue-3.6/series
new file mode 100644 (file)
index 0000000..2ab5d05
--- /dev/null
@@ -0,0 +1,14 @@
+ext4-fix-unjournaled-inode-bitmap-modification.patch
+blkcg-fix-use-after-free-of-q-root_blkg-and-q-root_rl.blkg.patch
+gpio-timberdale-fix-a-potential-wrapping-issue.patch
+gpiolib-don-t-return-eprobe_defer-to-sysfs-or-for-invalid-gpios.patch
+md-raid1-fix-assembling-of-arrays-containing-replacements.patch
+floppy-don-t-call-alloc_ordered_workqueue-inside-the-alloc_disk-loop.patch
+floppy-do-put_disk-on-current-dr-if-blk_init_queue-fails.patch
+floppy-properly-handle-failure-on-add_disk-loop.patch
+rbd-reset-backoff-if-unable-to-re-queue.patch
+libceph-avoid-null-kref_put-when-osd-reset-races-with-alloc_msg.patch
+ceph-fix-dentry-reference-leak-in-encode_fh.patch
+ceph-fix-oops-when-handling-mdsmap-that-decreases-max_mds.patch
+libceph-check-for-invalid-mapping.patch
+ceph-avoid-32-bit-page-index-overflow.patch