Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
3 : : * Copyright (C) 2004 - 2006 Red Hat, Inc. All rights reserved.
4 : : *
5 : : * This file is released under the GPL.
6 : : */
7 : :
8 : : #include "dm.h"
9 : :
10 : : #include <linux/module.h>
11 : : #include <linux/vmalloc.h>
12 : : #include <linux/miscdevice.h>
13 : : #include <linux/init.h>
14 : : #include <linux/wait.h>
15 : : #include <linux/slab.h>
16 : : #include <linux/dm-ioctl.h>
17 : : #include <linux/hdreg.h>
18 : : #include <linux/compat.h>
19 : :
20 : : #include <asm/uaccess.h>
21 : :
22 : : #define DM_MSG_PREFIX "ioctl"
23 : : #define DM_DRIVER_EMAIL "dm-devel@redhat.com"
24 : :
25 : : /*-----------------------------------------------------------------
26 : : * The ioctl interface needs to be able to look up devices by
27 : : * name or uuid.
28 : : *---------------------------------------------------------------*/
29 : : struct hash_cell {
30 : : struct list_head name_list;
31 : : struct list_head uuid_list;
32 : :
33 : : char *name;
34 : : char *uuid;
35 : : struct mapped_device *md;
36 : : struct dm_table *new_map;
37 : : };
38 : :
39 : : /*
40 : : * A dummy definition to make RCU happy.
41 : : * struct dm_table should never be dereferenced in this file.
42 : : */
43 : : struct dm_table {
44 : : int undefined__;
45 : : };
46 : :
47 : : struct vers_iter {
48 : : size_t param_size;
49 : : struct dm_target_versions *vers, *old_vers;
50 : : char *end;
51 : : uint32_t flags;
52 : : };
53 : :
54 : :
55 : : #define NUM_BUCKETS 64
56 : : #define MASK_BUCKETS (NUM_BUCKETS - 1)
57 : : static struct list_head _name_buckets[NUM_BUCKETS];
58 : : static struct list_head _uuid_buckets[NUM_BUCKETS];
59 : :
60 : : static void dm_hash_remove_all(bool keep_open_devices, bool mark_deferred, bool only_deferred);
61 : :
62 : : /*
63 : : * Guards access to both hash tables.
64 : : */
65 : : static DECLARE_RWSEM(_hash_lock);
66 : :
67 : : /*
68 : : * Protects use of mdptr to obtain hash cell name and uuid from mapped device.
69 : : */
70 : : static DEFINE_MUTEX(dm_hash_cells_mutex);
71 : :
72 : : static void init_buckets(struct list_head *buckets)
73 : : {
74 : : unsigned int i;
75 : :
76 [ # # ][ # # ]: 0 : for (i = 0; i < NUM_BUCKETS; i++)
77 : 0 : INIT_LIST_HEAD(buckets + i);
78 : : }
79 : :
80 : 0 : static int dm_hash_init(void)
81 : : {
82 : : init_buckets(_name_buckets);
83 : : init_buckets(_uuid_buckets);
84 : 0 : return 0;
85 : : }
86 : :
87 : : static void dm_hash_exit(void)
88 : : {
89 : 0 : dm_hash_remove_all(false, false, false);
90 : : }
91 : :
92 : : /*-----------------------------------------------------------------
93 : : * Hash function:
94 : : * We're not really concerned with the str hash function being
95 : : * fast since it's only used by the ioctl interface.
96 : : *---------------------------------------------------------------*/
97 : : static unsigned int hash_str(const char *str)
98 : : {
99 : : const unsigned int hash_mult = 2654435387U;
100 : : unsigned int h = 0;
101 : :
102 [ # # ][ # # ]: 0 : while (*str)
[ # # ][ # # ]
[ # # ][ # # ]
103 : 0 : h = (h + (unsigned int) *str++) * hash_mult;
104 : :
105 : 0 : return h & MASK_BUCKETS;
106 : : }
107 : :
108 : : /*-----------------------------------------------------------------
109 : : * Code for looking up a device by name
110 : : *---------------------------------------------------------------*/
111 : 0 : static struct hash_cell *__get_name_cell(const char *str)
112 : : {
113 : : struct hash_cell *hc;
114 : : unsigned int h = hash_str(str);
115 : :
116 [ # # ]: 0 : list_for_each_entry (hc, _name_buckets + h, name_list)
117 [ # # ]: 0 : if (!strcmp(hc->name, str)) {
118 : 0 : dm_get(hc->md);
119 : 0 : return hc;
120 : : }
121 : :
122 : : return NULL;
123 : : }
124 : :
125 : 0 : static struct hash_cell *__get_uuid_cell(const char *str)
126 : : {
127 : : struct hash_cell *hc;
128 : : unsigned int h = hash_str(str);
129 : :
130 [ # # ]: 0 : list_for_each_entry (hc, _uuid_buckets + h, uuid_list)
131 [ # # ]: 0 : if (!strcmp(hc->uuid, str)) {
132 : 0 : dm_get(hc->md);
133 : 0 : return hc;
134 : : }
135 : :
136 : : return NULL;
137 : : }
138 : :
139 : 0 : static struct hash_cell *__get_dev_cell(uint64_t dev)
140 : : {
141 : : struct mapped_device *md;
142 : : struct hash_cell *hc;
143 : :
144 : 0 : md = dm_get_md(huge_decode_dev(dev));
145 [ # # ]: 0 : if (!md)
146 : : return NULL;
147 : :
148 : 0 : hc = dm_get_mdptr(md);
149 [ # # ]: 0 : if (!hc) {
150 : 0 : dm_put(md);
151 : 0 : return NULL;
152 : : }
153 : :
154 : : return hc;
155 : : }
156 : :
157 : : /*-----------------------------------------------------------------
158 : : * Inserting, removing and renaming a device.
159 : : *---------------------------------------------------------------*/
160 : 0 : static struct hash_cell *alloc_cell(const char *name, const char *uuid,
161 : : struct mapped_device *md)
162 : : {
163 : : struct hash_cell *hc;
164 : :
165 : : hc = kmalloc(sizeof(*hc), GFP_KERNEL);
166 [ # # ]: 0 : if (!hc)
167 : : return NULL;
168 : :
169 : 0 : hc->name = kstrdup(name, GFP_KERNEL);
170 [ # # ]: 0 : if (!hc->name) {
171 : 0 : kfree(hc);
172 : 0 : return NULL;
173 : : }
174 : :
175 [ # # ]: 0 : if (!uuid)
176 : 0 : hc->uuid = NULL;
177 : :
178 : : else {
179 : 0 : hc->uuid = kstrdup(uuid, GFP_KERNEL);
180 [ # # ]: 0 : if (!hc->uuid) {
181 : 0 : kfree(hc->name);
182 : 0 : kfree(hc);
183 : 0 : return NULL;
184 : : }
185 : : }
186 : :
187 : 0 : INIT_LIST_HEAD(&hc->name_list);
188 : 0 : INIT_LIST_HEAD(&hc->uuid_list);
189 : 0 : hc->md = md;
190 : 0 : hc->new_map = NULL;
191 : 0 : return hc;
192 : : }
193 : :
194 : 0 : static void free_cell(struct hash_cell *hc)
195 : : {
196 [ # # ]: 0 : if (hc) {
197 : 0 : kfree(hc->name);
198 : 0 : kfree(hc->uuid);
199 : 0 : kfree(hc);
200 : : }
201 : 0 : }
202 : :
203 : : /*
204 : : * The kdev_t and uuid of a device can never change once it is
205 : : * initially inserted.
206 : : */
207 : 0 : static int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
208 : : {
209 : : struct hash_cell *cell, *hc;
210 : :
211 : : /*
212 : : * Allocate the new cells.
213 : : */
214 : 0 : cell = alloc_cell(name, uuid, md);
215 [ # # ]: 0 : if (!cell)
216 : : return -ENOMEM;
217 : :
218 : : /*
219 : : * Insert the cell into both hash tables.
220 : : */
221 : 0 : down_write(&_hash_lock);
222 : 0 : hc = __get_name_cell(name);
223 [ # # ]: 0 : if (hc) {
224 : 0 : dm_put(hc->md);
225 : 0 : goto bad;
226 : : }
227 : :
228 : 0 : list_add(&cell->name_list, _name_buckets + hash_str(name));
229 : :
230 [ # # ]: 0 : if (uuid) {
231 : 0 : hc = __get_uuid_cell(uuid);
232 [ # # ]: 0 : if (hc) {
233 : : list_del(&cell->name_list);
234 : 0 : dm_put(hc->md);
235 : 0 : goto bad;
236 : : }
237 : 0 : list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
238 : : }
239 : 0 : dm_get(md);
240 : 0 : mutex_lock(&dm_hash_cells_mutex);
241 : 0 : dm_set_mdptr(md, cell);
242 : 0 : mutex_unlock(&dm_hash_cells_mutex);
243 : 0 : up_write(&_hash_lock);
244 : :
245 : 0 : return 0;
246 : :
247 : : bad:
248 : 0 : up_write(&_hash_lock);
249 : 0 : free_cell(cell);
250 : 0 : return -EBUSY;
251 : : }
252 : :
253 : 0 : static struct dm_table *__hash_remove(struct hash_cell *hc)
254 : : {
255 : : struct dm_table *table;
256 : : int srcu_idx;
257 : :
258 : : /* remove from the dev hash */
259 : : list_del(&hc->uuid_list);
260 : : list_del(&hc->name_list);
261 : 0 : mutex_lock(&dm_hash_cells_mutex);
262 : 0 : dm_set_mdptr(hc->md, NULL);
263 : 0 : mutex_unlock(&dm_hash_cells_mutex);
264 : :
265 : 0 : table = dm_get_live_table(hc->md, &srcu_idx);
266 [ # # ]: 0 : if (table)
267 : 0 : dm_table_event(table);
268 : 0 : dm_put_live_table(hc->md, srcu_idx);
269 : :
270 : : table = NULL;
271 [ # # ]: 0 : if (hc->new_map)
272 : : table = hc->new_map;
273 : 0 : dm_put(hc->md);
274 : 0 : free_cell(hc);
275 : :
276 : 0 : return table;
277 : : }
278 : :
279 : 0 : static void dm_hash_remove_all(bool keep_open_devices, bool mark_deferred, bool only_deferred)
280 : : {
281 : : int i, dev_skipped;
282 : : struct hash_cell *hc;
283 : : struct mapped_device *md;
284 : : struct dm_table *t;
285 : :
286 : : retry:
287 : : dev_skipped = 0;
288 : :
289 : 0 : down_write(&_hash_lock);
290 : :
291 [ # # ]: 0 : for (i = 0; i < NUM_BUCKETS; i++) {
292 [ # # ]: 0 : list_for_each_entry(hc, _name_buckets + i, name_list) {
293 : 0 : md = hc->md;
294 : 0 : dm_get(md);
295 : :
296 [ # # # # ]: 0 : if (keep_open_devices &&
297 : 0 : dm_lock_for_deletion(md, mark_deferred, only_deferred)) {
298 : 0 : dm_put(md);
299 : 0 : dev_skipped++;
300 : 0 : continue;
301 : : }
302 : :
303 : 0 : t = __hash_remove(hc);
304 : :
305 : 0 : up_write(&_hash_lock);
306 : :
307 [ # # ]: 0 : if (t) {
308 : 0 : dm_sync_table(md);
309 : 0 : dm_table_destroy(t);
310 : : }
311 : 0 : dm_put(md);
312 [ # # ]: 0 : if (likely(keep_open_devices))
313 : 0 : dm_destroy(md);
314 : : else
315 : 0 : dm_destroy_immediate(md);
316 : :
317 : : /*
318 : : * Some mapped devices may be using other mapped
319 : : * devices, so repeat until we make no further
320 : : * progress. If a new mapped device is created
321 : : * here it will also get removed.
322 : : */
323 : : goto retry;
324 : : }
325 : : }
326 : :
327 : 0 : up_write(&_hash_lock);
328 : :
329 [ # # ]: 0 : if (dev_skipped)
330 : 0 : DMWARN("remove_all left %d open device(s)", dev_skipped);
331 : 0 : }
332 : :
333 : : /*
334 : : * Set the uuid of a hash_cell that isn't already set.
335 : : */
336 : 0 : static void __set_cell_uuid(struct hash_cell *hc, char *new_uuid)
337 : : {
338 : 0 : mutex_lock(&dm_hash_cells_mutex);
339 : 0 : hc->uuid = new_uuid;
340 : 0 : mutex_unlock(&dm_hash_cells_mutex);
341 : :
342 : 0 : list_add(&hc->uuid_list, _uuid_buckets + hash_str(new_uuid));
343 : 0 : }
344 : :
345 : : /*
346 : : * Changes the name of a hash_cell and returns the old name for
347 : : * the caller to free.
348 : : */
349 : 0 : static char *__change_cell_name(struct hash_cell *hc, char *new_name)
350 : : {
351 : : char *old_name;
352 : :
353 : : /*
354 : : * Rename and move the name cell.
355 : : */
356 : : list_del(&hc->name_list);
357 : 0 : old_name = hc->name;
358 : :
359 : 0 : mutex_lock(&dm_hash_cells_mutex);
360 : 0 : hc->name = new_name;
361 : 0 : mutex_unlock(&dm_hash_cells_mutex);
362 : :
363 : 0 : list_add(&hc->name_list, _name_buckets + hash_str(new_name));
364 : :
365 : 0 : return old_name;
366 : : }
367 : :
368 : 0 : static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
369 : : const char *new)
370 : : {
371 : : char *new_data, *old_name = NULL;
372 : : struct hash_cell *hc;
373 : : struct dm_table *table;
374 : : struct mapped_device *md;
375 : 0 : unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
376 : : int srcu_idx;
377 : :
378 : : /*
379 : : * duplicate new.
380 : : */
381 : 0 : new_data = kstrdup(new, GFP_KERNEL);
382 [ # # ]: 0 : if (!new_data)
383 : : return ERR_PTR(-ENOMEM);
384 : :
385 : 0 : down_write(&_hash_lock);
386 : :
387 : : /*
388 : : * Is new free ?
389 : : */
390 [ # # ]: 0 : if (change_uuid)
391 : 0 : hc = __get_uuid_cell(new);
392 : : else
393 : 0 : hc = __get_name_cell(new);
394 : :
395 [ # # ]: 0 : if (hc) {
396 [ # # ]: 0 : DMWARN("Unable to change %s on mapped device %s to one that "
397 : : "already exists: %s",
398 : : change_uuid ? "uuid" : "name",
399 : : param->name, new);
400 : 0 : dm_put(hc->md);
401 : 0 : up_write(&_hash_lock);
402 : 0 : kfree(new_data);
403 : 0 : return ERR_PTR(-EBUSY);
404 : : }
405 : :
406 : : /*
407 : : * Is there such a device as 'old' ?
408 : : */
409 : 0 : hc = __get_name_cell(param->name);
410 [ # # ]: 0 : if (!hc) {
411 [ # # ]: 0 : DMWARN("Unable to rename non-existent device, %s to %s%s",
412 : : param->name, change_uuid ? "uuid " : "", new);
413 : 0 : up_write(&_hash_lock);
414 : 0 : kfree(new_data);
415 : 0 : return ERR_PTR(-ENXIO);
416 : : }
417 : :
418 : : /*
419 : : * Does this device already have a uuid?
420 : : */
421 [ # # ][ # # ]: 0 : if (change_uuid && hc->uuid) {
422 : 0 : DMWARN("Unable to change uuid of mapped device %s to %s "
423 : : "because uuid is already set to %s",
424 : : param->name, new, hc->uuid);
425 : 0 : dm_put(hc->md);
426 : 0 : up_write(&_hash_lock);
427 : 0 : kfree(new_data);
428 : 0 : return ERR_PTR(-EINVAL);
429 : : }
430 : :
431 [ # # ]: 0 : if (change_uuid)
432 : 0 : __set_cell_uuid(hc, new_data);
433 : : else
434 : 0 : old_name = __change_cell_name(hc, new_data);
435 : :
436 : : /*
437 : : * Wake up any dm event waiters.
438 : : */
439 : 0 : table = dm_get_live_table(hc->md, &srcu_idx);
440 [ # # ]: 0 : if (table)
441 : 0 : dm_table_event(table);
442 : 0 : dm_put_live_table(hc->md, srcu_idx);
443 : :
444 [ # # ]: 0 : if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, param->event_nr))
445 : 0 : param->flags |= DM_UEVENT_GENERATED_FLAG;
446 : :
447 : 0 : md = hc->md;
448 : 0 : up_write(&_hash_lock);
449 : 0 : kfree(old_name);
450 : :
451 : 0 : return md;
452 : : }
453 : :
454 : 0 : void dm_deferred_remove(void)
455 : : {
456 : 0 : dm_hash_remove_all(true, false, true);
457 : 0 : }
458 : :
459 : : /*-----------------------------------------------------------------
460 : : * Implementation of the ioctl commands
461 : : *---------------------------------------------------------------*/
462 : : /*
463 : : * All the ioctl commands get dispatched to functions with this
464 : : * prototype.
465 : : */
466 : : typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size);
467 : :
468 : 0 : static int remove_all(struct dm_ioctl *param, size_t param_size)
469 : : {
470 : 0 : dm_hash_remove_all(true, !!(param->flags & DM_DEFERRED_REMOVE), false);
471 : 0 : param->data_size = 0;
472 : 0 : return 0;
473 : : }
474 : :
475 : : /*
476 : : * Round up the ptr to an 8-byte boundary.
477 : : */
478 : : #define ALIGN_MASK 7
479 : : static inline void *align_ptr(void *ptr)
480 : : {
481 : 0 : return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK);
482 : : }
483 : :
484 : : /*
485 : : * Retrieves the data payload buffer from an already allocated
486 : : * struct dm_ioctl.
487 : : */
488 : : static void *get_result_buffer(struct dm_ioctl *param, size_t param_size,
489 : : size_t *len)
490 : : {
491 : 0 : param->data_start = align_ptr(param + 1) - (void *) param;
492 : :
493 [ # # ][ # # ]: 0 : if (param->data_start < param_size)
[ # # # # ]
[ # # ]
494 : 0 : *len = param_size - param->data_start;
495 : : else
496 : : *len = 0;
497 : :
498 : 0 : return ((void *) param) + param->data_start;
499 : : }
500 : :
501 : 0 : static int list_devices(struct dm_ioctl *param, size_t param_size)
502 : : {
503 : : unsigned int i;
504 : : struct hash_cell *hc;
505 : : size_t len, needed = 0;
506 : 0 : struct gendisk *disk;
507 : : struct dm_name_list *nl, *old_nl = NULL;
508 : :
509 : 0 : down_write(&_hash_lock);
510 : :
511 : : /*
512 : : * Loop through all the devices working out how much
513 : : * space we need.
514 : : */
515 [ # # ]: 0 : for (i = 0; i < NUM_BUCKETS; i++) {
516 [ # # ]: 0 : list_for_each_entry (hc, _name_buckets + i, name_list) {
517 : 0 : needed += sizeof(struct dm_name_list);
518 : 0 : needed += strlen(hc->name) + 1;
519 : 0 : needed += ALIGN_MASK;
520 : : }
521 : : }
522 : :
523 : : /*
524 : : * Grab our output buffer.
525 : : */
526 : : nl = get_result_buffer(param, param_size, &len);
527 [ # # ]: 0 : if (len < needed) {
528 : 0 : param->flags |= DM_BUFFER_FULL_FLAG;
529 : 0 : goto out;
530 : : }
531 : 0 : param->data_size = param->data_start + needed;
532 : :
533 : 0 : nl->dev = 0; /* Flags no data */
534 : :
535 : : /*
536 : : * Now loop through filling out the names.
537 : : */
538 [ # # ]: 0 : for (i = 0; i < NUM_BUCKETS; i++) {
539 [ # # ]: 0 : list_for_each_entry (hc, _name_buckets + i, name_list) {
540 [ # # ]: 0 : if (old_nl)
541 : 0 : old_nl->next = (uint32_t) ((void *) nl -
542 : : (void *) old_nl);
543 : 0 : disk = dm_disk(hc->md);
544 : 0 : nl->dev = huge_encode_dev(disk_devt(disk));
545 : 0 : nl->next = 0;
546 : 0 : strcpy(nl->name, hc->name);
547 : :
548 : : old_nl = nl;
549 : 0 : nl = align_ptr(((void *) ++nl) + strlen(hc->name) + 1);
550 : : }
551 : : }
552 : :
553 : : out:
554 : 0 : up_write(&_hash_lock);
555 : 0 : return 0;
556 : : }
557 : :
558 : 0 : static void list_version_get_needed(struct target_type *tt, void *needed_param)
559 : : {
560 : : size_t *needed = needed_param;
561 : :
562 : 0 : *needed += sizeof(struct dm_target_versions);
563 : 0 : *needed += strlen(tt->name);
564 : 0 : *needed += ALIGN_MASK;
565 : 0 : }
566 : :
567 : 0 : static void list_version_get_info(struct target_type *tt, void *param)
568 : : {
569 : : struct vers_iter *info = param;
570 : :
571 : : /* Check space - it might have changed since the first iteration */
572 [ # # ]: 0 : if ((char *)info->vers + sizeof(tt->version) + strlen(tt->name) + 1 >
573 : 0 : info->end) {
574 : :
575 : 0 : info->flags = DM_BUFFER_FULL_FLAG;
576 : 0 : return;
577 : : }
578 : :
579 [ # # ]: 0 : if (info->old_vers)
580 : 0 : info->old_vers->next = (uint32_t) ((void *)info->vers -
581 : : (void *)info->old_vers);
582 : 0 : info->vers->version[0] = tt->version[0];
583 : 0 : info->vers->version[1] = tt->version[1];
584 : 0 : info->vers->version[2] = tt->version[2];
585 : 0 : info->vers->next = 0;
586 : 0 : strcpy(info->vers->name, tt->name);
587 : :
588 : 0 : info->old_vers = info->vers;
589 : 0 : info->vers = align_ptr(((void *) ++info->vers) + strlen(tt->name) + 1);
590 : : }
591 : :
592 : 0 : static int list_versions(struct dm_ioctl *param, size_t param_size)
593 : : {
594 : 0 : size_t len, needed = 0;
595 : : struct dm_target_versions *vers;
596 : : struct vers_iter iter_info;
597 : :
598 : : /*
599 : : * Loop through all the devices working out how much
600 : : * space we need.
601 : : */
602 : 0 : dm_target_iterate(list_version_get_needed, &needed);
603 : :
604 : : /*
605 : : * Grab our output buffer.
606 : : */
607 : : vers = get_result_buffer(param, param_size, &len);
608 [ # # ]: 0 : if (len < needed) {
609 : 0 : param->flags |= DM_BUFFER_FULL_FLAG;
610 : 0 : goto out;
611 : : }
612 : 0 : param->data_size = param->data_start + needed;
613 : :
614 : 0 : iter_info.param_size = param_size;
615 : 0 : iter_info.old_vers = NULL;
616 : 0 : iter_info.vers = vers;
617 : 0 : iter_info.flags = 0;
618 : 0 : iter_info.end = (char *)vers+len;
619 : :
620 : : /*
621 : : * Now loop through filling out the names & versions.
622 : : */
623 : 0 : dm_target_iterate(list_version_get_info, &iter_info);
624 : 0 : param->flags |= iter_info.flags;
625 : :
626 : : out:
627 : 0 : return 0;
628 : : }
629 : :
630 : 0 : static int check_name(const char *name)
631 : : {
632 [ # # ]: 0 : if (strchr(name, '/')) {
633 : 0 : DMWARN("invalid device name");
634 : 0 : return -EINVAL;
635 : : }
636 : :
637 : : return 0;
638 : : }
639 : :
640 : : /*
641 : : * On successful return, the caller must not attempt to acquire
642 : : * _hash_lock without first calling dm_table_put, because dm_table_destroy
643 : : * waits for this dm_table_put and could be called under this lock.
644 : : */
645 : 0 : static struct dm_table *dm_get_inactive_table(struct mapped_device *md, int *srcu_idx)
646 : : {
647 : : struct hash_cell *hc;
648 : : struct dm_table *table = NULL;
649 : :
650 : : /* increment rcu count, we don't care about the table pointer */
651 : 0 : dm_get_live_table(md, srcu_idx);
652 : :
653 : 0 : down_read(&_hash_lock);
654 : 0 : hc = dm_get_mdptr(md);
655 [ # # ][ # # ]: 0 : if (!hc || hc->md != md) {
656 : 0 : DMWARN("device has been removed from the dev hash table.");
657 : 0 : goto out;
658 : : }
659 : :
660 : 0 : table = hc->new_map;
661 : :
662 : : out:
663 : 0 : up_read(&_hash_lock);
664 : :
665 : 0 : return table;
666 : : }
667 : :
668 : 0 : static struct dm_table *dm_get_live_or_inactive_table(struct mapped_device *md,
669 : : struct dm_ioctl *param,
670 : : int *srcu_idx)
671 : : {
672 : 0 : return (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) ?
673 [ # # ]: 0 : dm_get_inactive_table(md, srcu_idx) : dm_get_live_table(md, srcu_idx);
674 : : }
675 : :
676 : : /*
677 : : * Fills in a dm_ioctl structure, ready for sending back to
678 : : * userland.
679 : : */
680 : 0 : static void __dev_status(struct mapped_device *md, struct dm_ioctl *param)
681 : : {
682 : 0 : struct gendisk *disk = dm_disk(md);
683 : : struct dm_table *table;
684 : : int srcu_idx;
685 : :
686 : 0 : param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG |
687 : : DM_ACTIVE_PRESENT_FLAG);
688 : :
689 [ # # ]: 0 : if (dm_suspended_md(md))
690 : 0 : param->flags |= DM_SUSPEND_FLAG;
691 : :
692 [ # # ]: 0 : if (dm_test_deferred_remove_flag(md))
693 : 0 : param->flags |= DM_DEFERRED_REMOVE;
694 : :
695 : 0 : param->dev = huge_encode_dev(disk_devt(disk));
696 : :
697 : : /*
698 : : * Yes, this will be out of date by the time it gets back
699 : : * to userland, but it is still very useful for
700 : : * debugging.
701 : : */
702 : 0 : param->open_count = dm_open_count(md);
703 : :
704 : 0 : param->event_nr = dm_get_event_nr(md);
705 : 0 : param->target_count = 0;
706 : :
707 : 0 : table = dm_get_live_table(md, &srcu_idx);
708 [ # # ]: 0 : if (table) {
709 [ # # ]: 0 : if (!(param->flags & DM_QUERY_INACTIVE_TABLE_FLAG)) {
710 [ # # ]: 0 : if (get_disk_ro(disk))
711 : 0 : param->flags |= DM_READONLY_FLAG;
712 : 0 : param->target_count = dm_table_get_num_targets(table);
713 : : }
714 : :
715 : 0 : param->flags |= DM_ACTIVE_PRESENT_FLAG;
716 : : }
717 : 0 : dm_put_live_table(md, srcu_idx);
718 : :
719 [ # # ]: 0 : if (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) {
720 : : int srcu_idx;
721 : 0 : table = dm_get_inactive_table(md, &srcu_idx);
722 [ # # ]: 0 : if (table) {
723 [ # # ]: 0 : if (!(dm_table_get_mode(table) & FMODE_WRITE))
724 : 0 : param->flags |= DM_READONLY_FLAG;
725 : 0 : param->target_count = dm_table_get_num_targets(table);
726 : : }
727 : 0 : dm_put_live_table(md, srcu_idx);
728 : : }
729 : 0 : }
730 : :
731 : 0 : static int dev_create(struct dm_ioctl *param, size_t param_size)
732 : : {
733 : : int r, m = DM_ANY_MINOR;
734 : : struct mapped_device *md;
735 : :
736 : 0 : r = check_name(param->name);
737 [ # # ]: 0 : if (r)
738 : : return r;
739 : :
740 [ # # ]: 0 : if (param->flags & DM_PERSISTENT_DEV_FLAG)
741 : 0 : m = MINOR(huge_decode_dev(param->dev));
742 : :
743 : 0 : r = dm_create(m, &md);
744 [ # # ]: 0 : if (r)
745 : : return r;
746 : :
747 [ # # ]: 0 : r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
748 [ # # ]: 0 : if (r) {
749 : 0 : dm_put(md);
750 : 0 : dm_destroy(md);
751 : 0 : return r;
752 : : }
753 : :
754 : 0 : param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
755 : :
756 : 0 : __dev_status(md, param);
757 : :
758 : 0 : dm_put(md);
759 : :
760 : 0 : return 0;
761 : : }
762 : :
763 : : /*
764 : : * Always use UUID for lookups if it's present, otherwise use name or dev.
765 : : */
766 : 0 : static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
767 : : {
768 : : struct hash_cell *hc = NULL;
769 : :
770 [ # # ]: 0 : if (*param->uuid) {
771 [ # # ][ # # ]: 0 : if (*param->name || param->dev)
772 : : return NULL;
773 : :
774 : 0 : hc = __get_uuid_cell(param->uuid);
775 [ # # ]: 0 : if (!hc)
776 : : return NULL;
777 [ # # ]: 0 : } else if (*param->name) {
778 [ # # ]: 0 : if (param->dev)
779 : : return NULL;
780 : :
781 : 0 : hc = __get_name_cell(param->name);
782 [ # # ]: 0 : if (!hc)
783 : : return NULL;
784 [ # # ]: 0 : } else if (param->dev) {
785 : 0 : hc = __get_dev_cell(param->dev);
786 [ # # ]: 0 : if (!hc)
787 : : return NULL;
788 : : } else
789 : : return NULL;
790 : :
791 : : /*
792 : : * Sneakily write in both the name and the uuid
793 : : * while we have the cell.
794 : : */
795 : 0 : strlcpy(param->name, hc->name, sizeof(param->name));
796 [ # # ]: 0 : if (hc->uuid)
797 : 0 : strlcpy(param->uuid, hc->uuid, sizeof(param->uuid));
798 : : else
799 : 0 : param->uuid[0] = '\0';
800 : :
801 [ # # ]: 0 : if (hc->new_map)
802 : 0 : param->flags |= DM_INACTIVE_PRESENT_FLAG;
803 : : else
804 : 0 : param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
805 : :
806 : 0 : return hc;
807 : : }
808 : :
809 : 0 : static struct mapped_device *find_device(struct dm_ioctl *param)
810 : : {
811 : : struct hash_cell *hc;
812 : : struct mapped_device *md = NULL;
813 : :
814 : 0 : down_read(&_hash_lock);
815 : 0 : hc = __find_device_hash_cell(param);
816 [ # # ]: 0 : if (hc)
817 : 0 : md = hc->md;
818 : 0 : up_read(&_hash_lock);
819 : :
820 : 0 : return md;
821 : : }
822 : :
823 : 0 : static int dev_remove(struct dm_ioctl *param, size_t param_size)
824 : : {
825 : : struct hash_cell *hc;
826 : : struct mapped_device *md;
827 : : int r;
828 : : struct dm_table *t;
829 : :
830 : 0 : down_write(&_hash_lock);
831 : 0 : hc = __find_device_hash_cell(param);
832 : :
833 [ # # ]: 0 : if (!hc) {
834 : : DMDEBUG_LIMIT("device doesn't appear to be in the dev hash table.");
835 : 0 : up_write(&_hash_lock);
836 : 0 : return -ENXIO;
837 : : }
838 : :
839 : 0 : md = hc->md;
840 : :
841 : : /*
842 : : * Ensure the device is not open and nothing further can open it.
843 : : */
844 : 0 : r = dm_lock_for_deletion(md, !!(param->flags & DM_DEFERRED_REMOVE), false);
845 [ # # ]: 0 : if (r) {
846 [ # # ][ # # ]: 0 : if (r == -EBUSY && param->flags & DM_DEFERRED_REMOVE) {
847 : 0 : up_write(&_hash_lock);
848 : 0 : dm_put(md);
849 : 0 : return 0;
850 : : }
851 : : DMDEBUG_LIMIT("unable to remove open device %s", hc->name);
852 : 0 : up_write(&_hash_lock);
853 : 0 : dm_put(md);
854 : 0 : return r;
855 : : }
856 : :
857 : 0 : t = __hash_remove(hc);
858 : 0 : up_write(&_hash_lock);
859 : :
860 [ # # ]: 0 : if (t) {
861 : 0 : dm_sync_table(md);
862 : 0 : dm_table_destroy(t);
863 : : }
864 : :
865 : 0 : param->flags &= ~DM_DEFERRED_REMOVE;
866 : :
867 [ # # ]: 0 : if (!dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr))
868 : 0 : param->flags |= DM_UEVENT_GENERATED_FLAG;
869 : :
870 : 0 : dm_put(md);
871 : 0 : dm_destroy(md);
872 : 0 : return 0;
873 : : }
874 : :
875 : : /*
876 : : * Check a string doesn't overrun the chunk of
877 : : * memory we copied from userland.
878 : : */
879 : : static int invalid_str(char *str, void *end)
880 : : {
881 [ # # ][ # # ]: 0 : while ((void *) str < end)
[ # # ][ # # ]
882 [ # # ][ # # ]: 0 : if (!*str++)
[ # # ][ # # ]
883 : : return 0;
884 : :
885 : : return -EINVAL;
886 : : }
887 : :
888 : 0 : static int dev_rename(struct dm_ioctl *param, size_t param_size)
889 : : {
890 : : int r;
891 : 0 : char *new_data = (char *) param + param->data_start;
892 : : struct mapped_device *md;
893 : 0 : unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0;
894 : :
895 [ # # ][ # # ]: 0 : if (new_data < param->data ||
896 [ # # ][ # # ]: 0 : invalid_str(new_data, (void *) param + param_size) || !*new_data ||
897 [ # # ]: 0 : strlen(new_data) > (change_uuid ? DM_UUID_LEN - 1 : DM_NAME_LEN - 1)) {
898 : 0 : DMWARN("Invalid new mapped device name or uuid string supplied.");
899 : 0 : return -EINVAL;
900 : : }
901 : :
902 [ # # ]: 0 : if (!change_uuid) {
903 : 0 : r = check_name(new_data);
904 [ # # ]: 0 : if (r)
905 : : return r;
906 : : }
907 : :
908 : 0 : md = dm_hash_rename(param, new_data);
909 [ # # ]: 0 : if (IS_ERR(md))
910 : 0 : return PTR_ERR(md);
911 : :
912 : 0 : __dev_status(md, param);
913 : 0 : dm_put(md);
914 : :
915 : 0 : return 0;
916 : : }
917 : :
918 : 0 : static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
919 : : {
920 : : int r = -EINVAL, x;
921 : : struct mapped_device *md;
922 : : struct hd_geometry geometry;
923 : : unsigned long indata[4];
924 : 0 : char *geostr = (char *) param + param->data_start;
925 : : char dummy;
926 : :
927 : 0 : md = find_device(param);
928 [ # # ]: 0 : if (!md)
929 : : return -ENXIO;
930 : :
931 [ # # ][ # # ]: 0 : if (geostr < param->data ||
932 : 0 : invalid_str(geostr, (void *) param + param_size)) {
933 : 0 : DMWARN("Invalid geometry supplied.");
934 : 0 : goto out;
935 : : }
936 : :
937 : 0 : x = sscanf(geostr, "%lu %lu %lu %lu%c", indata,
938 : : indata + 1, indata + 2, indata + 3, &dummy);
939 : :
940 [ # # ]: 0 : if (x != 4) {
941 : 0 : DMWARN("Unable to interpret geometry settings.");
942 : 0 : goto out;
943 : : }
944 : :
945 [ # # ][ # # ]: 0 : if (indata[0] > 65535 || indata[1] > 255 ||
946 [ # # ]: 0 : indata[2] > 255 || indata[3] > ULONG_MAX) {
947 : 0 : DMWARN("Geometry exceeds range limits.");
948 : 0 : goto out;
949 : : }
950 : :
951 : 0 : geometry.cylinders = indata[0];
952 : 0 : geometry.heads = indata[1];
953 : 0 : geometry.sectors = indata[2];
954 : 0 : geometry.start = indata[3];
955 : :
956 : 0 : r = dm_set_geometry(md, &geometry);
957 : :
958 : 0 : param->data_size = 0;
959 : :
960 : : out:
961 : 0 : dm_put(md);
962 : 0 : return r;
963 : : }
964 : :
965 : 0 : static int do_suspend(struct dm_ioctl *param)
966 : : {
967 : : int r = 0;
968 : : unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
969 : : struct mapped_device *md;
970 : :
971 : 0 : md = find_device(param);
972 [ # # ]: 0 : if (!md)
973 : : return -ENXIO;
974 : :
975 [ # # ]: 0 : if (param->flags & DM_SKIP_LOCKFS_FLAG)
976 : : suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
977 [ # # ]: 0 : if (param->flags & DM_NOFLUSH_FLAG)
978 : 0 : suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
979 : :
980 [ # # ]: 0 : if (!dm_suspended_md(md)) {
981 : 0 : r = dm_suspend(md, suspend_flags);
982 [ # # ]: 0 : if (r)
983 : : goto out;
984 : : }
985 : :
986 : 0 : __dev_status(md, param);
987 : :
988 : : out:
989 : 0 : dm_put(md);
990 : :
991 : 0 : return r;
992 : : }
993 : :
994 : 0 : static int do_resume(struct dm_ioctl *param)
995 : : {
996 : : int r = 0;
997 : : unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG;
998 : : struct hash_cell *hc;
999 : : struct mapped_device *md;
1000 : : struct dm_table *new_map, *old_map = NULL;
1001 : :
1002 : 0 : down_write(&_hash_lock);
1003 : :
1004 : 0 : hc = __find_device_hash_cell(param);
1005 [ # # ]: 0 : if (!hc) {
1006 : : DMDEBUG_LIMIT("device doesn't appear to be in the dev hash table.");
1007 : 0 : up_write(&_hash_lock);
1008 : 0 : return -ENXIO;
1009 : : }
1010 : :
1011 : 0 : md = hc->md;
1012 : :
1013 : 0 : new_map = hc->new_map;
1014 : 0 : hc->new_map = NULL;
1015 : 0 : param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
1016 : :
1017 : 0 : up_write(&_hash_lock);
1018 : :
1019 : : /* Do we need to load a new map ? */
1020 [ # # ]: 0 : if (new_map) {
1021 : : /* Suspend if it isn't already suspended */
1022 [ # # ]: 0 : if (param->flags & DM_SKIP_LOCKFS_FLAG)
1023 : : suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
1024 [ # # ]: 0 : if (param->flags & DM_NOFLUSH_FLAG)
1025 : 0 : suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
1026 [ # # ]: 0 : if (!dm_suspended_md(md))
1027 : 0 : dm_suspend(md, suspend_flags);
1028 : :
1029 : 0 : old_map = dm_swap_table(md, new_map);
1030 [ # # ]: 0 : if (IS_ERR(old_map)) {
1031 : 0 : dm_sync_table(md);
1032 : 0 : dm_table_destroy(new_map);
1033 : 0 : dm_put(md);
1034 : 0 : return PTR_ERR(old_map);
1035 : : }
1036 : :
1037 [ # # ]: 0 : if (dm_table_get_mode(new_map) & FMODE_WRITE)
1038 : 0 : set_disk_ro(dm_disk(md), 0);
1039 : : else
1040 : 0 : set_disk_ro(dm_disk(md), 1);
1041 : : }
1042 : :
1043 [ # # ]: 0 : if (dm_suspended_md(md)) {
1044 : 0 : r = dm_resume(md);
1045 [ # # ][ # # ]: 0 : if (!r && !dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr))
1046 : 0 : param->flags |= DM_UEVENT_GENERATED_FLAG;
1047 : : }
1048 : :
1049 : : /*
1050 : : * Since dm_swap_table synchronizes RCU, nobody should be in
1051 : : * read-side critical section already.
1052 : : */
1053 [ # # ]: 0 : if (old_map)
1054 : 0 : dm_table_destroy(old_map);
1055 : :
1056 [ # # ]: 0 : if (!r)
1057 : 0 : __dev_status(md, param);
1058 : :
1059 : 0 : dm_put(md);
1060 : 0 : return r;
1061 : : }
1062 : :
1063 : : /*
1064 : : * Set or unset the suspension state of a device.
1065 : : * If the device already is in the requested state we just return its status.
1066 : : */
1067 : 0 : static int dev_suspend(struct dm_ioctl *param, size_t param_size)
1068 : : {
1069 [ # # ]: 0 : if (param->flags & DM_SUSPEND_FLAG)
1070 : 0 : return do_suspend(param);
1071 : :
1072 : 0 : return do_resume(param);
1073 : : }
1074 : :
1075 : : /*
1076 : : * Copies device info back to user space, used by
1077 : : * the create and info ioctls.
1078 : : */
1079 : 0 : static int dev_status(struct dm_ioctl *param, size_t param_size)
1080 : : {
1081 : : struct mapped_device *md;
1082 : :
1083 : 0 : md = find_device(param);
1084 [ # # ]: 0 : if (!md)
1085 : : return -ENXIO;
1086 : :
1087 : 0 : __dev_status(md, param);
1088 : 0 : dm_put(md);
1089 : :
1090 : 0 : return 0;
1091 : : }
1092 : :
1093 : : /*
1094 : : * Build up the status struct for each target
1095 : : */
1096 : 0 : static void retrieve_status(struct dm_table *table,
1097 : : struct dm_ioctl *param, size_t param_size)
1098 : : {
1099 : : unsigned int i, num_targets;
1100 : : struct dm_target_spec *spec;
1101 : : char *outbuf, *outptr;
1102 : : status_type_t type;
1103 : : size_t remaining, len, used = 0;
1104 : : unsigned status_flags = 0;
1105 : :
1106 : : outptr = outbuf = get_result_buffer(param, param_size, &len);
1107 : :
1108 [ # # ]: 0 : if (param->flags & DM_STATUS_TABLE_FLAG)
1109 : : type = STATUSTYPE_TABLE;
1110 : : else
1111 : : type = STATUSTYPE_INFO;
1112 : :
1113 : : /* Get all the target info */
1114 : 0 : num_targets = dm_table_get_num_targets(table);
1115 [ # # ]: 0 : for (i = 0; i < num_targets; i++) {
1116 : 0 : struct dm_target *ti = dm_table_get_target(table, i);
1117 : : size_t l;
1118 : :
1119 : 0 : remaining = len - (outptr - outbuf);
1120 [ # # ]: 0 : if (remaining <= sizeof(struct dm_target_spec)) {
1121 : 0 : param->flags |= DM_BUFFER_FULL_FLAG;
1122 : 0 : break;
1123 : : }
1124 : :
1125 : : spec = (struct dm_target_spec *) outptr;
1126 : :
1127 : 0 : spec->status = 0;
1128 : 0 : spec->sector_start = ti->begin;
1129 : 0 : spec->length = ti->len;
1130 : 0 : strncpy(spec->target_type, ti->type->name,
1131 : : sizeof(spec->target_type));
1132 : :
1133 : 0 : outptr += sizeof(struct dm_target_spec);
1134 : 0 : remaining = len - (outptr - outbuf);
1135 [ # # ]: 0 : if (remaining <= 0) {
1136 : 0 : param->flags |= DM_BUFFER_FULL_FLAG;
1137 : 0 : break;
1138 : : }
1139 : :
1140 : : /* Get the status/table string from the target driver */
1141 [ # # ]: 0 : if (ti->type->status) {
1142 [ # # ]: 0 : if (param->flags & DM_NOFLUSH_FLAG)
1143 : : status_flags |= DM_STATUS_NOFLUSH_FLAG;
1144 : 0 : ti->type->status(ti, type, status_flags, outptr, remaining);
1145 : : } else
1146 : 0 : outptr[0] = '\0';
1147 : :
1148 : 0 : l = strlen(outptr) + 1;
1149 [ # # ]: 0 : if (l == remaining) {
1150 : 0 : param->flags |= DM_BUFFER_FULL_FLAG;
1151 : 0 : break;
1152 : : }
1153 : :
1154 : 0 : outptr += l;
1155 : 0 : used = param->data_start + (outptr - outbuf);
1156 : :
1157 : : outptr = align_ptr(outptr);
1158 : 0 : spec->next = outptr - outbuf;
1159 : : }
1160 : :
1161 [ # # ]: 0 : if (used)
1162 : 0 : param->data_size = used;
1163 : :
1164 : 0 : param->target_count = num_targets;
1165 : 0 : }
1166 : :
1167 : : /*
1168 : : * Wait for a device to report an event
1169 : : */
1170 : 0 : static int dev_wait(struct dm_ioctl *param, size_t param_size)
1171 : : {
1172 : : int r = 0;
1173 : : struct mapped_device *md;
1174 : : struct dm_table *table;
1175 : : int srcu_idx;
1176 : :
1177 : 0 : md = find_device(param);
1178 [ # # ]: 0 : if (!md)
1179 : : return -ENXIO;
1180 : :
1181 : : /*
1182 : : * Wait for a notification event
1183 : : */
1184 [ # # ]: 0 : if (dm_wait_event(md, param->event_nr)) {
1185 : : r = -ERESTARTSYS;
1186 : : goto out;
1187 : : }
1188 : :
1189 : : /*
1190 : : * The userland program is going to want to know what
1191 : : * changed to trigger the event, so we may as well tell
1192 : : * him and save an ioctl.
1193 : : */
1194 : 0 : __dev_status(md, param);
1195 : :
1196 : 0 : table = dm_get_live_or_inactive_table(md, param, &srcu_idx);
1197 [ # # ]: 0 : if (table)
1198 : 0 : retrieve_status(table, param, param_size);
1199 : 0 : dm_put_live_table(md, srcu_idx);
1200 : :
1201 : : out:
1202 : 0 : dm_put(md);
1203 : :
1204 : 0 : return r;
1205 : : }
1206 : :
1207 : : static inline fmode_t get_mode(struct dm_ioctl *param)
1208 : : {
1209 : : fmode_t mode = FMODE_READ | FMODE_WRITE;
1210 : :
1211 [ # # ]: 0 : if (param->flags & DM_READONLY_FLAG)
1212 : : mode = FMODE_READ;
1213 : :
1214 : : return mode;
1215 : : }
1216 : :
1217 : : static int next_target(struct dm_target_spec *last, uint32_t next, void *end,
1218 : : struct dm_target_spec **spec, char **target_params)
1219 : : {
1220 : 0 : *spec = (struct dm_target_spec *) ((unsigned char *) last + next);
1221 : 0 : *target_params = (char *) (*spec + 1);
1222 : :
1223 [ # # ]: 0 : if (*spec < (last + 1))
1224 : : return -EINVAL;
1225 : :
1226 : : return invalid_str(*target_params, end);
1227 : : }
1228 : :
1229 : 0 : static int populate_table(struct dm_table *table,
1230 : : struct dm_ioctl *param, size_t param_size)
1231 : : {
1232 : : int r;
1233 : : unsigned int i = 0;
1234 : : struct dm_target_spec *spec = (struct dm_target_spec *) param;
1235 : 0 : uint32_t next = param->data_start;
1236 : 0 : void *end = (void *) param + param_size;
1237 : : char *target_params;
1238 : :
1239 [ # # ]: 0 : if (!param->target_count) {
1240 : 0 : DMWARN("populate_table: no targets specified");
1241 : 0 : return -EINVAL;
1242 : : }
1243 : :
1244 [ # # ]: 0 : for (i = 0; i < param->target_count; i++) {
1245 : :
1246 : : r = next_target(spec, next, end, &spec, &target_params);
1247 [ # # ]: 0 : if (r) {
1248 : 0 : DMWARN("unable to find target");
1249 : 0 : return r;
1250 : : }
1251 : :
1252 : 0 : r = dm_table_add_target(table, spec->target_type,
1253 : : (sector_t) spec->sector_start,
1254 : : (sector_t) spec->length,
1255 : : target_params);
1256 [ # # ]: 0 : if (r) {
1257 : 0 : DMWARN("error adding target to table");
1258 : 0 : return r;
1259 : : }
1260 : :
1261 : 0 : next = spec->next;
1262 : : }
1263 : :
1264 : 0 : return dm_table_complete(table);
1265 : : }
1266 : :
1267 : 0 : static int table_load(struct dm_ioctl *param, size_t param_size)
1268 : : {
1269 : : int r;
1270 : : struct hash_cell *hc;
1271 : : struct dm_table *t, *old_map = NULL;
1272 : : struct mapped_device *md;
1273 : : struct target_type *immutable_target_type;
1274 : :
1275 : 0 : md = find_device(param);
1276 [ # # ]: 0 : if (!md)
1277 : : return -ENXIO;
1278 : :
1279 : 0 : r = dm_table_create(&t, get_mode(param), param->target_count, md);
1280 [ # # ]: 0 : if (r)
1281 : : goto err;
1282 : :
1283 : : /* Protect md->type and md->queue against concurrent table loads. */
1284 : 0 : dm_lock_md_type(md);
1285 : 0 : r = populate_table(t, param, param_size);
1286 [ # # ]: 0 : if (r)
1287 : : goto err_unlock_md_type;
1288 : :
1289 : 0 : immutable_target_type = dm_get_immutable_target_type(md);
1290 [ # # # # ]: 0 : if (immutable_target_type &&
1291 : 0 : (immutable_target_type != dm_table_get_immutable_target_type(t))) {
1292 : 0 : DMWARN("can't replace immutable target type %s",
1293 : : immutable_target_type->name);
1294 : : r = -EINVAL;
1295 : 0 : goto err_unlock_md_type;
1296 : : }
1297 : :
1298 [ # # ]: 0 : if (dm_get_md_type(md) == DM_TYPE_NONE)
1299 : : /* Initial table load: acquire type of table. */
1300 : 0 : dm_set_md_type(md, dm_table_get_type(t));
1301 [ # # ]: 0 : else if (dm_get_md_type(md) != dm_table_get_type(t)) {
1302 : 0 : DMWARN("can't change device type after initial table load.");
1303 : : r = -EINVAL;
1304 : 0 : goto err_unlock_md_type;
1305 : : }
1306 : :
1307 : : /* setup md->queue to reflect md's type (may block) */
1308 : 0 : r = dm_setup_md_queue(md);
1309 [ # # ]: 0 : if (r) {
1310 : 0 : DMWARN("unable to set up device queue for new table.");
1311 : 0 : goto err_unlock_md_type;
1312 : : }
1313 : 0 : dm_unlock_md_type(md);
1314 : :
1315 : : /* stage inactive table */
1316 : 0 : down_write(&_hash_lock);
1317 : 0 : hc = dm_get_mdptr(md);
1318 [ # # ][ # # ]: 0 : if (!hc || hc->md != md) {
1319 : 0 : DMWARN("device has been removed from the dev hash table.");
1320 : 0 : up_write(&_hash_lock);
1321 : : r = -ENXIO;
1322 : 0 : goto err_destroy_table;
1323 : : }
1324 : :
1325 [ # # ]: 0 : if (hc->new_map)
1326 : : old_map = hc->new_map;
1327 : 0 : hc->new_map = t;
1328 : 0 : up_write(&_hash_lock);
1329 : :
1330 : 0 : param->flags |= DM_INACTIVE_PRESENT_FLAG;
1331 : 0 : __dev_status(md, param);
1332 : :
1333 [ # # ]: 0 : if (old_map) {
1334 : 0 : dm_sync_table(md);
1335 : 0 : dm_table_destroy(old_map);
1336 : : }
1337 : :
1338 : 0 : dm_put(md);
1339 : :
1340 : 0 : return 0;
1341 : :
1342 : : err_unlock_md_type:
1343 : 0 : dm_unlock_md_type(md);
1344 : : err_destroy_table:
1345 : 0 : dm_table_destroy(t);
1346 : : err:
1347 : 0 : dm_put(md);
1348 : :
1349 : 0 : return r;
1350 : : }
1351 : :
1352 : 0 : static int table_clear(struct dm_ioctl *param, size_t param_size)
1353 : : {
1354 : : struct hash_cell *hc;
1355 : : struct mapped_device *md;
1356 : : struct dm_table *old_map = NULL;
1357 : :
1358 : 0 : down_write(&_hash_lock);
1359 : :
1360 : 0 : hc = __find_device_hash_cell(param);
1361 [ # # ]: 0 : if (!hc) {
1362 : : DMDEBUG_LIMIT("device doesn't appear to be in the dev hash table.");
1363 : 0 : up_write(&_hash_lock);
1364 : 0 : return -ENXIO;
1365 : : }
1366 : :
1367 [ # # ]: 0 : if (hc->new_map) {
1368 : : old_map = hc->new_map;
1369 : 0 : hc->new_map = NULL;
1370 : : }
1371 : :
1372 : 0 : param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
1373 : :
1374 : 0 : __dev_status(hc->md, param);
1375 : 0 : md = hc->md;
1376 : 0 : up_write(&_hash_lock);
1377 [ # # ]: 0 : if (old_map) {
1378 : 0 : dm_sync_table(md);
1379 : 0 : dm_table_destroy(old_map);
1380 : : }
1381 : 0 : dm_put(md);
1382 : :
1383 : 0 : return 0;
1384 : : }
1385 : :
1386 : : /*
1387 : : * Retrieves a list of devices used by a particular dm device.
1388 : : */
1389 : 0 : static void retrieve_deps(struct dm_table *table,
1390 : : struct dm_ioctl *param, size_t param_size)
1391 : : {
1392 : : unsigned int count = 0;
1393 : : struct list_head *tmp;
1394 : : size_t len, needed;
1395 : : struct dm_dev_internal *dd;
1396 : : struct dm_target_deps *deps;
1397 : :
1398 : : deps = get_result_buffer(param, param_size, &len);
1399 : :
1400 : : /*
1401 : : * Count the devices.
1402 : : */
1403 [ # # ]: 0 : list_for_each (tmp, dm_table_get_devices(table))
1404 : 0 : count++;
1405 : :
1406 : : /*
1407 : : * Check we have enough space.
1408 : : */
1409 : 0 : needed = sizeof(*deps) + (sizeof(*deps->dev) * count);
1410 [ # # ]: 0 : if (len < needed) {
1411 : 0 : param->flags |= DM_BUFFER_FULL_FLAG;
1412 : 0 : return;
1413 : : }
1414 : :
1415 : : /*
1416 : : * Fill in the devices.
1417 : : */
1418 : 0 : deps->count = count;
1419 : : count = 0;
1420 [ # # ]: 0 : list_for_each_entry (dd, dm_table_get_devices(table), list)
1421 : 0 : deps->dev[count++] = huge_encode_dev(dd->dm_dev.bdev->bd_dev);
1422 : :
1423 : 0 : param->data_size = param->data_start + needed;
1424 : : }
1425 : :
1426 : 0 : static int table_deps(struct dm_ioctl *param, size_t param_size)
1427 : : {
1428 : : struct mapped_device *md;
1429 : : struct dm_table *table;
1430 : : int srcu_idx;
1431 : :
1432 : 0 : md = find_device(param);
1433 [ # # ]: 0 : if (!md)
1434 : : return -ENXIO;
1435 : :
1436 : 0 : __dev_status(md, param);
1437 : :
1438 : 0 : table = dm_get_live_or_inactive_table(md, param, &srcu_idx);
1439 [ # # ]: 0 : if (table)
1440 : 0 : retrieve_deps(table, param, param_size);
1441 : 0 : dm_put_live_table(md, srcu_idx);
1442 : :
1443 : 0 : dm_put(md);
1444 : :
1445 : 0 : return 0;
1446 : : }
1447 : :
1448 : : /*
1449 : : * Return the status of a device as a text string for each
1450 : : * target.
1451 : : */
1452 : 0 : static int table_status(struct dm_ioctl *param, size_t param_size)
1453 : : {
1454 : : struct mapped_device *md;
1455 : : struct dm_table *table;
1456 : : int srcu_idx;
1457 : :
1458 : 0 : md = find_device(param);
1459 [ # # ]: 0 : if (!md)
1460 : : return -ENXIO;
1461 : :
1462 : 0 : __dev_status(md, param);
1463 : :
1464 : 0 : table = dm_get_live_or_inactive_table(md, param, &srcu_idx);
1465 [ # # ]: 0 : if (table)
1466 : 0 : retrieve_status(table, param, param_size);
1467 : 0 : dm_put_live_table(md, srcu_idx);
1468 : :
1469 : 0 : dm_put(md);
1470 : :
1471 : 0 : return 0;
1472 : : }
1473 : :
1474 : : /*
1475 : : * Process device-mapper dependent messages. Messages prefixed with '@'
1476 : : * are processed by the DM core. All others are delivered to the target.
1477 : : * Returns a number <= 1 if message was processed by device mapper.
1478 : : * Returns 2 if message should be delivered to the target.
1479 : : */
1480 : 0 : static int message_for_md(struct mapped_device *md, unsigned argc, char **argv,
1481 : : char *result, unsigned maxlen)
1482 : : {
1483 : : int r;
1484 : :
1485 [ # # ]: 0 : if (**argv != '@')
1486 : : return 2; /* no '@' prefix, deliver to target */
1487 : :
1488 [ # # ]: 0 : if (!strcasecmp(argv[0], "@cancel_deferred_remove")) {
1489 [ # # ]: 0 : if (argc != 1) {
1490 : 0 : DMERR("Invalid arguments for @cancel_deferred_remove");
1491 : 0 : return -EINVAL;
1492 : : }
1493 : 0 : return dm_cancel_deferred_remove(md);
1494 : : }
1495 : :
1496 : 0 : r = dm_stats_message(md, argc, argv, result, maxlen);
1497 [ # # ]: 0 : if (r < 2)
1498 : : return r;
1499 : :
1500 : 0 : DMERR("Unsupported message sent to DM core: %s", argv[0]);
1501 : 0 : return -EINVAL;
1502 : : }
1503 : :
1504 : : /*
1505 : : * Pass a message to the target that's at the supplied device offset.
1506 : : */
1507 : 0 : static int target_message(struct dm_ioctl *param, size_t param_size)
1508 : : {
1509 : : int r, argc;
1510 : : char **argv;
1511 : : struct mapped_device *md;
1512 : : struct dm_table *table;
1513 : : struct dm_target *ti;
1514 : 0 : struct dm_target_msg *tmsg = (void *) param + param->data_start;
1515 : : size_t maxlen;
1516 : : char *result = get_result_buffer(param, param_size, &maxlen);
1517 : : int srcu_idx;
1518 : :
1519 : 0 : md = find_device(param);
1520 [ # # ]: 0 : if (!md)
1521 : : return -ENXIO;
1522 : :
1523 [ # # ][ # # ]: 0 : if (tmsg < (struct dm_target_msg *) param->data ||
1524 : 0 : invalid_str(tmsg->message, (void *) param + param_size)) {
1525 : 0 : DMWARN("Invalid target message parameters.");
1526 : : r = -EINVAL;
1527 : 0 : goto out;
1528 : : }
1529 : :
1530 : 0 : r = dm_split_args(&argc, &argv, tmsg->message);
1531 [ # # ]: 0 : if (r) {
1532 : 0 : DMWARN("Failed to split target message parameters");
1533 : 0 : goto out;
1534 : : }
1535 : :
1536 [ # # ]: 0 : if (!argc) {
1537 : 0 : DMWARN("Empty message received.");
1538 : 0 : goto out_argv;
1539 : : }
1540 : :
1541 : 0 : r = message_for_md(md, argc, argv, result, maxlen);
1542 [ # # ]: 0 : if (r <= 1)
1543 : : goto out_argv;
1544 : :
1545 : 0 : table = dm_get_live_table(md, &srcu_idx);
1546 [ # # ]: 0 : if (!table)
1547 : : goto out_table;
1548 : :
1549 [ # # ]: 0 : if (dm_deleting_md(md)) {
1550 : : r = -ENXIO;
1551 : : goto out_table;
1552 : : }
1553 : :
1554 : 0 : ti = dm_table_find_target(table, tmsg->sector);
1555 [ # # ]: 0 : if (!dm_target_is_valid(ti)) {
1556 : 0 : DMWARN("Target message sector outside device.");
1557 : : r = -EINVAL;
1558 [ # # ]: 0 : } else if (ti->type->message)
1559 : 0 : r = ti->type->message(ti, argc, argv);
1560 : : else {
1561 : 0 : DMWARN("Target type does not support messages");
1562 : : r = -EINVAL;
1563 : : }
1564 : :
1565 : : out_table:
1566 : 0 : dm_put_live_table(md, srcu_idx);
1567 : : out_argv:
1568 : 0 : kfree(argv);
1569 : : out:
1570 [ # # ]: 0 : if (r >= 0)
1571 : 0 : __dev_status(md, param);
1572 : :
1573 [ # # ]: 0 : if (r == 1) {
1574 : 0 : param->flags |= DM_DATA_OUT_FLAG;
1575 [ # # ]: 0 : if (dm_message_test_buffer_overflow(result, maxlen))
1576 : 0 : param->flags |= DM_BUFFER_FULL_FLAG;
1577 : : else
1578 : 0 : param->data_size = param->data_start + strlen(result) + 1;
1579 : : r = 0;
1580 : : }
1581 : :
1582 : 0 : dm_put(md);
1583 : 0 : return r;
1584 : : }
1585 : :
1586 : : /*
1587 : : * The ioctl parameter block consists of two parts, a dm_ioctl struct
1588 : : * followed by a data buffer. This flag is set if the second part,
1589 : : * which has a variable size, is not used by the function processing
1590 : : * the ioctl.
1591 : : */
1592 : : #define IOCTL_FLAGS_NO_PARAMS 1
1593 : :
1594 : : /*-----------------------------------------------------------------
1595 : : * Implementation of open/close/ioctl on the special char
1596 : : * device.
1597 : : *---------------------------------------------------------------*/
1598 : : static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
1599 : : {
1600 : : static struct {
1601 : : int cmd;
1602 : : int flags;
1603 : : ioctl_fn fn;
1604 : : } _ioctls[] = {
1605 : : {DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */
1606 : : {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS, remove_all},
1607 : : {DM_LIST_DEVICES_CMD, 0, list_devices},
1608 : :
1609 : : {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_create},
1610 : : {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_remove},
1611 : : {DM_DEV_RENAME_CMD, 0, dev_rename},
1612 : : {DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend},
1613 : : {DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status},
1614 : : {DM_DEV_WAIT_CMD, 0, dev_wait},
1615 : :
1616 : : {DM_TABLE_LOAD_CMD, 0, table_load},
1617 : : {DM_TABLE_CLEAR_CMD, IOCTL_FLAGS_NO_PARAMS, table_clear},
1618 : : {DM_TABLE_DEPS_CMD, 0, table_deps},
1619 : : {DM_TABLE_STATUS_CMD, 0, table_status},
1620 : :
1621 : : {DM_LIST_VERSIONS_CMD, 0, list_versions},
1622 : :
1623 : : {DM_TARGET_MSG_CMD, 0, target_message},
1624 : : {DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry}
1625 : : };
1626 : :
1627 [ # # ]: 0 : if (unlikely(cmd >= ARRAY_SIZE(_ioctls)))
1628 : : return NULL;
1629 : :
1630 : 0 : *ioctl_flags = _ioctls[cmd].flags;
1631 : 0 : return _ioctls[cmd].fn;
1632 : : }
1633 : :
1634 : : /*
1635 : : * As well as checking the version compatibility this always
1636 : : * copies the kernel interface version out.
1637 : : */
1638 : 0 : static int check_version(unsigned int cmd, struct dm_ioctl __user *user)
1639 : : {
1640 : : uint32_t version[3];
1641 : : int r = 0;
1642 : :
1643 [ # # ]: 0 : if (copy_from_user(version, user->version, sizeof(version)))
1644 : : return -EFAULT;
1645 : :
1646 [ # # ][ # # ]: 0 : if ((DM_VERSION_MAJOR != version[0]) ||
1647 : 0 : (DM_VERSION_MINOR < version[1])) {
1648 : 0 : DMWARN("ioctl interface mismatch: "
1649 : : "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
1650 : : DM_VERSION_MAJOR, DM_VERSION_MINOR,
1651 : : DM_VERSION_PATCHLEVEL,
1652 : : version[0], version[1], version[2], cmd);
1653 : : r = -EINVAL;
1654 : : }
1655 : :
1656 : : /*
1657 : : * Fill in the kernel version.
1658 : : */
1659 : 0 : version[0] = DM_VERSION_MAJOR;
1660 : 0 : version[1] = DM_VERSION_MINOR;
1661 : 0 : version[2] = DM_VERSION_PATCHLEVEL;
1662 [ # # ]: 0 : if (copy_to_user(user->version, version, sizeof(version)))
1663 : : return -EFAULT;
1664 : :
1665 : 0 : return r;
1666 : : }
1667 : :
1668 : : #define DM_PARAMS_KMALLOC 0x0001 /* Params alloced with kmalloc */
1669 : : #define DM_PARAMS_VMALLOC 0x0002 /* Params alloced with vmalloc */
1670 : : #define DM_WIPE_BUFFER 0x0010 /* Wipe input buffer before returning from ioctl */
1671 : :
1672 : 0 : static void free_params(struct dm_ioctl *param, size_t param_size, int param_flags)
1673 : : {
1674 [ # # ]: 0 : if (param_flags & DM_WIPE_BUFFER)
1675 [ # # ]: 0 : memset(param, 0, param_size);
1676 : :
1677 [ # # ]: 0 : if (param_flags & DM_PARAMS_KMALLOC)
1678 : 0 : kfree(param);
1679 [ # # ]: 0 : if (param_flags & DM_PARAMS_VMALLOC)
1680 : 0 : vfree(param);
1681 : 0 : }
1682 : :
1683 : 0 : static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kernel,
1684 : : int ioctl_flags,
1685 : : struct dm_ioctl **param, int *param_flags)
1686 : : {
1687 : : struct dm_ioctl *dmi;
1688 : : int secure_data;
1689 : : const size_t minimum_data_size = sizeof(*param_kernel) - sizeof(param_kernel->data);
1690 : :
1691 [ # # ]: 0 : if (copy_from_user(param_kernel, user, minimum_data_size))
1692 : : return -EFAULT;
1693 : :
1694 [ # # ]: 0 : if (param_kernel->data_size < minimum_data_size)
1695 : : return -EINVAL;
1696 : :
1697 : 0 : secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG;
1698 : :
1699 [ # # ]: 0 : *param_flags = secure_data ? DM_WIPE_BUFFER : 0;
1700 : :
1701 [ # # ]: 0 : if (ioctl_flags & IOCTL_FLAGS_NO_PARAMS) {
1702 : : dmi = param_kernel;
1703 : 0 : dmi->data_size = minimum_data_size;
1704 : 0 : goto data_copied;
1705 : : }
1706 : :
1707 : : /*
1708 : : * Try to avoid low memory issues when a device is suspended.
1709 : : * Use kmalloc() rather than vmalloc() when we can.
1710 : : */
1711 : : dmi = NULL;
1712 [ # # ]: 0 : if (param_kernel->data_size <= KMALLOC_MAX_SIZE) {
1713 : : dmi = kmalloc(param_kernel->data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
1714 [ # # ]: 0 : if (dmi)
1715 : 0 : *param_flags |= DM_PARAMS_KMALLOC;
1716 : : }
1717 : :
1718 [ # # ]: 0 : if (!dmi) {
1719 : : unsigned noio_flag;
1720 : : noio_flag = memalloc_noio_save();
1721 : 0 : dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH | __GFP_HIGHMEM, PAGE_KERNEL);
1722 : : memalloc_noio_restore(noio_flag);
1723 [ # # ]: 0 : if (dmi)
1724 : 0 : *param_flags |= DM_PARAMS_VMALLOC;
1725 : : }
1726 : :
1727 [ # # ]: 0 : if (!dmi) {
1728 [ # # ][ # # ]: 0 : if (secure_data && clear_user(user, param_kernel->data_size))
1729 : : return -EFAULT;
1730 : : return -ENOMEM;
1731 : : }
1732 : :
1733 [ # # ]: 0 : if (copy_from_user(dmi, user, param_kernel->data_size))
1734 : : goto bad;
1735 : :
1736 : : data_copied:
1737 : : /*
1738 : : * Abort if something changed the ioctl data while it was being copied.
1739 : : */
1740 [ # # ]: 0 : if (dmi->data_size != param_kernel->data_size) {
1741 : 0 : DMERR("rejecting ioctl: data size modified while processing parameters");
1742 : 0 : goto bad;
1743 : : }
1744 : :
1745 : : /* Wipe the user buffer so we do not return it to userspace */
1746 [ # # ][ # # ]: 0 : if (secure_data && clear_user(user, param_kernel->data_size))
1747 : : goto bad;
1748 : :
1749 : 0 : *param = dmi;
1750 : 0 : return 0;
1751 : :
1752 : : bad:
1753 : 0 : free_params(dmi, param_kernel->data_size, *param_flags);
1754 : :
1755 : 0 : return -EFAULT;
1756 : : }
1757 : :
1758 : 0 : static int validate_params(uint cmd, struct dm_ioctl *param)
1759 : : {
1760 : : /* Always clear this flag */
1761 : 0 : param->flags &= ~DM_BUFFER_FULL_FLAG;
1762 : 0 : param->flags &= ~DM_UEVENT_GENERATED_FLAG;
1763 : 0 : param->flags &= ~DM_SECURE_DATA_FLAG;
1764 : 0 : param->flags &= ~DM_DATA_OUT_FLAG;
1765 : :
1766 : : /* Ignores parameters */
1767 [ # # ]: 0 : if (cmd == DM_REMOVE_ALL_CMD ||
1768 : 0 : cmd == DM_LIST_DEVICES_CMD ||
1769 : 0 : cmd == DM_LIST_VERSIONS_CMD)
1770 : : return 0;
1771 : :
1772 [ # # ]: 0 : if ((cmd == DM_DEV_CREATE_CMD)) {
1773 [ # # ]: 0 : if (!*param->name) {
1774 : 0 : DMWARN("name not supplied when creating device");
1775 : 0 : return -EINVAL;
1776 : : }
1777 [ # # ][ # # ]: 0 : } else if ((*param->uuid && *param->name)) {
1778 : 0 : DMWARN("only supply one of name or uuid, cmd(%u)", cmd);
1779 : 0 : return -EINVAL;
1780 : : }
1781 : :
1782 : : /* Ensure strings are terminated */
1783 : 0 : param->name[DM_NAME_LEN - 1] = '\0';
1784 : 0 : param->uuid[DM_UUID_LEN - 1] = '\0';
1785 : :
1786 : 0 : return 0;
1787 : : }
1788 : :
1789 : 0 : static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1790 : : {
1791 : : int r = 0;
1792 : : int ioctl_flags;
1793 : : int param_flags;
1794 : : unsigned int cmd;
1795 : : struct dm_ioctl *uninitialized_var(param);
1796 : : ioctl_fn fn = NULL;
1797 : : size_t input_param_size;
1798 : : struct dm_ioctl param_kernel;
1799 : :
1800 : : /* only root can play with this */
1801 [ # # ]: 0 : if (!capable(CAP_SYS_ADMIN))
1802 : : return -EACCES;
1803 : :
1804 [ # # ]: 0 : if (_IOC_TYPE(command) != DM_IOCTL)
1805 : : return -ENOTTY;
1806 : :
1807 : 0 : cmd = _IOC_NR(command);
1808 : :
1809 : : /*
1810 : : * Check the interface version passed in. This also
1811 : : * writes out the kernel's interface version.
1812 : : */
1813 : 0 : r = check_version(cmd, user);
1814 [ # # ]: 0 : if (r)
1815 : : return r;
1816 : :
1817 : : /*
1818 : : * Nothing more to do for the version command.
1819 : : */
1820 [ # # ]: 0 : if (cmd == DM_VERSION_CMD)
1821 : : return 0;
1822 : :
1823 : : fn = lookup_ioctl(cmd, &ioctl_flags);
1824 [ # # ]: 0 : if (!fn) {
1825 : 0 : DMWARN("dm_ctl_ioctl: unknown command 0x%x", command);
1826 : 0 : return -ENOTTY;
1827 : : }
1828 : :
1829 : : /*
1830 : : * Copy the parameters into kernel space.
1831 : : */
1832 : 0 : r = copy_params(user, ¶m_kernel, ioctl_flags, ¶m, ¶m_flags);
1833 : :
1834 [ # # ]: 0 : if (r)
1835 : : return r;
1836 : :
1837 : 0 : input_param_size = param->data_size;
1838 : 0 : r = validate_params(cmd, param);
1839 [ # # ]: 0 : if (r)
1840 : : goto out;
1841 : :
1842 : 0 : param->data_size = sizeof(*param);
1843 : 0 : r = fn(param, input_param_size);
1844 : :
1845 [ # # ][ # # ]: 0 : if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) &&
1846 : 0 : unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS))
1847 : 0 : DMERR("ioctl %d tried to output some data but has IOCTL_FLAGS_NO_PARAMS set", cmd);
1848 : :
1849 : : /*
1850 : : * Copy the results back to userland.
1851 : : */
1852 [ # # ][ # # ]: 0 : if (!r && copy_to_user(user, param, param->data_size))
1853 : : r = -EFAULT;
1854 : :
1855 : : out:
1856 : 0 : free_params(param, input_param_size, param_flags);
1857 : 0 : return r;
1858 : : }
1859 : :
1860 : 0 : static long dm_ctl_ioctl(struct file *file, uint command, ulong u)
1861 : : {
1862 : 0 : return (long)ctl_ioctl(command, (struct dm_ioctl __user *)u);
1863 : : }
1864 : :
1865 : : #ifdef CONFIG_COMPAT
1866 : : static long dm_compat_ctl_ioctl(struct file *file, uint command, ulong u)
1867 : : {
1868 : : return (long)dm_ctl_ioctl(file, command, (ulong) compat_ptr(u));
1869 : : }
1870 : : #else
1871 : : #define dm_compat_ctl_ioctl NULL
1872 : : #endif
1873 : :
1874 : : static const struct file_operations _ctl_fops = {
1875 : : .open = nonseekable_open,
1876 : : .unlocked_ioctl = dm_ctl_ioctl,
1877 : : .compat_ioctl = dm_compat_ctl_ioctl,
1878 : : .owner = THIS_MODULE,
1879 : : .llseek = noop_llseek,
1880 : : };
1881 : :
1882 : : static struct miscdevice _dm_misc = {
1883 : : .minor = MAPPER_CTRL_MINOR,
1884 : : .name = DM_NAME,
1885 : : .nodename = DM_DIR "/" DM_CONTROL_NODE,
1886 : : .fops = &_ctl_fops
1887 : : };
1888 : :
1889 : : MODULE_ALIAS_MISCDEV(MAPPER_CTRL_MINOR);
1890 : : MODULE_ALIAS("devname:" DM_DIR "/" DM_CONTROL_NODE);
1891 : :
1892 : : /*
1893 : : * Create misc character device and link to DM_DIR/control.
1894 : : */
1895 : 0 : int __init dm_interface_init(void)
1896 : : {
1897 : : int r;
1898 : :
1899 : 0 : r = dm_hash_init();
1900 [ # # ]: 0 : if (r)
1901 : : return r;
1902 : :
1903 : 0 : r = misc_register(&_dm_misc);
1904 [ # # ]: 0 : if (r) {
1905 : 0 : DMERR("misc_register failed for control device");
1906 : : dm_hash_exit();
1907 : 0 : return r;
1908 : : }
1909 : :
1910 : 0 : DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
1911 : : DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
1912 : : DM_DRIVER_EMAIL);
1913 : 0 : return 0;
1914 : : }
1915 : :
1916 : 0 : void dm_interface_exit(void)
1917 : : {
1918 [ # # ]: 0 : if (misc_deregister(&_dm_misc) < 0)
1919 : 0 : DMERR("misc_deregister failed for control device");
1920 : :
1921 : : dm_hash_exit();
1922 : 0 : }
1923 : :
1924 : : /**
1925 : : * dm_copy_name_and_uuid - Copy mapped device name & uuid into supplied buffers
1926 : : * @md: Pointer to mapped_device
1927 : : * @name: Buffer (size DM_NAME_LEN) for name
1928 : : * @uuid: Buffer (size DM_UUID_LEN) for uuid or empty string if uuid not defined
1929 : : */
1930 : 0 : int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid)
1931 : : {
1932 : : int r = 0;
1933 : : struct hash_cell *hc;
1934 : :
1935 [ # # ]: 0 : if (!md)
1936 : : return -ENXIO;
1937 : :
1938 : 0 : mutex_lock(&dm_hash_cells_mutex);
1939 : 0 : hc = dm_get_mdptr(md);
1940 [ # # ][ # # ]: 0 : if (!hc || hc->md != md) {
1941 : : r = -ENXIO;
1942 : : goto out;
1943 : : }
1944 : :
1945 [ # # ]: 0 : if (name)
1946 : 0 : strcpy(name, hc->name);
1947 [ # # ]: 0 : if (uuid)
1948 [ # # ]: 0 : strcpy(uuid, hc->uuid ? : "");
1949 : :
1950 : : out:
1951 : 0 : mutex_unlock(&dm_hash_cells_mutex);
1952 : :
1953 : 0 : return r;
1954 : : }
|