/* * 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); }
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); }
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); }
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); }
/* * 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); }
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); }