--- /dev/null
+From 17be8c245054b9c7786545af3ba3ca4e54cd4ad9 Mon Sep 17 00:00:00 2001
+From: Martin K. Petersen <martin.petersen@oracle.com>
+Date: Mon, 11 Jan 2010 03:21:49 -0500
+Subject: block: bdev_stack_limits wrapper
+
+From: Martin K. Petersen <martin.petersen@oracle.com>
+
+commit 17be8c245054b9c7786545af3ba3ca4e54cd4ad9 upstream.
+
+DM does not want to know about partition offsets. Add a partition-aware
+wrapper that DM can use when stacking block devices.
+
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Mike Snitzer <snitzer@redhat.com>
+Reviewed-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ block/blk-settings.c | 22 ++++++++++++++++++++++
+ include/linux/blkdev.h | 2 ++
+ 2 files changed, 24 insertions(+)
+
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -560,6 +560,28 @@ int blk_stack_limits(struct queue_limits
+ EXPORT_SYMBOL(blk_stack_limits);
+
+ /**
++ * bdev_stack_limits - adjust queue limits for stacked drivers
++ * @t: the stacking driver limits (top device)
++ * @bdev: the component block_device (bottom)
++ * @start: first data sector within component device
++ *
++ * Description:
++ * Merges queue limits for a top device and a block_device. Returns
++ * 0 if alignment didn't change. Returns -1 if adding the bottom
++ * device caused misalignment.
++ */
++int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev,
++ sector_t start)
++{
++ struct request_queue *bq = bdev_get_queue(bdev);
++
++ start += get_start_sect(bdev);
++
++ return blk_stack_limits(t, &bq->limits, start << 9);
++}
++EXPORT_SYMBOL(bdev_stack_limits);
++
++/**
+ * disk_stack_limits - adjust queue limits for stacked drivers
+ * @disk: MD/DM gendisk (top)
+ * @bdev: the underlying block device (bottom)
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -942,6 +942,8 @@ extern void blk_queue_io_opt(struct requ
+ extern void blk_set_default_limits(struct queue_limits *lim);
+ extern int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
+ sector_t offset);
++extern int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev,
++ sector_t offset);
+ extern void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
+ sector_t offset);
+ extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b);
--- /dev/null
+From b27d7f16d3c6c27345d4280a739809c1c2c4c0b5 Mon Sep 17 00:00:00 2001
+From: Martin K. Petersen <martin.petersen@oracle.com>
+Date: Mon, 11 Jan 2010 03:21:50 -0500
+Subject: DM: Fix device mapper topology stacking
+
+From: Martin K. Petersen <martin.petersen@oracle.com>
+
+commit b27d7f16d3c6c27345d4280a739809c1c2c4c0b5 upstream.
+
+Make DM use bdev_stack_limits() function so that partition offsets get
+taken into account when calculating alignment. Clarify stacking
+warnings.
+
+Also remove obsolete clearing of final alignment_offset and misalignment
+flag.
+
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Cc: Alasdair G. Kergon <agk@redhat.com>
+Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-table.c | 20 +++++---------------
+ 1 file changed, 5 insertions(+), 15 deletions(-)
+
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -499,16 +499,15 @@ int dm_set_device_limits(struct dm_targe
+ return 0;
+ }
+
+- if (blk_stack_limits(limits, &q->limits, start << 9) < 0)
+- DMWARN("%s: target device %s is misaligned: "
++ if (bdev_stack_limits(limits, bdev, start) < 0)
++ DMWARN("%s: adding target device %s caused an alignment inconsistency: "
+ "physical_block_size=%u, logical_block_size=%u, "
+ "alignment_offset=%u, start=%llu",
+ dm_device_name(ti->table->md), bdevname(bdev, b),
+ q->limits.physical_block_size,
+ q->limits.logical_block_size,
+ q->limits.alignment_offset,
+- (unsigned long long) start << 9);
+-
++ (unsigned long long) start << SECTOR_SHIFT);
+
+ /*
+ * Check if merge fn is supported.
+@@ -1025,9 +1024,9 @@ combine_limits:
+ * for the table.
+ */
+ if (blk_stack_limits(limits, &ti_limits, 0) < 0)
+- DMWARN("%s: target device "
++ DMWARN("%s: adding target device "
+ "(start sect %llu len %llu) "
+- "is misaligned",
++ "caused an alignment inconsistency",
+ dm_device_name(table->md),
+ (unsigned long long) ti->begin,
+ (unsigned long long) ti->len);
+@@ -1079,15 +1078,6 @@ void dm_table_set_restrictions(struct dm
+ struct queue_limits *limits)
+ {
+ /*
+- * Each target device in the table has a data area that should normally
+- * be aligned such that the DM device's alignment_offset is 0.
+- * FIXME: Propagate alignment_offsets up the stack and warn of
+- * sub-optimal or inconsistent settings.
+- */
+- limits->alignment_offset = 0;
+- limits->misaligned = 0;
+-
+- /*
+ * Copy table's limits to the DM device's request_queue
+ */
+ q->limits = *limits;