author | maybee |
Thu, 22 May 2008 11:13:47 -0700 | |
changeset 6689 | 47572a2f5e73 |
parent 6047 | 235fee4665e7 |
child 7046 | 361307ae060d |
permissions | -rw-r--r-- |
789 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
1544 | 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 |
*/ |
|
21 |
/* |
|
6047
235fee4665e7
6598604 BAD TRAP while set property to multiple filesystems
ahrens
parents:
5569
diff
changeset
|
22 |
* Copyright 2008 Sun Microsystems, Inc. All rights reserved. |
789 | 23 |
* Use is subject to license terms. |
24 |
*/ |
|
25 |
||
26 |
#pragma ident "%Z%%M% %I% %E% SMI" |
|
27 |
||
28 |
#include <sys/dmu.h> |
|
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
29 |
#include <sys/dmu_objset.h> |
789 | 30 |
#include <sys/dmu_tx.h> |
31 |
#include <sys/dsl_dataset.h> |
|
32 |
#include <sys/dsl_dir.h> |
|
33 |
#include <sys/dsl_prop.h> |
|
2199 | 34 |
#include <sys/dsl_synctask.h> |
789 | 35 |
#include <sys/spa.h> |
36 |
#include <sys/zio_checksum.h> /* for the default checksum value */ |
|
37 |
#include <sys/zap.h> |
|
38 |
#include <sys/fs/zfs.h> |
|
39 |
||
40 |
#include "zfs_prop.h" |
|
41 |
||
42 |
static int |
|
43 |
dodefault(const char *propname, int intsz, int numint, void *buf) |
|
44 |
{ |
|
45 |
zfs_prop_t prop; |
|
46 |
||
5331 | 47 |
/* |
48 |
* The setonce properties are read-only, BUT they still |
|
49 |
* have a default value that can be used as the initial |
|
50 |
* value. |
|
51 |
*/ |
|
5094 | 52 |
if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL || |
5331 | 53 |
(zfs_prop_readonly(prop) && !zfs_prop_setonce(prop))) |
789 | 54 |
return (ENOENT); |
55 |
||
4787 | 56 |
if (zfs_prop_get_type(prop) == PROP_TYPE_STRING) { |
789 | 57 |
if (intsz != 1) |
58 |
return (EOVERFLOW); |
|
5094 | 59 |
(void) strncpy(buf, zfs_prop_default_string(prop), |
60 |
numint); |
|
789 | 61 |
} else { |
62 |
if (intsz != 8 || numint < 1) |
|
63 |
return (EOVERFLOW); |
|
64 |
||
65 |
*(uint64_t *)buf = zfs_prop_default_numeric(prop); |
|
66 |
} |
|
67 |
||
68 |
return (0); |
|
69 |
} |
|
70 |
||
71 |
static int |
|
2082 | 72 |
dsl_prop_get_impl(dsl_dir_t *dd, const char *propname, |
789 | 73 |
int intsz, int numint, void *buf, char *setpoint) |
74 |
{ |
|
2082 | 75 |
int err = ENOENT; |
2676 | 76 |
zfs_prop_t prop; |
789 | 77 |
|
78 |
if (setpoint) |
|
79 |
setpoint[0] = '\0'; |
|
80 |
||
2676 | 81 |
prop = zfs_name_to_prop(propname); |
82 |
||
2082 | 83 |
/* |
84 |
* Note: dd may be NULL, therefore we shouldn't dereference it |
|
85 |
* ouside this loop. |
|
86 |
*/ |
|
87 |
for (; dd != NULL; dd = dd->dd_parent) { |
|
88 |
objset_t *mos = dd->dd_pool->dp_meta_objset; |
|
89 |
ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); |
|
789 | 90 |
err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, |
91 |
propname, intsz, numint, buf); |
|
92 |
if (err != ENOENT) { |
|
93 |
if (setpoint) |
|
94 |
dsl_dir_name(dd, setpoint); |
|
95 |
break; |
|
96 |
} |
|
2676 | 97 |
|
98 |
/* |
|
99 |
* Break out of this loop for non-inheritable properties. |
|
100 |
*/ |
|
5331 | 101 |
if (prop != ZPROP_INVAL && !zfs_prop_inheritable(prop)) |
2676 | 102 |
break; |
789 | 103 |
} |
104 |
if (err == ENOENT) |
|
105 |
err = dodefault(propname, intsz, numint, buf); |
|
106 |
||
107 |
return (err); |
|
108 |
} |
|
109 |
||
110 |
/* |
|
111 |
* Register interest in the named property. We'll call the callback |
|
112 |
* once to notify it of the current property value, and again each time |
|
113 |
* the property changes, until this callback is unregistered. |
|
114 |
* |
|
115 |
* Return 0 on success, errno if the prop is not an integer value. |
|
116 |
*/ |
|
117 |
int |
|
118 |
dsl_prop_register(dsl_dataset_t *ds, const char *propname, |
|
119 |
dsl_prop_changed_cb_t *callback, void *cbarg) |
|
120 |
{ |
|
2082 | 121 |
dsl_dir_t *dd = ds->ds_dir; |
789 | 122 |
uint64_t value; |
123 |
dsl_prop_cb_record_t *cbr; |
|
124 |
int err; |
|
2199 | 125 |
int need_rwlock; |
789 | 126 |
|
2199 | 127 |
need_rwlock = !RW_WRITE_HELD(&dd->dd_pool->dp_config_rwlock); |
128 |
if (need_rwlock) |
|
129 |
rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); |
|
789 | 130 |
|
2082 | 131 |
err = dsl_prop_get_impl(dd, propname, 8, 1, &value, NULL); |
789 | 132 |
if (err != 0) { |
5569
d3caac36d311
6634062 dsl_dataset_open_obj misuses RW_LOCK_HELD
ck153898
parents:
5378
diff
changeset
|
133 |
if (need_rwlock) |
d3caac36d311
6634062 dsl_dataset_open_obj misuses RW_LOCK_HELD
ck153898
parents:
5378
diff
changeset
|
134 |
rw_exit(&dd->dd_pool->dp_config_rwlock); |
789 | 135 |
return (err); |
136 |
} |
|
137 |
||
138 |
cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP); |
|
2082 | 139 |
cbr->cbr_ds = ds; |
789 | 140 |
cbr->cbr_propname = kmem_alloc(strlen(propname)+1, KM_SLEEP); |
141 |
(void) strcpy((char *)cbr->cbr_propname, propname); |
|
142 |
cbr->cbr_func = callback; |
|
143 |
cbr->cbr_arg = cbarg; |
|
144 |
mutex_enter(&dd->dd_lock); |
|
145 |
list_insert_head(&dd->dd_prop_cbs, cbr); |
|
146 |
mutex_exit(&dd->dd_lock); |
|
147 |
||
148 |
cbr->cbr_func(cbr->cbr_arg, value); |
|
149 |
||
1544 | 150 |
VERIFY(0 == dsl_dir_open_obj(dd->dd_pool, dd->dd_object, |
151 |
NULL, cbr, &dd)); |
|
2199 | 152 |
if (need_rwlock) |
153 |
rw_exit(&dd->dd_pool->dp_config_rwlock); |
|
789 | 154 |
/* Leave dataset open until this callback is unregistered */ |
155 |
return (0); |
|
156 |
} |
|
157 |
||
158 |
int |
|
159 |
dsl_prop_get_ds(dsl_dir_t *dd, const char *propname, |
|
160 |
int intsz, int numints, void *buf, char *setpoint) |
|
161 |
{ |
|
162 |
int err; |
|
163 |
||
164 |
rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); |
|
2082 | 165 |
err = dsl_prop_get_impl(dd, propname, intsz, numints, buf, setpoint); |
789 | 166 |
rw_exit(&dd->dd_pool->dp_config_rwlock); |
167 |
||
168 |
return (err); |
|
169 |
} |
|
170 |
||
4543 | 171 |
/* |
172 |
* Get property when config lock is already held. |
|
173 |
*/ |
|
174 |
int dsl_prop_get_ds_locked(dsl_dir_t *dd, const char *propname, |
|
175 |
int intsz, int numints, void *buf, char *setpoint) |
|
176 |
{ |
|
177 |
ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); |
|
178 |
return (dsl_prop_get_impl(dd, propname, intsz, numints, buf, setpoint)); |
|
179 |
} |
|
180 |
||
789 | 181 |
int |
182 |
dsl_prop_get(const char *ddname, const char *propname, |
|
183 |
int intsz, int numints, void *buf, char *setpoint) |
|
184 |
{ |
|
185 |
dsl_dir_t *dd; |
|
186 |
const char *tail; |
|
187 |
int err; |
|
188 |
||
1544 | 189 |
err = dsl_dir_open(ddname, FTAG, &dd, &tail); |
190 |
if (err) |
|
191 |
return (err); |
|
789 | 192 |
if (tail && tail[0] != '@') { |
193 |
dsl_dir_close(dd, FTAG); |
|
194 |
return (ENOENT); |
|
195 |
} |
|
196 |
||
197 |
err = dsl_prop_get_ds(dd, propname, intsz, numints, buf, setpoint); |
|
198 |
||
199 |
dsl_dir_close(dd, FTAG); |
|
200 |
return (err); |
|
201 |
} |
|
202 |
||
203 |
/* |
|
204 |
* Get the current property value. It may have changed by the time this |
|
205 |
* function returns, so it is NOT safe to follow up with |
|
206 |
* dsl_prop_register() and assume that the value has not changed in |
|
207 |
* between. |
|
208 |
* |
|
209 |
* Return 0 on success, ENOENT if ddname is invalid. |
|
210 |
*/ |
|
211 |
int |
|
212 |
dsl_prop_get_integer(const char *ddname, const char *propname, |
|
213 |
uint64_t *valuep, char *setpoint) |
|
214 |
{ |
|
215 |
return (dsl_prop_get(ddname, propname, 8, 1, valuep, setpoint)); |
|
216 |
} |
|
217 |
||
218 |
/* |
|
219 |
* Unregister this callback. Return 0 on success, ENOENT if ddname is |
|
220 |
* invalid, ENOMSG if no matching callback registered. |
|
221 |
*/ |
|
222 |
int |
|
223 |
dsl_prop_unregister(dsl_dataset_t *ds, const char *propname, |
|
224 |
dsl_prop_changed_cb_t *callback, void *cbarg) |
|
225 |
{ |
|
2082 | 226 |
dsl_dir_t *dd = ds->ds_dir; |
789 | 227 |
dsl_prop_cb_record_t *cbr; |
228 |
||
229 |
mutex_enter(&dd->dd_lock); |
|
230 |
for (cbr = list_head(&dd->dd_prop_cbs); |
|
231 |
cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { |
|
2082 | 232 |
if (cbr->cbr_ds == ds && |
789 | 233 |
cbr->cbr_func == callback && |
2082 | 234 |
cbr->cbr_arg == cbarg && |
235 |
strcmp(cbr->cbr_propname, propname) == 0) |
|
789 | 236 |
break; |
237 |
} |
|
238 |
||
239 |
if (cbr == NULL) { |
|
240 |
mutex_exit(&dd->dd_lock); |
|
241 |
return (ENOMSG); |
|
242 |
} |
|
243 |
||
244 |
list_remove(&dd->dd_prop_cbs, cbr); |
|
245 |
mutex_exit(&dd->dd_lock); |
|
246 |
kmem_free((void*)cbr->cbr_propname, strlen(cbr->cbr_propname)+1); |
|
247 |
kmem_free(cbr, sizeof (dsl_prop_cb_record_t)); |
|
248 |
||
249 |
/* Clean up from dsl_prop_register */ |
|
250 |
dsl_dir_close(dd, cbr); |
|
251 |
return (0); |
|
252 |
} |
|
253 |
||
2082 | 254 |
/* |
255 |
* Return the number of callbacks that are registered for this dataset. |
|
256 |
*/ |
|
257 |
int |
|
258 |
dsl_prop_numcb(dsl_dataset_t *ds) |
|
259 |
{ |
|
260 |
dsl_dir_t *dd = ds->ds_dir; |
|
261 |
dsl_prop_cb_record_t *cbr; |
|
262 |
int num = 0; |
|
263 |
||
264 |
mutex_enter(&dd->dd_lock); |
|
265 |
for (cbr = list_head(&dd->dd_prop_cbs); |
|
266 |
cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { |
|
267 |
if (cbr->cbr_ds == ds) |
|
268 |
num++; |
|
269 |
} |
|
270 |
mutex_exit(&dd->dd_lock); |
|
271 |
||
272 |
return (num); |
|
273 |
} |
|
274 |
||
789 | 275 |
static void |
276 |
dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, |
|
277 |
const char *propname, uint64_t value, int first) |
|
278 |
{ |
|
279 |
dsl_dir_t *dd; |
|
280 |
dsl_prop_cb_record_t *cbr; |
|
281 |
objset_t *mos = dp->dp_meta_objset; |
|
2199 | 282 |
zap_cursor_t zc; |
6047
235fee4665e7
6598604 BAD TRAP while set property to multiple filesystems
ahrens
parents:
5569
diff
changeset
|
283 |
zap_attribute_t *za; |
789 | 284 |
int err; |
285 |
||
286 |
ASSERT(RW_WRITE_HELD(&dp->dp_config_rwlock)); |
|
1544 | 287 |
err = dsl_dir_open_obj(dp, ddobj, NULL, FTAG, &dd); |
288 |
if (err) |
|
289 |
return; |
|
789 | 290 |
|
291 |
if (!first) { |
|
292 |
/* |
|
293 |
* If the prop is set here, then this change is not |
|
294 |
* being inherited here or below; stop the recursion. |
|
295 |
*/ |
|
296 |
err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, propname, |
|
297 |
8, 1, &value); |
|
298 |
if (err == 0) { |
|
299 |
dsl_dir_close(dd, FTAG); |
|
300 |
return; |
|
301 |
} |
|
302 |
ASSERT3U(err, ==, ENOENT); |
|
303 |
} |
|
304 |
||
305 |
mutex_enter(&dd->dd_lock); |
|
306 |
for (cbr = list_head(&dd->dd_prop_cbs); |
|
307 |
cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { |
|
308 |
if (strcmp(cbr->cbr_propname, propname) == 0) { |
|
309 |
cbr->cbr_func(cbr->cbr_arg, value); |
|
310 |
} |
|
311 |
} |
|
312 |
mutex_exit(&dd->dd_lock); |
|
313 |
||
6047
235fee4665e7
6598604 BAD TRAP while set property to multiple filesystems
ahrens
parents:
5569
diff
changeset
|
314 |
za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); |
2199 | 315 |
for (zap_cursor_init(&zc, mos, |
316 |
dd->dd_phys->dd_child_dir_zapobj); |
|
6047
235fee4665e7
6598604 BAD TRAP while set property to multiple filesystems
ahrens
parents:
5569
diff
changeset
|
317 |
zap_cursor_retrieve(&zc, za) == 0; |
2199 | 318 |
zap_cursor_advance(&zc)) { |
6047
235fee4665e7
6598604 BAD TRAP while set property to multiple filesystems
ahrens
parents:
5569
diff
changeset
|
319 |
dsl_prop_changed_notify(dp, za->za_first_integer, |
2199 | 320 |
propname, value, FALSE); |
789 | 321 |
} |
6047
235fee4665e7
6598604 BAD TRAP while set property to multiple filesystems
ahrens
parents:
5569
diff
changeset
|
322 |
kmem_free(za, sizeof (zap_attribute_t)); |
2199 | 323 |
zap_cursor_fini(&zc); |
789 | 324 |
dsl_dir_close(dd, FTAG); |
325 |
} |
|
326 |
||
327 |
struct prop_set_arg { |
|
328 |
const char *name; |
|
329 |
int intsz; |
|
330 |
int numints; |
|
331 |
const void *buf; |
|
332 |
}; |
|
333 |
||
2199 | 334 |
|
335 |
static void |
|
4543 | 336 |
dsl_prop_set_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) |
789 | 337 |
{ |
2199 | 338 |
dsl_dir_t *dd = arg1; |
339 |
struct prop_set_arg *psa = arg2; |
|
789 | 340 |
objset_t *mos = dd->dd_pool->dp_meta_objset; |
341 |
uint64_t zapobj = dd->dd_phys->dd_props_zapobj; |
|
342 |
uint64_t intval; |
|
2199 | 343 |
int isint; |
4543 | 344 |
char valbuf[32]; |
345 |
char *valstr; |
|
789 | 346 |
|
347 |
isint = (dodefault(psa->name, 8, 1, &intval) == 0); |
|
348 |
||
349 |
if (psa->numints == 0) { |
|
2199 | 350 |
int err = zap_remove(mos, zapobj, psa->name, tx); |
351 |
ASSERT(err == 0 || err == ENOENT); |
|
352 |
if (isint) { |
|
353 |
VERIFY(0 == dsl_prop_get_impl(dd->dd_parent, |
|
354 |
psa->name, 8, 1, &intval, NULL)); |
|
789 | 355 |
} |
356 |
} else { |
|
2199 | 357 |
VERIFY(0 == zap_update(mos, zapobj, psa->name, |
358 |
psa->intsz, psa->numints, psa->buf, tx)); |
|
789 | 359 |
if (isint) |
360 |
intval = *(uint64_t *)psa->buf; |
|
361 |
} |
|
362 |
||
2199 | 363 |
if (isint) { |
789 | 364 |
dsl_prop_changed_notify(dd->dd_pool, |
365 |
dd->dd_object, psa->name, intval, TRUE); |
|
366 |
} |
|
4543 | 367 |
if (isint) { |
368 |
(void) snprintf(valbuf, sizeof (valbuf), |
|
369 |
"%lld", (longlong_t)intval); |
|
370 |
valstr = valbuf; |
|
371 |
} else { |
|
372 |
valstr = (char *)psa->buf; |
|
373 |
} |
|
374 |
spa_history_internal_log((psa->numints == 0) ? LOG_DS_INHERIT : |
|
375 |
LOG_DS_PROPSET, dd->dd_pool->dp_spa, tx, cr, |
|
376 |
"%s=%s dataset = %llu", psa->name, valstr, |
|
377 |
dd->dd_phys->dd_head_dataset_obj); |
|
789 | 378 |
} |
379 |
||
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
380 |
void |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
381 |
dsl_prop_set_uint64_sync(dsl_dir_t *dd, const char *name, uint64_t val, |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
382 |
cred_t *cr, dmu_tx_t *tx) |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
383 |
{ |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
384 |
objset_t *mos = dd->dd_pool->dp_meta_objset; |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
385 |
uint64_t zapobj = dd->dd_phys->dd_props_zapobj; |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
386 |
|
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
387 |
ASSERT(dmu_tx_is_syncing(tx)); |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
388 |
|
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
389 |
VERIFY(0 == zap_update(mos, zapobj, name, sizeof (val), 1, &val, tx)); |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
390 |
|
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
391 |
dsl_prop_changed_notify(dd->dd_pool, dd->dd_object, name, val, TRUE); |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
392 |
|
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
393 |
spa_history_internal_log(LOG_DS_PROPSET, dd->dd_pool->dp_spa, tx, cr, |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
394 |
"%s=%llu dataset = %llu", name, (u_longlong_t)val, |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
395 |
dd->dd_phys->dd_head_dataset_obj); |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
396 |
} |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5331
diff
changeset
|
397 |
|
789 | 398 |
int |
2885 | 399 |
dsl_prop_set_dd(dsl_dir_t *dd, const char *propname, |
400 |
int intsz, int numints, const void *buf) |
|
401 |
{ |
|
402 |
struct prop_set_arg psa; |
|
403 |
||
404 |
psa.name = propname; |
|
405 |
psa.intsz = intsz; |
|
406 |
psa.numints = numints; |
|
407 |
psa.buf = buf; |
|
408 |
||
409 |
return (dsl_sync_task_do(dd->dd_pool, |
|
410 |
NULL, dsl_prop_set_sync, dd, &psa, 2)); |
|
411 |
} |
|
412 |
||
413 |
int |
|
789 | 414 |
dsl_prop_set(const char *ddname, const char *propname, |
415 |
int intsz, int numints, const void *buf) |
|
416 |
{ |
|
417 |
dsl_dir_t *dd; |
|
418 |
int err; |
|
419 |
||
2641 | 420 |
/* |
421 |
* We must do these checks before we get to the syncfunc, since |
|
422 |
* it can't fail. |
|
423 |
*/ |
|
424 |
if (strlen(propname) >= ZAP_MAXNAMELEN) |
|
425 |
return (ENAMETOOLONG); |
|
426 |
if (intsz * numints >= ZAP_MAXVALUELEN) |
|
427 |
return (E2BIG); |
|
428 |
||
1544 | 429 |
err = dsl_dir_open(ddname, FTAG, &dd, NULL); |
430 |
if (err) |
|
431 |
return (err); |
|
2885 | 432 |
err = dsl_prop_set_dd(dd, propname, intsz, numints, buf); |
789 | 433 |
dsl_dir_close(dd, FTAG); |
434 |
return (err); |
|
435 |
} |
|
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
436 |
|
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
437 |
/* |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
438 |
* Iterate over all properties for this dataset and return them in an nvlist. |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
439 |
*/ |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
440 |
int |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6047
diff
changeset
|
441 |
dsl_prop_get_all(objset_t *os, nvlist_t **nvp, boolean_t local) |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
442 |
{ |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
443 |
dsl_dataset_t *ds = os->os->os_dsl_dataset; |
2082 | 444 |
dsl_dir_t *dd = ds->ds_dir; |
5331 | 445 |
boolean_t snapshot; |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
446 |
int err = 0; |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
447 |
dsl_pool_t *dp; |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
448 |
objset_t *mos; |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
449 |
|
5331 | 450 |
snapshot = dsl_dataset_is_snapshot(ds); |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
451 |
|
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
452 |
VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
453 |
|
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
454 |
dp = dd->dd_pool; |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
455 |
mos = dp->dp_meta_objset; |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
456 |
|
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
457 |
rw_enter(&dp->dp_config_rwlock, RW_READER); |
2082 | 458 |
for (; dd != NULL; dd = dd->dd_parent) { |
2885 | 459 |
char setpoint[MAXNAMELEN]; |
460 |
zap_cursor_t zc; |
|
461 |
zap_attribute_t za; |
|
462 |
||
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
463 |
dsl_dir_name(dd, setpoint); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
464 |
|
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
465 |
for (zap_cursor_init(&zc, mos, dd->dd_phys->dd_props_zapobj); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
466 |
(err = zap_cursor_retrieve(&zc, &za)) == 0; |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
467 |
zap_cursor_advance(&zc)) { |
2885 | 468 |
nvlist_t *propval; |
469 |
zfs_prop_t prop; |
|
2676 | 470 |
/* |
471 |
* Skip non-inheritable properties. |
|
472 |
*/ |
|
473 |
if ((prop = zfs_name_to_prop(za.za_name)) != |
|
5094 | 474 |
ZPROP_INVAL && !zfs_prop_inheritable(prop) && |
2676 | 475 |
dd != ds->ds_dir) |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
476 |
continue; |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
477 |
|
5331 | 478 |
if (snapshot && |
479 |
!zfs_prop_valid_for_type(prop, ZFS_TYPE_SNAPSHOT)) |
|
480 |
continue; |
|
481 |
||
2676 | 482 |
if (nvlist_lookup_nvlist(*nvp, za.za_name, |
483 |
&propval) == 0) |
|
484 |
continue; |
|
485 |
||
486 |
VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, |
|
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
487 |
KM_SLEEP) == 0); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
488 |
if (za.za_integer_length == 1) { |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
489 |
/* |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
490 |
* String property |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
491 |
*/ |
2885 | 492 |
char *tmp = kmem_alloc(za.za_num_integers, |
493 |
KM_SLEEP); |
|
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
494 |
err = zap_lookup(mos, |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
495 |
dd->dd_phys->dd_props_zapobj, |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
496 |
za.za_name, 1, za.za_num_integers, |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
497 |
tmp); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
498 |
if (err != 0) { |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
499 |
kmem_free(tmp, za.za_num_integers); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
500 |
break; |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
501 |
} |
5094 | 502 |
VERIFY(nvlist_add_string(propval, ZPROP_VALUE, |
503 |
tmp) == 0); |
|
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
504 |
kmem_free(tmp, za.za_num_integers); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
505 |
} else { |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
506 |
/* |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
507 |
* Integer property |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
508 |
*/ |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
509 |
ASSERT(za.za_integer_length == 8); |
5094 | 510 |
(void) nvlist_add_uint64(propval, ZPROP_VALUE, |
511 |
za.za_first_integer); |
|
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
512 |
} |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
513 |
|
5094 | 514 |
VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, |
515 |
setpoint) == 0); |
|
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
516 |
VERIFY(nvlist_add_nvlist(*nvp, za.za_name, |
2676 | 517 |
propval) == 0); |
518 |
nvlist_free(propval); |
|
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
519 |
} |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
520 |
zap_cursor_fini(&zc); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
521 |
|
2082 | 522 |
if (err != ENOENT) |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
523 |
break; |
2082 | 524 |
err = 0; |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6047
diff
changeset
|
525 |
/* |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6047
diff
changeset
|
526 |
* If we are just after the props that have been set |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6047
diff
changeset
|
527 |
* locally, then we are done after the first iteration. |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6047
diff
changeset
|
528 |
*/ |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6047
diff
changeset
|
529 |
if (local) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6047
diff
changeset
|
530 |
break; |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
531 |
} |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
532 |
rw_exit(&dp->dp_config_rwlock); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
533 |
|
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
534 |
return (err); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
885
diff
changeset
|
535 |
} |
2885 | 536 |
|
537 |
void |
|
538 |
dsl_prop_nvlist_add_uint64(nvlist_t *nv, zfs_prop_t prop, uint64_t value) |
|
539 |
{ |
|
540 |
nvlist_t *propval; |
|
541 |
||
542 |
VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); |
|
5094 | 543 |
VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, value) == 0); |
2885 | 544 |
VERIFY(nvlist_add_nvlist(nv, zfs_prop_to_name(prop), propval) == 0); |
545 |
nvlist_free(propval); |
|
546 |
} |
|
547 |
||
548 |
void |
|
549 |
dsl_prop_nvlist_add_string(nvlist_t *nv, zfs_prop_t prop, const char *value) |
|
550 |
{ |
|
551 |
nvlist_t *propval; |
|
552 |
||
553 |
VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); |
|
5094 | 554 |
VERIFY(nvlist_add_string(propval, ZPROP_VALUE, value) == 0); |
2885 | 555 |
VERIFY(nvlist_add_nvlist(nv, zfs_prop_to_name(prop), propval) == 0); |
556 |
nvlist_free(propval); |
|
557 |
} |