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