static int _lookup_dev_name(uint64_t dev, char *buf, size_t len) { struct dm_names *names; unsigned next = 0; struct dm_task *dmt; int r = 0; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) return 0; if (!dm_task_run(dmt)) goto out; if (!(names = dm_task_get_names(dmt))) goto out; if (!names->dev) goto out; do { names = (void *) names + next; if (names->dev == dev) { strncpy(buf, names->name, len); r = 1; break; } next = names->next; } while (next); out: dm_task_destroy(dmt); return r; }
int era_dm_list(int (*cb)(void *arg, const char *name), void *cbarg) { struct dm_task *dmt; struct dm_names *names; unsigned next = 0; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) return -1; if (!dm_task_run(dmt)) goto out; if (!(names = dm_task_get_names(dmt))) goto out; if (names->dev) { do { names = (struct dm_names *)((char *)names + next); if (cb(cbarg, names->name)) goto out; next = names->next; } while(next); } dm_task_destroy(dmt); return 0; out: dm_task_destroy(dmt); return -1; }
extern int dm_flush_maps (void) { int r = 0; struct dm_task *dmt; struct dm_names *names; unsigned next = 0; if (!(dmt = dm_task_create (DM_DEVICE_LIST))) return 0; dm_task_no_open_count(dmt); if (!dm_task_run (dmt)) goto out; if (!(names = dm_task_get_names (dmt))) goto out; if (!names->dev) goto out; do { r |= dm_suspend_and_flush_map(names->name); next = names->next; names = (void *) names + next; } while (next); out: dm_task_destroy (dmt); return r; }
static int dm_device_remove(uint64_t dev) { struct dm_task *dmt; struct dm_names *dmnames; char *name = NULL; int ret = 0; /* Look for dev_name via dev, if dev_name could be transferred here, we could jump to DM_DEVICE_REMOVE directly */ dmt = dm_task_create(DM_DEVICE_LIST); if (!dmt) { BL_LOG_ERR("dm_task creation failed\n"); goto out; } ret = dm_task_run(dmt); if (!ret) { BL_LOG_ERR("dm_task_run failed\n"); goto out; } dmnames = dm_task_get_names(dmt); if (!dmnames || !dmnames->dev) { BL_LOG_ERR("dm_task_get_names failed\n"); goto out; } while (dmnames) { if (dmnames->dev == dev) { name = strdup(dmnames->name); break; } dmnames = (void *)dmnames + dmnames->next; } if (!name) { BL_LOG_ERR("Could not find device\n"); goto out; } dm_task_update_nodes(); out: if (dmt) dm_task_destroy(dmt); /* Start to remove device */ if (name) { ret = dm_device_remove_byname(name); free(name); } return ret; }
static int _process_all_v4(struct dm_task *dmt) { struct dm_task *task; struct dm_names *names; unsigned next = 0; int r = 1; if (!(task = dm_task_create(DM_DEVICE_LIST))) return 0; if (!dm_task_run(task)) { r = 0; goto out; } if (!(names = dm_task_get_names(task))) { r = 0; goto out; } if (!names->dev) goto out; do { names = (void *) names + next; if (!dm_task_set_name(dmt, names->name)) { r = 0; goto out; } if (!dm_task_run(dmt)) r = 0; next = names->next; } while (next); out: dm_task_destroy(task); return r; }
static int virStorageBackendGetMaps(virStoragePoolObjPtr pool) { int retval = 0; struct dm_task *dmt = NULL; struct dm_names *names = NULL; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) { retval = 1; goto out; } dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) { retval = 1; goto out; } if (!(names = dm_task_get_names(dmt))) { retval = 1; goto out; } if (!names->dev) { /* No devices found */ goto out; } virStorageBackendCreateVols(pool, names); out: if (dmt != NULL) { dm_task_destroy (dmt); } return retval; }
void grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), int floppy_disks) { int i; clear_seen_devices (); /* Floppies. */ for (i = 0; i < floppy_disks; i++) { char name[16]; struct stat st; get_floppy_disk_name (name, i); if (stat (name, &st) < 0) break; /* In floppies, write the map, whether check_device_readable_unique succeeds or not, because the user just may not insert floppies. */ if (hook (name, 1)) goto out; } #ifdef __linux__ { DIR *dir = opendir ("/dev/disk/by-id"); if (dir) { struct dirent *entry; struct device *devs; size_t devs_len = 0, devs_max = 1024, i; devs = xmalloc (devs_max * sizeof (*devs)); /* Dump all the directory entries into names, resizing if necessary. */ for (entry = readdir (dir); entry; entry = readdir (dir)) { /* Skip current and parent directory entries. */ if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0) continue; /* Skip partition entries. */ if (strstr (entry->d_name, "-part")) continue; /* Skip device-mapper entries; we'll handle the ones we want later. */ if (strncmp (entry->d_name, "dm-", sizeof ("dm-") - 1) == 0) continue; /* Skip RAID entries; they are handled by upper layers. */ if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0) continue; if (devs_len >= devs_max) { devs_max *= 2; devs = xrealloc (devs, devs_max * sizeof (*devs)); } devs[devs_len].stable = xasprintf ("/dev/disk/by-id/%s", entry->d_name); devs[devs_len].kernel = canonicalize_file_name (devs[devs_len].stable); devs_len++; } qsort (devs, devs_len, sizeof (*devs), &compare_devices); closedir (dir); /* Now add all the devices in sorted order. */ for (i = 0; i < devs_len; ++i) { if (check_device_readable_unique (devs[i].stable)) { if (hook (devs[i].stable, 0)) goto out; } free (devs[i].stable); free (devs[i].kernel); } free (devs); } } if (have_devfs ()) { i = 0; while (1) { char discn[32]; char name[PATH_MAX]; struct stat st; /* Linux creates symlinks "/dev/discs/discN" for convenience. The way to number disks is the same as GRUB's. */ sprintf (discn, "/dev/discs/disc%d", i++); if (stat (discn, &st) < 0) break; if (realpath (discn, name)) { strcat (name, "/disc"); if (hook (name, 0)) goto out; } } goto out; } #endif /* __linux__ */ /* IDE disks. */ for (i = 0; i < 96; i++) { char name[16]; get_ide_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } #ifdef __FreeBSD_kernel__ /* IDE disks using ATA Direct Access driver. */ if (get_kfreebsd_version () >= 800000) for (i = 0; i < 96; i++) { char name[16]; get_ada_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } /* ATARAID disks. */ for (i = 0; i < 8; i++) { char name[20]; get_ataraid_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } #endif #ifdef __linux__ /* Virtio disks. */ for (i = 0; i < 26; i++) { char name[16]; get_virtio_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } /* ATARAID disks. */ for (i = 0; i < 8; i++) { char name[20]; get_ataraid_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } /* Xen virtual block devices. */ for (i = 0; i < 26; i++) { char name[16]; get_xvd_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } #endif /* __linux__ */ /* The rest is SCSI disks. */ for (i = 0; i < 48; i++) { char name[16]; get_scsi_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } #ifdef __linux__ /* This is for DAC960 - we have /dev/rd/c<controller>d<logical drive>p<partition>. DAC960 driver currently supports up to 8 controllers, 32 logical drives, and 7 partitions. */ { int controller, drive; for (controller = 0; controller < 8; controller++) { for (drive = 0; drive < 15; drive++) { char name[24]; get_dac960_disk_name (name, controller, drive); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } } /* This is for Mylex Acceleraid - we have /dev/rd/c<controller>d<logical drive>p<partition>. */ { int controller, drive; for (controller = 0; controller < 8; controller++) { for (drive = 0; drive < 15; drive++) { char name[24]; get_acceleraid_disk_name (name, controller, drive); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } } /* This is for CCISS - we have /dev/cciss/c<controller>d<logical drive>p<partition>. */ { int controller, drive; for (controller = 0; controller < 3; controller++) { for (drive = 0; drive < 16; drive++) { char name[24]; get_cciss_disk_name (name, controller, drive); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } } /* This is for Compaq Intelligent Drive Array - we have /dev/ida/c<controller>d<logical drive>p<partition>. */ { int controller, drive; for (controller = 0; controller < 3; controller++) { for (drive = 0; drive < 16; drive++) { char name[24]; get_ida_disk_name (name, controller, drive); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } } /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */ { char unit; for (unit = 'a'; unit < 'f'; unit++) { char name[24]; get_i2o_disk_name (name, unit); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } /* MultiMediaCard (MMC). */ for (i = 0; i < 10; i++) { char name[16]; get_mmc_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } # ifdef HAVE_DEVICE_MAPPER # define dmraid_check(cond, ...) \ if (! (cond)) \ { \ grub_dprintf ("deviceiter", __VA_ARGS__); \ goto dmraid_end; \ } /* DM-RAID. */ if (grub_device_mapper_supported ()) { struct dm_tree *tree = NULL; struct dm_task *task = NULL; struct dm_names *names = NULL; unsigned int next = 0; void *top_handle, *second_handle; struct dm_tree_node *root, *top, *second; /* Build DM tree for all devices. */ tree = dm_tree_create (); dmraid_check (tree, "dm_tree_create failed\n"); task = dm_task_create (DM_DEVICE_LIST); dmraid_check (task, "dm_task_create failed\n"); dmraid_check (dm_task_run (task), "dm_task_run failed\n"); names = dm_task_get_names (task); dmraid_check (names, "dm_task_get_names failed\n"); dmraid_check (names->dev, "No DM devices found\n"); do { names = (void *) names + next; dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev), MINOR (names->dev)), "dm_tree_add_dev (%s) failed\n", names->name); next = names->next; } while (next); /* Walk the second-level children of the inverted tree; that is, devices which are directly composed of non-DM devices such as hard disks. This class includes all DM-RAID disks and excludes all DM-RAID partitions. */ root = dm_tree_find_node (tree, 0, 0); top_handle = NULL; top = dm_tree_next_child (&top_handle, root, 1); while (top) { second_handle = NULL; second = dm_tree_next_child (&second_handle, top, 1); while (second) { const char *node_name, *node_uuid; char *name; node_name = dm_tree_node_get_name (second); dmraid_check (node_name, "dm_tree_node_get_name failed\n"); node_uuid = dm_tree_node_get_uuid (second); dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n"); if (strncmp (node_uuid, "DMRAID-", 7) != 0) { grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name); goto dmraid_next_child; } name = xasprintf ("/dev/mapper/%s", node_name); if (check_device_readable_unique (name)) { if (hook (name, 0)) { free (name); if (task) dm_task_destroy (task); if (tree) dm_tree_free (tree); goto out; } } free (name); dmraid_next_child: second = dm_tree_next_child (&second_handle, top, 1); } top = dm_tree_next_child (&top_handle, root, 1); } dmraid_end: if (task) dm_task_destroy (task); if (tree) dm_tree_free (tree); } # endif /* HAVE_DEVICE_MAPPER */ #endif /* __linux__ */ out: clear_seen_devices (); }
/** * bd_mpath_is_mpath_member: * @device: device to test * @error: (out): place to store error (if any) * * Returns: %TRUE if the device is a multipath member, %FALSE if not or an error * appeared when queried (@error is set in those cases) */ gboolean bd_mpath_is_mpath_member (const gchar *device, GError **error) { struct dm_task *task_names = NULL; struct dm_names *names = NULL; gchar *symlink = NULL; guint64 next = 0; gchar **deps = NULL; gchar **dev_name = NULL; gboolean ret = FALSE; if (geteuid () != 0) { g_set_error (error, BD_MPATH_ERROR, BD_MPATH_ERROR_NOT_ROOT, "Not running as root, cannot query DM maps"); return FALSE; } /* we check if the 'device' is a dependency of any multipath map */ /* get maps */ task_names = dm_task_create(DM_DEVICE_LIST); if (!task_names) { g_warning ("Failed to create DM task"); g_set_error (error, BD_MPATH_ERROR, BD_MPATH_ERROR_DM_ERROR, "Failed to create DM task"); return FALSE; } dm_task_run(task_names); names = dm_task_get_names(task_names); if (!names || !names->dev) return FALSE; /* in case the device is symlink, we need to resolve it because maps's deps are devices and not their symlinks */ if (g_str_has_prefix (device, "/dev/mapper/") || g_str_has_prefix (device, "/dev/md/")) { symlink = g_file_read_link (device, error); if (!symlink) { /* the device doesn't exist and thus is not an mpath member */ g_clear_error (error); dm_task_destroy (task_names); return FALSE; } /* the symlink starts with "../" */ device = symlink + 3; } if (g_str_has_prefix (device, "/dev/")) device += 5; /* check all maps */ do { names = (void *)names + next; next = names->next; /* we are only interested in multipath maps */ if (map_is_multipath (names->name, error)) { deps = get_map_deps (names->name, NULL, error); if (*error) { g_prefix_error (error, "Failed to determine deps for '%s'", names->name); g_free (symlink); dm_task_destroy (task_names); return FALSE; } for (dev_name = deps; !ret && *dev_name; dev_name++) ret = (g_strcmp0 (*dev_name, device) == 0); g_strfreev (deps); } else if (*error) { g_prefix_error (error, "Failed to determine map's target for '%s'", names->name); g_free (symlink); dm_task_destroy (task_names); return FALSE; } } while (!ret && next); g_free (symlink); dm_task_destroy (task_names); return ret; }
int dm_get_maps (vector mp) { struct multipath * mpp; int r = 1; struct dm_task *dmt; struct dm_names *names; unsigned next = 0; if (!mp) return 1; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) return 1; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; if (!(names = dm_task_get_names(dmt))) goto out; if (!names->dev) { r = 0; /* this is perfectly valid */ goto out; } do { if (!dm_is_mpath(names->name)) goto next; mpp = alloc_multipath(); if (!mpp) goto out; mpp->alias = STRDUP(names->name); if (!mpp->alias) goto out1; if (dm_get_map(names->name, &mpp->size, NULL)) goto out1; dm_get_uuid(names->name, mpp->wwid); dm_get_info(names->name, &mpp->dmi); if (!vector_alloc_slot(mp)) goto out1; vector_set_slot(mp, mpp); mpp = NULL; next: next = names->next; names = (void *) names + next; } while (next); r = 0; goto out; out1: free_multipath(mpp, KEEP_PATHS); out: dm_task_destroy (dmt); return r; }
static int do_foreach_partmaps (const char * mapname, int (*partmap_func)(const char *, void *), void *data) { struct dm_task *dmt; struct dm_names *names; unsigned next = 0; char params[PARAMS_SIZE]; unsigned long long size; char dev_t[32]; int r = 1; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) return 1; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; if (!(names = dm_task_get_names(dmt))) goto out; if (!names->dev) { r = 0; /* this is perfectly valid */ goto out; } if (dm_dev_t(mapname, &dev_t[0], 32)) goto out; do { if ( /* * if devmap target is "linear" */ (dm_type(names->name, TGT_PART) > 0) && /* * and both uuid end with same suffix starting * at UUID_PREFIX */ (!dm_compare_uuid(names->name, mapname)) && /* * and we can fetch the map table from the kernel */ !dm_get_map(names->name, &size, ¶ms[0]) && /* * and the table maps over the multipath map */ strstr(params, dev_t) ) { if (partmap_func(names->name, data) != 0) goto out; } next = names->next; names = (void *) names + next; } while (next); r = 0; out: dm_task_destroy (dmt); return r; }