summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-05-30 08:25:50 +0800
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-30 08:25:50 +0800
commit678ec76293684a459c7d95074660c0950255c6ac (patch)
tree3f5d97e30223a317f64382aea1d501d0053d78a1
parent3ef2c9d6292984c1098d3689cbbba0dfad141534 (diff)
downloadstable-queue-678ec76293684a459c7d95074660c0950255c6ac.tar.gz
.39 patches
-rw-r--r--queue-2.6.39/block-add-a-non-queueable-flush-flag.patch70
-rw-r--r--queue-2.6.39/block-add-proper-state-guards-to-__elv_next_request.patch36
-rw-r--r--queue-2.6.39/block-always-allocate-genhd-ev-if-check_events-is.patch50
-rw-r--r--queue-2.6.39/block-fix-discard-topology-stacking-and-reporting.patch91
-rw-r--r--queue-2.6.39/block-hold-queue-if-flush-is-running-for-non-queueable.patch111
-rw-r--r--queue-2.6.39/block-move-bd_set_size-above-rescan_partitions-in.patch70
-rw-r--r--queue-2.6.39/ext4-don-t-set-pageuptodate-in-ext4_end_bio.patch103
-rw-r--r--queue-2.6.39/mtd-mtdconcat-fix-nand-oob-write.patch42
-rw-r--r--queue-2.6.39/mtd-omap-fix-subpage-ecc-issue-with-prefetch.patch72
-rw-r--r--queue-2.6.39/mtd-return-badblockbits-back.patch39
-rw-r--r--queue-2.6.39/series10
11 files changed, 694 insertions, 0 deletions
diff --git a/queue-2.6.39/block-add-a-non-queueable-flush-flag.patch b/queue-2.6.39/block-add-a-non-queueable-flush-flag.patch
new file mode 100644
index 0000000000..44b51f3638
--- /dev/null
+++ b/queue-2.6.39/block-add-a-non-queueable-flush-flag.patch
@@ -0,0 +1,70 @@
+From f3876930952390a31c3a7fd68dd621464a36eb80 Mon Sep 17 00:00:00 2001
+From: "shaohua.li@intel.com" <shaohua.li@intel.com>
+Date: Fri, 6 May 2011 11:34:32 -0600
+Subject: block: add a non-queueable flush flag
+
+From: "shaohua.li@intel.com" <shaohua.li@intel.com>
+
+commit f3876930952390a31c3a7fd68dd621464a36eb80 upstream.
+
+flush request isn't queueable in some drives. Add a flag to let driver
+notify block layer about this. We can optimize flush performance with the
+knowledge.
+
+Stable: 2.6.39 only
+
+Signed-off-by: Shaohua Li <shaohua.li@intel.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/blk-settings.c | 6 ++++++
+ include/linux/blkdev.h | 7 +++++++
+ 2 files changed, 13 insertions(+)
+
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -790,6 +790,12 @@ void blk_queue_flush(struct request_queu
+ }
+ EXPORT_SYMBOL_GPL(blk_queue_flush);
+
++void blk_queue_flush_queueable(struct request_queue *q, bool queueable)
++{
++ q->flush_not_queueable = !queueable;
++}
++EXPORT_SYMBOL_GPL(blk_queue_flush_queueable);
++
+ static int __init blk_settings_init(void)
+ {
+ blk_max_low_pfn = max_low_pfn - 1;
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -364,6 +364,7 @@ struct request_queue
+ * for flush operations
+ */
+ unsigned int flush_flags;
++ unsigned int flush_not_queueable:1;
+ unsigned int flush_pending_idx:1;
+ unsigned int flush_running_idx:1;
+ unsigned long flush_pending_since;
+@@ -843,6 +844,7 @@ extern void blk_queue_softirq_done(struc
+ extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *);
+ extern void blk_queue_rq_timeout(struct request_queue *, unsigned int);
+ extern void blk_queue_flush(struct request_queue *q, unsigned int flush);
++extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable);
+ extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
+
+ extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
+@@ -1111,6 +1113,11 @@ static inline unsigned int block_size(st
+ return bdev->bd_block_size;
+ }
+
++static inline bool queue_flush_queueable(struct request_queue *q)
++{
++ return !q->flush_not_queueable;
++}
++
+ typedef struct {struct page *v;} Sector;
+
+ unsigned char *read_dev_sector(struct block_device *, sector_t, Sector *);
diff --git a/queue-2.6.39/block-add-proper-state-guards-to-__elv_next_request.patch b/queue-2.6.39/block-add-proper-state-guards-to-__elv_next_request.patch
new file mode 100644
index 0000000000..dce9a29506
--- /dev/null
+++ b/queue-2.6.39/block-add-proper-state-guards-to-__elv_next_request.patch
@@ -0,0 +1,36 @@
+From 0a58e077eb600d1efd7e54ad9926a75a39d7f8ae Mon Sep 17 00:00:00 2001
+From: James Bottomley <James.Bottomley@suse.de>
+Date: Wed, 18 May 2011 16:20:10 +0200
+Subject: block: add proper state guards to __elv_next_request
+
+From: James Bottomley <James.Bottomley@suse.de>
+
+commit 0a58e077eb600d1efd7e54ad9926a75a39d7f8ae upstream.
+
+blk_cleanup_queue() calls elevator_exit() and after this, we can't
+touch the elevator without oopsing. __elv_next_request() must check
+for this state because in the refcounted queue model, we can still
+call it after blk_cleanup_queue() has been called.
+
+This was reported as causing an oops attributable to scsi.
+
+Signed-off-by: James Bottomley <James.Bottomley@suse.de>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/blk.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -81,7 +81,8 @@ static inline struct request *__elv_next
+ q->flush_queue_delayed = 1;
+ return NULL;
+ }
+- if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
++ if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags) ||
++ !q->elevator->ops->elevator_dispatch_fn(q, 0))
+ return NULL;
+ }
+ }
diff --git a/queue-2.6.39/block-always-allocate-genhd-ev-if-check_events-is.patch b/queue-2.6.39/block-always-allocate-genhd-ev-if-check_events-is.patch
new file mode 100644
index 0000000000..7114e407a5
--- /dev/null
+++ b/queue-2.6.39/block-always-allocate-genhd-ev-if-check_events-is.patch
@@ -0,0 +1,50 @@
+From 75e3f3ee3c64968d42f4843ec49e579f84b5aa0c Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Thu, 26 May 2011 21:06:50 +0200
+Subject: block: always allocate genhd->ev if check_events is
+ implemented
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 75e3f3ee3c64968d42f4843ec49e579f84b5aa0c upstream.
+
+9fd097b149 (block: unexport DISK_EVENT_MEDIA_CHANGE for legacy/fringe
+drivers) removed DISK_EVENT_MEDIA_CHANGE from legacy/fringe block
+drivers which have inadequate ->check_events(). Combined with earlier
+change 7c88a168da (block: don't propagate unlisted DISK_EVENTs to
+userland), this enables using ->check_events() for internal processing
+while avoiding enabling in-kernel block event polling which can lead
+to infinite event loop.
+
+Unfortunately, this made many drivers including floppy without any bit
+set in disk->events and ->async_events in which case disk_add_events()
+simply skipped allocation of disk->ev, which disables whole event
+handling. As ->check_events() is still used during open processing
+for revalidation, this can lead to open failure.
+
+This patch always allocates disk->ev if ->check_events is implemented.
+In the long term, it would make sense to simply include the event
+structure inline into genhd as it's now used by virtually all block
+devices.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Ondrej Zary <linux@rainbow-software.org>
+Reported-by: Alex Villacis Lasso <avillaci@ceibo.fiec.espol.edu.ec>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/genhd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -1728,7 +1728,7 @@ static void disk_add_events(struct gendi
+ {
+ struct disk_events *ev;
+
+- if (!disk->fops->check_events || !(disk->events | disk->async_events))
++ if (!disk->fops->check_events)
+ return;
+
+ ev = kzalloc(sizeof(*ev), GFP_KERNEL);
diff --git a/queue-2.6.39/block-fix-discard-topology-stacking-and-reporting.patch b/queue-2.6.39/block-fix-discard-topology-stacking-and-reporting.patch
new file mode 100644
index 0000000000..0c37fbebb5
--- /dev/null
+++ b/queue-2.6.39/block-fix-discard-topology-stacking-and-reporting.patch
@@ -0,0 +1,91 @@
+From a934a00a69e940b126b9bdbf83e630ef5fe43523 Mon Sep 17 00:00:00 2001
+From: "Martin K. Petersen" <martin.petersen@oracle.com>
+Date: Wed, 18 May 2011 10:37:35 +0200
+Subject: block: Fix discard topology stacking and reporting
+
+From: "Martin K. Petersen" <martin.petersen@oracle.com>
+
+commit a934a00a69e940b126b9bdbf83e630ef5fe43523 upstream.
+
+In some cases we would end up stacking discard_zeroes_data incorrectly.
+Fix this by enabling the feature by default for stacking drivers and
+clearing it for low-level drivers. Incorporating a device that does not
+support dzd will then cause the feature to be disabled in the stacking
+driver.
+
+Also ensure that the maximum discard value does not overflow when
+exported in sysfs and return 0 in the alignment and dzd fields for
+devices that don't support discard.
+
+Reported-by: Lukas Czerner <lczerner@redhat.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/blk-settings.c | 3 ++-
+ block/blk-sysfs.c | 3 ++-
+ include/linux/blkdev.h | 7 +++++--
+ 3 files changed, 9 insertions(+), 4 deletions(-)
+
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -120,7 +120,7 @@ void blk_set_default_limits(struct queue
+ lim->discard_granularity = 0;
+ lim->discard_alignment = 0;
+ lim->discard_misaligned = 0;
+- lim->discard_zeroes_data = -1;
++ lim->discard_zeroes_data = 1;
+ lim->logical_block_size = lim->physical_block_size = lim->io_min = 512;
+ lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT);
+ lim->alignment_offset = 0;
+@@ -166,6 +166,7 @@ void blk_queue_make_request(struct reque
+
+ blk_set_default_limits(&q->limits);
+ blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS);
++ q->limits.discard_zeroes_data = 0;
+
+ /*
+ * by default assume old behaviour and bounce for any highmem page
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -152,7 +152,8 @@ static ssize_t queue_discard_granularity
+
+ static ssize_t queue_discard_max_show(struct request_queue *q, char *page)
+ {
+- return queue_var_show(q->limits.max_discard_sectors << 9, page);
++ return sprintf(page, "%llu\n",
++ (unsigned long long)q->limits.max_discard_sectors << 9);
+ }
+
+ static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page)
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -257,7 +257,7 @@ struct queue_limits {
+ unsigned char misaligned;
+ unsigned char discard_misaligned;
+ unsigned char cluster;
+- signed char discard_zeroes_data;
++ unsigned char discard_zeroes_data;
+ };
+
+ struct request_queue
+@@ -1069,13 +1069,16 @@ static inline int queue_limit_discard_al
+ {
+ unsigned int alignment = (sector << 9) & (lim->discard_granularity - 1);
+
++ if (!lim->max_discard_sectors)
++ return 0;
++
+ return (lim->discard_granularity + lim->discard_alignment - alignment)
+ & (lim->discard_granularity - 1);
+ }
+
+ static inline unsigned int queue_discard_zeroes_data(struct request_queue *q)
+ {
+- if (q->limits.discard_zeroes_data == 1)
++ if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1)
+ return 1;
+
+ return 0;
diff --git a/queue-2.6.39/block-hold-queue-if-flush-is-running-for-non-queueable.patch b/queue-2.6.39/block-hold-queue-if-flush-is-running-for-non-queueable.patch
new file mode 100644
index 0000000000..87cc868910
--- /dev/null
+++ b/queue-2.6.39/block-hold-queue-if-flush-is-running-for-non-queueable.patch
@@ -0,0 +1,111 @@
+From 3ac0cc4508709d42ec9aa351086c7d38bfc0660c Mon Sep 17 00:00:00 2001
+From: "shaohua.li@intel.com" <shaohua.li@intel.com>
+Date: Fri, 6 May 2011 11:34:41 -0600
+Subject: block: hold queue if flush is running for non-queueable
+ flush drive
+
+From: "shaohua.li@intel.com" <shaohua.li@intel.com>
+
+commit 3ac0cc4508709d42ec9aa351086c7d38bfc0660c upstream.
+
+In some drives, flush requests are non-queueable. When flush request is
+running, normal read/write requests can't run. If block layer dispatches
+such request, driver can't handle it and requeue it. Tejun suggested we
+can hold the queue when flush is running. This can avoid unnecessary
+requeue. Also this can improve performance. For example, we have
+request flush1, write1, flush 2. flush1 is dispatched, then queue is
+hold, write1 isn't inserted to queue. After flush1 is finished, flush2
+will be dispatched. Since disk cache is already clean, flush2 will be
+finished very soon, so looks like flush2 is folded to flush1.
+
+In my test, the queue holding completely solves a regression introduced by
+commit 53d63e6b0dfb95882ec0219ba6bbd50cde423794:
+
+ block: make the flush insertion use the tail of the dispatch list
+
+ It's not a preempt type request, in fact we have to insert it
+ behind requests that do specify INSERT_FRONT.
+
+which causes about 20% regression running a sysbench fileio
+workload.
+
+Stable: 2.6.39 only
+
+Signed-off-by: Shaohua Li <shaohua.li@intel.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/blk-flush.c | 16 +++++++++++-----
+ block/blk.h | 21 ++++++++++++++++++++-
+ include/linux/blkdev.h | 1 +
+ 3 files changed, 32 insertions(+), 6 deletions(-)
+
+--- a/block/blk-flush.c
++++ b/block/blk-flush.c
+@@ -212,13 +212,19 @@ static void flush_end_io(struct request
+ }
+
+ /*
+- * Moving a request silently to empty queue_head may stall the
+- * queue. Kick the queue in those cases. This function is called
+- * from request completion path and calling directly into
+- * request_fn may confuse the driver. Always use kblockd.
++ * Kick the queue to avoid stall for two cases:
++ * 1. Moving a request silently to empty queue_head may stall the
++ * queue.
++ * 2. When flush request is running in non-queueable queue, the
++ * queue is hold. Restart the queue after flush request is finished
++ * to avoid stall.
++ * This function is called from request completion path and calling
++ * directly into request_fn may confuse the driver. Always use
++ * kblockd.
+ */
+- if (queued)
++ if (queued || q->flush_queue_delayed)
+ blk_run_queue_async(q);
++ q->flush_queue_delayed = 0;
+ }
+
+ /**
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -61,7 +61,26 @@ static inline struct request *__elv_next
+ rq = list_entry_rq(q->queue_head.next);
+ return rq;
+ }
+-
++ /*
++ * Flush request is running and flush request isn't queueable
++ * in the drive, we can hold the queue till flush request is
++ * finished. Even we don't do this, driver can't dispatch next
++ * requests and will requeue them. And this can improve
++ * throughput too. For example, we have request flush1, write1,
++ * flush 2. flush1 is dispatched, then queue is hold, write1
++ * isn't inserted to queue. After flush1 is finished, flush2
++ * will be dispatched. Since disk cache is already clean,
++ * flush2 will be finished very soon, so looks like flush2 is
++ * folded to flush1.
++ * Since the queue is hold, a flag is set to indicate the queue
++ * should be restarted later. Please see flush_end_io() for
++ * details.
++ */
++ if (q->flush_pending_idx != q->flush_running_idx &&
++ !queue_flush_queueable(q)) {
++ q->flush_queue_delayed = 1;
++ return NULL;
++ }
+ if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
+ return NULL;
+ }
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -365,6 +365,7 @@ struct request_queue
+ */
+ unsigned int flush_flags;
+ unsigned int flush_not_queueable:1;
++ unsigned int flush_queue_delayed:1;
+ unsigned int flush_pending_idx:1;
+ unsigned int flush_running_idx:1;
+ unsigned long flush_pending_since;
diff --git a/queue-2.6.39/block-move-bd_set_size-above-rescan_partitions-in.patch b/queue-2.6.39/block-move-bd_set_size-above-rescan_partitions-in.patch
new file mode 100644
index 0000000000..a96b9d650b
--- /dev/null
+++ b/queue-2.6.39/block-move-bd_set_size-above-rescan_partitions-in.patch
@@ -0,0 +1,70 @@
+From 7e69723fef8771a9d57bd27d36281d756130b4b5 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Mon, 23 May 2011 13:26:07 +0200
+Subject: block: move bd_set_size() above rescan_partitions() in
+ __blkdev_get()
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 7e69723fef8771a9d57bd27d36281d756130b4b5 upstream.
+
+02e352287a4 (block: rescan partitions on invalidated devices on
+-ENOMEDIA too) relocated partition rescan above explicit bd_set_size()
+to simplify condition check. As rescan_partitions() does its own bdev
+size setting, this doesn't break anything; however,
+rescan_partitions() prints out the following messages when adjusting
+bdev size, which can be confusing.
+
+ sda: detected capacity change from 0 to 146815737856
+ sdb: detected capacity change from 0 to 146815737856
+
+This patch restores the original order and remove the warning
+messages.
+
+stable: Please apply together with 02e352287a4 (block: rescan
+ partitions on invalidated devices on -ENOMEDIA too).
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Tony Luck <tony.luck@gmail.com>
+Tested-by: Tony Luck <tony.luck@gmail.com>
+Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ fs/block_dev.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/fs/block_dev.c
++++ b/fs/block_dev.c
+@@ -1120,6 +1120,15 @@ static int __blkdev_get(struct block_dev
+ goto restart;
+ }
+ }
++
++ if (!ret && !bdev->bd_openers) {
++ bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
++ bdi = blk_get_backing_dev_info(bdev);
++ if (bdi == NULL)
++ bdi = &default_backing_dev_info;
++ bdev_inode_switch_bdi(bdev->bd_inode, bdi);
++ }
++
+ /*
+ * If the device is invalidated, rescan partition
+ * if open succeeded or failed with -ENOMEDIUM.
+@@ -1130,14 +1139,6 @@ static int __blkdev_get(struct block_dev
+ rescan_partitions(disk, bdev);
+ if (ret)
+ goto out_clear;
+-
+- if (!bdev->bd_openers) {
+- bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
+- bdi = blk_get_backing_dev_info(bdev);
+- if (bdi == NULL)
+- bdi = &default_backing_dev_info;
+- bdev_inode_switch_bdi(bdev->bd_inode, bdi);
+- }
+ } else {
+ struct block_device *whole;
+ whole = bdget_disk(disk, 0);
diff --git a/queue-2.6.39/ext4-don-t-set-pageuptodate-in-ext4_end_bio.patch b/queue-2.6.39/ext4-don-t-set-pageuptodate-in-ext4_end_bio.patch
new file mode 100644
index 0000000000..f83ce26445
--- /dev/null
+++ b/queue-2.6.39/ext4-don-t-set-pageuptodate-in-ext4_end_bio.patch
@@ -0,0 +1,103 @@
+From 39db00f1c45e770856264bdb3ceca27980b01965 Mon Sep 17 00:00:00 2001
+From: Curt Wohlgemuth <curtw@google.com>
+Date: Sat, 30 Apr 2011 13:26:26 -0400
+Subject: ext4: don't set PageUptodate in ext4_end_bio()
+
+From: Curt Wohlgemuth <curtw@google.com>
+
+commit 39db00f1c45e770856264bdb3ceca27980b01965 upstream.
+
+In the bio completion routine, we should not be setting
+PageUptodate at all -- it's set at sys_write() time, and is
+unaffected by success/failure of the write to disk.
+
+This can cause a page corruption bug when the file system's
+block size is less than the architecture's VM page size.
+
+if we have only written a single block -- we might end up
+setting the page's PageUptodate flag, indicating that page
+is completely read into memory, which may not be true.
+This could cause subsequent reads to get bad data.
+
+This commit also takes the opportunity to clean up error
+handling in ext4_end_bio(), and remove some extraneous code:
+
+ - fixes ext4_end_bio() to set AS_EIO in the
+ page->mapping->flags on error, which was left out by
+ mistake. This is needed so that fsync() will
+ return an error if there was an I/O error.
+ - remove the clear_buffer_dirty() call on unmapped
+ buffers for each page.
+ - consolidate page/buffer error handling in a single
+ section.
+
+Signed-off-by: Curt Wohlgemuth <curtw@google.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Reported-by: Jim Meyering <jim@meyering.net>
+Reported-by: Hugh Dickins <hughd@google.com>
+Cc: Mingming Cao <cmm@us.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ext4/page-io.c | 37 ++++++++++---------------------------
+ 1 file changed, 10 insertions(+), 27 deletions(-)
+
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -203,46 +203,29 @@ static void ext4_end_bio(struct bio *bio
+ for (i = 0; i < io_end->num_io_pages; i++) {
+ struct page *page = io_end->pages[i]->p_page;
+ struct buffer_head *bh, *head;
+- int partial_write = 0;
++ loff_t offset;
++ loff_t io_end_offset;
+
+- head = page_buffers(page);
+- if (error)
++ if (error) {
+ SetPageError(page);
+- BUG_ON(!head);
+- if (head->b_size != PAGE_CACHE_SIZE) {
+- loff_t offset;
+- loff_t io_end_offset = io_end->offset + io_end->size;
++ set_bit(AS_EIO, &page->mapping->flags);
++ head = page_buffers(page);
++ BUG_ON(!head);
++
++ io_end_offset = io_end->offset + io_end->size;
+
+ offset = (sector_t) page->index << PAGE_CACHE_SHIFT;
+ bh = head;
+ do {
+ if ((offset >= io_end->offset) &&
+- (offset+bh->b_size <= io_end_offset)) {
+- if (error)
+- buffer_io_error(bh);
++ (offset+bh->b_size <= io_end_offset))
++ buffer_io_error(bh);
+
+- }
+- if (buffer_delay(bh))
+- partial_write = 1;
+- else if (!buffer_mapped(bh))
+- clear_buffer_dirty(bh);
+- else if (buffer_dirty(bh))
+- partial_write = 1;
+ offset += bh->b_size;
+ bh = bh->b_this_page;
+ } while (bh != head);
+ }
+
+- /*
+- * If this is a partial write which happened to make
+- * all buffers uptodate then we can optimize away a
+- * bogus readpage() for the next read(). Here we
+- * 'discover' whether the page went uptodate as a
+- * result of this (potentially partial) write.
+- */
+- if (!partial_write)
+- SetPageUptodate(page);
+-
+ put_io_page(io_end->pages[i]);
+ }
+ io_end->num_io_pages = 0;
diff --git a/queue-2.6.39/mtd-mtdconcat-fix-nand-oob-write.patch b/queue-2.6.39/mtd-mtdconcat-fix-nand-oob-write.patch
new file mode 100644
index 0000000000..810a5a214e
--- /dev/null
+++ b/queue-2.6.39/mtd-mtdconcat-fix-nand-oob-write.patch
@@ -0,0 +1,42 @@
+From 431e1ecabddcd7cbba237182ddf431771f98bb4c Mon Sep 17 00:00:00 2001
+From: Felix Radensky <felix@embedded-sol.com>
+Date: Mon, 25 Apr 2011 01:57:12 +0300
+Subject: mtd: mtdconcat: fix NAND OOB write
+
+From: Felix Radensky <felix@embedded-sol.com>
+
+commit 431e1ecabddcd7cbba237182ddf431771f98bb4c upstream.
+
+Currently mtdconcat is broken for NAND. An attemtpt to create
+JFFS2 filesystem on concatenation of several NAND devices fails
+with OOB write errors. This patch fixes that problem.
+
+Signed-off-by: Felix Radensky <felix@embedded-sol.com>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/mtd/mtdconcat.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/mtdconcat.c
++++ b/drivers/mtd/mtdconcat.c
+@@ -319,7 +319,7 @@ concat_write_oob(struct mtd_info *mtd, l
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+- ops->retlen = 0;
++ ops->retlen = ops->oobretlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+@@ -334,7 +334,7 @@ concat_write_oob(struct mtd_info *mtd, l
+ devops.len = subdev->size - to;
+
+ err = subdev->write_oob(subdev, to, &devops);
+- ops->retlen += devops.retlen;
++ ops->retlen += devops.oobretlen;
+ if (err)
+ return err;
+
diff --git a/queue-2.6.39/mtd-omap-fix-subpage-ecc-issue-with-prefetch.patch b/queue-2.6.39/mtd-omap-fix-subpage-ecc-issue-with-prefetch.patch
new file mode 100644
index 0000000000..63d5265271
--- /dev/null
+++ b/queue-2.6.39/mtd-omap-fix-subpage-ecc-issue-with-prefetch.patch
@@ -0,0 +1,72 @@
+From c5d8c0cae4af7d78823d32fcd1c458ee1a1b5489 Mon Sep 17 00:00:00 2001
+From: Kishore Kadiyala <kishore.kadiyala@ti.com>
+Date: Wed, 11 May 2011 21:17:27 +0530
+Subject: mtd: omap: fix subpage ecc issue with prefetch
+
+From: Kishore Kadiyala <kishore.kadiyala@ti.com>
+
+commit c5d8c0cae4af7d78823d32fcd1c458ee1a1b5489 upstream.
+
+When reading/writing a subpage (When HW ECC is not available/enabled)
+for number of bytes not aligned to 4, the mis-aligned bytes are handled
+first (by cpu copy method) before enabling the Prefetch engine to/from
+'p'(start of buffer 'buf'). Then it reads/writes rest of the bytes with
+the help of Prefetch engine, if available, or again using cpu copy method.
+Currently, reading/writing of rest of bytes, is not done correctly since
+its trying to read/write again to/from begining of buffer 'buf',
+overwriting the mis-aligned bytes.
+
+Read & write using prefetch engine got broken in commit '2c01946c'.
+We never hit a scenario of not getting 'gpmc_prefetch_enable' call
+success. So, problem did not get caught up.
+
+Signed-off-by: Kishore Kadiyala <kishore.kadiyala@ti.com>
+Signed-off-by: Vimal Singh <vimal.newwork@gmail.com>
+Reported-by: Bryan DE FARIA <bdefaria@adeneo-embedded.com>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/mtd/nand/omap2.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/mtd/nand/omap2.c
++++ b/drivers/mtd/nand/omap2.c
+@@ -263,11 +263,10 @@ static void omap_read_buf_pref(struct mt
+ if (ret) {
+ /* PFPW engine is busy, use cpu copy method */
+ if (info->nand.options & NAND_BUSWIDTH_16)
+- omap_read_buf16(mtd, buf, len);
++ omap_read_buf16(mtd, (u_char *)p, len);
+ else
+- omap_read_buf8(mtd, buf, len);
++ omap_read_buf8(mtd, (u_char *)p, len);
+ } else {
+- p = (u32 *) buf;
+ do {
+ r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+ r_count = r_count >> 2;
+@@ -293,7 +292,7 @@ static void omap_write_buf_pref(struct m
+ struct omap_nand_info, mtd);
+ uint32_t w_count = 0;
+ int i = 0, ret = 0;
+- u16 *p;
++ u16 *p = (u16 *)buf;
+ unsigned long tim, limit;
+
+ /* take care of subpage writes */
+@@ -309,11 +308,10 @@ static void omap_write_buf_pref(struct m
+ if (ret) {
+ /* PFPW engine is busy, use cpu copy method */
+ if (info->nand.options & NAND_BUSWIDTH_16)
+- omap_write_buf16(mtd, buf, len);
++ omap_write_buf16(mtd, (u_char *)p, len);
+ else
+- omap_write_buf8(mtd, buf, len);
++ omap_write_buf8(mtd, (u_char *)p, len);
+ } else {
+- p = (u16 *) buf;
+ while (len) {
+ w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+ w_count = w_count >> 1;
diff --git a/queue-2.6.39/mtd-return-badblockbits-back.patch b/queue-2.6.39/mtd-return-badblockbits-back.patch
new file mode 100644
index 0000000000..da7cef0b0e
--- /dev/null
+++ b/queue-2.6.39/mtd-return-badblockbits-back.patch
@@ -0,0 +1,39 @@
+From 26d9be11485ea8c1102c3e8eaa7667412eef4950 Mon Sep 17 00:00:00 2001
+From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Date: Thu, 28 Apr 2011 20:26:59 +0300
+Subject: mtd: return badblockbits back
+
+From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+
+commit 26d9be11485ea8c1102c3e8eaa7667412eef4950 upstream.
+
+In commit c7b28e25cb9beb943aead770ff14551b55fa8c79 the initialization of
+the backblockbits was accidentally removed. This patch returns it back,
+because otherwise some NAND drivers are broken.
+
+This problem was reported by "Saxena, Parth <parth.saxena@ti.com>" here:
+http://lists.infradead.org/pipermail/linux-mtd/2011-April/035221.html
+
+Reported-by: Saxena, Parth <parth.saxena@ti.com>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Tested-by: Saxena, Parth <parth.saxena@ti.com>
+Acked-by: Saxena, Parth <parth.saxena@ti.com>
+Acked-by: Brian Norris <computersforpeace@gmail.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/mtd/nand/nand_base.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/mtd/nand/nand_base.c
++++ b/drivers/mtd/nand/nand_base.c
+@@ -3112,6 +3112,8 @@ ident_done:
+ chip->chip_shift += 32 - 1;
+ }
+
++ chip->badblockbits = 8;
++
+ /* Set the bad block position */
+ if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16))
+ chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
diff --git a/queue-2.6.39/series b/queue-2.6.39/series
index 30951c7540..47ccaa28ab 100644
--- a/queue-2.6.39/series
+++ b/queue-2.6.39/series
@@ -20,3 +20,13 @@ ath9k_hw-fix-dual-band-assumption-for-xb113.patch
ath9k_hw-fix-sta-connection-issues-with-ar9380-xb113.patch
powerpc-oprofile-handle-events-that-raise-an-exception-without-overflowing.patch
iwlagn-fix-iwl_is_any_associated.patch
+ext4-don-t-set-pageuptodate-in-ext4_end_bio.patch
+block-move-bd_set_size-above-rescan_partitions-in.patch
+block-add-a-non-queueable-flush-flag.patch
+block-hold-queue-if-flush-is-running-for-non-queueable.patch
+block-fix-discard-topology-stacking-and-reporting.patch
+block-add-proper-state-guards-to-__elv_next_request.patch
+block-always-allocate-genhd-ev-if-check_events-is.patch
+mtd-mtdconcat-fix-nand-oob-write.patch
+mtd-return-badblockbits-back.patch
+mtd-omap-fix-subpage-ecc-issue-with-prefetch.patch