1 : /*
2 : * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 : * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
4 : *
5 : * This file is part of the device-mapper userspace tools.
6 : *
7 : * This copyrighted material is made available to anyone wishing to use,
8 : * modify, copy, or redistribute it subject to the terms and conditions
9 : * of the GNU Lesser General Public License v.2.1.
10 : *
11 : * You should have received a copy of the GNU Lesser General Public License
12 : * along with this program; if not, write to the Free Software Foundation,
13 : * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 : */
15 :
16 : #include "dmlib.h"
17 : #include "libdm-targets.h"
18 : #include "libdm-common.h"
19 : #include "kdev_t.h"
20 : #include "dm-ioctl.h"
21 :
22 : #include <stdarg.h>
23 : #include <sys/param.h>
24 : #include <sys/ioctl.h>
25 : #include <fcntl.h>
26 : #include <dirent.h>
27 :
28 : #ifdef UDEV_SYNC_SUPPORT
29 : # include <sys/types.h>
30 : # include <sys/ipc.h>
31 : # include <sys/sem.h>
32 : # define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
33 : # include <libudev.h>
34 : #endif
35 :
36 : #ifdef linux
37 : # include <linux/fs.h>
38 : #endif
39 :
40 : #ifdef HAVE_SELINUX
41 : # include <selinux/selinux.h>
42 : #endif
43 :
44 : #define DEV_DIR "/dev/"
45 :
46 : static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
47 :
48 : static int _verbose = 0;
49 :
50 : #ifdef UDEV_SYNC_SUPPORT
51 : static int _udev_running = -1;
52 : static int _sync_with_udev = 1;
53 : static int _udev_checking = 1;
54 : #endif
55 :
56 : /*
57 : * Library users can provide their own logging
58 : * function.
59 : */
60 :
61 3315 : static void _default_log_line(int level,
62 : const char *file __attribute((unused)),
63 : int line __attribute((unused)), int dm_errno,
64 : const char *f, va_list ap)
65 : {
66 3315 : int use_stderr = level & _LOG_STDERR;
67 :
68 3315 : level &= ~_LOG_STDERR;
69 :
70 3315 : if (level > _LOG_WARN && !_verbose)
71 3315 : return;
72 :
73 0 : if (level < _LOG_WARN)
74 0 : vfprintf(stderr, f, ap);
75 : else
76 0 : vfprintf(use_stderr ? stderr : stdout, f, ap);
77 :
78 0 : if (level < _LOG_WARN)
79 0 : fprintf(stderr, "\n");
80 : else
81 0 : fprintf(use_stderr ? stderr : stdout, "\n");
82 : }
83 :
84 3315 : static void _default_log_with_errno(int level,
85 : const char *file __attribute((unused)),
86 : int line __attribute((unused)), int dm_errno,
87 : const char *f, ...)
88 : {
89 : va_list ap;
90 :
91 3315 : va_start(ap, f);
92 3315 : _default_log_line(level, file, line, dm_errno, f, ap);
93 3315 : va_end(ap);
94 3315 : }
95 :
96 0 : static void _default_log(int level, const char *file,
97 : int line, const char *f, ...)
98 : {
99 : va_list ap;
100 :
101 0 : va_start(ap, f);
102 0 : _default_log_line(level, file, line, 0, f, ap);
103 0 : va_end(ap);
104 0 : }
105 :
106 : dm_log_fn dm_log = _default_log;
107 : dm_log_with_errno_fn dm_log_with_errno = _default_log_with_errno;
108 :
109 0 : void dm_log_init(dm_log_fn fn)
110 : {
111 0 : if (fn)
112 0 : dm_log = fn;
113 : else
114 0 : dm_log = _default_log;
115 :
116 0 : dm_log_with_errno = _default_log_with_errno;
117 0 : }
118 :
119 3318 : int dm_log_is_non_default(void)
120 : {
121 3318 : return (dm_log == _default_log) ? 0 : 1;
122 : }
123 :
124 3 : void dm_log_with_errno_init(dm_log_with_errno_fn fn)
125 : {
126 3 : if (fn)
127 3 : dm_log_with_errno = fn;
128 : else
129 0 : dm_log_with_errno = _default_log_with_errno;
130 :
131 3 : dm_log = _default_log;
132 3 : }
133 :
134 0 : void dm_log_init_verbose(int level)
135 : {
136 0 : _verbose = level;
137 0 : }
138 :
139 0 : static void _build_dev_path(char *buffer, size_t len, const char *dev_name)
140 : {
141 : /* If there's a /, assume caller knows what they're doing */
142 0 : if (strchr(dev_name, '/'))
143 0 : snprintf(buffer, len, "%s", dev_name);
144 : else
145 0 : snprintf(buffer, len, "%s/%s", _dm_dir, dev_name);
146 0 : }
147 :
148 0 : int dm_get_library_version(char *version, size_t size)
149 : {
150 0 : strncpy(version, DM_LIB_VERSION, size);
151 0 : return 1;
152 : }
153 :
154 1810 : struct dm_task *dm_task_create(int type)
155 : {
156 1810 : struct dm_task *dmt = dm_malloc(sizeof(*dmt));
157 :
158 1810 : if (!dmt) {
159 0 : log_error("dm_task_create: malloc(%" PRIsize_t ") failed",
160 : sizeof(*dmt));
161 0 : return NULL;
162 : }
163 :
164 1810 : if (!dm_check_version()) {
165 0 : dm_free(dmt);
166 0 : return NULL;
167 : }
168 :
169 1810 : memset(dmt, 0, sizeof(*dmt));
170 :
171 1810 : dmt->type = type;
172 1810 : dmt->minor = -1;
173 1810 : dmt->major = -1;
174 1810 : dmt->allow_default_major_fallback = 1;
175 1810 : dmt->uid = DM_DEVICE_UID;
176 1810 : dmt->gid = DM_DEVICE_GID;
177 1810 : dmt->mode = DM_DEVICE_MODE;
178 1810 : dmt->no_open_count = 0;
179 1810 : dmt->read_ahead = DM_READ_AHEAD_AUTO;
180 1810 : dmt->read_ahead_flags = 0;
181 1810 : dmt->event_nr = 0;
182 1810 : dmt->cookie_set = 0;
183 1810 : dmt->query_inactive_table = 0;
184 :
185 1810 : return dmt;
186 : }
187 :
188 : /*
189 : * Find the name associated with a given device number by scanning _dm_dir.
190 : */
191 0 : static char *_find_dm_name_of_device(dev_t st_rdev)
192 : {
193 : const char *name;
194 : char path[PATH_MAX];
195 : struct dirent *dirent;
196 : DIR *d;
197 : struct stat buf;
198 0 : char *new_name = NULL;
199 :
200 0 : if (!(d = opendir(_dm_dir))) {
201 0 : log_sys_error("opendir", _dm_dir);
202 0 : return NULL;
203 : }
204 :
205 0 : while ((dirent = readdir(d))) {
206 0 : name = dirent->d_name;
207 :
208 0 : if (!strcmp(name, ".") || !strcmp(name, ".."))
209 0 : continue;
210 :
211 0 : if (dm_snprintf(path, sizeof(path), "%s/%s", _dm_dir,
212 : name) == -1) {
213 0 : log_error("Couldn't create path for %s", name);
214 0 : continue;
215 : }
216 :
217 0 : if (stat(path, &buf))
218 0 : continue;
219 :
220 0 : if (buf.st_rdev == st_rdev) {
221 0 : if (!(new_name = dm_strdup(name)))
222 0 : log_error("dm_task_set_name: strdup(%s) failed",
223 : name);
224 0 : break;
225 : }
226 : }
227 :
228 0 : if (closedir(d))
229 0 : log_sys_error("closedir", _dm_dir);
230 :
231 0 : return new_name;
232 : }
233 :
234 1506 : int dm_task_set_name(struct dm_task *dmt, const char *name)
235 : {
236 : char *pos;
237 1506 : char *new_name = NULL;
238 : char path[PATH_MAX];
239 : struct stat st1, st2;
240 :
241 1506 : if (dmt->dev_name) {
242 300 : dm_free(dmt->dev_name);
243 300 : dmt->dev_name = NULL;
244 : }
245 :
246 : /*
247 : * Path supplied for existing device?
248 : */
249 1506 : if ((pos = strrchr(name, '/'))) {
250 0 : if (dmt->type == DM_DEVICE_CREATE) {
251 0 : log_error("Name \"%s\" invalid. It contains \"/\".", name);
252 0 : return 0;
253 : }
254 :
255 0 : if (stat(name, &st1)) {
256 0 : log_error("Device %s not found", name);
257 0 : return 0;
258 : }
259 :
260 : /*
261 : * If supplied path points to same device as last component
262 : * under /dev/mapper, use that name directly. Otherwise call
263 : * _find_dm_name_of_device() to scan _dm_dir for a match.
264 : */
265 0 : if (dm_snprintf(path, sizeof(path), "%s/%s", _dm_dir,
266 : pos + 1) == -1) {
267 0 : log_error("Couldn't create path for %s", pos + 1);
268 0 : return 0;
269 : }
270 :
271 0 : if (!stat(path, &st2) && (st1.st_rdev == st2.st_rdev))
272 0 : name = pos + 1;
273 0 : else if ((new_name = _find_dm_name_of_device(st1.st_rdev)))
274 0 : name = new_name;
275 : else {
276 0 : log_error("Device %s not found", name);
277 0 : return 0;
278 : }
279 : }
280 :
281 1506 : if (strlen(name) >= DM_NAME_LEN) {
282 0 : log_error("Name \"%s\" too long", name);
283 0 : if (new_name)
284 0 : dm_free(new_name);
285 0 : return 0;
286 : }
287 :
288 1506 : if (new_name)
289 0 : dmt->dev_name = new_name;
290 1506 : else if (!(dmt->dev_name = dm_strdup(name))) {
291 0 : log_error("dm_task_set_name: strdup(%s) failed", name);
292 0 : return 0;
293 : }
294 :
295 1506 : return 1;
296 : }
297 :
298 0 : int dm_task_set_uuid(struct dm_task *dmt, const char *uuid)
299 : {
300 0 : if (dmt->uuid) {
301 0 : dm_free(dmt->uuid);
302 0 : dmt->uuid = NULL;
303 : }
304 :
305 0 : if (!(dmt->uuid = dm_strdup(uuid))) {
306 0 : log_error("dm_task_set_uuid: strdup(%s) failed", uuid);
307 0 : return 0;
308 : }
309 :
310 0 : return 1;
311 : }
312 :
313 0 : int dm_task_set_major(struct dm_task *dmt, int major)
314 : {
315 0 : dmt->major = major;
316 0 : dmt->allow_default_major_fallback = 0;
317 :
318 0 : return 1;
319 : }
320 :
321 0 : int dm_task_set_minor(struct dm_task *dmt, int minor)
322 : {
323 0 : dmt->minor = minor;
324 :
325 0 : return 1;
326 : }
327 :
328 0 : int dm_task_set_major_minor(struct dm_task *dmt, int major, int minor,
329 : int allow_default_major_fallback)
330 : {
331 0 : dmt->major = major;
332 0 : dmt->minor = minor;
333 0 : dmt->allow_default_major_fallback = allow_default_major_fallback;
334 :
335 0 : return 1;
336 : }
337 :
338 0 : int dm_task_set_uid(struct dm_task *dmt, uid_t uid)
339 : {
340 0 : dmt->uid = uid;
341 :
342 0 : return 1;
343 : }
344 :
345 0 : int dm_task_set_gid(struct dm_task *dmt, gid_t gid)
346 : {
347 0 : dmt->gid = gid;
348 :
349 0 : return 1;
350 : }
351 :
352 0 : int dm_task_set_mode(struct dm_task *dmt, mode_t mode)
353 : {
354 0 : dmt->mode = mode;
355 :
356 0 : return 1;
357 : }
358 :
359 301 : int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
360 : const char *ttype, const char *params)
361 : {
362 301 : struct target *t = create_target(start, size, ttype, params);
363 :
364 301 : if (!t)
365 0 : return 0;
366 :
367 301 : if (!dmt->head)
368 301 : dmt->head = dmt->tail = t;
369 : else {
370 0 : dmt->tail->next = t;
371 0 : dmt->tail = t;
372 : }
373 :
374 301 : return 1;
375 : }
376 :
377 0 : int dm_set_selinux_context(const char *path, mode_t mode)
378 : {
379 : #ifdef HAVE_SELINUX
380 : security_context_t scontext;
381 :
382 : if (is_selinux_enabled() <= 0)
383 : return 1;
384 :
385 : if (matchpathcon(path, mode, &scontext) < 0) {
386 : log_error("%s: matchpathcon %07o failed: %s", path, mode,
387 : strerror(errno));
388 : return 0;
389 : }
390 :
391 : log_debug("Setting SELinux context for %s to %s.", path, scontext);
392 :
393 : if ((lsetfilecon(path, scontext) < 0) && (errno != ENOTSUP)) {
394 : log_sys_error("lsetfilecon", path);
395 : freecon(scontext);
396 : return 0;
397 : }
398 :
399 : freecon(scontext);
400 : #endif
401 0 : return 1;
402 : }
403 :
404 0 : static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
405 : uid_t uid, gid_t gid, mode_t mode, int check_udev)
406 : {
407 : char path[PATH_MAX];
408 : struct stat info;
409 0 : dev_t dev = MKDEV(major, minor);
410 : mode_t old_mask;
411 :
412 0 : _build_dev_path(path, sizeof(path), dev_name);
413 :
414 0 : if (stat(path, &info) >= 0) {
415 0 : if (!S_ISBLK(info.st_mode)) {
416 0 : log_error("A non-block device file at '%s' "
417 : "is already present", path);
418 0 : return 0;
419 : }
420 :
421 : /* If right inode already exists we don't touch uid etc. */
422 0 : if (info.st_rdev == dev)
423 0 : return 1;
424 :
425 0 : if (unlink(path) < 0) {
426 0 : log_error("Unable to unlink device node for '%s'",
427 : dev_name);
428 0 : return 0;
429 : }
430 0 : } else if (dm_udev_get_sync_support() && dm_udev_get_checking() &&
431 : check_udev)
432 0 : log_warn("%s not set up by udev: Falling back to direct "
433 : "node creation.", path);
434 :
435 0 : old_mask = umask(0);
436 0 : if (mknod(path, S_IFBLK | mode, dev) < 0) {
437 0 : umask(old_mask);
438 0 : log_error("Unable to make device node for '%s'", dev_name);
439 0 : return 0;
440 : }
441 0 : umask(old_mask);
442 :
443 0 : if (chown(path, uid, gid) < 0) {
444 0 : log_sys_error("chown", path);
445 0 : return 0;
446 : }
447 :
448 0 : log_debug("Created %s", path);
449 :
450 0 : if (!dm_set_selinux_context(path, S_IFBLK))
451 0 : return 0;
452 :
453 0 : return 1;
454 : }
455 :
456 0 : static int _rm_dev_node(const char *dev_name, int check_udev)
457 : {
458 : char path[PATH_MAX];
459 : struct stat info;
460 :
461 0 : _build_dev_path(path, sizeof(path), dev_name);
462 :
463 0 : if (stat(path, &info) < 0)
464 0 : return 1;
465 0 : else if (dm_udev_get_sync_support() && dm_udev_get_checking() &&
466 : check_udev)
467 0 : log_warn("Node %s was not removed by udev. "
468 : "Falling back to direct node removal.", path);
469 :
470 0 : if (unlink(path) < 0) {
471 0 : log_error("Unable to unlink device node for '%s'", dev_name);
472 0 : return 0;
473 : }
474 :
475 0 : log_debug("Removed %s", path);
476 :
477 0 : return 1;
478 : }
479 :
480 0 : static int _rename_dev_node(const char *old_name, const char *new_name,
481 : int check_udev)
482 : {
483 : char oldpath[PATH_MAX];
484 : char newpath[PATH_MAX];
485 : struct stat info;
486 :
487 0 : _build_dev_path(oldpath, sizeof(oldpath), old_name);
488 0 : _build_dev_path(newpath, sizeof(newpath), new_name);
489 :
490 0 : if (stat(newpath, &info) == 0) {
491 0 : if (!S_ISBLK(info.st_mode)) {
492 0 : log_error("A non-block device file at '%s' "
493 : "is already present", newpath);
494 0 : return 0;
495 : }
496 0 : else if (dm_udev_get_sync_support() && dm_udev_get_checking() &&
497 : check_udev) {
498 0 : if (stat(oldpath, &info) < 0 &&
499 0 : errno == ENOENT)
500 : /* assume udev already deleted this */
501 0 : return 1;
502 : else {
503 0 : log_warn("The node %s should have been renamed to %s "
504 : "by udev but old node is still present. "
505 : "Falling back to direct old node removal.",
506 : oldpath, newpath);
507 0 : return _rm_dev_node(old_name, 0);
508 : }
509 : }
510 :
511 0 : if (unlink(newpath) < 0) {
512 0 : if (errno == EPERM) {
513 : /* devfs, entry has already been renamed */
514 0 : return 1;
515 : }
516 0 : log_error("Unable to unlink device node for '%s'",
517 : new_name);
518 0 : return 0;
519 : }
520 : }
521 0 : else if (dm_udev_get_sync_support() && dm_udev_get_checking() &&
522 : check_udev)
523 0 : log_warn("The node %s should have been renamed to %s "
524 : "by udev but new node is not present. "
525 : "Falling back to direct node rename.",
526 : oldpath, newpath);
527 :
528 0 : if (rename(oldpath, newpath) < 0) {
529 0 : log_error("Unable to rename device node from '%s' to '%s'",
530 : old_name, new_name);
531 0 : return 0;
532 : }
533 :
534 0 : log_debug("Renamed %s to %s", oldpath, newpath);
535 :
536 0 : return 1;
537 : }
538 :
539 : #ifdef linux
540 0 : static int _open_dev_node(const char *dev_name)
541 : {
542 0 : int fd = -1;
543 : char path[PATH_MAX];
544 :
545 0 : _build_dev_path(path, sizeof(path), dev_name);
546 :
547 0 : if ((fd = open(path, O_RDONLY, 0)) < 0)
548 0 : log_sys_error("open", path);
549 :
550 0 : return fd;
551 : }
552 :
553 0 : int get_dev_node_read_ahead(const char *dev_name, uint32_t *read_ahead)
554 : {
555 0 : int r = 1;
556 : int fd;
557 : long read_ahead_long;
558 :
559 0 : if (!*dev_name) {
560 0 : log_error("Empty device name passed to BLKRAGET");
561 0 : return 0;
562 : }
563 :
564 0 : if ((fd = _open_dev_node(dev_name)) < 0)
565 0 : return_0;
566 :
567 0 : if (ioctl(fd, BLKRAGET, &read_ahead_long)) {
568 0 : log_sys_error("BLKRAGET", dev_name);
569 0 : *read_ahead = 0;
570 0 : r = 0;
571 : } else {
572 0 : *read_ahead = (uint32_t) read_ahead_long;
573 0 : log_debug("%s: read ahead is %" PRIu32, dev_name, *read_ahead);
574 : }
575 :
576 0 : if (close(fd))
577 0 : stack;
578 :
579 0 : return r;
580 : }
581 :
582 0 : static int _set_read_ahead(const char *dev_name, uint32_t read_ahead)
583 : {
584 0 : int r = 1;
585 : int fd;
586 0 : long read_ahead_long = (long) read_ahead;
587 :
588 0 : if (!*dev_name) {
589 0 : log_error("Empty device name passed to BLKRAGET");
590 0 : return 0;
591 : }
592 :
593 0 : if ((fd = _open_dev_node(dev_name)) < 0)
594 0 : return_0;
595 :
596 0 : log_debug("%s: Setting read ahead to %" PRIu32, dev_name, read_ahead);
597 :
598 0 : if (ioctl(fd, BLKRASET, read_ahead_long)) {
599 0 : log_sys_error("BLKRASET", dev_name);
600 0 : r = 0;
601 : }
602 :
603 0 : if (close(fd))
604 0 : stack;
605 :
606 0 : return r;
607 : }
608 :
609 0 : static int _set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead,
610 : uint32_t read_ahead_flags)
611 : {
612 : uint32_t current_read_ahead;
613 :
614 0 : if (read_ahead == DM_READ_AHEAD_AUTO)
615 0 : return 1;
616 :
617 0 : if (read_ahead == DM_READ_AHEAD_NONE)
618 0 : read_ahead = 0;
619 :
620 0 : if (read_ahead_flags & DM_READ_AHEAD_MINIMUM_FLAG) {
621 0 : if (!get_dev_node_read_ahead(dev_name, ¤t_read_ahead))
622 0 : return_0;
623 :
624 0 : if (current_read_ahead > read_ahead) {
625 0 : log_debug("%s: retaining kernel read ahead of %" PRIu32
626 : " (requested %" PRIu32 ")",
627 : dev_name, current_read_ahead, read_ahead);
628 0 : return 1;
629 : }
630 : }
631 :
632 0 : return _set_read_ahead(dev_name, read_ahead);
633 : }
634 :
635 : #else
636 :
637 : int get_dev_node_read_ahead(const char *dev_name, uint32_t *read_ahead)
638 : {
639 : *read_ahead = 0;
640 :
641 : return 1;
642 : }
643 :
644 : static int _set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead,
645 : uint32_t read_ahead_flags)
646 : {
647 : return 1;
648 : }
649 : #endif
650 :
651 : typedef enum {
652 : NODE_ADD,
653 : NODE_DEL,
654 : NODE_RENAME,
655 : NODE_READ_AHEAD
656 : } node_op_t;
657 :
658 0 : static int _do_node_op(node_op_t type, const char *dev_name, uint32_t major,
659 : uint32_t minor, uid_t uid, gid_t gid, mode_t mode,
660 : const char *old_name, uint32_t read_ahead,
661 : uint32_t read_ahead_flags, int check_udev)
662 : {
663 0 : switch (type) {
664 : case NODE_ADD:
665 0 : return _add_dev_node(dev_name, major, minor, uid, gid,
666 : mode, check_udev);
667 : case NODE_DEL:
668 0 : return _rm_dev_node(dev_name, check_udev);
669 : case NODE_RENAME:
670 0 : return _rename_dev_node(old_name, dev_name, check_udev);
671 : case NODE_READ_AHEAD:
672 0 : return _set_dev_node_read_ahead(dev_name, read_ahead,
673 : read_ahead_flags);
674 : }
675 :
676 0 : return 1;
677 : }
678 :
679 : static DM_LIST_INIT(_node_ops);
680 :
681 : struct node_op_parms {
682 : struct dm_list list;
683 : node_op_t type;
684 : char *dev_name;
685 : uint32_t major;
686 : uint32_t minor;
687 : uid_t uid;
688 : gid_t gid;
689 : mode_t mode;
690 : uint32_t read_ahead;
691 : uint32_t read_ahead_flags;
692 : char *old_name;
693 : int check_udev;
694 : char names[0];
695 : };
696 :
697 1204 : static void _store_str(char **pos, char **ptr, const char *str)
698 : {
699 1204 : strcpy(*pos, str);
700 1204 : *ptr = *pos;
701 1204 : *pos += strlen(*ptr) + 1;
702 1204 : }
703 :
704 602 : static int _stack_node_op(node_op_t type, const char *dev_name, uint32_t major,
705 : uint32_t minor, uid_t uid, gid_t gid, mode_t mode,
706 : const char *old_name, uint32_t read_ahead,
707 : uint32_t read_ahead_flags, int check_udev)
708 : {
709 : struct node_op_parms *nop;
710 : struct dm_list *noph, *nopht;
711 602 : size_t len = strlen(dev_name) + strlen(old_name) + 2;
712 : char *pos;
713 :
714 : /*
715 : * Ignore any outstanding operations on the node if deleting it
716 : */
717 602 : if (type == NODE_DEL) {
718 45451 : dm_list_iterate_safe(noph, nopht, &_node_ops) {
719 45150 : nop = dm_list_item(noph, struct node_op_parms);
720 45150 : if (!strcmp(dev_name, nop->dev_name)) {
721 0 : dm_list_del(&nop->list);
722 0 : dm_free(nop);
723 : }
724 : }
725 : }
726 :
727 602 : if (!(nop = dm_malloc(sizeof(*nop) + len))) {
728 0 : log_error("Insufficient memory to stack mknod operation");
729 0 : return 0;
730 : }
731 :
732 602 : pos = nop->names;
733 602 : nop->type = type;
734 602 : nop->major = major;
735 602 : nop->minor = minor;
736 602 : nop->uid = uid;
737 602 : nop->gid = gid;
738 602 : nop->mode = mode;
739 602 : nop->read_ahead = read_ahead;
740 602 : nop->read_ahead_flags = read_ahead_flags;
741 602 : nop->check_udev = check_udev;
742 :
743 602 : _store_str(&pos, &nop->dev_name, dev_name);
744 602 : _store_str(&pos, &nop->old_name, old_name);
745 :
746 602 : dm_list_add(&_node_ops, &nop->list);
747 :
748 602 : return 1;
749 : }
750 :
751 3 : static void _pop_node_ops(void)
752 : {
753 : struct dm_list *noph, *nopht;
754 : struct node_op_parms *nop;
755 :
756 3 : dm_list_iterate_safe(noph, nopht, &_node_ops) {
757 0 : nop = dm_list_item(noph, struct node_op_parms);
758 0 : _do_node_op(nop->type, nop->dev_name, nop->major, nop->minor,
759 0 : nop->uid, nop->gid, nop->mode, nop->old_name,
760 : nop->read_ahead, nop->read_ahead_flags,
761 : nop->check_udev);
762 0 : dm_list_del(&nop->list);
763 0 : dm_free(nop);
764 : }
765 3 : }
766 :
767 301 : int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
768 : uid_t uid, gid_t gid, mode_t mode, int check_udev)
769 : {
770 301 : log_debug("%s: Stacking NODE_ADD (%" PRIu32 ",%" PRIu32 ") %u:%u 0%o",
771 : dev_name, major, minor, uid, gid, mode);
772 :
773 301 : return _stack_node_op(NODE_ADD, dev_name, major, minor, uid,
774 : gid, mode, "", 0, 0, check_udev);
775 : }
776 :
777 0 : int rename_dev_node(const char *old_name, const char *new_name, int check_udev)
778 : {
779 0 : log_debug("%s: Stacking NODE_RENAME to %s", old_name, new_name);
780 :
781 0 : return _stack_node_op(NODE_RENAME, new_name, 0, 0, 0,
782 : 0, 0, old_name, 0, 0, check_udev);
783 : }
784 :
785 301 : int rm_dev_node(const char *dev_name, int check_udev)
786 : {
787 301 : log_debug("%s: Stacking NODE_DEL (replaces other stacked ops)", dev_name);
788 :
789 301 : return _stack_node_op(NODE_DEL, dev_name, 0, 0, 0,
790 : 0, 0, "", 0, 0, check_udev);
791 : }
792 :
793 602 : int set_dev_node_read_ahead(const char *dev_name, uint32_t read_ahead,
794 : uint32_t read_ahead_flags)
795 : {
796 602 : if (read_ahead == DM_READ_AHEAD_AUTO)
797 602 : return 1;
798 :
799 0 : log_debug("%s: Stacking NODE_READ_AHEAD %" PRIu32 " (flags=%" PRIu32
800 : ")", dev_name, read_ahead, read_ahead_flags);
801 :
802 0 : return _stack_node_op(NODE_READ_AHEAD, dev_name, 0, 0, 0, 0,
803 : 0, "", read_ahead, read_ahead_flags, 0);
804 : }
805 :
806 3 : void update_devs(void)
807 : {
808 3 : _pop_node_ops();
809 3 : }
810 :
811 3 : int dm_set_dev_dir(const char *dev_dir)
812 : {
813 : size_t len;
814 : const char *slash;
815 3 : if (*dev_dir != '/') {
816 0 : log_debug("Invalid dev_dir value, %s: "
817 : "not an absolute name.", dev_dir);
818 0 : return 0;
819 : }
820 :
821 3 : len = strlen(dev_dir);
822 3 : slash = dev_dir[len-1] == '/' ? "" : "/";
823 :
824 3 : if (snprintf(_dm_dir, sizeof _dm_dir, "%s%s%s", dev_dir, slash, DM_DIR)
825 : >= sizeof _dm_dir) {
826 0 : log_debug("Invalid dev_dir value, %s: name too long.", dev_dir);
827 0 : return 0;
828 : }
829 :
830 3 : return 1;
831 : }
832 :
833 604 : const char *dm_dir(void)
834 : {
835 604 : return _dm_dir;
836 : }
837 :
838 1 : int dm_mknodes(const char *name)
839 : {
840 : struct dm_task *dmt;
841 1 : int r = 0;
842 :
843 1 : if (!(dmt = dm_task_create(DM_DEVICE_MKNODES)))
844 0 : return 0;
845 :
846 1 : if (name && !dm_task_set_name(dmt, name))
847 0 : goto out;
848 :
849 1 : if (!dm_task_no_open_count(dmt))
850 0 : goto out;
851 :
852 1 : r = dm_task_run(dmt);
853 :
854 : out:
855 1 : dm_task_destroy(dmt);
856 1 : return r;
857 : }
858 :
859 0 : int dm_driver_version(char *version, size_t size)
860 : {
861 : struct dm_task *dmt;
862 0 : int r = 0;
863 :
864 0 : if (!(dmt = dm_task_create(DM_DEVICE_VERSION)))
865 0 : return 0;
866 :
867 0 : if (!dm_task_run(dmt))
868 0 : log_error("Failed to get driver version");
869 :
870 0 : if (!dm_task_get_driver_version(dmt, version, size))
871 0 : goto out;
872 :
873 0 : r = 1;
874 :
875 : out:
876 0 : dm_task_destroy(dmt);
877 0 : return r;
878 : }
879 :
880 : #ifndef UDEV_SYNC_SUPPORT
881 : void dm_udev_set_sync_support(int sync_with_udev)
882 : {
883 : }
884 :
885 : int dm_udev_get_sync_support(void)
886 : {
887 : return 0;
888 : }
889 :
890 : void dm_udev_set_checking(int checking)
891 : {
892 : }
893 :
894 : int dm_udev_get_checking(void)
895 : {
896 : return 0;
897 : }
898 :
899 : int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags)
900 : {
901 : if (dm_cookie_supported())
902 : dmt->event_nr = flags << DM_UDEV_FLAGS_SHIFT;
903 : *cookie = 0;
904 :
905 : return 1;
906 : }
907 :
908 : int dm_udev_complete(uint32_t cookie)
909 : {
910 : return 1;
911 : }
912 :
913 : int dm_udev_wait(uint32_t cookie)
914 : {
915 : return 1;
916 : }
917 :
918 : #else /* UDEV_SYNC_SUPPORT */
919 :
920 :
921 603 : static int _check_udev_is_running(void)
922 : {
923 : struct udev *udev;
924 : struct udev_queue *udev_queue;
925 : int r;
926 :
927 603 : if (!(udev = udev_new()))
928 0 : goto_bad;
929 :
930 603 : if (!(udev_queue = udev_queue_new(udev))) {
931 0 : udev_unref(udev);
932 0 : goto_bad;
933 : }
934 :
935 603 : if (!(r = udev_queue_get_udev_is_active(udev_queue)))
936 603 : log_debug("Udev is not running. "
937 : "Not using udev synchronisation code.");
938 :
939 603 : udev_queue_unref(udev_queue);
940 603 : udev_unref(udev);
941 :
942 603 : return r;
943 :
944 : bad:
945 0 : log_error("Could not get udev state. Assuming udev is not running.");
946 0 : return 0;
947 : }
948 :
949 0 : void dm_udev_set_sync_support(int sync_with_udev)
950 : {
951 0 : if (_udev_running < 0)
952 0 : _udev_running = _check_udev_is_running();
953 :
954 0 : _sync_with_udev = sync_with_udev;
955 0 : }
956 :
957 2712 : int dm_udev_get_sync_support(void)
958 : {
959 2712 : if (_udev_running < 0)
960 603 : _udev_running = _check_udev_is_running();
961 :
962 2712 : return dm_cookie_supported() && _udev_running && _sync_with_udev;
963 : }
964 :
965 0 : void dm_udev_set_checking(int checking)
966 : {
967 0 : if ((_udev_checking = checking))
968 0 : log_debug("DM udev checking enabled");
969 : else
970 0 : log_debug("DM udev checking disabled");
971 0 : }
972 :
973 0 : int dm_udev_get_checking(void)
974 : {
975 0 : return _udev_checking;
976 : }
977 :
978 0 : static int _get_cookie_sem(uint32_t cookie, int *semid)
979 : {
980 0 : if (cookie >> 16 != DM_COOKIE_MAGIC) {
981 0 : log_error("Could not continue to access notification "
982 : "semaphore identified by cookie value %"
983 : PRIu32 " (0x%x). Incorrect cookie prefix.",
984 : cookie, cookie);
985 0 : return 0;
986 : }
987 :
988 0 : if ((*semid = semget((key_t) cookie, 1, 0)) >= 0)
989 0 : return 1;
990 :
991 0 : switch (errno) {
992 : case ENOENT:
993 0 : log_error("Could not find notification "
994 : "semaphore identified by cookie "
995 : "value %" PRIu32 " (0x%x)",
996 : cookie, cookie);
997 0 : break;
998 : case EACCES:
999 0 : log_error("No permission to access "
1000 : "notificaton semaphore identified "
1001 : "by cookie value %" PRIu32 " (0x%x)",
1002 : cookie, cookie);
1003 0 : break;
1004 : default:
1005 0 : log_error("Failed to access notification "
1006 : "semaphore identified by cookie "
1007 : "value %" PRIu32 " (0x%x): %s",
1008 : cookie, cookie, strerror(errno));
1009 : break;
1010 : }
1011 :
1012 0 : return 0;
1013 : }
1014 :
1015 0 : static int _udev_notify_sem_inc(uint32_t cookie, int semid)
1016 : {
1017 0 : struct sembuf sb = {0, 1, 0};
1018 :
1019 0 : if (semop(semid, &sb, 1) < 0) {
1020 0 : log_error("semid %d: semop failed for cookie 0x%" PRIx32 ": %s",
1021 : semid, cookie, strerror(errno));
1022 0 : return 0;
1023 : }
1024 :
1025 0 : log_debug("Udev cookie 0x%" PRIx32 " (semid %d) incremented",
1026 : cookie, semid);
1027 :
1028 0 : return 1;
1029 : }
1030 :
1031 0 : static int _udev_notify_sem_dec(uint32_t cookie, int semid)
1032 : {
1033 0 : struct sembuf sb = {0, -1, IPC_NOWAIT};
1034 :
1035 0 : if (semop(semid, &sb, 1) < 0) {
1036 0 : switch (errno) {
1037 : case EAGAIN:
1038 0 : log_error("semid %d: semop failed for cookie "
1039 : "0x%" PRIx32 ": "
1040 : "incorrect semaphore state",
1041 : semid, cookie);
1042 0 : break;
1043 : default:
1044 0 : log_error("semid %d: semop failed for cookie "
1045 : "0x%" PRIx32 ": %s",
1046 : semid, cookie, strerror(errno));
1047 : break;
1048 : }
1049 0 : return 0;
1050 : }
1051 :
1052 0 : log_debug("Udev cookie 0x%" PRIx32 " (semid %d) decremented",
1053 : cookie, semid);
1054 :
1055 0 : return 1;
1056 : }
1057 :
1058 0 : static int _udev_notify_sem_destroy(uint32_t cookie, int semid)
1059 : {
1060 0 : if (semctl(semid, 0, IPC_RMID, 0) < 0) {
1061 0 : log_error("Could not cleanup notification semaphore "
1062 : "identified by cookie value %" PRIu32 " (0x%x): %s",
1063 : cookie, cookie, strerror(errno));
1064 0 : return 0;
1065 : }
1066 :
1067 0 : log_debug("Udev cookie 0x%" PRIx32 " (semid %d) destroyed", cookie,
1068 : semid);
1069 :
1070 0 : return 1;
1071 : }
1072 :
1073 0 : static int _udev_notify_sem_create(uint32_t *cookie, int *semid)
1074 : {
1075 : int fd;
1076 : int gen_semid;
1077 : uint16_t base_cookie;
1078 : uint32_t gen_cookie;
1079 :
1080 0 : if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
1081 0 : log_error("Failed to open /dev/urandom "
1082 : "to create random cookie value");
1083 0 : *cookie = 0;
1084 0 : return 0;
1085 : }
1086 :
1087 : /* Generate random cookie value. Be sure it is unique and non-zero. */
1088 : do {
1089 : /* FIXME Handle non-error returns from read(). Move _io() into libdm? */
1090 0 : if (read(fd, &base_cookie, sizeof(base_cookie)) != sizeof(base_cookie)) {
1091 0 : log_error("Failed to initialize notification cookie");
1092 0 : goto bad;
1093 : }
1094 :
1095 0 : gen_cookie = DM_COOKIE_MAGIC << 16 | base_cookie;
1096 :
1097 0 : if (base_cookie && (gen_semid = semget((key_t) gen_cookie,
1098 : 1, 0600 | IPC_CREAT | IPC_EXCL)) < 0) {
1099 0 : switch (errno) {
1100 : case EEXIST:
1101 : /* if the semaphore key exists, we
1102 : * simply generate another random one */
1103 0 : base_cookie = 0;
1104 0 : break;
1105 : case ENOMEM:
1106 0 : log_error("Not enough memory to create "
1107 : "notification semaphore");
1108 0 : goto bad;
1109 : case ENOSPC:
1110 0 : log_error("Limit for the maximum number "
1111 : "of semaphores reached. You can "
1112 : "check and set the limits in "
1113 : "/proc/sys/kernel/sem.");
1114 0 : goto bad;
1115 : default:
1116 0 : log_error("Failed to create notification "
1117 : "semaphore: %s", strerror(errno));
1118 0 : goto bad;
1119 : }
1120 : }
1121 0 : } while (!base_cookie);
1122 :
1123 0 : log_debug("Udev cookie 0x%" PRIx32 " (semid %d) created",
1124 : gen_cookie, gen_semid);
1125 :
1126 0 : if (semctl(gen_semid, 0, SETVAL, 1) < 0) {
1127 0 : log_error("semid %d: semctl failed: %s", gen_semid, strerror(errno));
1128 : /* We have to destroy just created semaphore
1129 : * so it won't stay in the system. */
1130 0 : (void) _udev_notify_sem_destroy(gen_cookie, gen_semid);
1131 0 : goto bad;
1132 : }
1133 :
1134 0 : log_debug("Udev cookie 0x%" PRIx32 " (semid %d) incremented",
1135 : gen_cookie, gen_semid);
1136 :
1137 0 : if (close(fd))
1138 0 : stack;
1139 :
1140 0 : *semid = gen_semid;
1141 0 : *cookie = gen_cookie;
1142 :
1143 0 : return 1;
1144 :
1145 : bad:
1146 0 : if (close(fd))
1147 0 : stack;
1148 :
1149 0 : *cookie = 0;
1150 :
1151 0 : return 0;
1152 : }
1153 :
1154 0 : int dm_udev_create_cookie(uint32_t *cookie)
1155 : {
1156 : int semid;
1157 :
1158 0 : if (!dm_udev_get_sync_support()) {
1159 0 : *cookie = 0;
1160 0 : return 1;
1161 : }
1162 :
1163 0 : return _udev_notify_sem_create(cookie, &semid);
1164 : }
1165 :
1166 602 : int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags)
1167 : {
1168 : int semid;
1169 :
1170 602 : if (dm_cookie_supported())
1171 602 : dmt->event_nr = flags << DM_UDEV_FLAGS_SHIFT;
1172 :
1173 602 : if (!dm_udev_get_sync_support()) {
1174 602 : *cookie = 0;
1175 602 : return 1;
1176 : }
1177 :
1178 0 : if (*cookie) {
1179 0 : if (!_get_cookie_sem(*cookie, &semid))
1180 0 : goto_bad;
1181 0 : } else if (!_udev_notify_sem_create(cookie, &semid))
1182 0 : goto_bad;
1183 :
1184 0 : if (!_udev_notify_sem_inc(*cookie, semid)) {
1185 0 : log_error("Could not set notification semaphore "
1186 : "identified by cookie value %" PRIu32 " (0x%x)",
1187 : *cookie, *cookie);
1188 0 : goto bad;
1189 : }
1190 :
1191 0 : dmt->event_nr |= ~DM_UDEV_FLAGS_MASK & *cookie;
1192 0 : dmt->cookie_set = 1;
1193 :
1194 0 : log_debug("Udev cookie 0x%" PRIx32 " (semid %d) assigned to dm_task "
1195 : "with flags 0x%" PRIx16, *cookie, semid, flags);
1196 :
1197 0 : return 1;
1198 :
1199 : bad:
1200 0 : dmt->event_nr = 0;
1201 0 : return 0;
1202 : }
1203 :
1204 0 : int dm_udev_complete(uint32_t cookie)
1205 : {
1206 : int semid;
1207 :
1208 0 : if (!cookie || !dm_udev_get_sync_support())
1209 0 : return 1;
1210 :
1211 0 : if (!_get_cookie_sem(cookie, &semid))
1212 0 : return_0;
1213 :
1214 0 : if (!_udev_notify_sem_dec(cookie, semid)) {
1215 0 : log_error("Could not signal waiting process using notification "
1216 : "semaphore identified by cookie value %" PRIu32 " (0x%x)",
1217 : cookie, cookie);
1218 0 : return 0;
1219 : }
1220 :
1221 0 : return 1;
1222 : }
1223 :
1224 602 : int dm_udev_wait(uint32_t cookie)
1225 : {
1226 : int semid;
1227 602 : struct sembuf sb = {0, 0, 0};
1228 :
1229 602 : if (!cookie || !dm_udev_get_sync_support())
1230 602 : return 1;
1231 :
1232 0 : if (!_get_cookie_sem(cookie, &semid))
1233 0 : return_0;
1234 :
1235 0 : if (!_udev_notify_sem_dec(cookie, semid)) {
1236 0 : log_error("Failed to set a proper state for notification "
1237 : "semaphore identified by cookie value %" PRIu32 " (0x%x) "
1238 : "to initialize waiting for incoming notifications.",
1239 : cookie, cookie);
1240 0 : (void) _udev_notify_sem_destroy(cookie, semid);
1241 0 : return 0;
1242 : }
1243 :
1244 0 : log_debug("Udev cookie 0x%" PRIx32 " (semid %d): Waiting for zero",
1245 : cookie, semid);
1246 :
1247 : repeat_wait:
1248 0 : if (semop(semid, &sb, 1) < 0) {
1249 0 : if (errno == EINTR)
1250 0 : goto repeat_wait;
1251 0 : else if (errno == EIDRM)
1252 0 : return 1;
1253 :
1254 0 : log_error("Could not set wait state for notification semaphore "
1255 : "identified by cookie value %" PRIu32 " (0x%x): %s",
1256 : cookie, cookie, strerror(errno));
1257 0 : (void) _udev_notify_sem_destroy(cookie, semid);
1258 0 : return 0;
1259 : }
1260 :
1261 0 : return _udev_notify_sem_destroy(cookie, semid);
1262 : }
1263 :
1264 : #endif /* UDEV_SYNC_SUPPORT */
|