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;
}
예제 #2
0
파일: era_dm.c 프로젝트: 004helix/erasetup
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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 ();
}
예제 #8
0
/**
 * 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;
}
예제 #9
0
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;
}
예제 #10
0
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, &params[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;
}