예제 #1
0
int
dev_list_gather(topo_mod_t *mod, topo_list_t *listp)
{
	di_node_t		devtree;
	di_devlink_handle_t	devhdl;
	disk_cbdata_t		dcb;

	if ((devtree = topo_mod_devinfo(mod)) == DI_NODE_NIL) {
		topo_mod_dprintf(mod, "disk_list_gather: "
		    "topo_mod_devinfo() failed");
		return (-1);
	}

	if ((devhdl = di_devlink_init(NULL, 0)) == DI_NODE_NIL) {
		topo_mod_dprintf(mod, "disk_list_gather: "
		    "di_devlink_init() failed");
		return (-1);
	}

	dcb.dcb_mod = mod;
	dcb.dcb_list = listp;
	dcb.dcb_devhdl = devhdl;

	/* walk the devinfo snapshot looking for disk nodes */
	(void) di_walk_node(devtree, DI_WALK_CLDFIRST, &dcb,
	    dev_walk_di_nodes);

	(void) di_devlink_fini(&devhdl);

	return (0);
}
예제 #2
0
/*
 * The functions in this file do a dev tree walk to build up a model of the
 * disks, controllers and paths on the system.  This model is returned in the
 * args->disk_listp and args->controller_listp members of the args param.
 * There is no global data for this file so it is thread safe.  It is up to
 * the caller to merge the resulting model with any existing model that is
 * cached.  The caller must also free the memory for this model when it is
 * no longer needed.
 */
void
findevs(struct search_args *args)
{
	di_node_t		di_root;

	args->bus_listp = NULL;
	args->controller_listp = NULL;
	args->disk_listp = NULL;

	args->dev_walk_status = 0;
	args->handle = di_devlink_init(NULL, 0);

	/*
	 * Have to make several passes at this with the new devfs caching.
	 * First, we find non-mpxio devices. Then we find mpxio/multipath
	 * devices.
	 */
	di_root = di_init("/", DINFOCACHE);
	args->ph = di_prom_init();
	(void) di_walk_minor(di_root, NULL, 0, args, add_devs);
	di_fini(di_root);

	di_root = di_init("/", DINFOCPYALL|DINFOPATH);
	(void) di_walk_minor(di_root, NULL, 0, args, add_devs);
	di_fini(di_root);

	(void) di_devlink_fini(&(args->handle));

	clean_paths(args);
}
예제 #3
0
int
sunos_get_device_list(struct libusb_context * ctx,
	struct discovered_devs **discdevs)
{
	di_node_t root_node;
	struct node_args args;
	di_devlink_handle_t devlink_hdl;

	args.ctx = ctx;
	args.discdevs = discdevs;
	args.last_ugenpath = NULL;
	if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
		usbi_dbg("di_int() failed: %s", strerror(errno));
		return (LIBUSB_ERROR_IO);
	}

	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
		di_fini(root_node);
		usbi_dbg("di_devlink_init() failed: %s", strerror(errno));

		return (LIBUSB_ERROR_IO);
	}
	args.dlink_hdl = devlink_hdl;

	/* walk each node to find USB devices */
	if (di_walk_node(root_node, DI_WALK_SIBFIRST, &args,
	    sunos_walk_minor_node_link) == -1) {
		usbi_dbg("di_walk_node() failed: %s", strerror(errno));
		di_fini(root_node);

		return (LIBUSB_ERROR_IO);
	}

	di_fini(root_node);
	di_devlink_fini(&devlink_hdl);

	usbi_dbg("%d devices", (*discdevs)->len);

	return ((*discdevs)->len);
}
char
*getDeviceFileName(MP_UINT64 objectSequenceNumber)
{
	char *deviceFileName = NULL;

	di_node_t root_node = DI_NODE_NIL;
	di_node_t cur_node  = DI_NODE_NIL;

	int instNum;
	int majorNum;
	MP_UINT64 osn;

	char *pathName  = NULL;
	char *minorName = "c,raw";
	char *devLink   = NULL;

	char fullName[512];

	walk_devlink_t warg;
	di_devlink_handle_t dlHandle = NULL;

	int diStatus = 0;


	log(LOG_INFO, "getDeviceFileName()", " - enter");

	log(LOG_INFO, "getDeviceFileName()",
	    " - objectSequenceNumber: %llx",
	    objectSequenceNumber);

	root_node = di_init("/", DINFOCACHE);
	if (DI_NODE_NIL == root_node) {
		log(LOG_INFO, "MP_GetMultipathLusPlugin()",
		    " - $ERROR, di_init() failed");

		return (NULL);
	}


	cur_node = di_drv_first_node("scsi_vhci", root_node);
	if (DI_NODE_NIL == cur_node) {
		log(LOG_INFO, "getDeviceFileName()",
		    " - $ERROR, di_drv_first_node() failed");

		di_fini(root_node);

		return (NULL);
	}


	cur_node = di_child_node(cur_node);

	while (DI_NODE_NIL != cur_node) {

		instNum = di_instance(cur_node);
		majorNum = di_driver_major(cur_node);

		osn = 0;
		osn = MP_STORE_INST_TO_ID(instNum, osn);
		osn = MP_STORE_MAJOR_TO_ID(majorNum, osn);

		if (osn == objectSequenceNumber) {

			log(LOG_INFO, "getDeviceFileName()",
			    " - found node.");

			break;
		}

		cur_node = di_sibling_node(cur_node);
	}

	if (DI_NODE_NIL != cur_node) {

		dlHandle = di_devlink_init(NULL, 0);
		if (NULL == dlHandle) {
			log(LOG_INFO, "getDeviceFileName()",
			    " - $ERROR, di_devlink_init() failed.");

			di_fini(root_node);

			return (NULL);
		}

		pathName = di_devfs_path(cur_node);

		(void) snprintf(fullName, 511, "%s:%s", pathName, minorName);

		log(LOG_INFO, "getDeviceFileName()",
		    " - fullName: {%s]", fullName);

		(void) memset(&warg, 0, sizeof (walk_devlink_t));

		devLink  = NULL;
		warg.linkpp = &devLink;

		diStatus = di_devlink_walk(dlHandle,
		    NULL,
		    fullName,
		    DI_PRIMARY_LINK,
		    (void *)&warg,
		    get_devlink);

		if (diStatus != 0) {

			log(LOG_INFO, "getDeviceFileName()",
			    "diStatus: %d", diStatus);

			if (diStatus < 0) {
				diStatus = errno;
			}

			log(LOG_INFO, "getDeviceFileName()",
			    "diStatus: %d", diStatus);

			log(LOG_INFO, "getDeviceFileName()",
			    "strerror(diStatus): %s", strerror(diStatus));
		}

		if (NULL != devLink) {

			deviceFileName =
			    (char *)calloc(1, strlen(devLink) + 1);

			(void) strncpy(deviceFileName, devLink,
			    strlen(devLink));

		} else {

			log(LOG_INFO, "getDeviceFileName()",
			    " - $ERROR, devLink is NULL.");

			deviceFileName =
			    (char *)calloc(1, 256);

			(void) strncpy(deviceFileName, pathName, 255);
		}

		di_devfs_path_free(pathName);

		(void) di_devlink_fini(&dlHandle);

	}


	di_fini(root_node);

	free(devLink);

	log(LOG_INFO, "getDeviceFileName()", " - exit");

	return (deviceFileName);
}
예제 #5
0
static int
init_zfd_devs(zlog_t *zlogp, zlog_mode_t mode)
{
	devctl_hdl_t bus_hdl = NULL;
	di_devlink_handle_t dl = NULL;
	int rv = -1;
	int ndevs;
	int reqdevs;
	int i;

	/*
	 * Three zfd devices are required for log mode.
	 * Interactive mode needs only one.
	 */
	reqdevs = (mode != ZLOG_INTERACTIVE) ? 3 : 1;

	/*
	 * Don't re-setup zone fd devs if they already exist; just
	 * skip ahead to making devlinks, which we do for sanity's sake.
	 */
	ndevs = count_zfd_devs(zlogp);

	if (ndevs == reqdevs)
		goto devlinks;

	if (ndevs > 0 || ndevs == -1) {
		if (destroy_zfd_devs(zlogp) == -1)
			goto error;
	}

	/*
	 * Time to make the devices.
	 */
	if ((bus_hdl = devctl_bus_acquire(ZFDNEX_FILEPATH, 0)) == NULL) {
		zerror(zlogp, B_TRUE, "devctl_bus_acquire failed");
		goto error;
	}

	for (i = 0; i < reqdevs; i++) {
		if (init_zfd_dev(zlogp, bus_hdl, i) != 0)
			goto error;
	}

devlinks:
	if ((dl = di_devlink_init("zfd", DI_MAKE_LINK)) == NULL) {
		zerror(zlogp, B_TRUE, "failed to create devlinks");
		goto error;
	}

	(void) di_devlink_fini(&dl);
	rv = 0;

	if (mode == ZLOG_INTERACTIVE) {
		/* We want to look like a tty. */
		make_tty(zlogp, 0);
	}

error:
	if (bus_hdl)
		devctl_release(bus_hdl);
	return (rv);
}
예제 #6
0
static char *
find_link(di_node_t cnode)
{
	di_minor_t devminor = DI_MINOR_NIL;
	di_devlink_handle_t	hdl;
	char *devfspath = NULL;
	char *minorpath = NULL;
	char *linkname = NULL;
	char *cbresult = NULL;

	devfspath = di_devfs_path(cnode);
	if (cnode == DI_NODE_NIL) {
		logmsg(MSG_ERROR,
		    gettext("find_ctrl must be called with non-null "
		    "di_node_t\n"));
		return (NULL);
	}
	logmsg(MSG_INFO, "find_link: devfspath %s\n", devfspath);

	if (((cbresult = calloc(1, MAXPATHLEN)) == NULL) ||
	    ((minorpath = calloc(1, MAXPATHLEN)) == NULL) ||
	    ((linkname = calloc(1, MAXPATHLEN)) == NULL)) {
		logmsg(MSG_ERROR, "unable to allocate space for dev link\n");
		return (NULL);
	}

	devminor = di_minor_next(cnode, devminor);
	hdl = di_devlink_init(di_devfs_minor_path(devminor), DI_MAKE_LINK);
	if (hdl == NULL) {
		logmsg((readonlyroot ? MSG_INFO : MSG_ERROR),
		    gettext("unable to take devlink snapshot: %s\n"),
		    strerror(errno));
		return (NULL);
	}

	linkname = "^dsk/";
	(void) snprintf(minorpath, MAXPATHLEN, "%s:c", devfspath);

	errno = 0;
	if (di_devlink_walk(hdl, linkname, minorpath, DI_PRIMARY_LINK,
	    (void *)cbresult, link_cb) < 0) {
		logmsg(MSG_ERROR,
		    gettext("Unable to walk devlink snapshot for %s: %s\n"),
		    minorpath, strerror(errno));
		return (NULL);
	}

	if (di_devlink_fini(&hdl) < 0) {
		logmsg(MSG_ERROR,
		    gettext("Unable to close devlink snapshot: %s\n"),
		    strerror(errno));
	}
	if (strstr(cbresult, "dsk/") == NULL)
		return (devfspath);

	bzero(minorpath, MAXPATHLEN);
	/* strip off the trailing "s2" */
	bcopy(cbresult, minorpath, strlen(cbresult) - 1);
	/* Now strip off the /dev/dsk/ prefix for output flexibility */
	linkname = strrchr(minorpath, '/');
	return (++linkname);
}
예제 #7
0
/*
 * init_console_dev() drives the device-tree configuration of the zone
 * console device.  The general strategy is to use the libdevice (devctl)
 * interfaces to instantiate a new zone console node.  We do a lot of
 * sanity checking, and are careful to reuse a console if one exists.
 *
 * Once the device is in the device tree, we kick devfsadm via di_devlink_init()
 * to ensure that the appropriate symlinks (to the master and slave console
 * devices) are placed in /dev in the global zone.
 */
static int
init_console_dev(zlog_t *zlogp)
{
	char conspath[MAXPATHLEN];
	devctl_hdl_t bus_hdl = NULL;
	devctl_hdl_t dev_hdl = NULL;
	devctl_ddef_t ddef_hdl = NULL;
	di_devlink_handle_t dl = NULL;
	int rv = -1;
	int ndevs;
	int masterfd;
	int slavefd;
	int i;

	/*
	 * Don't re-setup console if it is working and ready already; just
	 * skip ahead to making devlinks, which we do for sanity's sake.
	 */
	ndevs = count_console_devs(zlogp);
	if (ndevs == 1) {
		goto devlinks;
	} else if (ndevs > 1 || ndevs == -1) {
		/*
		 * For now, this seems like a reasonable but harsh punishment.
		 * If needed, we could try to get clever and delete all but
		 * the console which is pointed at by the current symlink.
		 */
		if (destroy_console_devs(zlogp) == -1) {
			goto error;
		}
	}

	/*
	 * Time to make the consoles!
	 */
	if ((bus_hdl = devctl_bus_acquire(ZCONSNEX_FILEPATH, 0)) == NULL) {
		zerror(zlogp, B_TRUE, "%s failed", "devctl_bus_acquire");
		goto error;
	}
	if ((ddef_hdl = devctl_ddef_alloc("zcons", 0)) == NULL) {
		zerror(zlogp, B_TRUE, "failed to allocate ddef handle");
		goto error;
	}
	/*
	 * Set three properties on this node; the first is the name of the
	 * zone; the second is a flag which lets pseudo know that it is
	 * OK to automatically allocate an instance # for this device;
	 * the third tells the device framework not to auto-detach this
	 * node-- we need the node to still be there when we ask devfsadmd
	 * to make links, and when we need to open it.
	 */
	if (devctl_ddef_string(ddef_hdl, "zonename", zone_name) == -1) {
		zerror(zlogp, B_TRUE, "failed to create zonename property");
		goto error;
	}
	if (devctl_ddef_int(ddef_hdl, "auto-assign-instance", 1) == -1) {
		zerror(zlogp, B_TRUE, "failed to create auto-assign-instance "
		    "property");
		goto error;
	}
	if (devctl_ddef_int(ddef_hdl, "ddi-no-autodetach", 1) == -1) {
		zerror(zlogp, B_TRUE, "failed to create ddi-no-auto-detach "
		    "property");
		goto error;
	}
	if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) {
		zerror(zlogp, B_TRUE, "failed to create console node");
		goto error;
	}

devlinks:
	if ((dl = di_devlink_init("zcons", DI_MAKE_LINK)) != NULL) {
		(void) di_devlink_fini(&dl);
	} else {
		zerror(zlogp, B_TRUE, "failed to create devlinks");
		goto error;
	}

	/*
	 * Open the master side of the console and issue the ZC_HOLDSLAVE ioctl,
	 * which will cause the master to retain a reference to the slave.
	 * This prevents ttymon from blowing through the slave's STREAMS anchor.
	 *
	 * In very rare cases the open returns ENOENT if devfs doesn't have
	 * everything setup yet due to heavy zone startup load. Wait for
	 * 1 sec. and retry a few times. Even if we can't setup the zone's
	 * console, we still go ahead and boot the zone.
	 */
	(void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
	    zone_name, ZCONS_MASTER_NAME);
	for (i = 0; i < ZCONS_RETRY; i++) {
		masterfd = open(conspath, O_RDWR | O_NOCTTY);
		if (masterfd >= 0 || errno != ENOENT)
			break;
		(void) sleep(1);
	}
	if (masterfd == -1) {
		zerror(zlogp, B_TRUE, "ERROR: could not open master side of "
		    "zone console for %s to acquire slave handle", zone_name);
		master_zcons_failed = B_TRUE;
	}

	(void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
	    zone_name, ZCONS_SLAVE_NAME);
	for (i = 0; i < ZCONS_RETRY; i++) {
		slavefd = open(conspath, O_RDWR | O_NOCTTY);
		if (slavefd >= 0 || errno != ENOENT)
			break;
		(void) sleep(1);
	}
	if (slavefd == -1)
		zerror(zlogp, B_TRUE, "ERROR: could not open slave side of zone"
		    " console for %s to acquire slave handle", zone_name);

	/*
	 * This ioctl can occasionally return ENXIO if devfs doesn't have
	 * everything plumbed up yet due to heavy zone startup load. Wait for
	 * 1 sec. and retry a few times before we fail to boot the zone.
	 */
	if (masterfd != -1 && slavefd != -1) {
		for (i = 0; i < ZCONS_RETRY; i++) {
			if (ioctl(masterfd, ZC_HOLDSLAVE,
			    (caddr_t)(intptr_t)slavefd) == 0) {
				rv = 0;
				break;
			} else if (errno != ENXIO) {
				break;
			}
			(void) sleep(1);
		}
		if (rv != 0)
			zerror(zlogp, B_TRUE, "ERROR: error while acquiring "
			    "slave handle of zone console for %s", zone_name);
	}

	if (slavefd != -1)
		(void) close(slavefd);
	if (masterfd != -1)
		(void) close(masterfd);

error:
	if (ddef_hdl)
		devctl_ddef_free(ddef_hdl);
	if (bus_hdl)
		devctl_release(bus_hdl);
	if (dev_hdl)
		devctl_release(dev_hdl);
	return (rv);
}
예제 #8
0
/*
 * Convert the specified devid/minor_name into a devid_nmlist_t array
 * with names that resolve into /devices or /dev depending on search_path.
 *
 * The man page indicates that:
 *
 *     This function traverses the file tree, starting at search_path.
 *
 * This is not true, we reverse engineer the paths relative to
 * the specified search path to avoid attaching all devices.
 */
int
devid_deviceid_to_nmlist(
	char		*search_path,
	ddi_devid_t	devid,
	char		*minor_name,
	devid_nmlist_t	**retlist)
{
	char			*cp;
	int			dev;
	char			*paths = NULL;
	char			*path;
	int			lens;
#ifndef __APPLE__
	di_devlink_handle_t	dlh = NULL;
#endif
	int			ret = -1;
#ifndef __APPLE__
	struct devlink_cbinfo	cbi;
#endif
	struct nmlist		*nlh = NULL;
	struct nmlist		*nl;
	devid_nmlist_t		*rl;
	int			nret;
	int			nagain = 0;
	int			err = 0;

	*retlist = NULL;

	/* verify valid search path starts with "/devices" or "/dev" */
	if ((strcmp(search_path, "/devices") == 0) ||
	    (strncmp(search_path, "/devices/", 9) == 0))
		dev = 0;
	else if ((strcmp(search_path, "/dev") == 0) ||
	    (strncmp(search_path, "/dev/", 5) == 0))
		dev = 1;
	else {
		errno = EINVAL;
		return (-1);
	}

#ifndef __APPLE__
	/* translate devid/minor_name to /devices paths */
again:	if (modctl(MODDEVID2PATHS, devid, minor_name, 0, &lens, NULL) != 0)
		goto out;
	if ((paths = (char *)malloc(lens)) == NULL)
		goto out;
	if (modctl(MODDEVID2PATHS, devid, minor_name, 0, &lens, paths) != 0) {
		if ((errno == EAGAIN) && (nagain++ < DEVICEID_NMLIST_NRETRY)) {
			free(paths);
			paths = NULL;
			goto again;
		}
		goto out;
	}

	/*
	 * initialize for /devices path to /dev path translation. To reduce
	 * overhead we reuse the last snapshot if DEVICEID_NMLIST_SLINK is set.
	 */
	if (dev) {
		dlh = devid_deviceid_to_nmlist_dlh;
		if (dlh &&
		    !(devid_deviceid_to_nmlist_flg & DEVICEID_NMLIST_SLINK)) {
			(void) di_devlink_fini(&dlh);
			dlh = devid_deviceid_to_nmlist_dlh = NULL;
		}
		if ((dlh == NULL) &&
		    ((dlh = di_devlink_init(NULL, 0)) == NULL))
				goto out;
	}

	/*
	 * iterate over all the devtspectype resolutions of the devid and
	 * convert them into the appropriate path form and add items to return
	 * to the nmlist list;
	 */
	for (path = paths; *path; path += strlen(path) + 1) {
		if (dev) {
			/* add /dev entries */
			cbi.cbi_nlhp = &nlh;
			cbi.cbi_search_path = search_path;
			cbi.cbi_error = 0;

			(void) di_devlink_walk(dlh, NULL, path,
			    devid_deviceid_to_nmlist_link,
			    (void *)&cbi, devlink_callback);
			if (cbi.cbi_error)
				goto out;
		} else {
			/* add /devices entry */
			cp = malloc(strlen("/devices") + strlen(path) + 1);
			(void) strcpy(cp, "/devices");
			(void) strcat(cp, path);
			if (strncmp(cp, search_path,
			    strlen(search_path)) == 0) {
				if (nmlist_add(&nlh, cp) == NULL) {
					free(cp);
					goto out;
				}
			}
			free(cp);
		}
	}

	/* convert from nmlist to retlist array */
	for (nl = nlh, nret = 0; nl; nl = nl->nl_next)
		nret++;
	if (nret == 0) {
		err = ENODEV;
		goto out;
	}
	if ((*retlist = calloc(nret + 1, sizeof (devid_nmlist_t))) == NULL) {
		err = ENOMEM;
		goto out;
	}
	for (nl = nlh, rl = *retlist; nl; nl = nl->nl_next, rl++) {
		rl->devname = nl->nl_devname;
		rl->dev = nl->nl_dev;
	}
	rl->devname = NULL;
	rl->dev = NODEV;

	ret = 0;

out:
	while ((nl = nlh) != NULL) {	/* free the nmlist */
		nlh = nl->nl_next;
		free(nl);
	}
	if (paths)
		free(paths);
	if (dlh) {
		if ((ret == 0) &&
		    (devid_deviceid_to_nmlist_flg & DEVICEID_NMLIST_SLINK))
			devid_deviceid_to_nmlist_dlh = dlh;
		else
			(void) di_devlink_fini(&dlh);
	}
	if (ret && *retlist)
		free(*retlist);
	if (ret && err != 0)
		errno = err;
#endif
	return (ret);
}