From: Greg Kroah-Hartman Date: Thu, 10 Sep 2009 22:57:58 +0000 (-0700) Subject: more .30 patches X-Git-Tag: v2.6.27.34~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0c6571043bbc053054dd58366f5cb1d281ecb9c0;p=thirdparty%2Fkernel%2Fstable-queue.git more .30 patches --- diff --git a/queue-2.6.30/dm-exception-store-split-set_chunk_size.patch b/queue-2.6.30/dm-exception-store-split-set_chunk_size.patch new file mode 100644 index 00000000000..f3e4a13934e --- /dev/null +++ b/queue-2.6.30/dm-exception-store-split-set_chunk_size.patch @@ -0,0 +1,51 @@ +From 2defcc3fb4661e7351cb2ac48d843efc4c64db13 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 4 Sep 2009 20:40:41 +0100 +Subject: dm exception store: split set_chunk_size + +From: Mikulas Patocka + +commit 2defcc3fb4661e7351cb2ac48d843efc4c64db13 upstream. + +Break the function set_chunk_size to two functions in preparation for +the fix in the following patch. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-exception-store.c | 8 ++++++++ + drivers/md/dm-exception-store.h | 4 ++++ + 2 files changed, 12 insertions(+) + +--- a/drivers/md/dm-exception-store.c ++++ b/drivers/md/dm-exception-store.c +@@ -171,6 +171,14 @@ static int set_chunk_size(struct dm_exce + */ + chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9); + ++ return dm_exception_store_set_chunk_size(store, chunk_size_ulong, ++ error); ++} ++ ++int dm_exception_store_set_chunk_size(struct dm_exception_store *store, ++ unsigned long chunk_size_ulong, ++ char **error) ++{ + /* Check chunk_size is a power of 2 */ + if (!is_power_of_2(chunk_size_ulong)) { + *error = "Chunk size is not a power of 2"; +--- a/drivers/md/dm-exception-store.h ++++ b/drivers/md/dm-exception-store.h +@@ -168,6 +168,10 @@ static inline chunk_t sector_to_chunk(st + int dm_exception_store_type_register(struct dm_exception_store_type *type); + int dm_exception_store_type_unregister(struct dm_exception_store_type *type); + ++int dm_exception_store_set_chunk_size(struct dm_exception_store *store, ++ unsigned long chunk_size_ulong, ++ char **error); ++ + int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, + unsigned *args_used, + struct dm_exception_store **store); diff --git a/queue-2.6.30/dm-raid1-do-not-allow-log_failure-variable-to-unset-after-being-set.patch b/queue-2.6.30/dm-raid1-do-not-allow-log_failure-variable-to-unset-after-being-set.patch new file mode 100644 index 00000000000..451d5b923d7 --- /dev/null +++ b/queue-2.6.30/dm-raid1-do-not-allow-log_failure-variable-to-unset-after-being-set.patch @@ -0,0 +1,61 @@ +From d2b698644c97cb033261536a4f2010924a00eac9 Mon Sep 17 00:00:00 2001 +From: Jonathan Brassow +Date: Fri, 4 Sep 2009 20:40:32 +0100 +Subject: dm raid1: do not allow log_failure variable to unset after being set + +From: Jonathan Brassow + +commit d2b698644c97cb033261536a4f2010924a00eac9 upstream. + +This patch fixes a bug which was triggering a case where the primary leg +could not be changed on failure even when the mirror was in-sync. + +The case involves the failure of the primary device along with +the transient failure of the log device. The problem is that +bios can be put on the 'failures' list (due to log failure) +before 'fail_mirror' is called due to the primary device failure. +Normally, this is fine, but if the log device failure is transient, +a subsequent iteration of the work thread, 'do_mirror', will +reset 'log_failure'. The 'do_failures' function then resets +the 'in_sync' variable when processing bios on the failures list. +The 'in_sync' variable is what is used to determine if the +primary device can be switched in the event of a failure. Since +this has been reset, the primary device is incorrectly assumed +to be not switchable. + +The case has been seen in the cluster mirror context, where one +machine realizes the log device is dead before the other machines. +As the responsibilities of the server migrate from one node to +another (because the mirror is being reconfigured due to the failure), +the new server may think for a moment that the log device is fine - +thus resetting the 'log_failure' variable. + +In any case, it is inappropiate for us to reset the 'log_failure' +variable. The above bug simply illustrates that it can actually +hurt us. + +Signed-off-by: Jonathan Brassow +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-raid1.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/md/dm-raid1.c ++++ b/drivers/md/dm-raid1.c +@@ -648,7 +648,13 @@ static void do_writes(struct mirror_set + */ + dm_rh_inc_pending(ms->rh, &sync); + dm_rh_inc_pending(ms->rh, &nosync); +- ms->log_failure = dm_rh_flush(ms->rh) ? 1 : 0; ++ ++ /* ++ * If the flush fails on a previous call and succeeds here, ++ * we must not reset the log_failure variable. We need ++ * userspace interaction to do that. ++ */ ++ ms->log_failure = dm_rh_flush(ms->rh) ? 1 : ms->log_failure; + + /* + * Dispatch io. diff --git a/queue-2.6.30/dm-snapshot-fix-header-corruption-race-on-invalidation.patch b/queue-2.6.30/dm-snapshot-fix-header-corruption-race-on-invalidation.patch new file mode 100644 index 00000000000..95ffc270534 --- /dev/null +++ b/queue-2.6.30/dm-snapshot-fix-header-corruption-race-on-invalidation.patch @@ -0,0 +1,143 @@ +From 61578dcd3fafe6babd72e8db32110cc0b630a432 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 4 Sep 2009 20:40:39 +0100 +Subject: dm snapshot: fix header corruption race on invalidation + +From: Mikulas Patocka + +commit 61578dcd3fafe6babd72e8db32110cc0b630a432 upstream. + +If a persistent snapshot fills up, a race can corrupt the on-disk header +which causes a crash on any future attempt to activate the snapshot +(typically while booting). This patch fixes the race. + +When the snapshot overflows, __invalidate_snapshot is called, which calls +snapshot store method drop_snapshot. It goes to persistent_drop_snapshot that +calls write_header. write_header constructs the new header in the "area" +location. + +Concurrently, an existing kcopyd job may finish, call copy_callback +and commit_exception method, that goes to persistent_commit_exception. +persistent_commit_exception doesn't do locking, relying on the fact that +callbacks are single-threaded, but it can race with snapshot invalidation and +overwrite the header that is just being written while the snapshot is being +invalidated. + +The result of this race is a corrupted header being written that can +lead to a crash on further reactivation (if chunk_size is zero in the +corrupted header). + +The fix is to use separate memory areas for each. + +See the bug: https://bugzilla.redhat.com/show_bug.cgi?id=461506 + +Signed-off-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-snap-persistent.c | 44 ++++++++++++++++++++++++++++++---------- + 1 file changed, 34 insertions(+), 10 deletions(-) + +--- a/drivers/md/dm-snap-persistent.c ++++ b/drivers/md/dm-snap-persistent.c +@@ -106,6 +106,13 @@ struct pstore { + void *zero_area; + + /* ++ * An area used for header. The header can be written ++ * concurrently with metadata (when invalidating the snapshot), ++ * so it needs a separate buffer. ++ */ ++ void *header_area; ++ ++ /* + * Used to keep track of which metadata area the data in + * 'chunk' refers to. + */ +@@ -148,16 +155,27 @@ static int alloc_area(struct pstore *ps) + */ + ps->area = vmalloc(len); + if (!ps->area) +- return r; ++ goto err_area; + + ps->zero_area = vmalloc(len); +- if (!ps->zero_area) { +- vfree(ps->area); +- return r; +- } ++ if (!ps->zero_area) ++ goto err_zero_area; + memset(ps->zero_area, 0, len); + ++ ps->header_area = vmalloc(len); ++ if (!ps->header_area) ++ goto err_header_area; ++ + return 0; ++ ++err_header_area: ++ vfree(ps->zero_area); ++ ++err_zero_area: ++ vfree(ps->area); ++ ++err_area: ++ return r; + } + + static void free_area(struct pstore *ps) +@@ -169,6 +187,10 @@ static void free_area(struct pstore *ps) + if (ps->zero_area) + vfree(ps->zero_area); + ps->zero_area = NULL; ++ ++ if (ps->header_area) ++ vfree(ps->header_area); ++ ps->header_area = NULL; + } + + struct mdata_req { +@@ -285,11 +307,11 @@ static int read_header(struct pstore *ps + if (r) + return r; + +- r = chunk_io(ps, ps->area, 0, READ, 1); ++ r = chunk_io(ps, ps->header_area, 0, READ, 1); + if (r) + goto bad; + +- dh = (struct disk_header *) ps->area; ++ dh = ps->header_area; + + if (le32_to_cpu(dh->magic) == 0) { + *new_snapshot = 1; +@@ -339,15 +361,15 @@ static int write_header(struct pstore *p + { + struct disk_header *dh; + +- memset(ps->area, 0, ps->store->chunk_size << SECTOR_SHIFT); ++ memset(ps->header_area, 0, ps->store->chunk_size << SECTOR_SHIFT); + +- dh = (struct disk_header *) ps->area; ++ dh = ps->header_area; + dh->magic = cpu_to_le32(SNAP_MAGIC); + dh->valid = cpu_to_le32(ps->valid); + dh->version = cpu_to_le32(ps->version); + dh->chunk_size = cpu_to_le32(ps->store->chunk_size); + +- return chunk_io(ps, ps->area, 0, WRITE, 1); ++ return chunk_io(ps, ps->header_area, 0, WRITE, 1); + } + + /* +@@ -667,6 +689,8 @@ static int persistent_ctr(struct dm_exce + ps->valid = 1; + ps->version = SNAPSHOT_DISK_VERSION; + ps->area = NULL; ++ ps->zero_area = NULL; ++ ps->header_area = NULL; + ps->next_free = 2; /* skipping the header and first area */ + ps->current_committed = 0; + diff --git a/queue-2.6.30/dm-snapshot-fix-on-disk-chunk-size-validation.patch b/queue-2.6.30/dm-snapshot-fix-on-disk-chunk-size-validation.patch new file mode 100644 index 00000000000..3aaa79e0627 --- /dev/null +++ b/queue-2.6.30/dm-snapshot-fix-on-disk-chunk-size-validation.patch @@ -0,0 +1,93 @@ +From ae0b7448e91353ea5f821601a055aca6b58042cd Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 4 Sep 2009 20:40:43 +0100 +Subject: dm snapshot: fix on disk chunk size validation + +From: Mikulas Patocka + +commit ae0b7448e91353ea5f821601a055aca6b58042cd upstream. + +Fix some problems seen in the chunk size processing when activating a +pre-existing snapshot. + +For a new snapshot, the chunk size can either be supplied by the creator +or a default value can be used. For an existing snapshot, the +chunk size in the snapshot header on disk should always be used. + +If someone attempts to load an existing snapshot and has the 'default +chunk size' option set, the kernel uses its default value even when it +is incorrect for the snapshot being loaded. This patch ensures the +correct on-disk value is always used. + +Secondly, when the code does use the chunk size stored on the disk it is +prudent to revalidate it, so the code can exit cleanly if it got +corrupted as happened in +https://bugzilla.redhat.com/show_bug.cgi?id=461506 . + +Signed-off-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-exception-store.c | 5 +++++ + drivers/md/dm-snap-persistent.c | 22 ++++++++++++++-------- + 2 files changed, 19 insertions(+), 8 deletions(-) + +--- a/drivers/md/dm-exception-store.c ++++ b/drivers/md/dm-exception-store.c +@@ -191,6 +191,11 @@ int dm_exception_store_set_chunk_size(st + return -EINVAL; + } + ++ if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) { ++ *error = "Chunk size is too high"; ++ return -EINVAL; ++ } ++ + store->chunk_size = chunk_size_ulong; + store->chunk_mask = chunk_size_ulong - 1; + store->chunk_shift = ffs(chunk_size_ulong) - 1; +--- a/drivers/md/dm-snap-persistent.c ++++ b/drivers/md/dm-snap-persistent.c +@@ -286,6 +286,7 @@ static int read_header(struct pstore *ps + struct disk_header *dh; + chunk_t chunk_size; + int chunk_size_supplied = 1; ++ char *chunk_err; + + /* + * Use default chunk size (or hardsect_size, if larger) if none supplied +@@ -329,20 +330,25 @@ static int read_header(struct pstore *ps + ps->version = le32_to_cpu(dh->version); + chunk_size = le32_to_cpu(dh->chunk_size); + +- if (!chunk_size_supplied || ps->store->chunk_size == chunk_size) ++ if (ps->store->chunk_size == chunk_size) + return 0; + +- DMWARN("chunk size %llu in device metadata overrides " +- "table chunk size of %llu.", +- (unsigned long long)chunk_size, +- (unsigned long long)ps->store->chunk_size); ++ if (chunk_size_supplied) ++ DMWARN("chunk size %llu in device metadata overrides " ++ "table chunk size of %llu.", ++ (unsigned long long)chunk_size, ++ (unsigned long long)ps->store->chunk_size); + + /* We had a bogus chunk_size. Fix stuff up. */ + free_area(ps); + +- ps->store->chunk_size = chunk_size; +- ps->store->chunk_mask = chunk_size - 1; +- ps->store->chunk_shift = ffs(chunk_size) - 1; ++ r = dm_exception_store_set_chunk_size(ps->store, chunk_size, ++ &chunk_err); ++ if (r) { ++ DMERR("invalid on-disk chunk size %llu: %s.", ++ (unsigned long long)chunk_size, chunk_err); ++ return r; ++ } + + r = dm_io_client_resize(sectors_to_pages(ps->store->chunk_size), + ps->io_client); diff --git a/queue-2.6.30/dm-snapshot-refactor-zero_disk_area-to-use-chunk_io.patch b/queue-2.6.30/dm-snapshot-refactor-zero_disk_area-to-use-chunk_io.patch new file mode 100644 index 00000000000..baae4c2dcd7 --- /dev/null +++ b/queue-2.6.30/dm-snapshot-refactor-zero_disk_area-to-use-chunk_io.patch @@ -0,0 +1,92 @@ +From 02d2fd31defce6ff77146ad0fef4f19006055d86 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 4 Sep 2009 20:40:37 +0100 +Subject: dm snapshot: refactor zero_disk_area to use chunk_io + +From: Mikulas Patocka + +commit 02d2fd31defce6ff77146ad0fef4f19006055d86 upstream. + +Refactor chunk_io to prepare for the fix in the following patch. + +Pass an area pointer to chunk_io and simplify zero_disk_area to use +chunk_io. No functional change. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-snap-persistent.c | 26 +++++++------------------- + 1 file changed, 7 insertions(+), 19 deletions(-) + +--- a/drivers/md/dm-snap-persistent.c ++++ b/drivers/md/dm-snap-persistent.c +@@ -188,7 +188,8 @@ static void do_metadata(struct work_stru + /* + * Read or write a chunk aligned and sized block of data from a device. + */ +-static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata) ++static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, ++ int metadata) + { + struct dm_io_region where = { + .bdev = ps->store->cow->bdev, +@@ -198,7 +199,7 @@ static int chunk_io(struct pstore *ps, c + struct dm_io_request io_req = { + .bi_rw = rw, + .mem.type = DM_IO_VMA, +- .mem.ptr.vma = ps->area, ++ .mem.ptr.vma = area, + .client = ps->io_client, + .notify.fn = NULL, + }; +@@ -240,7 +241,7 @@ static int area_io(struct pstore *ps, in + + chunk = area_location(ps, ps->current_area); + +- r = chunk_io(ps, chunk, rw, 0); ++ r = chunk_io(ps, ps->area, chunk, rw, 0); + if (r) + return r; + +@@ -254,20 +255,7 @@ static void zero_memory_area(struct psto + + static int zero_disk_area(struct pstore *ps, chunk_t area) + { +- struct dm_io_region where = { +- .bdev = ps->store->cow->bdev, +- .sector = ps->store->chunk_size * area_location(ps, area), +- .count = ps->store->chunk_size, +- }; +- struct dm_io_request io_req = { +- .bi_rw = WRITE, +- .mem.type = DM_IO_VMA, +- .mem.ptr.vma = ps->zero_area, +- .client = ps->io_client, +- .notify.fn = NULL, +- }; +- +- return dm_io(&io_req, 1, &where, NULL); ++ return chunk_io(ps, ps->zero_area, area_location(ps, area), WRITE, 0); + } + + static int read_header(struct pstore *ps, int *new_snapshot) +@@ -297,7 +285,7 @@ static int read_header(struct pstore *ps + if (r) + return r; + +- r = chunk_io(ps, 0, READ, 1); ++ r = chunk_io(ps, ps->area, 0, READ, 1); + if (r) + goto bad; + +@@ -359,7 +347,7 @@ static int write_header(struct pstore *p + dh->version = cpu_to_le32(ps->version); + dh->chunk_size = cpu_to_le32(ps->store->chunk_size); + +- return chunk_io(ps, 0, WRITE, 1); ++ return chunk_io(ps, ps->area, 0, WRITE, 1); + } + + /* diff --git a/queue-2.6.30/jffs2-add-missing-verify-buffer-allocation-deallocation.patch b/queue-2.6.30/jffs2-add-missing-verify-buffer-allocation-deallocation.patch new file mode 100644 index 00000000000..14950023dde --- /dev/null +++ b/queue-2.6.30/jffs2-add-missing-verify-buffer-allocation-deallocation.patch @@ -0,0 +1,49 @@ +From bc8cec0dff072f1a45ce7f6b2c5234bb3411ac51 Mon Sep 17 00:00:00 2001 +From: Massimo Cirillo +Date: Thu, 27 Aug 2009 10:44:09 +0200 +Subject: JFFS2: add missing verify buffer allocation/deallocation + +From: Massimo Cirillo + +commit bc8cec0dff072f1a45ce7f6b2c5234bb3411ac51 upstream. + +The function jffs2_nor_wbuf_flash_setup() doesn't allocate the verify buffer +if CONFIG_JFFS2_FS_WBUF_VERIFY is defined, so causing a kernel panic when +that macro is enabled and the verify function is called. Similarly the +jffs2_nor_wbuf_flash_cleanup() must free the buffer if +CONFIG_JFFS2_FS_WBUF_VERIFY is enabled. +The following patch fixes the problem. +The following patch applies to 2.6.30 kernel. + +Signed-off-by: Massimo Cirillo +Signed-off-by: Artem Bityutskiy +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jffs2/wbuf.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/fs/jffs2/wbuf.c ++++ b/fs/jffs2/wbuf.c +@@ -1268,10 +1268,20 @@ int jffs2_nor_wbuf_flash_setup(struct jf + if (!c->wbuf) + return -ENOMEM; + ++#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY ++ c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL); ++ if (!c->wbuf_verify) { ++ kfree(c->wbuf); ++ return -ENOMEM; ++ } ++#endif + return 0; + } + + void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) { ++#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY ++ kfree(c->wbuf_verify); ++#endif + kfree(c->wbuf); + } + diff --git a/queue-2.6.30/nilfs2-fix-preempt-count-underflow-in-nilfs_btnode_prepare_change_key.patch b/queue-2.6.30/nilfs2-fix-preempt-count-underflow-in-nilfs_btnode_prepare_change_key.patch new file mode 100644 index 00000000000..632805b4f0e --- /dev/null +++ b/queue-2.6.30/nilfs2-fix-preempt-count-underflow-in-nilfs_btnode_prepare_change_key.patch @@ -0,0 +1,77 @@ +From b1f1b8ce0a1d71cbc72f7540134d52b79bd8f5ac Mon Sep 17 00:00:00 2001 +From: Ryusuke Konishi +Date: Sun, 30 Aug 2009 04:21:41 +0900 +Subject: nilfs2: fix preempt count underflow in nilfs_btnode_prepare_change_key + +From: Ryusuke Konishi + +commit b1f1b8ce0a1d71cbc72f7540134d52b79bd8f5ac upstream. + +This will fix the following preempt count underflow reported from +users with the title "[NILFS users] segctord problem" (Message-ID: +<949415.6494.qm@web58808.mail.re1.yahoo.com> and Message-ID: +): + + WARNING: at kernel/sched.c:4890 sub_preempt_count+0x95/0xa0() + Hardware name: HP Compaq 6530b (KR980UT#ABC) + Modules linked in: bridge stp llc bnep rfcomm l2cap xfs exportfs nilfs2 cowloop loop vboxnetadp vboxnetflt vboxdrv btusb bluetooth uvcvideo videodev v4l1_compat v4l2_compat_ioctl32 arc4 snd_hda_codec_analog ecb iwlagn iwlcore rfkill lib80211 mac80211 snd_hda_intel snd_hda_codec ehci_hcd uhci_hcd usbcore snd_hwdep snd_pcm tg3 cfg80211 psmouse snd_timer joydev libphy ohci1394 snd_page_alloc hp_accel lis3lv02d ieee1394 led_class i915 drm i2c_algo_bit video backlight output i2c_core dm_crypt dm_mod + Pid: 4197, comm: segctord Not tainted 2.6.30-gentoo-r4-64 #7 + Call Trace: + [] ? sub_preempt_count+0x95/0xa0 + [] warn_slowpath_common+0x78/0xd0 + [] warn_slowpath_null+0xf/0x20 + [] sub_preempt_count+0x95/0xa0 + [] nilfs_btnode_prepare_change_key+0x11b/0x190 [nilfs2] + [] nilfs_btree_assign_p+0x19d/0x1e0 [nilfs2] + [] nilfs_btree_assign+0xbd/0x130 [nilfs2] + [] nilfs_bmap_assign+0x47/0x70 [nilfs2] + [] nilfs_segctor_do_construct+0x956/0x20f0 [nilfs2] + [] ? _spin_unlock_irqrestore+0x12/0x40 + [] ? __up_write+0xe0/0x150 + [] ? up_write+0x9/0x10 + [] ? nilfs_bmap_test_and_clear_dirty+0x43/0x60 [nilfs2] + [] ? nilfs_mdt_fetch_dirty+0x27/0x60 [nilfs2] + [] nilfs_segctor_construct+0x8c/0xd0 [nilfs2] + [] nilfs_segctor_thread+0x15c/0x3a0 [nilfs2] + [] ? nilfs_construction_timeout+0x0/0x10 [nilfs2] + [] ? add_timer+0x13/0x20 + [] ? __wake_up_common+0x5a/0x90 + [] ? autoremove_wake_function+0x0/0x40 + [] ? nilfs_segctor_thread+0x0/0x3a0 [nilfs2] + [] ? nilfs_segctor_thread+0x0/0x3a0 [nilfs2] + [] kthread+0x56/0x90 + [] child_rip+0xa/0x20 + [] ? kthread+0x0/0x90 + [] ? child_rip+0x0/0x20 + +This problem was caused due to a missing radix_tree_preload() call in +the retry path of nilfs_btnode_prepare_change_key() function. + +Reported-by: Eric A +Reported-by: Jerome Poulin +Signed-off-by: Ryusuke Konishi +Tested-by: Jerome Poulin +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nilfs2/btnode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nilfs2/btnode.c ++++ b/fs/nilfs2/btnode.c +@@ -206,6 +206,7 @@ int nilfs_btnode_prepare_change_key(stru + * We cannot call radix_tree_preload for the kernels older + * than 2.6.23, because it is not exported for modules. + */ ++retry: + err = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); + if (err) + goto failed_unlock; +@@ -216,7 +217,6 @@ int nilfs_btnode_prepare_change_key(stru + (unsigned long long)oldkey, + (unsigned long long)newkey); + +-retry: + spin_lock_irq(&btnc->tree_lock); + err = radix_tree_insert(&btnc->page_tree, newkey, obh->b_page); + spin_unlock_irq(&btnc->tree_lock); diff --git a/queue-2.6.30/pci-sr-iov-correct-broken-resource-alignment-calculations.patch b/queue-2.6.30/pci-sr-iov-correct-broken-resource-alignment-calculations.patch new file mode 100644 index 00000000000..9b4072ac534 --- /dev/null +++ b/queue-2.6.30/pci-sr-iov-correct-broken-resource-alignment-calculations.patch @@ -0,0 +1,159 @@ +From 6faf17f6f1ffc586d16efc2f9fa2083a7785ee74 Mon Sep 17 00:00:00 2001 +From: Chris Wright +Date: Fri, 28 Aug 2009 13:00:06 -0700 +Subject: PCI SR-IOV: correct broken resource alignment calculations + +From: Chris Wright + +commit 6faf17f6f1ffc586d16efc2f9fa2083a7785ee74 upstream. + +An SR-IOV capable device includes an SR-IOV PCIe capability which +describes the Virtual Function (VF) BAR requirements. A typical SR-IOV +device can support multiple VFs whose BARs must be in a contiguous region, +effectively an array of VF BARs. The BAR reports the size requirement +for a single VF. We calculate the full range needed by simply multiplying +the VF BAR size with the number of possible VFs and create a resource +spanning the full range. + +This all seems sane enough except it artificially inflates the alignment +requirement for the VF BAR. The VF BAR need only be aligned to the size +of a single BAR not the contiguous range of VF BARs. This can cause us +to fail to allocate resources for the BAR despite the fact that we +actually have enough space. + +This patch adds a thin PCI specific layer over the generic +resource_alignment() function which is aware of the special nature of +VF BARs and does sorting and allocation based on the smaller alignment +requirement. + +I recognize that while resource_alignment is generic, it's basically a +PCI helper. An alternative to this patch is to add PCI VF BAR specific +information to struct resource. I opted for the extra layer rather than +adding such PCI specific information to struct resource. This does +have the slight downside that we don't cache the BAR size and re-read +for each alignment query (happens a small handful of times during boot +for each VF BAR). + +Signed-off-by: Chris Wright +Cc: Ivan Kokshaysky +Cc: Linus Torvalds +Cc: Matthew Wilcox +Cc: Yu Zhao +Signed-off-by: Jesse Barnes +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/iov.c | 23 +++++++++++++++++++++++ + drivers/pci/pci.h | 13 +++++++++++++ + drivers/pci/setup-bus.c | 4 ++-- + drivers/pci/setup-res.c | 6 +++--- + 4 files changed, 41 insertions(+), 5 deletions(-) + +--- a/drivers/pci/iov.c ++++ b/drivers/pci/iov.c +@@ -595,6 +595,29 @@ int pci_iov_resource_bar(struct pci_dev + } + + /** ++ * pci_sriov_resource_alignment - get resource alignment for VF BAR ++ * @dev: the PCI device ++ * @resno: the resource number ++ * ++ * Returns the alignment of the VF BAR found in the SR-IOV capability. ++ * This is not the same as the resource size which is defined as ++ * the VF BAR size multiplied by the number of VFs. The alignment ++ * is just the VF BAR size. ++ */ ++int pci_sriov_resource_alignment(struct pci_dev *dev, int resno) ++{ ++ struct resource tmp; ++ enum pci_bar_type type; ++ int reg = pci_iov_resource_bar(dev, resno, &type); ++ ++ if (!reg) ++ return 0; ++ ++ __pci_read_base(dev, type, &tmp, reg); ++ return resource_alignment(&tmp); ++} ++ ++/** + * pci_restore_iov_state - restore the state of the IOV capability + * @dev: the PCI device + */ +--- a/drivers/pci/pci.h ++++ b/drivers/pci/pci.h +@@ -234,6 +234,7 @@ extern int pci_iov_init(struct pci_dev * + extern void pci_iov_release(struct pci_dev *dev); + extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, + enum pci_bar_type *type); ++extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno); + extern void pci_restore_iov_state(struct pci_dev *dev); + extern int pci_iov_bus_range(struct pci_bus *bus); + #else +@@ -259,4 +260,16 @@ static inline int pci_iov_bus_range(stru + } + #endif /* CONFIG_PCI_IOV */ + ++static inline int pci_resource_alignment(struct pci_dev *dev, ++ struct resource *res) ++{ ++#ifdef CONFIG_PCI_IOV ++ int resno = res - dev->resource; ++ ++ if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) ++ return pci_sriov_resource_alignment(dev, resno); ++#endif ++ return resource_alignment(res); ++} ++ + #endif /* DRIVERS_PCI_H */ +--- a/drivers/pci/setup-bus.c ++++ b/drivers/pci/setup-bus.c +@@ -25,7 +25,7 @@ + #include + #include + #include +- ++#include "pci.h" + + static void pbus_assign_resources_sorted(const struct pci_bus *bus) + { +@@ -355,7 +355,7 @@ static int pbus_size_mem(struct pci_bus + continue; + r_size = resource_size(r); + /* For bridges size != alignment */ +- align = resource_alignment(r); ++ align = pci_resource_alignment(dev, r); + order = __ffs(align) - 20; + if (order > 11) { + dev_warn(&dev->dev, "BAR %d bad alignment %llx: " +--- a/drivers/pci/setup-res.c ++++ b/drivers/pci/setup-res.c +@@ -145,7 +145,7 @@ int pci_assign_resource(struct pci_dev * + size = resource_size(res); + min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; + +- align = resource_alignment(res); ++ align = pci_resource_alignment(dev, res); + if (!align) { + dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus " + "alignment) %pR flags %#lx\n", +@@ -236,7 +236,7 @@ void pdev_sort_resources(struct pci_dev + if (!(r->flags) || r->parent) + continue; + +- r_align = resource_alignment(r); ++ r_align = pci_resource_alignment(dev, r); + if (!r_align) { + dev_warn(&dev->dev, "BAR %d: bogus alignment " + "%pR flags %#lx\n", +@@ -248,7 +248,7 @@ void pdev_sort_resources(struct pci_dev + struct resource_list *ln = list->next; + + if (ln) +- align = resource_alignment(ln->res); ++ align = pci_resource_alignment(ln->dev, ln->res); + + if (r_align > align) { + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); diff --git a/queue-2.6.30/scsi-sd-fix-bug-in-scsi-async-probing.patch b/queue-2.6.30/scsi-sd-fix-bug-in-scsi-async-probing.patch new file mode 100644 index 00000000000..78440e42016 --- /dev/null +++ b/queue-2.6.30/scsi-sd-fix-bug-in-scsi-async-probing.patch @@ -0,0 +1,98 @@ +From 601e7638254c118fca135af9b1a9f35061420f62 Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Tue, 26 May 2009 20:35:48 +0000 +Subject: SCSI: sd: fix bug in SCSI async probing + +From: James Bottomley + +commit 601e7638254c118fca135af9b1a9f35061420f62 upstream. + +The async split up of probing in sd.c created a potential failure case where +something goes wrong with device_add(), but which we don't recover properly. +Since, in general, asynchronous error handling is hard, move the device_add() +into the asynchronous path (it should be fast) and make sure all the deferred +processing cannot fail. + +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/sd.c | 45 +++++++++++++++++++++------------------------ + 1 file changed, 21 insertions(+), 24 deletions(-) + +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1902,24 +1902,6 @@ static void sd_probe_async(void *data, a + index = sdkp->index; + dev = &sdp->sdev_gendev; + +- if (!sdp->request_queue->rq_timeout) { +- if (sdp->type != TYPE_MOD) +- blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); +- else +- blk_queue_rq_timeout(sdp->request_queue, +- SD_MOD_TIMEOUT); +- } +- +- device_initialize(&sdkp->dev); +- sdkp->dev.parent = &sdp->sdev_gendev; +- sdkp->dev.class = &sd_disk_class; +- dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev)); +- +- if (device_add(&sdkp->dev)) +- goto out_free_index; +- +- get_device(&sdp->sdev_gendev); +- + if (index < SD_MAX_DISKS) { + gd->major = sd_major((index & 0xf0) >> 4); + gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); +@@ -1954,11 +1936,6 @@ static void sd_probe_async(void *data, a + + sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", + sdp->removable ? "removable " : ""); +- +- return; +- +- out_free_index: +- ida_remove(&sd_index_ida, index); + } + + /** +@@ -2026,6 +2003,24 @@ static int sd_probe(struct device *dev) + sdkp->openers = 0; + sdkp->previous_state = 1; + ++ if (!sdp->request_queue->rq_timeout) { ++ if (sdp->type != TYPE_MOD) ++ blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); ++ else ++ blk_queue_rq_timeout(sdp->request_queue, ++ SD_MOD_TIMEOUT); ++ } ++ ++ device_initialize(&sdkp->dev); ++ sdkp->dev.parent = &sdp->sdev_gendev; ++ sdkp->dev.class = &sd_disk_class; ++ dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev)); ++ ++ if (device_add(&sdkp->dev)) ++ goto out_free_index; ++ ++ get_device(&sdp->sdev_gendev); ++ + async_schedule(sd_probe_async, sdkp); + + return 0; +@@ -2055,8 +2050,10 @@ static int sd_probe(struct device *dev) + **/ + static int sd_remove(struct device *dev) + { +- struct scsi_disk *sdkp = dev_get_drvdata(dev); ++ struct scsi_disk *sdkp; + ++ async_synchronize_full(); ++ sdkp = dev_get_drvdata(dev); + device_del(&sdkp->dev); + del_gendisk(sdkp->disk); + sd_shutdown(dev); diff --git a/queue-2.6.30/series b/queue-2.6.30/series index 6481d94f00d..4f4979898d6 100644 --- a/queue-2.6.30/series +++ b/queue-2.6.30/series @@ -8,3 +8,15 @@ sparc64-kill-spurious-nmi-watchdog-triggers-by-increasing-limit-to-30-seconds.pa sparc64-validate-linear-d-tlb-misses.patch sparc64-fix-bootup-with-mcount-in-some-configs.patch sparc-sys32.s-incorrect-compat-layer-splice-system-call.patch +jffs2-add-missing-verify-buffer-allocation-deallocation.patch +slub-fix-kmem_cache_destroy-with-slab_destroy_by_rcu.patch +nilfs2-fix-preempt-count-underflow-in-nilfs_btnode_prepare_change_key.patch +pci-sr-iov-correct-broken-resource-alignment-calculations.patch +scsi-sd-fix-bug-in-scsi-async-probing.patch +sound-oxygen-handle-cards-with-missing-eeprom.patch +sound-oxygen-fix-mclk-rate-for-192-khz-playback.patch +dm-raid1-do-not-allow-log_failure-variable-to-unset-after-being-set.patch +dm-snapshot-refactor-zero_disk_area-to-use-chunk_io.patch +dm-snapshot-fix-header-corruption-race-on-invalidation.patch +dm-exception-store-split-set_chunk_size.patch +dm-snapshot-fix-on-disk-chunk-size-validation.patch diff --git a/queue-2.6.30/slub-fix-kmem_cache_destroy-with-slab_destroy_by_rcu.patch b/queue-2.6.30/slub-fix-kmem_cache_destroy-with-slab_destroy_by_rcu.patch new file mode 100644 index 00000000000..6abc86ab8f4 --- /dev/null +++ b/queue-2.6.30/slub-fix-kmem_cache_destroy-with-slab_destroy_by_rcu.patch @@ -0,0 +1,46 @@ +From d76b1590e06a63a3d8697168cd0aabf1c4b3cb3a Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 3 Sep 2009 22:38:59 +0300 +Subject: slub: Fix kmem_cache_destroy() with SLAB_DESTROY_BY_RCU + +From: Eric Dumazet + +commit d76b1590e06a63a3d8697168cd0aabf1c4b3cb3a upstream. + +kmem_cache_destroy() should call rcu_barrier() *after* kmem_cache_close() and +*before* sysfs_slab_remove() or risk rcu_free_slab() being called after +kmem_cache is deleted (kfreed). + +rmmod nf_conntrack can crash the machine because it has to kmem_cache_destroy() +a SLAB_DESTROY_BY_RCU enabled cache. + +Reported-by: Zdenek Kabelac +Signed-off-by: Eric Dumazet +Acked-by: Paul E. McKenney +Signed-off-by: Pekka Enberg +Signed-off-by: Greg Kroah-Hartman + +--- + mm/slub.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -2490,8 +2490,6 @@ static inline int kmem_cache_close(struc + */ + void kmem_cache_destroy(struct kmem_cache *s) + { +- if (s->flags & SLAB_DESTROY_BY_RCU) +- rcu_barrier(); + down_write(&slub_lock); + s->refcount--; + if (!s->refcount) { +@@ -2502,6 +2500,8 @@ void kmem_cache_destroy(struct kmem_cach + "still has objects.\n", s->name, __func__); + dump_stack(); + } ++ if (s->flags & SLAB_DESTROY_BY_RCU) ++ rcu_barrier(); + sysfs_slab_remove(s); + } else + up_write(&slub_lock); diff --git a/queue-2.6.30/sound-oxygen-fix-mclk-rate-for-192-khz-playback.patch b/queue-2.6.30/sound-oxygen-fix-mclk-rate-for-192-khz-playback.patch new file mode 100644 index 00000000000..812dc5e879b --- /dev/null +++ b/queue-2.6.30/sound-oxygen-fix-mclk-rate-for-192-khz-playback.patch @@ -0,0 +1,35 @@ +From b91ab72b830e1494c2c7f8de05ccb2ab2c9cfb26 Mon Sep 17 00:00:00 2001 +From: Clemens Ladisch +Date: Tue, 1 Sep 2009 08:23:58 +0200 +Subject: sound: oxygen: fix MCLK rate for 192 kHz playback + +From: Clemens Ladisch + +commit b91ab72b830e1494c2c7f8de05ccb2ab2c9cfb26 upstream. + +Do not forget to program the MCLK ratio for the I2S output. +Otherwise, the master clock frequency can be too high for +the DACs at sample frequencies above 96 kHz. + +Signed-off-by: Clemens Ladisch +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/oxygen/oxygen_pcm.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/pci/oxygen/oxygen_pcm.c ++++ b/sound/pci/oxygen/oxygen_pcm.c +@@ -469,9 +469,11 @@ static int oxygen_multich_hw_params(stru + oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, + oxygen_rate(hw_params) | + chip->model.dac_i2s_format | ++ oxygen_i2s_mclk(hw_params) | + oxygen_i2s_bits(hw_params), + OXYGEN_I2S_RATE_MASK | + OXYGEN_I2S_FORMAT_MASK | ++ OXYGEN_I2S_MCLK_MASK | + OXYGEN_I2S_BITS_MASK); + oxygen_update_dac_routing(chip); + oxygen_update_spdif_source(chip); diff --git a/queue-2.6.30/sound-oxygen-handle-cards-with-missing-eeprom.patch b/queue-2.6.30/sound-oxygen-handle-cards-with-missing-eeprom.patch new file mode 100644 index 00000000000..9d21782ee6b --- /dev/null +++ b/queue-2.6.30/sound-oxygen-handle-cards-with-missing-eeprom.patch @@ -0,0 +1,38 @@ +From 92653453c3015c083b9fe0ad48261c6b2267d482 Mon Sep 17 00:00:00 2001 +From: Clemens Ladisch +Date: Wed, 2 Sep 2009 18:25:39 +0200 +Subject: sound: oxygen: handle cards with missing EEPROM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Clemens Ladisch + +commit 92653453c3015c083b9fe0ad48261c6b2267d482 upstream. + +The card model detection code introduced in 2.6.30 that tries to work +around partially broken EEPROM contents by reading the EEPROM directly +does not handle cards where the EEPROM has been omitted. In this case, +we have to use the default ID to allow the driver to load. + +Signed-off-by: Clemens Ladisch +Reported-and-tested-by: Ozan Çağlayan +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/oxygen/oxygen_lib.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/sound/pci/oxygen/oxygen_lib.c ++++ b/sound/pci/oxygen/oxygen_lib.c +@@ -260,6 +260,9 @@ oxygen_search_pci_id(struct oxygen *chip + * chip didn't if the first EEPROM word was overwritten. + */ + subdevice = oxygen_read_eeprom(chip, 2); ++ /* use default ID if EEPROM is missing */ ++ if (subdevice == 0xffff) ++ subdevice = 0x8788; + /* + * We use only the subsystem device ID for searching because it is + * unique even without the subsystem vendor ID, which may have been