/* * Returns 'in use' details, if found, about a specific dev_name, * based on the caller(who). It is important to note that it is possible * for there to be more than one 'in use' statistic regarding a dev_name. * The **msg parameter returns a list of 'in use' details. This message * is formatted via gettext(). */ int dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp) { nvlist_t *dev_stats = NULL; char *by, *data; nvpair_t *nvwhat = NULL; nvpair_t *nvdesc = NULL; int found = 0; int err; char *dname = NULL; *errp = 0; *msg = NULL; /* * If the user doesn't want to do in use checking, return. */ if (NOINUSE_SET) return (0); dname = getfullblkname(dev_name); /* * If we cannot find the block name, we cannot check the device * for in use statistics. So, return found, which is == 0. */ if (dname == NULL || *dname == '\0') { return (found); } /* * Slice stats for swap devices are only returned if mounted * (e.g. /tmp). Other devices or files being used for swap * are ignored, so we add a special check here to use swapctl(2) * to perform in-use checking. */ if (ANY_ZPOOL_USE(who) && (err = dm_inuse_swap(dname, errp))) { /* on error, dm_inuse_swap sets errp */ if (err < 0) { free(dname); return (err); } /* simulate a mounted swap device */ (void) build_usage_string(dname, DM_USE_MOUNT, "swap", msg, &found, errp); /* if this fails, dm_get_usage_string changed */ ASSERT(found == 1); free(dname); return (found); } dm_get_slice_stats(dname, &dev_stats, errp); if (dev_stats == NULL) { /* * If there is an error, but it isn't a no device found error * return the error as recorded. Otherwise, with a full * block name, we might not be able to get the slice * associated, and will get an ENODEV error. For example, * an SVM metadevice will return a value from getfullblkname() * but libdiskmgt won't be able to find this device for * statistics gathering. This is expected and we should not * report errnoneous errors. */ if (*errp) { if (*errp == ENODEV) { *errp = 0; } } free(dname); return (found); } for (;;) { nvwhat = nvlist_next_nvpair(dev_stats, nvdesc); nvdesc = nvlist_next_nvpair(dev_stats, nvwhat); /* * End of the list found. */ if (nvwhat == NULL || nvdesc == NULL) { break; } /* * Otherwise, we check to see if this client(who) cares * about this in use scenario */ ASSERT(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0); ASSERT(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0); /* * If we error getting the string value continue on * to the next pair(if there is one) */ if (nvpair_value_string(nvwhat, &by)) { continue; } if (nvpair_value_string(nvdesc, &data)) { continue; } switch (who) { case DM_WHO_MKFS: /* * mkfs is not in use for these cases. * All others are in use. */ if (strcmp(by, DM_USE_LU) == 0 || strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { break; } if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) { goto out; } } break; case DM_WHO_SWAP: /* * Not in use for this. */ if (strcmp(by, DM_USE_DUMP) == 0 || strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { break; } if (strcmp(by, DM_USE_LU) == 0 && strcmp(data, "-") == 0) { break; } if (strcmp(by, DM_USE_VFSTAB) == 0 && strcmp(data, "") == 0) { break; } if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) { goto out; } } break; case DM_WHO_DUMP: /* * Not in use for this. */ if ((strcmp(by, DM_USE_MOUNT) == 0 && strcmp(data, "swap") == 0) || strcmp(by, DM_USE_DUMP) == 0 || strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { break; } if (build_usage_string(dname, by, data, msg, &found, errp)) { if (*errp) { goto out; } } break; case DM_WHO_FORMAT: if (strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) break; if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) { goto out; } } break; case DM_WHO_ZPOOL_FORCE: if (strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) break; /* FALLTHROUGH */ case DM_WHO_ZPOOL: if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) goto out; } break; case DM_WHO_ZPOOL_SPARE: if (strcmp(by, DM_USE_SPARE_ZPOOL) != 0) { if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) goto out; } } break; default: /* * nothing found in use for this client * of libdiskmgt. Default is 'not in use'. */ break; } } out: if (dname != NULL) free(dname); if (dev_stats != NULL) nvlist_free(dev_stats); return (found); }
/* * Returns 'in use' details, if found, about a specific dev_name, * based on the caller(who). It is important to note that it is possible * for there to be more than one 'in use' statistic regarding a dev_name. * The **msg parameter returns a list of 'in use' details. This message * is formatted via gettext(). */ int dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp) { nvlist_t *dev_stats = NULL; char *by, *data; nvpair_t *nvwhat = NULL; nvpair_t *nvdesc = NULL; int found = 0; *errp = 0; *msg = NULL; /* * If the user doesn't want to do in use checking, return. */ if (NOINUSE_SET) return (0); dm_get_slice_stats(dev_name, &dev_stats, errp); if (dev_stats == NULL) { /* * If there is an error, but it isn't a no device found error * return the error as recorded. Otherwise, with a full * block name, we might not be able to get the slice * associated, and will get an ENODEV error. For example, * an SVM metadevice will return a value from getfullblkname() * but libdiskmgt won't be able to find this device for * statistics gathering. This is expected and we should not * report errnoneous errors. */ if (*errp) { if (*errp == ENODEV) { *errp = 0; } } // free(dname); return (found); } for (;;) { nvwhat = nvlist_next_nvpair(dev_stats, nvdesc); nvdesc = nvlist_next_nvpair(dev_stats, nvwhat); /* * End of the list found. */ if (nvwhat == NULL || nvdesc == NULL) { break; } /* * Otherwise, we check to see if this client(who) cares * about this in use scenario */ ASSERT(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0); ASSERT(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0); /* * If we error getting the string value continue on * to the next pair(if there is one) */ if (nvpair_value_string(nvwhat, &by)) { continue; } if (nvpair_value_string(nvdesc, &data)) { continue; } switch (who) { case DM_WHO_ZPOOL_FORCE: if (strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0 || strcmp(by, DM_USE_OS_PARTITION) == 0) break; /* FALLTHROUGH */ case DM_WHO_ZPOOL: if (build_usage_string(dev_name, by, data, msg, &found, errp) != 0) { if (*errp) goto out; } break; case DM_WHO_ZPOOL_SPARE: if (strcmp(by, DM_USE_SPARE_ZPOOL) != 0) { if (build_usage_string(dev_name, by, data, msg, &found, errp) != 0) { if (*errp) goto out; } } break; default: /* * nothing found in use for this client * of libdiskmgt. Default is 'not in use'. */ break; } } out: nvlist_free(dev_stats); return (found); }