Blame view

drivers/md/dm.c 75.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
784aae735   Milan Broz   dm: add name and ...
3
   * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
   *
   * This file is released under the GPL.
   */
4cc96131a   Mike Snitzer   dm: move request-...
7
8
  #include "dm-core.h"
  #include "dm-rq.h"
51e5b2bd3   Mike Anderson   dm: add uevent to...
9
  #include "dm-uevent.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
  
  #include <linux/init.h>
  #include <linux/module.h>
48c9c27b8   Arjan van de Ven   [PATCH] sem2mutex...
13
  #include <linux/mutex.h>
6958c1c64   Mikulas Patocka   dm: use noio when...
14
  #include <linux/sched/mm.h>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
15
  #include <linux/sched/signal.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
  #include <linux/blkpg.h>
  #include <linux/bio.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/mempool.h>
f26c5719b   Dan Williams   dm: add dax_devic...
19
  #include <linux/dax.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  #include <linux/slab.h>
  #include <linux/idr.h>
7e026c8c0   Dan Williams   dm: add ->copy_fr...
22
  #include <linux/uio.h>
3ac51e741   Darrick J. Wong   [PATCH] dm store ...
23
  #include <linux/hdreg.h>
3f77316de   Kiyoshi Ueda   dm: separate devi...
24
  #include <linux/delay.h>
ffcc39364   Mike Snitzer   dm: enhance inter...
25
  #include <linux/wait.h>
71cdb6978   Christoph Hellwig   dm: add support f...
26
  #include <linux/pr.h>
b0b4d7c67   Elena Reshetova   dm: convert table...
27
  #include <linux/refcount.h>
c6a564ffa   Christoph Hellwig   block: move the p...
28
  #include <linux/part_stat.h>
bea2b9641   Eric Biggers   ANDROID: dm: add ...
29
30
  #include <linux/blk-crypto.h>
  #include <linux/keyslot-manager.h>
55782138e   Li Zefan   tracing/events: c...
31

72d948616   Alasdair G Kergon   [PATCH] dm: impro...
32
  #define DM_MSG_PREFIX "core"
60935eb21   Milan Broz   dm ioctl: support...
33
34
35
36
37
38
  /*
   * Cookies are numeric values sent with CHANGE and REMOVE
   * uevents while resuming, removing or renaming the device.
   */
  #define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE"
  #define DM_COOKIE_LENGTH 24
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
  static const char *_name = DM_NAME;
  
  static unsigned int major = 0;
  static unsigned int _major = 0;
d15b774c2   Alasdair G Kergon   dm: fix idr leak ...
43
  static DEFINE_IDR(_minor_idr);
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
44
  static DEFINE_SPINLOCK(_minor_lock);
2c140a246   Mikulas Patocka   dm: allow remove ...
45
46
47
48
  
  static void do_deferred_remove(struct work_struct *w);
  
  static DECLARE_WORK(deferred_remove_work, do_deferred_remove);
acfe0ad74   Mikulas Patocka   dm: allocate a sp...
49
  static struct workqueue_struct *deferred_remove_workqueue;
93e6442c7   Mikulas Patocka   dm: add basic sup...
50
51
  atomic_t dm_global_event_nr = ATOMIC_INIT(0);
  DECLARE_WAIT_QUEUE_HEAD(dm_global_eventq);
62e082430   Mikulas Patocka   dm ioctl: fix ali...
52
53
54
55
56
  void dm_issue_global_event(void)
  {
  	atomic_inc(&dm_global_event_nr);
  	wake_up(&dm_global_eventq);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  /*
64f52b0e3   Mike Snitzer   dm: improve perfo...
58
   * One of these is allocated (on-stack) per original bio.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
   */
64f52b0e3   Mike Snitzer   dm: improve perfo...
60
  struct clone_info {
64f52b0e3   Mike Snitzer   dm: improve perfo...
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  	struct dm_table *map;
  	struct bio *bio;
  	struct dm_io *io;
  	sector_t sector;
  	unsigned sector_count;
  };
  
  /*
   * One of these is allocated per clone bio.
   */
  #define DM_TIO_MAGIC 7282014
  struct dm_target_io {
  	unsigned magic;
  	struct dm_io *io;
  	struct dm_target *ti;
  	unsigned target_bio_nr;
  	unsigned *len_ptr;
  	bool inside_dm_io;
  	struct bio clone;
  };
  
  /*
745dc570b   Mike Snitzer   dm: rename 'bio' ...
83
   * One of these is allocated per original bio.
64f52b0e3   Mike Snitzer   dm: improve perfo...
84
   * It contains the first clone used for that original.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
   */
64f52b0e3   Mike Snitzer   dm: improve perfo...
86
  #define DM_IO_MAGIC 5191977
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  struct dm_io {
64f52b0e3   Mike Snitzer   dm: improve perfo...
88
  	unsigned magic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  	struct mapped_device *md;
4e4cbee93   Christoph Hellwig   block: switch bio...
90
  	blk_status_t status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  	atomic_t io_count;
745dc570b   Mike Snitzer   dm: rename 'bio' ...
92
  	struct bio *orig_bio;
3eaf840e0   Jun'ichi "Nick" Nomura   [PATCH] device-ma...
93
  	unsigned long start_time;
f88fb9811   Kiyoshi Ueda   dm: dec_pending n...
94
  	spinlock_t endio_lock;
fd2ed4d25   Mikulas Patocka   dm: add statistic...
95
  	struct dm_stats_aux stats_aux;
64f52b0e3   Mike Snitzer   dm: improve perfo...
96
97
  	/* last member of dm_target_io is 'struct bio' */
  	struct dm_target_io tio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  };
64f52b0e3   Mike Snitzer   dm: improve perfo...
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  void *dm_per_bio_data(struct bio *bio, size_t data_size)
  {
  	struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
  	if (!tio->inside_dm_io)
  		return (char *)bio - offsetof(struct dm_target_io, clone) - data_size;
  	return (char *)bio - offsetof(struct dm_target_io, clone) - offsetof(struct dm_io, tio) - data_size;
  }
  EXPORT_SYMBOL_GPL(dm_per_bio_data);
  
  struct bio *dm_bio_from_per_bio_data(void *data, size_t data_size)
  {
  	struct dm_io *io = (struct dm_io *)((char *)data + data_size);
  	if (io->magic == DM_IO_MAGIC)
  		return (struct bio *)((char *)io + offsetof(struct dm_io, tio) + offsetof(struct dm_target_io, clone));
  	BUG_ON(io->magic != DM_TIO_MAGIC);
  	return (struct bio *)((char *)io + offsetof(struct dm_target_io, clone));
  }
  EXPORT_SYMBOL_GPL(dm_bio_from_per_bio_data);
  
  unsigned dm_bio_get_target_bio_nr(const struct bio *bio)
  {
  	return container_of(bio, struct dm_target_io, clone)->target_bio_nr;
  }
  EXPORT_SYMBOL_GPL(dm_bio_get_target_bio_nr);
ba61fdd17   Jeff Mahoney   [PATCH] dm: fix i...
123
  #define MINOR_ALLOCED ((void *)-1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
  /*
   * Bits for the md->flags field.
   */
1eb787ec1   Alasdair G Kergon   dm: split DMF_BLO...
127
  #define DMF_BLOCK_IO_FOR_SUSPEND 0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  #define DMF_SUSPENDED 1
aa8d7c2fb   Alasdair G Kergon   [PATCH] device-ma...
129
  #define DMF_FROZEN 2
fba9f90e5   Jeff Mahoney   [PATCH] dm: add D...
130
  #define DMF_FREEING 3
5c6bd75d0   Alasdair G Kergon   [PATCH] dm: preve...
131
  #define DMF_DELETING 4
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
132
  #define DMF_NOFLUSH_SUSPENDING 5
8ae126660   Kent Overstreet   block: kill merge...
133
134
  #define DMF_DEFERRED_REMOVE 6
  #define DMF_SUSPENDED_INTERNALLY 7
5df96f2b9   Mikulas Patocka   dm integrity: fix...
135
  #define DMF_POST_SUSPENDING 8
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136

115485e83   Mike Snitzer   dm: add 'dm_numa_...
137
  #define DM_NUMA_NODE NUMA_NO_NODE
115485e83   Mike Snitzer   dm: add 'dm_numa_...
138
  static int dm_numa_node = DM_NUMA_NODE;
faad87df4   Mike Snitzer   dm: add 'dm_mq_nr...
139

e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
140
141
142
143
  /*
   * For mempools pre-allocation at the table loading time.
   */
  struct dm_md_mempools {
6f1c819c2   Kent Overstreet   dm: convert to bi...
144
145
  	struct bio_set bs;
  	struct bio_set io_bs;
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
146
  };
86f1152b1   Benjamin Marzinski   dm: allow active ...
147
148
  struct table_device {
  	struct list_head list;
b0b4d7c67   Elena Reshetova   dm: convert table...
149
  	refcount_t count;
86f1152b1   Benjamin Marzinski   dm: allow active ...
150
151
  	struct dm_dev dm_dev;
  };
f47908269   Mike Snitzer   dm: add reserved_...
152
  /*
e8603136c   Mike Snitzer   dm: add reserved_...
153
154
   * Bio-based DM's mempools' reserved IOs set by the user.
   */
4cc96131a   Mike Snitzer   dm: move request-...
155
  #define RESERVED_BIO_BASED_IOS		16
e8603136c   Mike Snitzer   dm: add reserved_...
156
  static unsigned reserved_bio_based_ios = RESERVED_BIO_BASED_IOS;
115485e83   Mike Snitzer   dm: add 'dm_numa_...
157
158
  static int __dm_get_module_param_int(int *module_param, int min, int max)
  {
6aa7de059   Mark Rutland   locking/atomics: ...
159
  	int param = READ_ONCE(*module_param);
115485e83   Mike Snitzer   dm: add 'dm_numa_...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  	int modified_param = 0;
  	bool modified = true;
  
  	if (param < min)
  		modified_param = min;
  	else if (param > max)
  		modified_param = max;
  	else
  		modified = false;
  
  	if (modified) {
  		(void)cmpxchg(module_param, param, modified_param);
  		param = modified_param;
  	}
  
  	return param;
  }
4cc96131a   Mike Snitzer   dm: move request-...
177
178
  unsigned __dm_get_module_param(unsigned *module_param,
  			       unsigned def, unsigned max)
f47908269   Mike Snitzer   dm: add reserved_...
179
  {
6aa7de059   Mark Rutland   locking/atomics: ...
180
  	unsigned param = READ_ONCE(*module_param);
09c2d5310   Mike Snitzer   dm: rename __dm_g...
181
  	unsigned modified_param = 0;
f47908269   Mike Snitzer   dm: add reserved_...
182

09c2d5310   Mike Snitzer   dm: rename __dm_g...
183
184
185
186
  	if (!param)
  		modified_param = def;
  	else if (param > max)
  		modified_param = max;
f47908269   Mike Snitzer   dm: add reserved_...
187

09c2d5310   Mike Snitzer   dm: rename __dm_g...
188
189
190
  	if (modified_param) {
  		(void)cmpxchg(module_param, param, modified_param);
  		param = modified_param;
f47908269   Mike Snitzer   dm: add reserved_...
191
  	}
09c2d5310   Mike Snitzer   dm: rename __dm_g...
192
  	return param;
f47908269   Mike Snitzer   dm: add reserved_...
193
  }
e8603136c   Mike Snitzer   dm: add reserved_...
194
195
  unsigned dm_get_reserved_bio_based_ios(void)
  {
09c2d5310   Mike Snitzer   dm: rename __dm_g...
196
  	return __dm_get_module_param(&reserved_bio_based_ios,
4cc96131a   Mike Snitzer   dm: move request-...
197
  				     RESERVED_BIO_BASED_IOS, DM_RESERVED_MAX_IOS);
e8603136c   Mike Snitzer   dm: add reserved_...
198
199
  }
  EXPORT_SYMBOL_GPL(dm_get_reserved_bio_based_ios);
115485e83   Mike Snitzer   dm: add 'dm_numa_...
200
201
202
203
204
  static unsigned dm_get_numa_node(void)
  {
  	return __dm_get_module_param_int(&dm_numa_node,
  					 DM_NUMA_NODE, num_online_nodes() - 1);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
  static int __init local_init(void)
  {
e689fbab3   Mike Snitzer   dm: remove unused...
207
  	int r;
1ae49ea2c   Mike Snitzer   dm: split request...
208

51e5b2bd3   Mike Anderson   dm: add uevent to...
209
  	r = dm_uevent_init();
51157b4ab   Kiyoshi Ueda   dm: tidy local_init
210
  	if (r)
e689fbab3   Mike Snitzer   dm: remove unused...
211
  		return r;
51e5b2bd3   Mike Anderson   dm: add uevent to...
212

acfe0ad74   Mikulas Patocka   dm: allocate a sp...
213
214
215
216
217
  	deferred_remove_workqueue = alloc_workqueue("kdmremove", WQ_UNBOUND, 1);
  	if (!deferred_remove_workqueue) {
  		r = -ENOMEM;
  		goto out_uevent_exit;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
  	_major = major;
  	r = register_blkdev(_major, _name);
51157b4ab   Kiyoshi Ueda   dm: tidy local_init
220
  	if (r < 0)
acfe0ad74   Mikulas Patocka   dm: allocate a sp...
221
  		goto out_free_workqueue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
226
  
  	if (!_major)
  		_major = r;
  
  	return 0;
51157b4ab   Kiyoshi Ueda   dm: tidy local_init
227

acfe0ad74   Mikulas Patocka   dm: allocate a sp...
228
229
  out_free_workqueue:
  	destroy_workqueue(deferred_remove_workqueue);
51157b4ab   Kiyoshi Ueda   dm: tidy local_init
230
231
  out_uevent_exit:
  	dm_uevent_exit();
51157b4ab   Kiyoshi Ueda   dm: tidy local_init
232
233
  
  	return r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
237
  }
  
  static void local_exit(void)
  {
2c140a246   Mikulas Patocka   dm: allow remove ...
238
  	flush_scheduled_work();
acfe0ad74   Mikulas Patocka   dm: allocate a sp...
239
  	destroy_workqueue(deferred_remove_workqueue);
2c140a246   Mikulas Patocka   dm: allow remove ...
240

00d59405c   Akinobu Mita   unregister_blkdev...
241
  	unregister_blkdev(_major, _name);
51e5b2bd3   Mike Anderson   dm: add uevent to...
242
  	dm_uevent_exit();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
  
  	_major = 0;
  
  	DMINFO("cleaned up");
  }
b9249e556   Alasdair G Kergon   dm: mark function...
248
  static int (*_inits[])(void) __initdata = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
  	local_init,
  	dm_target_init,
  	dm_linear_init,
  	dm_stripe_init,
952b35576   Mikulas Patocka   dm io: use slab f...
253
  	dm_io_init,
945fa4d28   Mikulas Patocka   dm kcopyd: remove...
254
  	dm_kcopyd_init,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  	dm_interface_init,
fd2ed4d25   Mikulas Patocka   dm: add statistic...
256
  	dm_statistics_init,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  };
b9249e556   Alasdair G Kergon   dm: mark function...
258
  static void (*_exits[])(void) = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
262
  	local_exit,
  	dm_target_exit,
  	dm_linear_exit,
  	dm_stripe_exit,
952b35576   Mikulas Patocka   dm io: use slab f...
263
  	dm_io_exit,
945fa4d28   Mikulas Patocka   dm kcopyd: remove...
264
  	dm_kcopyd_exit,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  	dm_interface_exit,
fd2ed4d25   Mikulas Patocka   dm: add statistic...
266
  	dm_statistics_exit,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  };
  
  static int __init dm_init(void)
  {
  	const int count = ARRAY_SIZE(_inits);
  
  	int r, i;
  
  	for (i = 0; i < count; i++) {
  		r = _inits[i]();
  		if (r)
  			goto bad;
  	}
  
  	return 0;
  
        bad:
  	while (i--)
  		_exits[i]();
  
  	return r;
  }
  
  static void __exit dm_exit(void)
  {
  	int i = ARRAY_SIZE(_exits);
  
  	while (i--)
  		_exits[i]();
d15b774c2   Alasdair G Kergon   dm: fix idr leak ...
296
297
298
299
  
  	/*
  	 * Should be empty by this point.
  	 */
d15b774c2   Alasdair G Kergon   dm: fix idr leak ...
300
  	idr_destroy(&_minor_idr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
303
304
305
  }
  
  /*
   * Block device functions
   */
432a212c0   Mike Anderson   dm: add dm_deleti...
306
307
308
309
  int dm_deleting_md(struct mapped_device *md)
  {
  	return test_bit(DMF_DELETING, &md->flags);
  }
fe5f9f2cd   Al Viro   [PATCH] switch dm
310
  static int dm_blk_open(struct block_device *bdev, fmode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
312
  {
  	struct mapped_device *md;
fba9f90e5   Jeff Mahoney   [PATCH] dm: add D...
313
  	spin_lock(&_minor_lock);
fe5f9f2cd   Al Viro   [PATCH] switch dm
314
  	md = bdev->bd_disk->private_data;
fba9f90e5   Jeff Mahoney   [PATCH] dm: add D...
315
316
  	if (!md)
  		goto out;
5c6bd75d0   Alasdair G Kergon   [PATCH] dm: preve...
317
  	if (test_bit(DMF_FREEING, &md->flags) ||
432a212c0   Mike Anderson   dm: add dm_deleti...
318
  	    dm_deleting_md(md)) {
fba9f90e5   Jeff Mahoney   [PATCH] dm: add D...
319
320
321
  		md = NULL;
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  	dm_get(md);
5c6bd75d0   Alasdair G Kergon   [PATCH] dm: preve...
323
  	atomic_inc(&md->open_count);
fba9f90e5   Jeff Mahoney   [PATCH] dm: add D...
324
325
326
327
  out:
  	spin_unlock(&_minor_lock);
  
  	return md ? 0 : -ENXIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
  }
db2a144be   Al Viro   block_device_oper...
329
  static void dm_blk_close(struct gendisk *disk, fmode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
  {
63a4f065e   Mike Snitzer   dm: fix add_disk(...
331
  	struct mapped_device *md;
6e9624b8c   Arnd Bergmann   block: push down ...
332

4a1aeb982   Milan Broz   dm: remove dm_mut...
333
  	spin_lock(&_minor_lock);
63a4f065e   Mike Snitzer   dm: fix add_disk(...
334
335
336
  	md = disk->private_data;
  	if (WARN_ON(!md))
  		goto out;
2c140a246   Mikulas Patocka   dm: allow remove ...
337
338
  	if (atomic_dec_and_test(&md->open_count) &&
  	    (test_bit(DMF_DEFERRED_REMOVE, &md->flags)))
acfe0ad74   Mikulas Patocka   dm: allocate a sp...
339
  		queue_work(deferred_remove_workqueue, &deferred_remove_work);
2c140a246   Mikulas Patocka   dm: allow remove ...
340

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
  	dm_put(md);
63a4f065e   Mike Snitzer   dm: fix add_disk(...
342
  out:
4a1aeb982   Milan Broz   dm: remove dm_mut...
343
  	spin_unlock(&_minor_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  }
5c6bd75d0   Alasdair G Kergon   [PATCH] dm: preve...
345
346
347
348
349
350
351
352
  int dm_open_count(struct mapped_device *md)
  {
  	return atomic_read(&md->open_count);
  }
  
  /*
   * Guarantees nothing is using the device before it's deleted.
   */
2c140a246   Mikulas Patocka   dm: allow remove ...
353
  int dm_lock_for_deletion(struct mapped_device *md, bool mark_deferred, bool only_deferred)
5c6bd75d0   Alasdair G Kergon   [PATCH] dm: preve...
354
355
356
357
  {
  	int r = 0;
  
  	spin_lock(&_minor_lock);
2c140a246   Mikulas Patocka   dm: allow remove ...
358
  	if (dm_open_count(md)) {
5c6bd75d0   Alasdair G Kergon   [PATCH] dm: preve...
359
  		r = -EBUSY;
2c140a246   Mikulas Patocka   dm: allow remove ...
360
361
362
363
  		if (mark_deferred)
  			set_bit(DMF_DEFERRED_REMOVE, &md->flags);
  	} else if (only_deferred && !test_bit(DMF_DEFERRED_REMOVE, &md->flags))
  		r = -EEXIST;
5c6bd75d0   Alasdair G Kergon   [PATCH] dm: preve...
364
365
366
367
368
369
370
  	else
  		set_bit(DMF_DELETING, &md->flags);
  
  	spin_unlock(&_minor_lock);
  
  	return r;
  }
2c140a246   Mikulas Patocka   dm: allow remove ...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
  int dm_cancel_deferred_remove(struct mapped_device *md)
  {
  	int r = 0;
  
  	spin_lock(&_minor_lock);
  
  	if (test_bit(DMF_DELETING, &md->flags))
  		r = -EBUSY;
  	else
  		clear_bit(DMF_DEFERRED_REMOVE, &md->flags);
  
  	spin_unlock(&_minor_lock);
  
  	return r;
  }
  
  static void do_deferred_remove(struct work_struct *w)
  {
  	dm_deferred_remove();
  }
3ac51e741   Darrick J. Wong   [PATCH] dm store ...
391
392
393
394
395
396
  static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
  {
  	struct mapped_device *md = bdev->bd_disk->private_data;
  
  	return dm_get_geometry(md, geo);
  }
d41003513   Christoph Hellwig   block: rework zon...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
  #ifdef CONFIG_BLK_DEV_ZONED
  int dm_report_zones_cb(struct blk_zone *zone, unsigned int idx, void *data)
  {
  	struct dm_report_zones_args *args = data;
  	sector_t sector_diff = args->tgt->begin - args->start;
  
  	/*
  	 * Ignore zones beyond the target range.
  	 */
  	if (zone->start >= args->start + args->tgt->len)
  		return 0;
  
  	/*
  	 * Remap the start sector and write pointer position of the zone
  	 * to match its position in the target range.
  	 */
  	zone->start += sector_diff;
  	if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) {
  		if (zone->cond == BLK_ZONE_COND_FULL)
  			zone->wp = zone->start + zone->len;
  		else if (zone->cond == BLK_ZONE_COND_EMPTY)
  			zone->wp = zone->start;
  		else
  			zone->wp += sector_diff;
  	}
  
  	args->next_sector = zone->start + zone->len;
  	return args->orig_cb(zone, args->zone_idx++, args->orig_data);
  }
  EXPORT_SYMBOL_GPL(dm_report_zones_cb);
e76239a37   Christoph Hellwig   block: add a repo...
427
  static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
d41003513   Christoph Hellwig   block: rework zon...
428
  		unsigned int nr_zones, report_zones_cb cb, void *data)
e76239a37   Christoph Hellwig   block: add a repo...
429
  {
e76239a37   Christoph Hellwig   block: add a repo...
430
  	struct mapped_device *md = disk->private_data;
e76239a37   Christoph Hellwig   block: add a repo...
431
432
  	struct dm_table *map;
  	int srcu_idx, ret;
d41003513   Christoph Hellwig   block: rework zon...
433
434
435
436
437
  	struct dm_report_zones_args args = {
  		.next_sector = sector,
  		.orig_data = data,
  		.orig_cb = cb,
  	};
e76239a37   Christoph Hellwig   block: add a repo...
438
439
440
441
442
  
  	if (dm_suspended_md(md))
  		return -EAGAIN;
  
  	map = dm_get_live_table(md, &srcu_idx);
894783357   Sergei Shtepa   dm: fix bug with ...
443
444
445
446
  	if (!map) {
  		ret = -EIO;
  		goto out;
  	}
e76239a37   Christoph Hellwig   block: add a repo...
447

d41003513   Christoph Hellwig   block: rework zon...
448
449
  	do {
  		struct dm_target *tgt;
e76239a37   Christoph Hellwig   block: add a repo...
450

d41003513   Christoph Hellwig   block: rework zon...
451
452
453
454
455
  		tgt = dm_table_find_target(map, args.next_sector);
  		if (WARN_ON_ONCE(!tgt->type->report_zones)) {
  			ret = -EIO;
  			goto out;
  		}
e76239a37   Christoph Hellwig   block: add a repo...
456

d41003513   Christoph Hellwig   block: rework zon...
457
  		args.tgt = tgt;
a9cb9f414   Johannes Thumshirn   dm: don't call re...
458
459
  		ret = tgt->type->report_zones(tgt, &args,
  					      nr_zones - args.zone_idx);
d41003513   Christoph Hellwig   block: rework zon...
460
461
462
463
  		if (ret < 0)
  			goto out;
  	} while (args.zone_idx < nr_zones &&
  		 args.next_sector < get_capacity(disk));
e76239a37   Christoph Hellwig   block: add a repo...
464

d41003513   Christoph Hellwig   block: rework zon...
465
  	ret = args.zone_idx;
e76239a37   Christoph Hellwig   block: add a repo...
466
467
468
  out:
  	dm_put_live_table(md, srcu_idx);
  	return ret;
e76239a37   Christoph Hellwig   block: add a repo...
469
  }
d41003513   Christoph Hellwig   block: rework zon...
470
471
472
  #else
  #define dm_blk_report_zones		NULL
  #endif /* CONFIG_BLK_DEV_ZONED */
e76239a37   Christoph Hellwig   block: add a repo...
473

971888c46   Mike Snitzer   dm: hold DM table...
474
  static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
5bd5e8d89   Mike Snitzer   dm: remove fmode_...
475
  			    struct block_device **bdev)
aa129a224   Milan Broz   [PATCH] dm: suppo...
476
  {
664820265   Mike Snitzer   dm: do not return...
477
  	struct dm_target *tgt;
6c182cd88   Hannes Reinecke   dm mpath: fix ioc...
478
  	struct dm_table *map;
971888c46   Mike Snitzer   dm: hold DM table...
479
  	int r;
aa129a224   Milan Broz   [PATCH] dm: suppo...
480

6c182cd88   Hannes Reinecke   dm mpath: fix ioc...
481
  retry:
e56f81e0b   Christoph Hellwig   dm: refactor ioct...
482
  	r = -ENOTTY;
971888c46   Mike Snitzer   dm: hold DM table...
483
  	map = dm_get_live_table(md, srcu_idx);
aa129a224   Milan Broz   [PATCH] dm: suppo...
484
  	if (!map || !dm_table_get_size(map))
971888c46   Mike Snitzer   dm: hold DM table...
485
  		return r;
aa129a224   Milan Broz   [PATCH] dm: suppo...
486
487
488
  
  	/* We only support devices that have a single target */
  	if (dm_table_get_num_targets(map) != 1)
971888c46   Mike Snitzer   dm: hold DM table...
489
  		return r;
aa129a224   Milan Broz   [PATCH] dm: suppo...
490

664820265   Mike Snitzer   dm: do not return...
491
492
  	tgt = dm_table_get_target(map, 0);
  	if (!tgt->type->prepare_ioctl)
971888c46   Mike Snitzer   dm: hold DM table...
493
  		return r;
519049afe   Mike Snitzer   dm: use blkdev_ge...
494

971888c46   Mike Snitzer   dm: hold DM table...
495
496
  	if (dm_suspended_md(md))
  		return -EAGAIN;
aa129a224   Milan Broz   [PATCH] dm: suppo...
497

5bd5e8d89   Mike Snitzer   dm: remove fmode_...
498
  	r = tgt->type->prepare_ioctl(tgt, bdev);
5bbbfdf68   Junichi Nomura   dm: fix ioctl ret...
499
  	if (r == -ENOTCONN && !fatal_signal_pending(current)) {
971888c46   Mike Snitzer   dm: hold DM table...
500
  		dm_put_live_table(md, *srcu_idx);
6c182cd88   Hannes Reinecke   dm mpath: fix ioc...
501
502
503
  		msleep(10);
  		goto retry;
  	}
971888c46   Mike Snitzer   dm: hold DM table...
504

e56f81e0b   Christoph Hellwig   dm: refactor ioct...
505
506
  	return r;
  }
971888c46   Mike Snitzer   dm: hold DM table...
507
  static void dm_unprepare_ioctl(struct mapped_device *md, int srcu_idx)
971888c46   Mike Snitzer   dm: hold DM table...
508
509
510
  {
  	dm_put_live_table(md, srcu_idx);
  }
e56f81e0b   Christoph Hellwig   dm: refactor ioct...
511
512
513
514
  static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
  			unsigned int cmd, unsigned long arg)
  {
  	struct mapped_device *md = bdev->bd_disk->private_data;
971888c46   Mike Snitzer   dm: hold DM table...
515
  	int r, srcu_idx;
e56f81e0b   Christoph Hellwig   dm: refactor ioct...
516

5bd5e8d89   Mike Snitzer   dm: remove fmode_...
517
  	r = dm_prepare_ioctl(md, &srcu_idx, &bdev);
e56f81e0b   Christoph Hellwig   dm: refactor ioct...
518
  	if (r < 0)
971888c46   Mike Snitzer   dm: hold DM table...
519
  		goto out;
6c182cd88   Hannes Reinecke   dm mpath: fix ioc...
520

e56f81e0b   Christoph Hellwig   dm: refactor ioct...
521
522
  	if (r > 0) {
  		/*
e980f6235   Christoph Hellwig   dm: don't allow i...
523
524
  		 * Target determined this ioctl is being issued against a
  		 * subset of the parent bdev; require extra privileges.
e56f81e0b   Christoph Hellwig   dm: refactor ioct...
525
  		 */
e980f6235   Christoph Hellwig   dm: don't allow i...
526
  		if (!capable(CAP_SYS_RAWIO)) {
0eb56457d   Mike Snitzer   dm: eliminate pot...
527
  			DMDEBUG_LIMIT(
e980f6235   Christoph Hellwig   dm: don't allow i...
528
529
530
  	"%s: sending ioctl %x to DM device without required privilege.",
  				current->comm, cmd);
  			r = -ENOIOCTLCMD;
e56f81e0b   Christoph Hellwig   dm: refactor ioct...
531
  			goto out;
e980f6235   Christoph Hellwig   dm: don't allow i...
532
  		}
e56f81e0b   Christoph Hellwig   dm: refactor ioct...
533
  	}
6c182cd88   Hannes Reinecke   dm mpath: fix ioc...
534

664820265   Mike Snitzer   dm: do not return...
535
  	r =  __blkdev_driver_ioctl(bdev, mode, cmd, arg);
e56f81e0b   Christoph Hellwig   dm: refactor ioct...
536
  out:
971888c46   Mike Snitzer   dm: hold DM table...
537
  	dm_unprepare_ioctl(md, srcu_idx);
aa129a224   Milan Broz   [PATCH] dm: suppo...
538
539
  	return r;
  }
7465d7ac5   Mike Snitzer   dm: eliminate nee...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
  u64 dm_start_time_ns_from_clone(struct bio *bio)
  {
  	struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
  	struct dm_io *io = tio->io;
  
  	return jiffies_to_nsecs(io->start_time);
  }
  EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone);
  
  static void start_io_acct(struct dm_io *io)
  {
  	struct mapped_device *md = io->md;
  	struct bio *bio = io->orig_bio;
  
  	io->start_time = bio_start_io_acct(bio);
  	if (unlikely(dm_stats_used(&md->stats)))
  		dm_stats_account_io(&md->stats, bio_data_dir(bio),
  				    bio->bi_iter.bi_sector, bio_sectors(bio),
  				    false, 0, &io->stats_aux);
  }
  
  static void end_io_acct(struct dm_io *io)
  {
  	struct mapped_device *md = io->md;
  	struct bio *bio = io->orig_bio;
  	unsigned long duration = jiffies - io->start_time;
  
  	bio_end_io_acct(bio, io->start_time);
  
  	if (unlikely(dm_stats_used(&md->stats)))
  		dm_stats_account_io(&md->stats, bio_data_dir(bio),
  				    bio->bi_iter.bi_sector, bio_sectors(bio),
  				    true, duration, &io->stats_aux);
  
  	/* nudge anyone waiting on suspend queue */
  	if (unlikely(wq_has_sleeper(&md->wait)))
  		wake_up(&md->wait);
  }
978e51ba3   Mike Snitzer   dm: optimize bio-...
578
579
  
  static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  {
64f52b0e3   Mike Snitzer   dm: improve perfo...
581
582
583
  	struct dm_io *io;
  	struct dm_target_io *tio;
  	struct bio *clone;
6f1c819c2   Kent Overstreet   dm: convert to bi...
584
  	clone = bio_alloc_bioset(GFP_NOIO, 0, &md->io_bs);
64f52b0e3   Mike Snitzer   dm: improve perfo...
585
586
587
588
589
590
591
592
593
  	if (!clone)
  		return NULL;
  
  	tio = container_of(clone, struct dm_target_io, clone);
  	tio->inside_dm_io = true;
  	tio->io = NULL;
  
  	io = container_of(tio, struct dm_io, tio);
  	io->magic = DM_IO_MAGIC;
978e51ba3   Mike Snitzer   dm: optimize bio-...
594
595
596
597
598
599
600
  	io->status = 0;
  	atomic_set(&io->io_count, 1);
  	io->orig_bio = bio;
  	io->md = md;
  	spin_lock_init(&io->endio_lock);
  
  	start_io_acct(io);
64f52b0e3   Mike Snitzer   dm: improve perfo...
601
602
  
  	return io;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
  }
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
604
  static void free_io(struct mapped_device *md, struct dm_io *io)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  {
64f52b0e3   Mike Snitzer   dm: improve perfo...
606
607
608
609
610
611
612
613
614
615
616
617
  	bio_put(&io->tio.clone);
  }
  
  static struct dm_target_io *alloc_tio(struct clone_info *ci, struct dm_target *ti,
  				      unsigned target_bio_nr, gfp_t gfp_mask)
  {
  	struct dm_target_io *tio;
  
  	if (!ci->io->tio.io) {
  		/* the dm_target_io embedded in ci->io is available */
  		tio = &ci->io->tio;
  	} else {
6f1c819c2   Kent Overstreet   dm: convert to bi...
618
  		struct bio *clone = bio_alloc_bioset(gfp_mask, 0, &ci->io->md->bs);
64f52b0e3   Mike Snitzer   dm: improve perfo...
619
620
621
622
623
624
625
626
627
628
629
630
631
  		if (!clone)
  			return NULL;
  
  		tio = container_of(clone, struct dm_target_io, clone);
  		tio->inside_dm_io = false;
  	}
  
  	tio->magic = DM_TIO_MAGIC;
  	tio->io = ci->io;
  	tio->ti = ti;
  	tio->target_bio_nr = target_bio_nr;
  
  	return tio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  }
cfae7529b   Mike Snitzer   dm: remove unused...
633
  static void free_tio(struct dm_target_io *tio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
  {
64f52b0e3   Mike Snitzer   dm: improve perfo...
635
636
  	if (tio->inside_dm_io)
  		return;
dba141601   Mikulas Patocka   dm: store dm_targ...
637
  	bio_put(&tio->clone);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
641
642
  }
  
  /*
   * Add the bio to the list of deferred io.
   */
92c639021   Mikulas Patocka   dm: remove dm_req...
643
  static void queue_io(struct mapped_device *md, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
  {
05447420f   Kiyoshi Ueda   dm: fix locking c...
645
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646

05447420f   Kiyoshi Ueda   dm: fix locking c...
647
  	spin_lock_irqsave(&md->deferred_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  	bio_list_add(&md->deferred, bio);
05447420f   Kiyoshi Ueda   dm: fix locking c...
649
  	spin_unlock_irqrestore(&md->deferred_lock, flags);
6a8736d10   Tejun Heo   dm: relax orderin...
650
  	queue_work(md->wq, &md->work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
653
654
655
  }
  
  /*
   * Everyone (including functions in this file), should use this
   * function to access the md->map field, and make sure they call
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
656
   * dm_put_live_table() when finished.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
   */
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
658
  struct dm_table *dm_get_live_table(struct mapped_device *md, int *srcu_idx) __acquires(md->io_barrier)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
  {
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
660
661
662
663
  	*srcu_idx = srcu_read_lock(&md->io_barrier);
  
  	return srcu_dereference(md->map, &md->io_barrier);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664

83d5e5b0a   Mikulas Patocka   dm: optimize use ...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
  void dm_put_live_table(struct mapped_device *md, int srcu_idx) __releases(md->io_barrier)
  {
  	srcu_read_unlock(&md->io_barrier, srcu_idx);
  }
  
  void dm_sync_table(struct mapped_device *md)
  {
  	synchronize_srcu(&md->io_barrier);
  	synchronize_rcu_expedited();
  }
  
  /*
   * A fast alternative to dm_get_live_table/dm_put_live_table.
   * The caller must not block between these two functions.
   */
  static struct dm_table *dm_get_live_table_fast(struct mapped_device *md) __acquires(RCU)
  {
  	rcu_read_lock();
  	return rcu_dereference(md->map);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685

83d5e5b0a   Mikulas Patocka   dm: optimize use ...
686
687
688
  static void dm_put_live_table_fast(struct mapped_device *md) __releases(RCU)
  {
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
  }
971888c46   Mike Snitzer   dm: hold DM table...
690
  static char *_dm_claim_ptr = "I belong to device-mapper";
3ac51e741   Darrick J. Wong   [PATCH] dm store ...
691
  /*
86f1152b1   Benjamin Marzinski   dm: allow active ...
692
693
694
695
696
   * Open a table device so we can use it as a map destination.
   */
  static int open_table_device(struct table_device *td, dev_t dev,
  			     struct mapped_device *md)
  {
86f1152b1   Benjamin Marzinski   dm: allow active ...
697
698
699
700
701
  	struct block_device *bdev;
  
  	int r;
  
  	BUG_ON(td->dm_dev.bdev);
519049afe   Mike Snitzer   dm: use blkdev_ge...
702
  	bdev = blkdev_get_by_dev(dev, td->dm_dev.mode | FMODE_EXCL, _dm_claim_ptr);
86f1152b1   Benjamin Marzinski   dm: allow active ...
703
704
705
706
707
708
709
710
711
712
  	if (IS_ERR(bdev))
  		return PTR_ERR(bdev);
  
  	r = bd_link_disk_holder(bdev, dm_disk(md));
  	if (r) {
  		blkdev_put(bdev, td->dm_dev.mode | FMODE_EXCL);
  		return r;
  	}
  
  	td->dm_dev.bdev = bdev;
817bf4026   Dan Williams   dm: teach dm-targ...
713
  	td->dm_dev.dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
86f1152b1   Benjamin Marzinski   dm: allow active ...
714
715
716
717
718
719
720
721
722
723
724
725
726
  	return 0;
  }
  
  /*
   * Close a table device that we've been using.
   */
  static void close_table_device(struct table_device *td, struct mapped_device *md)
  {
  	if (!td->dm_dev.bdev)
  		return;
  
  	bd_unlink_disk_holder(td->dm_dev.bdev, dm_disk(md));
  	blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL);
817bf4026   Dan Williams   dm: teach dm-targ...
727
  	put_dax(td->dm_dev.dax_dev);
86f1152b1   Benjamin Marzinski   dm: allow active ...
728
  	td->dm_dev.bdev = NULL;
817bf4026   Dan Williams   dm: teach dm-targ...
729
  	td->dm_dev.dax_dev = NULL;
86f1152b1   Benjamin Marzinski   dm: allow active ...
730
731
732
  }
  
  static struct table_device *find_table_device(struct list_head *l, dev_t dev,
8454fca4f   Sheetal Singala   dm: fix a couple ...
733
734
  					      fmode_t mode)
  {
86f1152b1   Benjamin Marzinski   dm: allow active ...
735
736
737
738
739
740
741
742
743
744
  	struct table_device *td;
  
  	list_for_each_entry(td, l, list)
  		if (td->dm_dev.bdev->bd_dev == dev && td->dm_dev.mode == mode)
  			return td;
  
  	return NULL;
  }
  
  int dm_get_table_device(struct mapped_device *md, dev_t dev, fmode_t mode,
8454fca4f   Sheetal Singala   dm: fix a couple ...
745
746
  			struct dm_dev **result)
  {
86f1152b1   Benjamin Marzinski   dm: allow active ...
747
748
749
750
751
752
  	int r;
  	struct table_device *td;
  
  	mutex_lock(&md->table_devices_lock);
  	td = find_table_device(&md->table_devices, dev, mode);
  	if (!td) {
115485e83   Mike Snitzer   dm: add 'dm_numa_...
753
  		td = kmalloc_node(sizeof(*td), GFP_KERNEL, md->numa_node_id);
86f1152b1   Benjamin Marzinski   dm: allow active ...
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
  		if (!td) {
  			mutex_unlock(&md->table_devices_lock);
  			return -ENOMEM;
  		}
  
  		td->dm_dev.mode = mode;
  		td->dm_dev.bdev = NULL;
  
  		if ((r = open_table_device(td, dev, md))) {
  			mutex_unlock(&md->table_devices_lock);
  			kfree(td);
  			return r;
  		}
  
  		format_dev_t(td->dm_dev.name, dev);
b0b4d7c67   Elena Reshetova   dm: convert table...
769
  		refcount_set(&td->count, 1);
86f1152b1   Benjamin Marzinski   dm: allow active ...
770
  		list_add(&td->list, &md->table_devices);
b0b4d7c67   Elena Reshetova   dm: convert table...
771
772
  	} else {
  		refcount_inc(&td->count);
86f1152b1   Benjamin Marzinski   dm: allow active ...
773
  	}
86f1152b1   Benjamin Marzinski   dm: allow active ...
774
775
776
777
778
779
780
781
782
783
784
785
  	mutex_unlock(&md->table_devices_lock);
  
  	*result = &td->dm_dev;
  	return 0;
  }
  EXPORT_SYMBOL_GPL(dm_get_table_device);
  
  void dm_put_table_device(struct mapped_device *md, struct dm_dev *d)
  {
  	struct table_device *td = container_of(d, struct table_device, dm_dev);
  
  	mutex_lock(&md->table_devices_lock);
b0b4d7c67   Elena Reshetova   dm: convert table...
786
  	if (refcount_dec_and_test(&td->count)) {
86f1152b1   Benjamin Marzinski   dm: allow active ...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
  		close_table_device(td, md);
  		list_del(&td->list);
  		kfree(td);
  	}
  	mutex_unlock(&md->table_devices_lock);
  }
  EXPORT_SYMBOL(dm_put_table_device);
  
  static void free_table_devices(struct list_head *devices)
  {
  	struct list_head *tmp, *next;
  
  	list_for_each_safe(tmp, next, devices) {
  		struct table_device *td = list_entry(tmp, struct table_device, list);
  
  		DMWARN("dm_destroy: %s still exists with %d references",
b0b4d7c67   Elena Reshetova   dm: convert table...
803
  		       td->dm_dev.name, refcount_read(&td->count));
86f1152b1   Benjamin Marzinski   dm: allow active ...
804
805
806
807
808
  		kfree(td);
  	}
  }
  
  /*
3ac51e741   Darrick J. Wong   [PATCH] dm store ...
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
   * Get the geometry associated with a dm device
   */
  int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo)
  {
  	*geo = md->geometry;
  
  	return 0;
  }
  
  /*
   * Set the geometry of a device.
   */
  int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo)
  {
  	sector_t sz = (sector_t)geo->cylinders * geo->heads * geo->sectors;
  
  	if (geo->start > sz) {
  		DMWARN("Start sector is beyond the geometry limits.");
  		return -EINVAL;
  	}
  
  	md->geometry = *geo;
  
  	return 0;
  }
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
834
835
836
837
  static int __noflush_suspending(struct mapped_device *md)
  {
  	return test_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
  /*
   * Decrements the number of outstanding ios that a bio has been
   * cloned into, completing the original io if necc.
   */
4e4cbee93   Christoph Hellwig   block: switch bio...
842
  static void dec_pending(struct dm_io *io, blk_status_t error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
  {
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
844
  	unsigned long flags;
4e4cbee93   Christoph Hellwig   block: switch bio...
845
  	blk_status_t io_error;
b35f8caa0   Milan Broz   dm crypt: wait fo...
846
847
  	struct bio *bio;
  	struct mapped_device *md = io->md;
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
848
849
  
  	/* Push-back supersedes any I/O errors */
f88fb9811   Kiyoshi Ueda   dm: dec_pending n...
850
851
  	if (unlikely(error)) {
  		spin_lock_irqsave(&io->endio_lock, flags);
745dc570b   Mike Snitzer   dm: rename 'bio' ...
852
  		if (!(io->status == BLK_STS_DM_REQUEUE && __noflush_suspending(md)))
4e4cbee93   Christoph Hellwig   block: switch bio...
853
  			io->status = error;
f88fb9811   Kiyoshi Ueda   dm: dec_pending n...
854
855
  		spin_unlock_irqrestore(&io->endio_lock, flags);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
  
  	if (atomic_dec_and_test(&io->io_count)) {
4e4cbee93   Christoph Hellwig   block: switch bio...
858
  		if (io->status == BLK_STS_DM_REQUEUE) {
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
859
860
  			/*
  			 * Target requested pushing back the I/O.
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
861
  			 */
022c26110   Mikulas Patocka   dm: merge pushbac...
862
  			spin_lock_irqsave(&md->deferred_lock, flags);
6a8736d10   Tejun Heo   dm: relax orderin...
863
  			if (__noflush_suspending(md))
745dc570b   Mike Snitzer   dm: rename 'bio' ...
864
865
  				/* NOTE early return due to BLK_STS_DM_REQUEUE below */
  				bio_list_add_head(&md->deferred, io->orig_bio);
6a8736d10   Tejun Heo   dm: relax orderin...
866
  			else
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
867
  				/* noflush suspend was interrupted. */
4e4cbee93   Christoph Hellwig   block: switch bio...
868
  				io->status = BLK_STS_IOERR;
022c26110   Mikulas Patocka   dm: merge pushbac...
869
  			spin_unlock_irqrestore(&md->deferred_lock, flags);
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
870
  		}
4e4cbee93   Christoph Hellwig   block: switch bio...
871
  		io_error = io->status;
745dc570b   Mike Snitzer   dm: rename 'bio' ...
872
  		bio = io->orig_bio;
6a8736d10   Tejun Heo   dm: relax orderin...
873
874
  		end_io_acct(io);
  		free_io(md, io);
4e4cbee93   Christoph Hellwig   block: switch bio...
875
  		if (io_error == BLK_STS_DM_REQUEUE)
6a8736d10   Tejun Heo   dm: relax orderin...
876
  			return;
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
877

1eff9d322   Jens Axboe   block: rename bio...
878
  		if ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size) {
af7e466a1   Mikulas Patocka   dm: implement bas...
879
  			/*
6a8736d10   Tejun Heo   dm: relax orderin...
880
  			 * Preflush done for flush with data, reissue
28a8f0d31   Mike Christie   block, drivers, f...
881
  			 * without REQ_PREFLUSH.
af7e466a1   Mikulas Patocka   dm: implement bas...
882
  			 */
1eff9d322   Jens Axboe   block: rename bio...
883
  			bio->bi_opf &= ~REQ_PREFLUSH;
6a8736d10   Tejun Heo   dm: relax orderin...
884
  			queue_io(md, bio);
af7e466a1   Mikulas Patocka   dm: implement bas...
885
  		} else {
b372d360d   Mike Snitzer   dm: convey that a...
886
  			/* done with normal IO or empty flush */
8dd601fa8   NeilBrown   dm: correctly han...
887
888
  			if (io_error)
  				bio->bi_status = io_error;
4246a0b63   Christoph Hellwig   block: add a bi_e...
889
  			bio_endio(bio);
b35f8caa0   Milan Broz   dm crypt: wait fo...
890
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
891
892
  	}
  }
bcb44433b   Mike Snitzer   dm: disable DISCA...
893
894
895
896
897
898
899
900
  void disable_discard(struct mapped_device *md)
  {
  	struct queue_limits *limits = dm_get_queue_limits(md);
  
  	/* device doesn't really support DISCARD, disable it */
  	limits->max_discard_sectors = 0;
  	blk_queue_flag_clear(QUEUE_FLAG_DISCARD, md->queue);
  }
4cc96131a   Mike Snitzer   dm: move request-...
901
  void disable_write_same(struct mapped_device *md)
7eee4ae2d   Mike Snitzer   dm: disable WRITE...
902
903
904
905
906
907
  {
  	struct queue_limits *limits = dm_get_queue_limits(md);
  
  	/* device doesn't really support WRITE SAME, disable it */
  	limits->max_write_same_sectors = 0;
  }
ac62d6208   Christoph Hellwig   dm: support REQ_O...
908
909
910
911
912
913
914
  void disable_write_zeroes(struct mapped_device *md)
  {
  	struct queue_limits *limits = dm_get_queue_limits(md);
  
  	/* device doesn't really support WRITE ZEROES, disable it */
  	limits->max_write_zeroes_sectors = 0;
  }
4246a0b63   Christoph Hellwig   block: add a bi_e...
915
  static void clone_endio(struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
  {
4e4cbee93   Christoph Hellwig   block: switch bio...
917
  	blk_status_t error = bio->bi_status;
bfc6d41ce   Mikulas Patocka   dm: stop using bi...
918
  	struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
b35f8caa0   Milan Broz   dm crypt: wait fo...
919
  	struct dm_io *io = tio->io;
9faf400f7   Stefan Bader   [PATCH] dm: use p...
920
  	struct mapped_device *md = tio->io->md;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  	dm_endio_fn endio = tio->ti->type->end_io;
415c79e13   Johannes Thumshirn   dm: update origin...
922
  	struct bio *orig_bio = io->orig_bio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923

9c37de297   Mike Snitzer   dm: remove specia...
924
  	if (unlikely(error == BLK_STS_TARGET)) {
bcb44433b   Mike Snitzer   dm: disable DISCA...
925
926
927
928
929
  		if (bio_op(bio) == REQ_OP_DISCARD &&
  		    !bio->bi_disk->queue->limits.max_discard_sectors)
  			disable_discard(md);
  		else if (bio_op(bio) == REQ_OP_WRITE_SAME &&
  			 !bio->bi_disk->queue->limits.max_write_same_sectors)
ac62d6208   Christoph Hellwig   dm: support REQ_O...
930
  			disable_write_same(md);
bcb44433b   Mike Snitzer   dm: disable DISCA...
931
932
  		else if (bio_op(bio) == REQ_OP_WRITE_ZEROES &&
  			 !bio->bi_disk->queue->limits.max_write_zeroes_sectors)
ac62d6208   Christoph Hellwig   dm: support REQ_O...
933
934
  			disable_write_zeroes(md);
  	}
7eee4ae2d   Mike Snitzer   dm: disable WRITE...
935

415c79e13   Johannes Thumshirn   dm: update origin...
936
937
938
939
940
941
942
943
944
945
946
  	/*
  	 * For zone-append bios get offset in zone of the written
  	 * sector and add that to the original bio sector pos.
  	 */
  	if (bio_op(orig_bio) == REQ_OP_ZONE_APPEND) {
  		sector_t written_sector = bio->bi_iter.bi_sector;
  		struct request_queue *q = orig_bio->bi_disk->queue;
  		u64 mask = (u64)blk_queue_zone_sectors(q) - 1;
  
  		orig_bio->bi_iter.bi_sector += written_sector & mask;
  	}
1be569098   Christoph Hellwig   dm: change ->end_...
947
  	if (endio) {
4e4cbee93   Christoph Hellwig   block: switch bio...
948
  		int r = endio(tio->ti, bio, &error);
1be569098   Christoph Hellwig   dm: change ->end_...
949
950
  		switch (r) {
  		case DM_ENDIO_REQUEUE:
4e4cbee93   Christoph Hellwig   block: switch bio...
951
  			error = BLK_STS_DM_REQUEUE;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
952
  			fallthrough;
1be569098   Christoph Hellwig   dm: change ->end_...
953
954
955
956
957
958
959
960
961
962
  		case DM_ENDIO_DONE:
  			break;
  		case DM_ENDIO_INCOMPLETE:
  			/* The target will handle the io */
  			return;
  		default:
  			DMWARN("unimplemented target endio return value: %d", r);
  			BUG();
  		}
  	}
cfae7529b   Mike Snitzer   dm: remove unused...
963
  	free_tio(tio);
b35f8caa0   Milan Broz   dm crypt: wait fo...
964
  	dec_pending(io, error);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
  }
78d8e58a0   Mike Snitzer   Revert "block, dm...
966
  /*
56a67df76   Mike Snitzer   dm: factor out ma...
967
968
969
   * Return maximum size of I/O possible at the supplied sector up to the current
   * target boundary.
   */
3720281db   Mike Snitzer   dm: optimize max_...
970
971
  static inline sector_t max_io_len_target_boundary(struct dm_target *ti,
  						  sector_t target_offset)
56a67df76   Mike Snitzer   dm: factor out ma...
972
  {
56a67df76   Mike Snitzer   dm: factor out ma...
973
974
  	return ti->len - target_offset;
  }
3720281db   Mike Snitzer   dm: optimize max_...
975
  static sector_t max_io_len(struct dm_target *ti, sector_t sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
  {
3720281db   Mike Snitzer   dm: optimize max_...
977
978
  	sector_t target_offset = dm_target_offset(ti, sector);
  	sector_t len = max_io_len_target_boundary(ti, target_offset);
5091cdec5   Mike Snitzer   dm: change max_io...
979
  	sector_t max_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
  
  	/*
3ee16db39   Mike Snitzer   dm: fix IO splitting
982
983
984
985
986
  	 * Does the target need to split IO even further?
  	 * - varied (per target) IO splitting is a tenet of DM; this
  	 *   explains why stacked chunk_sectors based splitting via
  	 *   blk_max_size_offset() isn't possible here. So pass in
  	 *   ti->max_io_len to override stacked chunk_sectors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
  	 */
3ee16db39   Mike Snitzer   dm: fix IO splitting
988
989
990
991
992
993
  	if (ti->max_io_len) {
  		max_len = blk_max_size_offset(ti->table->md->queue,
  					      target_offset, ti->max_io_len);
  		if (len > max_len)
  			len = max_len;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
995
996
  
  	return len;
  }
542f90381   Mike Snitzer   dm: support non p...
997
998
999
1000
1001
1002
1003
1004
  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;
  	}
75ae19362   Mikulas Patocka   dm: revert 8f50e3...
1005
  	ti->max_io_len = (uint32_t) len;
542f90381   Mike Snitzer   dm: support non p...
1006
1007
1008
1009
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(dm_set_target_max_io_len);
f26c5719b   Dan Williams   dm: add dax_devic...
1010
  static struct dm_target *dm_dax_get_live_target(struct mapped_device *md,
3d97c829e   Mike Snitzer   dm: fix some spar...
1011
1012
  						sector_t sector, int *srcu_idx)
  	__acquires(md->io_barrier)
545ed20e6   Toshi Kani   dm: add infrastru...
1013
  {
545ed20e6   Toshi Kani   dm: add infrastru...
1014
1015
  	struct dm_table *map;
  	struct dm_target *ti;
545ed20e6   Toshi Kani   dm: add infrastru...
1016

f26c5719b   Dan Williams   dm: add dax_devic...
1017
  	map = dm_get_live_table(md, srcu_idx);
545ed20e6   Toshi Kani   dm: add infrastru...
1018
  	if (!map)
f26c5719b   Dan Williams   dm: add dax_devic...
1019
  		return NULL;
545ed20e6   Toshi Kani   dm: add infrastru...
1020
1021
  
  	ti = dm_table_find_target(map, sector);
123d87d55   Mikulas Patocka   dm: make dm_table...
1022
  	if (!ti)
f26c5719b   Dan Williams   dm: add dax_devic...
1023
  		return NULL;
545ed20e6   Toshi Kani   dm: add infrastru...
1024

f26c5719b   Dan Williams   dm: add dax_devic...
1025
1026
  	return ti;
  }
545ed20e6   Toshi Kani   dm: add infrastru...
1027

f26c5719b   Dan Williams   dm: add dax_devic...
1028
  static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
3d97c829e   Mike Snitzer   dm: fix some spar...
1029
  				 long nr_pages, void **kaddr, pfn_t *pfn)
f26c5719b   Dan Williams   dm: add dax_devic...
1030
1031
1032
1033
1034
1035
  {
  	struct mapped_device *md = dax_get_private(dax_dev);
  	sector_t sector = pgoff * PAGE_SECTORS;
  	struct dm_target *ti;
  	long len, ret = -EIO;
  	int srcu_idx;
545ed20e6   Toshi Kani   dm: add infrastru...
1036

f26c5719b   Dan Williams   dm: add dax_devic...
1037
  	ti = dm_dax_get_live_target(md, sector, &srcu_idx);
545ed20e6   Toshi Kani   dm: add infrastru...
1038

f26c5719b   Dan Williams   dm: add dax_devic...
1039
1040
1041
1042
  	if (!ti)
  		goto out;
  	if (!ti->type->direct_access)
  		goto out;
3720281db   Mike Snitzer   dm: optimize max_...
1043
  	len = max_io_len(ti, sector) / PAGE_SECTORS;
f26c5719b   Dan Williams   dm: add dax_devic...
1044
1045
1046
  	if (len < 1)
  		goto out;
  	nr_pages = min(len, nr_pages);
dbc626597   Ross Zwisler   dm: prevent DAX m...
1047
  	ret = ti->type->direct_access(ti, pgoff, nr_pages, kaddr, pfn);
817bf4026   Dan Williams   dm: teach dm-targ...
1048

f26c5719b   Dan Williams   dm: add dax_devic...
1049
   out:
545ed20e6   Toshi Kani   dm: add infrastru...
1050
  	dm_put_live_table(md, srcu_idx);
f26c5719b   Dan Williams   dm: add dax_devic...
1051
1052
  
  	return ret;
545ed20e6   Toshi Kani   dm: add infrastru...
1053
  }
7bf7eac8d   Dan Williams   dax: Arrange for ...
1054
1055
1056
1057
1058
  static bool dm_dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
  		int blocksize, sector_t start, sector_t len)
  {
  	struct mapped_device *md = dax_get_private(dax_dev);
  	struct dm_table *map;
02186d889   Dan Williams   dm/dax: Fix table...
1059
  	bool ret = false;
7bf7eac8d   Dan Williams   dax: Arrange for ...
1060
  	int srcu_idx;
7bf7eac8d   Dan Williams   dax: Arrange for ...
1061
1062
1063
  
  	map = dm_get_live_table(md, &srcu_idx);
  	if (!map)
02186d889   Dan Williams   dm/dax: Fix table...
1064
  		goto out;
7bf7eac8d   Dan Williams   dax: Arrange for ...
1065

2e9ee0955   Pankaj Gupta   dm: enable synchr...
1066
  	ret = dm_table_supports_dax(map, device_supports_dax, &blocksize);
7bf7eac8d   Dan Williams   dax: Arrange for ...
1067

02186d889   Dan Williams   dm/dax: Fix table...
1068
  out:
7bf7eac8d   Dan Williams   dax: Arrange for ...
1069
1070
1071
1072
  	dm_put_live_table(md, srcu_idx);
  
  	return ret;
  }
7e026c8c0   Dan Williams   dm: add ->copy_fr...
1073
  static size_t dm_dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff,
3d97c829e   Mike Snitzer   dm: fix some spar...
1074
  				    void *addr, size_t bytes, struct iov_iter *i)
7e026c8c0   Dan Williams   dm: add ->copy_fr...
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
  {
  	struct mapped_device *md = dax_get_private(dax_dev);
  	sector_t sector = pgoff * PAGE_SECTORS;
  	struct dm_target *ti;
  	long ret = 0;
  	int srcu_idx;
  
  	ti = dm_dax_get_live_target(md, sector, &srcu_idx);
  
  	if (!ti)
  		goto out;
  	if (!ti->type->dax_copy_from_iter) {
  		ret = copy_from_iter(addr, bytes, i);
  		goto out;
  	}
  	ret = ti->type->dax_copy_from_iter(ti, pgoff, addr, bytes, i);
   out:
  	dm_put_live_table(md, srcu_idx);
  
  	return ret;
  }
b3a9a0c36   Dan Williams   dax: Introduce a ...
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
  static size_t dm_dax_copy_to_iter(struct dax_device *dax_dev, pgoff_t pgoff,
  		void *addr, size_t bytes, struct iov_iter *i)
  {
  	struct mapped_device *md = dax_get_private(dax_dev);
  	sector_t sector = pgoff * PAGE_SECTORS;
  	struct dm_target *ti;
  	long ret = 0;
  	int srcu_idx;
  
  	ti = dm_dax_get_live_target(md, sector, &srcu_idx);
  
  	if (!ti)
  		goto out;
  	if (!ti->type->dax_copy_to_iter) {
  		ret = copy_to_iter(addr, bytes, i);
  		goto out;
  	}
  	ret = ti->type->dax_copy_to_iter(ti, pgoff, addr, bytes, i);
   out:
  	dm_put_live_table(md, srcu_idx);
  
  	return ret;
  }
cdf6cdcd3   Vivek Goyal   dm,dax: Add dax z...
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
  static int dm_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
  				  size_t nr_pages)
  {
  	struct mapped_device *md = dax_get_private(dax_dev);
  	sector_t sector = pgoff * PAGE_SECTORS;
  	struct dm_target *ti;
  	int ret = -EIO;
  	int srcu_idx;
  
  	ti = dm_dax_get_live_target(md, sector, &srcu_idx);
  
  	if (!ti)
  		goto out;
  	if (WARN_ON(!ti->type->dax_zero_page_range)) {
  		/*
  		 * ->zero_page_range() is mandatory dax operation. If we are
  		 *  here, something is wrong.
  		 */
cdf6cdcd3   Vivek Goyal   dm,dax: Add dax z...
1137
1138
1139
  		goto out;
  	}
  	ret = ti->type->dax_zero_page_range(ti, pgoff, nr_pages);
cdf6cdcd3   Vivek Goyal   dm,dax: Add dax z...
1140
1141
1142
1143
1144
   out:
  	dm_put_live_table(md, srcu_idx);
  
  	return ret;
  }
1dd40c3ec   Mikulas Patocka   dm: introduce dm_...
1145
1146
  /*
   * A target may call dm_accept_partial_bio only from the map routine.  It is
2e2d6f7e4   Ajay Joshi   dm: add zone open...
1147
1148
   * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_RESET,
   * REQ_OP_ZONE_OPEN, REQ_OP_ZONE_CLOSE and REQ_OP_ZONE_FINISH.
1dd40c3ec   Mikulas Patocka   dm: introduce dm_...
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
   *
   * dm_accept_partial_bio informs the dm that the target only wants to process
   * additional n_sectors sectors of the bio and the rest of the data should be
   * sent in a next bio.
   *
   * A diagram that explains the arithmetics:
   * +--------------------+---------------+-------+
   * |         1          |       2       |   3   |
   * +--------------------+---------------+-------+
   *
   * <-------------- *tio->len_ptr --------------->
   *                      <------- bi_size ------->
   *                      <-- n_sectors -->
   *
   * Region 1 was already iterated over with bio_advance or similar function.
   *	(it may be empty if the target doesn't use bio_advance)
   * Region 2 is the remaining bio size that the target wants to process.
   *	(it may be empty if region 1 is non-empty, although there is no reason
   *	 to make it empty)
   * The target requires that region 3 is to be sent in the next bio.
   *
   * If the target wants to receive multiple copies of the bio (via num_*bios, etc),
   * the partially processed part (the sum of regions 1+2) must be the same for all
   * copies of the bio.
   */
  void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors)
  {
  	struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
  	unsigned bi_size = bio->bi_iter.bi_size >> SECTOR_SHIFT;
1eff9d322   Jens Axboe   block: rename bio...
1178
  	BUG_ON(bio->bi_opf & REQ_PREFLUSH);
1dd40c3ec   Mikulas Patocka   dm: introduce dm_...
1179
1180
1181
1182
1183
1184
  	BUG_ON(bi_size > *tio->len_ptr);
  	BUG_ON(n_sectors > bi_size);
  	*tio->len_ptr -= bi_size - n_sectors;
  	bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT;
  }
  EXPORT_SYMBOL_GPL(dm_accept_partial_bio);
978e51ba3   Mike Snitzer   dm: optimize bio-...
1185
  static blk_qc_t __map_bio(struct dm_target_io *tio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
1187
  {
  	int r;
2056a782f   Jens Axboe   [PATCH] Block que...
1188
  	sector_t sector;
dba141601   Mikulas Patocka   dm: store dm_targ...
1189
  	struct bio *clone = &tio->clone;
64f52b0e3   Mike Snitzer   dm: improve perfo...
1190
  	struct dm_io *io = tio->io;
bd2a49b86   Alasdair G Kergon   dm: clean up clon...
1191
  	struct dm_target *ti = tio->ti;
978e51ba3   Mike Snitzer   dm: optimize bio-...
1192
  	blk_qc_t ret = BLK_QC_T_NONE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194
  	clone->bi_end_io = clone_endio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
1197
1198
1199
1200
  
  	/*
  	 * Map the clone.  If r == 0 we don't need to do
  	 * anything, the target has assumed ownership of
  	 * this io.
  	 */
64f52b0e3   Mike Snitzer   dm: improve perfo...
1201
  	atomic_inc(&io->io_count);
4f024f379   Kent Overstreet   block: Abstract o...
1202
  	sector = clone->bi_iter.bi_sector;
d67a5f4b5   Mikulas Patocka   dm: flush queued ...
1203

7de3ee57d   Mikulas Patocka   dm: remove map_info
1204
  	r = ti->type->map(ti, clone);
846785e6a   Christoph Hellwig   dm: don't return ...
1205
1206
1207
1208
  	switch (r) {
  	case DM_MAPIO_SUBMITTED:
  		break;
  	case DM_MAPIO_REMAPPED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
  		/* the bio has been remapped so dispatch it */
74d46992e   Christoph Hellwig   block: replace bi...
1210
  		trace_block_bio_remap(clone->bi_disk->queue, clone,
64f52b0e3   Mike Snitzer   dm: improve perfo...
1211
  				      bio_dev(io->orig_bio), sector);
5a6c35f9a   Christoph Hellwig   block: remove dir...
1212
  		ret = submit_bio_noacct(clone);
846785e6a   Christoph Hellwig   dm: don't return ...
1213
1214
  		break;
  	case DM_MAPIO_KILL:
4e4cbee93   Christoph Hellwig   block: switch bio...
1215
  		free_tio(tio);
64f52b0e3   Mike Snitzer   dm: improve perfo...
1216
  		dec_pending(io, BLK_STS_IOERR);
4e4cbee93   Christoph Hellwig   block: switch bio...
1217
  		break;
846785e6a   Christoph Hellwig   dm: don't return ...
1218
  	case DM_MAPIO_REQUEUE:
cfae7529b   Mike Snitzer   dm: remove unused...
1219
  		free_tio(tio);
64f52b0e3   Mike Snitzer   dm: improve perfo...
1220
  		dec_pending(io, BLK_STS_DM_REQUEUE);
846785e6a   Christoph Hellwig   dm: don't return ...
1221
1222
  		break;
  	default:
45cbcd798   Kiyoshi Ueda   [PATCH] dm: map a...
1223
1224
  		DMWARN("unimplemented target map return value: %d", r);
  		BUG();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226

978e51ba3   Mike Snitzer   dm: optimize bio-...
1227
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229

e0d6609a5   Mikulas Patocka   dm: change sector...
1230
  static void bio_setup_sector(struct bio *bio, sector_t sector, unsigned len)
bd2a49b86   Alasdair G Kergon   dm: clean up clon...
1231
  {
4f024f379   Kent Overstreet   block: Abstract o...
1232
1233
  	bio->bi_iter.bi_sector = sector;
  	bio->bi_iter.bi_size = to_bytes(len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
1235
1236
1237
1238
  }
  
  /*
   * Creates a bio that consists of range of complete bvecs.
   */
c80914e81   Mike Snitzer   dm: return error ...
1239
1240
  static int clone_bio(struct dm_target_io *tio, struct bio *bio,
  		     sector_t sector, unsigned len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
  {
dba141601   Mikulas Patocka   dm: store dm_targ...
1242
  	struct bio *clone = &tio->clone;
07560151d   Eric Biggers   block: make bio_c...
1243
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244

1c3b13e64   Kent Overstreet   dm: Refactor for ...
1245
  	__bio_clone_fast(clone, bio);
07560151d   Eric Biggers   block: make bio_c...
1246
1247
1248
  	r = bio_crypt_clone(clone, bio, GFP_NOIO);
  	if (r < 0)
  		return r;
e2460f2a4   Mikulas Patocka   dm: mark targets ...
1249

10f1b43cb   Satya Tangirala   FROMLIST: block: ...
1250
  	if (bio_integrity(bio)) {
e2460f2a4   Mikulas Patocka   dm: mark targets ...
1251
1252
1253
1254
1255
1256
1257
  		if (unlikely(!dm_target_has_integrity(tio->ti->type) &&
  			     !dm_target_passes_integrity(tio->ti->type))) {
  			DMWARN("%s: the target %s doesn't support integrity data.",
  				dm_device_name(tio->io->md),
  				tio->ti->type->name);
  			return -EIO;
  		}
cfd7e6c13   Satya Tangirala   FROMLIST: Update ...
1258
1259
1260
  		r = bio_integrity_clone(clone, bio, GFP_NOIO);
  		if (r < 0)
  			return r;
c80914e81   Mike Snitzer   dm: return error ...
1261
  	}
bd2a49b86   Alasdair G Kergon   dm: clean up clon...
1262

fa8db4948   Mike Snitzer   dm: don't use bio...
1263
1264
1265
1266
1267
  	bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
  	clone->bi_iter.bi_size = to_bytes(len);
  
  	if (bio_integrity(bio))
  		bio_integrity_trim(clone);
c80914e81   Mike Snitzer   dm: return error ...
1268
1269
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
  }
318716dde   Mike Snitzer   dm: safely alloca...
1271
1272
  static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
  				struct dm_target *ti, unsigned num_bios)
f9ab94cee   Mikulas Patocka   dm: introduce num...
1273
  {
dba141601   Mikulas Patocka   dm: store dm_targ...
1274
  	struct dm_target_io *tio;
318716dde   Mike Snitzer   dm: safely alloca...
1275
  	int try;
dba141601   Mikulas Patocka   dm: store dm_targ...
1276

318716dde   Mike Snitzer   dm: safely alloca...
1277
1278
  	if (!num_bios)
  		return;
f9ab94cee   Mikulas Patocka   dm: introduce num...
1279

318716dde   Mike Snitzer   dm: safely alloca...
1280
1281
1282
1283
1284
  	if (num_bios == 1) {
  		tio = alloc_tio(ci, ti, 0, GFP_NOIO);
  		bio_list_add(blist, &tio->clone);
  		return;
  	}
9015df24a   Alasdair G Kergon   dm: initialise ti...
1285

318716dde   Mike Snitzer   dm: safely alloca...
1286
1287
1288
1289
1290
  	for (try = 0; try < 2; try++) {
  		int bio_nr;
  		struct bio *bio;
  
  		if (try)
bc02cdbe5   Mike Snitzer   dm: remove redund...
1291
  			mutex_lock(&ci->io->md->table_devices_lock);
318716dde   Mike Snitzer   dm: safely alloca...
1292
1293
1294
1295
1296
1297
1298
1299
  		for (bio_nr = 0; bio_nr < num_bios; bio_nr++) {
  			tio = alloc_tio(ci, ti, bio_nr, try ? GFP_NOIO : GFP_NOWAIT);
  			if (!tio)
  				break;
  
  			bio_list_add(blist, &tio->clone);
  		}
  		if (try)
bc02cdbe5   Mike Snitzer   dm: remove redund...
1300
  			mutex_unlock(&ci->io->md->table_devices_lock);
318716dde   Mike Snitzer   dm: safely alloca...
1301
1302
1303
1304
1305
1306
1307
1308
  		if (bio_nr == num_bios)
  			return;
  
  		while ((bio = bio_list_pop(blist))) {
  			tio = container_of(bio, struct dm_target_io, clone);
  			free_tio(tio);
  		}
  	}
9015df24a   Alasdair G Kergon   dm: initialise ti...
1309
  }
978e51ba3   Mike Snitzer   dm: optimize bio-...
1310
1311
  static blk_qc_t __clone_and_map_simple_bio(struct clone_info *ci,
  					   struct dm_target_io *tio, unsigned *len)
9015df24a   Alasdair G Kergon   dm: initialise ti...
1312
  {
dba141601   Mikulas Patocka   dm: store dm_targ...
1313
  	struct bio *clone = &tio->clone;
9015df24a   Alasdair G Kergon   dm: initialise ti...
1314

1dd40c3ec   Mikulas Patocka   dm: introduce dm_...
1315
  	tio->len_ptr = len;
997782735   Junichi Nomura   dm: remove nr_iov...
1316
  	__bio_clone_fast(clone, ci->bio);
bd2a49b86   Alasdair G Kergon   dm: clean up clon...
1317
  	if (len)
1dd40c3ec   Mikulas Patocka   dm: introduce dm_...
1318
  		bio_setup_sector(clone, ci->sector, *len);
f9ab94cee   Mikulas Patocka   dm: introduce num...
1319

978e51ba3   Mike Snitzer   dm: optimize bio-...
1320
  	return __map_bio(tio);
f9ab94cee   Mikulas Patocka   dm: introduce num...
1321
  }
14fe594d6   Alasdair G Kergon   dm: rename bio cl...
1322
  static void __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
1dd40c3ec   Mikulas Patocka   dm: introduce dm_...
1323
  				  unsigned num_bios, unsigned *len)
06a426cee   Mike Snitzer   dm: use common __...
1324
  {
318716dde   Mike Snitzer   dm: safely alloca...
1325
1326
1327
1328
1329
  	struct bio_list blist = BIO_EMPTY_LIST;
  	struct bio *bio;
  	struct dm_target_io *tio;
  
  	alloc_multiple_bios(&blist, ci, ti, num_bios);
06a426cee   Mike Snitzer   dm: use common __...
1330

318716dde   Mike Snitzer   dm: safely alloca...
1331
1332
  	while ((bio = bio_list_pop(&blist))) {
  		tio = container_of(bio, struct dm_target_io, clone);
978e51ba3   Mike Snitzer   dm: optimize bio-...
1333
  		(void) __clone_and_map_simple_bio(ci, tio, len);
318716dde   Mike Snitzer   dm: safely alloca...
1334
  	}
06a426cee   Mike Snitzer   dm: use common __...
1335
  }
14fe594d6   Alasdair G Kergon   dm: rename bio cl...
1336
  static int __send_empty_flush(struct clone_info *ci)
f9ab94cee   Mikulas Patocka   dm: introduce num...
1337
  {
06a426cee   Mike Snitzer   dm: use common __...
1338
  	unsigned target_nr = 0;
f9ab94cee   Mikulas Patocka   dm: introduce num...
1339
  	struct dm_target *ti;
828678b87   Mike Snitzer   dm: push use of o...
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
  	struct bio flush_bio;
  
  	/*
  	 * Use an on-stack bio for this, it's safe since we don't
  	 * need to reference it after submit. It's just used as
  	 * the basis for the clone(s).
  	 */
  	bio_init(&flush_bio, NULL, 0);
  	flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC;
  	ci->bio = &flush_bio;
  	ci->sector_count = 0;
f9ab94cee   Mikulas Patocka   dm: introduce num...
1351

892ad71f6   Dennis Zhou   dm: set the stati...
1352
  	/*
dbe3ece12   Jens Axboe   dm: don't reuse b...
1353
1354
1355
1356
1357
  	 * Empty flush uses a statically initialized bio, as the base for
  	 * cloning.  However, blkg association requires that a bdev is
  	 * associated with a gendisk, which doesn't happen until the bdev is
  	 * opened.  So, blkg association is done at issue time of the flush
  	 * rather than when the device is created in alloc_dev().
892ad71f6   Dennis Zhou   dm: set the stati...
1358
1359
  	 */
  	bio_set_dev(ci->bio, ci->io->md->bdev);
b372d360d   Mike Snitzer   dm: convey that a...
1360
  	BUG_ON(bio_has_data(ci->bio));
f9ab94cee   Mikulas Patocka   dm: introduce num...
1361
  	while ((ti = dm_table_get_target(ci->map, target_nr++)))
1dd40c3ec   Mikulas Patocka   dm: introduce dm_...
1362
  		__send_duplicate_bios(ci, ti, ti->num_flush_bios, NULL);
828678b87   Mike Snitzer   dm: push use of o...
1363
1364
  
  	bio_uninit(ci->bio);
f9ab94cee   Mikulas Patocka   dm: introduce num...
1365
1366
  	return 0;
  }
c80914e81   Mike Snitzer   dm: return error ...
1367
  static int __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti,
f31c21e43   NeilBrown   dm: remove unused...
1368
  				    sector_t sector, unsigned *len)
5ae89a872   Mike Snitzer   dm: linear suppor...
1369
  {
dba141601   Mikulas Patocka   dm: store dm_targ...
1370
  	struct bio *bio = ci->bio;
5ae89a872   Mike Snitzer   dm: linear suppor...
1371
  	struct dm_target_io *tio;
f31c21e43   NeilBrown   dm: remove unused...
1372
  	int r;
5ae89a872   Mike Snitzer   dm: linear suppor...
1373

318716dde   Mike Snitzer   dm: safely alloca...
1374
  	tio = alloc_tio(ci, ti, 0, GFP_NOIO);
f31c21e43   NeilBrown   dm: remove unused...
1375
1376
1377
1378
1379
  	tio->len_ptr = len;
  	r = clone_bio(tio, bio, sector, *len);
  	if (r < 0) {
  		free_tio(tio);
  		return r;
b0d8ed4d9   Alasdair G Kergon   dm: add target nu...
1380
  	}
978e51ba3   Mike Snitzer   dm: optimize bio-...
1381
  	(void) __map_bio(tio);
c80914e81   Mike Snitzer   dm: return error ...
1382

f31c21e43   NeilBrown   dm: remove unused...
1383
  	return 0;
5ae89a872   Mike Snitzer   dm: linear suppor...
1384
  }
3d7f45625   Mike Snitzer   dm: fix __send_ch...
1385
  static int __send_changing_extent_only(struct clone_info *ci, struct dm_target *ti,
61697a6ab   Mike Snitzer   dm: eliminate 'sp...
1386
  				       unsigned num_bios)
ba1cbad93   Mike Snitzer   dm: handle reques...
1387
  {
51b86f9a8   Michael Lass   dm: make sure to ...
1388
  	unsigned len;
ba1cbad93   Mike Snitzer   dm: handle reques...
1389

3d7f45625   Mike Snitzer   dm: fix __send_ch...
1390
1391
1392
1393
1394
1395
  	/*
  	 * Even though the device advertised support for this type of
  	 * request, that does not mean every target supports it, and
  	 * reconfiguration might also have changed that since the
  	 * check was performed.
  	 */
3d7f45625   Mike Snitzer   dm: fix __send_ch...
1396
1397
  	if (!num_bios)
  		return -EOPNOTSUPP;
ba1cbad93   Mike Snitzer   dm: handle reques...
1398

3720281db   Mike Snitzer   dm: optimize max_...
1399
1400
  	len = min_t(sector_t, ci->sector_count,
  		    max_io_len_target_boundary(ti, dm_target_offset(ti, ci->sector)));
51b86f9a8   Michael Lass   dm: make sure to ...
1401

3d7f45625   Mike Snitzer   dm: fix __send_ch...
1402
  	__send_duplicate_bios(ci, ti, num_bios, &len);
e262f3474   Mikulas Patocka   dm stats: add sup...
1403

3d7f45625   Mike Snitzer   dm: fix __send_ch...
1404
1405
  	ci->sector += len;
  	ci->sector_count -= len;
5ae89a872   Mike Snitzer   dm: linear suppor...
1406
1407
  
  	return 0;
ba1cbad93   Mike Snitzer   dm: handle reques...
1408
  }
568c73a35   Mike Snitzer   dm: update dm_pro...
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
  static bool is_abnormal_io(struct bio *bio)
  {
  	bool r = false;
  
  	switch (bio_op(bio)) {
  	case REQ_OP_DISCARD:
  	case REQ_OP_SECURE_ERASE:
  	case REQ_OP_WRITE_SAME:
  	case REQ_OP_WRITE_ZEROES:
  		r = true;
  		break;
  	}
  
  	return r;
  }
0519c71e8   Mike Snitzer   dm: backfill abno...
1424
1425
1426
1427
  static bool __process_abnormal_io(struct clone_info *ci, struct dm_target *ti,
  				  int *result)
  {
  	struct bio *bio = ci->bio;
9679b5a7e   Mike Snitzer   dm: simplify __pr...
1428
  	unsigned num_bios = 0;
0519c71e8   Mike Snitzer   dm: backfill abno...
1429

9679b5a7e   Mike Snitzer   dm: simplify __pr...
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
  	switch (bio_op(bio)) {
  	case REQ_OP_DISCARD:
  		num_bios = ti->num_discard_bios;
  		break;
  	case REQ_OP_SECURE_ERASE:
  		num_bios = ti->num_secure_erase_bios;
  		break;
  	case REQ_OP_WRITE_SAME:
  		num_bios = ti->num_write_same_bios;
  		break;
  	case REQ_OP_WRITE_ZEROES:
  		num_bios = ti->num_write_zeroes_bios;
  		break;
  	default:
0519c71e8   Mike Snitzer   dm: backfill abno...
1444
  		return false;
9679b5a7e   Mike Snitzer   dm: simplify __pr...
1445
  	}
0519c71e8   Mike Snitzer   dm: backfill abno...
1446

9679b5a7e   Mike Snitzer   dm: simplify __pr...
1447
  	*result = __send_changing_extent_only(ci, ti, num_bios);
0519c71e8   Mike Snitzer   dm: backfill abno...
1448
1449
  	return true;
  }
e4c938111   Alasdair G Kergon   dm: refactor bio ...
1450
  /*
e4c938111   Alasdair G Kergon   dm: refactor bio ...
1451
1452
   * Select the correct strategy for processing a non-flush bio.
   */
14fe594d6   Alasdair G Kergon   dm: rename bio cl...
1453
  static int __split_and_process_non_flush(struct clone_info *ci)
0ce65797a   Mike Snitzer   dm: impose config...
1454
  {
512875bd9   Jun'ichi Nomura   dm: table detect ...
1455
  	struct dm_target *ti;
1c3b13e64   Kent Overstreet   dm: Refactor for ...
1456
  	unsigned len;
c80914e81   Mike Snitzer   dm: return error ...
1457
  	int r;
0ce65797a   Mike Snitzer   dm: impose config...
1458

512875bd9   Jun'ichi Nomura   dm: table detect ...
1459
  	ti = dm_table_find_target(ci->map, ci->sector);
123d87d55   Mikulas Patocka   dm: make dm_table...
1460
  	if (!ti)
512875bd9   Jun'ichi Nomura   dm: table detect ...
1461
  		return -EIO;
568c73a35   Mike Snitzer   dm: update dm_pro...
1462
  	if (__process_abnormal_io(ci, ti, &r))
0519c71e8   Mike Snitzer   dm: backfill abno...
1463
  		return r;
3d7f45625   Mike Snitzer   dm: fix __send_ch...
1464

3720281db   Mike Snitzer   dm: optimize max_...
1465
  	len = min_t(sector_t, max_io_len(ti, ci->sector), ci->sector_count);
0ce65797a   Mike Snitzer   dm: impose config...
1466

c80914e81   Mike Snitzer   dm: return error ...
1467
1468
1469
  	r = __clone_and_map_data_bio(ci, ti, ci->sector, &len);
  	if (r < 0)
  		return r;
0ce65797a   Mike Snitzer   dm: impose config...
1470

1c3b13e64   Kent Overstreet   dm: Refactor for ...
1471
1472
  	ci->sector += len;
  	ci->sector_count -= len;
0ce65797a   Mike Snitzer   dm: impose config...
1473

1c3b13e64   Kent Overstreet   dm: Refactor for ...
1474
  	return 0;
0ce65797a   Mike Snitzer   dm: impose config...
1475
  }
978e51ba3   Mike Snitzer   dm: optimize bio-...
1476
1477
1478
1479
1480
1481
1482
  static void init_clone_info(struct clone_info *ci, struct mapped_device *md,
  			    struct dm_table *map, struct bio *bio)
  {
  	ci->map = map;
  	ci->io = alloc_io(md, bio);
  	ci->sector = bio->bi_iter.bi_sector;
  }
a1e1cb72d   Mike Snitzer   dm: fix redundant...
1483
1484
  #define __dm_part_stat_sub(part, field, subnd)	\
  	(part_stat_get(part, field) -= (subnd))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485
  /*
14fe594d6   Alasdair G Kergon   dm: rename bio cl...
1486
   * Entry point to split a bio into clones and submit them to the targets.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1487
   */
978e51ba3   Mike Snitzer   dm: optimize bio-...
1488
1489
  static blk_qc_t __split_and_process_bio(struct mapped_device *md,
  					struct dm_table *map, struct bio *bio)
0ce65797a   Mike Snitzer   dm: impose config...
1490
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1491
  	struct clone_info ci;
978e51ba3   Mike Snitzer   dm: optimize bio-...
1492
  	blk_qc_t ret = BLK_QC_T_NONE;
512875bd9   Jun'ichi Nomura   dm: table detect ...
1493
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494

978e51ba3   Mike Snitzer   dm: optimize bio-...
1495
  	init_clone_info(&ci, md, map, bio);
0ce65797a   Mike Snitzer   dm: impose config...
1496

1eff9d322   Jens Axboe   block: rename bio...
1497
  	if (bio->bi_opf & REQ_PREFLUSH) {
14fe594d6   Alasdair G Kergon   dm: rename bio cl...
1498
  		error = __send_empty_flush(&ci);
b372d360d   Mike Snitzer   dm: convey that a...
1499
  		/* dec_pending submits any data associated with flush */
2e2d6f7e4   Ajay Joshi   dm: add zone open...
1500
  	} else if (op_is_zone_mgmt(bio_op(bio))) {
a4aa5e56e   Damien Le Moal   dm: fix REQ_OP_ZO...
1501
1502
1503
  		ci.bio = bio;
  		ci.sector_count = 0;
  		error = __split_and_process_non_flush(&ci);
b372d360d   Mike Snitzer   dm: convey that a...
1504
  	} else {
6a8736d10   Tejun Heo   dm: relax orderin...
1505
  		ci.bio = bio;
d87f4c14f   Tejun Heo   dm: implement REQ...
1506
  		ci.sector_count = bio_sectors(bio);
18a25da84   NeilBrown   dm: ensure bio su...
1507
  		while (ci.sector_count && !error) {
14fe594d6   Alasdair G Kergon   dm: rename bio cl...
1508
  			error = __split_and_process_non_flush(&ci);
18a25da84   NeilBrown   dm: ensure bio su...
1509
1510
  			if (current->bio_list && ci.sector_count && !error) {
  				/*
ed00aabd5   Christoph Hellwig   block: rename gen...
1511
  				 * Remainder must be passed to submit_bio_noacct()
18a25da84   NeilBrown   dm: ensure bio su...
1512
1513
1514
  				 * so that it gets handled *after* bios already submitted
  				 * have been completely processed.
  				 * We take a clone of the original to store in
745dc570b   Mike Snitzer   dm: rename 'bio' ...
1515
  				 * ci.io->orig_bio to be used by end_io_acct() and
18a25da84   NeilBrown   dm: ensure bio su...
1516
  				 * for dec_pending to use for completion handling.
18a25da84   NeilBrown   dm: ensure bio su...
1517
  				 */
f21c601a2   Mike Snitzer   dm: use bio_split...
1518
1519
  				struct bio *b = bio_split(bio, bio_sectors(bio) - ci.sector_count,
  							  GFP_NOIO, &md->queue->bio_split);
745dc570b   Mike Snitzer   dm: rename 'bio' ...
1520
  				ci.io->orig_bio = b;
a1e1cb72d   Mike Snitzer   dm: fix redundant...
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
  
  				/*
  				 * Adjust IO stats for each split, otherwise upon queue
  				 * reentry there will be redundant IO accounting.
  				 * NOTE: this is a stop-gap fix, a proper fix involves
  				 * significant refactoring of DM core's bio splitting
  				 * (by eliminating DM's splitting and just using bio_split)
  				 */
  				part_stat_lock();
  				__dm_part_stat_sub(&dm_disk(md)->part0,
  						   sectors[op_stat_group(bio_op(bio))], ci.sector_count);
  				part_stat_unlock();
18a25da84   NeilBrown   dm: ensure bio su...
1533
  				bio_chain(b, bio);
075c18c3e   Mike Snitzer   dm: add missing t...
1534
  				trace_block_split(md->queue, b, bio->bi_iter.bi_sector);
ed00aabd5   Christoph Hellwig   block: rename gen...
1535
  				ret = submit_bio_noacct(bio);
18a25da84   NeilBrown   dm: ensure bio su...
1536
1537
1538
  				break;
  			}
  		}
d87f4c14f   Tejun Heo   dm: implement REQ...
1539
  	}
0ce65797a   Mike Snitzer   dm: impose config...
1540

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541
  	/* drop the extra reference count */
54385bf75   Bart Van Assche   dm: fix the secon...
1542
  	dec_pending(ci.io, errno_to_blk_status(error));
978e51ba3   Mike Snitzer   dm: optimize bio-...
1543
  	return ret;
0ce65797a   Mike Snitzer   dm: impose config...
1544
  }
c62b37d96   Christoph Hellwig   block: move ->mak...
1545
  static blk_qc_t dm_submit_bio(struct bio *bio)
cec47e3d4   Kiyoshi Ueda   dm: prepare for r...
1546
  {
c4a59c4e5   Christoph Hellwig   dm: stop using ->...
1547
  	struct mapped_device *md = bio->bi_disk->private_data;
978e51ba3   Mike Snitzer   dm: optimize bio-...
1548
  	blk_qc_t ret = BLK_QC_T_NONE;
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
1549
1550
  	int srcu_idx;
  	struct dm_table *map;
cec47e3d4   Kiyoshi Ueda   dm: prepare for r...
1551

83d5e5b0a   Mikulas Patocka   dm: optimize use ...
1552
  	map = dm_get_live_table(md, &srcu_idx);
b2abdb1b4   Mike Snitzer   dm: fold dm_proce...
1553
1554
1555
1556
1557
1558
  	if (unlikely(!map)) {
  		DMERR_LIMIT("%s: mapping table unavailable, erroring io",
  			    dm_device_name(md));
  		bio_io_error(bio);
  		goto out;
  	}
29e4013de   Tejun Heo   dm: implement REQ...
1559

b2abdb1b4   Mike Snitzer   dm: fold dm_proce...
1560
  	/* If suspended, queue this IO for later */
6a8736d10   Tejun Heo   dm: relax orderin...
1561
  	if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) {
6abc49468   Konstantin Khlebnikov   dm: add support f...
1562
1563
  		if (bio->bi_opf & REQ_NOWAIT)
  			bio_wouldblock_error(bio);
b2abdb1b4   Mike Snitzer   dm: fold dm_proce...
1564
  		else if (bio->bi_opf & REQ_RAHEAD)
54d9a1b45   Alasdair G Kergon   dm: simplify dm_r...
1565
  			bio_io_error(bio);
b2abdb1b4   Mike Snitzer   dm: fold dm_proce...
1566
1567
1568
  		else
  			queue_io(md, bio);
  		goto out;
cec47e3d4   Kiyoshi Ueda   dm: prepare for r...
1569
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1570

b2abdb1b4   Mike Snitzer   dm: fold dm_proce...
1571
1572
1573
1574
1575
1576
  	/*
  	 * Use blk_queue_split() for abnormal IO (e.g. discard, writesame, etc)
  	 * otherwise associated queue_limits won't be imposed.
  	 */
  	if (is_abnormal_io(bio))
  		blk_queue_split(&bio);
978e51ba3   Mike Snitzer   dm: optimize bio-...
1577

9c37de297   Mike Snitzer   dm: remove specia...
1578
  	ret = __split_and_process_bio(md, map, bio);
b2abdb1b4   Mike Snitzer   dm: fold dm_proce...
1579
  out:
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
1580
  	dm_put_live_table(md, srcu_idx);
978e51ba3   Mike Snitzer   dm: optimize bio-...
1581
1582
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
1584
1585
  /*-----------------------------------------------------------------
   * An IDR is used to keep track of allocated minor numbers.
   *---------------------------------------------------------------*/
2b06cfff1   Alasdair G Kergon   [PATCH] dm: conso...
1586
  static void free_minor(int minor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1587
  {
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
1588
  	spin_lock(&_minor_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
  	idr_remove(&_minor_idr, minor);
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
1590
  	spin_unlock(&_minor_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
1592
1593
1594
1595
  }
  
  /*
   * See if the device with a specific minor # is free.
   */
cf13ab8e0   Frederik Deweerdt   dm: remove md arg...
1596
  static int specific_minor(int minor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1597
  {
c9d76be69   Tejun Heo   dm: convert to id...
1598
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1599
1600
1601
  
  	if (minor >= (1 << MINORBITS))
  		return -EINVAL;
c9d76be69   Tejun Heo   dm: convert to id...
1602
  	idr_preload(GFP_KERNEL);
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
1603
  	spin_lock(&_minor_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604

c9d76be69   Tejun Heo   dm: convert to id...
1605
  	r = idr_alloc(&_minor_idr, MINOR_ALLOCED, minor, minor + 1, GFP_NOWAIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1606

f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
1607
  	spin_unlock(&_minor_lock);
c9d76be69   Tejun Heo   dm: convert to id...
1608
1609
1610
1611
  	idr_preload_end();
  	if (r < 0)
  		return r == -ENOSPC ? -EBUSY : r;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
  }
cf13ab8e0   Frederik Deweerdt   dm: remove md arg...
1613
  static int next_free_minor(int *minor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1614
  {
c9d76be69   Tejun Heo   dm: convert to id...
1615
  	int r;
62f75c2f3   Jeff Mahoney   [PATCH] dm: move ...
1616

c9d76be69   Tejun Heo   dm: convert to id...
1617
  	idr_preload(GFP_KERNEL);
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
1618
  	spin_lock(&_minor_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619

c9d76be69   Tejun Heo   dm: convert to id...
1620
  	r = idr_alloc(&_minor_idr, MINOR_ALLOCED, 0, 1 << MINORBITS, GFP_NOWAIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1621

f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
1622
  	spin_unlock(&_minor_lock);
c9d76be69   Tejun Heo   dm: convert to id...
1623
1624
1625
1626
1627
  	idr_preload_end();
  	if (r < 0)
  		return r;
  	*minor = r;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1628
  }
83d5cde47   Alexey Dobriyan   const: make block...
1629
  static const struct block_device_operations dm_blk_dops;
681cc5e86   Mike Snitzer   dm: fix request-b...
1630
  static const struct block_device_operations dm_rq_blk_dops;
f26c5719b   Dan Williams   dm: add dax_devic...
1631
  static const struct dax_operations dm_dax_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632

53d5914f2   Mikulas Patocka   dm: remove unnece...
1633
  static void dm_wq_work(struct work_struct *work);
bea2b9641   Eric Biggers   ANDROID: dm: add ...
1634
  static void dm_destroy_inline_encryption(struct request_queue *q);
0f20972f7   Mike Snitzer   dm: factor out a ...
1635
1636
  static void cleanup_mapped_device(struct mapped_device *md)
  {
0f20972f7   Mike Snitzer   dm: factor out a ...
1637
1638
  	if (md->wq)
  		destroy_workqueue(md->wq);
6f1c819c2   Kent Overstreet   dm: convert to bi...
1639
1640
  	bioset_exit(&md->bs);
  	bioset_exit(&md->io_bs);
0f20972f7   Mike Snitzer   dm: factor out a ...
1641

f26c5719b   Dan Williams   dm: add dax_devic...
1642
1643
1644
1645
1646
  	if (md->dax_dev) {
  		kill_dax(md->dax_dev);
  		put_dax(md->dax_dev);
  		md->dax_dev = NULL;
  	}
0f20972f7   Mike Snitzer   dm: factor out a ...
1647
1648
1649
1650
  	if (md->disk) {
  		spin_lock(&_minor_lock);
  		md->disk->private_data = NULL;
  		spin_unlock(&_minor_lock);
0f20972f7   Mike Snitzer   dm: factor out a ...
1651
1652
1653
  		del_gendisk(md->disk);
  		put_disk(md->disk);
  	}
bea2b9641   Eric Biggers   ANDROID: dm: add ...
1654
1655
  	if (md->queue) {
  		dm_destroy_inline_encryption(md->queue);
0f20972f7   Mike Snitzer   dm: factor out a ...
1656
  		blk_cleanup_queue(md->queue);
bea2b9641   Eric Biggers   ANDROID: dm: add ...
1657
  	}
0f20972f7   Mike Snitzer   dm: factor out a ...
1658

d09960b00   Tahsin Erdogan   dm: free io_barri...
1659
  	cleanup_srcu_struct(&md->io_barrier);
0f20972f7   Mike Snitzer   dm: factor out a ...
1660
1661
1662
1663
  	if (md->bdev) {
  		bdput(md->bdev);
  		md->bdev = NULL;
  	}
4cc96131a   Mike Snitzer   dm: move request-...
1664

d5ffebdd7   Mike Snitzer   dm: backfill miss...
1665
1666
1667
  	mutex_destroy(&md->suspend_lock);
  	mutex_destroy(&md->type_lock);
  	mutex_destroy(&md->table_devices_lock);
4cc96131a   Mike Snitzer   dm: move request-...
1668
  	dm_mq_cleanup_mapped_device(md);
0f20972f7   Mike Snitzer   dm: factor out a ...
1669
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
1671
1672
  /*
   * Allocate and initialise a blank device with a given minor.
   */
2b06cfff1   Alasdair G Kergon   [PATCH] dm: conso...
1673
  static struct mapped_device *alloc_dev(int minor)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
  {
115485e83   Mike Snitzer   dm: add 'dm_numa_...
1675
1676
  	int r, numa_node_id = dm_get_numa_node();
  	struct mapped_device *md;
ba61fdd17   Jeff Mahoney   [PATCH] dm: fix i...
1677
  	void *old_md;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678

856eb0916   Mikulas Patocka   dm: allocate stru...
1679
  	md = kvzalloc_node(sizeof(*md), GFP_KERNEL, numa_node_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1680
1681
1682
1683
  	if (!md) {
  		DMWARN("unable to allocate device, out of memory.");
  		return NULL;
  	}
10da4f795   Jeff Mahoney   [PATCH] dm: add m...
1684
  	if (!try_module_get(THIS_MODULE))
6ed7ade89   Milan Broz   dm: tidy alloc_de...
1685
  		goto bad_module_get;
10da4f795   Jeff Mahoney   [PATCH] dm: add m...
1686

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1687
  	/* get a minor number for the dev */
2b06cfff1   Alasdair G Kergon   [PATCH] dm: conso...
1688
  	if (minor == DM_ANY_MINOR)
cf13ab8e0   Frederik Deweerdt   dm: remove md arg...
1689
  		r = next_free_minor(&minor);
2b06cfff1   Alasdair G Kergon   [PATCH] dm: conso...
1690
  	else
cf13ab8e0   Frederik Deweerdt   dm: remove md arg...
1691
  		r = specific_minor(minor);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
  	if (r < 0)
6ed7ade89   Milan Broz   dm: tidy alloc_de...
1693
  		goto bad_minor;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1694

83d5e5b0a   Mikulas Patocka   dm: optimize use ...
1695
1696
1697
  	r = init_srcu_struct(&md->io_barrier);
  	if (r < 0)
  		goto bad_io_barrier;
115485e83   Mike Snitzer   dm: add 'dm_numa_...
1698
  	md->numa_node_id = numa_node_id;
591ddcfc4   Mike Snitzer   dm: allow immutab...
1699
  	md->init_tio_pdu = false;
a5664dad7   Mike Snitzer   dm ioctl: make bi...
1700
  	md->type = DM_TYPE_NONE;
e61290a4a   Daniel Walker   dm: convert suspe...
1701
  	mutex_init(&md->suspend_lock);
a5664dad7   Mike Snitzer   dm ioctl: make bi...
1702
  	mutex_init(&md->type_lock);
86f1152b1   Benjamin Marzinski   dm: allow active ...
1703
  	mutex_init(&md->table_devices_lock);
022c26110   Mikulas Patocka   dm: merge pushbac...
1704
  	spin_lock_init(&md->deferred_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1705
  	atomic_set(&md->holders, 1);
5c6bd75d0   Alasdair G Kergon   [PATCH] dm: preve...
1706
  	atomic_set(&md->open_count, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1707
  	atomic_set(&md->event_nr, 0);
7a8c3d3b9   Mike Anderson   dm: uevent genera...
1708
1709
  	atomic_set(&md->uevent_seq, 0);
  	INIT_LIST_HEAD(&md->uevent_list);
86f1152b1   Benjamin Marzinski   dm: allow active ...
1710
  	INIT_LIST_HEAD(&md->table_devices);
7a8c3d3b9   Mike Anderson   dm: uevent genera...
1711
  	spin_lock_init(&md->uevent_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712

47ace7e01   Mike Snitzer   dm: fix potential...
1713
  	/*
c62b37d96   Christoph Hellwig   block: move ->mak...
1714
1715
1716
  	 * default to bio-based until DM table is loaded and md->type
  	 * established. If request-based table is loaded: blk-mq will
  	 * override accordingly.
47ace7e01   Mike Snitzer   dm: fix potential...
1717
  	 */
c62b37d96   Christoph Hellwig   block: move ->mak...
1718
  	md->queue = blk_alloc_queue(numa_node_id);
3d745ea5b   Christoph Hellwig   block: simplify q...
1719
1720
  	if (!md->queue)
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1721

c12c9a3c3   Mike Snitzer   dm: various clean...
1722
  	md->disk = alloc_disk_node(1, md->numa_node_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
  	if (!md->disk)
0f20972f7   Mike Snitzer   dm: factor out a ...
1724
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1725

f0b041153   Jeff Mahoney   [PATCH] dm: fix b...
1726
  	init_waitqueue_head(&md->wait);
53d5914f2   Mikulas Patocka   dm: remove unnece...
1727
  	INIT_WORK(&md->work, dm_wq_work);
f0b041153   Jeff Mahoney   [PATCH] dm: fix b...
1728
  	init_waitqueue_head(&md->eventq);
2995fa78e   Mikulas Patocka   dm sysfs: fix a m...
1729
  	init_completion(&md->kobj_holder.completion);
f0b041153   Jeff Mahoney   [PATCH] dm: fix b...
1730

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1731
1732
1733
1734
1735
1736
  	md->disk->major = _major;
  	md->disk->first_minor = minor;
  	md->disk->fops = &dm_blk_dops;
  	md->disk->queue = md->queue;
  	md->disk->private_data = md;
  	sprintf(md->disk->disk_name, "dm-%d", minor);
f26c5719b   Dan Williams   dm: add dax_devic...
1737

976431b02   Dan Williams   dax, dm: allow de...
1738
  	if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
fefc1d97f   Pankaj Gupta   libnvdimm: add da...
1739
1740
  		md->dax_dev = alloc_dax(md, md->disk->disk_name,
  					&dm_dax_ops, 0);
4e4ced937   Vivek Goyal   dax: Move mandato...
1741
  		if (IS_ERR(md->dax_dev))
976431b02   Dan Williams   dax, dm: allow de...
1742
1743
  			goto bad;
  	}
f26c5719b   Dan Williams   dm: add dax_devic...
1744

c100ec49f   Mike Snitzer   dm: fix incomplet...
1745
  	add_disk_no_queue_reg(md->disk);
7e51f257e   Mike Anderson   [PATCH] dm: store...
1746
  	format_dev_t(md->name, MKDEV(_major, minor));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1747

670368a8d   Tejun Heo   dm: stop using WQ...
1748
  	md->wq = alloc_workqueue("kdmflush", WQ_MEM_RECLAIM, 0);
304f3f6a5   Milan Broz   dm: move deferred...
1749
  	if (!md->wq)
0f20972f7   Mike Snitzer   dm: factor out a ...
1750
  		goto bad;
304f3f6a5   Milan Broz   dm: move deferred...
1751

32a926da5   Mikulas Patocka   dm: always hold b...
1752
1753
  	md->bdev = bdget_disk(md->disk, 0);
  	if (!md->bdev)
0f20972f7   Mike Snitzer   dm: factor out a ...
1754
  		goto bad;
32a926da5   Mikulas Patocka   dm: always hold b...
1755

fd2ed4d25   Mikulas Patocka   dm: add statistic...
1756
  	dm_stats_init(&md->stats);
ba61fdd17   Jeff Mahoney   [PATCH] dm: fix i...
1757
  	/* Populate the mapping, nobody knows we exist yet */
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
1758
  	spin_lock(&_minor_lock);
ba61fdd17   Jeff Mahoney   [PATCH] dm: fix i...
1759
  	old_md = idr_replace(&_minor_idr, md, minor);
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
1760
  	spin_unlock(&_minor_lock);
ba61fdd17   Jeff Mahoney   [PATCH] dm: fix i...
1761
1762
  
  	BUG_ON(old_md != MINOR_ALLOCED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
  	return md;
0f20972f7   Mike Snitzer   dm: factor out a ...
1764
1765
  bad:
  	cleanup_mapped_device(md);
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
1766
  bad_io_barrier:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1767
  	free_minor(minor);
6ed7ade89   Milan Broz   dm: tidy alloc_de...
1768
  bad_minor:
10da4f795   Jeff Mahoney   [PATCH] dm: add m...
1769
  	module_put(THIS_MODULE);
6ed7ade89   Milan Broz   dm: tidy alloc_de...
1770
  bad_module_get:
856eb0916   Mikulas Patocka   dm: allocate stru...
1771
  	kvfree(md);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1772
1773
  	return NULL;
  }
ae9da83f6   Jun'ichi Nomura   dm: fix thaw_bdev
1774
  static void unlock_fs(struct mapped_device *md);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1775
1776
  static void free_dev(struct mapped_device *md)
  {
f331c0296   Tejun Heo   block: don't depe...
1777
  	int minor = MINOR(disk_devt(md->disk));
63d94e482   Jun'ichi Nomura   [PATCH] dm: free ...
1778

32a926da5   Mikulas Patocka   dm: always hold b...
1779
  	unlock_fs(md);
2eb6e1e3a   Keith Busch   dm: submit stacke...
1780

0f20972f7   Mike Snitzer   dm: factor out a ...
1781
  	cleanup_mapped_device(md);
63a4f065e   Mike Snitzer   dm: fix add_disk(...
1782

86f1152b1   Benjamin Marzinski   dm: allow active ...
1783
  	free_table_devices(&md->table_devices);
63a4f065e   Mike Snitzer   dm: fix add_disk(...
1784
  	dm_stats_cleanup(&md->stats);
63a4f065e   Mike Snitzer   dm: fix add_disk(...
1785
  	free_minor(minor);
10da4f795   Jeff Mahoney   [PATCH] dm: add m...
1786
  	module_put(THIS_MODULE);
856eb0916   Mikulas Patocka   dm: allocate stru...
1787
  	kvfree(md);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1788
  }
2a2a4c510   Jens Axboe   dm: use bioset_in...
1789
  static int __bind_mempools(struct mapped_device *md, struct dm_table *t)
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1790
  {
c0820cf5a   Mikulas Patocka   dm: introduce per...
1791
  	struct dm_md_mempools *p = dm_table_get_md_mempools(t);
2a2a4c510   Jens Axboe   dm: use bioset_in...
1792
  	int ret = 0;
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1793

0776aa0e3   Mike Snitzer   dm: ensure bio-ba...
1794
  	if (dm_table_bio_based(t)) {
64f52b0e3   Mike Snitzer   dm: improve perfo...
1795
1796
1797
1798
1799
  		/*
  		 * The md may already have mempools that need changing.
  		 * If so, reload bioset because front_pad may have changed
  		 * because a different table was loaded.
  		 */
6f1c819c2   Kent Overstreet   dm: convert to bi...
1800
1801
  		bioset_exit(&md->bs);
  		bioset_exit(&md->io_bs);
0776aa0e3   Mike Snitzer   dm: ensure bio-ba...
1802

6f1c819c2   Kent Overstreet   dm: convert to bi...
1803
  	} else if (bioset_initialized(&md->bs)) {
4e6e36c37   Mike Snitzer   Revert "dm: do no...
1804
1805
1806
1807
1808
1809
1810
1811
1812
  		/*
  		 * There's no need to reload with request-based dm
  		 * because the size of front_pad doesn't change.
  		 * Note for future: If you are to reload bioset,
  		 * prep-ed requests in the queue may refer
  		 * to bio from the old bioset, so you must walk
  		 * through the queue to unprep.
  		 */
  		goto out;
c0820cf5a   Mikulas Patocka   dm: introduce per...
1813
  	}
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1814

6f1c819c2   Kent Overstreet   dm: convert to bi...
1815
1816
1817
  	BUG_ON(!p ||
  	       bioset_initialized(&md->bs) ||
  	       bioset_initialized(&md->io_bs));
cbc4e3c13   Mike Snitzer   dm: do not alloca...
1818

2a2a4c510   Jens Axboe   dm: use bioset_in...
1819
1820
1821
1822
1823
1824
  	ret = bioset_init_from_src(&md->bs, &p->bs);
  	if (ret)
  		goto out;
  	ret = bioset_init_from_src(&md->io_bs, &p->io_bs);
  	if (ret)
  		bioset_exit(&md->bs);
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1825
  out:
022333427   Mike Snitzer   dm: optimize dm_m...
1826
  	/* mempool bind completed, no longer need any mempools in the table */
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1827
  	dm_table_free_md_mempools(t);
2a2a4c510   Jens Axboe   dm: use bioset_in...
1828
  	return ret;
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1829
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
1831
1832
1833
1834
  /*
   * Bind a table to the device.
   */
  static void event_callback(void *context)
  {
7a8c3d3b9   Mike Anderson   dm: uevent genera...
1835
1836
  	unsigned long flags;
  	LIST_HEAD(uevents);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1837
  	struct mapped_device *md = (struct mapped_device *) context;
7a8c3d3b9   Mike Anderson   dm: uevent genera...
1838
1839
1840
  	spin_lock_irqsave(&md->uevent_lock, flags);
  	list_splice_init(&md->uevent_list, &uevents);
  	spin_unlock_irqrestore(&md->uevent_lock, flags);
ed9e19823   Tejun Heo   block: implement ...
1841
  	dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj);
7a8c3d3b9   Mike Anderson   dm: uevent genera...
1842

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843
1844
  	atomic_inc(&md->event_nr);
  	wake_up(&md->eventq);
62e082430   Mikulas Patocka   dm ioctl: fix ali...
1845
  	dm_issue_global_event();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1846
  }
c217649bf   Mike Snitzer   dm: dont take i_m...
1847
  /*
042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
1848
1849
1850
1851
   * Returns old map, which caller must destroy.
   */
  static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
  			       struct queue_limits *limits)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
  {
042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
1853
  	struct dm_table *old_map;
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1854
  	struct request_queue *q = md->queue;
978e51ba3   Mike Snitzer   dm: optimize bio-...
1855
  	bool request_based = dm_table_request_based(t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1856
  	sector_t size;
2a2a4c510   Jens Axboe   dm: use bioset_in...
1857
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1858

5a8f1f80e   Bart Van Assche   dm: add two lockd...
1859
  	lockdep_assert_held(&md->suspend_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860
  	size = dm_table_get_size(t);
3ac51e741   Darrick J. Wong   [PATCH] dm store ...
1861
1862
1863
1864
  
  	/*
  	 * Wipe any geometry if the size of the table changed.
  	 */
fd2ed4d25   Mikulas Patocka   dm: add statistic...
1865
  	if (size != dm_get_size(md))
3ac51e741   Darrick J. Wong   [PATCH] dm store ...
1866
  		memset(&md->geometry, 0, sizeof(md->geometry));
c2b4bb8cb   Christoph Hellwig   block: fix lockin...
1867
1868
  	set_capacity(md->disk, size);
  	bd_set_nr_sectors(md->bdev, size);
d58168763   Mikulas Patocka   dm table: rework ...
1869

2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
1870
  	dm_table_event_callback(t, event_callback, md);
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1871
1872
1873
1874
1875
1876
1877
  	/*
  	 * The queue hasn't been stopped yet, if the old table type wasn't
  	 * for request-based during suspension.  So stop it to prevent
  	 * I/O mapping before resume.
  	 * This must be done before setting the queue restrictions,
  	 * because request-based dm may be run just after the setting.
  	 */
978e51ba3   Mike Snitzer   dm: optimize bio-...
1878
  	if (request_based)
eca7ee6dc   Mike Snitzer   dm: distinquish o...
1879
  		dm_stop_queue(q);
978e51ba3   Mike Snitzer   dm: optimize bio-...
1880

9c37de297   Mike Snitzer   dm: remove specia...
1881
  	if (request_based) {
16f122661   Mike Snitzer   dm: optimize dm_m...
1882
  		/*
9c37de297   Mike Snitzer   dm: remove specia...
1883
1884
  		 * Leverage the fact that request-based DM targets are
  		 * immutable singletons - used to optimize dm_mq_queue_rq.
16f122661   Mike Snitzer   dm: optimize dm_m...
1885
1886
1887
  		 */
  		md->immutable_target = dm_table_get_immutable_target(t);
  	}
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1888

2a2a4c510   Jens Axboe   dm: use bioset_in...
1889
1890
1891
1892
1893
  	ret = __bind_mempools(md, t);
  	if (ret) {
  		old_map = ERR_PTR(ret);
  		goto out;
  	}
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
1894

a12f5d48b   Eric Dumazet   dm: use rcu_deref...
1895
  	old_map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
1d3aa6f68   Mike Snitzer   dm: remove dummy ...
1896
  	rcu_assign_pointer(md->map, (void *)t);
36a0456fb   Alasdair G Kergon   dm table: add imm...
1897
  	md->immutable_target_type = dm_table_get_immutable_target_type(t);
754c5fc7e   Mike Snitzer   dm: calculate que...
1898
  	dm_table_set_restrictions(t, q, limits);
41abc4e1a   Hannes Reinecke   dm: do not call d...
1899
1900
  	if (old_map)
  		dm_sync_table(md);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901

2a2a4c510   Jens Axboe   dm: use bioset_in...
1902
  out:
042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
1903
  	return old_map;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
  }
a79401559   Alasdair G Kergon   dm: bind new tabl...
1905
1906
1907
1908
  /*
   * Returns unbound table for the caller to free.
   */
  static struct dm_table *__unbind(struct mapped_device *md)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1909
  {
a12f5d48b   Eric Dumazet   dm: use rcu_deref...
1910
  	struct dm_table *map = rcu_dereference_protected(md->map, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1911
1912
  
  	if (!map)
a79401559   Alasdair G Kergon   dm: bind new tabl...
1913
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1914
1915
  
  	dm_table_event_callback(map, NULL, NULL);
9cdb85200   Monam Agarwal   dm: use RCU_INIT_...
1916
  	RCU_INIT_POINTER(md->map, NULL);
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
1917
  	dm_sync_table(md);
a79401559   Alasdair G Kergon   dm: bind new tabl...
1918
1919
  
  	return map;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1920
1921
1922
1923
1924
  }
  
  /*
   * Constructor for a new device.
   */
2b06cfff1   Alasdair G Kergon   [PATCH] dm: conso...
1925
  int dm_create(int minor, struct mapped_device **result)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  {
c12c9a3c3   Mike Snitzer   dm: various clean...
1927
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1928
  	struct mapped_device *md;
2b06cfff1   Alasdair G Kergon   [PATCH] dm: conso...
1929
  	md = alloc_dev(minor);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
  	if (!md)
  		return -ENXIO;
c12c9a3c3   Mike Snitzer   dm: various clean...
1932
1933
1934
1935
1936
  	r = dm_sysfs_init(md);
  	if (r) {
  		free_dev(md);
  		return r;
  	}
784aae735   Milan Broz   dm: add name and ...
1937

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1938
1939
1940
  	*result = md;
  	return 0;
  }
a5664dad7   Mike Snitzer   dm ioctl: make bi...
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
  /*
   * Functions to manage md->type.
   * All are required to hold md->type_lock.
   */
  void dm_lock_md_type(struct mapped_device *md)
  {
  	mutex_lock(&md->type_lock);
  }
  
  void dm_unlock_md_type(struct mapped_device *md)
  {
  	mutex_unlock(&md->type_lock);
  }
7e0d574f2   Bart Van Assche   dm: introduce enu...
1954
  void dm_set_md_type(struct mapped_device *md, enum dm_queue_mode type)
a5664dad7   Mike Snitzer   dm ioctl: make bi...
1955
  {
00c4fc3b1   Mike Snitzer   dm ioctl: increas...
1956
  	BUG_ON(!mutex_is_locked(&md->type_lock));
a5664dad7   Mike Snitzer   dm ioctl: make bi...
1957
1958
  	md->type = type;
  }
7e0d574f2   Bart Van Assche   dm: introduce enu...
1959
  enum dm_queue_mode dm_get_md_type(struct mapped_device *md)
a5664dad7   Mike Snitzer   dm ioctl: make bi...
1960
1961
1962
  {
  	return md->type;
  }
36a0456fb   Alasdair G Kergon   dm table: add imm...
1963
1964
1965
1966
  struct target_type *dm_get_immutable_target_type(struct mapped_device *md)
  {
  	return md->immutable_target_type;
  }
4a0b4ddf2   Mike Snitzer   dm: do not initia...
1967
  /*
f84cb8a46   Mike Snitzer   dm mpath: disable...
1968
1969
1970
1971
1972
1973
1974
1975
1976
   * The queue_limits are only valid as long as you have a reference
   * count on 'md'.
   */
  struct queue_limits *dm_get_queue_limits(struct mapped_device *md)
  {
  	BUG_ON(!atomic_read(&md->holders));
  	return &md->queue->limits;
  }
  EXPORT_SYMBOL_GPL(dm_get_queue_limits);
bea2b9641   Eric Biggers   ANDROID: dm: add ...
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
  #ifdef CONFIG_BLK_INLINE_ENCRYPTION
  struct dm_keyslot_evict_args {
  	const struct blk_crypto_key *key;
  	int err;
  };
  
  static int dm_keyslot_evict_callback(struct dm_target *ti, struct dm_dev *dev,
  				     sector_t start, sector_t len, void *data)
  {
  	struct dm_keyslot_evict_args *args = data;
  	int err;
98777a7eb   Eric Biggers   Merge commit 3826...
1988
  	err = blk_crypto_evict_key(bdev_get_queue(dev->bdev), args->key);
bea2b9641   Eric Biggers   ANDROID: dm: add ...
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
  	if (!args->err)
  		args->err = err;
  	/* Always try to evict the key from all devices. */
  	return 0;
  }
  
  /*
   * When an inline encryption key is evicted from a device-mapper device, evict
   * it from all the underlying devices.
   */
c2b86b727   Satya Tangirala   FROMLIST: Update ...
1999
  static int dm_keyslot_evict(struct blk_keyslot_manager *ksm,
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2000
2001
  			    const struct blk_crypto_key *key, unsigned int slot)
  {
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2002
  	struct mapped_device *md = container_of(ksm, struct mapped_device, ksm);
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
  	struct dm_keyslot_evict_args args = { key };
  	struct dm_table *t;
  	int srcu_idx;
  	int i;
  	struct dm_target *ti;
  
  	t = dm_get_live_table(md, &srcu_idx);
  	if (!t)
  		return 0;
  	for (i = 0; i < dm_table_get_num_targets(t); i++) {
  		ti = dm_table_get_target(t, i);
  		if (!ti->type->iterate_devices)
  			continue;
  		ti->type->iterate_devices(ti, dm_keyslot_evict_callback, &args);
  	}
  	dm_put_live_table(md, srcu_idx);
  	return args.err;
  }
60d41471b   Barani Muthukumaran   ANDROID: dm: add ...
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
  struct dm_derive_raw_secret_args {
  	const u8 *wrapped_key;
  	unsigned int wrapped_key_size;
  	u8 *secret;
  	unsigned int secret_size;
  	int err;
  };
  
  static int dm_derive_raw_secret_callback(struct dm_target *ti,
  					 struct dm_dev *dev, sector_t start,
  					 sector_t len, void *data)
  {
  	struct dm_derive_raw_secret_args *args = data;
98777a7eb   Eric Biggers   Merge commit 3826...
2034
  	struct request_queue *q = bdev_get_queue(dev->bdev);
60d41471b   Barani Muthukumaran   ANDROID: dm: add ...
2035
2036
2037
2038
2039
2040
2041
2042
  
  	if (!args->err)
  		return 0;
  
  	if (!q->ksm) {
  		args->err = -EOPNOTSUPP;
  		return 0;
  	}
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2043
2044
2045
2046
  	args->err = blk_ksm_derive_raw_secret(q->ksm, args->wrapped_key,
  					      args->wrapped_key_size,
  					      args->secret,
  					      args->secret_size);
60d41471b   Barani Muthukumaran   ANDROID: dm: add ...
2047
2048
2049
2050
2051
2052
2053
2054
2055
  	/* Try another device in case this fails. */
  	return 0;
  }
  
  /*
   * Retrieve the raw_secret from the underlying device. Given that
   * only only one raw_secret can exist for a particular wrappedkey,
   * retrieve it only from the first device that supports derive_raw_secret()
   */
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2056
  static int dm_derive_raw_secret(struct blk_keyslot_manager *ksm,
60d41471b   Barani Muthukumaran   ANDROID: dm: add ...
2057
2058
2059
2060
  				const u8 *wrapped_key,
  				unsigned int wrapped_key_size,
  				u8 *secret, unsigned int secret_size)
  {
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2061
  	struct mapped_device *md = container_of(ksm, struct mapped_device, ksm);
60d41471b   Barani Muthukumaran   ANDROID: dm: add ...
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
  	struct dm_derive_raw_secret_args args = {
  		.wrapped_key = wrapped_key,
  		.wrapped_key_size = wrapped_key_size,
  		.secret = secret,
  		.secret_size = secret_size,
  		.err = -EOPNOTSUPP,
  	};
  	struct dm_table *t;
  	int srcu_idx;
  	int i;
  	struct dm_target *ti;
  
  	t = dm_get_live_table(md, &srcu_idx);
  	if (!t)
  		return -EOPNOTSUPP;
  	for (i = 0; i < dm_table_get_num_targets(t); i++) {
  		ti = dm_table_get_target(t, i);
  		if (!ti->type->iterate_devices)
  			continue;
  		ti->type->iterate_devices(ti, dm_derive_raw_secret_callback,
  					  &args);
  		if (!args.err)
  			break;
  	}
  	dm_put_live_table(md, srcu_idx);
  	return args.err;
  }
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2089
  static struct blk_ksm_ll_ops dm_ksm_ll_ops = {
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2090
  	.keyslot_evict = dm_keyslot_evict,
60d41471b   Barani Muthukumaran   ANDROID: dm: add ...
2091
  	.derive_raw_secret = dm_derive_raw_secret,
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2092
  };
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2093
  static void dm_init_inline_encryption(struct mapped_device *md)
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2094
  {
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2095
2096
  	blk_ksm_init_passthrough(&md->ksm);
  	md->ksm.ksm_ll_ops = dm_ksm_ll_ops;
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2097
2098
  
  	/*
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2099
  	 * Initially declare support for all crypto settings. Anything
935b0c41f   Eric Biggers   ANDROID: block: r...
2100
2101
  	 * unsupported by a child device will be removed later when calculating
  	 * the device restrictions.
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2102
  	 */
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2103
2104
2105
2106
2107
2108
2109
  	md->ksm.max_dun_bytes_supported = UINT_MAX;
  	md->ksm.features = BLK_CRYPTO_FEATURE_STANDARD_KEYS |
  			   BLK_CRYPTO_FEATURE_WRAPPED_KEYS;
  	memset(md->ksm.crypto_modes_supported, 0xFF,
  	       sizeof(md->ksm.crypto_modes_supported));
  
  	blk_ksm_register(&md->ksm, md->queue);
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2110
2111
2112
2113
  }
  
  static void dm_destroy_inline_encryption(struct request_queue *q)
  {
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2114
2115
  	blk_ksm_destroy(q->ksm);
  	blk_ksm_unregister(q);
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2116
2117
  }
  #else /* CONFIG_BLK_INLINE_ENCRYPTION */
c2b86b727   Satya Tangirala   FROMLIST: Update ...
2118
  static inline void dm_init_inline_encryption(struct mapped_device *md)
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2119
  {
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2120
2121
2122
2123
2124
2125
  }
  
  static inline void dm_destroy_inline_encryption(struct request_queue *q)
  {
  }
  #endif /* !CONFIG_BLK_INLINE_ENCRYPTION */
4a0b4ddf2   Mike Snitzer   dm: do not initia...
2126
2127
2128
  /*
   * Setup the DM device's queue based on md's type
   */
591ddcfc4   Mike Snitzer   dm: allow immutab...
2129
  int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
4a0b4ddf2   Mike Snitzer   dm: do not initia...
2130
  {
bfebd1cdb   Mike Snitzer   dm: add full blk-...
2131
  	int r;
c100ec49f   Mike Snitzer   dm: fix incomplet...
2132
  	struct queue_limits limits;
7e0d574f2   Bart Van Assche   dm: introduce enu...
2133
  	enum dm_queue_mode type = dm_get_md_type(md);
bfebd1cdb   Mike Snitzer   dm: add full blk-...
2134

545ed20e6   Toshi Kani   dm: add infrastru...
2135
  	switch (type) {
bfebd1cdb   Mike Snitzer   dm: add full blk-...
2136
  	case DM_TYPE_REQUEST_BASED:
681cc5e86   Mike Snitzer   dm: fix request-b...
2137
  		md->disk->fops = &dm_rq_blk_dops;
e83068a5f   Mike Snitzer   dm mpath: add opt...
2138
  		r = dm_mq_init_request_queue(md, t);
bfebd1cdb   Mike Snitzer   dm: add full blk-...
2139
  		if (r) {
681cc5e86   Mike Snitzer   dm: fix request-b...
2140
  			DMERR("Cannot initialize queue for request-based dm mapped device");
bfebd1cdb   Mike Snitzer   dm: add full blk-...
2141
2142
2143
2144
  			return r;
  		}
  		break;
  	case DM_TYPE_BIO_BASED:
545ed20e6   Toshi Kani   dm: add infrastru...
2145
  	case DM_TYPE_DAX_BIO_BASED:
bfebd1cdb   Mike Snitzer   dm: add full blk-...
2146
  		break;
7e0d574f2   Bart Van Assche   dm: introduce enu...
2147
2148
2149
  	case DM_TYPE_NONE:
  		WARN_ON_ONCE(true);
  		break;
4a0b4ddf2   Mike Snitzer   dm: do not initia...
2150
  	}
c100ec49f   Mike Snitzer   dm: fix incomplet...
2151
2152
2153
2154
2155
  	r = dm_calculate_queue_limits(t, &limits);
  	if (r) {
  		DMERR("Cannot calculate initial queue limits");
  		return r;
  	}
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2156

c2b86b727   Satya Tangirala   FROMLIST: Update ...
2157
  	dm_init_inline_encryption(md);
bea2b9641   Eric Biggers   ANDROID: dm: add ...
2158

c100ec49f   Mike Snitzer   dm: fix incomplet...
2159
2160
  	dm_table_set_restrictions(t, md->queue, &limits);
  	blk_register_queue(md->disk);
4a0b4ddf2   Mike Snitzer   dm: do not initia...
2161
2162
  	return 0;
  }
2bec1f4a8   Mikulas Patocka   dm: fix a race co...
2163
  struct mapped_device *dm_get_md(dev_t dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2164
2165
  {
  	struct mapped_device *md;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2166
2167
2168
2169
  	unsigned minor = MINOR(dev);
  
  	if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
  		return NULL;
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
2170
  	spin_lock(&_minor_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2171
2172
  
  	md = idr_find(&_minor_idr, minor);
49de57697   Mike Snitzer   dm: small cleanup...
2173
2174
2175
2176
  	if (!md || md == MINOR_ALLOCED || (MINOR(disk_devt(dm_disk(md))) != minor) ||
  	    test_bit(DMF_FREEING, &md->flags) || dm_deleting_md(md)) {
  		md = NULL;
  		goto out;
fba9f90e5   Jeff Mahoney   [PATCH] dm: add D...
2177
  	}
49de57697   Mike Snitzer   dm: small cleanup...
2178
  	dm_get(md);
fba9f90e5   Jeff Mahoney   [PATCH] dm: add D...
2179
  out:
f32c10b09   Jeff Mahoney   [PATCH] dm: chang...
2180
  	spin_unlock(&_minor_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2181

637842cfd   David Teigland   [PATCH] device-ma...
2182
2183
  	return md;
  }
3cf2e4ba7   Alasdair G Kergon   dm: export dm get md
2184
  EXPORT_SYMBOL_GPL(dm_get_md);
d229a9589   David Teigland   [PATCH] device-ma...
2185

9ade92a9a   Alasdair G Kergon   [PATCH] dm: tidy ...
2186
  void *dm_get_mdptr(struct mapped_device *md)
637842cfd   David Teigland   [PATCH] device-ma...
2187
  {
9ade92a9a   Alasdair G Kergon   [PATCH] dm: tidy ...
2188
  	return md->interface_ptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
  }
  
  void dm_set_mdptr(struct mapped_device *md, void *ptr)
  {
  	md->interface_ptr = ptr;
  }
  
  void dm_get(struct mapped_device *md)
  {
  	atomic_inc(&md->holders);
3f77316de   Kiyoshi Ueda   dm: separate devi...
2199
  	BUG_ON(test_bit(DMF_FREEING, &md->flags));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2200
  }
09ee96b21   Mikulas Patocka   dm snapshot: susp...
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
  int dm_hold(struct mapped_device *md)
  {
  	spin_lock(&_minor_lock);
  	if (test_bit(DMF_FREEING, &md->flags)) {
  		spin_unlock(&_minor_lock);
  		return -EBUSY;
  	}
  	dm_get(md);
  	spin_unlock(&_minor_lock);
  	return 0;
  }
  EXPORT_SYMBOL_GPL(dm_hold);
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
2213
2214
2215
2216
2217
  const char *dm_device_name(struct mapped_device *md)
  {
  	return md->name;
  }
  EXPORT_SYMBOL_GPL(dm_device_name);
3f77316de   Kiyoshi Ueda   dm: separate devi...
2218
  static void __dm_destroy(struct mapped_device *md, bool wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2219
  {
1134e5ae7   Mike Anderson   [PATCH] dm table:...
2220
  	struct dm_table *map;
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
2221
  	int srcu_idx;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2222

3f77316de   Kiyoshi Ueda   dm: separate devi...
2223
  	might_sleep();
fba9f90e5   Jeff Mahoney   [PATCH] dm: add D...
2224

63a4f065e   Mike Snitzer   dm: fix add_disk(...
2225
  	spin_lock(&_minor_lock);
3f77316de   Kiyoshi Ueda   dm: separate devi...
2226
2227
2228
  	idr_replace(&_minor_idr, MINOR_ALLOCED, MINOR(disk_devt(dm_disk(md))));
  	set_bit(DMF_FREEING, &md->flags);
  	spin_unlock(&_minor_lock);
3b785fbcf   Bart Van Assche   dm: mark request_...
2229

c12c9a3c3   Mike Snitzer   dm: various clean...
2230
  	blk_set_queue_dying(md->queue);
3f77316de   Kiyoshi Ueda   dm: separate devi...
2231

ab7c7bb6f   Mikulas Patocka   dm: hold suspend_...
2232
2233
2234
2235
2236
  	/*
  	 * Take suspend_lock so that presuspend and postsuspend methods
  	 * do not race with internal suspend.
  	 */
  	mutex_lock(&md->suspend_lock);
2a708cff9   Junichi Nomura   dm: fix AB-BA dea...
2237
  	map = dm_get_live_table(md, &srcu_idx);
3f77316de   Kiyoshi Ueda   dm: separate devi...
2238
2239
  	if (!dm_suspended_md(md)) {
  		dm_table_presuspend_targets(map);
adc0daad3   Mikulas Patocka   dm: report suspen...
2240
  		set_bit(DMF_SUSPENDED, &md->flags);
5df96f2b9   Mikulas Patocka   dm integrity: fix...
2241
  		set_bit(DMF_POST_SUSPENDING, &md->flags);
3f77316de   Kiyoshi Ueda   dm: separate devi...
2242
  		dm_table_postsuspend_targets(map);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2243
  	}
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
2244
2245
  	/* dm_put_live_table must be before msleep, otherwise deadlock is possible */
  	dm_put_live_table(md, srcu_idx);
2a708cff9   Junichi Nomura   dm: fix AB-BA dea...
2246
  	mutex_unlock(&md->suspend_lock);
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
2247

3f77316de   Kiyoshi Ueda   dm: separate devi...
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
  	/*
  	 * Rare, but there may be I/O requests still going to complete,
  	 * for example.  Wait for all references to disappear.
  	 * No one should increment the reference count of the mapped_device,
  	 * after the mapped_device state becomes DMF_FREEING.
  	 */
  	if (wait)
  		while (atomic_read(&md->holders))
  			msleep(1);
  	else if (atomic_read(&md->holders))
  		DMWARN("%s: Forcibly removing mapped_device still in use! (%d users)",
  		       dm_device_name(md), atomic_read(&md->holders));
  
  	dm_sysfs_exit(md);
3f77316de   Kiyoshi Ueda   dm: separate devi...
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
  	dm_table_destroy(__unbind(md));
  	free_dev(md);
  }
  
  void dm_destroy(struct mapped_device *md)
  {
  	__dm_destroy(md, true);
  }
  
  void dm_destroy_immediate(struct mapped_device *md)
  {
  	__dm_destroy(md, false);
  }
  
  void dm_put(struct mapped_device *md)
  {
  	atomic_dec(&md->holders);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2279
  }
79eb885c9   Edward Goggin   dm mpath: log dev...
2280
  EXPORT_SYMBOL_GPL(dm_put);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2281

85067747c   Ming Lei   dm: do not use wa...
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
  static bool md_in_flight_bios(struct mapped_device *md)
  {
  	int cpu;
  	struct hd_struct *part = &dm_disk(md)->part0;
  	long sum = 0;
  
  	for_each_possible_cpu(cpu) {
  		sum += part_stat_local_read_cpu(part, in_flight[0], cpu);
  		sum += part_stat_local_read_cpu(part, in_flight[1], cpu);
  	}
  
  	return sum != 0;
  }
  
  static int dm_wait_for_bios_completion(struct mapped_device *md, long task_state)
46125c1c9   Milan Broz   dm: refactor dm_s...
2297
2298
  {
  	int r = 0;
9f4c3f874   Bart Van Assche   dm: convert wait ...
2299
  	DEFINE_WAIT(wait);
46125c1c9   Milan Broz   dm: refactor dm_s...
2300

85067747c   Ming Lei   dm: do not use wa...
2301
  	while (true) {
9f4c3f874   Bart Van Assche   dm: convert wait ...
2302
  		prepare_to_wait(&md->wait, &wait, task_state);
46125c1c9   Milan Broz   dm: refactor dm_s...
2303

85067747c   Ming Lei   dm: do not use wa...
2304
  		if (!md_in_flight_bios(md))
46125c1c9   Milan Broz   dm: refactor dm_s...
2305
  			break;
e3fabdfdf   Bart Van Assche   dm: use signal_pe...
2306
  		if (signal_pending_state(task_state, current)) {
46125c1c9   Milan Broz   dm: refactor dm_s...
2307
2308
2309
2310
2311
2312
  			r = -EINTR;
  			break;
  		}
  
  		io_schedule();
  	}
9f4c3f874   Bart Van Assche   dm: convert wait ...
2313
  	finish_wait(&md->wait, &wait);
b44ebeb01   Mikulas Patocka   dm: move wait que...
2314

46125c1c9   Milan Broz   dm: refactor dm_s...
2315
2316
  	return r;
  }
85067747c   Ming Lei   dm: do not use wa...
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
  static int dm_wait_for_completion(struct mapped_device *md, long task_state)
  {
  	int r = 0;
  
  	if (!queue_is_mq(md->queue))
  		return dm_wait_for_bios_completion(md, task_state);
  
  	while (true) {
  		if (!blk_mq_queue_inflight(md->queue))
  			break;
  
  		if (signal_pending_state(task_state, current)) {
  			r = -EINTR;
  			break;
  		}
  
  		msleep(5);
  	}
  
  	return r;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2338
2339
2340
  /*
   * Process the deferred bios
   */
ef2085870   Mikulas Patocka   dm: merge __flush...
2341
  static void dm_wq_work(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2342
  {
0c2915b8c   Mike Snitzer   dm: fix missing i...
2343
2344
  	struct mapped_device *md = container_of(work, struct mapped_device, work);
  	struct bio *bio;
ef2085870   Mikulas Patocka   dm: merge __flush...
2345

3b00b2036   Mikulas Patocka   dm: rework queuei...
2346
  	while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) {
df12ee996   Alasdair G Kergon   dm: rearrange dm_...
2347
  		spin_lock_irq(&md->deferred_lock);
0c2915b8c   Mike Snitzer   dm: fix missing i...
2348
  		bio = bio_list_pop(&md->deferred);
df12ee996   Alasdair G Kergon   dm: rearrange dm_...
2349
  		spin_unlock_irq(&md->deferred_lock);
0c2915b8c   Mike Snitzer   dm: fix missing i...
2350
  		if (!bio)
df12ee996   Alasdair G Kergon   dm: rearrange dm_...
2351
  			break;
022c26110   Mikulas Patocka   dm: merge pushbac...
2352

0c2915b8c   Mike Snitzer   dm: fix missing i...
2353
  		submit_bio_noacct(bio);
022c26110   Mikulas Patocka   dm: merge pushbac...
2354
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2355
  }
9a1fb4644   Mikulas Patocka   dm: remove unnece...
2356
  static void dm_queue_flush(struct mapped_device *md)
304f3f6a5   Milan Broz   dm: move deferred...
2357
  {
3b00b2036   Mikulas Patocka   dm: rework queuei...
2358
  	clear_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
4e857c58e   Peter Zijlstra   arch: Mass conver...
2359
  	smp_mb__after_atomic();
53d5914f2   Mikulas Patocka   dm: remove unnece...
2360
  	queue_work(md->wq, &md->work);
304f3f6a5   Milan Broz   dm: move deferred...
2361
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2362
  /*
042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
2363
   * Swap in a new table, returning the old one for the caller to destroy.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2364
   */
042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
2365
  struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2366
  {
87eb5b21d   Mike Christie   dm: fix limits in...
2367
  	struct dm_table *live_map = NULL, *map = ERR_PTR(-EINVAL);
754c5fc7e   Mike Snitzer   dm: calculate que...
2368
  	struct queue_limits limits;
042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
2369
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2370

e61290a4a   Daniel Walker   dm: convert suspe...
2371
  	mutex_lock(&md->suspend_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2372
2373
  
  	/* device must be suspended */
4f186f8bb   Kiyoshi Ueda   dm: rename dm_sus...
2374
  	if (!dm_suspended_md(md))
93c534aef   Alasdair G Kergon   [PATCH] device-ma...
2375
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2376

3ae706561   Mike Snitzer   dm: retain table ...
2377
2378
2379
2380
2381
2382
2383
  	/*
  	 * If the new table has no data devices, retain the existing limits.
  	 * This helps multipath with queue_if_no_path if all paths disappear,
  	 * then new I/O is queued based on these limits, and then some paths
  	 * reappear.
  	 */
  	if (dm_table_has_no_data_devices(table)) {
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
2384
  		live_map = dm_get_live_table_fast(md);
3ae706561   Mike Snitzer   dm: retain table ...
2385
2386
  		if (live_map)
  			limits = md->queue->limits;
83d5e5b0a   Mikulas Patocka   dm: optimize use ...
2387
  		dm_put_live_table_fast(md);
3ae706561   Mike Snitzer   dm: retain table ...
2388
  	}
87eb5b21d   Mike Christie   dm: fix limits in...
2389
2390
2391
2392
2393
2394
  	if (!live_map) {
  		r = dm_calculate_queue_limits(table, &limits);
  		if (r) {
  			map = ERR_PTR(r);
  			goto out;
  		}
042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
2395
  	}
754c5fc7e   Mike Snitzer   dm: calculate que...
2396

042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
2397
  	map = __bind(md, table, &limits);
62e082430   Mikulas Patocka   dm ioctl: fix ali...
2398
  	dm_issue_global_event();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2399

93c534aef   Alasdair G Kergon   [PATCH] device-ma...
2400
  out:
e61290a4a   Daniel Walker   dm: convert suspe...
2401
  	mutex_unlock(&md->suspend_lock);
042d2a9bc   Alasdair G Kergon   dm: keep old tabl...
2402
  	return map;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2403
2404
2405
2406
2407
2408
  }
  
  /*
   * Functions to lock and unlock any filesystem running on the
   * device.
   */
2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
2409
  static int lock_fs(struct mapped_device *md)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2410
  {
e39e2e95e   Alasdair G Kergon   [PATCH] device-ma...
2411
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2412
2413
  
  	WARN_ON(md->frozen_sb);
dfbe03f6d   Alasdair G Kergon   [PATCH] device-ma...
2414

db8fef4fa   Mikulas Patocka   dm: rename suspen...
2415
  	md->frozen_sb = freeze_bdev(md->bdev);
dfbe03f6d   Alasdair G Kergon   [PATCH] device-ma...
2416
  	if (IS_ERR(md->frozen_sb)) {
cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2417
  		r = PTR_ERR(md->frozen_sb);
e39e2e95e   Alasdair G Kergon   [PATCH] device-ma...
2418
2419
  		md->frozen_sb = NULL;
  		return r;
dfbe03f6d   Alasdair G Kergon   [PATCH] device-ma...
2420
  	}
aa8d7c2fb   Alasdair G Kergon   [PATCH] device-ma...
2421
  	set_bit(DMF_FROZEN, &md->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2422
2423
  	return 0;
  }
2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
2424
  static void unlock_fs(struct mapped_device *md)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2425
  {
aa8d7c2fb   Alasdair G Kergon   [PATCH] device-ma...
2426
2427
  	if (!test_bit(DMF_FROZEN, &md->flags))
  		return;
db8fef4fa   Mikulas Patocka   dm: rename suspen...
2428
  	thaw_bdev(md->bdev, md->frozen_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2429
  	md->frozen_sb = NULL;
aa8d7c2fb   Alasdair G Kergon   [PATCH] device-ma...
2430
  	clear_bit(DMF_FROZEN, &md->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2431
2432
2433
  }
  
  /*
b48633f83   Bart Van Assche   dm: rename task s...
2434
2435
2436
2437
   * @suspend_flags: DM_SUSPEND_LOCKFS_FLAG and/or DM_SUSPEND_NOFLUSH_FLAG
   * @task_state: e.g. TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE
   * @dmf_suspended_flag: DMF_SUSPENDED or DMF_SUSPENDED_INTERNALLY
   *
ffcc39364   Mike Snitzer   dm: enhance inter...
2438
2439
2440
   * If __dm_suspend returns 0, the device is completely quiescent
   * now. There is no request-processing activity. All new requests
   * are being added to md->deferred list.
cec47e3d4   Kiyoshi Ueda   dm: prepare for r...
2441
   */
ffcc39364   Mike Snitzer   dm: enhance inter...
2442
  static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
b48633f83   Bart Van Assche   dm: rename task s...
2443
  			unsigned suspend_flags, long task_state,
eaf9a7361   Mike Snitzer   dm: set DMF_SUSPE...
2444
  			int dmf_suspended_flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2445
  {
ffcc39364   Mike Snitzer   dm: enhance inter...
2446
2447
2448
  	bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
  	bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG;
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2449

5a8f1f80e   Bart Van Assche   dm: add two lockd...
2450
  	lockdep_assert_held(&md->suspend_lock);
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
2451
2452
2453
2454
2455
2456
  	/*
  	 * DMF_NOFLUSH_SUSPENDING must be set before presuspend.
  	 * This flag is cleared before dm_suspend returns.
  	 */
  	if (noflush)
  		set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
86331f39a   Bart Van Assche   dm mpath: make it...
2457
  	else
ac75b09fc   Mike Snitzer   dm: use DMDEBUG m...
2458
  		DMDEBUG("%s: suspending with flush", dm_device_name(md));
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
2459

d67ee213f   Mike Snitzer   dm: add presuspen...
2460
2461
2462
2463
  	/*
  	 * This gets reverted if there's an error later and the targets
  	 * provide the .presuspend_undo hook.
  	 */
cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2464
  	dm_table_presuspend_targets(map);
32a926da5   Mikulas Patocka   dm: always hold b...
2465
  	/*
9f518b27c   Kiyoshi Ueda   dm: simplify requ...
2466
2467
2468
2469
  	 * Flush I/O to the device.
  	 * Any I/O submitted after lock_fs() may not be flushed.
  	 * noflush takes precedence over do_lockfs.
  	 * (lock_fs() flushes I/Os and waits for them to complete.)
32a926da5   Mikulas Patocka   dm: always hold b...
2470
2471
2472
  	 */
  	if (!noflush && do_lockfs) {
  		r = lock_fs(md);
d67ee213f   Mike Snitzer   dm: add presuspen...
2473
2474
  		if (r) {
  			dm_table_presuspend_undo_targets(map);
ffcc39364   Mike Snitzer   dm: enhance inter...
2475
  			return r;
d67ee213f   Mike Snitzer   dm: add presuspen...
2476
  		}
aa8d7c2fb   Alasdair G Kergon   [PATCH] device-ma...
2477
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2478
2479
  
  	/*
3b00b2036   Mikulas Patocka   dm: rework queuei...
2480
2481
  	 * Here we must make sure that no processes are submitting requests
  	 * to target drivers i.e. no one may be executing
0cede372c   Mike Snitzer   dm: fix comment i...
2482
  	 * __split_and_process_bio from dm_submit_bio.
3b00b2036   Mikulas Patocka   dm: rework queuei...
2483
  	 *
0cede372c   Mike Snitzer   dm: fix comment i...
2484
  	 * To get all processes out of __split_and_process_bio in dm_submit_bio,
3b00b2036   Mikulas Patocka   dm: rework queuei...
2485
  	 * we take the write lock. To prevent any process from reentering
0cede372c   Mike Snitzer   dm: fix comment i...
2486
2487
  	 * __split_and_process_bio from dm_submit_bio and quiesce the thread
  	 * (dm_wq_work), we set DMF_BLOCK_IO_FOR_SUSPEND and call
6a8736d10   Tejun Heo   dm: relax orderin...
2488
  	 * flush_workqueue(md->wq).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2489
  	 */
1eb787ec1   Alasdair G Kergon   dm: split DMF_BLO...
2490
  	set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
41abc4e1a   Hannes Reinecke   dm: do not call d...
2491
2492
  	if (map)
  		synchronize_srcu(&md->io_barrier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2493

d0bcb8786   Kiyoshi Ueda   dm: add request b...
2494
  	/*
29e4013de   Tejun Heo   dm: implement REQ...
2495
2496
  	 * Stop md->queue before flushing md->wq in case request-based
  	 * dm defers requests to md->wq from md->queue.
d0bcb8786   Kiyoshi Ueda   dm: add request b...
2497
  	 */
6a23e05c2   Jens Axboe   dm: remove legacy...
2498
  	if (dm_request_based(md))
eca7ee6dc   Mike Snitzer   dm: distinquish o...
2499
  		dm_stop_queue(md->queue);
cec47e3d4   Kiyoshi Ueda   dm: prepare for r...
2500

d0bcb8786   Kiyoshi Ueda   dm: add request b...
2501
  	flush_workqueue(md->wq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2502
  	/*
3b00b2036   Mikulas Patocka   dm: rework queuei...
2503
2504
2505
  	 * At this point no more requests are entering target request routines.
  	 * We call dm_wait_for_completion to wait for all existing requests
  	 * to finish.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2506
  	 */
b48633f83   Bart Van Assche   dm: rename task s...
2507
  	r = dm_wait_for_completion(md, task_state);
eaf9a7361   Mike Snitzer   dm: set DMF_SUSPE...
2508
2509
  	if (!r)
  		set_bit(dmf_suspended_flag, &md->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2510

6d6f10df8   Milan Broz   dm: refactor defe...
2511
  	if (noflush)
022c26110   Mikulas Patocka   dm: merge pushbac...
2512
  		clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
41abc4e1a   Hannes Reinecke   dm: do not call d...
2513
2514
  	if (map)
  		synchronize_srcu(&md->io_barrier);
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
2515

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2516
  	/* were we interrupted ? */
46125c1c9   Milan Broz   dm: refactor dm_s...
2517
  	if (r < 0) {
9a1fb4644   Mikulas Patocka   dm: remove unnece...
2518
  		dm_queue_flush(md);
73d410c01   Milan Broz   dm: tidy dm_suspend
2519

cec47e3d4   Kiyoshi Ueda   dm: prepare for r...
2520
  		if (dm_request_based(md))
eca7ee6dc   Mike Snitzer   dm: distinquish o...
2521
  			dm_start_queue(md->queue);
cec47e3d4   Kiyoshi Ueda   dm: prepare for r...
2522

2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
2523
  		unlock_fs(md);
d67ee213f   Mike Snitzer   dm: add presuspen...
2524
  		dm_table_presuspend_undo_targets(map);
ffcc39364   Mike Snitzer   dm: enhance inter...
2525
  		/* pushback list is already flushed, so skip flush */
2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
2526
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2527

ffcc39364   Mike Snitzer   dm: enhance inter...
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
  	return r;
  }
  
  /*
   * We need to be able to change a mapping table under a mounted
   * filesystem.  For example we might want to move some data in
   * the background.  Before the table can be swapped with
   * dm_bind_table, dm_suspend must be called to flush any in
   * flight bios and ensure that any further io gets deferred.
   */
  /*
   * Suspend mechanism in request-based dm.
   *
   * 1. Flush all I/Os by lock_fs() if needed.
   * 2. Stop dispatching any I/O by stopping the request_queue.
   * 3. Wait for all in-flight I/Os to be completed or requeued.
   *
   * To abort suspend, start the request_queue.
   */
  int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
  {
  	struct dm_table *map = NULL;
  	int r = 0;
  
  retry:
  	mutex_lock_nested(&md->suspend_lock, SINGLE_DEPTH_NESTING);
  
  	if (dm_suspended_md(md)) {
  		r = -EINVAL;
  		goto out_unlock;
  	}
  
  	if (dm_suspended_internally_md(md)) {
  		/* already internally suspended, wait for internal resume */
  		mutex_unlock(&md->suspend_lock);
  		r = wait_on_bit(&md->flags, DMF_SUSPENDED_INTERNALLY, TASK_INTERRUPTIBLE);
  		if (r)
  			return r;
  		goto retry;
  	}
a12f5d48b   Eric Dumazet   dm: use rcu_deref...
2568
  	map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
ffcc39364   Mike Snitzer   dm: enhance inter...
2569

eaf9a7361   Mike Snitzer   dm: set DMF_SUSPE...
2570
  	r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE, DMF_SUSPENDED);
ffcc39364   Mike Snitzer   dm: enhance inter...
2571
2572
  	if (r)
  		goto out_unlock;
3b00b2036   Mikulas Patocka   dm: rework queuei...
2573

5df96f2b9   Mikulas Patocka   dm integrity: fix...
2574
  	set_bit(DMF_POST_SUSPENDING, &md->flags);
4d4471cb5   Kiyoshi Ueda   dm: swap target p...
2575
  	dm_table_postsuspend_targets(map);
5df96f2b9   Mikulas Patocka   dm integrity: fix...
2576
  	clear_bit(DMF_POST_SUSPENDING, &md->flags);
4d4471cb5   Kiyoshi Ueda   dm: swap target p...
2577

d287483d6   Alasdair G Kergon   [PATCH] dm: suspe...
2578
  out_unlock:
e61290a4a   Daniel Walker   dm: convert suspe...
2579
  	mutex_unlock(&md->suspend_lock);
cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2580
  	return r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2581
  }
ffcc39364   Mike Snitzer   dm: enhance inter...
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
  static int __dm_resume(struct mapped_device *md, struct dm_table *map)
  {
  	if (map) {
  		int r = dm_table_resume_targets(map);
  		if (r)
  			return r;
  	}
  
  	dm_queue_flush(md);
  
  	/*
  	 * Flushing deferred I/Os must be done after targets are resumed
  	 * so that mapping of targets can work correctly.
  	 * Request-based dm is queueing the deferred I/Os in its request_queue.
  	 */
  	if (dm_request_based(md))
eca7ee6dc   Mike Snitzer   dm: distinquish o...
2598
  		dm_start_queue(md->queue);
ffcc39364   Mike Snitzer   dm: enhance inter...
2599
2600
2601
2602
2603
  
  	unlock_fs(md);
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2604
2605
  int dm_resume(struct mapped_device *md)
  {
8dc23658b   Minfei Huang   dm: return correc...
2606
  	int r;
cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2607
  	struct dm_table *map = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2608

ffcc39364   Mike Snitzer   dm: enhance inter...
2609
  retry:
8dc23658b   Minfei Huang   dm: return correc...
2610
  	r = -EINVAL;
ffcc39364   Mike Snitzer   dm: enhance inter...
2611
  	mutex_lock_nested(&md->suspend_lock, SINGLE_DEPTH_NESTING);
4f186f8bb   Kiyoshi Ueda   dm: rename dm_sus...
2612
  	if (!dm_suspended_md(md))
cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2613
  		goto out;
cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2614

ffcc39364   Mike Snitzer   dm: enhance inter...
2615
2616
2617
2618
2619
2620
2621
2622
  	if (dm_suspended_internally_md(md)) {
  		/* already internally suspended, wait for internal resume */
  		mutex_unlock(&md->suspend_lock);
  		r = wait_on_bit(&md->flags, DMF_SUSPENDED_INTERNALLY, TASK_INTERRUPTIBLE);
  		if (r)
  			return r;
  		goto retry;
  	}
a12f5d48b   Eric Dumazet   dm: use rcu_deref...
2623
  	map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
2624
  	if (!map || !dm_table_get_size(map))
cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2625
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2626

ffcc39364   Mike Snitzer   dm: enhance inter...
2627
  	r = __dm_resume(md, map);
8757b7764   Milan Broz   [PATCH] dm table:...
2628
2629
  	if (r)
  		goto out;
2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
2630

2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
2631
  	clear_bit(DMF_SUSPENDED, &md->flags);
cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2632
  out:
e61290a4a   Daniel Walker   dm: convert suspe...
2633
  	mutex_unlock(&md->suspend_lock);
2ca3310e7   Alasdair G Kergon   [PATCH] device-ma...
2634

cf222b376   Alasdair G Kergon   [PATCH] device-ma...
2635
  	return r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2636
  }
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2637
2638
2639
2640
  /*
   * Internal suspend/resume works like userspace-driven suspend. It waits
   * until all bios finish and prevents issuing new bios to the target drivers.
   * It may be used only from the kernel.
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2641
   */
ffcc39364   Mike Snitzer   dm: enhance inter...
2642
  static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_flags)
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2643
  {
ffcc39364   Mike Snitzer   dm: enhance inter...
2644
  	struct dm_table *map = NULL;
1ea0654e4   Bart Van Assche   dm: verify suspen...
2645
  	lockdep_assert_held(&md->suspend_lock);
96b26c8c6   Mikulas Patocka   dm: fix handling ...
2646
  	if (md->internal_suspend_count++)
ffcc39364   Mike Snitzer   dm: enhance inter...
2647
2648
2649
2650
2651
2652
  		return; /* nested internal suspend */
  
  	if (dm_suspended_md(md)) {
  		set_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
  		return; /* nest suspend */
  	}
a12f5d48b   Eric Dumazet   dm: use rcu_deref...
2653
  	map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
ffcc39364   Mike Snitzer   dm: enhance inter...
2654
2655
2656
2657
2658
2659
2660
  
  	/*
  	 * Using TASK_UNINTERRUPTIBLE because only NOFLUSH internal suspend is
  	 * supported.  Properly supporting a TASK_INTERRUPTIBLE internal suspend
  	 * would require changing .presuspend to return an error -- avoid this
  	 * until there is a need for more elaborate variants of internal suspend.
  	 */
eaf9a7361   Mike Snitzer   dm: set DMF_SUSPE...
2661
2662
  	(void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
  			    DMF_SUSPENDED_INTERNALLY);
ffcc39364   Mike Snitzer   dm: enhance inter...
2663

5df96f2b9   Mikulas Patocka   dm integrity: fix...
2664
  	set_bit(DMF_POST_SUSPENDING, &md->flags);
ffcc39364   Mike Snitzer   dm: enhance inter...
2665
  	dm_table_postsuspend_targets(map);
5df96f2b9   Mikulas Patocka   dm integrity: fix...
2666
  	clear_bit(DMF_POST_SUSPENDING, &md->flags);
ffcc39364   Mike Snitzer   dm: enhance inter...
2667
2668
2669
2670
  }
  
  static void __dm_internal_resume(struct mapped_device *md)
  {
96b26c8c6   Mikulas Patocka   dm: fix handling ...
2671
2672
2673
  	BUG_ON(!md->internal_suspend_count);
  
  	if (--md->internal_suspend_count)
ffcc39364   Mike Snitzer   dm: enhance inter...
2674
  		return; /* resume from nested internal suspend */
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2675
  	if (dm_suspended_md(md))
ffcc39364   Mike Snitzer   dm: enhance inter...
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
  		goto done; /* resume from nested suspend */
  
  	/*
  	 * NOTE: existing callers don't need to call dm_table_resume_targets
  	 * (which may fail -- so best to avoid it for now by passing NULL map)
  	 */
  	(void) __dm_resume(md, NULL);
  
  done:
  	clear_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
  	smp_mb__after_atomic();
  	wake_up_bit(&md->flags, DMF_SUSPENDED_INTERNALLY);
  }
  
  void dm_internal_suspend_noflush(struct mapped_device *md)
  {
  	mutex_lock(&md->suspend_lock);
  	__dm_internal_suspend(md, DM_SUSPEND_NOFLUSH_FLAG);
  	mutex_unlock(&md->suspend_lock);
  }
  EXPORT_SYMBOL_GPL(dm_internal_suspend_noflush);
  
  void dm_internal_resume(struct mapped_device *md)
  {
  	mutex_lock(&md->suspend_lock);
  	__dm_internal_resume(md);
  	mutex_unlock(&md->suspend_lock);
  }
  EXPORT_SYMBOL_GPL(dm_internal_resume);
  
  /*
   * Fast variants of internal suspend/resume hold md->suspend_lock,
   * which prevents interaction with userspace-driven suspend.
   */
  
  void dm_internal_suspend_fast(struct mapped_device *md)
  {
  	mutex_lock(&md->suspend_lock);
  	if (dm_suspended_md(md) || dm_suspended_internally_md(md))
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2715
2716
2717
2718
2719
2720
2721
  		return;
  
  	set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
  	synchronize_srcu(&md->io_barrier);
  	flush_workqueue(md->wq);
  	dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
  }
b735fede8   Mikulas Patocka   dm snapshot: susp...
2722
  EXPORT_SYMBOL_GPL(dm_internal_suspend_fast);
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2723

ffcc39364   Mike Snitzer   dm: enhance inter...
2724
  void dm_internal_resume_fast(struct mapped_device *md)
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2725
  {
ffcc39364   Mike Snitzer   dm: enhance inter...
2726
  	if (dm_suspended_md(md) || dm_suspended_internally_md(md))
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2727
2728
2729
2730
2731
2732
2733
  		goto done;
  
  	dm_queue_flush(md);
  
  done:
  	mutex_unlock(&md->suspend_lock);
  }
b735fede8   Mikulas Patocka   dm snapshot: susp...
2734
  EXPORT_SYMBOL_GPL(dm_internal_resume_fast);
fd2ed4d25   Mikulas Patocka   dm: add statistic...
2735

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2736
2737
2738
  /*-----------------------------------------------------------------
   * Event notification.
   *---------------------------------------------------------------*/
3abf85b5b   Peter Rajnoha   dm ioctl: introdu...
2739
  int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
60935eb21   Milan Broz   dm ioctl: support...
2740
  		       unsigned cookie)
69267a30b   Alasdair G Kergon   dm: trigger chang...
2741
  {
6958c1c64   Mikulas Patocka   dm: use noio when...
2742
2743
  	int r;
  	unsigned noio_flag;
60935eb21   Milan Broz   dm ioctl: support...
2744
2745
  	char udev_cookie[DM_COOKIE_LENGTH];
  	char *envp[] = { udev_cookie, NULL };
6958c1c64   Mikulas Patocka   dm: use noio when...
2746
  	noio_flag = memalloc_noio_save();
60935eb21   Milan Broz   dm ioctl: support...
2747
  	if (!cookie)
6958c1c64   Mikulas Patocka   dm: use noio when...
2748
  		r = kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
60935eb21   Milan Broz   dm ioctl: support...
2749
2750
2751
  	else {
  		snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
  			 DM_COOKIE_ENV_VAR_NAME, cookie);
6958c1c64   Mikulas Patocka   dm: use noio when...
2752
2753
  		r = kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
  				       action, envp);
60935eb21   Milan Broz   dm ioctl: support...
2754
  	}
6958c1c64   Mikulas Patocka   dm: use noio when...
2755
2756
2757
2758
  
  	memalloc_noio_restore(noio_flag);
  
  	return r;
69267a30b   Alasdair G Kergon   dm: trigger chang...
2759
  }
7a8c3d3b9   Mike Anderson   dm: uevent genera...
2760
2761
2762
2763
  uint32_t dm_next_uevent_seq(struct mapped_device *md)
  {
  	return atomic_add_return(1, &md->uevent_seq);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
  uint32_t dm_get_event_nr(struct mapped_device *md)
  {
  	return atomic_read(&md->event_nr);
  }
  
  int dm_wait_event(struct mapped_device *md, int event_nr)
  {
  	return wait_event_interruptible(md->eventq,
  			(event_nr != atomic_read(&md->event_nr)));
  }
7a8c3d3b9   Mike Anderson   dm: uevent genera...
2774
2775
2776
2777
2778
2779
2780
2781
  void dm_uevent_add(struct mapped_device *md, struct list_head *elist)
  {
  	unsigned long flags;
  
  	spin_lock_irqsave(&md->uevent_lock, flags);
  	list_add(elist, &md->uevent_list);
  	spin_unlock_irqrestore(&md->uevent_lock, flags);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2782
2783
2784
2785
2786
2787
2788
2789
  /*
   * The gendisk is only valid as long as you have a reference
   * count on 'md'.
   */
  struct gendisk *dm_disk(struct mapped_device *md)
  {
  	return md->disk;
  }
65ff5b7dd   Sami Tolvanen   dm verity: add er...
2790
  EXPORT_SYMBOL_GPL(dm_disk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2791

784aae735   Milan Broz   dm: add name and ...
2792
2793
  struct kobject *dm_kobject(struct mapped_device *md)
  {
2995fa78e   Mikulas Patocka   dm sysfs: fix a m...
2794
  	return &md->kobj_holder.kobj;
784aae735   Milan Broz   dm: add name and ...
2795
  }
784aae735   Milan Broz   dm: add name and ...
2796
2797
2798
  struct mapped_device *dm_get_from_kobject(struct kobject *kobj)
  {
  	struct mapped_device *md;
2995fa78e   Mikulas Patocka   dm sysfs: fix a m...
2799
  	md = container_of(kobj, struct mapped_device, kobj_holder.kobj);
784aae735   Milan Broz   dm: add name and ...
2800

b9a41d21d   Hou Tao   dm: fix race betw...
2801
2802
2803
2804
2805
  	spin_lock(&_minor_lock);
  	if (test_bit(DMF_FREEING, &md->flags) || dm_deleting_md(md)) {
  		md = NULL;
  		goto out;
  	}
784aae735   Milan Broz   dm: add name and ...
2806
  	dm_get(md);
b9a41d21d   Hou Tao   dm: fix race betw...
2807
2808
  out:
  	spin_unlock(&_minor_lock);
784aae735   Milan Broz   dm: add name and ...
2809
2810
  	return md;
  }
4f186f8bb   Kiyoshi Ueda   dm: rename dm_sus...
2811
  int dm_suspended_md(struct mapped_device *md)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2812
2813
2814
  {
  	return test_bit(DMF_SUSPENDED, &md->flags);
  }
5df96f2b9   Mikulas Patocka   dm integrity: fix...
2815
2816
2817
2818
  static int dm_post_suspending_md(struct mapped_device *md)
  {
  	return test_bit(DMF_POST_SUSPENDING, &md->flags);
  }
ffcc39364   Mike Snitzer   dm: enhance inter...
2819
2820
2821
2822
  int dm_suspended_internally_md(struct mapped_device *md)
  {
  	return test_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
  }
2c140a246   Mikulas Patocka   dm: allow remove ...
2823
2824
2825
2826
  int dm_test_deferred_remove_flag(struct mapped_device *md)
  {
  	return test_bit(DMF_DEFERRED_REMOVE, &md->flags);
  }
64dbce580   Kiyoshi Ueda   dm: export suspen...
2827
2828
  int dm_suspended(struct dm_target *ti)
  {
33bd6f069   Mike Snitzer   dm table: make 's...
2829
  	return dm_suspended_md(ti->table->md);
64dbce580   Kiyoshi Ueda   dm: export suspen...
2830
2831
  }
  EXPORT_SYMBOL_GPL(dm_suspended);
5df96f2b9   Mikulas Patocka   dm integrity: fix...
2832
2833
  int dm_post_suspending(struct dm_target *ti)
  {
33bd6f069   Mike Snitzer   dm table: make 's...
2834
  	return dm_post_suspending_md(ti->table->md);
5df96f2b9   Mikulas Patocka   dm integrity: fix...
2835
2836
  }
  EXPORT_SYMBOL_GPL(dm_post_suspending);
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
2837
2838
  int dm_noflush_suspending(struct dm_target *ti)
  {
33bd6f069   Mike Snitzer   dm table: make 's...
2839
  	return __noflush_suspending(ti->table->md);
2e93ccc19   Kiyoshi Ueda   [PATCH] dm: suspe...
2840
2841
  }
  EXPORT_SYMBOL_GPL(dm_noflush_suspending);
7e0d574f2   Bart Van Assche   dm: introduce enu...
2842
  struct dm_md_mempools *dm_alloc_md_mempools(struct mapped_device *md, enum dm_queue_mode type,
0776aa0e3   Mike Snitzer   dm: ensure bio-ba...
2843
2844
  					    unsigned integrity, unsigned per_io_data_size,
  					    unsigned min_pool_size)
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
2845
  {
115485e83   Mike Snitzer   dm: add 'dm_numa_...
2846
  	struct dm_md_mempools *pools = kzalloc_node(sizeof(*pools), GFP_KERNEL, md->numa_node_id);
78d8e58a0   Mike Snitzer   Revert "block, dm...
2847
  	unsigned int pool_size = 0;
64f52b0e3   Mike Snitzer   dm: improve perfo...
2848
  	unsigned int front_pad, io_front_pad;
6f1c819c2   Kent Overstreet   dm: convert to bi...
2849
  	int ret;
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
2850
2851
  
  	if (!pools)
4e6e36c37   Mike Snitzer   Revert "dm: do no...
2852
  		return NULL;
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
2853

78d8e58a0   Mike Snitzer   Revert "block, dm...
2854
2855
  	switch (type) {
  	case DM_TYPE_BIO_BASED:
545ed20e6   Toshi Kani   dm: add infrastru...
2856
  	case DM_TYPE_DAX_BIO_BASED:
0776aa0e3   Mike Snitzer   dm: ensure bio-ba...
2857
  		pool_size = max(dm_get_reserved_bio_based_ios(), min_pool_size);
30187e1d4   Mike Snitzer   dm: rename target...
2858
  		front_pad = roundup(per_io_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone);
64f52b0e3   Mike Snitzer   dm: improve perfo...
2859
  		io_front_pad = roundup(front_pad,  __alignof__(struct dm_io)) + offsetof(struct dm_io, tio);
6f1c819c2   Kent Overstreet   dm: convert to bi...
2860
2861
  		ret = bioset_init(&pools->io_bs, pool_size, io_front_pad, 0);
  		if (ret)
64f52b0e3   Mike Snitzer   dm: improve perfo...
2862
  			goto out;
6f1c819c2   Kent Overstreet   dm: convert to bi...
2863
  		if (integrity && bioset_integrity_create(&pools->io_bs, pool_size))
eb8db831b   Christoph Hellwig   dm: always defer ...
2864
  			goto out;
78d8e58a0   Mike Snitzer   Revert "block, dm...
2865
2866
  		break;
  	case DM_TYPE_REQUEST_BASED:
0776aa0e3   Mike Snitzer   dm: ensure bio-ba...
2867
  		pool_size = max(dm_get_reserved_rq_based_ios(), min_pool_size);
78d8e58a0   Mike Snitzer   Revert "block, dm...
2868
  		front_pad = offsetof(struct dm_rq_clone_bio_info, clone);
591ddcfc4   Mike Snitzer   dm: allow immutab...
2869
  		/* per_io_data_size is used for blk-mq pdu at queue allocation */
78d8e58a0   Mike Snitzer   Revert "block, dm...
2870
2871
2872
2873
  		break;
  	default:
  		BUG();
  	}
6f1c819c2   Kent Overstreet   dm: convert to bi...
2874
2875
  	ret = bioset_init(&pools->bs, pool_size, front_pad, 0);
  	if (ret)
5f0152041   Jun'ichi Nomura   dm: merge io_pool...
2876
  		goto out;
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
2877

6f1c819c2   Kent Overstreet   dm: convert to bi...
2878
  	if (integrity && bioset_integrity_create(&pools->bs, pool_size))
5f0152041   Jun'ichi Nomura   dm: merge io_pool...
2879
  		goto out;
a91a2785b   Martin K. Petersen   block: Require su...
2880

e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
2881
  	return pools;
5f1b670d0   Christoph Hellwig   block, dm: don't ...
2882

5f1b670d0   Christoph Hellwig   block, dm: don't ...
2883
2884
  out:
  	dm_free_md_mempools(pools);
78d8e58a0   Mike Snitzer   Revert "block, dm...
2885

4e6e36c37   Mike Snitzer   Revert "dm: do no...
2886
  	return NULL;
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
2887
2888
2889
2890
2891
2892
  }
  
  void dm_free_md_mempools(struct dm_md_mempools *pools)
  {
  	if (!pools)
  		return;
6f1c819c2   Kent Overstreet   dm: convert to bi...
2893
2894
  	bioset_exit(&pools->bs);
  	bioset_exit(&pools->io_bs);
e6ee8c0b7   Kiyoshi Ueda   dm: enable reques...
2895
2896
2897
  
  	kfree(pools);
  }
9c72bad1f   Christoph Hellwig   dm: call PR reser...
2898
2899
2900
2901
2902
2903
2904
2905
2906
  struct dm_pr {
  	u64	old_key;
  	u64	new_key;
  	u32	flags;
  	bool	fail_early;
  };
  
  static int dm_call_pr(struct block_device *bdev, iterate_devices_callout_fn fn,
  		      void *data)
71cdb6978   Christoph Hellwig   dm: add support f...
2907
2908
  {
  	struct mapped_device *md = bdev->bd_disk->private_data;
9c72bad1f   Christoph Hellwig   dm: call PR reser...
2909
2910
2911
  	struct dm_table *table;
  	struct dm_target *ti;
  	int ret = -ENOTTY, srcu_idx;
71cdb6978   Christoph Hellwig   dm: add support f...
2912

9c72bad1f   Christoph Hellwig   dm: call PR reser...
2913
2914
2915
  	table = dm_get_live_table(md, &srcu_idx);
  	if (!table || !dm_table_get_size(table))
  		goto out;
71cdb6978   Christoph Hellwig   dm: add support f...
2916

9c72bad1f   Christoph Hellwig   dm: call PR reser...
2917
2918
2919
2920
  	/* We only support devices that have a single target */
  	if (dm_table_get_num_targets(table) != 1)
  		goto out;
  	ti = dm_table_get_target(table, 0);
71cdb6978   Christoph Hellwig   dm: add support f...
2921

9c72bad1f   Christoph Hellwig   dm: call PR reser...
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
  	ret = -EINVAL;
  	if (!ti->type->iterate_devices)
  		goto out;
  
  	ret = ti->type->iterate_devices(ti, fn, data);
  out:
  	dm_put_live_table(md, srcu_idx);
  	return ret;
  }
  
  /*
   * For register / unregister we need to manually call out to every path.
   */
  static int __dm_pr_register(struct dm_target *ti, struct dm_dev *dev,
  			    sector_t start, sector_t len, void *data)
  {
  	struct dm_pr *pr = data;
  	const struct pr_ops *ops = dev->bdev->bd_disk->fops->pr_ops;
  
  	if (!ops || !ops->pr_register)
  		return -EOPNOTSUPP;
  	return ops->pr_register(dev->bdev, pr->old_key, pr->new_key, pr->flags);
  }
  
  static int dm_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
  			  u32 flags)
  {
  	struct dm_pr pr = {
  		.old_key	= old_key,
  		.new_key	= new_key,
  		.flags		= flags,
  		.fail_early	= true,
  	};
  	int ret;
  
  	ret = dm_call_pr(bdev, __dm_pr_register, &pr);
  	if (ret && new_key) {
  		/* unregister all paths if we failed to register any path */
  		pr.old_key = new_key;
  		pr.new_key = 0;
  		pr.flags = 0;
  		pr.fail_early = false;
  		dm_call_pr(bdev, __dm_pr_register, &pr);
  	}
  
  	return ret;
71cdb6978   Christoph Hellwig   dm: add support f...
2968
2969
2970
  }
  
  static int dm_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,
956a40258   Mike Snitzer   dm: fix sparse "u...
2971
  			 u32 flags)
71cdb6978   Christoph Hellwig   dm: add support f...
2972
2973
2974
  {
  	struct mapped_device *md = bdev->bd_disk->private_data;
  	const struct pr_ops *ops;
971888c46   Mike Snitzer   dm: hold DM table...
2975
  	int r, srcu_idx;
71cdb6978   Christoph Hellwig   dm: add support f...
2976

5bd5e8d89   Mike Snitzer   dm: remove fmode_...
2977
  	r = dm_prepare_ioctl(md, &srcu_idx, &bdev);
71cdb6978   Christoph Hellwig   dm: add support f...
2978
  	if (r < 0)
971888c46   Mike Snitzer   dm: hold DM table...
2979
  		goto out;
71cdb6978   Christoph Hellwig   dm: add support f...
2980
2981
2982
2983
2984
2985
  
  	ops = bdev->bd_disk->fops->pr_ops;
  	if (ops && ops->pr_reserve)
  		r = ops->pr_reserve(bdev, key, type, flags);
  	else
  		r = -EOPNOTSUPP;
971888c46   Mike Snitzer   dm: hold DM table...
2986
2987
  out:
  	dm_unprepare_ioctl(md, srcu_idx);
71cdb6978   Christoph Hellwig   dm: add support f...
2988
2989
2990
2991
2992
2993
2994
  	return r;
  }
  
  static int dm_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
  {
  	struct mapped_device *md = bdev->bd_disk->private_data;
  	const struct pr_ops *ops;
971888c46   Mike Snitzer   dm: hold DM table...
2995
  	int r, srcu_idx;
71cdb6978   Christoph Hellwig   dm: add support f...
2996

5bd5e8d89   Mike Snitzer   dm: remove fmode_...
2997
  	r = dm_prepare_ioctl(md, &srcu_idx, &bdev);
71cdb6978   Christoph Hellwig   dm: add support f...
2998
  	if (r < 0)
971888c46   Mike Snitzer   dm: hold DM table...
2999
  		goto out;
71cdb6978   Christoph Hellwig   dm: add support f...
3000
3001
3002
3003
3004
3005
  
  	ops = bdev->bd_disk->fops->pr_ops;
  	if (ops && ops->pr_release)
  		r = ops->pr_release(bdev, key, type);
  	else
  		r = -EOPNOTSUPP;
971888c46   Mike Snitzer   dm: hold DM table...
3006
3007
  out:
  	dm_unprepare_ioctl(md, srcu_idx);
71cdb6978   Christoph Hellwig   dm: add support f...
3008
3009
3010
3011
  	return r;
  }
  
  static int dm_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key,
956a40258   Mike Snitzer   dm: fix sparse "u...
3012
  			 enum pr_type type, bool abort)
71cdb6978   Christoph Hellwig   dm: add support f...
3013
3014
3015
  {
  	struct mapped_device *md = bdev->bd_disk->private_data;
  	const struct pr_ops *ops;
971888c46   Mike Snitzer   dm: hold DM table...
3016
  	int r, srcu_idx;
71cdb6978   Christoph Hellwig   dm: add support f...
3017

5bd5e8d89   Mike Snitzer   dm: remove fmode_...
3018
  	r = dm_prepare_ioctl(md, &srcu_idx, &bdev);
71cdb6978   Christoph Hellwig   dm: add support f...
3019
  	if (r < 0)
971888c46   Mike Snitzer   dm: hold DM table...
3020
  		goto out;
71cdb6978   Christoph Hellwig   dm: add support f...
3021
3022
3023
3024
3025
3026
  
  	ops = bdev->bd_disk->fops->pr_ops;
  	if (ops && ops->pr_preempt)
  		r = ops->pr_preempt(bdev, old_key, new_key, type, abort);
  	else
  		r = -EOPNOTSUPP;
971888c46   Mike Snitzer   dm: hold DM table...
3027
3028
  out:
  	dm_unprepare_ioctl(md, srcu_idx);
71cdb6978   Christoph Hellwig   dm: add support f...
3029
3030
3031
3032
3033
3034
3035
  	return r;
  }
  
  static int dm_pr_clear(struct block_device *bdev, u64 key)
  {
  	struct mapped_device *md = bdev->bd_disk->private_data;
  	const struct pr_ops *ops;
971888c46   Mike Snitzer   dm: hold DM table...
3036
  	int r, srcu_idx;
71cdb6978   Christoph Hellwig   dm: add support f...
3037

5bd5e8d89   Mike Snitzer   dm: remove fmode_...
3038
  	r = dm_prepare_ioctl(md, &srcu_idx, &bdev);
71cdb6978   Christoph Hellwig   dm: add support f...
3039
  	if (r < 0)
971888c46   Mike Snitzer   dm: hold DM table...
3040
  		goto out;
71cdb6978   Christoph Hellwig   dm: add support f...
3041
3042
3043
3044
3045
3046
  
  	ops = bdev->bd_disk->fops->pr_ops;
  	if (ops && ops->pr_clear)
  		r = ops->pr_clear(bdev, key);
  	else
  		r = -EOPNOTSUPP;
971888c46   Mike Snitzer   dm: hold DM table...
3047
3048
  out:
  	dm_unprepare_ioctl(md, srcu_idx);
71cdb6978   Christoph Hellwig   dm: add support f...
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
  	return r;
  }
  
  static const struct pr_ops dm_pr_ops = {
  	.pr_register	= dm_pr_register,
  	.pr_reserve	= dm_pr_reserve,
  	.pr_release	= dm_pr_release,
  	.pr_preempt	= dm_pr_preempt,
  	.pr_clear	= dm_pr_clear,
  };
83d5cde47   Alexey Dobriyan   const: make block...
3059
  static const struct block_device_operations dm_blk_dops = {
c62b37d96   Christoph Hellwig   block: move ->mak...
3060
  	.submit_bio = dm_submit_bio,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3061
3062
  	.open = dm_blk_open,
  	.release = dm_blk_close,
aa129a224   Milan Broz   [PATCH] dm: suppo...
3063
  	.ioctl = dm_blk_ioctl,
3ac51e741   Darrick J. Wong   [PATCH] dm store ...
3064
  	.getgeo = dm_blk_getgeo,
e76239a37   Christoph Hellwig   block: add a repo...
3065
  	.report_zones = dm_blk_report_zones,
71cdb6978   Christoph Hellwig   dm: add support f...
3066
  	.pr_ops = &dm_pr_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3067
3068
  	.owner = THIS_MODULE
  };
681cc5e86   Mike Snitzer   dm: fix request-b...
3069
3070
3071
3072
3073
3074
3075
3076
  static const struct block_device_operations dm_rq_blk_dops = {
  	.open = dm_blk_open,
  	.release = dm_blk_close,
  	.ioctl = dm_blk_ioctl,
  	.getgeo = dm_blk_getgeo,
  	.pr_ops = &dm_pr_ops,
  	.owner = THIS_MODULE
  };
f26c5719b   Dan Williams   dm: add dax_devic...
3077
3078
  static const struct dax_operations dm_dax_ops = {
  	.direct_access = dm_dax_direct_access,
7bf7eac8d   Dan Williams   dax: Arrange for ...
3079
  	.dax_supported = dm_dax_supported,
7e026c8c0   Dan Williams   dm: add ->copy_fr...
3080
  	.copy_from_iter = dm_dax_copy_from_iter,
b3a9a0c36   Dan Williams   dax: Introduce a ...
3081
  	.copy_to_iter = dm_dax_copy_to_iter,
cdf6cdcd3   Vivek Goyal   dm,dax: Add dax z...
3082
  	.zero_page_range = dm_dax_zero_page_range,
f26c5719b   Dan Williams   dm: add dax_devic...
3083
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3084
3085
3086
3087
3088
3089
3090
3091
  /*
   * module hooks
   */
  module_init(dm_init);
  module_exit(dm_exit);
  
  module_param(major, uint, 0);
  MODULE_PARM_DESC(major, "The major number of the device mapper");
f47908269   Mike Snitzer   dm: add reserved_...
3092

e8603136c   Mike Snitzer   dm: add reserved_...
3093
3094
  module_param(reserved_bio_based_ios, uint, S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(reserved_bio_based_ios, "Reserved IOs in bio-based mempools");
115485e83   Mike Snitzer   dm: add 'dm_numa_...
3095
3096
  module_param(dm_numa_node, int, S_IRUGO | S_IWUSR);
  MODULE_PARM_DESC(dm_numa_node, "NUMA node for DM device memory allocations");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3097
3098
3099
  MODULE_DESCRIPTION(DM_NAME " driver");
  MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
  MODULE_LICENSE("GPL");