1 789 ahrens /* 2 789 ahrens * CDDL HEADER START 3 789 ahrens * 4 789 ahrens * The contents of this file are subject to the terms of the 5 1544 eschrock * Common Development and Distribution License (the "License"). 6 1544 eschrock * You may not use this file except in compliance with the License. 7 789 ahrens * 8 789 ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 789 ahrens * or http://www.opensolaris.org/os/licensing. 10 789 ahrens * See the License for the specific language governing permissions 11 789 ahrens * and limitations under the License. 12 789 ahrens * 13 789 ahrens * When distributing Covered Code, include this CDDL HEADER in each 14 789 ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 789 ahrens * If applicable, add the following below this CDDL HEADER, with the 16 789 ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17 789 ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18 789 ahrens * 19 789 ahrens * CDDL HEADER END 20 789 ahrens */ 21 3126 ahl 22 789 ahrens /* 23 8802 Sanjeev * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 789 ahrens * Use is subject to license terms. 25 789 ahrens */ 26 789 ahrens 27 789 ahrens #include <ctype.h> 28 789 ahrens #include <errno.h> 29 789 ahrens #include <libintl.h> 30 789 ahrens #include <math.h> 31 789 ahrens #include <stdio.h> 32 789 ahrens #include <stdlib.h> 33 789 ahrens #include <strings.h> 34 789 ahrens #include <unistd.h> 35 5367 ahrens #include <stddef.h> 36 789 ahrens #include <zone.h> 37 2082 eschrock #include <fcntl.h> 38 789 ahrens #include <sys/mntent.h> 39 1294 lling #include <sys/mount.h> 40 4543 marks #include <priv.h> 41 4543 marks #include <pwd.h> 42 4543 marks #include <grp.h> 43 4543 marks #include <stddef.h> 44 4543 marks #include <ucred.h> 45 9396 Matthew #include <idmap.h> 46 9396 Matthew #include <aclutils.h> 47 10160 Matthew #include <directory.h> 48 789 ahrens 49 789 ahrens #include <sys/spa.h> 50 2676 eschrock #include <sys/zap.h> 51 789 ahrens #include <libzfs.h> 52 789 ahrens 53 789 ahrens #include "zfs_namecheck.h" 54 789 ahrens #include "zfs_prop.h" 55 789 ahrens #include "libzfs_impl.h" 56 4543 marks #include "zfs_deleg.h" 57 4007 mmusante 58 9396 Matthew static int userquota_propname_decode(const char *propname, boolean_t zoned, 59 9396 Matthew zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp); 60 789 ahrens 61 789 ahrens /* 62 789 ahrens * Given a single type (not a mask of types), return the type in a human 63 789 ahrens * readable form. 64 789 ahrens */ 65 789 ahrens const char * 66 789 ahrens zfs_type_to_name(zfs_type_t type) 67 789 ahrens { 68 789 ahrens switch (type) { 69 789 ahrens case ZFS_TYPE_FILESYSTEM: 70 789 ahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 71 789 ahrens case ZFS_TYPE_SNAPSHOT: 72 789 ahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 73 789 ahrens case ZFS_TYPE_VOLUME: 74 789 ahrens return (dgettext(TEXT_DOMAIN, "volume")); 75 789 ahrens } 76 789 ahrens 77 789 ahrens return (NULL); 78 789 ahrens } 79 789 ahrens 80 789 ahrens /* 81 789 ahrens * Given a path and mask of ZFS types, return a string describing this dataset. 82 789 ahrens * This is used when we fail to open a dataset and we cannot get an exact type. 83 789 ahrens * We guess what the type would have been based on the path and the mask of 84 789 ahrens * acceptable types. 85 789 ahrens */ 86 789 ahrens static const char * 87 789 ahrens path_to_str(const char *path, int types) 88 789 ahrens { 89 789 ahrens /* 90 789 ahrens * When given a single type, always report the exact type. 91 789 ahrens */ 92 789 ahrens if (types == ZFS_TYPE_SNAPSHOT) 93 789 ahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 94 789 ahrens if (types == ZFS_TYPE_FILESYSTEM) 95 789 ahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 96 789 ahrens if (types == ZFS_TYPE_VOLUME) 97 789 ahrens return (dgettext(TEXT_DOMAIN, "volume")); 98 789 ahrens 99 789 ahrens /* 100 789 ahrens * The user is requesting more than one type of dataset. If this is the 101 789 ahrens * case, consult the path itself. If we're looking for a snapshot, and 102 789 ahrens * a '@' is found, then report it as "snapshot". Otherwise, remove the 103 789 ahrens * snapshot attribute and try again. 104 789 ahrens */ 105 789 ahrens if (types & ZFS_TYPE_SNAPSHOT) { 106 789 ahrens if (strchr(path, '@') != NULL) 107 789 ahrens return (dgettext(TEXT_DOMAIN, "snapshot")); 108 789 ahrens return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT)); 109 789 ahrens } 110 789 ahrens 111 789 ahrens /* 112 789 ahrens * The user has requested either filesystems or volumes. 113 789 ahrens * We have no way of knowing a priori what type this would be, so always 114 789 ahrens * report it as "filesystem" or "volume", our two primitive types. 115 789 ahrens */ 116 789 ahrens if (types & ZFS_TYPE_FILESYSTEM) 117 789 ahrens return (dgettext(TEXT_DOMAIN, "filesystem")); 118 789 ahrens 119 789 ahrens assert(types & ZFS_TYPE_VOLUME); 120 789 ahrens return (dgettext(TEXT_DOMAIN, "volume")); 121 789 ahrens } 122 789 ahrens 123 789 ahrens /* 124 789 ahrens * Validate a ZFS path. This is used even before trying to open the dataset, to 125 9396 Matthew * provide a more meaningful error message. We call zfs_error_aux() to 126 9396 Matthew * explain exactly why the name was not valid. 127 789 ahrens */ 128 789 ahrens static int 129 5326 ek110237 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type, 130 5326 ek110237 boolean_t modifying) 131 789 ahrens { 132 789 ahrens namecheck_err_t why; 133 789 ahrens char what; 134 789 ahrens 135 789 ahrens if (dataset_namecheck(path, &why, &what) != 0) { 136 2082 eschrock if (hdl != NULL) { 137 789 ahrens switch (why) { 138 1003 lling case NAME_ERR_TOOLONG: 139 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 140 2082 eschrock "name is too long")); 141 1003 lling break; 142 1003 lling 143 789 ahrens case NAME_ERR_LEADING_SLASH: 144 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 145 2082 eschrock "leading slash in name")); 146 789 ahrens break; 147 789 ahrens 148 789 ahrens case NAME_ERR_EMPTY_COMPONENT: 149 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 150 2082 eschrock "empty component in name")); 151 789 ahrens break; 152 789 ahrens 153 789 ahrens case NAME_ERR_TRAILING_SLASH: 154 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 155 2082 eschrock "trailing slash in name")); 156 789 ahrens break; 157 789 ahrens 158 789 ahrens case NAME_ERR_INVALCHAR: 159 2082 eschrock zfs_error_aux(hdl, 160 789 ahrens dgettext(TEXT_DOMAIN, "invalid character " 161 2082 eschrock "'%c' in name"), what); 162 789 ahrens break; 163 789 ahrens 164 789 ahrens case NAME_ERR_MULTIPLE_AT: 165 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 166 2082 eschrock "multiple '@' delimiters in name")); 167 2856 nd150628 break; 168 2856 nd150628 169 2856 nd150628 case NAME_ERR_NOLETTER: 170 2856 nd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 171 2856 nd150628 "pool doesn't begin with a letter")); 172 2856 nd150628 break; 173 2856 nd150628 174 2856 nd150628 case NAME_ERR_RESERVED: 175 2856 nd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 176 2856 nd150628 "name is reserved")); 177 2856 nd150628 break; 178 2856 nd150628 179 2856 nd150628 case NAME_ERR_DISKLIKE: 180 2856 nd150628 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 181 2856 nd150628 "reserved disk name")); 182 789 ahrens break; 183 789 ahrens } 184 789 ahrens } 185 789 ahrens 186 789 ahrens return (0); 187 789 ahrens } 188 789 ahrens 189 789 ahrens if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) { 190 2082 eschrock if (hdl != NULL) 191 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 192 2082 eschrock "snapshot delimiter '@' in filesystem name")); 193 2199 ahrens return (0); 194 2199 ahrens } 195 2199 ahrens 196 2199 ahrens if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) { 197 2199 ahrens if (hdl != NULL) 198 2199 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 199 3413 mmusante "missing '@' delimiter in snapshot name")); 200 789 ahrens return (0); 201 789 ahrens } 202 789 ahrens 203 5326 ek110237 if (modifying && strchr(path, '%') != NULL) { 204 5326 ek110237 if (hdl != NULL) 205 5326 ek110237 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 206 5326 ek110237 "invalid character %c in name"), '%'); 207 5326 ek110237 return (0); 208 5326 ek110237 } 209 5326 ek110237 210 2082 eschrock return (-1); 211 789 ahrens } 212 789 ahrens 213 789 ahrens int 214 789 ahrens zfs_name_valid(const char *name, zfs_type_t type) 215 789 ahrens { 216 6423 gw25295 if (type == ZFS_TYPE_POOL) 217 6423 gw25295 return (zpool_name_valid(NULL, B_FALSE, name)); 218 5326 ek110237 return (zfs_validate_name(NULL, name, type, B_FALSE)); 219 789 ahrens } 220 789 ahrens 221 789 ahrens /* 222 2676 eschrock * This function takes the raw DSL properties, and filters out the user-defined 223 2676 eschrock * properties into a separate nvlist. 224 2676 eschrock */ 225 4217 eschrock static nvlist_t * 226 4217 eschrock process_user_props(zfs_handle_t *zhp, nvlist_t *props) 227 2676 eschrock { 228 2676 eschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 229 2676 eschrock nvpair_t *elem; 230 2676 eschrock nvlist_t *propval; 231 4217 eschrock nvlist_t *nvl; 232 2676 eschrock 233 4217 eschrock if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 234 4217 eschrock (void) no_memory(hdl); 235 4217 eschrock return (NULL); 236 4217 eschrock } 237 2676 eschrock 238 2676 eschrock elem = NULL; 239 4217 eschrock while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 240 2676 eschrock if (!zfs_prop_user(nvpair_name(elem))) 241 2676 eschrock continue; 242 2676 eschrock 243 2676 eschrock verify(nvpair_value_nvlist(elem, &propval) == 0); 244 4217 eschrock if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) { 245 4217 eschrock nvlist_free(nvl); 246 4217 eschrock (void) no_memory(hdl); 247 4217 eschrock return (NULL); 248 4217 eschrock } 249 2676 eschrock } 250 2676 eschrock 251 4217 eschrock return (nvl); 252 2676 eschrock } 253 2676 eschrock 254 6865 rm160521 static zpool_handle_t * 255 6865 rm160521 zpool_add_handle(zfs_handle_t *zhp, const char *pool_name) 256 6865 rm160521 { 257 6865 rm160521 libzfs_handle_t *hdl = zhp->zfs_hdl; 258 6865 rm160521 zpool_handle_t *zph; 259 6865 rm160521 260 6865 rm160521 if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) { 261 6865 rm160521 if (hdl->libzfs_pool_handles != NULL) 262 6865 rm160521 zph->zpool_next = hdl->libzfs_pool_handles; 263 6865 rm160521 hdl->libzfs_pool_handles = zph; 264 6865 rm160521 } 265 6865 rm160521 return (zph); 266 6865 rm160521 } 267 6865 rm160521 268 6865 rm160521 static zpool_handle_t * 269 6865 rm160521 zpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len) 270 6865 rm160521 { 271 6865 rm160521 libzfs_handle_t *hdl = zhp->zfs_hdl; 272 6865 rm160521 zpool_handle_t *zph = hdl->libzfs_pool_handles; 273 6865 rm160521 274 6865 rm160521 while ((zph != NULL) && 275 6865 rm160521 (strncmp(pool_name, zpool_get_name(zph), len) != 0)) 276 6865 rm160521 zph = zph->zpool_next; 277 6865 rm160521 return (zph); 278 6865 rm160521 } 279 6865 rm160521 280 6865 rm160521 /* 281 6865 rm160521 * Returns a handle to the pool that contains the provided dataset. 282 6865 rm160521 * If a handle to that pool already exists then that handle is returned. 283 6865 rm160521 * Otherwise, a new handle is created and added to the list of handles. 284 6865 rm160521 */ 285 6865 rm160521 static zpool_handle_t * 286 6865 rm160521 zpool_handle(zfs_handle_t *zhp) 287 6865 rm160521 { 288 6865 rm160521 char *pool_name; 289 6865 rm160521 int len; 290 6865 rm160521 zpool_handle_t *zph; 291 6865 rm160521 292 6865 rm160521 len = strcspn(zhp->zfs_name, "/@") + 1; 293 6865 rm160521 pool_name = zfs_alloc(zhp->zfs_hdl, len); 294 6865 rm160521 (void) strlcpy(pool_name, zhp->zfs_name, len); 295 6865 rm160521 296 6865 rm160521 zph = zpool_find_handle(zhp, pool_name, len); 297 6865 rm160521 if (zph == NULL) 298 6865 rm160521 zph = zpool_add_handle(zhp, pool_name); 299 6865 rm160521 300 6865 rm160521 free(pool_name); 301 6865 rm160521 return (zph); 302 6865 rm160521 } 303 6865 rm160521 304 6865 rm160521 void 305 6865 rm160521 zpool_free_handles(libzfs_handle_t *hdl) 306 6865 rm160521 { 307 6865 rm160521 zpool_handle_t *next, *zph = hdl->libzfs_pool_handles; 308 6865 rm160521 309 6865 rm160521 while (zph != NULL) { 310 6865 rm160521 next = zph->zpool_next; 311 6865 rm160521 zpool_close(zph); 312 6865 rm160521 zph = next; 313 6865 rm160521 } 314 6865 rm160521 hdl->libzfs_pool_handles = NULL; 315 6865 rm160521 } 316 6865 rm160521 317 2676 eschrock /* 318 789 ahrens * Utility function to gather stats (objset and zpl) for the given object. 319 789 ahrens */ 320 789 ahrens static int 321 8228 Eric get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc) 322 8228 Eric { 323 8228 Eric libzfs_handle_t *hdl = zhp->zfs_hdl; 324 8228 Eric 325 8228 Eric (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name)); 326 8228 Eric 327 8228 Eric while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) { 328 8228 Eric if (errno == ENOMEM) { 329 8228 Eric if (zcmd_expand_dst_nvlist(hdl, zc) != 0) { 330 8228 Eric return (-1); 331 8228 Eric } 332 8228 Eric } else { 333 8228 Eric return (-1); 334 8228 Eric } 335 8228 Eric } 336 8228 Eric return (0); 337 8228 Eric } 338 8228 Eric 339 11022 Tom /* 340 11022 Tom * Utility function to get the received properties of the given object. 341 11022 Tom */ 342 11022 Tom static int 343 11022 Tom get_recvd_props_ioctl(zfs_handle_t *zhp) 344 11022 Tom { 345 11022 Tom libzfs_handle_t *hdl = zhp->zfs_hdl; 346 11022 Tom nvlist_t *recvdprops; 347 11022 Tom zfs_cmd_t zc = { 0 }; 348 11022 Tom int err; 349 11022 Tom 350 11022 Tom if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) 351 11022 Tom return (-1); 352 11022 Tom 353 11022 Tom (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 354 11022 Tom 355 11022 Tom while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_RECVD_PROPS, &zc) != 0) { 356 11022 Tom if (errno == ENOMEM) { 357 11022 Tom if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { 358 11022 Tom return (-1); 359 11022 Tom } 360 11022 Tom } else { 361 11022 Tom zcmd_free_nvlists(&zc); 362 11022 Tom return (-1); 363 11022 Tom } 364 11022 Tom } 365 11022 Tom 366 11022 Tom err = zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &recvdprops); 367 11022 Tom zcmd_free_nvlists(&zc); 368 11022 Tom if (err != 0) 369 11022 Tom return (-1); 370 11022 Tom 371 11022 Tom nvlist_free(zhp->zfs_recvd_props); 372 11022 Tom zhp->zfs_recvd_props = recvdprops; 373 11022 Tom 374 11022 Tom return (0); 375 11022 Tom } 376 11022 Tom 377 8228 Eric static int 378 8228 Eric put_stats_zhdl(zfs_handle_t *zhp, zfs_cmd_t *zc) 379 8228 Eric { 380 4217 eschrock nvlist_t *allprops, *userprops; 381 789 ahrens 382 8228 Eric zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */ 383 8228 Eric 384 8228 Eric if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) { 385 8228 Eric return (-1); 386 8228 Eric } 387 2676 eschrock 388 9396 Matthew /* 389 9396 Matthew * XXX Why do we store the user props separately, in addition to 390 9396 Matthew * storing them in zfs_props? 391 9396 Matthew */ 392 4217 eschrock if ((userprops = process_user_props(zhp, allprops)) == NULL) { 393 4217 eschrock nvlist_free(allprops); 394 2676 eschrock return (-1); 395 4217 eschrock } 396 4217 eschrock 397 4217 eschrock nvlist_free(zhp->zfs_props); 398 4217 eschrock nvlist_free(zhp->zfs_user_props); 399 4217 eschrock 400 4217 eschrock zhp->zfs_props = allprops; 401 4217 eschrock zhp->zfs_user_props = userprops; 402 789 ahrens 403 789 ahrens return (0); 404 789 ahrens } 405 789 ahrens 406 8228 Eric static int 407 8228 Eric get_stats(zfs_handle_t *zhp) 408 8228 Eric { 409 8228 Eric int rc = 0; 410 8228 Eric zfs_cmd_t zc = { 0 }; 411 8228 Eric 412 8228 Eric if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 413 8228 Eric return (-1); 414 8228 Eric if (get_stats_ioctl(zhp, &zc) != 0) 415 8228 Eric rc = -1; 416 8228 Eric else if (put_stats_zhdl(zhp, &zc) != 0) 417 8228 Eric rc = -1; 418 8228 Eric zcmd_free_nvlists(&zc); 419 8228 Eric return (rc); 420 8228 Eric } 421 8228 Eric 422 789 ahrens /* 423 789 ahrens * Refresh the properties currently stored in the handle. 424 789 ahrens */ 425 789 ahrens void 426 789 ahrens zfs_refresh_properties(zfs_handle_t *zhp) 427 789 ahrens { 428 789 ahrens (void) get_stats(zhp); 429 789 ahrens } 430 789 ahrens 431 789 ahrens /* 432 789 ahrens * Makes a handle from the given dataset name. Used by zfs_open() and 433 789 ahrens * zfs_iter_* to create child handles on the fly. 434 789 ahrens */ 435 8228 Eric static int 436 8228 Eric make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc) 437 8228 Eric { 438 10298 Matthew if (put_stats_zhdl(zhp, zc) != 0) 439 10298 Matthew return (-1); 440 789 ahrens 441 789 ahrens /* 442 789 ahrens * We've managed to open the dataset and gather statistics. Determine 443 789 ahrens * the high-level type. 444 789 ahrens */ 445 2885 ahrens if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 446 2885 ahrens zhp->zfs_head_type = ZFS_TYPE_VOLUME; 447 2885 ahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 448 2885 ahrens zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM; 449 2885 ahrens else 450 2885 ahrens abort(); 451 2885 ahrens 452 789 ahrens if (zhp->zfs_dmustats.dds_is_snapshot) 453 789 ahrens zhp->zfs_type = ZFS_TYPE_SNAPSHOT; 454 789 ahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) 455 789 ahrens zhp->zfs_type = ZFS_TYPE_VOLUME; 456 789 ahrens else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS) 457 789 ahrens zhp->zfs_type = ZFS_TYPE_FILESYSTEM; 458 789 ahrens else 459 2082 eschrock abort(); /* we should never see any other types */ 460 789 ahrens 461 6865 rm160521 zhp->zpool_hdl = zpool_handle(zhp); 462 8228 Eric return (0); 463 8228 Eric } 464 8228 Eric 465 8228 Eric zfs_handle_t * 466 8228 Eric make_dataset_handle(libzfs_handle_t *hdl, const char *path) 467 8228 Eric { 468 8228 Eric zfs_cmd_t zc = { 0 }; 469 8228 Eric 470 8228 Eric zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); 471 8228 Eric 472 8228 Eric if (zhp == NULL) 473 8228 Eric return (NULL); 474 8228 Eric 475 8228 Eric zhp->zfs_hdl = hdl; 476 8228 Eric (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name)); 477 8228 Eric if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) { 478 8228 Eric free(zhp); 479 8228 Eric return (NULL); 480 8228 Eric } 481 8228 Eric if (get_stats_ioctl(zhp, &zc) == -1) { 482 8228 Eric zcmd_free_nvlists(&zc); 483 8228 Eric free(zhp); 484 8228 Eric return (NULL); 485 8228 Eric } 486 8228 Eric if (make_dataset_handle_common(zhp, &zc) == -1) { 487 8228 Eric free(zhp); 488 8228 Eric zhp = NULL; 489 8228 Eric } 490 8228 Eric zcmd_free_nvlists(&zc); 491 8228 Eric return (zhp); 492 8228 Eric } 493 8228 Eric 494 8228 Eric static zfs_handle_t * 495 8228 Eric make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc) 496 8228 Eric { 497 8228 Eric zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1); 498 8228 Eric 499 8228 Eric if (zhp == NULL) 500 8228 Eric return (NULL); 501 8228 Eric 502 8228 Eric zhp->zfs_hdl = hdl; 503 8228 Eric (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name)); 504 8228 Eric if (make_dataset_handle_common(zhp, zc) == -1) { 505 8228 Eric free(zhp); 506 8228 Eric return (NULL); 507 8228 Eric } 508 789 ahrens return (zhp); 509 789 ahrens } 510 789 ahrens 511 789 ahrens /* 512 789 ahrens * Opens the given snapshot, filesystem, or volume. The 'types' 513 789 ahrens * argument is a mask of acceptable types. The function will print an 514 789 ahrens * appropriate error message and return NULL if it can't be opened. 515 789 ahrens */ 516 789 ahrens zfs_handle_t * 517 2082 eschrock zfs_open(libzfs_handle_t *hdl, const char *path, int types) 518 789 ahrens { 519 789 ahrens zfs_handle_t *zhp; 520 2082 eschrock char errbuf[1024]; 521 2082 eschrock 522 2082 eschrock (void) snprintf(errbuf, sizeof (errbuf), 523 2082 eschrock dgettext(TEXT_DOMAIN, "cannot open '%s'"), path); 524 789 ahrens 525 789 ahrens /* 526 2082 eschrock * Validate the name before we even try to open it. 527 789 ahrens */ 528 5326 ek110237 if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) { 529 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 530 2082 eschrock "invalid dataset name")); 531 2082 eschrock (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf); 532 789 ahrens return (NULL); 533 789 ahrens } 534 789 ahrens 535 789 ahrens /* 536 789 ahrens * Try to get stats for the dataset, which will tell us if it exists. 537 789 ahrens */ 538 789 ahrens errno = 0; 539 2082 eschrock if ((zhp = make_dataset_handle(hdl, path)) == NULL) { 540 3237 lling (void) zfs_standard_error(hdl, errno, errbuf); 541 789 ahrens return (NULL); 542 789 ahrens } 543 789 ahrens 544 789 ahrens if (!(types & zhp->zfs_type)) { 545 2082 eschrock (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 546 2142 eschrock zfs_close(zhp); 547 789 ahrens return (NULL); 548 789 ahrens } 549 789 ahrens 550 789 ahrens return (zhp); 551 789 ahrens } 552 789 ahrens 553 789 ahrens /* 554 789 ahrens * Release a ZFS handle. Nothing to do but free the associated memory. 555 789 ahrens */ 556 789 ahrens void 557 789 ahrens zfs_close(zfs_handle_t *zhp) 558 789 ahrens { 559 789 ahrens if (zhp->zfs_mntopts) 560 789 ahrens free(zhp->zfs_mntopts); 561 2676 eschrock nvlist_free(zhp->zfs_props); 562 2676 eschrock nvlist_free(zhp->zfs_user_props); 563 11022 Tom nvlist_free(zhp->zfs_recvd_props); 564 789 ahrens free(zhp); 565 8228 Eric } 566 8228 Eric 567 8228 Eric typedef struct mnttab_node { 568 8228 Eric struct mnttab mtn_mt; 569 8228 Eric avl_node_t mtn_node; 570 8228 Eric } mnttab_node_t; 571 8228 Eric 572 8228 Eric static int 573 8228 Eric libzfs_mnttab_cache_compare(const void *arg1, const void *arg2) 574 8228 Eric { 575 8228 Eric const mnttab_node_t *mtn1 = arg1; 576 8228 Eric const mnttab_node_t *mtn2 = arg2; 577 8228 Eric int rv; 578 8228 Eric 579 8228 Eric rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special); 580 8228 Eric 581 8228 Eric if (rv == 0) 582 8228 Eric return (0); 583 8228 Eric return (rv > 0 ? 1 : -1); 584 8228 Eric } 585 8228 Eric 586 8228 Eric void 587 8228 Eric libzfs_mnttab_init(libzfs_handle_t *hdl) 588 8228 Eric { 589 8228 Eric assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0); 590 8228 Eric avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare, 591 8228 Eric sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node)); 592 8811 Eric } 593 8811 Eric 594 8811 Eric void 595 8811 Eric libzfs_mnttab_update(libzfs_handle_t *hdl) 596 8811 Eric { 597 8811 Eric struct mnttab entry; 598 8228 Eric 599 8228 Eric rewind(hdl->libzfs_mnttab); 600 8228 Eric while (getmntent(hdl->libzfs_mnttab, &entry) == 0) { 601 8228 Eric mnttab_node_t *mtn; 602 8228 Eric 603 8228 Eric if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) 604 8228 Eric continue; 605 8228 Eric mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); 606 8228 Eric mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special); 607 8228 Eric mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp); 608 8228 Eric mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype); 609 8228 Eric mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts); 610 8228 Eric avl_add(&hdl->libzfs_mnttab_cache, mtn); 611 8228 Eric } 612 8228 Eric } 613 8228 Eric 614 8228 Eric void 615 8228 Eric libzfs_mnttab_fini(libzfs_handle_t *hdl) 616 8228 Eric { 617 8228 Eric void *cookie = NULL; 618 8228 Eric mnttab_node_t *mtn; 619 8228 Eric 620 8228 Eric while (mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie)) { 621 8228 Eric free(mtn->mtn_mt.mnt_special); 622 8228 Eric free(mtn->mtn_mt.mnt_mountp); 623 8228 Eric free(mtn->mtn_mt.mnt_fstype); 624 8228 Eric free(mtn->mtn_mt.mnt_mntopts); 625 8228 Eric free(mtn); 626 8228 Eric } 627 8228 Eric avl_destroy(&hdl->libzfs_mnttab_cache); 628 8228 Eric } 629 8228 Eric 630 8811 Eric void 631 8811 Eric libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable) 632 8811 Eric { 633 8811 Eric hdl->libzfs_mnttab_enable = enable; 634 8811 Eric } 635 8811 Eric 636 8228 Eric int 637 8228 Eric libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname, 638 8228 Eric struct mnttab *entry) 639 8228 Eric { 640 8228 Eric mnttab_node_t find; 641 8228 Eric mnttab_node_t *mtn; 642 8228 Eric 643 8811 Eric if (!hdl->libzfs_mnttab_enable) { 644 8811 Eric struct mnttab srch = { 0 }; 645 8811 Eric 646 8811 Eric if (avl_numnodes(&hdl->libzfs_mnttab_cache)) 647 8811 Eric libzfs_mnttab_fini(hdl); 648 8811 Eric rewind(hdl->libzfs_mnttab); 649 8811 Eric srch.mnt_special = (char *)fsname; 650 8811 Eric srch.mnt_fstype = MNTTYPE_ZFS; 651 8811 Eric if (getmntany(hdl->libzfs_mnttab, entry, &srch) == 0) 652 8811 Eric return (0); 653 8811 Eric else 654 8811 Eric return (ENOENT); 655 8811 Eric } 656 8811 Eric 657 8228 Eric if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) 658 8811 Eric libzfs_mnttab_update(hdl); 659 8228 Eric 660 8228 Eric find.mtn_mt.mnt_special = (char *)fsname; 661 8228 Eric mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL); 662 8228 Eric if (mtn) { 663 8228 Eric *entry = mtn->mtn_mt; 664 8228 Eric return (0); 665 8228 Eric } 666 8228 Eric return (ENOENT); 667 8228 Eric } 668 8228 Eric 669 8228 Eric void 670 8228 Eric libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special, 671 8228 Eric const char *mountp, const char *mntopts) 672 8228 Eric { 673 8228 Eric mnttab_node_t *mtn; 674 8228 Eric 675 8228 Eric if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) 676 8228 Eric return; 677 8228 Eric mtn = zfs_alloc(hdl, sizeof (mnttab_node_t)); 678 8228 Eric mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special); 679 8228 Eric mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp); 680 8228 Eric mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS); 681 8228 Eric mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts); 682 8228 Eric avl_add(&hdl->libzfs_mnttab_cache, mtn); 683 8228 Eric } 684 8228 Eric 685 8228 Eric void 686 8228 Eric libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname) 687 8228 Eric { 688 8228 Eric mnttab_node_t find; 689 8228 Eric mnttab_node_t *ret; 690 8228 Eric 691 8228 Eric find.mtn_mt.mnt_special = (char *)fsname; 692 8228 Eric if (ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL)) { 693 8228 Eric avl_remove(&hdl->libzfs_mnttab_cache, ret); 694 8228 Eric free(ret->mtn_mt.mnt_special); 695 8228 Eric free(ret->mtn_mt.mnt_mountp); 696 8228 Eric free(ret->mtn_mt.mnt_fstype); 697 8228 Eric free(ret->mtn_mt.mnt_mntopts); 698 8228 Eric free(ret); 699 8228 Eric } 700 789 ahrens } 701 3912 lling 702 5713 rm160521 int 703 5713 rm160521 zfs_spa_version(zfs_handle_t *zhp, int *spa_version) 704 5713 rm160521 { 705 6865 rm160521 zpool_handle_t *zpool_handle = zhp->zpool_hdl; 706 6865 rm160521 707 5713 rm160521 if (zpool_handle == NULL) 708 5713 rm160521 return (-1); 709 5713 rm160521 710 5713 rm160521 *spa_version = zpool_get_prop_int(zpool_handle, 711 5713 rm160521 ZPOOL_PROP_VERSION, NULL); 712 5713 rm160521 return (0); 713 5713 rm160521 } 714 5713 rm160521 715 5713 rm160521 /* 716 5713 rm160521 * The choice of reservation property depends on the SPA version. 717 5713 rm160521 */ 718 5713 rm160521 static int 719 5713 rm160521 zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop) 720 5713 rm160521 { 721 5713 rm160521 int spa_version; 722 5713 rm160521 723 5713 rm160521 if (zfs_spa_version(zhp, &spa_version) < 0) 724 5713 rm160521 return (-1); 725 5713 rm160521 726 5713 rm160521 if (spa_version >= SPA_VERSION_REFRESERVATION) 727 5713 rm160521 *resv_prop = ZFS_PROP_REFRESERVATION; 728 5713 rm160521 else 729 5713 rm160521 *resv_prop = ZFS_PROP_RESERVATION; 730 5713 rm160521 731 5713 rm160521 return (0); 732 5713 rm160521 } 733 5713 rm160521 734 3912 lling /* 735 2676 eschrock * Given an nvlist of properties to set, validates that they are correct, and 736 2676 eschrock * parses any numeric properties (index, boolean, etc) if they are specified as 737 2676 eschrock * strings. 738 2676 eschrock */ 739 7184 timh nvlist_t * 740 7184 timh zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl, 741 5094 lling uint64_t zoned, zfs_handle_t *zhp, const char *errbuf) 742 2676 eschrock { 743 2676 eschrock nvpair_t *elem; 744 2676 eschrock uint64_t intval; 745 2676 eschrock char *strval; 746 5094 lling zfs_prop_t prop; 747 2676 eschrock nvlist_t *ret; 748 5331 amw int chosen_normal = -1; 749 5331 amw int chosen_utf = -1; 750 5094 lling 751 2676 eschrock if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) { 752 2676 eschrock (void) no_memory(hdl); 753 2676 eschrock return (NULL); 754 2676 eschrock } 755 2676 eschrock 756 9396 Matthew /* 757 9396 Matthew * Make sure this property is valid and applies to this type. 758 9396 Matthew */ 759 9396 Matthew 760 2676 eschrock elem = NULL; 761 2676 eschrock while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { 762 5094 lling const char *propname = nvpair_name(elem); 763 2676 eschrock 764 9396 Matthew prop = zfs_name_to_prop(propname); 765 9396 Matthew if (prop == ZPROP_INVAL && zfs_prop_user(propname)) { 766 9396 Matthew /* 767 9396 Matthew * This is a user property: make sure it's a 768 5094 lling * string, and that it's less than ZAP_MAXNAMELEN. 769 5094 lling */ 770 5094 lling if (nvpair_type(elem) != DATA_TYPE_STRING) { 771 5094 lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 772 5094 lling "'%s' must be a string"), propname); 773 5094 lling (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 774 5094 lling goto error; 775 5094 lling } 776 5094 lling 777 5094 lling if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) { 778 5094 lling zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 779 5094 lling "property name '%s' is too long"), 780 2676 eschrock propname); 781 2676 eschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 782 2676 eschrock goto error; 783 2676 eschrock } 784 2676 eschrock 785 2676 eschrock (void) nvpair_value_string(elem, &strval); 786 2676 eschrock if (nvlist_add_string(ret, propname, strval) != 0) { 787 2676 eschrock (void) no_memory(hdl); 788 2676 eschrock goto error; 789 2676 eschrock } 790 2676 eschrock continue; 791 7265 ahrens } 792 7265 ahrens 793 9396 Matthew /* 794 9396 Matthew * Currently, only user properties can be modified on 795 9396 Matthew * snapshots. 796 9396 Matthew */ 797 7265 ahrens if (type == ZFS_TYPE_SNAPSHOT) { 798 7265 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 799 7265 ahrens "this property can not be modified for snapshots")); 800 7265 ahrens (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 801 9396 Matthew goto error; 802 9396 Matthew } 803 9396 Matthew 804 9396 Matthew if (prop == ZPROP_INVAL && zfs_prop_userquota(propname)) { 805 9396 Matthew zfs_userquota_prop_t uqtype; 806 9396 Matthew char newpropname[128]; 807 9396 Matthew char domain[128]; 808 9396 Matthew uint64_t rid; 809 9396 Matthew uint64_t valary[3]; 810 9396 Matthew 811 9396 Matthew if (userquota_propname_decode(propname, zoned, 812 9396 Matthew &uqtype, domain, sizeof (domain), &rid) != 0) { 813 9396 Matthew zfs_error_aux(hdl, 814 9396 Matthew dgettext(TEXT_DOMAIN, 815 9396 Matthew "'%s' has an invalid user/group name"), 816 9396 Matthew propname); 817 9396 Matthew (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 818 9396 Matthew goto error; 819 9396 Matthew } 820 9396 Matthew 821 9396 Matthew if (uqtype != ZFS_PROP_USERQUOTA && 822 9396 Matthew uqtype != ZFS_PROP_GROUPQUOTA) { 823 9396 Matthew zfs_error_aux(hdl, 824 9396 Matthew dgettext(TEXT_DOMAIN, "'%s' is readonly"), 825 9396 Matthew propname); 826 9396 Matthew (void) zfs_error(hdl, EZFS_PROPREADONLY, 827 9396 Matthew errbuf); 828 9396 Matthew goto error; 829 9396 Matthew } 830 9396 Matthew 831 9396 Matthew if (nvpair_type(elem) == DATA_TYPE_STRING) { 832 9396 Matthew (void) nvpair_value_string(elem, &strval); 833 9396 Matthew if (strcmp(strval, "none") == 0) { 834 9396 Matthew intval = 0; 835 9396 Matthew } else if (zfs_nicestrtonum(hdl, 836 9396 Matthew strval, &intval) != 0) { 837 9396 Matthew (void) zfs_error(hdl, 838 9396 Matthew EZFS_BADPROP, errbuf); 839 9396 Matthew goto error; 840 9396 Matthew } 841 9396 Matthew } else if (nvpair_type(elem) == 842 9396 Matthew DATA_TYPE_UINT64) { 843 9396 Matthew (void) nvpair_value_uint64(elem, &intval); 844 9396 Matthew if (intval == 0) { 845 9396 Matthew zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 846 9396 Matthew "use 'none' to disable " 847 9396 Matthew "userquota/groupquota")); 848 9396 Matthew goto error; 849 9396 Matthew } 850 9396 Matthew } else { 851 9396 Matthew zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 852 9396 Matthew "'%s' must be a number"), propname); 853 9396 Matthew (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 854 9396 Matthew goto error; 855 9396 Matthew } 856 9396 Matthew 857 10969 Matthew /* 858 10969 Matthew * Encode the prop name as 859 10969 Matthew * userquota@<hex-rid>-domain, to make it easy 860 10969 Matthew * for the kernel to decode. 861 10969 Matthew */ 862 9396 Matthew (void) snprintf(newpropname, sizeof (newpropname), 863 10969 Matthew "%s%llx-%s", zfs_userquota_prop_prefixes[uqtype], 864 10969 Matthew (longlong_t)rid, domain); 865 9396 Matthew valary[0] = uqtype; 866 9396 Matthew valary[1] = rid; 867 9396 Matthew valary[2] = intval; 868 9396 Matthew if (nvlist_add_uint64_array(ret, newpropname, 869 9396 Matthew valary, 3) != 0) { 870 9396 Matthew (void) no_memory(hdl); 871 9396 Matthew goto error; 872 9396 Matthew } 873 9396 Matthew continue; 874 9396 Matthew } 875 9396 Matthew 876 9396 Matthew if (prop == ZPROP_INVAL) { 877 9396 Matthew zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 878 9396 Matthew "invalid property '%s'"), propname); 879 9396 Matthew (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 880 7265 ahrens goto error; 881 2676 eschrock } 882 2676 eschrock 883 2676 eschrock if (!zfs_prop_valid_for_type(prop, type)) { 884 2676 eschrock zfs_error_aux(hdl, 885 2676 eschrock dgettext(TEXT_DOMAIN, "'%s' does not " 886 2676 eschrock "apply to datasets of this type"), propname); 887 2676 eschrock (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf); 888 2676 eschrock goto error; 889 2676 eschrock } 890 2676 eschrock 891 2676 eschrock if (zfs_prop_readonly(prop) && 892 5331 amw (!zfs_prop_setonce(prop) || zhp != NULL)) { 893 2676 eschrock zfs_error_aux(hdl, 894 2676 eschrock dgettext(TEXT_DOMAIN, "'%s' is readonly"), 895 2676 eschrock propname); 896 2676 eschrock (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf); 897 2676 eschrock goto error; 898 2676 eschrock } 899 2676 eschrock 900 5094 lling if (zprop_parse_value(hdl, elem, prop, type, ret, 901 5094 lling &strval, &intval, errbuf) != 0) 902 5094 lling goto error; 903 2676 eschrock 904 2676 eschrock /* 905 2676 eschrock * Perform some additional checks for specific properties. 906 2676 eschrock */ 907 2676 eschrock switch (prop) { 908 4577 ahrens case ZFS_PROP_VERSION: 909 4577 ahrens { 910 4577 ahrens int version; 911 4577 ahrens 912 4577 ahrens if (zhp == NULL) 913 4577 ahrens break; 914 4577 ahrens version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION); 915 4577 ahrens if (intval < version) { 916 4577 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 917 4577 ahrens "Can not downgrade; already at version %u"), 918 4577 ahrens version); 919 4577 ahrens (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 920 4577 ahrens goto error; 921 4577 ahrens } 922 4577 ahrens break; 923 4577 ahrens } 924 4577 ahrens 925 2676 eschrock case ZFS_PROP_RECORDSIZE: 926 2676 eschrock case ZFS_PROP_VOLBLOCKSIZE: 927 2676 eschrock /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */ 928 2676 eschrock if (intval < SPA_MINBLOCKSIZE || 929 2676 eschrock intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) { 930 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 931 2676 eschrock "'%s' must be power of 2 from %u " 932 2676 eschrock "to %uk"), propname, 933 789 ahrens (uint_t)SPA_MINBLOCKSIZE, 934 789 ahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 935 2676 eschrock (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 936 2676 eschrock goto error; 937 2676 eschrock } 938 2676 eschrock break; 939 2676 eschrock 940 3126 ahl case ZFS_PROP_SHAREISCSI: 941 3126 ahl if (strcmp(strval, "off") != 0 && 942 3126 ahl strcmp(strval, "on") != 0 && 943 3126 ahl strcmp(strval, "type=disk") != 0) { 944 3126 ahl zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 945 3126 ahl "'%s' must be 'on', 'off', or 'type=disk'"), 946 3126 ahl propname); 947 3126 ahl (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 948 3126 ahl goto error; 949 3126 ahl } 950 3126 ahl 951 3126 ahl break; 952 10972 Ric 953 10972 Ric case ZFS_PROP_MLSLABEL: 954 10972 Ric { 955 10972 Ric /* 956 10972 Ric * Verify the mlslabel string and convert to 957 10972 Ric * internal hex label string. 958 10972 Ric */ 959 10972 Ric 960 10972 Ric m_label_t *new_sl; 961 10972 Ric char *hex = NULL; /* internal label string */ 962 10972 Ric 963 10972 Ric /* Default value is already OK. */ 964 10972 Ric if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0) 965 10972 Ric break; 966 10972 Ric 967 10972 Ric /* Verify the label can be converted to binary form */ 968 10972 Ric if (((new_sl = m_label_alloc(MAC_LABEL)) == NULL) || 969 10972 Ric (str_to_label(strval, &new_sl, MAC_LABEL, 970 10972 Ric L_NO_CORRECTION, NULL) == -1)) { 971 10972 Ric goto badlabel; 972 10972 Ric } 973 10972 Ric 974 10972 Ric /* Now translate to hex internal label string */ 975 10972 Ric if (label_to_str(new_sl, &hex, M_INTERNAL, 976 10972 Ric DEF_NAMES) != 0) { 977 10972 Ric if (hex) 978 10972 Ric free(hex); 979 10972 Ric goto badlabel; 980 10972 Ric } 981 10972 Ric m_label_free(new_sl); 982 10972 Ric 983 10972 Ric /* If string is already in internal form, we're done. */ 984 10972 Ric if (strcmp(strval, hex) == 0) { 985 10972 Ric free(hex); 986 10972 Ric break; 987 10972 Ric } 988 10972 Ric 989 10972 Ric /* Replace the label string with the internal form. */ 990 10984 Ric (void) nvlist_remove(ret, zfs_prop_to_name(prop), 991 10972 Ric DATA_TYPE_STRING); 992 10972 Ric verify(nvlist_add_string(ret, zfs_prop_to_name(prop), 993 10972 Ric hex) == 0); 994 10972 Ric free(hex); 995 10972 Ric 996 10972 Ric break; 997 10972 Ric 998 10972 Ric badlabel: 999 10972 Ric zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1000 10972 Ric "invalid mlslabel '%s'"), strval); 1001 10972 Ric (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 1002 10972 Ric m_label_free(new_sl); /* OK if null */ 1003 10972 Ric goto error; 1004 10972 Ric 1005 10972 Ric } 1006 3126 ahl 1007 2676 eschrock case ZFS_PROP_MOUNTPOINT: 1008 4778 rm160521 { 1009 4778 rm160521 namecheck_err_t why; 1010 4778 rm160521 1011 2676 eschrock if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 || 1012 2676 eschrock strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0) 1013 2676 eschrock break; 1014 2676 eschrock 1015 4778 rm160521 if (mountpoint_namecheck(strval, &why)) { 1016 4778 rm160521 switch (why) { 1017 4778 rm160521 case NAME_ERR_LEADING_SLASH: 1018 4778 rm160521 zfs_error_aux(hdl, 1019 4778 rm160521 dgettext(TEXT_DOMAIN, 1020 4778 rm160521 "'%s' must be an absolute path, " 1021 4778 rm160521 "'none', or 'legacy'"), propname); 1022 4778 rm160521 break; 1023 4778 rm160521 case NAME_ERR_TOOLONG: 1024 4778 rm160521 zfs_error_aux(hdl, 1025 4778 rm160521 dgettext(TEXT_DOMAIN, 1026 4778 rm160521 "component of '%s' is too long"), 1027 4778 rm160521 propname); 1028 4778 rm160521 break; 1029 4778 rm160521 } 1030 4778 rm160521 (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 1031 4778 rm160521 goto error; 1032 4778 rm160521 } 1033 4778 rm160521 } 1034 4778 rm160521 1035 3126 ahl /*FALLTHRU*/ 1036 2676 eschrock 1037 5331 amw case ZFS_PROP_SHARESMB: 1038 3126 ahl case ZFS_PROP_SHARENFS: 1039 3126 ahl /* 1040 5331 amw * For the mountpoint and sharenfs or sharesmb 1041 5331 amw * properties, check if it can be set in a 1042 5331 amw * global/non-global zone based on 1043 3126 ahl * the zoned property value: 1044 3126 ahl * 1045 3126 ahl * global zone non-global zone 1046 3126 ahl * -------------------------------------------------- 1047 3126 ahl * zoned=on mountpoint (no) mountpoint (yes) 1048 3126 ahl * sharenfs (no) sharenfs (no) 1049 5331 amw * sharesmb (no) sharesmb (no) 1050 3126 ahl * 1051 3126 ahl * zoned=off mountpoint (yes) N/A 1052 3126 ahl * sharenfs (yes) 1053 5331 amw * sharesmb (yes) 1054 3126 ahl */ 1055 2676 eschrock if (zoned) { 1056 2676 eschrock if (getzoneid() == GLOBAL_ZONEID) { 1057 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1058 2676 eschrock "'%s' cannot be set on " 1059 2676 eschrock "dataset in a non-global zone"), 1060 2676 eschrock propname); 1061 2676 eschrock (void) zfs_error(hdl, EZFS_ZONED, 1062 2676 eschrock errbuf); 1063 2676 eschrock goto error; 1064 5331 amw } else if (prop == ZFS_PROP_SHARENFS || 1065 5331 amw prop == ZFS_PROP_SHARESMB) { 1066 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1067 2676 eschrock "'%s' cannot be set in " 1068 2676 eschrock "a non-global zone"), propname); 1069 2676 eschrock (void) zfs_error(hdl, EZFS_ZONED, 1070 2676 eschrock errbuf); 1071 2676 eschrock goto error; 1072 2676 eschrock } 1073 2676 eschrock } else if (getzoneid() != GLOBAL_ZONEID) { 1074 2676 eschrock /* 1075 2676 eschrock * If zoned property is 'off', this must be in 1076 9396 Matthew * a global zone. If not, something is wrong. 1077 2676 eschrock */ 1078 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1079 2676 eschrock "'%s' cannot be set while dataset " 1080 2676 eschrock "'zoned' property is set"), propname); 1081 2676 eschrock (void) zfs_error(hdl, EZFS_ZONED, errbuf); 1082 2676 eschrock goto error; 1083 4180 dougm } 1084 4180 dougm 1085 4180 dougm /* 1086 4180 dougm * At this point, it is legitimate to set the 1087 4180 dougm * property. Now we want to make sure that the 1088 4180 dougm * property value is valid if it is sharenfs. 1089 4180 dougm */ 1090 5331 amw if ((prop == ZFS_PROP_SHARENFS || 1091 5331 amw prop == ZFS_PROP_SHARESMB) && 1092 4217 eschrock strcmp(strval, "on") != 0 && 1093 4217 eschrock strcmp(strval, "off") != 0) { 1094 5331 amw zfs_share_proto_t proto; 1095 5331 amw 1096 5331 amw if (prop == ZFS_PROP_SHARESMB) 1097 5331 amw proto = PROTO_SMB; 1098 5331 amw else 1099 5331 amw proto = PROTO_NFS; 1100 4180 dougm 1101 4180 dougm /* 1102 5331 amw * Must be an valid sharing protocol 1103 5331 amw * option string so init the libshare 1104 5331 amw * in order to enable the parser and 1105 5331 amw * then parse the options. We use the 1106 5331 amw * control API since we don't care about 1107 5331 amw * the current configuration and don't 1108 4180 dougm * want the overhead of loading it 1109 4180 dougm * until we actually do something. 1110 4180 dougm */ 1111 4180 dougm 1112 4217 eschrock if (zfs_init_libshare(hdl, 1113 4217 eschrock SA_INIT_CONTROL_API) != SA_OK) { 1114 4217 eschrock /* 1115 4217 eschrock * An error occurred so we can't do 1116 4217 eschrock * anything 1117 4217 eschrock */ 1118 4217 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1119 4217 eschrock "'%s' cannot be set: problem " 1120 4217 eschrock "in share initialization"), 1121 4217 eschrock propname); 1122 4217 eschrock (void) zfs_error(hdl, EZFS_BADPROP, 1123 4217 eschrock errbuf); 1124 4217 eschrock goto error; 1125 4217 eschrock } 1126 4180 dougm 1127 5331 amw if (zfs_parse_options(strval, proto) != SA_OK) { 1128 4217 eschrock /* 1129 4217 eschrock * There was an error in parsing so 1130 4217 eschrock * deal with it by issuing an error 1131 4217 eschrock * message and leaving after 1132 4217 eschrock * uninitializing the the libshare 1133 4217 eschrock * interface. 1134 4217 eschrock */ 1135 4217 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1136 4217 eschrock "'%s' cannot be set to invalid " 1137 4217 eschrock "options"), propname); 1138 4217 eschrock (void) zfs_error(hdl, EZFS_BADPROP, 1139 4217 eschrock errbuf); 1140 4217 eschrock zfs_uninit_libshare(hdl); 1141 4217 eschrock goto error; 1142 4217 eschrock } 1143 4180 dougm zfs_uninit_libshare(hdl); 1144 789 ahrens } 1145 3126 ahl 1146 3126 ahl break; 1147 5331 amw case ZFS_PROP_UTF8ONLY: 1148 5331 amw chosen_utf = (int)intval; 1149 5331 amw break; 1150 5331 amw case ZFS_PROP_NORMALIZE: 1151 5331 amw chosen_normal = (int)intval; 1152 5331 amw break; 1153 789 ahrens } 1154 789 ahrens 1155 2676 eschrock /* 1156 2676 eschrock * For changes to existing volumes, we have some additional 1157 2676 eschrock * checks to enforce. 1158 2676 eschrock */ 1159 2676 eschrock if (type == ZFS_TYPE_VOLUME && zhp != NULL) { 1160 2676 eschrock uint64_t volsize = zfs_prop_get_int(zhp, 1161 2676 eschrock ZFS_PROP_VOLSIZE); 1162 2676 eschrock uint64_t blocksize = zfs_prop_get_int(zhp, 1163 2676 eschrock ZFS_PROP_VOLBLOCKSIZE); 1164 2676 eschrock char buf[64]; 1165 789 ahrens 1166 2676 eschrock switch (prop) { 1167 2676 eschrock case ZFS_PROP_RESERVATION: 1168 5378 ck153898 case ZFS_PROP_REFRESERVATION: 1169 2676 eschrock if (intval > volsize) { 1170 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1171 2676 eschrock "'%s' is greater than current " 1172 2676 eschrock "volume size"), propname); 1173 2676 eschrock (void) zfs_error(hdl, EZFS_BADPROP, 1174 2676 eschrock errbuf); 1175 2676 eschrock goto error; 1176 2676 eschrock } 1177 789 ahrens break; 1178 789 ahrens 1179 2676 eschrock case ZFS_PROP_VOLSIZE: 1180 2676 eschrock if (intval % blocksize != 0) { 1181 2676 eschrock zfs_nicenum(blocksize, buf, 1182 2676 eschrock sizeof (buf)); 1183 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1184 2676 eschrock "'%s' must be a multiple of " 1185 2676 eschrock "volume block size (%s)"), 1186 2676 eschrock propname, buf); 1187 2676 eschrock (void) zfs_error(hdl, EZFS_BADPROP, 1188 2676 eschrock errbuf); 1189 2676 eschrock goto error; 1190 2676 eschrock } 1191 789 ahrens 1192 2676 eschrock if (intval == 0) { 1193 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1194 2676 eschrock "'%s' cannot be zero"), 1195 2676 eschrock propname); 1196 2676 eschrock (void) zfs_error(hdl, EZFS_BADPROP, 1197 2676 eschrock errbuf); 1198 2676 eschrock goto error; 1199 789 ahrens } 1200 3126 ahl break; 1201 789 ahrens } 1202 789 ahrens } 1203 5375 timh } 1204 5375 timh 1205 5375 timh /* 1206 5331 amw * If normalization was chosen, but no UTF8 choice was made, 1207 5331 amw * enforce rejection of non-UTF8 names. 1208 5331 amw * 1209 5331 amw * If normalization was chosen, but rejecting non-UTF8 names 1210 5331 amw * was explicitly not chosen, it is an error. 1211 5331 amw */ 1212 5498 timh if (chosen_normal > 0 && chosen_utf < 0) { 1213 5331 amw if (nvlist_add_uint64(ret, 1214 5331 amw zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) { 1215 5331 amw (void) no_memory(hdl); 1216 5331 amw goto error; 1217 5331 amw } 1218 5498 timh } else if (chosen_normal > 0 && chosen_utf == 0) { 1219 5331 amw zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1220 5331 amw "'%s' must be set 'on' if normalization chosen"), 1221 5331 amw zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); 1222 5331 amw (void) zfs_error(hdl, EZFS_BADPROP, errbuf); 1223 5331 amw goto error; 1224 789 ahrens } 1225 789 ahrens 1226 2676 eschrock /* 1227 2676 eschrock * If this is an existing volume, and someone is setting the volsize, 1228 2676 eschrock * make sure that it matches the reservation, or add it if necessary. 1229 2676 eschrock */ 1230 2676 eschrock if (zhp != NULL && type == ZFS_TYPE_VOLUME && 1231 2676 eschrock nvlist_lookup_uint64(ret, zfs_prop_to_name(ZFS_PROP_VOLSIZE), 1232 2676 eschrock &intval) == 0) { 1233 2676 eschrock uint64_t old_volsize = zfs_prop_get_int(zhp, 1234 2676 eschrock ZFS_PROP_VOLSIZE); 1235 5481 ck153898 uint64_t old_reservation; 1236 2676 eschrock uint64_t new_reservation; 1237 5481 ck153898 zfs_prop_t resv_prop; 1238 5713 rm160521 1239 5713 rm160521 if (zfs_which_resv_prop(zhp, &resv_prop) < 0) 1240 5713 rm160521 goto error; 1241 5481 ck153898 old_reservation = zfs_prop_get_int(zhp, resv_prop); 1242 789 ahrens 1243 2676 eschrock if (old_volsize == old_reservation && 1244 5481 ck153898 nvlist_lookup_uint64(ret, zfs_prop_to_name(resv_prop), 1245 2676 eschrock &new_reservation) != 0) { 1246 2676 eschrock if (nvlist_add_uint64(ret, 1247 5481 ck153898 zfs_prop_to_name(resv_prop), intval) != 0) { 1248 2676 eschrock (void) no_memory(hdl); 1249 2676 eschrock goto error; 1250 2676 eschrock } 1251 2676 eschrock } 1252 2676 eschrock } 1253 2676 eschrock return (ret); 1254 2676 eschrock 1255 2676 eschrock error: 1256 2676 eschrock nvlist_free(ret); 1257 2676 eschrock return (NULL); 1258 789 ahrens } 1259 789 ahrens 1260 11022 Tom void 1261 11022 Tom zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err, 1262 11022 Tom char *errbuf) 1263 11022 Tom { 1264 11022 Tom switch (err) { 1265 11022 Tom 1266 11022 Tom case ENOSPC: 1267 11022 Tom /* 1268 11022 Tom * For quotas and reservations, ENOSPC indicates 1269 11022 Tom * something different; setting a quota or reservation 1270 11022 Tom * doesn't use any disk space. 1271 11022 Tom */ 1272 11022 Tom switch (prop) { 1273 11022 Tom case ZFS_PROP_QUOTA: 1274 11022 Tom case ZFS_PROP_REFQUOTA: 1275 11022 Tom zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1276 11022 Tom "size is less than current used or " 1277 11022 Tom "reserved space")); 1278 11022 Tom (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1279 11022 Tom break; 1280 11022 Tom 1281 11022 Tom case ZFS_PROP_RESERVATION: 1282 11022 Tom case ZFS_PROP_REFRESERVATION: 1283 11022 Tom zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1284 11022 Tom "size is greater than available space")); 1285 11022 Tom (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf); 1286 11022 Tom break; 1287 11022 Tom 1288 11022 Tom default: 1289 11022 Tom (void) zfs_standard_error(hdl, err, errbuf); 1290 11022 Tom break; 1291 11022 Tom } 1292 11022 Tom break; 1293 11022 Tom 1294 11022 Tom case EBUSY: 1295 11022 Tom (void) zfs_standard_error(hdl, EBUSY, errbuf); 1296 11022 Tom break; 1297 11022 Tom 1298 11022 Tom case EROFS: 1299 11022 Tom (void) zfs_error(hdl, EZFS_DSREADONLY, errbuf); 1300 11022 Tom break; 1301 11022 Tom 1302 11022 Tom case ENOTSUP: 1303 11022 Tom zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1304 11022 Tom "pool and or dataset must be upgraded to set this " 1305 11022 Tom "property or value")); 1306 11022 Tom (void) zfs_error(hdl, EZFS_BADVERSION, errbuf); 1307 11022 Tom break; 1308 11022 Tom 1309 11022 Tom case ERANGE: 1310 11022 Tom if (prop == ZFS_PROP_COMPRESSION) { 1311 11022 Tom (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1312 11022 Tom "property setting is not allowed on " 1313 11022 Tom "bootable datasets")); 1314 11022 Tom (void) zfs_error(hdl, EZFS_NOTSUP, errbuf); 1315 11022 Tom } else { 1316 11022 Tom (void) zfs_standard_error(hdl, err, errbuf); 1317 11022 Tom } 1318 11022 Tom break; 1319 11022 Tom 1320 11022 Tom case EOVERFLOW: 1321 11022 Tom /* 1322 11022 Tom * This platform can't address a volume this big. 1323 11022 Tom */ 1324 11022 Tom #ifdef _ILP32 1325 11022 Tom if (prop == ZFS_PROP_VOLSIZE) { 1326 11022 Tom (void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf); 1327 11022 Tom break; 1328 11022 Tom } 1329 11022 Tom #endif 1330 11022 Tom /* FALLTHROUGH */ 1331 11022 Tom default: 1332 11022 Tom (void) zfs_standard_error(hdl, err, errbuf); 1333 11022 Tom } 1334 11022 Tom } 1335 11022 Tom 1336 789 ahrens /* 1337 789 ahrens * Given a property name and value, set the property for the given dataset. 1338 789 ahrens */ 1339 789 ahrens int 1340 2676 eschrock zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval) 1341 789 ahrens { 1342 789 ahrens zfs_cmd_t zc = { 0 }; 1343 2676 eschrock int ret = -1; 1344 2676 eschrock prop_changelist_t *cl = NULL; 1345 2082 eschrock char errbuf[1024]; 1346 2082 eschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 1347 2676 eschrock nvlist_t *nvl = NULL, *realprops; 1348 2676 eschrock zfs_prop_t prop; 1349 7509 Mark boolean_t do_prefix; 1350 7509 Mark uint64_t idx; 1351 2082 eschrock 1352 2082 eschrock (void) snprintf(errbuf, sizeof (errbuf), 1353 2676 eschrock dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), 1354 2082 eschrock zhp->zfs_name); 1355 789 ahrens 1356 2676 eschrock if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || 1357 2676 eschrock nvlist_add_string(nvl, propname, propval) != 0) { 1358 2676 eschrock (void) no_memory(hdl); 1359 2676 eschrock goto error; 1360 789 ahrens } 1361 789 ahrens 1362 7184 timh if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl, 1363 2676 eschrock zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL) 1364 2676 eschrock goto error; 1365 5094 lling 1366 2676 eschrock nvlist_free(nvl); 1367 2676 eschrock nvl = realprops; 1368 2676 eschrock 1369 2676 eschrock prop = zfs_name_to_prop(propname); 1370 2676 eschrock 1371 7366 Tim if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL) 1372 2676 eschrock goto error; 1373 789 ahrens 1374 789 ahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 1375 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1376 2082 eschrock "child dataset with inherited mountpoint is used " 1377 2082 eschrock "in a non-global zone")); 1378 2082 eschrock ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1379 789 ahrens goto error; 1380 789 ahrens } 1381 789 ahrens 1382 7509 Mark /* 1383 7509 Mark * If the dataset's canmount property is being set to noauto, 1384 7509 Mark * then we want to prevent unmounting & remounting it. 1385 7509 Mark */ 1386 7509 Mark do_prefix = !((prop == ZFS_PROP_CANMOUNT) && 1387 7509 Mark (zprop_string_to_index(prop, propval, &idx, 1388 7509 Mark ZFS_TYPE_DATASET) == 0) && (idx == ZFS_CANMOUNT_NOAUTO)); 1389 6168 hs24103 1390 6168 hs24103 if (do_prefix && (ret = changelist_prefix(cl)) != 0) 1391 7509 Mark goto error; 1392 789 ahrens 1393 789 ahrens /* 1394 789 ahrens * Execute the corresponding ioctl() to set this property. 1395 789 ahrens */ 1396 789 ahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1397 789 ahrens 1398 5094 lling if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0) 1399 2676 eschrock goto error; 1400 2676 eschrock 1401 4543 marks ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc); 1402 8845 amw 1403 789 ahrens if (ret != 0) { 1404 11022 Tom zfs_setprop_error(hdl, prop, errno, errbuf); 1405 789 ahrens } else { 1406 6168 hs24103 if (do_prefix) 1407 6168 hs24103 ret = changelist_postfix(cl); 1408 6168 hs24103 1409 789 ahrens /* 1410 789 ahrens * Refresh the statistics so the new property value 1411 789 ahrens * is reflected. 1412 789 ahrens */ 1413 6168 hs24103 if (ret == 0) 1414 2676 eschrock (void) get_stats(zhp); 1415 789 ahrens } 1416 789 ahrens 1417 789 ahrens error: 1418 2676 eschrock nvlist_free(nvl); 1419 2676 eschrock zcmd_free_nvlists(&zc); 1420 2676 eschrock if (cl) 1421 2676 eschrock changelist_free(cl); 1422 789 ahrens return (ret); 1423 789 ahrens } 1424 789 ahrens 1425 789 ahrens /* 1426 11022 Tom * Given a property, inherit the value from the parent dataset, or if received 1427 11022 Tom * is TRUE, revert to the received value, if any. 1428 11022 Tom */ 1429 11022 Tom int 1430 11022 Tom zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received) 1431 789 ahrens { 1432 789 ahrens zfs_cmd_t zc = { 0 }; 1433 789 ahrens int ret; 1434 789 ahrens prop_changelist_t *cl; 1435 2082 eschrock libzfs_handle_t *hdl = zhp->zfs_hdl; 1436 2082 eschrock char errbuf[1024]; 1437 2676 eschrock zfs_prop_t prop; 1438 2082 eschrock 1439 2082 eschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 1440 2082 eschrock "cannot inherit %s for '%s'"), propname, zhp->zfs_name); 1441 2676 eschrock 1442 11022 Tom zc.zc_cookie = received; 1443 5094 lling if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) { 1444 2676 eschrock /* 1445 2676 eschrock * For user properties, the amount of work we have to do is very 1446 2676 eschrock * small, so just do it here. 1447 2676 eschrock */ 1448 2676 eschrock if (!zfs_prop_user(propname)) { 1449 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1450 2676 eschrock "invalid property")); 1451 2676 eschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 1452 2676 eschrock } 1453 2676 eschrock 1454 2676 eschrock (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1455 2676 eschrock (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 1456 2676 eschrock 1457 4849 ahrens if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0) 1458 2676 eschrock return (zfs_standard_error(hdl, errno, errbuf)); 1459 2676 eschrock 1460 2676 eschrock return (0); 1461 2676 eschrock } 1462 789 ahrens 1463 789 ahrens /* 1464 789 ahrens * Verify that this property is inheritable. 1465 789 ahrens */ 1466 2082 eschrock if (zfs_prop_readonly(prop)) 1467 2082 eschrock return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf)); 1468 789 ahrens 1469 11022 Tom if (!zfs_prop_inheritable(prop) && !received) 1470 2082 eschrock return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf)); 1471 789 ahrens 1472 789 ahrens /* 1473 789 ahrens * Check to see if the value applies to this type 1474 789 ahrens */ 1475 2082 eschrock if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1476 2082 eschrock return (zfs_error(hdl, EZFS_PROPTYPE, errbuf)); 1477 789 ahrens 1478 3443 rm160521 /* 1479 3443 rm160521 * Normalize the name, to get rid of shorthand abbrevations. 1480 3443 rm160521 */ 1481 3443 rm160521 propname = zfs_prop_to_name(prop); 1482 789 ahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1483 2676 eschrock (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value)); 1484 789 ahrens 1485 789 ahrens if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID && 1486 789 ahrens zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) { 1487 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1488 2082 eschrock "dataset is used in a non-global zone")); 1489 2082 eschrock return (zfs_error(hdl, EZFS_ZONED, errbuf)); 1490 789 ahrens } 1491 789 ahrens 1492 789 ahrens /* 1493 789 ahrens * Determine datasets which will be affected by this change, if any. 1494 789 ahrens */ 1495 7366 Tim if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL) 1496 789 ahrens return (-1); 1497 789 ahrens 1498 789 ahrens if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) { 1499 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 1500 2082 eschrock "child dataset with inherited mountpoint is used " 1501 2082 eschrock "in a non-global zone")); 1502 2082 eschrock ret = zfs_error(hdl, EZFS_ZONED, errbuf); 1503 789 ahrens goto error; 1504 789 ahrens } 1505 789 ahrens 1506 789 ahrens if ((ret = changelist_prefix(cl)) != 0) 1507 789 ahrens goto error; 1508 789 ahrens 1509 4849 ahrens if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc)) != 0) { 1510 2082 eschrock return (zfs_standard_error(hdl, errno, errbuf)); 1511 789 ahrens } else { 1512 789 ahrens 1513 2169 nd150628 if ((ret = changelist_postfix(cl)) != 0) 1514 789 ahrens goto error; 1515 789 ahrens 1516 789 ahrens /* 1517 789 ahrens * Refresh the statistics so the new property is reflected. 1518 789 ahrens */ 1519 789 ahrens (void) get_stats(zhp); 1520 789 ahrens } 1521 789 ahrens 1522 789 ahrens error: 1523 789 ahrens changelist_free(cl); 1524 789 ahrens return (ret); 1525 789 ahrens } 1526 789 ahrens 1527 789 ahrens /* 1528 1356 eschrock * True DSL properties are stored in an nvlist. The following two functions 1529 1356 eschrock * extract them appropriately. 1530 1356 eschrock */ 1531 1356 eschrock static uint64_t 1532 1356 eschrock getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 1533 1356 eschrock { 1534 1356 eschrock nvlist_t *nv; 1535 1356 eschrock uint64_t value; 1536 1356 eschrock 1537 2885 ahrens *source = NULL; 1538 1356 eschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 1539 1356 eschrock zfs_prop_to_name(prop), &nv) == 0) { 1540 5094 lling verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0); 1541 5094 lling (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source); 1542 1356 eschrock } else { 1543 8802 Sanjeev verify(!zhp->zfs_props_table || 1544 8802 Sanjeev zhp->zfs_props_table[prop] == B_TRUE); 1545 1356 eschrock value = zfs_prop_default_numeric(prop); 1546 1356 eschrock *source = ""; 1547 1356 eschrock } 1548 1356 eschrock 1549 1356 eschrock return (value); 1550 1356 eschrock } 1551 1356 eschrock 1552 1356 eschrock static char * 1553 1356 eschrock getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source) 1554 1356 eschrock { 1555 1356 eschrock nvlist_t *nv; 1556 1356 eschrock char *value; 1557 1356 eschrock 1558 2885 ahrens *source = NULL; 1559 1356 eschrock if (nvlist_lookup_nvlist(zhp->zfs_props, 1560 1356 eschrock zfs_prop_to_name(prop), &nv) == 0) { 1561 5094 lling verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0); 1562 5094 lling (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source); 1563 1356 eschrock } else { 1564 8802 Sanjeev verify(!zhp->zfs_props_table || 1565 8802 Sanjeev zhp->zfs_props_table[prop] == B_TRUE); 1566 1356 eschrock if ((value = (char *)zfs_prop_default_string(prop)) == NULL) 1567 1356 eschrock value = ""; 1568 1356 eschrock *source = ""; 1569 1356 eschrock } 1570 1356 eschrock 1571 1356 eschrock return (value); 1572 1356 eschrock } 1573 1356 eschrock 1574 11022 Tom static boolean_t 1575 11022 Tom zfs_is_recvd_props_mode(zfs_handle_t *zhp) 1576 11022 Tom { 1577 11022 Tom return (zhp->zfs_props == zhp->zfs_recvd_props); 1578 11022 Tom } 1579 11022 Tom 1580 11022 Tom static void 1581 11022 Tom zfs_set_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie) 1582 11022 Tom { 1583 11022 Tom *cookie = (uint64_t)(uintptr_t)zhp->zfs_props; 1584 11022 Tom zhp->zfs_props = zhp->zfs_recvd_props; 1585 11022 Tom } 1586 11022 Tom 1587 11022 Tom static void 1588 11022 Tom zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie) 1589 11022 Tom { 1590 11022 Tom zhp->zfs_props = (nvlist_t *)(uintptr_t)*cookie; 1591 11022 Tom *cookie = 0; 1592 11022 Tom } 1593 11022 Tom 1594 1356 eschrock /* 1595 789 ahrens * Internal function for getting a numeric property. Both zfs_prop_get() and 1596 789 ahrens * zfs_prop_get_int() are built using this interface. 1597 789 ahrens * 1598 789 ahrens * Certain properties can be overridden using 'mount -o'. In this case, scan 1599 789 ahrens * the contents of the /etc/mnttab entry, searching for the appropriate options. 1600 789 ahrens * If they differ from the on-disk values, report the current values and mark 1601 789 ahrens * the source "temporary". 1602 789 ahrens */ 1603 2082 eschrock static int 1604 5094 lling get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src, 1605 2082 eschrock char **source, uint64_t *val) 1606 789 ahrens { 1607 5147 rm160521 zfs_cmd_t zc = { 0 }; 1608 5592 timh nvlist_t *zplprops = NULL; 1609 789 ahrens struct mnttab mnt; 1610 3265 ahrens char *mntopt_on = NULL; 1611 3265 ahrens char *mntopt_off = NULL; 1612 11022 Tom boolean_t received = zfs_is_recvd_props_mode(zhp); 1613 789 ahrens 1614 789 ahrens *source = NULL; 1615 3265 ahrens 1616 3265 ahrens switch (prop) { 1617 3265 ahrens case ZFS_PROP_ATIME: 1618 3265 ahrens mntopt_on = MNTOPT_ATIME; 1619 3265 ahrens mntopt_off = MNTOPT_NOATIME; 1620 3265 ahrens break; 1621 3265 ahrens 1622 3265 ahrens case ZFS_PROP_DEVICES: 1623 3265 ahrens mntopt_on = MNTOPT_DEVICES; 1624 3265 ahrens mntopt_off = MNTOPT_NODEVICES; 1625 3265 ahrens break; 1626 3265 ahrens 1627 3265 ahrens case ZFS_PROP_EXEC: 1628 3265 ahrens mntopt_on = MNTOPT_EXEC; 1629 3265 ahrens mntopt_off = MNTOPT_NOEXEC; 1630 3265 ahrens break; 1631 3265 ahrens 1632 3265 ahrens case ZFS_PROP_READONLY: 1633 3265 ahrens mntopt_on = MNTOPT_RO; 1634 3265 ahrens mntopt_off = MNTOPT_RW; 1635 3265 ahrens break; 1636 3265 ahrens 1637 3265 ahrens case ZFS_PROP_SETUID: 1638 3265 ahrens mntopt_on = MNTOPT_SETUID; 1639 3265 ahrens mntopt_off = MNTOPT_NOSETUID; 1640 3265 ahrens break; 1641 3265 ahrens 1642 3265 ahrens case ZFS_PROP_XATTR: 1643 3265 ahrens mntopt_on = MNTOPT_XATTR; 1644 3265 ahrens mntopt_off = MNTOPT_NOXATTR; 1645 3265 ahrens break; 1646 5331 amw 1647 5331 amw case ZFS_PROP_NBMAND: 1648 5331 amw mntopt_on = MNTOPT_NBMAND; 1649 5331 amw mntopt_off = MNTOPT_NONBMAND; 1650 5331 amw break; 1651 3265 ahrens } 1652 789 ahrens 1653 2474 eschrock /* 1654 2474 eschrock * Because looking up the mount options is potentially expensive 1655 2474 eschrock * (iterating over all of /etc/mnttab), we defer its calculation until 1656 2474 eschrock * we're looking up a property which requires its presence. 1657 2474 eschrock */ 1658 2474 eschrock if (!zhp->zfs_mntcheck && 1659 3265 ahrens (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { 1660 8228 Eric libzfs_handle_t *hdl = zhp->zfs_hdl; 1661 8228 Eric struct mnttab entry; 1662 8228 Eric 1663 8228 Eric if (libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0) { 1664 8228 Eric zhp->zfs_mntopts = zfs_strdup(hdl, 1665 3265 ahrens entry.mnt_mntopts); 1666 3265 ahrens if (zhp->zfs_mntopts == NULL) 1667 3265 ahrens return (-1); 1668 3265 ahrens } 1669 2474 eschrock 1670 2474 eschrock zhp->zfs_mntcheck = B_TRUE; 1671 2474 eschrock } 1672 2474 eschrock 1673 789 ahrens if (zhp->zfs_mntopts == NULL) 1674 789 ahrens mnt.mnt_mntopts = ""; 1675 789 ahrens else 1676 789 ahrens mnt.mnt_mntopts = zhp->zfs_mntopts; 1677 789 ahrens 1678 789 ahrens switch (prop) { 1679 789 ahrens case ZFS_PROP_ATIME: 1680 3265 ahrens case ZFS_PROP_DEVICES: 1681 3265 ahrens case ZFS_PROP_EXEC: 1682 3265 ahrens case ZFS_PROP_READONLY: 1683 3265 ahrens case ZFS_PROP_SETUID: 1684 3265 ahrens case ZFS_PROP_XATTR: 1685 5331 amw case ZFS_PROP_NBMAND: 1686 2082 eschrock *val = getprop_uint64(zhp, prop, source); 1687 789 ahrens 1688 11022 Tom if (received) 1689 11022 Tom break; 1690 11022 Tom 1691 3265 ahrens if (hasmntopt(&mnt, mntopt_on) && !*val) { 1692 2082 eschrock *val = B_TRUE; 1693 789 ahrens if (src) 1694 5094 lling *src = ZPROP_SRC_TEMPORARY; 1695 3265 ahrens } else if (hasmntopt(&mnt, mntopt_off) && *val) { 1696 2082 eschrock *val = B_FALSE; 1697 789 ahrens if (src) 1698 5094 lling *src = ZPROP_SRC_TEMPORARY; 1699 789 ahrens } 1700 2082 eschrock break; 1701 789 ahrens 1702 3265 ahrens case ZFS_PROP_CANMOUNT: 1703 789 ahrens case ZFS_PROP_QUOTA: 1704 5378 ck153898 case ZFS_PROP_REFQUOTA: 1705 2885 ahrens case ZFS_PROP_RESERVATION: 1706 5378 ck153898 case ZFS_PROP_REFRESERVATION: 1707 2885 ahrens *val = getprop_uint64(zhp, prop, source); 1708 11022 Tom 1709 11022 Tom if (*source == NULL) { 1710 11022 Tom /* not default, must be local */ 1711 789 ahrens *source = zhp->zfs_name; 1712 11022 Tom } 1713 2082 eschrock break; 1714 789 ahrens 1715 789 ahrens case ZFS_PROP_MOUNTED: 1716 2082 eschrock *val = (zhp->zfs_mntopts != NULL); 1717 3234 ck153898 break; 1718 3234 ck153898 1719 3377 eschrock case ZFS_PROP_NUMCLONES: 1720 3377 eschrock *val = zhp->zfs_dmustats.dds_num_clones; 1721 5147 rm160521 break; 1722 5147 rm160521 1723 5147 rm160521 case ZFS_PROP_VERSION: 1724 5498 timh case ZFS_PROP_NORMALIZE: 1725 5498 timh case ZFS_PROP_UTF8ONLY: 1726 5498 timh case ZFS_PROP_CASE: 1727 5498 timh if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) || 1728 5498 timh zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 1729 5473 rm160521 return (-1); 1730 5147 rm160521 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 1731 5498 timh if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) { 1732 5498 timh zcmd_free_nvlists(&zc); 1733 10204 Matthew return (-1); 1734 5147 rm160521 } 1735 5498 timh if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 || 1736 5498 timh nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop), 1737 5498 timh val) != 0) { 1738 5498 timh zcmd_free_nvlists(&zc); 1739 10204 Matthew return (-1); 1740 5498 timh } 1741 5592 timh if (zplprops) 1742 5592 timh nvlist_free(zplprops); 1743 5498 timh zcmd_free_nvlists(&zc); 1744 3377 eschrock break; 1745 3377 eschrock 1746 789 ahrens default: 1747 4577 ahrens switch (zfs_prop_get_type(prop)) { 1748 4787 ahrens case PROP_TYPE_NUMBER: 1749 4787 ahrens case PROP_TYPE_INDEX: 1750 4577 ahrens *val = getprop_uint64(zhp, prop, source); 1751 7390 Matthew /* 1752 9396 Matthew * If we tried to use a default value for a 1753 7390 Matthew * readonly property, it means that it was not 1754 11080 Tom * present. 1755 7390 Matthew */ 1756 7390 Matthew if (zfs_prop_readonly(prop) && 1757 11080 Tom *source != NULL && (*source)[0] == '\0') { 1758 11080 Tom *source = NULL; 1759 7390 Matthew } 1760 4577 ahrens break; 1761 4577 ahrens 1762 4787 ahrens case PROP_TYPE_STRING: 1763 4577 ahrens default: 1764 4577 ahrens zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 1765 4577 ahrens "cannot get non-numeric property")); 1766 4577 ahrens return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP, 1767 4577 ahrens dgettext(TEXT_DOMAIN, "internal error"))); 1768 4577 ahrens } 1769 789 ahrens } 1770 789 ahrens 1771 789 ahrens return (0); 1772 789 ahrens } 1773 789 ahrens 1774 789 ahrens /* 1775 789 ahrens * Calculate the source type, given the raw source string. 1776 789 ahrens */ 1777 789 ahrens static void 1778 5094 lling get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source, 1779 789 ahrens char *statbuf, size_t statlen) 1780 789 ahrens { 1781 5094 lling if (statbuf == NULL || *srctype == ZPROP_SRC_TEMPORARY) 1782 789 ahrens return; 1783 789 ahrens 1784 789 ahrens if (source == NULL) { 1785 5094 lling *srctype = ZPROP_SRC_NONE; 1786 789 ahrens } else if (source[0] == '\0') { 1787 5094 lling *srctype = ZPROP_SRC_DEFAULT; 1788 11022 Tom } else if (strstr(source, ZPROP_SOURCE_VAL_RECVD) != NULL) { 1789 11022 Tom *srctype = ZPROP_SRC_RECEIVED; 1790 789 ahrens } else { 1791 789 ahrens if (strcmp(source, zhp->zfs_name) == 0) { 1792 5094 lling *srctype = ZPROP_SRC_LOCAL; 1793 789 ahrens } else { 1794 789 ahrens (void) strlcpy(statbuf, source, statlen); 1795 5094 lling *srctype = ZPROP_SRC_INHERITED; 1796 789 ahrens } 1797 789 ahrens } 1798 789 ahrens 1799 11022 Tom } 1800 11022 Tom 1801 11022 Tom int 1802 11022 Tom zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf, 1803 11022 Tom size_t proplen, boolean_t literal) 1804 11022 Tom { 1805 11022 Tom zfs_prop_t prop; 1806 11022 Tom int err = 0; 1807 11022 Tom 1808 11022 Tom if (zhp->zfs_recvd_props == NULL) 1809 11022 Tom if (get_recvd_props_ioctl(zhp) != 0) 1810 11022 Tom return (-1); 1811 11022 Tom 1812 11022 Tom prop = zfs_name_to_prop(propname); 1813 11022 Tom 1814 11022 Tom if (prop != ZPROP_INVAL) { 1815 11022 Tom uint64_t cookie; 1816 11022 Tom if (!nvlist_exists(zhp->zfs_recvd_props, propname)) 1817 11022 Tom return (-1); 1818 11022 Tom zfs_set_recvd_props_mode(zhp, &cookie); 1819 11022 Tom err = zfs_prop_get(zhp, prop, propbuf, proplen, 1820 11022 Tom NULL, NULL, 0, literal); 1821 11022 Tom zfs_unset_recvd_props_mode(zhp, &cookie); 1822 11022 Tom } else if (zfs_prop_userquota(propname)) { 1823 11022 Tom return (-1); 1824 11022 Tom } else { 1825 11022 Tom nvlist_t *propval; 1826 11022 Tom char *recvdval; 1827 11022 Tom if (nvlist_lookup_nvlist(zhp->zfs_recvd_props, 1828 11022 Tom propname, &propval) != 0) 1829 11022 Tom return (-1); 1830 11022 Tom verify(nvlist_lookup_string(propval, ZPROP_VALUE, 1831 11022 Tom &recvdval) == 0); 1832 11022 Tom (void) strlcpy(propbuf, recvdval, proplen); 1833 11022 Tom } 1834 11022 Tom 1835 11022 Tom return (err == 0 ? 0 : -1); 1836 789 ahrens } 1837 789 ahrens 1838 789 ahrens /* 1839 789 ahrens * Retrieve a property from the given object. If 'literal' is specified, then 1840 789 ahrens * numbers are left as exact values. Otherwise, numbers are converted to a 1841 789 ahrens * human-readable form. 1842 789 ahrens * 1843 789 ahrens * Returns 0 on success, or -1 on error. 1844 789 ahrens */ 1845 789 ahrens int 1846 789 ahrens zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, 1847 5094 lling zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal) 1848 789 ahrens { 1849 789 ahrens char *source = NULL; 1850 789 ahrens uint64_t val; 1851 789 ahrens char *str; 1852 2676 eschrock const char *strval; 1853 11022 Tom boolean_t received = zfs_is_recvd_props_mode(zhp); 1854 789 ahrens 1855 789 ahrens /* 1856 789 ahrens * Check to see if this property applies to our object 1857 789 ahrens */ 1858 789 ahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) 1859 11022 Tom return (-1); 1860 11022 Tom 1861 11022 Tom if (received && zfs_prop_readonly(prop)) 1862 789 ahrens return (-1); 1863 789 ahrens 1864 789 ahrens if (src) 1865 5094 lling *src = ZPROP_SRC_NONE; 1866 789 ahrens 1867 789 ahrens switch (prop) { 1868 789 ahrens case ZFS_PROP_CREATION: 1869 789 ahrens /* 1870 789 ahrens * 'creation' is a time_t stored in the statistics. We convert 1871 789 ahrens * this into a string unless 'literal' is specified. 1872 789 ahrens */ 1873 789 ahrens { 1874 2885 ahrens val = getprop_uint64(zhp, prop, &source); 1875 2885 ahrens time_t time = (time_t)val; 1876 789 ahrens struct tm t; 1877 789 ahrens 1878 789 ahrens if (literal || 1879 789 ahrens localtime_r(&time, &t) == NULL || 1880 789 ahrens strftime(propbuf, proplen, "%a %b %e %k:%M %Y", 1881 789 ahrens &t) == 0) 1882 2885 ahrens (void) snprintf(propbuf, proplen, "%llu", val); 1883 789 ahrens } 1884 789 ahrens break; 1885 789 ahrens 1886 789 ahrens case ZFS_PROP_MOUNTPOINT: 1887 789 ahrens /* 1888 789 ahrens * Getting the precise mountpoint can be tricky. 1889 789 ahrens * 1890 789 ahrens * - for 'none' or 'legacy', return those values. 1891 789 ahrens * - for inherited mountpoints, we want to take everything 1892 789 ahrens * after our ancestor and append it to the inherited value. 1893 789 ahrens * 1894 789 ahrens * If the pool has an alternate root, we want to prepend that 1895 789 ahrens * root to any values we return. 1896 789 ahrens */ 1897 6865 rm160521 1898 1356 eschrock str = getprop_string(zhp, prop, &source); 1899 789 ahrens 1900 6612 gw25295 if (str[0] == '/') { 1901 6865 rm160521 char buf[MAXPATHLEN]; 1902 6865 rm160521 char *root = buf; 1903 1356 eschrock const char *relpath = zhp->zfs_name + strlen(source); 1904 789 ahrens 1905 789 ahrens if (relpath[0] == '/') 1906 789 ahrens relpath++; 1907 6612 gw25295 1908 6865 rm160521 if ((zpool_get_prop(zhp->zpool_hdl, 1909 6865 rm160521 ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) || 1910 6865 rm160521 (strcmp(root, "-") == 0)) 1911 6865 rm160521 root[0] = '\0'; 1912 6612 gw25295 /* 1913 6612 gw25295 * Special case an alternate root of '/'. This will 1914 6612 gw25295 * avoid having multiple leading slashes in the 1915 6612 gw25295 * mountpoint path. 1916 6612 gw25295 */ 1917 6612 gw25295 if (strcmp(root, "/") == 0) 1918 6612 gw25295 root++; 1919 6612 gw25295 1920 6612 gw25295 /* 1921 6612 gw25295 * If the mountpoint is '/' then skip over this 1922 6612 gw25295 * if we are obtaining either an alternate root or 1923 6612 gw25295 * an inherited mountpoint. 1924 6612 gw25295 */ 1925 6612 gw25295 if (str[1] == '\0' && (root[0] != '\0' || 1926 6612 gw25295 relpath[0] != '\0')) 1927 1356 eschrock str++; 1928 789 ahrens 1929 789 ahrens if (relpath[0] == '\0') 1930 789 ahrens (void) snprintf(propbuf, proplen, "%s%s", 1931 1356 eschrock root, str); 1932 789 ahrens else 1933 789 ahrens (void) snprintf(propbuf, proplen, "%s%s%s%s", 1934 1356 eschrock root, str, relpath[0] == '@' ? "" : "/", 1935 789 ahrens relpath); 1936 789 ahrens } else { 1937 789 ahrens /* 'legacy' or 'none' */ 1938 1356 eschrock (void) strlcpy(propbuf, str, proplen); 1939 789 ahrens } 1940 789 ahrens 1941 789 ahrens break; 1942 789 ahrens 1943 789 ahrens case ZFS_PROP_ORIGIN: 1944 2885 ahrens (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), 1945 789 ahrens proplen); 1946 789 ahrens /* 1947 789 ahrens * If there is no parent at all, return failure to indicate that 1948 789 ahrens * it doesn't apply to this dataset. 1949 789 ahrens */ 1950 789 ahrens if (propbuf[0] == '\0') 1951 789 ahrens return (-1); 1952 789 ahrens break; 1953 789 ahrens 1954 789 ahrens case ZFS_PROP_QUOTA: 1955 5378 ck153898 case ZFS_PROP_REFQUOTA: 1956 789 ahrens case ZFS_PROP_RESERVATION: 1957 5378 ck153898 case ZFS_PROP_REFRESERVATION: 1958 5378 ck153898 1959 2082 eschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 1960 2082 eschrock return (-1); 1961 789 ahrens 1962 789 ahrens /* 1963 789 ahrens * If quota or reservation is 0, we translate this into 'none' 1964 789 ahrens * (unless literal is set), and indicate that it's the default 1965 789 ahrens * value. Otherwise, we print the number nicely and indicate 1966 789 ahrens * that its set locally. 1967 789 ahrens */ 1968 789 ahrens if (val == 0) { 1969 789 ahrens if (literal) 1970 789 ahrens (void) strlcpy(propbuf, "0", proplen); 1971 789 ahrens else 1972 789 ahrens (void) strlcpy(propbuf, "none", proplen); 1973 789 ahrens } else { 1974 789 ahrens if (literal) 1975 2856 nd150628 (void) snprintf(propbuf, proplen, "%llu", 1976 3912 lling (u_longlong_t)val); 1977 789 ahrens else 1978 789 ahrens zfs_nicenum(val, propbuf, proplen); 1979 789 ahrens } 1980 789 ahrens break; 1981 789 ahrens 1982 789 ahrens case ZFS_PROP_COMPRESSRATIO: 1983 2082 eschrock if (get_numeric_property(zhp, prop, src, &source, &val) != 0) 1984 2082 eschrock return (-1); 1985 10922 Jeff (void) snprintf(propbuf, proplen, "%llu.%02llux", 1986 10922 Jeff (u_longlong_t)(val / 100), 1987 10922 Jeff (u_longlong_t)(val % 100)); 1988 789 ahrens break; 1989 789 ahrens 1990 789 ahrens case ZFS_PROP_TYPE: 1991 789 ahrens switch (zhp->zfs_type) { 1992 789 ahrens case ZFS_TYPE_FILESYSTEM: 1993 789 ahrens str = "filesystem"; 1994 789 ahrens break; 1995 789 ahrens case ZFS_TYPE_VOLUME: 1996 789 ahrens str = "volume"; 1997 789 ahrens break; 1998 789 ahrens case ZFS_TYPE_SNAPSHOT: 1999 789 ahrens str = "snapshot"; 2000 789 ahrens break; 2001 789 ahrens default: 2002 2082 eschrock abort(); 2003 789 ahrens } 2004 789 ahrens (void) snprintf(propbuf, proplen, "%s", str); 2005 789 ahrens break; 2006 789 ahrens 2007 789 ahrens case ZFS_PROP_MOUNTED: 2008 789 ahrens /* 2009 789 ahrens * The 'mounted' property is a pseudo-property that described 2010 789 ahrens * whether the filesystem is currently mounted. Even though 2011 789 ahrens * it's a boolean value, the typical values of "on" and "off" 2012 789 ahrens * don't make sense, so we translate to "yes" and "no". 2013 789 ahrens */ 2014 2082 eschrock if (get_numeric_property(zhp, ZFS_PROP_MOUNTED, 2015 2082 eschrock src, &source, &val) != 0) 2016 2082 eschrock return (-1); 2017 2082 eschrock if (val) 2018 789 ahrens (void) strlcpy(propbuf, "yes", proplen); 2019 789 ahrens else 2020 789 ahrens (void) strlcpy(propbuf, "no", proplen); 2021 789 ahrens break; 2022 789 ahrens 2023 789 ahrens case ZFS_PROP_NAME: 2024 789 ahrens /* 2025 789 ahrens * The 'name' property is a pseudo-property derived from the 2026 789 ahrens * dataset name. It is presented as a real property to simplify 2027 789 ahrens * consumers. 2028 789 ahrens */ 2029 789 ahrens (void) strlcpy(propbuf, zhp->zfs_name, proplen); 2030 10972 Ric break; 2031 10972 Ric 2032 10972 Ric case ZFS_PROP_MLSLABEL: 2033 10972 Ric { 2034 10972 Ric m_label_t *new_sl = NULL; 2035 10972 Ric char *ascii = NULL; /* human readable label */ 2036 10972 Ric 2037 10972 Ric (void) strlcpy(propbuf, 2038 10972 Ric getprop_string(zhp, prop, &source), proplen); 2039 10972 Ric 2040 10972 Ric if (literal || (strcasecmp(propbuf, 2041 10972 Ric ZFS_MLSLABEL_DEFAULT) == 0)) 2042 10972 Ric break; 2043 10972 Ric 2044 10972 Ric /* 2045 10972 Ric * Try to translate the internal hex string to 2046 10972 Ric * human-readable output. If there are any 2047 10972 Ric * problems just use the hex string. 2048 10972 Ric */ 2049 10972 Ric 2050 10972 Ric if (str_to_label(propbuf, &new_sl, MAC_LABEL, 2051 10972 Ric L_NO_CORRECTION, NULL) == -1) { 2052 10972 Ric m_label_free(new_sl); 2053 10972 Ric break; 2054 10972 Ric } 2055 10972 Ric 2056 10972 Ric if (label_to_str(new_sl, &ascii, M_LABEL, 2057 10972 Ric DEF_NAMES) != 0) { 2058 10972 Ric if (ascii) 2059 10972 Ric free(ascii); 2060 10972 Ric m_label_free(new_sl); 2061 10972 Ric break; 2062 10972 Ric } 2063 10972 Ric m_label_free(new_sl); 2064 10972 Ric 2065 10972 Ric (void) strlcpy(propbuf, ascii, proplen); 2066 10972 Ric free(ascii); 2067 10972 Ric } 2068 789 ahrens break; 2069 789 ahrens 2070 789 ahrens default: 2071 4577 ahrens switch (zfs_prop_get_type(prop)) { 2072 4787 ahrens case PROP_TYPE_NUMBER: 2073 4577 ahrens if (get_numeric_property(zhp, prop, src, 2074 4577 ahrens &source, &val) != 0) 2075 4577 ahrens return (-1); 2076 4577 ahrens if (literal) 2077 4577 ahrens (void) snprintf(propbuf, proplen, "%llu", 2078 4577 ahrens (u_longlong_t)val); 2079 4577 ahrens else 2080 4577 ahrens zfs_nicenum(val, propbuf, proplen); 2081 4577 ahrens break; 2082 4577 ahrens 2083 4787 ahrens case PROP_TYPE_STRING: 2084 4577 ahrens (void) strlcpy(propbuf, 2085 4577 ahrens getprop_string(zhp, prop, &source), proplen); 2086 4577 ahrens break; 2087 4577 ahrens 2088 4787 ahrens case PROP_TYPE_INDEX: 2089 4861 ahrens if (get_numeric_property(zhp, prop, src, 2090 4861 ahrens &source, &val) != 0) 2091 4861 ahrens return (-1); 2092 4861 ahrens if (zfs_prop_index_to_string(prop, val, &strval) != 0) 2093 4577 ahrens return (-1); 2094 4577 ahrens (void) strlcpy(propbuf, strval, proplen); 2095 4577 ahrens break; 2096 4577 ahrens 2097 4577 ahrens default: 2098 4577 ahrens abort(); 2099 4577 ahrens } 2100 789 ahrens } 2101 789 ahrens 2102 789 ahrens get_source(zhp, src, source, statbuf, statlen); 2103 789 ahrens 2104 789 ahrens return (0); 2105 789 ahrens } 2106 789 ahrens 2107 789 ahrens /* 2108 789 ahrens * Utility function to get the given numeric property. Does no validation that 2109 789 ahrens * the given property is the appropriate type; should only be used with 2110 789 ahrens * hard-coded property types. 2111 789 ahrens */ 2112 789 ahrens uint64_t 2113 789 ahrens zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop) 2114 789 ahrens { 2115 789 ahrens char *source; 2116 2082 eschrock uint64_t val; 2117 789 ahrens 2118 5367 ahrens (void) get_numeric_property(zhp, prop, NULL, &source, &val); 2119 2082 eschrock 2120 2082 eschrock return (val); 2121 5713 rm160521 } 2122 5713 rm160521 2123 5713 rm160521 int 2124 5713 rm160521 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val) 2125 5713 rm160521 { 2126 5713 rm160521 char buf[64]; 2127 5713 rm160521 2128 9396 Matthew (void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val); 2129 5713 rm160521 return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf)); 2130 789 ahrens } 2131 789 ahrens 2132 789 ahrens /* 2133 789 ahrens * Similar to zfs_prop_get(), but returns the value as an integer. 2134 789 ahrens */ 2135 789 ahrens int 2136 789 ahrens zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value, 2137 5094 lling zprop_source_t *src, char *statbuf, size_t statlen) 2138 789 ahrens { 2139 789 ahrens char *source; 2140 789 ahrens 2141 789 ahrens /* 2142 789 ahrens * Check to see if this property applies to our object 2143 789 ahrens */ 2144 4849 ahrens if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) { 2145 3237 lling return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE, 2146 2082 eschrock dgettext(TEXT_DOMAIN, "cannot get property '%s'"), 2147 2082 eschrock zfs_prop_to_name(prop))); 2148 4849 ahrens } 2149 789 ahrens 2150 789 ahrens if (src) 2151 5094 lling *src = ZPROP_SRC_NONE; 2152 789 ahrens 2153 2082 eschrock if (get_numeric_property(zhp, prop, src, &source, value) != 0) 2154 2082 eschrock return (-1); 2155 789 ahrens 2156 789 ahrens get_source(zhp, src, source, statbuf, statlen); 2157 789 ahrens 2158 789 ahrens return (0); 2159 789 ahrens } 2160 789 ahrens 2161 9396 Matthew static int 2162 9396 Matthew idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser, 2163 9396 Matthew char **domainp, idmap_rid_t *ridp) 2164 9396 Matthew { 2165 9396 Matthew idmap_handle_t *idmap_hdl = NULL; 2166 9396 Matthew idmap_get_handle_t *get_hdl = NULL; 2167 9396 Matthew idmap_stat status; 2168 9396 Matthew int err = EINVAL; 2169 9396 Matthew 2170 9396 Matthew if (idmap_init(&idmap_hdl) != IDMAP_SUCCESS) 2171 9396 Matthew goto out; 2172 9396 Matthew if (idmap_get_create(idmap_hdl, &get_hdl) != IDMAP_SUCCESS) 2173 9396 Matthew goto out; 2174 9396 Matthew 2175 9396 Matthew if (isuser) { 2176 9396 Matthew err = idmap_get_sidbyuid(get_hdl, id, 2177 9396 Matthew IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status); 2178 9396 Matthew } else { 2179 9396 Matthew err = idmap_get_sidbygid(get_hdl, id, 2180 9396 Matthew IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status); 2181 9396 Matthew } 2182 9396 Matthew if (err == IDMAP_SUCCESS && 2183 9396 Matthew idmap_get_mappings(get_hdl) == IDMAP_SUCCESS && 2184 9396 Matthew status == IDMAP_SUCCESS) 2185 9396 Matthew err = 0; 2186 9396 Matthew else 2187 9396 Matthew err = EINVAL; 2188 9396 Matthew out: 2189 9396 Matthew if (get_hdl) 2190 9396 Matthew idmap_get_destroy(get_hdl); 2191 9396 Matthew if (idmap_hdl) 2192 9396 Matthew (void) idmap_fini(idmap_hdl); 2193 9396 Matthew return (err); 2194 9396 Matthew } 2195 9396 Matthew 2196 9396 Matthew /* 2197 9396 Matthew * convert the propname into parameters needed by kernel 2198 9396 Matthew * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829 2199 9396 Matthew * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789 2200 9396 Matthew */ 2201 9396 Matthew static int 2202 9396 Matthew userquota_propname_decode(const char *propname, boolean_t zoned, 2203 9396 Matthew zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp) 2204 9396 Matthew { 2205 9396 Matthew zfs_userquota_prop_t type; 2206 9396 Matthew char *cp, *end; 2207 10160 Matthew char *numericsid = NULL; 2208 9396 Matthew boolean_t isuser; 2209 9396 Matthew 2210 9396 Matthew domain[0] = '\0'; 2211 9396 Matthew 2212 9396 Matthew /* Figure out the property type ({user|group}{quota|space}) */ 2213 9396 Matthew for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) { 2214 9396 Matthew if (strncmp(propname, zfs_userquota_prop_prefixes[type], 2215 9396 Matthew strlen(zfs_userquota_prop_prefixes[type])) == 0) 2216 9396 Matthew break; 2217 9396 Matthew } 2218 9396 Matthew if (type == ZFS_NUM_USERQUOTA_PROPS) 2219 9396 Matthew return (EINVAL); 2220 9396 Matthew *typep = type; 2221 9396 Matthew 2222 9396 Matthew isuser = (type == ZFS_PROP_USERQUOTA || 2223 9396 Matthew type == ZFS_PROP_USERUSED); 2224 9396 Matthew 2225 9396 Matthew cp = strchr(propname, '@') + 1; 2226 9396 Matthew 2227 9396 Matthew if (strchr(cp, '@')) { 2228 9396 Matthew /* 2229 9396 Matthew * It's a SID name (eg "user@domain") that needs to be 2230 10160 Matthew * turned into S-1-domainID-RID. 2231 10160 Matthew */ 2232 10160 Matthew directory_error_t e; 2233 9396 Matthew if (zoned && getzoneid() == GLOBAL_ZONEID) 2234 9396 Matthew return (ENOENT); 2235 10160 Matthew if (isuser) { 2236 10160 Matthew e = directory_sid_from_user_name(NULL, 2237 10160 Matthew cp, &numericsid); 2238 10160 Matthew } else { 2239 10160 Matthew e = directory_sid_from_group_name(NULL, 2240 10160 Matthew cp, &numericsid); 2241 10160 Matthew } 2242 10160 Matthew if (e != NULL) { 2243 10160 Matthew directory_error_free(e); 2244 10160 Matthew return (ENOENT); 2245 10160 Matthew } 2246 10160 Matthew if (numericsid == NULL) 2247 10160 Matthew return (ENOENT); 2248 10160 Matthew cp = numericsid; 2249 10160 Matthew /* will be further decoded below */ 2250 10160 Matthew } 2251 10160 Matthew 2252 10160 Matthew if (strncmp(cp, "S-1-", 4) == 0) { 2253 9396 Matthew /* It's a numeric SID (eg "S-1-234-567-89") */ 2254 10160 Matthew (void) strlcpy(domain, cp, domainlen); 2255 9396 Matthew cp = strrchr(domain, '-'); 2256 9396 Matthew *cp = '\0'; 2257 9396 Matthew cp++; 2258 9396 Matthew 2259 9396 Matthew errno = 0; 2260 9396 Matthew *ridp = strtoull(cp, &end, 10); 2261 10160 Matthew if (numericsid) { 2262 10160 Matthew free(numericsid); 2263 10160 Matthew numericsid = NULL; 2264 10160 Matthew } 2265 9688 Matthew if (errno != 0 || *end != '\0') 2266 9396 Matthew return (EINVAL); 2267 9396 Matthew } else if (!isdigit(*cp)) { 2268 9396 Matthew /* 2269 9396 Matthew * It's a user/group name (eg "user") that needs to be 2270 9396 Matthew * turned into a uid/gid 2271 9396 Matthew */ 2272 9396 Matthew if (zoned && getzoneid() == GLOBAL_ZONEID) 2273 9396 Matthew return (ENOENT); 2274 9396 Matthew if (isuser) { 2275 9396 Matthew struct passwd *pw; 2276 9396 Matthew pw = getpwnam(cp); 2277 9396 Matthew if (pw == NULL) 2278 9396 Matthew return (ENOENT); 2279 9396 Matthew *ridp = pw->pw_uid; 2280 9396 Matthew } else { 2281 9396 Matthew struct group *gr; 2282 9396 Matthew gr = getgrnam(cp); 2283 9396 Matthew if (gr == NULL) 2284 9396 Matthew return (ENOENT); 2285 9396 Matthew *ridp = gr->gr_gid; 2286 9396 Matthew } 2287 9396 Matthew } else { 2288 9396 Matthew /* It's a user/group ID (eg "12345"). */ 2289 9396 Matthew uid_t id = strtoul(cp, &end, 10); 2290 9396 Matthew idmap_rid_t rid; 2291 9396 Matthew char *mapdomain; 2292 9396 Matthew 2293 9396 Matthew if (*end != '\0') 2294 9396 Matthew return (EINVAL); 2295 9396 Matthew if (id > MAXUID) { 2296 9396 Matthew /* It's an ephemeral ID. */ 2297 9396 Matthew if (idmap_id_to_numeric_domain_rid(id, isuser, 2298 9396 Matthew &mapdomain, &rid) != 0) 2299 9396 Matthew return (ENOENT); 2300 10160 Matthew (void) strlcpy(domain, mapdomain, domainlen); 2301 9396 Matthew *ridp = rid; 2302 9396 Matthew } else { 2303 9396 Matthew *ridp = id; 2304 9396 Matthew } 2305 9396 Matthew } 2306 9396 Matthew 2307 10160 Matthew ASSERT3P(numericsid, ==, NULL); 2308 9396 Matthew return (0); 2309 9396 Matthew } 2310 9396 Matthew 2311 9469 Lin static int 2312 9469 Lin zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname, 2313 9469 Lin uint64_t *propvalue, zfs_userquota_prop_t *typep) 2314 9396 Matthew { 2315 9396 Matthew int err; 2316 9396 Matthew zfs_cmd_t zc = { 0 }; 2317 9396 Matthew 2318 9396 Matthew (void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2319 9396 Matthew 2320 9396 Matthew err = userquota_propname_decode(propname, 2321 9396 Matthew zfs_prop_get_int(zhp, ZFS_PROP_ZONED), 2322 9469 Lin typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid); 2323 9469 Lin zc.zc_objset_type = *typep; 2324 9396 Matthew if (err) 2325 9396 Matthew return (err); 2326 9396 Matthew 2327 9396 Matthew err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc); 2328 9396 Matthew if (err) 2329 9396 Matthew return (err); 2330 9396 Matthew 2331 9469 Lin *propvalue = zc.zc_cookie; 2332 9469 Lin return (0); 2333 9469 Lin } 2334 9469 Lin 2335 9469 Lin int 2336 9469 Lin zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname, 2337 9469 Lin uint64_t *propvalue) 2338 9469 Lin { 2339 9469 Lin zfs_userquota_prop_t type; 2340 9469 Lin 2341 9469 Lin return (zfs_prop_get_userquota_common(zhp, propname, propvalue, 2342 9469 Lin &type)); 2343 9469 Lin } 2344 9469 Lin 2345 9469 Lin int 2346 9469 Lin zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname, 2347 9469 Lin char *propbuf, int proplen, boolean_t literal) 2348 9469 Lin { 2349 9469 Lin int err; 2350 9469 Lin uint64_t propvalue; 2351 9469 Lin zfs_userquota_prop_t type; 2352 9469 Lin 2353 9469 Lin err = zfs_prop_get_userquota_common(zhp, propname, &propvalue, 2354 9469 Lin &type); 2355 9469 Lin 2356 9469 Lin if (err) 2357 9469 Lin return (err); 2358 9469 Lin 2359 9396 Matthew if (literal) { 2360 9469 Lin (void) snprintf(propbuf, proplen, "%llu", propvalue); 2361 9469 Lin } else if (propvalue == 0 && 2362 9396 Matthew (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) { 2363 9396 Matthew (void) strlcpy(propbuf, "none", proplen); 2364 9396 Matthew } else { 2365 9469 Lin zfs_nicenum(propvalue, propbuf, proplen); 2366 9396 Matthew } 2367 9396 Matthew return (0); 2368 9396 Matthew } 2369 9396 Matthew 2370 789 ahrens /* 2371 789 ahrens * Returns the name of the given zfs handle. 2372 789 ahrens */ 2373 789 ahrens const char * 2374 789 ahrens zfs_get_name(const zfs_handle_t *zhp) 2375 789 ahrens { 2376 789 ahrens return (zhp->zfs_name); 2377 789 ahrens } 2378 789 ahrens 2379 789 ahrens /* 2380 789 ahrens * Returns the type of the given zfs handle. 2381 789 ahrens */ 2382 789 ahrens zfs_type_t 2383 789 ahrens zfs_get_type(const zfs_handle_t *zhp) 2384 789 ahrens { 2385 789 ahrens return (zhp->zfs_type); 2386 789 ahrens } 2387 789 ahrens 2388 8228 Eric static int 2389 8228 Eric zfs_do_list_ioctl(zfs_handle_t *zhp, int arg, zfs_cmd_t *zc) 2390 8228 Eric { 2391 8228 Eric int rc; 2392 8228 Eric uint64_t orig_cookie; 2393 8228 Eric 2394 8228 Eric orig_cookie = zc->zc_cookie; 2395 8228 Eric top: 2396 8228 Eric (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name)); 2397 8228 Eric rc = ioctl(zhp->zfs_hdl->libzfs_fd, arg, zc); 2398 8228 Eric 2399 8228 Eric if (rc == -1) { 2400 8228 Eric switch (errno) { 2401 8228 Eric case ENOMEM: 2402 8228 Eric /* expand nvlist memory and try again */ 2403 8228 Eric if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, zc) != 0) { 2404 8228 Eric zcmd_free_nvlists(zc); 2405 8228 Eric return (-1); 2406 8228 Eric } 2407 8228 Eric zc->zc_cookie = orig_cookie; 2408 8228 Eric goto top; 2409 8228 Eric /* 2410 8228 Eric * An errno value of ESRCH indicates normal completion. 2411 8228 Eric * If ENOENT is returned, then the underlying dataset 2412 8228 Eric * has been removed since we obtained the handle. 2413 8228 Eric */ 2414 8228 Eric case ESRCH: 2415 8228 Eric case ENOENT: 2416 8228 Eric rc = 1; 2417 8228 Eric break; 2418 8228 Eric default: 2419 8228 Eric rc = zfs_standard_error(zhp->zfs_hdl, errno, 2420 8228 Eric dgettext(TEXT_DOMAIN, 2421 8228 Eric "cannot iterate filesystems")); 2422 8228 Eric break; 2423 8228 Eric } 2424 8228 Eric } 2425 8228 Eric return (rc); 2426 8228 Eric } 2427 8228 Eric 2428 789 ahrens /* 2429 1356 eschrock * Iterate over all child filesystems 2430 789 ahrens */ 2431 789 ahrens int 2432 1356 eschrock zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2433 789 ahrens { 2434 789 ahrens zfs_cmd_t zc = { 0 }; 2435 789 ahrens zfs_handle_t *nzhp; 2436 789 ahrens int ret; 2437 789 ahrens 2438 5367 ahrens if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM) 2439 5367 ahrens return (0); 2440 5367 ahrens 2441 8228 Eric if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 2442 8228 Eric return (-1); 2443 8228 Eric 2444 8228 Eric while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT, 2445 8228 Eric &zc)) == 0) { 2446 789 ahrens /* 2447 789 ahrens * Silently ignore errors, as the only plausible explanation is 2448 789 ahrens * that the pool has since been removed. 2449 789 ahrens */ 2450 8228 Eric if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl, 2451 8228 Eric &zc)) == NULL) { 2452 8228 Eric continue; 2453 8228 Eric } 2454 8228 Eric 2455 8228 Eric if ((ret = func(nzhp, data)) != 0) { 2456 8228 Eric zcmd_free_nvlists(&zc); 2457 789 ahrens return (ret); 2458 8228 Eric } 2459 8228 Eric } 2460 8228 Eric zcmd_free_nvlists(&zc); 2461 8228 Eric return ((ret < 0) ? ret : 0); 2462 1356 eschrock } 2463 1356 eschrock 2464 1356 eschrock /* 2465 1356 eschrock * Iterate over all snapshots 2466 1356 eschrock */ 2467 1356 eschrock int 2468 1356 eschrock zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2469 1356 eschrock { 2470 1356 eschrock zfs_cmd_t zc = { 0 }; 2471 1356 eschrock zfs_handle_t *nzhp; 2472 1356 eschrock int ret; 2473 5367 ahrens 2474 5367 ahrens if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) 2475 5367 ahrens return (0); 2476 789 ahrens 2477 8228 Eric if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) 2478 8228 Eric return (-1); 2479 8228 Eric while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT, 2480 8228 Eric &zc)) == 0) { 2481 8228 Eric 2482 8228 Eric if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl, 2483 8228 Eric &zc)) == NULL) { 2484 8228 Eric continue; 2485 8228 Eric } 2486 8228 Eric 2487 8228 Eric if ((ret = func(nzhp, data)) != 0) { 2488 8228 Eric zcmd_free_nvlists(&zc); 2489 789 ahrens return (ret); 2490 8228 Eric } 2491 8228 Eric } 2492 8228 Eric zcmd_free_nvlists(&zc); 2493 8228 Eric return ((ret < 0) ? ret : 0); 2494 1356 eschrock } 2495 1356 eschrock 2496 1356 eschrock /* 2497 1356 eschrock * Iterate over all children, snapshots and filesystems 2498 1356 eschrock */ 2499 1356 eschrock int 2500 1356 eschrock zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data) 2501 1356 eschrock { 2502 1356 eschrock int ret; 2503 1356 eschrock 2504 1356 eschrock if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0) 2505 1356 eschrock return (ret); 2506 1356 eschrock 2507 1356 eschrock return (zfs_iter_snapshots(zhp, func, data)); 2508 789 ahrens } 2509 789 ahrens 2510 789 ahrens /* 2511 789 ahrens * Given a complete name, return just the portion that refers to the parent. 2512 789 ahrens * Can return NULL if this is a pool. 2513 789 ahrens */ 2514 789 ahrens static int 2515 789 ahrens parent_name(const char *path, char *buf, size_t buflen) 2516 789 ahrens { 2517 789 ahrens char *loc; 2518 789 ahrens 2519 789 ahrens if ((loc = strrchr(path, '/')) == NULL) 2520 789 ahrens return (-1); 2521 789 ahrens 2522 789 ahrens (void) strncpy(buf, path, MIN(buflen, loc - path)); 2523 789 ahrens buf[loc - path] = '\0'; 2524 789 ahrens 2525 789 ahrens return (0); 2526 789 ahrens } 2527 789 ahrens 2528 789 ahrens /* 2529 4490 vb160487 * If accept_ancestor is false, then check to make sure that the given path has 2530 4490 vb160487 * a parent, and that it exists. If accept_ancestor is true, then find the 2531 4490 vb160487 * closest existing ancestor for the given path. In prefixlen return the 2532 4490 vb160487 * length of already existing prefix of the given path. We also fetch the 2533 4490 vb160487 * 'zoned' property, which is used to validate property settings when creating 2534 4490 vb160487 * new datasets. 2535 789 ahrens */ 2536 789 ahrens static int 2537 4490 vb160487 check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned, 2538 4490 vb160487 boolean_t accept_ancestor, int *prefixlen) 2539 789 ahrens { 2540 789 ahrens zfs_cmd_t zc = { 0 }; 2541 789 ahrens char parent[ZFS_MAXNAMELEN]; 2542 789 ahrens char *slash; 2543 1356 eschrock zfs_handle_t *zhp; 2544 2082 eschrock char errbuf[1024]; 2545 2082 eschrock 2546 8269 Mark (void) snprintf(errbuf, sizeof (errbuf), 2547 8269 Mark dgettext(TEXT_DOMAIN, "cannot create '%s'"), path); 2548 789 ahrens 2549 789 ahrens /* get parent, and check to see if this is just a pool */ 2550 789 ahrens if (parent_name(path, parent, sizeof (parent)) != 0) { 2551 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2552 2082 eschrock "missing dataset name")); 2553 2082 eschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2554 789 ahrens } 2555 789 ahrens 2556 789 ahrens /* check to see if the pool exists */ 2557 789 ahrens if ((slash = strchr(parent, '/')) == NULL) 2558 789 ahrens slash = parent + strlen(parent); 2559 789 ahrens (void) strncpy(zc.zc_name, parent, slash - parent); 2560 789 ahrens zc.zc_name[slash - parent] = '\0'; 2561 2082 eschrock if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 && 2562 789 ahrens errno == ENOENT) { 2563 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2564 2082 eschrock "no such pool '%s'"), zc.zc_name); 2565 2082 eschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2566 789 ahrens } 2567 789 ahrens 2568 789 ahrens /* check to see if the parent dataset exists */ 2569 4490 vb160487 while ((zhp = make_dataset_handle(hdl, parent)) == NULL) { 2570 4490 vb160487 if (errno == ENOENT && accept_ancestor) { 2571 4490 vb160487 /* 2572 4490 vb160487 * Go deeper to find an ancestor, give up on top level. 2573 4490 vb160487 */ 2574 4490 vb160487 if (parent_name(parent, parent, sizeof (parent)) != 0) { 2575 4490 vb160487 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2576 4490 vb160487 "no such pool '%s'"), zc.zc_name); 2577 4490 vb160487 return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2578 4490 vb160487 } 2579 4490 vb160487 } else if (errno == ENOENT) { 2580 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2581 2082 eschrock "parent does not exist")); 2582 2082 eschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2583 4490 vb160487 } else 2584 2082 eschrock return (zfs_standard_error(hdl, errno, errbuf)); 2585 789 ahrens } 2586 789 ahrens 2587 2676 eschrock *zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); 2588 789 ahrens /* we are in a non-global zone, but parent is in the global zone */ 2589 2676 eschrock if (getzoneid() != GLOBAL_ZONEID && !(*zoned)) { 2590 2082 eschrock (void) zfs_standard_error(hdl, EPERM, errbuf); 2591 1356 eschrock zfs_close(zhp); 2592 789 ahrens return (-1); 2593 789 ahrens } 2594 789 ahrens 2595 789 ahrens /* make sure parent is a filesystem */ 2596 1356 eschrock if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 2597 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2598 2082 eschrock "parent is not a filesystem")); 2599 2082 eschrock (void) zfs_error(hdl, EZFS_BADTYPE, errbuf); 2600 1356 eschrock zfs_close(zhp); 2601 789 ahrens return (-1); 2602 789 ahrens } 2603 789 ahrens 2604 1356 eschrock zfs_close(zhp); 2605 4490 vb160487 if (prefixlen != NULL) 2606 4490 vb160487 *prefixlen = strlen(parent); 2607 4490 vb160487 return (0); 2608 4490 vb160487 } 2609 4490 vb160487 2610 4490 vb160487 /* 2611 4490 vb160487 * Finds whether the dataset of the given type(s) exists. 2612 4490 vb160487 */ 2613 4490 vb160487 boolean_t 2614 4490 vb160487 zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types) 2615 4490 vb160487 { 2616 4490 vb160487 zfs_handle_t *zhp; 2617 4490 vb160487 2618 5326 ek110237 if (!zfs_validate_name(hdl, path, types, B_FALSE)) 2619 4490 vb160487 return (B_FALSE); 2620 4490 vb160487 2621 4490 vb160487 /* 2622 4490 vb160487 * Try to get stats for the dataset, which will tell us if it exists. 2623 4490 vb160487 */ 2624 4490 vb160487 if ((zhp = make_dataset_handle(hdl, path)) != NULL) { 2625 4490 vb160487 int ds_type = zhp->zfs_type; 2626 4490 vb160487 2627 4490 vb160487 zfs_close(zhp); 2628 4490 vb160487 if (types & ds_type) 2629 4490 vb160487 return (B_TRUE); 2630 4490 vb160487 } 2631 4490 vb160487 return (B_FALSE); 2632 5367 ahrens } 2633 5367 ahrens 2634 5367 ahrens /* 2635 5367 ahrens * Given a path to 'target', create all the ancestors between 2636 5367 ahrens * the prefixlen portion of the path, and the target itself. 2637 5367 ahrens * Fail if the initial prefixlen-ancestor does not already exist. 2638 5367 ahrens */ 2639 5367 ahrens int 2640 5367 ahrens create_parents(libzfs_handle_t *hdl, char *target, int prefixlen) 2641 5367 ahrens { 2642 5367 ahrens zfs_handle_t *h; 2643 5367 ahrens char *cp; 2644 5367 ahrens const char *opname; 2645 5367 ahrens 2646 5367 ahrens /* make sure prefix exists */ 2647 5367 ahrens cp = target + prefixlen; 2648 5367 ahrens if (*cp != '/') { 2649 5367 ahrens assert(strchr(cp, '/') == NULL); 2650 5367 ahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 2651 5367 ahrens } else { 2652 5367 ahrens *cp = '\0'; 2653 5367 ahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 2654 5367 ahrens *cp = '/'; 2655 5367 ahrens } 2656 5367 ahrens if (h == NULL) 2657 5367 ahrens return (-1); 2658 5367 ahrens zfs_close(h); 2659 5367 ahrens 2660 5367 ahrens /* 2661 5367 ahrens * Attempt to create, mount, and share any ancestor filesystems, 2662 5367 ahrens * up to the prefixlen-long one. 2663 5367 ahrens */ 2664 5367 ahrens for (cp = target + prefixlen + 1; 2665 5367 ahrens cp = strchr(cp, '/'); *cp = '/', cp++) { 2666 5367 ahrens char *logstr; 2667 5367 ahrens 2668 5367 ahrens *cp = '\0'; 2669 5367 ahrens 2670 5367 ahrens h = make_dataset_handle(hdl, target); 2671 5367 ahrens if (h) { 2672 5367 ahrens /* it already exists, nothing to do here */ 2673 5367 ahrens zfs_close(h); 2674 5367 ahrens continue; 2675 5367 ahrens } 2676 5367 ahrens 2677 5367 ahrens logstr = hdl->libzfs_log_str; 2678 5367 ahrens hdl->libzfs_log_str = NULL; 2679 5367 ahrens if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM, 2680 5367 ahrens NULL) != 0) { 2681 5367 ahrens hdl->libzfs_log_str = logstr; 2682 5367 ahrens opname = dgettext(TEXT_DOMAIN, "create"); 2683 5367 ahrens goto ancestorerr; 2684 5367 ahrens } 2685 5367 ahrens 2686 5367 ahrens hdl->libzfs_log_str = logstr; 2687 5367 ahrens h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM); 2688 5367 ahrens if (h == NULL) { 2689 5367 ahrens opname = dgettext(TEXT_DOMAIN, "open"); 2690 5367 ahrens goto ancestorerr; 2691 5367 ahrens } 2692 5367 ahrens 2693 5367 ahrens if (zfs_mount(h, NULL, 0) != 0) { 2694 5367 ahrens opname = dgettext(TEXT_DOMAIN, "mount"); 2695 5367 ahrens goto ancestorerr; 2696 5367 ahrens } 2697 5367 ahrens 2698 5367 ahrens if (zfs_share(h) != 0) { 2699 5367 ahrens opname = dgettext(TEXT_DOMAIN, "share"); 2700 5367 ahrens goto ancestorerr; 2701 5367 ahrens } 2702 5367 ahrens 2703 5367 ahrens zfs_close(h); 2704 5367 ahrens } 2705 5367 ahrens 2706 5367 ahrens return (0); 2707 5367 ahrens 2708 5367 ahrens ancestorerr: 2709 5367 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2710 5367 ahrens "failed to %s ancestor '%s'"), opname, target); 2711 5367 ahrens return (-1); 2712 4490 vb160487 } 2713 4490 vb160487 2714 4490 vb160487 /* 2715 4490 vb160487 * Creates non-existing ancestors of the given path. 2716 4490 vb160487 */ 2717 4490 vb160487 int 2718 4490 vb160487 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path) 2719 4490 vb160487 { 2720 4490 vb160487 int prefix; 2721 4490 vb160487 uint64_t zoned; 2722 4490 vb160487 char *path_copy; 2723 4490 vb160487 int rc; 2724 4490 vb160487 2725 4490 vb160487 if (check_parents(hdl, path, &zoned, B_TRUE, &prefix) != 0) 2726 4490 vb160487 return (-1); 2727 4490 vb160487 2728 4490 vb160487 if ((path_copy = strdup(path)) != NULL) { 2729 4490 vb160487 rc = create_parents(hdl, path_copy, prefix); 2730 4490 vb160487 free(path_copy); 2731 4490 vb160487 } 2732 4490 vb160487 if (path_copy == NULL || rc != 0) 2733 4490 vb160487 return (-1); 2734 4490 vb160487 2735 789 ahrens return (0); 2736 789 ahrens } 2737 789 ahrens 2738 789 ahrens /* 2739 2676 eschrock * Create a new filesystem or volume. 2740 789 ahrens */ 2741 789 ahrens int 2742 2082 eschrock zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type, 2743 2676 eschrock nvlist_t *props) 2744 789 ahrens { 2745 789 ahrens zfs_cmd_t zc = { 0 }; 2746 789 ahrens int ret; 2747 789 ahrens uint64_t size = 0; 2748 789 ahrens uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE); 2749 2082 eschrock char errbuf[1024]; 2750 2676 eschrock uint64_t zoned; 2751 2082 eschrock 2752 2082 eschrock (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2753 2082 eschrock "cannot create '%s'"), path); 2754 789 ahrens 2755 789 ahrens /* validate the path, taking care to note the extended error message */ 2756 5326 ek110237 if (!zfs_validate_name(hdl, path, type, B_TRUE)) 2757 2082 eschrock return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); 2758 789 ahrens 2759 789 ahrens /* validate parents exist */ 2760 4490 vb160487 if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0) 2761 789 ahrens return (-1); 2762 789 ahrens 2763 789 ahrens /* 2764 789 ahrens * The failure modes when creating a dataset of a different type over 2765 789 ahrens * one that already exists is a little strange. In particular, if you 2766 789 ahrens * try to create a dataset on top of an existing dataset, the ioctl() 2767 789 ahrens * will return ENOENT, not EEXIST. To prevent this from happening, we 2768 789 ahrens * first try to see if the dataset exists. 2769 789 ahrens */ 2770 789 ahrens (void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name)); 2771 5094 lling if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) { 2772 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2773 2082 eschrock "dataset already exists")); 2774 2082 eschrock return (zfs_error(hdl, EZFS_EXISTS, errbuf)); 2775 789 ahrens } 2776 789 ahrens 2777 789 ahrens if (type == ZFS_TYPE_VOLUME) 2778 789 ahrens zc.zc_objset_type = DMU_OST_ZVOL; 2779 789 ahrens else 2780 789 ahrens zc.zc_objset_type = DMU_OST_ZFS; 2781 789 ahrens 2782 7184 timh if (props && (props = zfs_valid_proplist(hdl, type, props, 2783 3912 lling zoned, NULL, errbuf)) == 0) 2784 2676 eschrock return (-1); 2785 2676 eschrock 2786 789 ahrens if (type == ZFS_TYPE_VOLUME) { 2787 1133 eschrock /* 2788 1133 eschrock * If we are creating a volume, the size and block size must 2789 1133 eschrock * satisfy a few restraints. First, the blocksize must be a 2790 1133 eschrock * valid block size between SPA_{MIN,MAX}BLOCKSIZE. Second, the 2791 1133 eschrock * volsize must be a multiple of the block size, and cannot be 2792 1133 eschrock * zero. 2793 1133 eschrock */ 2794 2676 eschrock if (props == NULL || nvlist_lookup_uint64(props, 2795 2676 eschrock zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) { 2796 2676 eschrock nvlist_free(props); 2797 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2798 2676 eschrock "missing volume size")); 2799 2676 eschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2800 1133 eschrock } 2801 1133 eschrock 2802 2676 eschrock if ((ret = nvlist_lookup_uint64(props, 2803 2676 eschrock zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 2804 2676 eschrock &blocksize)) != 0) { 2805 2676 eschrock if (ret == ENOENT) { 2806 2676 eschrock blocksize = zfs_prop_default_numeric( 2807 2676 eschrock ZFS_PROP_VOLBLOCKSIZE); 2808 2676 eschrock } else { 2809 2676 eschrock nvlist_free(props); 2810 2676 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2811 2676 eschrock "missing volume block size")); 2812 2676 eschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2813 2676 eschrock } 2814 2676 eschrock } 2815 2676 eschrock 2816 2676 eschrock if (size == 0) { 2817 2676 eschrock nvlist_free(props); 2818 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2819 2676 eschrock "volume size cannot be zero")); 2820 2676 eschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2821 1133 eschrock } 2822 1133 eschrock 2823 1133 eschrock if (size % blocksize != 0) { 2824 2676 eschrock nvlist_free(props); 2825 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2826 2676 eschrock "volume size must be a multiple of volume block " 2827 2676 eschrock "size")); 2828 2676 eschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2829 789 ahrens } 2830 2676 eschrock } 2831 789 ahrens 2832 5094 lling if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0) 2833 2676 eschrock return (-1); 2834 2676 eschrock nvlist_free(props); 2835 789 ahrens 2836 789 ahrens /* create the dataset */ 2837 4543 marks ret = zfs_ioctl(hdl, ZFS_IOC_CREATE, &zc); 2838 789 ahrens 2839 2676 eschrock zcmd_free_nvlists(&zc); 2840 789 ahrens 2841 789 ahrens /* check for failure */ 2842 789 ahrens if (ret != 0) { 2843 789 ahrens char parent[ZFS_MAXNAMELEN]; 2844 789 ahrens (void) parent_name(path, parent, sizeof (parent)); 2845 789 ahrens 2846 789 ahrens switch (errno) { 2847 789 ahrens case ENOENT: 2848 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2849 2082 eschrock "no such parent '%s'"), parent); 2850 2082 eschrock return (zfs_error(hdl, EZFS_NOENT, errbuf)); 2851 789 ahrens 2852 789 ahrens case EINVAL: 2853 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2854 3413 mmusante "parent '%s' is not a filesystem"), parent); 2855 2082 eschrock return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); 2856 789 ahrens 2857 789 ahrens case EDOM: 2858 2082 eschrock zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2859 2676 eschrock "volume block size must be power of 2 from " 2860 2676 eschrock "%u to %uk"), 2861 789 ahrens (uint_t)SPA_MINBLOCKSIZE, 2862 789 ahrens (uint_t)SPA_MAXBLOCKSIZE >> 10); 2863 2082 eschrock 2864 2676 eschrock return (zfs_error(hdl, EZFS_BADPROP, errbuf)); 2865 4603 ahrens 2866 4603 ahrens case ENOTSUP: 2867 4603 ahrens zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, 2868 4603 ahrens "pool must be upgraded to set this " 2869 4603 ahrens "property or value")); 2870 4603 ahrens return (zfs_error(hdl, EZFS_BADVERSION, errbuf)); 2871 789 ahrens #ifdef _ILP32 2872 789 ahrens case EOVERFLOW: 2873 789 ahrens /* 2874 789 ahrens * This platform can't address a volume this big. 2875 789 ahrens */ 2876 2082 eschrock if (type == ZFS_TYPE_VOLUME) 2877 2082 eschrock return (zfs_error(hdl, EZFS_VOLTOOBIG, 2878 2082 eschrock errbuf)); 2879 789 ahrens #endif 2880 2082 eschrock /* FALLTHROUGH */ 2881 789 ahrens default: 2882 2082 eschrock return (zfs_standard_error(hdl, errno, errbuf)); 2883 789 ahrens } 2884 789 ahrens } 2885 789 ahrens 2886 789 ahrens return (0); 2887 789 ahrens } 2888 789 ahrens 2889 789 ahrens /* 2890 789 ahrens * Destroys the given dataset. The caller must make sure that the filesystem 2891 789 ahrens * isn't mounted, and that there are no active dependents. 2892 789 ahrens */ 2893 789 ahrens int 2894 10242 chris zfs_destroy(zfs_handle_t *zhp, boolean_t defer) 2895 789 ahrens { 2896 789 ahrens zfs_cmd_t zc = { 0 }; 2897 789 ahrens 2898 789 ahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2899 789 ahrens 2900 2676 eschrock if (ZFS_IS_VOLUME(zhp)) { 2901 3126 ahl /* 2902 4543 marks * If user doesn't have permissions to unshare volume, then 2903 4543 marks * abort the request. This would only happen for a 2904 4543 marks * non-privileged user. 2905 4543 marks */ 2906 4543 marks if (zfs_unshare_iscsi(zhp) != 0) { 2907 4543 marks return (-1); 2908 4543 marks } 2909 3126 ahl 2910 789 ahrens zc.zc_objset_type = DMU_OST_ZVOL; 2911 789 ahrens } else { 2912 789 ahrens zc.zc_objset_type = DMU_OST_ZFS; 2913 789 ahrens } 2914 789 ahrens 2915 10242 chris zc.zc_defer_destroy = defer; 2916 4543 marks if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0) { 2917 3237 lling return (zfs_standard_error_fmt(zhp->zfs_hdl, errno, 2918 2082 eschrock dgettext(TEXT_DOMAIN, "cannot destroy '%s'"), 2919 2082 eschrock zhp->zfs_name)); 2920 2199 ahrens } 2921 789 ahrens 2922 789 ahrens remove_mountpoint(zhp); 2923 2199 ahrens 2924 2199 ahrens return (0); 2925 2199 ahrens } 2926 2199 ahrens 2927 2199 ahrens struct destroydata { 2928 2199 ahrens char *snapname; 2929 2199 ahrens boolean_t gotone; 2930 3265 ahrens boolean_t closezhp; 2931 2199 ahrens }; 2932 2199 ahrens 2933 2199 ahrens static int 2934 10588 Eric zfs_check_snap_cb(zfs_handle_t *zhp, void *arg) 2935 2199 ahrens { 2936 2199 ahrens struct destroydata *dd = arg; 2937 2199 ahrens zfs_handle_t *szhp; 2938 2199 ahrens char name[ZFS_MAXNAMELEN]; 2939 3265 ahrens boolean_t closezhp = dd->closezhp; 2940 10588 Eric int rv = 0; 2941 2199 ahrens 2942 2676 eschrock (void) strlcpy(name, zhp->zfs_name, sizeof (name)); 2943 2676 eschrock (void) strlcat(name, "@", sizeof (name)); 2944 2676 eschrock (void) strlcat(name, dd->snapname, sizeof (name)); 2945 2199 ahrens 2946 2199 ahrens szhp = make_dataset_handle(zhp->zfs_hdl, name); 2947 2199 ahrens if (szhp) { 2948 2199 ahrens dd->gotone = B_TRUE; 2949 2199 ahrens zfs_close(szhp); 2950 2199 ahrens } 2951 2199 ahrens 2952 3265 ahrens dd->closezhp = B_TRUE; 2953 10588 Eric if (!dd->gotone) 2954 10588 Eric rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, arg); 2955 3265 ahrens if (closezhp) 2956 3265 ahrens zfs_close(zhp); 2957 3265 ahrens return (rv); 2958 2199 ahrens } 2959 2199 ahrens 2960 2199 ahrens /* 2961 2199 ahrens * Destroys all snapshots with the given name in zhp & descendants. 2962 2199 ahrens */ 2963 2199 ahrens int 2964 10242 chris zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer) 2965 2199 ahrens { 2966 2199 ahrens zfs_cmd_t zc = { 0 }; 2967 2199 ahrens int ret; 2968 2199 ahrens struct destroydata dd = { 0 }; 2969 2199 ahrens 2970 2199 ahrens dd.snapname = snapname; 2971 10588 Eric (void) zfs_check_snap_cb(zhp, &dd); 2972 2199 ahrens 2973 2199 ahrens if (!dd.gotone) { 2974 3237 lling return (zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT, 2975 2199 ahrens dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"), 2976 2199 ahrens zhp->zfs_name, snapname)); 2977 2199 ahrens } 2978 2199 ahrens 2979 2199 ahrens (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); 2980 2676 eschrock (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value)); 2981 10242 chris zc.zc_defer_destroy = defer; 2982 2199 ahrens 2983 4543 marks ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS, &zc); 2984 2199 ahrens if (ret != 0) { 2985 2199 ahrens char errbuf[1024]; 2986 2199 ahrens 2987 2199 ahrens (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, 2988 2199 ahrens "cannot destroy '%s@%s'"), zc.zc_name, snapname); 2989 2199 ahrens 2990 2199 ahrens switch (errno) { 2991 2199 ahrens case EEXIST: 2992 2199 ahrens zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN, 2993 2199 ahrens "snapshot is cloned")); 2994 2199 ahrens return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf)); 2995 2199 ahrens 2996 2199 ahrens default: 2997 2199 ahrens return (zfs_standard_error(zhp->zfs_hdl, errno, 2998 2199 ahrens errbuf)); 2999 2199 ahrens } 3000 2199 ahrens } 3001 789 ahrens 3002 789 ahrens return (0); 3003 789 ahrens } 3004 789 ahrens 3005 789 ahrens /* 3006 789 ahrens * Clones the given dataset. The target must be of the same type as the source. 3007 789 ahrens */ 3008 789 ahrens int 3009 2676 eschrock zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props) 3010 789 ahrens { 3011