/* * Handle a EC_DEV_ADD.ESC_DISK event. * * illumos * Expects: DEV_PHYS_PATH string in schema * Matches: vdev's ZPOOL_CONFIG_PHYS_PATH or ZPOOL_CONFIG_DEVID * * path: '/dev/dsk/c0t1d0s0' (persistent) * devid: 'id1,sd@SATA_____Hitachi_HDS72101______JP2940HZ3H74MC/a' * phys_path: '/pci@0,0/pci103c,1609@11/disk@1,0:a' * * linux * provides: DEV_PHYS_PATH and DEV_IDENTIFIER strings in schema * Matches: vdev's ZPOOL_CONFIG_PHYS_PATH or ZPOOL_CONFIG_DEVID * * path: '/dev/sdc1' (not persistent) * devid: 'ata-SAMSUNG_HD204UI_S2HGJD2Z805891-part1' * phys_path: 'pci-0000:04:00.0-sas-0x4433221106000000-lun-0' */ static int zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi) { char *devpath = NULL, *devid; boolean_t is_slice; /* * Expecting a devid string and an optional physical location */ if (nvlist_lookup_string(nvl, DEV_IDENTIFIER, &devid) != 0) return (-1); (void) nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devpath); is_slice = (nvlist_lookup_boolean(nvl, DEV_IS_PART) == 0); zed_log_msg(LOG_INFO, "zfs_deliver_add: adding %s (%s) (is_slice %d)", devid, devpath ? devpath : "NULL", is_slice); /* * Iterate over all vdevs looking for a match in the folllowing order: * 1. ZPOOL_CONFIG_DEVID (identifies the unique disk) * 2. ZPOOL_CONFIG_PHYS_PATH (identifies disk physical location). * * For disks, we only want to pay attention to vdevs marked as whole * disks or are a multipath device. */ if (!devid_iter(devid, zfs_process_add, is_slice) && devpath != NULL) (void) devphys_iter(devpath, devid, zfs_process_add, is_slice); return (0); }
/* * This function is called when we receive a devfs add event. This can be * either a disk event or a lofi event, and the behavior is slightly different * depending on which it is. */ static int zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi) { char *devpath, *devname; char path[PATH_MAX], realpath[PATH_MAX]; char *colon, *raw; int ret; /* * The main unit of operation is the physical device path. For disks, * this is the device node, as all minor nodes are affected. For lofi * devices, this includes the minor path. Unfortunately, this isn't * represented in the DEV_PHYS_PATH for various reasons. */ if (nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devpath) != 0) return (-1); /* * If this is a lofi device, then also get the minor instance name. * Unfortunately, the current payload doesn't include an easy way to get * this information. So we cheat by resolving the 'dev_name' (which * refers to the raw device) and taking the portion between ':(*),raw'. */ (void) strlcpy(realpath, devpath, sizeof (realpath)); if (is_lofi) { if (nvlist_lookup_string(nvl, DEV_NAME, &devname) == 0 && (ret = resolvepath(devname, path, sizeof (path))) > 0) { path[ret] = '\0'; colon = strchr(path, ':'); if (colon != NULL) raw = strstr(colon + 1, ",raw"); if (colon != NULL && raw != NULL) { *raw = '\0'; (void) snprintf(realpath, sizeof (realpath), "%s%s", devpath, colon); *raw = ','; } } } /* * Iterate over all vdevs with a matching devid, and then those with a * matching /devices path. For disks, we only want to pay attention to * vdevs marked as whole disks. For lofi, we don't care (because we're * matching an exact minor name). */ if (!devid_iter(realpath, zfs_process_add, !is_lofi)) (void) devpath_iter(realpath, zfs_process_add, !is_lofi); return (0); }