예제 #1
0
/*
 * 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);
}
예제 #2
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));
}
예제 #3
0
/*
 * 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);
}
예제 #4
0
/*
 * 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);
}
예제 #5
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);
}
예제 #6
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);
}
예제 #7
0
파일: zhack.c 프로젝트: 64116278/zfs
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);
}
예제 #8
0
/*
 * 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);
}
예제 #9
0
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);
}
예제 #10
0
파일: libshare.c 프로젝트: DeHackEd/zfs
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);
}
예제 #11
0
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;
}
예제 #12
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);

}
예제 #13
0
/*
 * 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;
	}
}
예제 #14
0
/*
 *	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;
}
예제 #15
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;
	}
}
예제 #16
0
파일: zinject.c 프로젝트: RJVB/zfs
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);
}
예제 #17
0
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);
}
예제 #18
0
파일: zfs_util.c 프로젝트: derzzle/zfs
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);
}
예제 #19
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);
}
예제 #20
0
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;
}
예제 #21
0
파일: fs.c 프로젝트: alex-tools/nad
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);
}
예제 #22
0
void
fmd_fmri_fini(void)
{
	if (g_zfs)
		libzfs_fini(g_zfs);
}
예제 #23
0
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);
}
예제 #24
0
/*
 * 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);
}
예제 #25
0
파일: zinject.c 프로젝트: harshada/zfs
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);
}
예제 #26
0
/*
 * 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);
}