/* * path - path of the dataset * count - return value of the number of snapshots for the dataset */ int smbd_vss_get_count(const char *path, uint32_t *count) { char dataset[MAXPATHLEN]; libzfs_handle_t *libhd; zfs_handle_t *zfshd; smbd_vss_count_t vss_count; bzero(&vss_count, sizeof (smbd_vss_count_t)); *count = 0; if (smb_getdataset(path, dataset, MAXPATHLEN) != 0) return (-1); if ((libhd = libzfs_init()) == NULL) return (-1); if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) { libzfs_fini(libhd); return (-1); } (void) zfs_iter_snapshots(zfshd, smbd_vss_iterate_count, (void *)&vss_count); if (vss_count.vc_count > SMBD_VSS_SNAPSHOT_MAX) vss_count.vc_count = SMBD_VSS_SNAPSHOT_MAX; *count = vss_count.vc_count; zfs_close(zfshd); libzfs_fini(libhd); return (0); }
/* Remove a home directory structure */ int rm_homedir(char *dir, int flags) { struct stat stbuf; char *nm, *rp; rp = realpath(dir, NULL); if (rp && (strcmp(rp, "/") == 0)) { return (0); } if ((stat(dir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) return (0); if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) && (flags & MANAGE_ZFS)) { if (g_zfs == NULL) g_zfs = libzfs_init(); if (g_zfs == NULL) { errmsg(M_OOPS, "libzfs_init failure", strerror(errno)); return (EX_HOMEDIR); } if ((nm = get_mnt_special(dir, stbuf.st_fstype)) != NULL) { zfs_handle_t *zhp; if ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) != NULL) { if ((zfs_unmount(zhp, NULL, 0) == 0) && (zfs_destroy(zhp, B_FALSE) == 0)) { zfs_close(zhp); libzfs_fini(g_zfs); g_zfs = NULL; return (0); } errmsg(M_OOPS, "destroy the home directory", libzfs_error_description(g_zfs)); (void) zfs_mount(zhp, NULL, 0); zfs_close(zhp); libzfs_fini(g_zfs); g_zfs = NULL; return (EX_HOMEDIR); } } } (void) sprintf(cmdbuf, "rm -rf %s", dir); if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (system(cmdbuf)); }
/* * given the path to a zvol, return the cXtYdZ name * returns < 0 on error, 0 if it isn't a zvol, > 1 on success */ static int ztop(char *arg, char *diskname) { zpool_handle_t *zpool_handle; nvlist_t *config, *nvroot; nvlist_t **child; uint_t children; libzfs_handle_t *lzfs; char *vname; char *p; char pool_name[MAXPATHLEN]; if (strncmp(arg, "/dev/zvol/dsk/", 14)) { return (0); } arg += 14; (void) strncpy(pool_name, arg, MAXPATHLEN); if ((p = strchr(pool_name, '/')) != NULL) *p = '\0'; STRCPYLIM(new_cc.cf_fs, p + 1, "statefile path"); if ((lzfs = libzfs_init()) == NULL) { mesg(MERR, "failed to initialize ZFS library\n"); return (-1); } if ((zpool_handle = zpool_open(lzfs, pool_name)) == NULL) { mesg(MERR, "couldn't open pool '%s'\n", pool_name); libzfs_fini(lzfs); return (-1); } config = zpool_get_config(zpool_handle, NULL); if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot) != 0) { zpool_close(zpool_handle); libzfs_fini(lzfs); return (-1); } verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &child, &children) == 0); if (children != 1) { mesg(MERR, "expected one vdev, got %d\n", children); zpool_close(zpool_handle); libzfs_fini(lzfs); return (-1); } vname = zpool_vdev_name(lzfs, zpool_handle, child[0], B_FALSE); if (vname == NULL) { mesg(MERR, "couldn't determine vdev name\n"); zpool_close(zpool_handle); libzfs_fini(lzfs); return (-1); } (void) strcpy(diskname, "/dev/dsk/"); (void) strcat(diskname, vname); free(vname); zpool_close(zpool_handle); libzfs_fini(lzfs); return (1); }
/* * Sets the share properties on a ZFS share. For now, this method sets only * the "sharesmb" property. * * This method includes building a comma seperated name-value string to be * set on the "sharesmb" property of a ZFS share. This name-value string is * build in 2 steps: * - New property values given as name-value pair are set first. * - Existing optionset properties, which are not part of the new properties * passed in step 1, are appended to the newly set properties. */ int sa_zfs_setprop(sa_handle_t handle, char *path, nvlist_t *nvl) { zfs_handle_t *z_fs; libzfs_handle_t *z_lib; char sharesmb_val[MAXPATHLEN]; char *dataset, *lastcomma; if (nvlist_empty(nvl)) return (0); if ((handle == NULL) || (path == NULL)) return (-1); if ((dataset = get_zfs_dataset(handle, path, B_FALSE)) == NULL) return (-1); if ((z_lib = libzfs_init()) == NULL) { free(dataset); return (-1); } z_fs = zfs_open(z_lib, dataset, ZFS_TYPE_DATASET); if (z_fs == NULL) { free(dataset); libzfs_fini(z_lib); return (-1); } bzero(sharesmb_val, MAXPATHLEN); if (sa_zfs_sprintf_new_prop(nvl, sharesmb_val) != 0) { free(dataset); zfs_close(z_fs); libzfs_fini(z_lib); return (-1); } if (sa_zfs_sprintf_existing_prop(z_fs, sharesmb_val) != 0) { free(dataset); zfs_close(z_fs); libzfs_fini(z_lib); return (-1); } lastcomma = strrchr(sharesmb_val, ','); if ((lastcomma != NULL) && (lastcomma[1] == '\0')) *lastcomma = '\0'; (void) zfs_prop_set(z_fs, zfs_prop_to_name(ZFS_PROP_SHARESMB), sharesmb_val); free(dataset); zfs_close(z_fs); libzfs_fini(z_lib); return (0); }
/* * path - path of the dataset for the operation * gmttoken - the @GMT token to be looked up * toktime - time_t used if gmttoken == NULL * snapname - the snapshot name to be returned [MAXPATHLEN] * * Here we are going to get the snapshot name from the @GMT token * The snapname returned by ZFS is : <dataset name>@<snapshot name> * So we are going to make sure there is the @ symbol in * the right place and then just return the snapshot name */ int smbd_vss_map_gmttoken(const char *path, char *gmttoken, time_t toktime, char *snapname) { char dataset[MAXPATHLEN]; libzfs_handle_t *libhd; zfs_handle_t *zfshd; smbd_vss_map_gmttoken_t vss_map_gmttoken; char *zsnap; const char *lsnap; struct tm tm; if (gmttoken != NULL && *gmttoken == '@' && strptime(gmttoken, smbd_vss_gmttoken_fmt, &tm) != NULL) { toktime = timegm(&tm); } vss_map_gmttoken.mg_snaptime = toktime; vss_map_gmttoken.mg_snapname = snapname; *snapname = '\0'; if (smb_getdataset(path, dataset, MAXPATHLEN) != 0) return (-1); if ((libhd = libzfs_init()) == NULL) return (-1); if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) { libzfs_fini(libhd); return (-1); } (void) zfs_iter_snapshots(zfshd, smbd_vss_iterate_map_gmttoken, (void *)&vss_map_gmttoken); /* compare the zfs snapshot name and the local snap name */ zsnap = snapname; lsnap = dataset; while ((*lsnap != '\0') && (*zsnap != '\0') && (*lsnap == *zsnap)) { zsnap++; lsnap++; } /* Now we should be passed the dataset name */ if ((*zsnap == '@') && (*lsnap == '\0')) { zsnap++; (void) strlcpy(snapname, zsnap, MAXPATHLEN); } else { *snapname = '\0'; } zfs_close(zfshd); libzfs_fini(libhd); return (0); }
int sa_zfs_is_shared(sa_handle_t sahandle, char *path) { int ret = 0; char *dataset; zfs_handle_t *handle = NULL; char shareopts[ZFS_MAXPROPLEN]; libzfs_handle_t *libhandle; dataset = get_zfs_dataset((sa_handle_t)sahandle, path, B_FALSE); if (dataset != NULL) { libhandle = libzfs_init(); if (libhandle != NULL) { handle = zfs_open(libhandle, dataset, ZFS_TYPE_FILESYSTEM); if (handle != NULL) { if (zfs_prop_get(handle, ZFS_PROP_SHARENFS, shareopts, sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0 && strcmp(shareopts, "off") != 0) { ret = 1; /* it is shared */ } zfs_close(handle); } libzfs_fini(libhandle); } free(dataset); } return (ret); }
int main(int argc, char **argv) { extern void zfs_prop_init(void); char *path[MAX_NUM_PATHS]; const char *subcommand; int rv = 0; char c; g_importargs.path = path; dprintf_setup(&argc, argv); zfs_prop_init(); while ((c = getopt(argc, argv, "c:d:")) != -1) { switch (c) { case 'c': g_importargs.cachefile = optarg; break; case 'd': assert(g_importargs.paths < MAX_NUM_PATHS); g_importargs.path[g_importargs.paths++] = optarg; break; default: usage(); break; } } argc -= optind; argv += optind; optind = 1; if (argc == 0) { (void) fprintf(stderr, "error: no command specified\n"); usage(); } subcommand = argv[0]; if (strcmp(subcommand, "feature") == 0) { rv = zhack_do_feature(argc, argv); } else { (void) fprintf(stderr, "error: unknown subcommand: %s\n", subcommand); usage(); } if (!g_readonly && spa_export(g_pool, NULL, B_TRUE, B_FALSE) != 0) { fatal(NULL, FTAG, "pool export failed; " "changes may not be committed to disk\n"); } libzfs_fini(g_zfs); kernel_fini(); return (rv); }
/* * This method computes ACL on share path from a share name. * Return 0 upon success, -1 upon failure. */ static int srvsvc_shareacl_getpath(smb_share_t *si, char *shr_acl_path) { char dataset[MAXPATHLEN]; char mp[ZFS_MAXPROPLEN]; libzfs_handle_t *libhd; zfs_handle_t *zfshd; int ret = 0; ret = smb_getdataset(si->shr_path, dataset, MAXPATHLEN); if (ret != 0) return (ret); if ((libhd = libzfs_init()) == NULL) return (-1); if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) { libzfs_fini(libhd); return (-1); } if (zfs_prop_get(zfshd, ZFS_PROP_MOUNTPOINT, mp, sizeof (mp), NULL, NULL, 0, B_FALSE) != 0) { zfs_close(zfshd); libzfs_fini(libhd); return (-1); } zfs_close(zfshd); libzfs_fini(libhd); (void) snprintf(shr_acl_path, MAXPATHLEN, "%s/.zfs/shares/%s", mp, si->shr_name); return (ret); }
static char * get_zfs_property(char *dataset, zfs_prop_t property) { zfs_handle_t *handle = NULL; char shareopts[ZFS_MAXPROPLEN]; libzfs_handle_t *libhandle; libhandle = libzfs_init(); if (libhandle != NULL) { handle = zfs_open(libhandle, dataset, ZFS_TYPE_FILESYSTEM); if (handle != NULL) { if (zfs_prop_get(handle, property, shareopts, sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0) { zfs_close(handle); libzfs_fini(libhandle); return (strdup(shareopts)); } zfs_close(handle); } libzfs_fini(libhandle); } return (NULL); }
void sa_fini(sa_handle_t handle) { sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle; sa_share_impl_t impl_share, next; sa_share_impl_t *pcurr; if (impl_handle == NULL) return; /* * clean up shares which don't have a non-NULL dataset property, * which means they're in sharetab but we couldn't find their * ZFS dataset. */ pcurr = &(impl_handle->shares); impl_share = *pcurr; while (impl_share != NULL) { next = impl_share->next; if (impl_share->dataset == NULL) { /* remove item from the linked list */ *pcurr = next; sa_disable_share(impl_share, NULL); free_share(impl_share); } else { pcurr = &(impl_share->next); } impl_share = next; } update_sharetab(impl_handle); if (impl_handle->zfs_libhandle != NULL) libzfs_fini(impl_handle->zfs_libhandle); impl_share = impl_handle->shares; while (impl_share != NULL) { next = impl_share->next; free_share(impl_share); impl_share = next; } free(impl_handle); }
void zfs_fini(void) { if (g_zfs) { libzfs_fini(g_zfs); g_zfs = NULL; } if (handle_nvpair) { dlclose(handle_nvpair); handle_nvpair = NULL; } if (handle_libzfs) { dlclose(handle_libzfs); handle_libzfs = NULL; } osd_zfs_setup = 0; }
/* * Just checking the existance of the given target. Here we check whether * both zfs and iscsitarget aware of the given target/volume. It neither * care about the credentials nor SHAREISCSI properties. */ static char * validate_zfs_iscsitgt(tgt_node_t *x) { char *msg = NULL; char *prop = NULL; char *dataset = NULL; libzfs_handle_t *zh = NULL; zfs_handle_t *zfsh = NULL; tgt_node_t *n = NULL; if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } if (((zh = libzfs_init()) == NULL) || ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_DATASET)) == NULL)) { xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); goto error; } while ((n = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, n)) != NULL) { if (strcmp(n->x_value, dataset) == 0) break; } if (n == NULL) { xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); goto error; } xml_rtn_msg(&msg, ERR_SUCCESS); error: if (zfsh) zfs_close(zfsh); if (prop) free(prop); if (zh) libzfs_fini(zh); if (dataset) free(dataset); return (msg); }
/* * Close the libzfs interface. */ void zed_event_fini(struct zed_conf *zcp) { if (!zcp) zed_log_die("Failed zed_event_fini: %s", strerror(EINVAL)); if (zcp->zevent_fd >= 0) { if (close(zcp->zevent_fd) < 0) zed_log_msg(LOG_WARNING, "Failed to close \"%s\": %s", ZFS_DEV, strerror(errno)); zcp->zevent_fd = -1; } if (zcp->zfs_hdl) { libzfs_fini(zcp->zfs_hdl); zcp->zfs_hdl = NULL; } }
/* * Collects zpool stats of the pool configured in the configData var. * It opens a handler to the pool, load a tree of vdevs and then the * stats of the root vdev. These stats are temporarily saved and then * inserted in the SQL database. */ int collectZpoolStats() { // Open a handle to the zfs filesystems libzfs_handle_t *g_zfs = libzfs_init(); // Open a handle to the defined zpool zpool_handle_t *zhp; zhp = zpool_open_canfail(g_zfs, configData.poolname->value); // Declarations and such... nvlist_t *configuration, *vdevroot; vdev_stat_t *vdevstats; iostatcollection statisticscollection; int nelem; configuration = zpool_get_config(zhp, NULL); // Now we have the config, we can release the handle to the zpool libzfs_fini(g_zfs); free(zhp); // Put the vdev tree belonging to the pool in newconfig in newnvroot. verify(nvlist_lookup_nvlist(configuration, ZPOOL_CONFIG_VDEV_TREE, &vdevroot) == 0); // Load the new vdev stats in newvdevstat verify(nvlist_lookup_uint64_array(vdevroot, ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vdevstats, &nelem) == 0); // Place the collected statistics in the collection statisticscollection.readops = vdevstats->vs_ops[ZIO_TYPE_READ]; statisticscollection.writeops = vdevstats->vs_ops[ZIO_TYPE_WRITE]; statisticscollection.readbytes = vdevstats->vs_bytes[ZIO_TYPE_READ]; statisticscollection.writebytes = vdevstats->vs_bytes[ZIO_TYPE_WRITE]; statisticscollection.checksum_errors = vdevstats->vs_checksum_errors; statisticscollection.state = vdevstats->vs_state; statisticscollection.space_alloc = vdevstats->vs_alloc; statisticscollection.space = vdevstats->vs_space; // Create the query and post it to MySQL char queryString[1024]; snprintf(queryString, 1024, "INSERT INTO io_stats (date, %s, %s, %s, %s, %s, %s, %s, %s) VALUES (NOW(), '%llu', '%llu', '%llu', '%llu', '%llu', '%llu', '%llu', '%llu')", "iop_read", "iop_write", "bandwidth_read", "bandwidth_write", "space", "space_alloc", "checksum_errors", "state", statisticscollection.readops, statisticscollection.writeops, statisticscollection.readbytes, statisticscollection.writebytes, statisticscollection.space, statisticscollection.space_alloc, statisticscollection.checksum_errors, statisticscollection.state); if (executeQuery(queryString)) return 1; return 0; }
void sa_zfs_fini(sa_handle_impl_t impl_handle) { if (impl_handle->zfs_libhandle != NULL) { if (impl_handle->zfs_list != NULL) { zfs_handle_t **zhp = impl_handle->zfs_list; size_t i; /* * Contents of zfs_list need to be freed so we * don't lose ZFS handles. */ for (i = 0; i < impl_handle->zfs_list_count; i++) { zfs_close(zhp[i]); } free(impl_handle->zfs_list); impl_handle->zfs_list = NULL; impl_handle->zfs_list_count = 0; } libzfs_fini(impl_handle->zfs_libhandle); impl_handle->zfs_libhandle = NULL; } }
int main(int argc, char **argv) { int c; char *range = NULL; char *cancel = NULL; char *end; char *raw = NULL; char *device = NULL; int level = 0; int quiet = 0; int error = 0; int domount = 0; int io_type = ZIO_TYPES; int action = VDEV_STATE_UNKNOWN; err_type_t type = TYPE_INVAL; err_type_t label = TYPE_INVAL; zinject_record_t record = { 0 }; char pool[MAXNAMELEN]; char dataset[MAXNAMELEN]; zfs_handle_t *zhp = NULL; int nowrites = 0; int dur_txg = 0; int dur_secs = 0; int ret; int flags = 0; if ((g_zfs = libzfs_init()) == NULL) return (1); libzfs_print_on_error(g_zfs, B_TRUE); if ((zfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { (void) fprintf(stderr, "failed to open ZFS device\n"); return (1); } if (argc == 1) { /* * No arguments. Print the available handlers. If there are no * available handlers, direct the user to '-h' for help * information. */ if (print_all_handlers() == 0) { (void) printf("No handlers registered.\n"); (void) printf("Run 'zinject -h' for usage " "information.\n"); } return (0); } while ((c = getopt(argc, argv, ":aA:b:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) { switch (c) { case 'a': flags |= ZINJECT_FLUSH_ARC; break; case 'A': if (strcasecmp(optarg, "degrade") == 0) { action = VDEV_STATE_DEGRADED; } else if (strcasecmp(optarg, "fault") == 0) { action = VDEV_STATE_FAULTED; } else { (void) fprintf(stderr, "invalid action '%s': " "must be 'degrade' or 'fault'\n", optarg); usage(); return (1); } break; case 'b': raw = optarg; break; case 'c': cancel = optarg; break; case 'd': device = optarg; break; case 'D': errno = 0; record.zi_timer = strtoull(optarg, &end, 10); if (errno != 0 || *end != '\0') { (void) fprintf(stderr, "invalid i/o delay " "value: '%s'\n", optarg); usage(); return (1); } break; case 'e': if (strcasecmp(optarg, "io") == 0) { error = EIO; } else if (strcasecmp(optarg, "checksum") == 0) { error = ECKSUM; } else if (strcasecmp(optarg, "nxio") == 0) { error = ENXIO; } else if (strcasecmp(optarg, "dtl") == 0) { error = ECHILD; } else { (void) fprintf(stderr, "invalid error type " "'%s': must be 'io', 'checksum' or " "'nxio'\n", optarg); usage(); return (1); } break; case 'f': record.zi_freq = atoi(optarg); if (record.zi_freq < 1 || record.zi_freq > 100) { (void) fprintf(stderr, "frequency range must " "be in the range (0, 100]\n"); return (1); } break; case 'F': record.zi_failfast = B_TRUE; break; case 'g': dur_txg = 1; record.zi_duration = (int)strtol(optarg, &end, 10); if (record.zi_duration <= 0 || *end != '\0') { (void) fprintf(stderr, "invalid duration '%s': " "must be a positive integer\n", optarg); usage(); return (1); } /* store duration of txgs as its negative */ record.zi_duration *= -1; break; case 'h': usage(); return (0); case 'I': /* default duration, if one hasn't yet been defined */ nowrites = 1; if (dur_secs == 0 && dur_txg == 0) record.zi_duration = 30; break; case 'l': level = (int)strtol(optarg, &end, 10); if (*end != '\0') { (void) fprintf(stderr, "invalid level '%s': " "must be an integer\n", optarg); usage(); return (1); } break; case 'm': domount = 1; break; case 'p': (void) strlcpy(record.zi_func, optarg, sizeof (record.zi_func)); record.zi_cmd = ZINJECT_PANIC; break; case 'q': quiet = 1; break; case 'r': range = optarg; break; case 's': dur_secs = 1; record.zi_duration = (int)strtol(optarg, &end, 10); if (record.zi_duration <= 0 || *end != '\0') { (void) fprintf(stderr, "invalid duration '%s': " "must be a positive integer\n", optarg); usage(); return (1); } break; case 'T': if (strcasecmp(optarg, "read") == 0) { io_type = ZIO_TYPE_READ; } else if (strcasecmp(optarg, "write") == 0) { io_type = ZIO_TYPE_WRITE; } else if (strcasecmp(optarg, "free") == 0) { io_type = ZIO_TYPE_FREE; } else if (strcasecmp(optarg, "claim") == 0) { io_type = ZIO_TYPE_CLAIM; } else if (strcasecmp(optarg, "all") == 0) { io_type = ZIO_TYPES; } else { (void) fprintf(stderr, "invalid I/O type " "'%s': must be 'read', 'write', 'free', " "'claim' or 'all'\n", optarg); usage(); return (1); } break; case 't': if ((type = name_to_type(optarg)) == TYPE_INVAL && !MOS_TYPE(type)) { (void) fprintf(stderr, "invalid type '%s'\n", optarg); usage(); return (1); } break; case 'u': flags |= ZINJECT_UNLOAD_SPA; break; case 'L': if ((label = name_to_type(optarg)) == TYPE_INVAL && !LABEL_TYPE(type)) { (void) fprintf(stderr, "invalid label type " "'%s'\n", optarg); usage(); return (1); } break; case ':': (void) fprintf(stderr, "option -%c requires an " "operand\n", optopt); usage(); return (1); case '?': (void) fprintf(stderr, "invalid option '%c'\n", optopt); usage(); return (2); } } argc -= optind; argv += optind; if (record.zi_duration != 0) record.zi_cmd = ZINJECT_IGNORED_WRITES; if (cancel != NULL) { /* * '-c' is invalid with any other options. */ if (raw != NULL || range != NULL || type != TYPE_INVAL || level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED) { (void) fprintf(stderr, "cancel (-c) incompatible with " "any other options\n"); usage(); return (2); } if (argc != 0) { (void) fprintf(stderr, "extraneous argument to '-c'\n"); usage(); return (2); } if (strcmp(cancel, "all") == 0) { return (cancel_all_handlers()); } else { int id = (int)strtol(cancel, &end, 10); if (*end != '\0') { (void) fprintf(stderr, "invalid handle id '%s':" " must be an integer or 'all'\n", cancel); usage(); return (1); } return (cancel_handler(id)); } } if (device != NULL) { /* * Device (-d) injection uses a completely different mechanism * for doing injection, so handle it separately here. */ if (raw != NULL || range != NULL || type != TYPE_INVAL || level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED) { (void) fprintf(stderr, "device (-d) incompatible with " "data error injection\n"); usage(); return (2); } if (argc != 1) { (void) fprintf(stderr, "device (-d) injection requires " "a single pool name\n"); usage(); return (2); } (void) strcpy(pool, argv[0]); dataset[0] = '\0'; if (error == ECKSUM) { (void) fprintf(stderr, "device error type must be " "'io' or 'nxio'\n"); return (1); } record.zi_iotype = io_type; if (translate_device(pool, device, label, &record) != 0) return (1); if (!error) error = ENXIO; if (action != VDEV_STATE_UNKNOWN) return (perform_action(pool, &record, action)); } else if (raw != NULL) { if (range != NULL || type != TYPE_INVAL || level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED) { (void) fprintf(stderr, "raw (-b) format with " "any other options\n"); usage(); return (2); } if (argc != 1) { (void) fprintf(stderr, "raw (-b) format expects a " "single pool name\n"); usage(); return (2); } (void) strcpy(pool, argv[0]); dataset[0] = '\0'; if (error == ENXIO) { (void) fprintf(stderr, "data error type must be " "'checksum' or 'io'\n"); return (1); } record.zi_cmd = ZINJECT_DATA_FAULT; if (translate_raw(raw, &record) != 0) return (1); if (!error) error = EIO; } else if (record.zi_cmd == ZINJECT_PANIC) { if (raw != NULL || range != NULL || type != TYPE_INVAL || level != 0 || device != NULL) { (void) fprintf(stderr, "panic (-p) incompatible with " "other options\n"); usage(); return (2); } if (argc < 1 || argc > 2) { (void) fprintf(stderr, "panic (-p) injection requires " "a single pool name and an optional id\n"); usage(); return (2); } (void) strcpy(pool, argv[0]); if (argv[1] != NULL) record.zi_type = atoi(argv[1]); dataset[0] = '\0'; } else if (record.zi_cmd == ZINJECT_IGNORED_WRITES) { if (nowrites == 0) { (void) fprintf(stderr, "-s or -g meaningless " "without -I (ignore writes)\n"); usage(); return (2); } else if (dur_secs && dur_txg) { (void) fprintf(stderr, "choose a duration either " "in seconds (-s) or a number of txgs (-g) " "but not both\n"); usage(); return (2); } else if (argc != 1) { (void) fprintf(stderr, "ignore writes (-I) " "injection requires a single pool name\n"); usage(); return (2); } (void) strcpy(pool, argv[0]); dataset[0] = '\0'; } else if (type == TYPE_INVAL) { if (flags == 0) { (void) fprintf(stderr, "at least one of '-b', '-d', " "'-t', '-a', '-p', '-I' or '-u' " "must be specified\n"); usage(); return (2); } if (argc == 1 && (flags & ZINJECT_UNLOAD_SPA)) { (void) strcpy(pool, argv[0]); dataset[0] = '\0'; } else if (argc != 0) { (void) fprintf(stderr, "extraneous argument for " "'-f'\n"); usage(); return (2); } flags |= ZINJECT_NULL; } else { if (argc != 1) { (void) fprintf(stderr, "missing object\n"); usage(); return (2); } if (error == ENXIO) { (void) fprintf(stderr, "data error type must be " "'checksum' or 'io'\n"); return (1); } record.zi_cmd = ZINJECT_DATA_FAULT; if (translate_record(type, argv[0], range, level, &record, pool, dataset) != 0) return (1); if (!error) error = EIO; } /* * If this is pool-wide metadata, unmount everything. The ioctl() will * unload the pool, so that we trigger spa-wide reopen of metadata next * time we access the pool. */ if (dataset[0] != '\0' && domount) { if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL) return (1); if (zfs_unmount(zhp, NULL, 0) != 0) return (1); } record.zi_error = error; ret = register_handler(pool, flags, &record, quiet); if (dataset[0] != '\0' && domount) ret = (zfs_mount(zhp, NULL, 0) != 0); libzfs_fini(g_zfs); return (ret); }
void smbd_vss_get_snapshots(const char *path, uint32_t count, uint32_t *return_count, uint32_t *num_gmttokens, char **gmttokenp) { char dataset[MAXPATHLEN]; libzfs_handle_t *libhd; zfs_handle_t *zfshd; smbd_vss_get_uint64_date_t vss_uint64_date; int i; uint64_t *timep; *return_count = 0; *num_gmttokens = 0; if (count == 0) return; if (count > SMBD_VSS_SNAPSHOT_MAX) count = SMBD_VSS_SNAPSHOT_MAX; vss_uint64_date.gd_count = count; vss_uint64_date.gd_return_count = 0; vss_uint64_date.gd_gmt_array = malloc(count * sizeof (uint64_t)); if (vss_uint64_date.gd_gmt_array == NULL) return; if (smb_getdataset(path, dataset, MAXPATHLEN) != 0) { free(vss_uint64_date.gd_gmt_array); return; } if ((libhd = libzfs_init()) == NULL) { free(vss_uint64_date.gd_gmt_array); return; } if ((zfshd = zfs_open(libhd, dataset, ZFS_TYPE_DATASET)) == NULL) { free(vss_uint64_date.gd_gmt_array); libzfs_fini(libhd); return; } (void) zfs_iter_snapshots(zfshd, smbd_vss_iterate_get_uint64_date, (void *)&vss_uint64_date); *num_gmttokens = vss_uint64_date.gd_return_count; *return_count = vss_uint64_date.gd_return_count; /* * Sort the list since neither zfs nor the client sorts it. */ qsort((char *)vss_uint64_date.gd_gmt_array, vss_uint64_date.gd_return_count, sizeof (uint64_t), smbd_vss_cmp_time); timep = vss_uint64_date.gd_gmt_array; for (i = 0; i < vss_uint64_date.gd_return_count; i++) { *gmttokenp = malloc(SMB_VSS_GMT_SIZE); if (*gmttokenp) smbd_vss_time2gmttoken(*timep, *gmttokenp); else vss_uint64_date.gd_return_count = 0; timep++; gmttokenp++; } free(vss_uint64_date.gd_gmt_array); zfs_close(zfshd); libzfs_fini(libhd); }
static int zpool_import_by_guid(uint64_t searchguid) { int err = 0; nvlist_t *pools = NULL; nvpair_t *elem; nvlist_t *config; nvlist_t *found_config = NULL; nvlist_t *policy = NULL; boolean_t first; int flags = ZFS_IMPORT_NORMAL; uint32_t rewind_policy = ZPOOL_NO_REWIND; uint64_t pool_state, txg = -1ULL; importargs_t idata = { 0 }; #ifdef ZFS_AUTOIMPORT_ZPOOL_STATUS_OK_ONLY char *msgid; zpool_status_t reason; zpool_errata_t errata; #endif if ((g_zfs = libzfs_init()) == NULL) return (1); idata.unique = B_TRUE; /* In the future, we can capture further policy and include it here */ if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 || nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) goto error; if (!priv_ineffect(PRIV_SYS_CONFIG)) { printf("cannot discover pools: permission denied\n"); nvlist_free(policy); return (1); } idata.guid = searchguid; pools = zpool_search_import(g_zfs, &idata); if (pools == NULL && idata.exists) { printf("cannot import '%llu': a pool with that guid is already " "created/imported\n", searchguid); err = 1; } else if (pools == NULL) { printf("cannot import '%llu': no such pool available\n", searchguid); err = 1; } if (err == 1) { nvlist_free(policy); return (1); } /* * At this point we have a list of import candidate configs. Even though * we were searching by guid, we still need to post-process the list to * deal with pool state. */ err = 0; elem = NULL; first = B_TRUE; while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { verify(nvpair_value_nvlist(elem, &config) == 0); verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &pool_state) == 0); if (pool_state == POOL_STATE_DESTROYED) continue; verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY, policy) == 0); uint64_t guid; /* * Search for a pool by guid. */ verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) == 0); if (guid == searchguid) found_config = config; } /* * If we were searching for a specific pool, verify that we found a * pool, and then do the import. */ if (err == 0) { if (found_config == NULL) { printf("cannot import '%llu': no such pool available\n", searchguid); err = B_TRUE; } else { #ifdef ZFS_AUTOIMPORT_ZPOOL_STATUS_OK_ONLY reason = zpool_import_status(config, &msgid, &errata); if (reason == ZPOOL_STATUS_OK) err |= do_import(found_config, NULL, NULL, NULL, flags); else err = 1; #else err |= do_import(found_config, NULL, NULL, NULL, flags); #endif } } error: nvlist_free(pools); nvlist_free(policy); libzfs_fini(g_zfs); return (err ? 1 : 0); }
/* * remove_zfs -- unshare a ZVOL from the target */ static char * remove_zfs(tgt_node_t *x, ucred_t *cred) { char *prop; char *msg = NULL; tgt_node_t *targ = NULL; libzfs_handle_t *zh = NULL; const priv_set_t *eset; if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } if ((zh = libzfs_init()) == NULL) { xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); free(prop); return (msg); } eset = ucred_getprivset(cred, PRIV_EFFECTIVE); if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) : ucred_geteuid(cred) != 0) { /* * See if user has ZFS dataset permissions to do operation */ if (zfs_iscsi_perm_check(zh, prop, cred) != 0) { xml_rtn_msg(&msg, ERR_NO_PERMISSION); free(prop); libzfs_fini(zh); return (msg); } } libzfs_fini(zh); while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) != NULL) { if (strcmp(targ->x_value, prop) == 0) break; } free(prop); if (targ == NULL) { /* * We're unsharing a target. If we don't have a reference * then there's no problem. */ xml_rtn_msg(&msg, ERR_SUCCESS); return (msg); } if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &prop) == False) { xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME); return (msg); } tgt_node_remove(targets_config, targ, MatchBoth); /* * Wait until here to issue a logout to any initiators that * might be logged into the target. Certain initiators are * sneaky in that if asked to logout they will, but turn right * around and log back into the target. By waiting until here * to issue the logout we'll have removed reference to the target * such that this can't happen. */ if (isns_enabled() == True) { if (isns_dereg(prop) != 0) syslog(LOG_INFO, "ISNS dereg failed\n"); } logout_targ(prop); free(prop); xml_rtn_msg(&msg, ERR_SUCCESS); return (msg); }
int main(int argc, char *argv[]) { config_t cnf; zstatus_t zstat; if(geteuid() != 0) { // Tell user to run app as root, then exit. fprintf(stderr, "you have to run %s as root\n", argv[0]); exit(1); } cnf.zname[0] = '\0'; zstat.err_message[0] = '\0'; zstat.name = cnf.zname; g_zfs = libzfs_init(); init_config(&cnf); init_devlist(&zstat.d); get_config(argc, argv, &cnf); zpool_iter(g_zfs, zpool_get_stats, (void *)&cnf); zfs_iter_root(g_zfs, zfs_get_stats, (void *)&cnf); zpool_iter(g_zfs, zpool_print_vdev, (void *)&zstat); if (cnf.sw == SW_UNDEF) { fprintf(stderr, "show type is not defined\n"); return 1; } else if (cnf.sw == SW_POOLS) { if (cnf.ft == TP_UNDEF) { fprintf(stderr, "undef format type\n"); return 1; } else if (cnf.ft == TP_TEXT) show_zpools(g_zfs); else if (cnf.ft == TP_JSON) show_zpools_json(g_zfs); return 0; } else if (cnf.sw == SW_DEVSTATE) { find_state_in_devlist(&zstat.d, cnf.vdev); free_devlist(&zstat.d); return 0; } else if (cnf.sw == SW_DEVICES) { if (cnf.ft == TP_UNDEF) { fprintf(stderr, "undef format type\n"); return 1; } else if (cnf.ft == TP_TEXT) print_devlist_text(&zstat.d); else if (cnf.ft == TP_JSON) print_devlist_json(&zstat.d); return 0; } if(cnf.zpool.name == NULL || cnf.zfs.name == NULL) { fprintf(stderr, "could not find zpool: %s\n", cnf.zname); return 1; } if (cnf.sw == SW_ALL) print_stats(&cnf); else if (cnf.sw == SW_READ_OPS) print_stats_read_ops(&cnf); else if (cnf.sw == SW_WRITE_OPS) print_stats_write_ops(&cnf); else if (cnf.sw == SW_READ_BTS) print_stats_read_bts(&cnf); else if (cnf.sw == SW_WRITE_BTS) print_stats_write_bts(&cnf); else if (cnf.sw == SW_HEALTH) print_stats_health_bool(&cnf); else if (cnf.sw == SW_LOGICAL) print_stats_logical(&cnf); else if (cnf.sw == SW_COMPRESS) print_stats_compress(&cnf); else if (cnf.sw == SW_USED) print_stats_used(&cnf); else if (cnf.sw == SW_REAL_USED) print_stats_real_used(&cnf); else if (cnf.sw == SW_AVAILABLE) print_stats_available(&cnf); else if (cnf.sw == SW_DEDUPRATIO)print_stats_dedupratio(&cnf); else if (cnf.sw == SW_DDT) print_stats_ddt_memory(&cnf); else if (cnf.sw == SW_ERR_MESSAGE) print_status_message(&zstat); free_devlist(&zstat.d); libzfs_fini(g_zfs); return 0; }
int main(int argc, char **argv) { struct extmnttab mnt; FILE *fp; fp = fopen("/etc/mnttab", "r"); if(!fp) { perror("fopen"); exit(-1); } while(getextmntent(fp, &mnt, sizeof (struct extmnttab)) == 0) { struct statvfs buf; int i; for(i=0;suppress_fstype[i] != NULL;i++) if(!strcmp(mnt.mnt_fstype, suppress_fstype[i])) break; if (suppress_fstype[i] == NULL && statvfs(mnt.mnt_mountp, &buf) == 0) { if(!strcmp(mnt.mnt_fstype, "zfs")) { uint64_t used, avail; uint64_t *space_used = NULL, *space_avail = NULL; libzfs_handle_t *zfsh = libzfs_init(); zfs_handle_t *handle = zfs_path_to_zhandle(zfsh, (char *)mnt.mnt_mountp, ZFS_TYPE_FILESYSTEM); if(handle) { char source[ZFS_MAXNAMELEN]; zprop_source_t srctype; int rv; #define ZFS_PULL_N_PRINT(prop, name, T, F, expr) do { \ uint64_t datum; \ if(zfs_prop_get_numeric(handle, prop, \ &datum, &srctype, source, sizeof(source)) == 0) { \ printf("zfs`%s`" name "\t" T" \t" F "\n", mnt.mnt_mountp, expr); \ } \ } while(0) uint64_t used = -1, avail = -1; if(zfs_prop_get_numeric(handle, ZFS_PROP_USEDDS, &used, &srctype, source, sizeof(source)) == 0) { printf("zfs`%s`used\tL\t%llu\n", mnt.mnt_mountp, used); } if(zfs_prop_get_numeric(handle, ZFS_PROP_AVAILABLE, &avail, &srctype, source, sizeof(source)) == 0) { printf("zfs`%s`avail\tL\t%llu\n", mnt.mnt_mountp, avail); } if(used != -1 && avail != -1) { printf("zfs`%s`used_percent\tn\t%f\n", mnt.mnt_mountp, 100.0 * (used / (double)(used + avail))); } ZFS_PULL_N_PRINT(ZFS_PROP_USEDCHILD, "used_children", "L", "%llu", datum); ZFS_PULL_N_PRINT(ZFS_PROP_USEDSNAP, "used_snapshot", "L", "%llu", datum); ZFS_PULL_N_PRINT(ZFS_PROP_REFERENCED, "referenced", "L", "%llu", datum); ZFS_PULL_N_PRINT(ZFS_PROP_RECORDSIZE, "record_size", "L", "%llu", datum); ZFS_PULL_N_PRINT(ZFS_PROP_QUOTA, "quota", "L", "%llu", datum); ZFS_PULL_N_PRINT(ZFS_PROP_RESERVATION, "reservation", "L", "%llu", datum); ZFS_PULL_N_PRINT(ZFS_PROP_REFRESERVATION, "ref_reservation", "L", "%llu", datum); ZFS_PULL_N_PRINT(ZFS_PROP_USEDREFRESERV, "ref_reservation_used", "L", "%llu", datum); #ifdef HAVE_LOGICAL_USED ZFS_PULL_N_PRINT(ZFS_PROP_LOGICALUSED, "logical_used", "L", "%llu", datum); ZFS_PULL_N_PRINT(ZFS_PROP_LOGICALREFERENCED, "logical_referenced", "L", "%llu", datum); #endif ZFS_PULL_N_PRINT(ZFS_PROP_COMPRESSRATIO, "compress_ratio", "n", "%f", (double)datum/100.0); zfs_close(handle); } libzfs_fini(zfsh); } else { printf("fs`%s`f_bsize\tL\t%llu\n", mnt.mnt_mountp, buf.f_bsize); printf("fs`%s`f_frsize\tL\t%llu\n", mnt.mnt_mountp, buf.f_frsize); printf("fs`%s`f_blocks\tL\t%llu\n", mnt.mnt_mountp, buf.f_blocks); printf("fs`%s`f_bfree\tL\t%llu\n", mnt.mnt_mountp, buf.f_bfree); printf("fs`%s`f_bavail\tL\t%llu\n", mnt.mnt_mountp, buf.f_bavail); printf("fs`%s`f_files\tL\t%llu\n", mnt.mnt_mountp, buf.f_blocks); printf("fs`%s`f_ffree\tL\t%llu\n", mnt.mnt_mountp, buf.f_ffree); printf("fs`%s`f_favail\tL\t%llu\n", mnt.mnt_mountp, buf.f_favail); } } } exit(0); }
void fmd_fmri_fini(void) { if (g_zfs) libzfs_fini(g_zfs); }
int sa_share_zfs(sa_share_t share, sa_resource_t resource, char *path, share_t *sh, void *exportdata, zfs_share_op_t operation) { libzfs_handle_t *libhandle; sa_group_t group; sa_handle_t sahandle; char *dataset; int err = EINVAL; int i, j; char newpath[MAXPATHLEN]; char *pathp; /* * First find the dataset name */ if ((group = sa_get_parent_group(share)) == NULL) { return (EINVAL); } if ((sahandle = sa_find_group_handle(group)) == NULL) { return (EINVAL); } /* * If get_zfs_dataset fails, see if it is a subdirectory */ pathp = path; while ((dataset = get_zfs_dataset(sahandle, pathp, B_TRUE)) == NULL) { char *p; if (pathp == path) { (void) strlcpy(newpath, path, sizeof (newpath)); pathp = newpath; } /* * Make sure only one leading '/' This condition came * about when using HAStoragePlus which insisted on * putting an extra leading '/' in the ZFS path * name. The problem is fixed in other areas, but this * will catch any other ways that a double slash might * get introduced. */ while (*pathp == '/' && *(pathp + 1) == '/') pathp++; /* * chop off part of path, but if we are at root then * make sure path is a / */ if ((strlen(pathp) > 1) && (p = strrchr(pathp, '/'))) { if (pathp == p) { *(p + 1) = '\0'; /* skip over /, root case */ } else { *p = '\0'; } } else { return (EINVAL); } } libhandle = libzfs_init(); if (libhandle != NULL) { char *resource_name; i = (sh->sh_path ? strlen(sh->sh_path) : 0); sh->sh_size = i; j = (sh->sh_res ? strlen(sh->sh_res) : 0); sh->sh_size += j; SMAX(i, j); j = (sh->sh_fstype ? strlen(sh->sh_fstype) : 0); sh->sh_size += j; SMAX(i, j); j = (sh->sh_opts ? strlen(sh->sh_opts) : 0); sh->sh_size += j; SMAX(i, j); j = (sh->sh_descr ? strlen(sh->sh_descr) : 0); sh->sh_size += j; SMAX(i, j); resource_name = sa_get_resource_attr(resource, "name"); err = zfs_deleg_share_nfs(libhandle, dataset, path, resource_name, exportdata, sh, i, operation); if (err == SA_OK) sa_update_sharetab_ts(sahandle); else err = errno; if (resource_name) sa_free_attr_string(resource_name); libzfs_fini(libhandle); } free(dataset); return (err); }
/* * Create a home directory and populate with files from skeleton * directory. */ int create_home(char *homedir, char *skeldir, uid_t uid, gid_t gid, int flags) /* home directory to create */ /* skel directory to copy if indicated */ /* uid of new user */ /* group id of new user */ /* miscellaneous flags */ { struct stat stbuf; char *dataset; char *dname, *bname, *rp; int created_fs = 0; rp = realpath(homedir, NULL); if (rp && (strcmp(rp, "/") == 0)) { return (EX_HOMEDIR); } (void) strcpy(dhome, homedir); (void) strcpy(bhome, homedir); dname = dirname(dhome); bname = basename(bhome); (void) strcpy(pdir, dname); if ((stat(pdir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) { errmsg(M_OOPS, "access the parent directory", strerror(errno)); return (EX_HOMEDIR); } if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) && (flags & MANAGE_ZFS)) { if (g_zfs == NULL) g_zfs = libzfs_init(); if (g_zfs == NULL) { errmsg(M_OOPS, "libzfs_init failure", strerror(errno)); return (EX_HOMEDIR); } if ((dataset = get_mnt_special(pdir, stbuf.st_fstype)) != NULL) { char nm[ZFS_MAX_DATASET_NAME_LEN]; zfs_handle_t *zhp; (void) snprintf(nm, sizeof (nm), "%s/%s", dataset, bname); if ((zfs_create(g_zfs, nm, ZFS_TYPE_FILESYSTEM, NULL) != 0) || ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) == NULL)) { errmsg(M_OOPS, "create the home directory", libzfs_error_description(g_zfs)); libzfs_fini(g_zfs); g_zfs = NULL; return (EX_HOMEDIR); } if (zfs_mount(zhp, NULL, 0) != 0) { errmsg(M_OOPS, "mount the home directory", libzfs_error_description(g_zfs)); (void) zfs_destroy(zhp, B_FALSE); zfs_close(zhp); libzfs_fini(g_zfs); g_zfs = NULL; return (EX_HOMEDIR); } zfs_close(zhp); if (chmod(homedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) { errmsg(M_OOPS, "change permissions of home directory", strerror(errno)); libzfs_fini(g_zfs); g_zfs = NULL; return (EX_HOMEDIR); } created_fs = 1; } else { errmsg(M_NO_ZFS_MOUNTPOINT, pdir); } } if (!created_fs) { if (mkdir(homedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) { errmsg(M_OOPS, "create the home directory", strerror(errno)); if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_HOMEDIR); } } if (chown(homedir, uid, gid) != 0) { errmsg(M_OOPS, "change ownership of home directory", strerror(errno)); if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_HOMEDIR); } if (skeldir != NULL) { /* copy the skel_dir into the home directory */ (void) sprintf(cmdbuf, "cd %s && find . -print | cpio -pd %s", skeldir, homedir); if (system(cmdbuf) != 0) { errmsg(M_OOPS, "copy skeleton directory into home " "directory", strerror(errno)); (void) rm_homedir(homedir, flags); if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_HOMEDIR); } /* make sure contents in the home dirctory have correct owner */ (void) sprintf(cmdbuf, "cd %s && find . -exec chown %ld:%ld {} \\;", homedir, uid, gid); if (system(cmdbuf) != 0) { errmsg(M_OOPS, "change owner and group of files home directory", strerror(errno)); (void) rm_homedir(homedir, flags); if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_HOMEDIR); } } if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_SUCCESS); }
int main(int argc, char **argv) { int c; char *range = NULL; char *cancel = NULL; char *end; char *raw = NULL; char *device = NULL; int level = 0; int quiet = 0; int error = 0; int domount = 0; err_type_t type = TYPE_INVAL; err_type_t label = TYPE_INVAL; zinject_record_t record = { 0 }; char pool[MAXNAMELEN]; char dataset[MAXNAMELEN]; zfs_handle_t *zhp; int ret; int flags = 0; if ((g_zfs = libzfs_init()) == NULL) { (void) fprintf(stderr, "internal error: failed to " "initialize ZFS library\n"); return (1); } libzfs_print_on_error(g_zfs, B_TRUE); if ((zfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { (void) fprintf(stderr, "failed to open ZFS device\n"); return (1); } if (argc == 1) { /* * No arguments. Print the available handlers. If there are no * available handlers, direct the user to '-h' for help * information. */ if (print_all_handlers() == 0) { (void) printf("No handlers registered.\n"); (void) printf("Run 'zinject -h' for usage " "information.\n"); } return (0); } while ((c = getopt(argc, argv, ":ab:d:f:Fqhc:t:l:mr:e:uL:")) != -1) { switch (c) { case 'a': flags |= ZINJECT_FLUSH_ARC; break; case 'b': raw = optarg; break; case 'c': cancel = optarg; break; case 'd': device = optarg; break; case 'e': if (strcasecmp(optarg, "io") == 0) { error = EIO; } else if (strcasecmp(optarg, "checksum") == 0) { error = ECKSUM; } else if (strcasecmp(optarg, "nxio") == 0) { error = ENXIO; } else { (void) fprintf(stderr, "invalid error type " "'%s': must be 'io', 'checksum' or " "'nxio'\n", optarg); usage(); return (1); } break; case 'f': record.zi_freq = atoi(optarg); if (record.zi_freq < 1 || record.zi_freq > 100) { (void) fprintf(stderr, "frequency range must " "be in the range (0, 100]\n"); return (1); } break; case 'F': record.zi_failfast = B_TRUE; break; case 'h': usage(); return (0); case 'l': level = (int)strtol(optarg, &end, 10); if (*end != '\0') { (void) fprintf(stderr, "invalid level '%s': " "must be an integer\n", optarg); usage(); return (1); } break; case 'm': domount = 1; break; case 'q': quiet = 1; break; case 'r': range = optarg; break; case 't': if ((type = name_to_type(optarg)) == TYPE_INVAL && !MOS_TYPE(type)) { (void) fprintf(stderr, "invalid type '%s'\n", optarg); usage(); return (1); } break; case 'u': flags |= ZINJECT_UNLOAD_SPA; break; case 'L': if ((label = name_to_type(optarg)) == TYPE_INVAL && !LABEL_TYPE(type)) { (void) fprintf(stderr, "invalid label type " "'%s'\n", optarg); usage(); return (1); } break; case ':': (void) fprintf(stderr, "option -%c requires an " "operand\n", optopt); usage(); return (1); case '?': (void) fprintf(stderr, "invalid option '%c'\n", optopt); usage(); return (2); } } argc -= optind; argv += optind; if (cancel != NULL) { /* * '-c' is invalid with any other options. */ if (raw != NULL || range != NULL || type != TYPE_INVAL || level != 0) { (void) fprintf(stderr, "cancel (-c) incompatible with " "any other options\n"); usage(); return (2); } if (argc != 0) { (void) fprintf(stderr, "extraneous argument to '-c'\n"); usage(); return (2); } if (strcmp(cancel, "all") == 0) { return (cancel_all_handlers()); } else { int id = (int)strtol(cancel, &end, 10); if (*end != '\0') { (void) fprintf(stderr, "invalid handle id '%s':" " must be an integer or 'all'\n", cancel); usage(); return (1); } return (cancel_handler(id)); } } if (device != NULL) { /* * Device (-d) injection uses a completely different mechanism * for doing injection, so handle it separately here. */ if (raw != NULL || range != NULL || type != TYPE_INVAL || level != 0) { (void) fprintf(stderr, "device (-d) incompatible with " "data error injection\n"); usage(); return (2); } if (argc != 1) { (void) fprintf(stderr, "device (-d) injection requires " "a single pool name\n"); usage(); return (2); } (void) strcpy(pool, argv[0]); dataset[0] = '\0'; if (error == ECKSUM) { (void) fprintf(stderr, "device error type must be " "'io' or 'nxio'\n"); return (1); } if (translate_device(pool, device, label, &record) != 0) return (1); if (!error) error = ENXIO; } else if (raw != NULL) { if (range != NULL || type != TYPE_INVAL || level != 0) { (void) fprintf(stderr, "raw (-b) format with " "any other options\n"); usage(); return (2); } if (argc != 1) { (void) fprintf(stderr, "raw (-b) format expects a " "single pool name\n"); usage(); return (2); } (void) strcpy(pool, argv[0]); dataset[0] = '\0'; if (error == ENXIO) { (void) fprintf(stderr, "data error type must be " "'checksum' or 'io'\n"); return (1); } if (translate_raw(raw, &record) != 0) return (1); if (!error) error = EIO; } else if (type == TYPE_INVAL) { if (flags == 0) { (void) fprintf(stderr, "at least one of '-b', '-d', " "'-t', '-a', or '-u' must be specified\n"); usage(); return (2); } if (argc == 1 && (flags & ZINJECT_UNLOAD_SPA)) { (void) strcpy(pool, argv[0]); dataset[0] = '\0'; } else if (argc != 0) { (void) fprintf(stderr, "extraneous argument for " "'-f'\n"); usage(); return (2); } flags |= ZINJECT_NULL; } else { if (argc != 1) { (void) fprintf(stderr, "missing object\n"); usage(); return (2); } if (error == ENXIO) { (void) fprintf(stderr, "data error type must be " "'checksum' or 'io'\n"); return (1); } if (translate_record(type, argv[0], range, level, &record, pool, dataset) != 0) return (1); if (!error) error = EIO; } /* * If this is pool-wide metadata, unmount everything. The ioctl() will * unload the pool, so that we trigger spa-wide reopen of metadata next * time we access the pool. */ if (dataset[0] != '\0' && domount) { if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL) return (1); #ifdef HAVE_ZPL if (zfs_unmount(zhp, NULL, 0) != 0) return (1); #endif /* HAVE_ZPL */ } record.zi_error = error; ret = register_handler(pool, flags, &record, quiet); #ifdef HAVE_ZPL if (dataset[0] != '\0' && domount) ret = (zfs_mount(zhp, NULL, 0) != 0); #endif /* HAVE_ZPL */ libzfs_fini(g_zfs); return (ret); }
/* * Active pool health status. * * To determine the status for a pool, we make several passes over the config, * picking the most egregious error we find. In order of importance, we do the * following: * * - Check for a complete and valid configuration * - Look for any faulted or missing devices in a non-replicated config * - Check for any data errors * - Check for any faulted or missing devices in a replicated config * - Look for any devices showing errors * - Check for any resilvering devices * * There can obviously be multiple errors within a single pool, so this routine * only picks the most damaging of all the current errors to report. */ static zpool_status_t check_status(zpool_handle_t *zhp, nvlist_t *config, boolean_t isimport) { nvlist_t *nvroot; vdev_stat_t *vs; uint_t vsc; uint64_t nerr; uint64_t version; uint64_t stateval; uint64_t hostid = 0; verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, &version) == 0); verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0); verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS, (uint64_t **)&vs, &vsc) == 0); verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &stateval) == 0); (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid); /* * Pool last accessed by another system. */ if (hostid != 0 && (unsigned long)hostid != gethostid() && stateval == POOL_STATE_ACTIVE) return (ZPOOL_STATUS_HOSTID_MISMATCH); /* * Newer on-disk version. */ if (vs->vs_state == VDEV_STATE_CANT_OPEN && vs->vs_aux == VDEV_AUX_VERSION_NEWER) return (ZPOOL_STATUS_VERSION_NEWER); /* * Check that the config is complete. */ if (vs->vs_state == VDEV_STATE_CANT_OPEN && vs->vs_aux == VDEV_AUX_BAD_GUID_SUM) return (ZPOOL_STATUS_BAD_GUID_SUM); /* * Pool has experienced failed I/O. */ if (stateval == POOL_STATE_IO_FAILURE) { zpool_handle_t *tmp_zhp = NULL; libzfs_handle_t *hdl = NULL; char property[ZPOOL_MAXPROPLEN]; char *failmode = NULL; if (zhp == NULL) { char *poolname; verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &poolname) == 0); if ((hdl = libzfs_init()) == NULL) return (ZPOOL_STATUS_IO_FAILURE_WAIT); tmp_zhp = zpool_open_canfail(hdl, poolname); if (tmp_zhp == NULL) { libzfs_fini(hdl); return (ZPOOL_STATUS_IO_FAILURE_WAIT); } } if (zpool_get_prop(zhp ? zhp : tmp_zhp, ZPOOL_PROP_FAILUREMODE, property, sizeof (property), NULL) == 0) failmode = property; if (tmp_zhp != NULL) zpool_close(tmp_zhp); if (hdl != NULL) libzfs_fini(hdl); if (failmode == NULL) return (ZPOOL_STATUS_IO_FAILURE_WAIT); if (strncmp(failmode, "continue", strlen("continue")) == 0) return (ZPOOL_STATUS_IO_FAILURE_CONTINUE); else return (ZPOOL_STATUS_IO_FAILURE_WAIT); } /* * Could not read a log. */ if (vs->vs_state == VDEV_STATE_CANT_OPEN && vs->vs_aux == VDEV_AUX_BAD_LOG) { return (ZPOOL_STATUS_BAD_LOG); } /* * Bad devices in non-replicated config. */ if (vs->vs_state == VDEV_STATE_CANT_OPEN && find_vdev_problem(nvroot, vdev_faulted)) return (ZPOOL_STATUS_FAULTED_DEV_NR); if (vs->vs_state == VDEV_STATE_CANT_OPEN && find_vdev_problem(nvroot, vdev_missing)) return (ZPOOL_STATUS_MISSING_DEV_NR); if (vs->vs_state == VDEV_STATE_CANT_OPEN && find_vdev_problem(nvroot, vdev_broken)) return (ZPOOL_STATUS_CORRUPT_LABEL_NR); /* * Corrupted pool metadata */ if (vs->vs_state == VDEV_STATE_CANT_OPEN && vs->vs_aux == VDEV_AUX_CORRUPT_DATA) return (ZPOOL_STATUS_CORRUPT_POOL); /* * Persistent data errors. */ if (!isimport) { if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT, &nerr) == 0 && nerr != 0) return (ZPOOL_STATUS_CORRUPT_DATA); } /* * Missing devices in a replicated config. */ if (find_vdev_problem(nvroot, vdev_faulted)) return (ZPOOL_STATUS_FAULTED_DEV_R); if (find_vdev_problem(nvroot, vdev_missing)) return (ZPOOL_STATUS_MISSING_DEV_R); if (find_vdev_problem(nvroot, vdev_broken)) return (ZPOOL_STATUS_CORRUPT_LABEL_R); /* * Devices with errors */ if (!isimport && find_vdev_problem(nvroot, vdev_errors)) return (ZPOOL_STATUS_FAILING_DEV); /* * Offlined devices */ if (find_vdev_problem(nvroot, vdev_offlined)) return (ZPOOL_STATUS_OFFLINE_DEV); /* * Currently resilvering */ if (!vs->vs_scrub_complete && vs->vs_scrub_type == POOL_SCRUB_RESILVER) return (ZPOOL_STATUS_RESILVERING); /* * Outdated, but usable, version */ if (version < SPA_VERSION) return (ZPOOL_STATUS_VERSION_OLDER); return (ZPOOL_STATUS_OK); }