Print this page
cstyle fixes
dsl_dataset_set_fsid_guid should use ZFS_SPACE_CHECK_RESERVED
dsl_dataset_set_fsid_guid _check and _sync func declared static,
removed from dsl_dataset.h
rewrite unique_valid
6333 ZFS should let the user specify or modify the fsid_guid of a dataset
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libzfs/common/libzfs_changelist.c
+++ new/usr/src/lib/libzfs/common/libzfs_changelist.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 *
26 26 * Portions Copyright 2007 Ramprakash Jelari
27 27 */
28 28
29 29 #include <libintl.h>
30 30 #include <libuutil.h>
31 31 #include <stddef.h>
32 32 #include <stdlib.h>
33 33 #include <string.h>
34 34 #include <unistd.h>
35 35 #include <zone.h>
36 36
37 37 #include <libzfs.h>
38 38
39 39 #include "libzfs_impl.h"
40 40
41 41 /*
42 42 * Structure to keep track of dataset state. Before changing the 'sharenfs' or
43 43 * 'mountpoint' property, we record whether the filesystem was previously
44 44 * mounted/shared. This prior state dictates whether we remount/reshare the
45 45 * dataset after the property has been changed.
46 46 *
47 47 * The interface consists of the following sequence of functions:
48 48 *
49 49 * changelist_gather()
50 50 * changelist_prefix()
51 51 * < change property >
52 52 * changelist_postfix()
53 53 * changelist_free()
54 54 *
55 55 * Other interfaces:
56 56 *
57 57 * changelist_remove() - remove a node from a gathered list
58 58 * changelist_rename() - renames all datasets appropriately when doing a rename
59 59 * changelist_unshare() - unshares all the nodes in a given changelist
60 60 * changelist_haszonedchild() - check if there is any child exported to
61 61 * a local zone
62 62 */
63 63 typedef struct prop_changenode {
64 64 zfs_handle_t *cn_handle;
65 65 int cn_shared;
66 66 int cn_mounted;
67 67 int cn_zoned;
68 68 boolean_t cn_needpost; /* is postfix() needed? */
69 69 uu_list_node_t cn_listnode;
70 70 } prop_changenode_t;
71 71
72 72 struct prop_changelist {
73 73 zfs_prop_t cl_prop;
74 74 zfs_prop_t cl_realprop;
75 75 zfs_prop_t cl_shareprop; /* used with sharenfs/sharesmb */
76 76 uu_list_pool_t *cl_pool;
77 77 uu_list_t *cl_list;
78 78 boolean_t cl_waslegacy;
79 79 boolean_t cl_allchildren;
80 80 boolean_t cl_alldependents;
81 81 int cl_mflags; /* Mount flags */
82 82 int cl_gflags; /* Gather request flags */
83 83 boolean_t cl_haszonedchild;
84 84 boolean_t cl_sorted;
85 85 };
86 86
87 87 /*
88 88 * If the property is 'mountpoint', go through and unmount filesystems as
89 89 * necessary. We don't do the same for 'sharenfs', because we can just re-share
90 90 * with different options without interrupting service. We do handle 'sharesmb'
91 91 * since there may be old resource names that need to be removed.
92 92 */
93 93 int
94 94 changelist_prefix(prop_changelist_t *clp)
95 95 {
96 96 prop_changenode_t *cn;
97 97 int ret = 0;
98 98
99 99 if (clp->cl_prop != ZFS_PROP_MOUNTPOINT &&
100 100 clp->cl_prop != ZFS_PROP_SHARESMB)
101 101 return (0);
102 102
103 103 for (cn = uu_list_first(clp->cl_list); cn != NULL;
104 104 cn = uu_list_next(clp->cl_list, cn)) {
105 105
106 106 /* if a previous loop failed, set the remaining to false */
107 107 if (ret == -1) {
108 108 cn->cn_needpost = B_FALSE;
109 109 continue;
110 110 }
111 111
112 112 /*
113 113 * If we are in the global zone, but this dataset is exported
114 114 * to a local zone, do nothing.
115 115 */
116 116 if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
117 117 continue;
118 118
119 119 if (!ZFS_IS_VOLUME(cn->cn_handle)) {
120 120 /*
121 121 * Do the property specific processing.
122 122 */
123 123 switch (clp->cl_prop) {
124 124 case ZFS_PROP_MOUNTPOINT:
125 125 if (zfs_unmount(cn->cn_handle, NULL,
126 126 clp->cl_mflags) != 0) {
127 127 ret = -1;
128 128 cn->cn_needpost = B_FALSE;
129 129 }
130 130 break;
131 131 case ZFS_PROP_SHARESMB:
132 132 (void) zfs_unshare_smb(cn->cn_handle, NULL);
133 133 break;
134 134 }
135 135 }
136 136 }
137 137
138 138 if (ret == -1)
139 139 (void) changelist_postfix(clp);
140 140
141 141 return (ret);
142 142 }
143 143
144 144 /*
145 145 * If the property is 'mountpoint' or 'sharenfs', go through and remount and/or
146 146 * reshare the filesystems as necessary. In changelist_gather() we recorded
147 147 * whether the filesystem was previously shared or mounted. The action we take
148 148 * depends on the previous state, and whether the value was previously 'legacy'.
149 149 * For non-legacy properties, we only remount/reshare the filesystem if it was
150 150 * previously mounted/shared. Otherwise, we always remount/reshare the
151 151 * filesystem.
152 152 */
153 153 int
154 154 changelist_postfix(prop_changelist_t *clp)
155 155 {
156 156 prop_changenode_t *cn;
157 157 char shareopts[ZFS_MAXPROPLEN];
158 158 int errors = 0;
159 159 libzfs_handle_t *hdl;
160 160
161 161 /*
162 162 * If we're changing the mountpoint, attempt to destroy the underlying
163 163 * mountpoint. All other datasets will have inherited from this dataset
164 164 * (in which case their mountpoints exist in the filesystem in the new
165 165 * location), or have explicit mountpoints set (in which case they won't
166 166 * be in the changelist).
167 167 */
168 168 if ((cn = uu_list_last(clp->cl_list)) == NULL)
169 169 return (0);
170 170
171 171 if (clp->cl_prop == ZFS_PROP_MOUNTPOINT)
172 172 remove_mountpoint(cn->cn_handle);
173 173
174 174 /*
175 175 * It is possible that the changelist_prefix() used libshare
176 176 * to unshare some entries. Since libshare caches data, an
177 177 * attempt to reshare during postfix can fail unless libshare
178 178 * is uninitialized here so that it will reinitialize later.
179 179 */
180 180 if (cn->cn_handle != NULL) {
181 181 hdl = cn->cn_handle->zfs_hdl;
182 182 assert(hdl != NULL);
183 183 zfs_uninit_libshare(hdl);
184 184 }
185 185
186 186 /*
187 187 * We walk the datasets in reverse, because we want to mount any parent
188 188 * datasets before mounting the children. We walk all datasets even if
189 189 * there are errors.
190 190 */
191 191 for (cn = uu_list_last(clp->cl_list); cn != NULL;
192 192 cn = uu_list_prev(clp->cl_list, cn)) {
193 193
194 194 boolean_t sharenfs;
195 195 boolean_t sharesmb;
196 196 boolean_t mounted;
197 197
198 198 /*
199 199 * If we are in the global zone, but this dataset is exported
200 200 * to a local zone, do nothing.
201 201 */
202 202 if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
203 203 continue;
204 204
205 205 /* Only do post-processing if it's required */
206 206 if (!cn->cn_needpost)
207 207 continue;
208 208 cn->cn_needpost = B_FALSE;
209 209
210 210 zfs_refresh_properties(cn->cn_handle);
211 211
212 212 if (ZFS_IS_VOLUME(cn->cn_handle))
213 213 continue;
214 214
215 215 /*
216 216 * Remount if previously mounted or mountpoint was legacy,
217 217 * or sharenfs or sharesmb property is set.
218 218 */
219 219 sharenfs = ((zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARENFS,
220 220 shareopts, sizeof (shareopts), NULL, NULL, 0,
221 221 B_FALSE) == 0) && (strcmp(shareopts, "off") != 0));
222 222
223 223 sharesmb = ((zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARESMB,
224 224 shareopts, sizeof (shareopts), NULL, NULL, 0,
225 225 B_FALSE) == 0) && (strcmp(shareopts, "off") != 0));
226 226
227 227 mounted = zfs_is_mounted(cn->cn_handle, NULL);
228 228
229 229 if (!mounted && (cn->cn_mounted ||
230 230 ((sharenfs || sharesmb || clp->cl_waslegacy) &&
231 231 (zfs_prop_get_int(cn->cn_handle,
232 232 ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_ON)))) {
233 233
234 234 if (zfs_mount(cn->cn_handle, NULL, 0) != 0)
235 235 errors++;
236 236 else
237 237 mounted = TRUE;
238 238 }
239 239
240 240 /*
241 241 * If the file system is mounted we always re-share even
242 242 * if the filesystem is currently shared, so that we can
243 243 * adopt any new options.
244 244 */
245 245 if (sharenfs && mounted)
246 246 errors += zfs_share_nfs(cn->cn_handle);
247 247 else if (cn->cn_shared || clp->cl_waslegacy)
248 248 errors += zfs_unshare_nfs(cn->cn_handle, NULL);
249 249 if (sharesmb && mounted)
250 250 errors += zfs_share_smb(cn->cn_handle);
251 251 else if (cn->cn_shared || clp->cl_waslegacy)
252 252 errors += zfs_unshare_smb(cn->cn_handle, NULL);
253 253 }
254 254
255 255 return (errors ? -1 : 0);
256 256 }
257 257
258 258 /*
259 259 * Is this "dataset" a child of "parent"?
260 260 */
261 261 boolean_t
262 262 isa_child_of(const char *dataset, const char *parent)
263 263 {
264 264 int len;
265 265
266 266 len = strlen(parent);
267 267
268 268 if (strncmp(dataset, parent, len) == 0 &&
269 269 (dataset[len] == '@' || dataset[len] == '/' ||
270 270 dataset[len] == '\0'))
271 271 return (B_TRUE);
272 272 else
273 273 return (B_FALSE);
274 274
275 275 }
276 276
277 277 /*
278 278 * If we rename a filesystem, child filesystem handles are no longer valid
279 279 * since we identify each dataset by its name in the ZFS namespace. As a
280 280 * result, we have to go through and fix up all the names appropriately. We
281 281 * could do this automatically if libzfs kept track of all open handles, but
282 282 * this is a lot less work.
283 283 */
284 284 void
285 285 changelist_rename(prop_changelist_t *clp, const char *src, const char *dst)
286 286 {
287 287 prop_changenode_t *cn;
288 288 char newname[ZFS_MAXNAMELEN];
289 289
290 290 for (cn = uu_list_first(clp->cl_list); cn != NULL;
291 291 cn = uu_list_next(clp->cl_list, cn)) {
292 292 /*
293 293 * Do not rename a clone that's not in the source hierarchy.
294 294 */
295 295 if (!isa_child_of(cn->cn_handle->zfs_name, src))
296 296 continue;
297 297
298 298 /*
299 299 * Destroy the previous mountpoint if needed.
300 300 */
301 301 remove_mountpoint(cn->cn_handle);
302 302
303 303 (void) strlcpy(newname, dst, sizeof (newname));
304 304 (void) strcat(newname, cn->cn_handle->zfs_name + strlen(src));
305 305
306 306 (void) strlcpy(cn->cn_handle->zfs_name, newname,
307 307 sizeof (cn->cn_handle->zfs_name));
308 308 }
309 309 }
310 310
311 311 /*
312 312 * Given a gathered changelist for the 'sharenfs' or 'sharesmb' property,
313 313 * unshare all the datasets in the list.
314 314 */
315 315 int
316 316 changelist_unshare(prop_changelist_t *clp, zfs_share_proto_t *proto)
317 317 {
318 318 prop_changenode_t *cn;
319 319 int ret = 0;
320 320
321 321 if (clp->cl_prop != ZFS_PROP_SHARENFS &&
322 322 clp->cl_prop != ZFS_PROP_SHARESMB)
323 323 return (0);
324 324
325 325 for (cn = uu_list_first(clp->cl_list); cn != NULL;
326 326 cn = uu_list_next(clp->cl_list, cn)) {
327 327 if (zfs_unshare_proto(cn->cn_handle, NULL, proto) != 0)
328 328 ret = -1;
329 329 }
330 330
331 331 return (ret);
332 332 }
333 333
334 334 /*
335 335 * Check if there is any child exported to a local zone in a given changelist.
336 336 * This information has already been recorded while gathering the changelist
337 337 * via changelist_gather().
338 338 */
339 339 int
340 340 changelist_haszonedchild(prop_changelist_t *clp)
341 341 {
342 342 return (clp->cl_haszonedchild);
343 343 }
344 344
345 345 /*
346 346 * Remove a node from a gathered list.
347 347 */
348 348 void
349 349 changelist_remove(prop_changelist_t *clp, const char *name)
350 350 {
351 351 prop_changenode_t *cn;
352 352
353 353 for (cn = uu_list_first(clp->cl_list); cn != NULL;
354 354 cn = uu_list_next(clp->cl_list, cn)) {
355 355
356 356 if (strcmp(cn->cn_handle->zfs_name, name) == 0) {
357 357 uu_list_remove(clp->cl_list, cn);
358 358 zfs_close(cn->cn_handle);
359 359 free(cn);
360 360 return;
361 361 }
362 362 }
363 363 }
364 364
365 365 /*
366 366 * Release any memory associated with a changelist.
367 367 */
368 368 void
369 369 changelist_free(prop_changelist_t *clp)
370 370 {
371 371 prop_changenode_t *cn;
372 372 void *cookie;
373 373
374 374 if (clp->cl_list) {
375 375 cookie = NULL;
376 376 while ((cn = uu_list_teardown(clp->cl_list, &cookie)) != NULL) {
377 377 zfs_close(cn->cn_handle);
378 378 free(cn);
379 379 }
380 380
381 381 uu_list_destroy(clp->cl_list);
382 382 }
383 383 if (clp->cl_pool)
384 384 uu_list_pool_destroy(clp->cl_pool);
385 385
386 386 free(clp);
387 387 }
388 388
389 389 static int
390 390 change_one(zfs_handle_t *zhp, void *data)
391 391 {
392 392 prop_changelist_t *clp = data;
393 393 char property[ZFS_MAXPROPLEN];
394 394 char where[64];
395 395 prop_changenode_t *cn;
396 396 zprop_source_t sourcetype;
397 397 zprop_source_t share_sourcetype;
398 398
399 399 /*
400 400 * We only want to unmount/unshare those filesystems that may inherit
401 401 * from the target filesystem. If we find any filesystem with a
402 402 * locally set mountpoint, we ignore any children since changing the
403 403 * property will not affect them. If this is a rename, we iterate
404 404 * over all children regardless, since we need them unmounted in
405 405 * order to do the rename. Also, if this is a volume and we're doing
406 406 * a rename, then always add it to the changelist.
407 407 */
408 408
409 409 if (!(ZFS_IS_VOLUME(zhp) && clp->cl_realprop == ZFS_PROP_NAME) &&
410 410 zfs_prop_get(zhp, clp->cl_prop, property,
411 411 sizeof (property), &sourcetype, where, sizeof (where),
412 412 B_FALSE) != 0) {
413 413 zfs_close(zhp);
414 414 return (0);
415 415 }
416 416
417 417 /*
418 418 * If we are "watching" sharenfs or sharesmb
419 419 * then check out the companion property which is tracked
420 420 * in cl_shareprop
421 421 */
422 422 if (clp->cl_shareprop != ZPROP_INVAL &&
423 423 zfs_prop_get(zhp, clp->cl_shareprop, property,
424 424 sizeof (property), &share_sourcetype, where, sizeof (where),
425 425 B_FALSE) != 0) {
426 426 zfs_close(zhp);
427 427 return (0);
428 428 }
429 429
430 430 if (clp->cl_alldependents || clp->cl_allchildren ||
431 431 sourcetype == ZPROP_SRC_DEFAULT ||
432 432 sourcetype == ZPROP_SRC_INHERITED ||
433 433 (clp->cl_shareprop != ZPROP_INVAL &&
434 434 (share_sourcetype == ZPROP_SRC_DEFAULT ||
435 435 share_sourcetype == ZPROP_SRC_INHERITED))) {
436 436 if ((cn = zfs_alloc(zfs_get_handle(zhp),
437 437 sizeof (prop_changenode_t))) == NULL) {
438 438 zfs_close(zhp);
439 439 return (-1);
440 440 }
441 441
442 442 cn->cn_handle = zhp;
443 443 cn->cn_mounted = (clp->cl_gflags & CL_GATHER_MOUNT_ALWAYS) ||
444 444 zfs_is_mounted(zhp, NULL);
445 445 cn->cn_shared = zfs_is_shared(zhp);
446 446 cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
447 447 cn->cn_needpost = B_TRUE;
448 448
449 449 /* Indicate if any child is exported to a local zone. */
450 450 if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
451 451 clp->cl_haszonedchild = B_TRUE;
452 452
453 453 uu_list_node_init(cn, &cn->cn_listnode, clp->cl_pool);
454 454
455 455 if (clp->cl_sorted) {
456 456 uu_list_index_t idx;
457 457
458 458 (void) uu_list_find(clp->cl_list, cn, NULL,
459 459 &idx);
460 460 uu_list_insert(clp->cl_list, cn, idx);
461 461 } else {
462 462 /*
463 463 * Add this child to beginning of the list. Children
464 464 * below this one in the hierarchy will get added above
465 465 * this one in the list. This produces a list in
466 466 * reverse dataset name order.
467 467 * This is necessary when the original mountpoint
468 468 * is legacy or none.
469 469 */
470 470 ASSERT(!clp->cl_alldependents);
471 471 verify(uu_list_insert_before(clp->cl_list,
472 472 uu_list_first(clp->cl_list), cn) == 0);
473 473 }
474 474
475 475 if (!clp->cl_alldependents)
476 476 return (zfs_iter_children(zhp, change_one, data));
477 477 } else {
478 478 zfs_close(zhp);
479 479 }
480 480
481 481 return (0);
482 482 }
483 483
484 484 /*ARGSUSED*/
485 485 static int
486 486 compare_mountpoints(const void *a, const void *b, void *unused)
487 487 {
488 488 const prop_changenode_t *ca = a;
489 489 const prop_changenode_t *cb = b;
490 490
491 491 char mounta[MAXPATHLEN];
492 492 char mountb[MAXPATHLEN];
493 493
494 494 boolean_t hasmounta, hasmountb;
495 495
496 496 /*
497 497 * When unsharing or unmounting filesystems, we need to do it in
498 498 * mountpoint order. This allows the user to have a mountpoint
499 499 * hierarchy that is different from the dataset hierarchy, and still
500 500 * allow it to be changed. However, if either dataset doesn't have a
501 501 * mountpoint (because it is a volume or a snapshot), we place it at the
502 502 * end of the list, because it doesn't affect our change at all.
503 503 */
504 504 hasmounta = (zfs_prop_get(ca->cn_handle, ZFS_PROP_MOUNTPOINT, mounta,
505 505 sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
506 506 hasmountb = (zfs_prop_get(cb->cn_handle, ZFS_PROP_MOUNTPOINT, mountb,
507 507 sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
508 508
509 509 if (!hasmounta && hasmountb)
510 510 return (-1);
511 511 else if (hasmounta && !hasmountb)
512 512 return (1);
513 513 else if (!hasmounta && !hasmountb)
514 514 return (0);
515 515 else
516 516 return (strcmp(mountb, mounta));
517 517 }
518 518
519 519 /*
520 520 * Given a ZFS handle and a property, construct a complete list of datasets
521 521 * that need to be modified as part of this process. For anything but the
522 522 * 'mountpoint' and 'sharenfs' properties, this just returns an empty list.
523 523 * Otherwise, we iterate over all children and look for any datasets that
524 524 * inherit the property. For each such dataset, we add it to the list and
525 525 * mark whether it was shared beforehand.
526 526 */
527 527 prop_changelist_t *
528 528 changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
529 529 int mnt_flags)
530 530 {
531 531 prop_changelist_t *clp;
532 532 prop_changenode_t *cn;
533 533 zfs_handle_t *temp;
534 534 char property[ZFS_MAXPROPLEN];
535 535 uu_compare_fn_t *compare = NULL;
536 536 boolean_t legacy = B_FALSE;
537 537
538 538 if ((clp = zfs_alloc(zhp->zfs_hdl, sizeof (prop_changelist_t))) == NULL)
539 539 return (NULL);
540 540
541 541 /*
542 542 * For mountpoint-related tasks, we want to sort everything by
543 543 * mountpoint, so that we mount and unmount them in the appropriate
544 544 * order, regardless of their position in the hierarchy.
545 545 */
546 546 if (prop == ZFS_PROP_NAME || prop == ZFS_PROP_ZONED ||
547 547 prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS ||
548 548 prop == ZFS_PROP_SHARESMB) {
549 549
550 550 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT,
551 551 property, sizeof (property),
552 552 NULL, NULL, 0, B_FALSE) == 0 &&
553 553 (strcmp(property, "legacy") == 0 ||
554 554 strcmp(property, "none") == 0)) {
555 555
556 556 legacy = B_TRUE;
557 557 }
558 558 if (!legacy) {
559 559 compare = compare_mountpoints;
560 560 clp->cl_sorted = B_TRUE;
561 561 }
562 562 }
563 563
564 564 clp->cl_pool = uu_list_pool_create("changelist_pool",
565 565 sizeof (prop_changenode_t),
566 566 offsetof(prop_changenode_t, cn_listnode),
567 567 compare, 0);
568 568 if (clp->cl_pool == NULL) {
569 569 assert(uu_error() == UU_ERROR_NO_MEMORY);
570 570 (void) zfs_error(zhp->zfs_hdl, EZFS_NOMEM, "internal error");
571 571 changelist_free(clp);
572 572 return (NULL);
573 573 }
574 574
575 575 clp->cl_list = uu_list_create(clp->cl_pool, NULL,
576 576 clp->cl_sorted ? UU_LIST_SORTED : 0);
577 577 clp->cl_gflags = gather_flags;
578 578 clp->cl_mflags = mnt_flags;
579 579
580 580 if (clp->cl_list == NULL) {
581 581 assert(uu_error() == UU_ERROR_NO_MEMORY);
582 582 (void) zfs_error(zhp->zfs_hdl, EZFS_NOMEM, "internal error");
583 583 changelist_free(clp);
584 584 return (NULL);
585 585 }
586 586
587 587 /*
588 588 * If this is a rename or the 'zoned' property, we pretend we're
589 589 * changing the mountpoint and flag it so we can catch all children in
590 590 * change_one().
591 591 *
592 592 * Flag cl_alldependents to catch all children plus the dependents
593 593 * (clones) that are not in the hierarchy.
594 594 */
↓ open down ↓ |
594 lines elided |
↑ open up ↑ |
595 595 if (prop == ZFS_PROP_NAME) {
596 596 clp->cl_prop = ZFS_PROP_MOUNTPOINT;
597 597 clp->cl_alldependents = B_TRUE;
598 598 } else if (prop == ZFS_PROP_ZONED) {
599 599 clp->cl_prop = ZFS_PROP_MOUNTPOINT;
600 600 clp->cl_allchildren = B_TRUE;
601 601 } else if (prop == ZFS_PROP_CANMOUNT) {
602 602 clp->cl_prop = ZFS_PROP_MOUNTPOINT;
603 603 } else if (prop == ZFS_PROP_VOLSIZE) {
604 604 clp->cl_prop = ZFS_PROP_MOUNTPOINT;
605 + } else if (prop == ZFS_PROP_FSID_GUID) {
606 + clp->cl_prop = ZFS_PROP_MOUNTPOINT;
605 607 } else {
606 608 clp->cl_prop = prop;
607 609 }
608 610 clp->cl_realprop = prop;
609 611
610 612 if (clp->cl_prop != ZFS_PROP_MOUNTPOINT &&
611 613 clp->cl_prop != ZFS_PROP_SHARENFS &&
612 614 clp->cl_prop != ZFS_PROP_SHARESMB)
613 615 return (clp);
614 616
615 617 /*
616 618 * If watching SHARENFS or SHARESMB then
617 619 * also watch its companion property.
618 620 */
619 621 if (clp->cl_prop == ZFS_PROP_SHARENFS)
620 622 clp->cl_shareprop = ZFS_PROP_SHARESMB;
621 623 else if (clp->cl_prop == ZFS_PROP_SHARESMB)
622 624 clp->cl_shareprop = ZFS_PROP_SHARENFS;
623 625
624 626 if (clp->cl_alldependents) {
625 627 if (zfs_iter_dependents(zhp, B_TRUE, change_one, clp) != 0) {
626 628 changelist_free(clp);
627 629 return (NULL);
628 630 }
629 631 } else if (zfs_iter_children(zhp, change_one, clp) != 0) {
630 632 changelist_free(clp);
631 633 return (NULL);
632 634 }
633 635
634 636 /*
635 637 * We have to re-open ourselves because we auto-close all the handles
636 638 * and can't tell the difference.
637 639 */
638 640 if ((temp = zfs_open(zhp->zfs_hdl, zfs_get_name(zhp),
639 641 ZFS_TYPE_DATASET)) == NULL) {
640 642 changelist_free(clp);
641 643 return (NULL);
642 644 }
643 645
644 646 /*
645 647 * Always add ourself to the list. We add ourselves to the end so that
646 648 * we're the last to be unmounted.
647 649 */
648 650 if ((cn = zfs_alloc(zhp->zfs_hdl,
649 651 sizeof (prop_changenode_t))) == NULL) {
650 652 zfs_close(temp);
651 653 changelist_free(clp);
652 654 return (NULL);
653 655 }
654 656
655 657 cn->cn_handle = temp;
656 658 cn->cn_mounted = (clp->cl_gflags & CL_GATHER_MOUNT_ALWAYS) ||
657 659 zfs_is_mounted(temp, NULL);
658 660 cn->cn_shared = zfs_is_shared(temp);
659 661 cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
660 662 cn->cn_needpost = B_TRUE;
661 663
662 664 uu_list_node_init(cn, &cn->cn_listnode, clp->cl_pool);
663 665 if (clp->cl_sorted) {
664 666 uu_list_index_t idx;
665 667 (void) uu_list_find(clp->cl_list, cn, NULL, &idx);
666 668 uu_list_insert(clp->cl_list, cn, idx);
667 669 } else {
668 670 /*
669 671 * Add the target dataset to the end of the list.
670 672 * The list is not really unsorted. The list will be
671 673 * in reverse dataset name order. This is necessary
672 674 * when the original mountpoint is legacy or none.
673 675 */
674 676 verify(uu_list_insert_after(clp->cl_list,
675 677 uu_list_last(clp->cl_list), cn) == 0);
676 678 }
677 679
678 680 /*
679 681 * If the mountpoint property was previously 'legacy', or 'none',
680 682 * record it as the behavior of changelist_postfix() will be different.
681 683 */
682 684 if ((clp->cl_prop == ZFS_PROP_MOUNTPOINT) && legacy) {
683 685 /*
684 686 * do not automatically mount ex-legacy datasets if
685 687 * we specifically set canmount to noauto
686 688 */
687 689 if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) !=
688 690 ZFS_CANMOUNT_NOAUTO)
689 691 clp->cl_waslegacy = B_TRUE;
690 692 }
691 693
692 694 return (clp);
693 695 }
↓ open down ↓ |
79 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX