aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2011-08-02 07:32:04 -0400
committerAlasdair G Kergon <agk@redhat.com>2011-08-02 07:32:04 -0400
commitd5b9dd04bd74b774b8e8d93ced7a0d15ad403fa9 (patch)
tree060512c4c411e4adda203fd721b79b50b0ff54df /drivers/md/dm.c
parent08649012545cfb116798260352547cf4d47064ec (diff)
dm: ignore merge_bvec for snapshots when safe
Add a new flag DMF_MERGE_IS_OPTIONAL to struct mapped_device to indicate whether the device can accept bios larger than the size its merge function returns. When set, use this to send large bios to snapshots which can split them if necessary. Snapshot I/O may be significantly fragmented and this approach seems to improve peformance. Before the patch, dm_set_device_limits restricted bio size to page size if the underlying device had a merge function and the target didn't provide a merge function. After the patch, dm_set_device_limits restricts bio size to page size if the underlying device has a merge function, doesn't have DMF_MERGE_IS_OPTIONAL flag and the target doesn't provide a merge function. The snapshot target can't provide a merge function because when the merge function is called, it is impossible to determine where the bio will be remapped. Previously this led us to impose a 4k limit, which we can now remove if the snapshot store is located on a device without a merge function. Together with another patch for optimizing full chunk writes, it improves performance from 29MB/s to 40MB/s when writing to the filesystem on snapshot store. If the snapshot store is placed on a non-dm device with a merge function (such as md-raid), device mapper still limits all bios to page size. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r--drivers/md/dm.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index aeb0fa1ccfe4..1000eaf984ef 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -111,6 +111,7 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
111#define DMF_FREEING 3 111#define DMF_FREEING 3
112#define DMF_DELETING 4 112#define DMF_DELETING 4
113#define DMF_NOFLUSH_SUSPENDING 5 113#define DMF_NOFLUSH_SUSPENDING 5
114#define DMF_MERGE_IS_OPTIONAL 6
114 115
115/* 116/*
116 * Work processed by per-device workqueue. 117 * Work processed by per-device workqueue.
@@ -1993,6 +1994,59 @@ static void __set_size(struct mapped_device *md, sector_t size)
1993} 1994}
1994 1995
1995/* 1996/*
1997 * Return 1 if the queue has a compulsory merge_bvec_fn function.
1998 *
1999 * If this function returns 0, then the device is either a non-dm
2000 * device without a merge_bvec_fn, or it is a dm device that is
2001 * able to split any bios it receives that are too big.
2002 */
2003int dm_queue_merge_is_compulsory(struct request_queue *q)
2004{
2005 struct mapped_device *dev_md;
2006
2007 if (!q->merge_bvec_fn)
2008 return 0;
2009
2010 if (q->make_request_fn == dm_request) {
2011 dev_md = q->queuedata;
2012 if (test_bit(DMF_MERGE_IS_OPTIONAL, &dev_md->flags))
2013 return 0;
2014 }
2015
2016 return 1;
2017}
2018
2019static int dm_device_merge_is_compulsory(struct dm_target *ti,
2020 struct dm_dev *dev, sector_t start,
2021 sector_t len, void *data)
2022{
2023 struct block_device *bdev = dev->bdev;
2024 struct request_queue *q = bdev_get_queue(bdev);
2025
2026 return dm_queue_merge_is_compulsory(q);
2027}
2028
2029/*
2030 * Return 1 if it is acceptable to ignore merge_bvec_fn based
2031 * on the properties of the underlying devices.
2032 */
2033static int dm_table_merge_is_optional(struct dm_table *table)
2034{
2035 unsigned i = 0;
2036 struct dm_target *ti;
2037
2038 while (i < dm_table_get_num_targets(table)) {
2039 ti = dm_table_get_target(table, i++);
2040
2041 if (ti->type->iterate_devices &&
2042 ti->type->iterate_devices(ti, dm_device_merge_is_compulsory, NULL))
2043 return 0;
2044 }
2045
2046 return 1;
2047}
2048
2049/*
1996 * Returns old map, which caller must destroy. 2050 * Returns old map, which caller must destroy.
1997 */ 2051 */
1998static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, 2052static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
@@ -2002,6 +2056,7 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
2002 struct request_queue *q = md->queue; 2056 struct request_queue *q = md->queue;
2003 sector_t size; 2057 sector_t size;
2004 unsigned long flags; 2058 unsigned long flags;
2059 int merge_is_optional;
2005 2060
2006 size = dm_table_get_size(t); 2061 size = dm_table_get_size(t);
2007 2062
@@ -2027,10 +2082,16 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
2027 2082
2028 __bind_mempools(md, t); 2083 __bind_mempools(md, t);
2029 2084
2085 merge_is_optional = dm_table_merge_is_optional(t);
2086
2030 write_lock_irqsave(&md->map_lock, flags); 2087 write_lock_irqsave(&md->map_lock, flags);
2031 old_map = md->map; 2088 old_map = md->map;
2032 md->map = t; 2089 md->map = t;
2033 dm_table_set_restrictions(t, q, limits); 2090 dm_table_set_restrictions(t, q, limits);
2091 if (merge_is_optional)
2092 set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
2093 else
2094 clear_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
2034 write_unlock_irqrestore(&md->map_lock, flags); 2095 write_unlock_irqrestore(&md->map_lock, flags);
2035 2096
2036 return old_map; 2097 return old_map;