diff options
Diffstat (limited to 'drivers/md/dm.c')
| -rw-r--r-- | drivers/md/dm.c | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 6a5e9ed2fcc3..b3e26c7d1417 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -211,10 +211,55 @@ struct dm_md_mempools { | |||
| 211 | struct bio_set *bs; | 211 | struct bio_set *bs; |
| 212 | }; | 212 | }; |
| 213 | 213 | ||
| 214 | #define MIN_IOS 256 | 214 | #define RESERVED_BIO_BASED_IOS 16 |
| 215 | #define RESERVED_REQUEST_BASED_IOS 256 | ||
| 216 | #define RESERVED_MAX_IOS 1024 | ||
| 215 | static struct kmem_cache *_io_cache; | 217 | static struct kmem_cache *_io_cache; |
| 216 | static struct kmem_cache *_rq_tio_cache; | 218 | static struct kmem_cache *_rq_tio_cache; |
| 217 | 219 | ||
| 220 | /* | ||
| 221 | * Bio-based DM's mempools' reserved IOs set by the user. | ||
| 222 | */ | ||
| 223 | static unsigned reserved_bio_based_ios = RESERVED_BIO_BASED_IOS; | ||
| 224 | |||
| 225 | /* | ||
| 226 | * Request-based DM's mempools' reserved IOs set by the user. | ||
| 227 | */ | ||
| 228 | static unsigned reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS; | ||
| 229 | |||
| 230 | static unsigned __dm_get_reserved_ios(unsigned *reserved_ios, | ||
| 231 | unsigned def, unsigned max) | ||
| 232 | { | ||
| 233 | unsigned ios = ACCESS_ONCE(*reserved_ios); | ||
| 234 | unsigned modified_ios = 0; | ||
| 235 | |||
| 236 | if (!ios) | ||
| 237 | modified_ios = def; | ||
| 238 | else if (ios > max) | ||
| 239 | modified_ios = max; | ||
| 240 | |||
| 241 | if (modified_ios) { | ||
| 242 | (void)cmpxchg(reserved_ios, ios, modified_ios); | ||
| 243 | ios = modified_ios; | ||
| 244 | } | ||
| 245 | |||
| 246 | return ios; | ||
| 247 | } | ||
| 248 | |||
| 249 | unsigned dm_get_reserved_bio_based_ios(void) | ||
| 250 | { | ||
| 251 | return __dm_get_reserved_ios(&reserved_bio_based_ios, | ||
| 252 | RESERVED_BIO_BASED_IOS, RESERVED_MAX_IOS); | ||
| 253 | } | ||
| 254 | EXPORT_SYMBOL_GPL(dm_get_reserved_bio_based_ios); | ||
| 255 | |||
| 256 | unsigned dm_get_reserved_rq_based_ios(void) | ||
| 257 | { | ||
| 258 | return __dm_get_reserved_ios(&reserved_rq_based_ios, | ||
| 259 | RESERVED_REQUEST_BASED_IOS, RESERVED_MAX_IOS); | ||
| 260 | } | ||
| 261 | EXPORT_SYMBOL_GPL(dm_get_reserved_rq_based_ios); | ||
| 262 | |||
| 218 | static int __init local_init(void) | 263 | static int __init local_init(void) |
| 219 | { | 264 | { |
| 220 | int r = -ENOMEM; | 265 | int r = -ENOMEM; |
| @@ -2278,6 +2323,17 @@ struct target_type *dm_get_immutable_target_type(struct mapped_device *md) | |||
| 2278 | } | 2323 | } |
| 2279 | 2324 | ||
| 2280 | /* | 2325 | /* |
| 2326 | * The queue_limits are only valid as long as you have a reference | ||
| 2327 | * count on 'md'. | ||
| 2328 | */ | ||
| 2329 | struct queue_limits *dm_get_queue_limits(struct mapped_device *md) | ||
| 2330 | { | ||
| 2331 | BUG_ON(!atomic_read(&md->holders)); | ||
| 2332 | return &md->queue->limits; | ||
| 2333 | } | ||
| 2334 | EXPORT_SYMBOL_GPL(dm_get_queue_limits); | ||
| 2335 | |||
| 2336 | /* | ||
| 2281 | * Fully initialize a request-based queue (->elevator, ->request_fn, etc). | 2337 | * Fully initialize a request-based queue (->elevator, ->request_fn, etc). |
| 2282 | */ | 2338 | */ |
| 2283 | static int dm_init_request_based_queue(struct mapped_device *md) | 2339 | static int dm_init_request_based_queue(struct mapped_device *md) |
| @@ -2862,18 +2918,18 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, u | |||
| 2862 | 2918 | ||
| 2863 | if (type == DM_TYPE_BIO_BASED) { | 2919 | if (type == DM_TYPE_BIO_BASED) { |
| 2864 | cachep = _io_cache; | 2920 | cachep = _io_cache; |
| 2865 | pool_size = 16; | 2921 | pool_size = dm_get_reserved_bio_based_ios(); |
| 2866 | front_pad = roundup(per_bio_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone); | 2922 | front_pad = roundup(per_bio_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone); |
| 2867 | } else if (type == DM_TYPE_REQUEST_BASED) { | 2923 | } else if (type == DM_TYPE_REQUEST_BASED) { |
| 2868 | cachep = _rq_tio_cache; | 2924 | cachep = _rq_tio_cache; |
| 2869 | pool_size = MIN_IOS; | 2925 | pool_size = dm_get_reserved_rq_based_ios(); |
| 2870 | front_pad = offsetof(struct dm_rq_clone_bio_info, clone); | 2926 | front_pad = offsetof(struct dm_rq_clone_bio_info, clone); |
| 2871 | /* per_bio_data_size is not used. See __bind_mempools(). */ | 2927 | /* per_bio_data_size is not used. See __bind_mempools(). */ |
| 2872 | WARN_ON(per_bio_data_size != 0); | 2928 | WARN_ON(per_bio_data_size != 0); |
| 2873 | } else | 2929 | } else |
| 2874 | goto out; | 2930 | goto out; |
| 2875 | 2931 | ||
| 2876 | pools->io_pool = mempool_create_slab_pool(MIN_IOS, cachep); | 2932 | pools->io_pool = mempool_create_slab_pool(pool_size, cachep); |
| 2877 | if (!pools->io_pool) | 2933 | if (!pools->io_pool) |
| 2878 | goto out; | 2934 | goto out; |
| 2879 | 2935 | ||
| @@ -2924,6 +2980,13 @@ module_exit(dm_exit); | |||
| 2924 | 2980 | ||
| 2925 | module_param(major, uint, 0); | 2981 | module_param(major, uint, 0); |
| 2926 | MODULE_PARM_DESC(major, "The major number of the device mapper"); | 2982 | MODULE_PARM_DESC(major, "The major number of the device mapper"); |
| 2983 | |||
| 2984 | module_param(reserved_bio_based_ios, uint, S_IRUGO | S_IWUSR); | ||
| 2985 | MODULE_PARM_DESC(reserved_bio_based_ios, "Reserved IOs in bio-based mempools"); | ||
| 2986 | |||
| 2987 | module_param(reserved_rq_based_ios, uint, S_IRUGO | S_IWUSR); | ||
| 2988 | MODULE_PARM_DESC(reserved_rq_based_ios, "Reserved IOs in request-based mempools"); | ||
| 2989 | |||
| 2927 | MODULE_DESCRIPTION(DM_NAME " driver"); | 2990 | MODULE_DESCRIPTION(DM_NAME " driver"); |
| 2928 | MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>"); | 2991 | MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>"); |
| 2929 | MODULE_LICENSE("GPL"); | 2992 | MODULE_LICENSE("GPL"); |
