summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-09-07 15:07:55 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-09-07 15:07:55 -0400
commitfac805f8c198092de9a2842efd7f5022e2937b18 (patch)
tree7557809c373f97a343c427d8fded0696060394ce /drivers/md/dm.c
parent2461c7d60f9f3821274e4acf9019cba8b82c94b5 (diff)
parentf10723841e624c0726c70356b31d91befed01dd6 (diff)
downloadtalos-obmc-linux-fac805f8c198092de9a2842efd7f5022e2937b18.tar.gz
talos-obmc-linux-fac805f8c198092de9a2842efd7f5022e2937b18.zip
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r--drivers/md/dm.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index e24143cc2040..4e09b6ff5b49 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -968,22 +968,41 @@ static sector_t max_io_len_target_boundary(sector_t sector, struct dm_target *ti
static sector_t max_io_len(sector_t sector, struct dm_target *ti)
{
sector_t len = max_io_len_target_boundary(sector, ti);
+ sector_t offset, max_len;
/*
- * Does the target need to split even further ?
+ * Does the target need to split even further?
*/
- if (ti->split_io) {
- sector_t boundary;
- sector_t offset = dm_target_offset(ti, sector);
- boundary = ((offset + ti->split_io) & ~(ti->split_io - 1))
- - offset;
- if (len > boundary)
- len = boundary;
+ if (ti->max_io_len) {
+ offset = dm_target_offset(ti, sector);
+ if (unlikely(ti->max_io_len & (ti->max_io_len - 1)))
+ max_len = sector_div(offset, ti->max_io_len);
+ else
+ max_len = offset & (ti->max_io_len - 1);
+ max_len = ti->max_io_len - max_len;
+
+ if (len > max_len)
+ len = max_len;
}
return len;
}
+int dm_set_target_max_io_len(struct dm_target *ti, sector_t len)
+{
+ if (len > UINT_MAX) {
+ DMERR("Specified maximum size of target IO (%llu) exceeds limit (%u)",
+ (unsigned long long)len, UINT_MAX);
+ ti->error = "Maximum size of target IO is too large";
+ return -EINVAL;
+ }
+
+ ti->max_io_len = (uint32_t) len;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dm_set_target_max_io_len);
+
static void __map_bio(struct dm_target *ti, struct bio *clone,
struct dm_target_io *tio)
{
@@ -1196,7 +1215,10 @@ static int __clone_and_map_discard(struct clone_info *ci)
if (!ti->num_discard_requests)
return -EOPNOTSUPP;
- len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti));
+ if (!ti->split_discard_requests)
+ len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti));
+ else
+ len = min(ci->sector_count, max_io_len(ci->sector, ti));
__issue_target_requests(ci, ti, ti->num_discard_requests, len);
OpenPOWER on IntegriCloud