X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=lib%2Flibzfs%2Flibzfs_dataset.c;h=3d31c106d356da83fd2137f333a75061f7db2697;hb=b8864a233c569edcc57c686f3ea8cd1ae3b89153;hp=a3f5a7d0fc6d702f34d32d06286d885ffefd30a3;hpb=428870ff734fdaccc342b33fc53cf94724409a46;p=zfs.git diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index a3f5a7d..3d31c10 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -126,7 +125,7 @@ path_to_str(const char *path, int types) * provide a more meaningful error message. We call zfs_error_aux() to * explain exactly why the name was not valid. */ -static int +int zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type, boolean_t modifying) { @@ -1212,39 +1211,46 @@ badlabel: (void) zfs_error(hdl, EZFS_BADPROP, errbuf); goto error; } + return (ret); + +error: + nvlist_free(ret); + return (NULL); +} + +int +zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl) +{ + uint64_t old_volsize; + uint64_t new_volsize; + uint64_t old_reservation; + uint64_t new_reservation; + zfs_prop_t resv_prop; /* * If this is an existing volume, and someone is setting the volsize, * make sure that it matches the reservation, or add it if necessary. */ - if (zhp != NULL && type == ZFS_TYPE_VOLUME && - nvlist_lookup_uint64(ret, zfs_prop_to_name(ZFS_PROP_VOLSIZE), - &intval) == 0) { - uint64_t old_volsize = zfs_prop_get_int(zhp, - ZFS_PROP_VOLSIZE); - uint64_t old_reservation; - uint64_t new_reservation; - zfs_prop_t resv_prop; - - if (zfs_which_resv_prop(zhp, &resv_prop) < 0) - goto error; - old_reservation = zfs_prop_get_int(zhp, resv_prop); - - if (old_volsize == old_reservation && - nvlist_lookup_uint64(ret, zfs_prop_to_name(resv_prop), - &new_reservation) != 0) { - if (nvlist_add_uint64(ret, - zfs_prop_to_name(resv_prop), intval) != 0) { - (void) no_memory(hdl); - goto error; - } - } + old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE); + if (zfs_which_resv_prop(zhp, &resv_prop) < 0) + return (-1); + old_reservation = zfs_prop_get_int(zhp, resv_prop); + if ((zvol_volsize_to_reservation(old_volsize, zhp->zfs_props) != + old_reservation) || nvlist_lookup_uint64(nvl, + zfs_prop_to_name(resv_prop), &new_reservation) != ENOENT) { + return (0); } - return (ret); - -error: - nvlist_free(ret); - return (NULL); + if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE), + &new_volsize) != 0) + return (-1); + new_reservation = zvol_volsize_to_reservation(new_volsize, + zhp->zfs_props); + if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop), + new_reservation) != 0) { + (void) no_memory(zhp->zfs_hdl); + return (-1); + } + return (1); } void @@ -1346,6 +1352,7 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) zfs_prop_t prop; boolean_t do_prefix; uint64_t idx; + int added_resv; (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), @@ -1366,6 +1373,11 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) prop = zfs_name_to_prop(propname); + if (prop == ZFS_PROP_VOLSIZE) { + if ((added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) + goto error; + } + if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL) goto error; @@ -1400,6 +1412,22 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) if (ret != 0) { zfs_setprop_error(hdl, prop, errno, errbuf); + if (added_resv && errno == ENOSPC) { + /* clean up the volsize property we tried to set */ + uint64_t old_volsize = zfs_prop_get_int(zhp, + ZFS_PROP_VOLSIZE); + nvlist_free(nvl); + zcmd_free_nvlists(&zc); + if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) + goto error; + if (nvlist_add_uint64(nvl, + zfs_prop_to_name(ZFS_PROP_VOLSIZE), + old_volsize) != 0) + goto error; + if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0) + goto error; + (void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc); + } } else { if (do_prefix) ret = changelist_postfix(cl); @@ -1474,7 +1502,7 @@ zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received) return (zfs_error(hdl, EZFS_PROPTYPE, errbuf)); /* - * Normalize the name, to get rid of shorthand abbrevations. + * Normalize the name, to get rid of shorthand abbreviations. */ propname = zfs_prop_to_name(prop); (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); @@ -1878,7 +1906,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, localtime_r(&time, &t) == NULL || strftime(propbuf, proplen, "%a %b %e %k:%M %Y", &t) == 0) - (void) snprintf(propbuf, proplen, "%llu", val); + (void) snprintf(propbuf, proplen, "%llu", (u_longlong_t) val); } break; @@ -2173,14 +2201,11 @@ static int idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser, char **domainp, idmap_rid_t *ridp) { - idmap_handle_t *idmap_hdl = NULL; idmap_get_handle_t *get_hdl = NULL; idmap_stat status; int err = EINVAL; - if (idmap_init(&idmap_hdl) != IDMAP_SUCCESS) - goto out; - if (idmap_get_create(idmap_hdl, &get_hdl) != IDMAP_SUCCESS) + if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS) goto out; if (isuser) { @@ -2199,8 +2224,6 @@ idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser, out: if (get_hdl) idmap_get_destroy(get_hdl); - if (idmap_hdl) - (void) idmap_fini(idmap_hdl); return (err); } @@ -2368,7 +2391,8 @@ zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname, return (err); if (literal) { - (void) snprintf(propbuf, proplen, "%llu", propvalue); + (void) snprintf(propbuf, proplen, "%llu", + (u_longlong_t)propvalue); } else if (propvalue == 0 && (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) { (void) strlcpy(propbuf, "none", proplen); @@ -3898,11 +3922,14 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type, int zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, - boolean_t recursive, boolean_t temphold, boolean_t enoent_ok) + boolean_t recursive, boolean_t temphold, boolean_t enoent_ok, + int cleanup_fd, uint64_t dsobj, uint64_t createtxg) { zfs_cmd_t zc = { 0 }; libzfs_handle_t *hdl = zhp->zfs_hdl; + ASSERT(!recursive || dsobj == 0); + (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); if (strlcpy(zc.zc_string, tag, sizeof (zc.zc_string)) @@ -3910,6 +3937,9 @@ zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, return (zfs_error(hdl, EZFS_TAGTOOLONG, tag)); zc.zc_cookie = recursive; zc.zc_temphold = temphold; + zc.zc_cleanup_fd = cleanup_fd; + zc.zc_sendobj = dsobj; + zc.zc_createtxg = createtxg; if (zfs_ioctl(hdl, ZFS_IOC_HOLD, &zc) != 0) { char errbuf[ZFS_MAXNAMELEN+32]; @@ -3939,7 +3969,7 @@ zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, return (zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf)); case ENOENT: if (enoent_ok) - return (0); + return (ENOENT); /* FALLTHROUGH */ default: return (zfs_standard_error_fmt(hdl, errno, errbuf)); @@ -3949,102 +3979,6 @@ zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag, return (0); } -struct hold_range_arg { - zfs_handle_t *origin; - const char *fromsnap; - const char *tosnap; - char lastsnapheld[ZFS_MAXNAMELEN]; - const char *tag; - boolean_t temphold; - boolean_t seento; - boolean_t seenfrom; - boolean_t holding; - boolean_t recursive; - snapfilter_cb_t *filter_cb; - void *filter_cb_arg; -}; - -static int -zfs_hold_range_one(zfs_handle_t *zhp, void *arg) -{ - struct hold_range_arg *hra = arg; - const char *thissnap; - int error; - - thissnap = strchr(zfs_get_name(zhp), '@') + 1; - - if (hra->fromsnap && !hra->seenfrom && - strcmp(hra->fromsnap, thissnap) == 0) - hra->seenfrom = B_TRUE; - - /* snap is older or newer than the desired range, ignore it */ - if (hra->seento || !hra->seenfrom) { - zfs_close(zhp); - return (0); - } - - if (!hra->seento && strcmp(hra->tosnap, thissnap) == 0) - hra->seento = B_TRUE; - - if (hra->filter_cb != NULL && - hra->filter_cb(zhp, hra->filter_cb_arg) == B_FALSE) { - zfs_close(zhp); - return (0); - } - - if (hra->holding) { - /* We could be racing with destroy, so ignore ENOENT. */ - error = zfs_hold(hra->origin, thissnap, hra->tag, - hra->recursive, hra->temphold, B_TRUE); - if (error == 0) { - (void) strlcpy(hra->lastsnapheld, zfs_get_name(zhp), - sizeof (hra->lastsnapheld)); - } - } else { - error = zfs_release(hra->origin, thissnap, hra->tag, - hra->recursive); - } - - zfs_close(zhp); - return (error); -} - -/* - * Add a user hold on the set of snapshots starting with fromsnap up to - * and including tosnap. If we're unable to to acquire a particular hold, - * undo any holds up to that point. - */ -int -zfs_hold_range(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, - const char *tag, boolean_t recursive, boolean_t temphold, - snapfilter_cb_t filter_cb, void *cbarg) -{ - struct hold_range_arg arg = { 0 }; - int error; - - arg.origin = zhp; - arg.fromsnap = fromsnap; - arg.tosnap = tosnap; - arg.tag = tag; - arg.temphold = temphold; - arg.holding = B_TRUE; - arg.recursive = recursive; - arg.seenfrom = (fromsnap == NULL); - arg.filter_cb = filter_cb; - arg.filter_cb_arg = cbarg; - - error = zfs_iter_snapshots_sorted(zhp, zfs_hold_range_one, &arg); - - /* - * Make sure we either hold the entire range or none. - */ - if (error && arg.lastsnapheld[0] != '\0') { - (void) zfs_release_range(zhp, fromsnap, - (const char *)arg.lastsnapheld, tag, recursive); - } - return (error); -} - int zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag, boolean_t recursive) @@ -4086,26 +4020,6 @@ zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag, return (0); } -/* - * Release a user hold from the set of snapshots starting with fromsnap - * up to and including tosnap. - */ -int -zfs_release_range(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, - const char *tag, boolean_t recursive) -{ - struct hold_range_arg arg = { 0 }; - - arg.origin = zhp; - arg.fromsnap = fromsnap; - arg.tosnap = tosnap; - arg.tag = tag; - arg.recursive = recursive; - arg.seenfrom = (fromsnap == NULL); - - return (zfs_iter_snapshots_sorted(zhp, zfs_hold_range_one, &arg)); -} - uint64_t zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props) {