Example #1
0
/*
 * For the master device:
 *	/dev/lofictl -> /devices/pseudo/lofi@0:ctl
 * For each other device
 *	/dev/lofi/1 -> /devices/pseudo/lofi@0:1
 *	/dev/rlofi/1 -> /devices/pseudo/lofi@0:1,raw
 */
static int
lofi(di_minor_t minor, di_node_t node)
{
	dev_t	dev;
	char mn[MAXNAMELEN + 1];
	char blkname[MAXNAMELEN + 1];
	char rawname[MAXNAMELEN + 1];
	char path[PATH_MAX + 1];

	(void) strcpy(mn, di_minor_name(minor));

	if (strcmp(mn, "ctl") == 0) {
		(void) devfsadm_mklink(LOFI_CTL_NAME, node, minor, 0);
	} else {
		dev = di_minor_devt(minor);
		(void) snprintf(blkname, sizeof (blkname), "%d",
		    (int)minor(dev));
		(void) snprintf(rawname, sizeof (rawname), "%d,raw",
		    (int)minor(dev));

		if (strcmp(mn, blkname) == 0) {
			(void) snprintf(path, sizeof (path), "%s/%s",
			    LOFI_BLOCK_NAME, blkname);
		} else if (strcmp(mn, rawname) == 0) {
			(void) snprintf(path, sizeof (path), "%s/%s",
			    LOFI_CHAR_NAME, blkname);
		} else {
			return (DEVFSADM_CONTINUE);
		}

		(void) devfsadm_mklink(path, node, minor, 0);
	}
	return (DEVFSADM_CONTINUE);
}
Example #2
0
static int
is_zvol(di_node_t node, di_minor_t minor)
{
	if ((strncmp(di_node_name(node), ZFS_DRIVER, 3) == 0) &&
	    minor(di_minor_devt(minor)))
		return (1);
	return (0);
}
Example #3
0
int
wrsm(di_minor_t minor, di_node_t node)
{
	const char *node_name = di_node_name(node);
	const char *minor_name = di_minor_name(minor);
	char path[PATH_MAX + 1];

	if (minor_name == NULL || node_name == NULL) {
		return (DEVFSADM_CONTINUE);
	}
	if (strcmp(minor_name, "admin") == 0) {
		/* admin pseudo device */
		(void) snprintf(path, sizeof (path), "%s%s", node_name,
		    minor_name);
	} else if (strcmp(minor_name, "ctrl") == 0) {
		/* controller pseudo device */
		dev_t dev = di_minor_devt(minor);
		minor_t dev_minor = minor(dev);
		(void) snprintf(path, sizeof (path), "%s%u", node_name,
		    (uint_t)dev_minor);
	} else {
		/*
		 * For hardware devices, the devlink must be
		 * /dev/<node_name><portid>. devpath is of the format
		 * ".../<node_name>@<portid>,0". Need to extract the
		 * <portid> for use in bulding devlink.
		 */
		char devpath[PATH_MAX + 1];
		char *devfs_path;
		int i;

		devfs_path = di_devfs_path(node);
		if (devfs_path == NULL) {
			return (DEVFSADM_CONTINUE);
		}
		(void) strcpy(devpath, devfs_path);
		di_devfs_path_free(devfs_path);

		for (i = strlen(devpath); devpath[i] != '@' && i > 0; i--) {
			if (devpath[i] == ',') {
				devpath[i] = 0;
			}
		}
		if (i == 0) {
			return (DEVFSADM_CONTINUE);
		}
		(void) snprintf(path, sizeof (path), "wci%s", &devpath[i+1]);
	}
	(void) devfsadm_mklink(path, node, minor, 0);

	return (DEVFSADM_CONTINUE);
}
/*
 * For the zfs control node:
 *	/dev/zfs -> /devices/pseudo/zfs@0:zfs
 * For zvols:
 *	/dev/zvol/dsk/<pool>/<dataset> -> /devices/pseudo/zfs@0:1
 *	/dev/zvol/rdsk/<pool>/<dataset> -> /devices/pseudo/zfs@0:1,raw
 */
static int
zfs(di_minor_t minor, di_node_t node)
{
	dev_t	dev;
	int	err;
	char mn[MAXNAMELEN + 1];
	char blkname[MAXNAMELEN + 1];
	char rawname[MAXNAMELEN + 1];
	char path[PATH_MAX + 1];
	char *name;

	(void) strcpy(mn, di_minor_name(minor));

	if (strcmp(mn, ZFS_DRIVER) == 0) {
		(void) devfsadm_mklink(ZFS_DRIVER, node, minor, 0);
	} else {
		dev = di_minor_devt(minor);
		err = di_prop_lookup_strings(dev, node, ZVOL_PROP_NAME, &name);
		if (err < 0) {
			/* property not defined so can't do anything */
			return (DEVFSADM_CONTINUE);
		}
		(void) snprintf(blkname, sizeof (blkname), "%dc",
		    (int)minor(dev));
		(void) snprintf(rawname, sizeof (rawname), "%dc,raw",
		    (int)minor(dev));

		/*
		 * This is where the actual public name gets constructed.
		 * Change the snprintf format to change the public
		 * path that gets constructed.
		 */
		if (strcmp(mn, blkname) == 0) {
			(void) snprintf(path, sizeof (path), "%s/%s",
			    ZVOL_DEV_DIR, name);
		} else if (strcmp(mn, rawname) == 0) {
			(void) snprintf(path, sizeof (path), "%s/%s",
			    ZVOL_RDEV_DIR, name);
		} else {
			return (DEVFSADM_CONTINUE);
		}

		(void) devfsadm_mklink(path, node, minor, 0);
	}
	return (DEVFSADM_CONTINUE);
}
Example #5
0
static int
dm(di_minor_t minor, di_node_t node)
{
	dev_t	dev;
	minor_t	minorno;
	char	minorname[MAXNAMELEN + 1];
	char	dmname[MAXNAMELEN + 1];
	char	blkname[MAXNAMELEN + 1];
	char	rawname[MAXNAMELEN + 1];
	char	path[PATH_MAX + 1];

	(void) strcpy(minorname, di_minor_name(minor));
	dev = di_minor_devt(minor);
	minorno = minor(dev);

	/* Is it a control node ? */
	if ((minorno == 0) && (strcmp(minorname, "ctl") == 0)) {
		(void) devfsadm_mklink(DM_CONTROL_NODE, node, minor, 0);
		(void) devfsadm_secondary_link(DM_CONTROL_LINUX,
		    DM_CONTROL_NODE, 0);
		return (DEVFSADM_CONTINUE);
	}

	/* If we got here that is not a control node */
	(void) strlcpy(dmname, sizeof (dmname), minorname);
	
	(void) snprintf(blkname, sizeof (blkname), "%s,blk", minorname);
	(void) snprintf(rawname, sizeof (rawname), "%s,raw", minorname);

		if (strcmp(mn, blkname) == 0) {
			(void) snprintf(path, sizeof (path), "%s/%s",
			    DM_BLOCK_NAME, blkname);
		} else if (strcmp(mn, rawname) == 0) {
			(void) snprintf(path, sizeof (path), "%s/%s",
			    DM_CHAR_NAME, blkname);
		} else {
			return (DEVFSADM_CONTINUE);
		}

		(void) devfsadm_mklink(path, node, minor, 0);

	return (DEVFSADM_CONTINUE);
}
Example #6
0
/*
 * For the admin device:
 *	/dev/md/admin -> /devices/pseudo/md@0:admin
 *
 * For metadevice:
 *	/dev/md/dsk/foobar --> /devices/pseudo/md@0:0,100,blk
 *	/dev/md/rdsk/foobar --> /devices/pseudo/md@0:0,100,raw
 *
 * Where 'foobar' is user specified arbitrary name and '100'
 * is the minor number returned by MD_IOCMAKE_DEV ioctl
 *
 */
static int
md_create(di_minor_t minor, di_node_t node)
{
	char mn[MAXNAMELEN + 1];
	char path[PATH_MAX + 1];
	char set_path[PATH_MAX +1];
	char sym_path[PATH_MAX + 1];
	int set = -1, ret;
	char *type, *dir;
	char *device_name;
	dev_t minor_devt = di_minor_devt(minor);
	int key;
	mdsetname_t	*sp = NULL;
	md_error_t ep;

	/*
	 * Initialize sdssc entry points. Don't worry about the return
	 * value here since the interface functions will get initialized
	 * correctly regardless.
	 */
	(void) sdssc_bind_library();

	(void) strcpy(mn, di_minor_name(minor));

	/*
	 * Check whether we are being requested to setup the admin
	 * device link or one of the metadevice links. They need
	 * to be treated differently.
	 */

	if (strcmp(mn, "admin") == 0) {
		/* there is only one admin link and always in /dev/md/admin */
		(void) devfsadm_mklink("md/admin", node, minor, 0);
	} else {
		/*
		 * Extract out the minor components and create the
		 * appropriate links. The node looks like:
		 * md@<set>,<mdev>,<type>
		 * where the <set> number is the named diskset,
		 * <mdev> is the metadevice number, and <type>
		 * is the trailing "blk" or "raw" indication.
		 *
		 * NOTE: when <set> is non-zero, we need to create
		 * under the "shared" directory entry instead of linking
		 * into the top level dsk/rdsk directories.
		 */
		ret = sscanf(mn, "%d,", &set);
		if (ret == 1 && (type = strrchr(mn, ',')) != NULL) {
			type++;
			if (strcmp(type, "blk") == 0) {
				dir = "dsk";
			} else {
				dir = "rdsk";
			}

			(void) memset(&ep, '\0', sizeof (ep));
			if ((device_name = meta_getnmentbydev(set,
			    MD_SIDEWILD, minor_devt, NULL, NULL,
			    &key, &ep)) == NULL) {
				(void) close_admin(&ep);
				return (DEVFSADM_CONTINUE);
			}

			if (set == 0) {
				/* this is a simple md */
				(void) snprintf(path, sizeof (path),
				    "md/%s/%s", dir, basename(device_name));
			} else {
				/* this is a shared md */
				(void) snprintf(path, sizeof (path),
				    "md/shared/%d/%s/%s", set, dir,
				    basename(device_name));

				/*
				 * flush the caches so the next call to
				 * metasetnosetname will get us the
				 * updated cache.
				 */
				metaflushnames(0);
				if ((sp = metasetnosetname(set, &ep))
				    != NULL) {
					(void) snprintf(set_path,
					    sizeof (set_path), "md/shared/%d",
					    sp->setno);
					(void) snprintf(sym_path,
					    sizeof (sym_path), "md/%s",
					    sp->setname);
				}
			}
			(void) devfsadm_mklink(path, node, minor, 0);
			Free(device_name);

			if (sp != NULL) {
				(void) devfsadm_secondary_link(sym_path,
				    set_path, 0);
			}
		}
	}

	(void) close_admin(&ep);
	return (DEVFSADM_CONTINUE);
}
Example #7
0
static int
add_devs(di_node_t node, di_minor_t minor, void *arg)
{
	struct search_args	*args;
	int result = DI_WALK_CONTINUE;

	args = (struct search_args *)arg;

	if (dm_debug > 1) {
		/* This is all just debugging code */
		char	*devpath;
		char	dev_name[MAXPATHLEN];

		devpath = di_devfs_path(node);
		(void) snprintf(dev_name, sizeof (dev_name), "%s:%s", devpath,
		    di_minor_name(minor));
		di_devfs_path_free((void *) devpath);

		(void) fprintf(stderr,
		    "INFO: dev: %s, node: %s%d, minor: 0x%x, type: %s\n",
		    dev_name, di_node_name(node), di_instance(node),
		    di_minor_spectype(minor),
		    (di_minor_nodetype(minor) != NULL ?
		    di_minor_nodetype(minor) : "NULL"));
	}

	if (bus_type(node, minor, args->ph) != NULL) {
		if (add_bus(args, node, minor, NULL) == NULL) {
			args->dev_walk_status = ENOMEM;
			result = DI_WALK_TERMINATE;
		}

	} else if (is_ctrl(node, minor)) {
		if (add_controller(args, node, minor) == NULL) {
			args->dev_walk_status = ENOMEM;
			result = DI_WALK_TERMINATE;
		}

	} else if (di_minor_spectype(minor) == S_IFCHR &&
	    (is_drive(minor) || is_zvol(node, minor))) {
		char	*devidstr;
		char	kernel_name[MAXPATHLEN];
		disk_t	*diskp;

		(void) snprintf(kernel_name, sizeof (kernel_name), "%s%d",
		    di_node_name(node), di_instance(node));
		devidstr = get_str_prop(DEVICE_ID_PROP, node);

		args->node = node;
		args->minor = minor;
		/*
		 * Check if we already got this disk and
		 * this is another slice.
		 */
		if (!have_disk(args, devidstr, kernel_name, &diskp)) {
			args->dev_walk_status = 0;
			/*
			 * This is a newly found disk, create the
			 * disk structure.
			 */
			diskp = create_disk(devidstr, kernel_name, args);
			if (diskp == NULL) {
				args->dev_walk_status = ENOMEM;
			}

			if (diskp->drv_type != DM_DT_FLOPPY) {
				/* add the controller relationship */
				if (args->dev_walk_status == 0) {
					if (add_disk2controller(diskp,
					    args) != 0) {
						args->dev_walk_status = ENOMEM;
					}
				}
			}
		}
		if (is_zvol(node, minor)) {
			char zvdsk[MAXNAMELEN];
			char *str;
			alias_t *ap;

			if (di_prop_lookup_strings(di_minor_devt(minor),
			    node, "name", &str) == -1)
				return (DI_WALK_CONTINUE);
			(void) snprintf(zvdsk, MAXNAMELEN, "/dev/zvol/rdsk/%s",
			    str);
			if ((ap = find_alias(diskp, kernel_name)) == NULL) {
				if (new_alias(diskp, kernel_name,
				    zvdsk, args) != 0) {
					args->dev_walk_status = ENOMEM;
				}
			} else {
				/*
				 * It is possible that we have already added
				 * this devpath.
				 * Do not add it again. new_devpath will
				 * return a 0 if found, and not add the path.
				 */
				if (new_devpath(ap, zvdsk) != 0) {
					args->dev_walk_status = ENOMEM;
				}
			}
		}

		/* Add the devpaths for the drive. */
		if (args->dev_walk_status == 0) {
			char	*devpath;
			char	slice_path[MAXPATHLEN];
			char	*pattern;

			/*
			 * We will come through here once for each of
			 * the raw slice device names.
			 */
			devpath = di_devfs_path(node);
			(void) snprintf(slice_path,
			    sizeof (slice_path), "%s:%s",
			    devpath, di_minor_name(minor));
			di_devfs_path_free((void *) devpath);

			if (libdiskmgt_str_eq(di_minor_nodetype(minor),
			    DDI_NT_FD)) {
				pattern = DEVLINK_FLOPPY_REGEX;
			} else {
				pattern = DEVLINK_REGEX;
			}

			/* Walk the /dev tree to get the devlinks. */
			(void) di_devlink_walk(args->handle, pattern,
			    slice_path, DI_PRIMARY_LINK, arg, add_devpath);
		}

		if (args->dev_walk_status != 0) {
			result = DI_WALK_TERMINATE;
		}
	}

	return (result);
}