Mercurial > illumos > illumos-gate
annotate usr/src/uts/common/fs/zfs/zfs_ioctl.c @ 4808:63629eaeb41a
6498144 ::kmastat could be even easier to read
6580855 spa_scrub() should be called with spa_namespace_lock held, not the config lock
author | ek110237 |
---|---|
date | Mon, 06 Aug 2007 15:11:21 -0700 |
parents | 602d3f97842c |
children | 3a61e0a9a953 |
rev | line source |
---|---|
789 | 1 /* |
2 * CDDL HEADER START | |
3 * | |
4 * The contents of this file are subject to the terms of the | |
1485 | 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 /* | |
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
22 * Copyright 2007 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/types.h> | |
29 #include <sys/param.h> | |
30 #include <sys/errno.h> | |
31 #include <sys/uio.h> | |
32 #include <sys/buf.h> | |
33 #include <sys/modctl.h> | |
34 #include <sys/open.h> | |
35 #include <sys/file.h> | |
36 #include <sys/kmem.h> | |
37 #include <sys/conf.h> | |
38 #include <sys/cmn_err.h> | |
39 #include <sys/stat.h> | |
40 #include <sys/zfs_ioctl.h> | |
41 #include <sys/zap.h> | |
42 #include <sys/spa.h> | |
3912 | 43 #include <sys/spa_impl.h> |
789 | 44 #include <sys/vdev.h> |
3912 | 45 #include <sys/vdev_impl.h> |
789 | 46 #include <sys/dmu.h> |
47 #include <sys/dsl_dir.h> | |
48 #include <sys/dsl_dataset.h> | |
49 #include <sys/dsl_prop.h> | |
4543 | 50 #include <sys/dsl_deleg.h> |
51 #include <sys/dmu_objset.h> | |
789 | 52 #include <sys/ddi.h> |
53 #include <sys/sunddi.h> | |
54 #include <sys/sunldi.h> | |
55 #include <sys/policy.h> | |
56 #include <sys/zone.h> | |
57 #include <sys/nvpair.h> | |
58 #include <sys/pathname.h> | |
59 #include <sys/mount.h> | |
60 #include <sys/sdt.h> | |
61 #include <sys/fs/zfs.h> | |
62 #include <sys/zfs_ctldir.h> | |
2885 | 63 #include <sys/zvol.h> |
4543 | 64 #include <sharefs/share.h> |
4577 | 65 #include <sys/zfs_znode.h> |
789 | 66 |
67 #include "zfs_namecheck.h" | |
2676 | 68 #include "zfs_prop.h" |
4543 | 69 #include "zfs_deleg.h" |
789 | 70 |
71 extern struct modlfs zfs_modlfs; | |
72 | |
73 extern void zfs_init(void); | |
74 extern void zfs_fini(void); | |
75 | |
76 ldi_ident_t zfs_li = NULL; | |
77 dev_info_t *zfs_dip; | |
78 | |
79 typedef int zfs_ioc_func_t(zfs_cmd_t *); | |
4543 | 80 typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); |
789 | 81 |
82 typedef struct zfs_ioc_vec { | |
83 zfs_ioc_func_t *zvec_func; | |
84 zfs_secpolicy_func_t *zvec_secpolicy; | |
85 enum { | |
4577 | 86 NO_NAME, |
87 POOL_NAME, | |
88 DATASET_NAME | |
4543 | 89 } zvec_namecheck; |
90 boolean_t zvec_his_log; | |
789 | 91 } zfs_ioc_vec_t; |
92 | |
93 /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ | |
94 void | |
95 __dprintf(const char *file, const char *func, int line, const char *fmt, ...) | |
96 { | |
97 const char *newfile; | |
98 char buf[256]; | |
99 va_list adx; | |
100 | |
101 /* | |
102 * Get rid of annoying "../common/" prefix to filename. | |
103 */ | |
104 newfile = strrchr(file, '/'); | |
105 if (newfile != NULL) { | |
106 newfile = newfile + 1; /* Get rid of leading / */ | |
107 } else { | |
108 newfile = file; | |
109 } | |
110 | |
111 va_start(adx, fmt); | |
112 (void) vsnprintf(buf, sizeof (buf), fmt, adx); | |
113 va_end(adx); | |
114 | |
115 /* | |
116 * To get this data, use the zfs-dprintf probe as so: | |
117 * dtrace -q -n 'zfs-dprintf \ | |
118 * /stringof(arg0) == "dbuf.c"/ \ | |
119 * {printf("%s: %s", stringof(arg1), stringof(arg3))}' | |
120 * arg0 = file name | |
121 * arg1 = function name | |
122 * arg2 = line number | |
123 * arg3 = message | |
124 */ | |
125 DTRACE_PROBE4(zfs__dprintf, | |
126 char *, newfile, char *, func, int, line, char *, buf); | |
127 } | |
128 | |
4543 | 129 static void |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
130 history_str_free(char *buf) |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
131 { |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
132 kmem_free(buf, HIS_MAX_RECORD_LEN); |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
133 } |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
134 |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
135 static char * |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
136 history_str_get(zfs_cmd_t *zc) |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
137 { |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
138 char *buf; |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
139 |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
140 if (zc->zc_history == NULL) |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
141 return (NULL); |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
142 |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
143 buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP); |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
144 if (copyinstr((void *)(uintptr_t)zc->zc_history, |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
145 buf, HIS_MAX_RECORD_LEN, NULL) != 0) { |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
146 history_str_free(buf); |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
147 return (NULL); |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
148 } |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
149 |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
150 buf[HIS_MAX_RECORD_LEN -1] = '\0'; |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
151 |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
152 return (buf); |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
153 } |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
154 |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
155 static void |
4543 | 156 zfs_log_history(zfs_cmd_t *zc) |
157 { | |
158 spa_t *spa; | |
4603
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
159 char *buf; |
4543 | 160 |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
161 if ((buf = history_str_get(zc)) == NULL) |
4577 | 162 return; |
163 | |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
164 if (spa_open(zc->zc_name, &spa, FTAG) == 0) { |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
165 if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY) |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
166 (void) spa_history_log(spa, buf, LOG_CMD_NORMAL); |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
167 spa_close(spa, FTAG); |
4543 | 168 } |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
169 history_str_free(buf); |
4543 | 170 } |
171 | |
789 | 172 /* |
173 * Policy for top-level read operations (list pools). Requires no privileges, | |
174 * and can be used in the local zone, as there is no associated dataset. | |
175 */ | |
176 /* ARGSUSED */ | |
177 static int | |
4543 | 178 zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) |
789 | 179 { |
180 return (0); | |
181 } | |
182 | |
183 /* | |
184 * Policy for dataset read operations (list children, get statistics). Requires | |
185 * no privileges, but must be visible in the local zone. | |
186 */ | |
187 /* ARGSUSED */ | |
188 static int | |
4543 | 189 zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) |
789 | 190 { |
191 if (INGLOBALZONE(curproc) || | |
4543 | 192 zone_dataset_visible(zc->zc_name, NULL)) |
789 | 193 return (0); |
194 | |
195 return (ENOENT); | |
196 } | |
197 | |
198 static int | |
199 zfs_dozonecheck(const char *dataset, cred_t *cr) | |
200 { | |
201 uint64_t zoned; | |
202 int writable = 1; | |
203 | |
204 /* | |
205 * The dataset must be visible by this zone -- check this first | |
206 * so they don't see EPERM on something they shouldn't know about. | |
207 */ | |
208 if (!INGLOBALZONE(curproc) && | |
209 !zone_dataset_visible(dataset, &writable)) | |
210 return (ENOENT); | |
211 | |
212 if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) | |
213 return (ENOENT); | |
214 | |
215 if (INGLOBALZONE(curproc)) { | |
216 /* | |
217 * If the fs is zoned, only root can access it from the | |
218 * global zone. | |
219 */ | |
220 if (secpolicy_zfs(cr) && zoned) | |
221 return (EPERM); | |
222 } else { | |
223 /* | |
224 * If we are in a local zone, the 'zoned' property must be set. | |
225 */ | |
226 if (!zoned) | |
227 return (EPERM); | |
228 | |
229 /* must be writable by this zone */ | |
230 if (!writable) | |
231 return (EPERM); | |
232 } | |
233 return (0); | |
234 } | |
235 | |
236 int | |
4543 | 237 zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) |
789 | 238 { |
239 int error; | |
240 | |
4543 | 241 error = zfs_dozonecheck(name, cr); |
242 if (error == 0) { | |
243 error = secpolicy_zfs(cr); | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
244 if (error) |
4543 | 245 error = dsl_deleg_access(name, perm, cr); |
246 } | |
247 return (error); | |
248 } | |
249 | |
250 static int | |
251 zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) | |
252 { | |
253 /* | |
254 * Check permissions for special properties. | |
255 */ | |
256 switch (prop) { | |
257 case ZFS_PROP_ZONED: | |
258 /* | |
259 * Disallow setting of 'zoned' from within a local zone. | |
260 */ | |
261 if (!INGLOBALZONE(curproc)) | |
262 return (EPERM); | |
263 break; | |
789 | 264 |
4543 | 265 case ZFS_PROP_QUOTA: |
266 if (!INGLOBALZONE(curproc)) { | |
267 uint64_t zoned; | |
268 char setpoint[MAXNAMELEN]; | |
269 /* | |
270 * Unprivileged users are allowed to modify the | |
271 * quota on things *under* (ie. contained by) | |
272 * the thing they own. | |
273 */ | |
274 if (dsl_prop_get_integer(name, "zoned", &zoned, | |
275 setpoint)) | |
276 return (EPERM); | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
277 if (!zoned || strlen(name) <= strlen(setpoint)) |
4543 | 278 return (EPERM); |
279 } | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
280 break; |
4543 | 281 } |
282 | |
4787 | 283 return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); |
789 | 284 } |
285 | |
4543 | 286 int |
287 zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) | |
288 { | |
289 int error; | |
290 | |
291 error = zfs_dozonecheck(zc->zc_name, cr); | |
292 if (error) | |
293 return (error); | |
294 | |
295 /* | |
296 * permission to set permissions will be evaluated later in | |
297 * dsl_deleg_can_allow() | |
298 */ | |
299 return (0); | |
300 } | |
301 | |
302 int | |
303 zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) | |
304 { | |
305 int error; | |
306 error = zfs_secpolicy_write_perms(zc->zc_name, | |
307 ZFS_DELEG_PERM_ROLLBACK, cr); | |
308 if (error == 0) | |
309 error = zfs_secpolicy_write_perms(zc->zc_name, | |
310 ZFS_DELEG_PERM_MOUNT, cr); | |
311 return (error); | |
312 } | |
313 | |
314 int | |
315 zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) | |
316 { | |
317 return (zfs_secpolicy_write_perms(zc->zc_name, | |
318 ZFS_DELEG_PERM_SEND, cr)); | |
319 } | |
320 | |
321 int | |
322 zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) | |
323 { | |
324 if (!INGLOBALZONE(curproc)) | |
325 return (EPERM); | |
326 | |
327 if (secpolicy_nfs(CRED()) == 0) { | |
328 return (0); | |
329 } else { | |
330 vnode_t *vp; | |
331 int error; | |
332 | |
333 if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, | |
334 NO_FOLLOW, NULL, &vp)) != 0) | |
335 return (error); | |
336 | |
337 /* Now make sure mntpnt and dataset are ZFS */ | |
338 | |
339 if (vp->v_vfsp->vfs_fstype != zfsfstype || | |
340 (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), | |
341 zc->zc_name) != 0)) { | |
342 VN_RELE(vp); | |
343 return (EPERM); | |
344 } | |
345 | |
346 VN_RELE(vp); | |
347 return (dsl_deleg_access(zc->zc_name, | |
348 ZFS_DELEG_PERM_SHARE, cr)); | |
349 } | |
350 } | |
351 | |
789 | 352 static int |
4543 | 353 zfs_get_parent(const char *datasetname, char *parent, int parentsize) |
789 | 354 { |
355 char *cp; | |
356 | |
357 /* | |
358 * Remove the @bla or /bla from the end of the name to get the parent. | |
359 */ | |
4543 | 360 (void) strncpy(parent, datasetname, parentsize); |
361 cp = strrchr(parent, '@'); | |
789 | 362 if (cp != NULL) { |
363 cp[0] = '\0'; | |
364 } else { | |
4543 | 365 cp = strrchr(parent, '/'); |
789 | 366 if (cp == NULL) |
367 return (ENOENT); | |
368 cp[0] = '\0'; | |
369 } | |
370 | |
4543 | 371 return (0); |
372 } | |
373 | |
374 int | |
375 zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) | |
376 { | |
377 int error; | |
378 | |
379 if ((error = zfs_secpolicy_write_perms(name, | |
380 ZFS_DELEG_PERM_MOUNT, cr)) != 0) | |
381 return (error); | |
382 | |
383 return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); | |
384 } | |
385 | |
386 static int | |
387 zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) | |
388 { | |
389 return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); | |
390 } | |
391 | |
392 /* | |
393 * Must have sys_config privilege to check the iscsi permission | |
394 */ | |
395 /* ARGSUSED */ | |
396 static int | |
397 zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) | |
398 { | |
399 return (secpolicy_zfs(cr)); | |
400 } | |
401 | |
402 int | |
403 zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) | |
404 { | |
405 char parentname[MAXNAMELEN]; | |
406 int error; | |
407 | |
408 if ((error = zfs_secpolicy_write_perms(from, | |
409 ZFS_DELEG_PERM_RENAME, cr)) != 0) | |
410 return (error); | |
411 | |
412 if ((error = zfs_secpolicy_write_perms(from, | |
413 ZFS_DELEG_PERM_MOUNT, cr)) != 0) | |
414 return (error); | |
415 | |
416 if ((error = zfs_get_parent(to, parentname, | |
417 sizeof (parentname))) != 0) | |
418 return (error); | |
419 | |
420 if ((error = zfs_secpolicy_write_perms(parentname, | |
421 ZFS_DELEG_PERM_CREATE, cr)) != 0) | |
422 return (error); | |
423 | |
424 if ((error = zfs_secpolicy_write_perms(parentname, | |
425 ZFS_DELEG_PERM_MOUNT, cr)) != 0) | |
426 return (error); | |
427 | |
428 return (error); | |
429 } | |
430 | |
431 static int | |
432 zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) | |
433 { | |
434 return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); | |
435 } | |
436 | |
437 static int | |
438 zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) | |
439 { | |
440 char parentname[MAXNAMELEN]; | |
441 objset_t *clone; | |
442 int error; | |
443 | |
444 error = zfs_secpolicy_write_perms(zc->zc_name, | |
445 ZFS_DELEG_PERM_PROMOTE, cr); | |
446 if (error) | |
447 return (error); | |
448 | |
449 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, | |
450 DS_MODE_STANDARD | DS_MODE_READONLY, &clone); | |
451 | |
452 if (error == 0) { | |
453 dsl_dataset_t *pclone = NULL; | |
454 dsl_dir_t *dd; | |
455 dd = clone->os->os_dsl_dataset->ds_dir; | |
456 | |
457 rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); | |
458 error = dsl_dataset_open_obj(dd->dd_pool, | |
459 dd->dd_phys->dd_clone_parent_obj, NULL, | |
460 DS_MODE_NONE, FTAG, &pclone); | |
461 rw_exit(&dd->dd_pool->dp_config_rwlock); | |
462 if (error) { | |
463 dmu_objset_close(clone); | |
464 return (error); | |
465 } | |
466 | |
467 error = zfs_secpolicy_write_perms(zc->zc_name, | |
468 ZFS_DELEG_PERM_MOUNT, cr); | |
469 | |
470 dsl_dataset_name(pclone, parentname); | |
471 dmu_objset_close(clone); | |
472 dsl_dataset_close(pclone, DS_MODE_NONE, FTAG); | |
473 if (error == 0) | |
474 error = zfs_secpolicy_write_perms(parentname, | |
475 ZFS_DELEG_PERM_PROMOTE, cr); | |
476 } | |
477 return (error); | |
478 } | |
479 | |
480 static int | |
481 zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) | |
482 { | |
483 int error; | |
484 | |
485 if ((error = zfs_secpolicy_write_perms(zc->zc_name, | |
486 ZFS_DELEG_PERM_RECEIVE, cr)) != 0) | |
487 return (error); | |
488 | |
489 if ((error = zfs_secpolicy_write_perms(zc->zc_name, | |
490 ZFS_DELEG_PERM_MOUNT, cr)) != 0) | |
491 return (error); | |
492 | |
493 return (zfs_secpolicy_write_perms(zc->zc_name, | |
494 ZFS_DELEG_PERM_CREATE, cr)); | |
495 } | |
496 | |
497 int | |
498 zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) | |
499 { | |
500 int error; | |
501 | |
502 if ((error = zfs_secpolicy_write_perms(name, | |
503 ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) | |
504 return (error); | |
505 | |
506 error = zfs_secpolicy_write_perms(name, | |
507 ZFS_DELEG_PERM_MOUNT, cr); | |
508 | |
509 return (error); | |
510 } | |
511 | |
512 static int | |
513 zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) | |
514 { | |
515 | |
516 return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); | |
517 } | |
518 | |
519 static int | |
520 zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) | |
521 { | |
522 char parentname[MAXNAMELEN]; | |
523 int error; | |
524 | |
525 if ((error = zfs_get_parent(zc->zc_name, parentname, | |
526 sizeof (parentname))) != 0) | |
527 return (error); | |
528 | |
529 if (zc->zc_value[0] != '\0') { | |
530 if ((error = zfs_secpolicy_write_perms(zc->zc_value, | |
531 ZFS_DELEG_PERM_CLONE, cr)) != 0) | |
532 return (error); | |
533 } | |
534 | |
535 if ((error = zfs_secpolicy_write_perms(parentname, | |
536 ZFS_DELEG_PERM_CREATE, cr)) != 0) | |
537 return (error); | |
538 | |
539 error = zfs_secpolicy_write_perms(parentname, | |
540 ZFS_DELEG_PERM_MOUNT, cr); | |
541 | |
542 return (error); | |
543 } | |
544 | |
545 static int | |
546 zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) | |
547 { | |
548 int error; | |
549 | |
550 error = secpolicy_fs_unmount(cr, NULL); | |
551 if (error) { | |
552 error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); | |
553 } | |
554 return (error); | |
789 | 555 } |
556 | |
557 /* | |
558 * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires | |
559 * SYS_CONFIG privilege, which is not available in a local zone. | |
560 */ | |
561 /* ARGSUSED */ | |
562 static int | |
4543 | 563 zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) |
789 | 564 { |
565 if (secpolicy_sys_config(cr, B_FALSE) != 0) | |
566 return (EPERM); | |
567 | |
568 return (0); | |
569 } | |
570 | |
571 /* | |
4543 | 572 * Just like zfs_secpolicy_config, except that we will check for |
573 * mount permission on the dataset for permission to create/remove | |
574 * the minor nodes. | |
575 */ | |
576 static int | |
577 zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) | |
578 { | |
579 if (secpolicy_sys_config(cr, B_FALSE) != 0) { | |
580 return (dsl_deleg_access(zc->zc_name, | |
581 ZFS_DELEG_PERM_MOUNT, cr)); | |
582 } | |
583 | |
584 return (0); | |
585 } | |
586 | |
587 /* | |
1544 | 588 * Policy for fault injection. Requires all privileges. |
589 */ | |
590 /* ARGSUSED */ | |
591 static int | |
4543 | 592 zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) |
1544 | 593 { |
594 return (secpolicy_zinject(cr)); | |
595 } | |
596 | |
597 /* | |
789 | 598 * Returns the nvlist as specified by the user in the zfs_cmd_t. |
599 */ | |
600 static int | |
2676 | 601 get_nvlist(zfs_cmd_t *zc, nvlist_t **nvp) |
789 | 602 { |
603 char *packed; | |
604 size_t size; | |
605 int error; | |
606 nvlist_t *config = NULL; | |
607 | |
608 /* | |
2676 | 609 * Read in and unpack the user-supplied nvlist. |
789 | 610 */ |
2676 | 611 if ((size = zc->zc_nvlist_src_size) == 0) |
789 | 612 return (EINVAL); |
613 | |
614 packed = kmem_alloc(size, KM_SLEEP); | |
615 | |
2676 | 616 if ((error = xcopyin((void *)(uintptr_t)zc->zc_nvlist_src, packed, |
789 | 617 size)) != 0) { |
618 kmem_free(packed, size); | |
619 return (error); | |
620 } | |
621 | |
622 if ((error = nvlist_unpack(packed, size, &config, 0)) != 0) { | |
623 kmem_free(packed, size); | |
624 return (error); | |
625 } | |
626 | |
627 kmem_free(packed, size); | |
628 | |
629 *nvp = config; | |
630 return (0); | |
631 } | |
632 | |
633 static int | |
2676 | 634 put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) |
635 { | |
636 char *packed = NULL; | |
637 size_t size; | |
638 int error; | |
639 | |
640 VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); | |
641 | |
642 if (size > zc->zc_nvlist_dst_size) { | |
643 error = ENOMEM; | |
644 } else { | |
4611 | 645 packed = kmem_alloc(size, KM_SLEEP); |
2676 | 646 VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, |
647 KM_SLEEP) == 0); | |
648 error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, | |
649 size); | |
650 kmem_free(packed, size); | |
651 } | |
652 | |
653 zc->zc_nvlist_dst_size = size; | |
654 return (error); | |
655 } | |
656 | |
657 static int | |
789 | 658 zfs_ioc_pool_create(zfs_cmd_t *zc) |
659 { | |
660 int error; | |
661 nvlist_t *config; | |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
662 char *buf; |
789 | 663 |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
664 if ((buf = history_str_get(zc)) == NULL) |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
665 return (EINVAL); |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
666 |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
667 if ((error = get_nvlist(zc, &config)) != 0) { |
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
668 history_str_free(buf); |
789 | 669 return (error); |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
670 } |
789 | 671 |
2676 | 672 error = spa_create(zc->zc_name, config, zc->zc_value[0] == '\0' ? |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
673 NULL : zc->zc_value, buf); |
789 | 674 |
675 nvlist_free(config); | |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
676 history_str_free(buf); |
789 | 677 |
678 return (error); | |
679 } | |
680 | |
681 static int | |
682 zfs_ioc_pool_destroy(zfs_cmd_t *zc) | |
683 { | |
4543 | 684 int error; |
685 zfs_log_history(zc); | |
686 error = spa_destroy(zc->zc_name); | |
687 return (error); | |
789 | 688 } |
689 | |
690 static int | |
691 zfs_ioc_pool_import(zfs_cmd_t *zc) | |
692 { | |
693 int error; | |
694 nvlist_t *config; | |
695 uint64_t guid; | |
696 | |
2676 | 697 if ((error = get_nvlist(zc, &config)) != 0) |
789 | 698 return (error); |
699 | |
700 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || | |
1544 | 701 guid != zc->zc_guid) |
789 | 702 error = EINVAL; |
703 else | |
704 error = spa_import(zc->zc_name, config, | |
2676 | 705 zc->zc_value[0] == '\0' ? NULL : zc->zc_value); |
789 | 706 |
707 nvlist_free(config); | |
708 | |
709 return (error); | |
710 } | |
711 | |
712 static int | |
713 zfs_ioc_pool_export(zfs_cmd_t *zc) | |
714 { | |
4543 | 715 int error; |
716 zfs_log_history(zc); | |
717 error = spa_export(zc->zc_name, NULL); | |
718 return (error); | |
789 | 719 } |
720 | |
721 static int | |
722 zfs_ioc_pool_configs(zfs_cmd_t *zc) | |
723 { | |
724 nvlist_t *configs; | |
725 int error; | |
726 | |
727 if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) | |
728 return (EEXIST); | |
729 | |
2676 | 730 error = put_nvlist(zc, configs); |
789 | 731 |
732 nvlist_free(configs); | |
733 | |
734 return (error); | |
735 } | |
736 | |
737 static int | |
738 zfs_ioc_pool_stats(zfs_cmd_t *zc) | |
739 { | |
740 nvlist_t *config; | |
741 int error; | |
1544 | 742 int ret = 0; |
789 | 743 |
2676 | 744 error = spa_get_stats(zc->zc_name, &config, zc->zc_value, |
745 sizeof (zc->zc_value)); | |
789 | 746 |
747 if (config != NULL) { | |
2676 | 748 ret = put_nvlist(zc, config); |
789 | 749 nvlist_free(config); |
1544 | 750 |
751 /* | |
752 * The config may be present even if 'error' is non-zero. | |
753 * In this case we return success, and preserve the real errno | |
754 * in 'zc_cookie'. | |
755 */ | |
756 zc->zc_cookie = error; | |
789 | 757 } else { |
1544 | 758 ret = error; |
789 | 759 } |
760 | |
1544 | 761 return (ret); |
789 | 762 } |
763 | |
764 /* | |
765 * Try to import the given pool, returning pool stats as appropriate so that | |
766 * user land knows which devices are available and overall pool health. | |
767 */ | |
768 static int | |
769 zfs_ioc_pool_tryimport(zfs_cmd_t *zc) | |
770 { | |
771 nvlist_t *tryconfig, *config; | |
772 int error; | |
773 | |
2676 | 774 if ((error = get_nvlist(zc, &tryconfig)) != 0) |
789 | 775 return (error); |
776 | |
777 config = spa_tryimport(tryconfig); | |
778 | |
779 nvlist_free(tryconfig); | |
780 | |
781 if (config == NULL) | |
782 return (EINVAL); | |
783 | |
2676 | 784 error = put_nvlist(zc, config); |
789 | 785 nvlist_free(config); |
786 | |
787 return (error); | |
788 } | |
789 | |
790 static int | |
791 zfs_ioc_pool_scrub(zfs_cmd_t *zc) | |
792 { | |
793 spa_t *spa; | |
794 int error; | |
795 | |
2926 | 796 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
797 return (error); | |
798 | |
4808 | 799 mutex_enter(&spa_namespace_lock); |
2926 | 800 error = spa_scrub(spa, zc->zc_cookie, B_FALSE); |
4808 | 801 mutex_exit(&spa_namespace_lock); |
2926 | 802 |
803 spa_close(spa, FTAG); | |
804 | |
789 | 805 return (error); |
806 } | |
807 | |
808 static int | |
809 zfs_ioc_pool_freeze(zfs_cmd_t *zc) | |
810 { | |
811 spa_t *spa; | |
812 int error; | |
813 | |
814 error = spa_open(zc->zc_name, &spa, FTAG); | |
815 if (error == 0) { | |
816 spa_freeze(spa); | |
817 spa_close(spa, FTAG); | |
818 } | |
819 return (error); | |
820 } | |
821 | |
822 static int | |
1760 | 823 zfs_ioc_pool_upgrade(zfs_cmd_t *zc) |
824 { | |
825 spa_t *spa; | |
826 int error; | |
827 | |
2926 | 828 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
829 return (error); | |
830 | |
831 spa_upgrade(spa); | |
832 spa_close(spa, FTAG); | |
833 | |
834 return (error); | |
835 } | |
836 | |
837 static int | |
838 zfs_ioc_pool_get_history(zfs_cmd_t *zc) | |
839 { | |
840 spa_t *spa; | |
841 char *hist_buf; | |
842 uint64_t size; | |
843 int error; | |
844 | |
845 if ((size = zc->zc_history_len) == 0) | |
846 return (EINVAL); | |
847 | |
848 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) | |
849 return (error); | |
850 | |
4577 | 851 if (spa_version(spa) < SPA_VERSION_ZPOOL_HISTORY) { |
3863
d56571426115
6529406 zpool history needs to bump the on-disk version
ek110237
parents:
3741
diff
changeset
|
852 spa_close(spa, FTAG); |
d56571426115
6529406 zpool history needs to bump the on-disk version
ek110237
parents:
3741
diff
changeset
|
853 return (ENOTSUP); |
d56571426115
6529406 zpool history needs to bump the on-disk version
ek110237
parents:
3741
diff
changeset
|
854 } |
d56571426115
6529406 zpool history needs to bump the on-disk version
ek110237
parents:
3741
diff
changeset
|
855 |
2926 | 856 hist_buf = kmem_alloc(size, KM_SLEEP); |
857 if ((error = spa_history_get(spa, &zc->zc_history_offset, | |
858 &zc->zc_history_len, hist_buf)) == 0) { | |
4543 | 859 error = xcopyout(hist_buf, |
860 (char *)(uintptr_t)zc->zc_history, | |
2926 | 861 zc->zc_history_len); |
862 } | |
863 | |
864 spa_close(spa, FTAG); | |
865 kmem_free(hist_buf, size); | |
866 return (error); | |
867 } | |
868 | |
869 static int | |
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
870 zfs_ioc_dsobj_to_dsname(zfs_cmd_t *zc) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
871 { |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
872 int error; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
873 |
3912 | 874 if (error = dsl_dsobj_to_dsname(zc->zc_name, zc->zc_obj, zc->zc_value)) |
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
875 return (error); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
876 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
877 return (0); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
878 } |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
879 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
880 static int |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
881 zfs_ioc_obj_to_path(zfs_cmd_t *zc) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
882 { |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
883 objset_t *osp; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
884 int error; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
885 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
886 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
887 DS_MODE_NONE | DS_MODE_READONLY, &osp)) != 0) |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
888 return (error); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
889 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
890 error = zfs_obj_to_path(osp, zc->zc_obj, zc->zc_value, |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
891 sizeof (zc->zc_value)); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
892 dmu_objset_close(osp); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
893 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
894 return (error); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
895 } |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
896 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
897 static int |
789 | 898 zfs_ioc_vdev_add(zfs_cmd_t *zc) |
899 { | |
900 spa_t *spa; | |
901 int error; | |
902 nvlist_t *config; | |
903 | |
904 error = spa_open(zc->zc_name, &spa, FTAG); | |
905 if (error != 0) | |
906 return (error); | |
907 | |
3912 | 908 /* |
909 * A root pool with concatenated devices is not supported. | |
910 * Thus, can not add a device to a root pool with one device. | |
911 */ | |
912 if (spa->spa_root_vdev->vdev_children == 1 && spa->spa_bootfs != 0) { | |
913 spa_close(spa, FTAG); | |
914 return (EDOM); | |
915 } | |
916 | |
2676 | 917 if ((error = get_nvlist(zc, &config)) == 0) { |
789 | 918 error = spa_vdev_add(spa, config); |
919 nvlist_free(config); | |
920 } | |
921 spa_close(spa, FTAG); | |
922 return (error); | |
923 } | |
924 | |
925 static int | |
926 zfs_ioc_vdev_remove(zfs_cmd_t *zc) | |
927 { | |
2082 | 928 spa_t *spa; |
929 int error; | |
930 | |
931 error = spa_open(zc->zc_name, &spa, FTAG); | |
932 if (error != 0) | |
933 return (error); | |
934 error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); | |
935 spa_close(spa, FTAG); | |
936 return (error); | |
789 | 937 } |
938 | |
939 static int | |
4451 | 940 zfs_ioc_vdev_set_state(zfs_cmd_t *zc) |
789 | 941 { |
942 spa_t *spa; | |
943 int error; | |
4451 | 944 vdev_state_t newstate = VDEV_STATE_UNKNOWN; |
789 | 945 |
2926 | 946 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
789 | 947 return (error); |
4451 | 948 switch (zc->zc_cookie) { |
949 case VDEV_STATE_ONLINE: | |
950 error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); | |
951 break; | |
952 | |
953 case VDEV_STATE_OFFLINE: | |
954 error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); | |
955 break; | |
789 | 956 |
4451 | 957 case VDEV_STATE_FAULTED: |
958 error = vdev_fault(spa, zc->zc_guid); | |
959 break; | |
789 | 960 |
4451 | 961 case VDEV_STATE_DEGRADED: |
962 error = vdev_degrade(spa, zc->zc_guid); | |
963 break; | |
964 | |
965 default: | |
966 error = EINVAL; | |
967 } | |
968 zc->zc_cookie = newstate; | |
789 | 969 spa_close(spa, FTAG); |
970 return (error); | |
971 } | |
972 | |
973 static int | |
974 zfs_ioc_vdev_attach(zfs_cmd_t *zc) | |
975 { | |
976 spa_t *spa; | |
977 int replacing = zc->zc_cookie; | |
978 nvlist_t *config; | |
979 int error; | |
980 | |
2926 | 981 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
789 | 982 return (error); |
983 | |
2676 | 984 if ((error = get_nvlist(zc, &config)) == 0) { |
1544 | 985 error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); |
789 | 986 nvlist_free(config); |
987 } | |
988 | |
989 spa_close(spa, FTAG); | |
990 return (error); | |
991 } | |
992 | |
993 static int | |
994 zfs_ioc_vdev_detach(zfs_cmd_t *zc) | |
995 { | |
996 spa_t *spa; | |
997 int error; | |
998 | |
2926 | 999 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
789 | 1000 return (error); |
1001 | |
1544 | 1002 error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); |
789 | 1003 |
1004 spa_close(spa, FTAG); | |
1005 return (error); | |
1006 } | |
1007 | |
1008 static int | |
1354
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1009 zfs_ioc_vdev_setpath(zfs_cmd_t *zc) |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1010 { |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1011 spa_t *spa; |
2676 | 1012 char *path = zc->zc_value; |
1544 | 1013 uint64_t guid = zc->zc_guid; |
1354
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1014 int error; |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1015 |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1016 error = spa_open(zc->zc_name, &spa, FTAG); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1017 if (error != 0) |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1018 return (error); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1019 |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1020 error = spa_vdev_setpath(spa, guid, path); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1021 spa_close(spa, FTAG); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1022 return (error); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1023 } |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1024 |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1025 static int |
789 | 1026 zfs_ioc_objset_stats(zfs_cmd_t *zc) |
1027 { | |
1028 objset_t *os = NULL; | |
1029 int error; | |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
1354
diff
changeset
|
1030 nvlist_t *nv; |
789 | 1031 |
1032 retry: | |
1033 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, | |
1034 DS_MODE_STANDARD | DS_MODE_READONLY, &os); | |
1035 if (error != 0) { | |
1036 /* | |
1037 * This is ugly: dmu_objset_open() can return EBUSY if | |
1038 * the objset is held exclusively. Fortunately this hold is | |
1039 * only for a short while, so we retry here. | |
1040 * This avoids user code having to handle EBUSY, | |
1041 * for example for a "zfs list". | |
1042 */ | |
1043 if (error == EBUSY) { | |
1044 delay(1); | |
1045 goto retry; | |
1046 } | |
1047 return (error); | |
1048 } | |
1049 | |
2885 | 1050 dmu_objset_fast_stat(os, &zc->zc_objset_stats); |
789 | 1051 |
2856 | 1052 if (zc->zc_nvlist_dst != 0 && |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
1354
diff
changeset
|
1053 (error = dsl_prop_get_all(os, &nv)) == 0) { |
2885 | 1054 dmu_objset_stats(os, nv); |
3087 | 1055 /* |
4577 | 1056 * NB: {zpl,zvol}_get_stats() will read the objset contents, |
3087 | 1057 * which we aren't supposed to do with a |
1058 * DS_MODE_STANDARD open, because it could be | |
1059 * inconsistent. So this is a bit of a workaround... | |
1060 */ | |
4577 | 1061 if (!zc->zc_objset_stats.dds_inconsistent) { |
1062 if (dmu_objset_type(os) == DMU_OST_ZVOL) | |
1063 VERIFY(zvol_get_stats(os, nv) == 0); | |
1064 else if (dmu_objset_type(os) == DMU_OST_ZFS) | |
1065 (void) zfs_get_stats(os, nv); | |
1066 } | |
2676 | 1067 error = put_nvlist(zc, nv); |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
1354
diff
changeset
|
1068 nvlist_free(nv); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
1354
diff
changeset
|
1069 } |
789 | 1070 |
2676 | 1071 spa_altroot(dmu_objset_spa(os), zc->zc_value, sizeof (zc->zc_value)); |
1544 | 1072 |
789 | 1073 dmu_objset_close(os); |
1074 return (error); | |
1075 } | |
1076 | |
1077 static int | |
1078 zfs_ioc_dataset_list_next(zfs_cmd_t *zc) | |
1079 { | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1080 objset_t *os; |
789 | 1081 int error; |
1082 char *p; | |
1083 | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1084 retry: |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1085 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1086 DS_MODE_STANDARD | DS_MODE_READONLY, &os); |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1087 if (error != 0) { |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1088 /* |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1089 * This is ugly: dmu_objset_open() can return EBUSY if |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1090 * the objset is held exclusively. Fortunately this hold is |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1091 * only for a short while, so we retry here. |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1092 * This avoids user code having to handle EBUSY, |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1093 * for example for a "zfs list". |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1094 */ |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1095 if (error == EBUSY) { |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1096 delay(1); |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1097 goto retry; |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1098 } |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1099 if (error == ENOENT) |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1100 error = ESRCH; |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1101 return (error); |
789 | 1102 } |
1103 | |
1104 p = strrchr(zc->zc_name, '/'); | |
1105 if (p == NULL || p[1] != '\0') | |
1106 (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); | |
1107 p = zc->zc_name + strlen(zc->zc_name); | |
1108 | |
1109 do { | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1110 error = dmu_dir_list_next(os, |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1111 sizeof (zc->zc_name) - (p - zc->zc_name), p, |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1112 NULL, &zc->zc_cookie); |
789 | 1113 if (error == ENOENT) |
1114 error = ESRCH; | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1115 } while (error == 0 && !INGLOBALZONE(curproc) && |
789 | 1116 !zone_dataset_visible(zc->zc_name, NULL)); |
1117 | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1118 /* |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1119 * If it's a hidden dataset (ie. with a '$' in its name), don't |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1120 * try to get stats for it. Userland will skip over it. |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1121 */ |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1122 if (error == 0 && strchr(zc->zc_name, '$') == NULL) |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1123 error = zfs_ioc_objset_stats(zc); /* fill in the stats */ |
789 | 1124 |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1125 dmu_objset_close(os); |
789 | 1126 return (error); |
1127 } | |
1128 | |
1129 static int | |
1130 zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) | |
1131 { | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1132 objset_t *os; |
789 | 1133 int error; |
1134 | |
1135 retry: | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1136 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1137 DS_MODE_STANDARD | DS_MODE_READONLY, &os); |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1138 if (error != 0) { |
789 | 1139 /* |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1140 * This is ugly: dmu_objset_open() can return EBUSY if |
789 | 1141 * the objset is held exclusively. Fortunately this hold is |
1142 * only for a short while, so we retry here. | |
1143 * This avoids user code having to handle EBUSY, | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1144 * for example for a "zfs list". |
789 | 1145 */ |
1146 if (error == EBUSY) { | |
1147 delay(1); | |
1148 goto retry; | |
1149 } | |
1150 if (error == ENOENT) | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1151 error = ESRCH; |
789 | 1152 return (error); |
1153 } | |
1154 | |
1003 | 1155 /* |
1156 * A dataset name of maximum length cannot have any snapshots, | |
1157 * so exit immediately. | |
1158 */ | |
1159 if (strlcat(zc->zc_name, "@", sizeof (zc->zc_name)) >= MAXNAMELEN) { | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1160 dmu_objset_close(os); |
1003 | 1161 return (ESRCH); |
789 | 1162 } |
1163 | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1164 error = dmu_snapshot_list_next(os, |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1165 sizeof (zc->zc_name) - strlen(zc->zc_name), |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1166 zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie); |
789 | 1167 if (error == ENOENT) |
1168 error = ESRCH; | |
1169 | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1170 if (error == 0) |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1171 error = zfs_ioc_objset_stats(zc); /* fill in the stats */ |
789 | 1172 |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1173 dmu_objset_close(os); |
789 | 1174 return (error); |
1175 } | |
1176 | |
1177 static int | |
4787 | 1178 zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) |
789 | 1179 { |
2676 | 1180 nvpair_t *elem; |
1181 int error; | |
1182 uint64_t intval; | |
1183 char *strval; | |
1184 | |
4543 | 1185 /* |
1186 * First validate permission to set all of the properties | |
1187 */ | |
2676 | 1188 elem = NULL; |
1189 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1190 const char *propname = nvpair_name(elem); |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1191 zfs_prop_t prop = zfs_name_to_prop(propname); |
2676 | 1192 |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1193 if (prop == ZFS_PROP_INVAL) { |
2676 | 1194 /* |
1195 * If this is a user-defined property, it must be a | |
1196 * string, and there is no further validation to do. | |
1197 */ | |
1198 if (!zfs_prop_user(propname) || | |
1199 nvpair_type(elem) != DATA_TYPE_STRING) | |
1200 return (EINVAL); | |
1201 | |
4543 | 1202 error = zfs_secpolicy_write_perms(name, |
4787 | 1203 ZFS_DELEG_PERM_USERPROP, CRED()); |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1204 if (error) |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1205 return (error); |
4543 | 1206 continue; |
2676 | 1207 } |
1208 | |
4787 | 1209 if ((error = zfs_secpolicy_setprop(name, prop, CRED())) != 0) |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1210 return (error); |
2676 | 1211 |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1212 /* |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1213 * Check that this value is valid for this pool version |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1214 */ |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1215 switch (prop) { |
3886
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1216 case ZFS_PROP_COMPRESSION: |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1217 /* |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1218 * If the user specified gzip compression, make sure |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1219 * the SPA supports it. We ignore any errors here since |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1220 * we'll catch them later. |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1221 */ |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1222 if (nvpair_type(elem) == DATA_TYPE_UINT64 && |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1223 nvpair_value_uint64(elem, &intval) == 0 && |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1224 intval >= ZIO_COMPRESS_GZIP_1 && |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1225 intval <= ZIO_COMPRESS_GZIP_9) { |
4543 | 1226 spa_t *spa; |
1227 | |
4603
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1228 if (spa_open(name, &spa, FTAG) == 0) { |
3886
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1229 if (spa_version(spa) < |
4577 | 1230 SPA_VERSION_GZIP_COMPRESSION) { |
3886
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1231 spa_close(spa, FTAG); |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1232 return (ENOTSUP); |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1233 } |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1234 |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1235 spa_close(spa, FTAG); |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1236 } |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1237 } |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1238 break; |
4603
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1239 |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1240 case ZFS_PROP_COPIES: |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1241 { |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1242 spa_t *spa; |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1243 |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1244 if (spa_open(name, &spa, FTAG) == 0) { |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1245 if (spa_version(spa) < |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1246 SPA_VERSION_DITTO_BLOCKS) { |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1247 spa_close(spa, FTAG); |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1248 return (ENOTSUP); |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1249 } |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1250 spa_close(spa, FTAG); |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1251 } |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1252 break; |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1253 } |
2676 | 1254 } |
4543 | 1255 } |
1256 | |
1257 elem = NULL; | |
1258 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1259 const char *propname = nvpair_name(elem); |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1260 zfs_prop_t prop = zfs_name_to_prop(propname); |
4543 | 1261 |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1262 if (prop == ZFS_PROP_INVAL) { |
4543 | 1263 VERIFY(nvpair_value_string(elem, &strval) == 0); |
1264 error = dsl_prop_set(name, propname, 1, | |
1265 strlen(strval) + 1, strval); | |
1266 if (error == 0) | |
1267 continue; | |
1268 else | |
1269 return (error); | |
1270 } | |
2676 | 1271 |
1272 switch (prop) { | |
1273 case ZFS_PROP_QUOTA: | |
1274 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
4577 | 1275 (error = dsl_dir_set_quota(name, intval)) != 0) |
2676 | 1276 return (error); |
1277 break; | |
1278 | |
1279 case ZFS_PROP_RESERVATION: | |
1280 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
1281 (error = dsl_dir_set_reservation(name, | |
1282 intval)) != 0) | |
1283 return (error); | |
1284 break; | |
789 | 1285 |
2676 | 1286 case ZFS_PROP_VOLSIZE: |
1287 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
4787 | 1288 (error = zvol_set_volsize(name, |
1289 ddi_driver_major(zfs_dip), intval)) != 0) | |
2676 | 1290 return (error); |
1291 break; | |
1292 | |
1293 case ZFS_PROP_VOLBLOCKSIZE: | |
1294 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
4577 | 1295 (error = zvol_set_volblocksize(name, intval)) != 0) |
1296 return (error); | |
1297 break; | |
1298 | |
1299 case ZFS_PROP_VERSION: | |
1300 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
1301 (error = zfs_set_version(name, intval)) != 0) | |
2676 | 1302 return (error); |
1303 break; | |
1304 | |
1305 default: | |
1306 if (nvpair_type(elem) == DATA_TYPE_STRING) { | |
1307 if (zfs_prop_get_type(prop) != | |
4787 | 1308 PROP_TYPE_STRING) |
2676 | 1309 return (EINVAL); |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1310 VERIFY(nvpair_value_string(elem, &strval) == 0); |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1311 if ((error = dsl_prop_set(name, |
2676 | 1312 nvpair_name(elem), 1, strlen(strval) + 1, |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1313 strval)) != 0) |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1314 return (error); |
2676 | 1315 } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { |
2885 | 1316 const char *unused; |
1317 | |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1318 VERIFY(nvpair_value_uint64(elem, &intval) == 0); |
2676 | 1319 |
1320 switch (zfs_prop_get_type(prop)) { | |
4787 | 1321 case PROP_TYPE_NUMBER: |
2676 | 1322 break; |
4787 | 1323 case PROP_TYPE_BOOLEAN: |
2676 | 1324 if (intval > 1) |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1325 return (EINVAL); |
2676 | 1326 break; |
4787 | 1327 case PROP_TYPE_STRING: |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1328 return (EINVAL); |
4787 | 1329 case PROP_TYPE_INDEX: |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1330 if (zfs_prop_index_to_string(prop, |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1331 intval, &unused) != 0) |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1332 return (EINVAL); |
2676 | 1333 break; |
1334 default: | |
4577 | 1335 cmn_err(CE_PANIC, |
1336 "unknown property type"); | |
2676 | 1337 break; |
1338 } | |
1339 | |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1340 if ((error = dsl_prop_set(name, propname, |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1341 8, 1, &intval)) != 0) |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1342 return (error); |
2676 | 1343 } else { |
1344 return (EINVAL); | |
1345 } | |
1346 break; | |
1347 } | |
1348 } | |
1349 | |
1350 return (0); | |
789 | 1351 } |
1352 | |
1353 static int | |
2676 | 1354 zfs_ioc_set_prop(zfs_cmd_t *zc) |
789 | 1355 { |
2676 | 1356 nvlist_t *nvl; |
1357 int error; | |
789 | 1358 |
2676 | 1359 /* |
1360 * If zc_value is set, then this is an attempt to inherit a value. | |
1361 * Otherwise, zc_nvlist refers to a list of properties to set. | |
1362 */ | |
1363 if (zc->zc_value[0] != '\0') { | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1364 zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1365 |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1366 if (prop == ZFS_PROP_INVAL) { |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1367 if (!zfs_prop_user(zc->zc_value)) |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1368 return (EINVAL); |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1369 error = zfs_secpolicy_write_perms(zc->zc_name, |
4787 | 1370 ZFS_DELEG_PERM_USERPROP, CRED()); |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1371 } else { |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1372 if (!zfs_prop_inheritable(prop)) |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1373 return (EINVAL); |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1374 error = zfs_secpolicy_setprop(zc->zc_name, |
4787 | 1375 prop, CRED()); |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1376 } |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1377 if (error) |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1378 return (error); |
2676 | 1379 |
1380 return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); | |
1381 } | |
1382 | |
1383 if ((error = get_nvlist(zc, &nvl)) != 0) | |
1384 return (error); | |
1385 | |
4787 | 1386 error = zfs_set_prop_nvlist(zc->zc_name, nvl); |
4543 | 1387 |
2676 | 1388 nvlist_free(nvl); |
1389 return (error); | |
789 | 1390 } |
1391 | |
1392 static int | |
4098
0a182c2128e6
6545726 make ZFS_IOC_POOL_*_PROPS in sync with zfs_ioc_pool_props_*
lling
parents:
4007
diff
changeset
|
1393 zfs_ioc_pool_set_props(zfs_cmd_t *zc) |
3912 | 1394 { |
1395 nvlist_t *nvl; | |
1396 int error, reset_bootfs = 0; | |
1397 uint64_t objnum; | |
4543 | 1398 uint64_t intval; |
3912 | 1399 zpool_prop_t prop; |
1400 nvpair_t *elem; | |
1401 char *propname, *strval; | |
1402 spa_t *spa; | |
1403 vdev_t *rvdev; | |
1404 char *vdev_type; | |
1405 objset_t *os; | |
1406 | |
1407 if ((error = get_nvlist(zc, &nvl)) != 0) | |
1408 return (error); | |
1409 | |
1410 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { | |
1411 nvlist_free(nvl); | |
1412 return (error); | |
1413 } | |
1414 | |
4577 | 1415 if (spa_version(spa) < SPA_VERSION_BOOTFS) { |
3912 | 1416 nvlist_free(nvl); |
1417 spa_close(spa, FTAG); | |
1418 return (ENOTSUP); | |
1419 } | |
1420 | |
1421 elem = NULL; | |
1422 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { | |
1423 | |
1424 propname = nvpair_name(elem); | |
1425 | |
1426 if ((prop = zpool_name_to_prop(propname)) == | |
1427 ZFS_PROP_INVAL) { | |
1428 nvlist_free(nvl); | |
1429 spa_close(spa, FTAG); | |
1430 return (EINVAL); | |
1431 } | |
1432 | |
1433 switch (prop) { | |
4543 | 1434 case ZPOOL_PROP_DELEGATION: |
1435 VERIFY(nvpair_value_uint64(elem, &intval) == 0); | |
1436 if (intval > 1) | |
1437 error = EINVAL; | |
1438 break; | |
4451 | 1439 case ZPOOL_PROP_BOOTFS: |
3912 | 1440 /* |
1441 * A bootable filesystem can not be on a RAIDZ pool | |
1442 * nor a striped pool with more than 1 device. | |
1443 */ | |
1444 rvdev = spa->spa_root_vdev; | |
1445 vdev_type = | |
1446 rvdev->vdev_child[0]->vdev_ops->vdev_op_type; | |
1447 if (strcmp(vdev_type, VDEV_TYPE_RAIDZ) == 0 || | |
1448 (strcmp(vdev_type, VDEV_TYPE_MIRROR) != 0 && | |
1449 rvdev->vdev_children > 1)) { | |
1450 error = ENOTSUP; | |
1451 break; | |
1452 } | |
1453 | |
1454 reset_bootfs = 1; | |
1455 | |
1456 VERIFY(nvpair_value_string(elem, &strval) == 0); | |
1457 if (strval == NULL || strval[0] == '\0') { | |
4451 | 1458 objnum = zpool_prop_default_numeric( |
1459 ZPOOL_PROP_BOOTFS); | |
3912 | 1460 break; |
1461 } | |
1462 | |
1463 if (error = dmu_objset_open(strval, DMU_OST_ZFS, | |
1464 DS_MODE_STANDARD | DS_MODE_READONLY, &os)) | |
1465 break; | |
1466 objnum = dmu_objset_id(os); | |
1467 dmu_objset_close(os); | |
1468 break; | |
1469 } | |
1470 | |
1471 if (error) | |
1472 break; | |
1473 } | |
1474 if (error == 0) { | |
1475 if (reset_bootfs) { | |
1476 VERIFY(nvlist_remove(nvl, | |
4451 | 1477 zpool_prop_to_name(ZPOOL_PROP_BOOTFS), |
3912 | 1478 DATA_TYPE_STRING) == 0); |
1479 VERIFY(nvlist_add_uint64(nvl, | |
4451 | 1480 zpool_prop_to_name(ZPOOL_PROP_BOOTFS), |
1481 objnum) == 0); | |
3912 | 1482 } |
1483 error = spa_set_props(spa, nvl); | |
1484 } | |
1485 | |
1486 nvlist_free(nvl); | |
1487 spa_close(spa, FTAG); | |
1488 | |
1489 return (error); | |
1490 } | |
1491 | |
1492 static int | |
4098
0a182c2128e6
6545726 make ZFS_IOC_POOL_*_PROPS in sync with zfs_ioc_pool_props_*
lling
parents:
4007
diff
changeset
|
1493 zfs_ioc_pool_get_props(zfs_cmd_t *zc) |
3912 | 1494 { |
1495 spa_t *spa; | |
1496 int error; | |
1497 nvlist_t *nvp = NULL; | |
1498 | |
1499 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) | |
1500 return (error); | |
1501 | |
1502 error = spa_get_props(spa, &nvp); | |
1503 | |
1504 if (error == 0 && zc->zc_nvlist_dst != NULL) | |
1505 error = put_nvlist(zc, nvp); | |
1506 else | |
1507 error = EFAULT; | |
1508 | |
1509 spa_close(spa, FTAG); | |
1510 | |
1511 if (nvp) | |
1512 nvlist_free(nvp); | |
1513 return (error); | |
1514 } | |
1515 | |
1516 static int | |
4543 | 1517 zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) |
1518 { | |
1519 nvlist_t *nvp; | |
1520 int error; | |
1521 uint32_t uid; | |
1522 uint32_t gid; | |
1523 uint32_t *groups; | |
1524 uint_t group_cnt; | |
1525 cred_t *usercred; | |
1526 | |
1527 if ((error = get_nvlist(zc, &nvp)) != 0) { | |
1528 return (error); | |
1529 } | |
1530 | |
1531 if ((error = nvlist_lookup_uint32(nvp, | |
1532 ZFS_DELEG_PERM_UID, &uid)) != 0) { | |
1533 nvlist_free(nvp); | |
1534 return (EPERM); | |
1535 } | |
1536 | |
1537 if ((error = nvlist_lookup_uint32(nvp, | |
1538 ZFS_DELEG_PERM_GID, &gid)) != 0) { | |
1539 nvlist_free(nvp); | |
1540 return (EPERM); | |
1541 } | |
1542 | |
1543 if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, | |
1544 &groups, &group_cnt)) != 0) { | |
1545 nvlist_free(nvp); | |
1546 return (EPERM); | |
1547 } | |
1548 usercred = cralloc(); | |
1549 if ((crsetugid(usercred, uid, gid) != 0) || | |
1550 (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { | |
1551 nvlist_free(nvp); | |
1552 crfree(usercred); | |
1553 return (EPERM); | |
1554 } | |
1555 nvlist_free(nvp); | |
1556 error = dsl_deleg_access(zc->zc_name, | |
4787 | 1557 zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); |
4543 | 1558 crfree(usercred); |
1559 return (error); | |
1560 } | |
1561 | |
1562 static int | |
1563 zfs_ioc_set_fsacl(zfs_cmd_t *zc) | |
1564 { | |
1565 int error; | |
1566 nvlist_t *fsaclnv = NULL; | |
1567 | |
1568 if ((error = get_nvlist(zc, &fsaclnv)) != 0) | |
1569 return (error); | |
1570 | |
1571 /* | |
1572 * Verify nvlist is constructed correctly | |
1573 */ | |
1574 if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { | |
1575 nvlist_free(fsaclnv); | |
1576 return (EINVAL); | |
1577 } | |
1578 | |
1579 /* | |
1580 * If we don't have PRIV_SYS_MOUNT, then validate | |
1581 * that user is allowed to hand out each permission in | |
1582 * the nvlist(s) | |
1583 */ | |
1584 | |
4787 | 1585 error = secpolicy_zfs(CRED()); |
4543 | 1586 if (error) { |
4787 | 1587 if (zc->zc_perm_action == B_FALSE) { |
1588 error = dsl_deleg_can_allow(zc->zc_name, | |
1589 fsaclnv, CRED()); | |
1590 } else { | |
1591 error = dsl_deleg_can_unallow(zc->zc_name, | |
1592 fsaclnv, CRED()); | |
1593 } | |
4543 | 1594 } |
1595 | |
1596 if (error == 0) | |
1597 error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); | |
1598 | |
1599 nvlist_free(fsaclnv); | |
1600 return (error); | |
1601 } | |
1602 | |
1603 static int | |
1604 zfs_ioc_get_fsacl(zfs_cmd_t *zc) | |
1605 { | |
1606 nvlist_t *nvp; | |
1607 int error; | |
1608 | |
1609 if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { | |
1610 error = put_nvlist(zc, nvp); | |
1611 nvlist_free(nvp); | |
1612 } | |
1613 | |
1614 return (error); | |
1615 } | |
1616 | |
1617 static int | |
789 | 1618 zfs_ioc_create_minor(zfs_cmd_t *zc) |
1619 { | |
4787 | 1620 return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); |
789 | 1621 } |
1622 | |
1623 static int | |
1624 zfs_ioc_remove_minor(zfs_cmd_t *zc) | |
1625 { | |
2676 | 1626 return (zvol_remove_minor(zc->zc_name)); |
789 | 1627 } |
1628 | |
1629 /* | |
1630 * Search the vfs list for a specified resource. Returns a pointer to it | |
1631 * or NULL if no suitable entry is found. The caller of this routine | |
1632 * is responsible for releasing the returned vfs pointer. | |
1633 */ | |
1634 static vfs_t * | |
1635 zfs_get_vfs(const char *resource) | |
1636 { | |
1637 struct vfs *vfsp; | |
1638 struct vfs *vfs_found = NULL; | |
1639 | |
1640 vfs_list_read_lock(); | |
1641 vfsp = rootvfs; | |
1642 do { | |
1643 if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { | |
1644 VFS_HOLD(vfsp); | |
1645 vfs_found = vfsp; | |
1646 break; | |
1647 } | |
1648 vfsp = vfsp->vfs_next; | |
1649 } while (vfsp != rootvfs); | |
1650 vfs_list_unlock(); | |
1651 return (vfs_found); | |
1652 } | |
1653 | |
4543 | 1654 /* ARGSUSED */ |
789 | 1655 static void |
4543 | 1656 zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) |
789 | 1657 { |
4577 | 1658 nvlist_t *nvprops = arg; |
1659 uint64_t version = ZPL_VERSION; | |
1660 | |
1661 (void) nvlist_lookup_uint64(nvprops, | |
1662 zfs_prop_to_name(ZFS_PROP_VERSION), &version); | |
1663 | |
1664 zfs_create_fs(os, cr, version, tx); | |
789 | 1665 } |
1666 | |
1667 static int | |
1668 zfs_ioc_create(zfs_cmd_t *zc) | |
1669 { | |
1670 objset_t *clone; | |
1671 int error = 0; | |
4543 | 1672 nvlist_t *nvprops = NULL; |
1673 void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); | |
789 | 1674 dmu_objset_type_t type = zc->zc_objset_type; |
1675 | |
1676 switch (type) { | |
1677 | |
1678 case DMU_OST_ZFS: | |
1679 cbfunc = zfs_create_cb; | |
1680 break; | |
1681 | |
1682 case DMU_OST_ZVOL: | |
1683 cbfunc = zvol_create_cb; | |
1684 break; | |
1685 | |
1686 default: | |
2199 | 1687 cbfunc = NULL; |
1688 } | |
1689 if (strchr(zc->zc_name, '@')) | |
789 | 1690 return (EINVAL); |
1691 | |
2676 | 1692 if (zc->zc_nvlist_src != NULL && |
4543 | 1693 (error = get_nvlist(zc, &nvprops)) != 0) |
2676 | 1694 return (error); |
1695 | |
1696 if (zc->zc_value[0] != '\0') { | |
789 | 1697 /* |
1698 * We're creating a clone of an existing snapshot. | |
1699 */ | |
2676 | 1700 zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; |
1701 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { | |
4543 | 1702 nvlist_free(nvprops); |
789 | 1703 return (EINVAL); |
2676 | 1704 } |
789 | 1705 |
2676 | 1706 error = dmu_objset_open(zc->zc_value, type, |
789 | 1707 DS_MODE_STANDARD | DS_MODE_READONLY, &clone); |
2676 | 1708 if (error) { |
4543 | 1709 nvlist_free(nvprops); |
789 | 1710 return (error); |
2676 | 1711 } |
789 | 1712 error = dmu_objset_create(zc->zc_name, type, clone, NULL, NULL); |
1713 dmu_objset_close(clone); | |
1714 } else { | |
2676 | 1715 if (cbfunc == NULL) { |
4543 | 1716 nvlist_free(nvprops); |
2199 | 1717 return (EINVAL); |
2676 | 1718 } |
1719 | |
789 | 1720 if (type == DMU_OST_ZVOL) { |
2676 | 1721 uint64_t volsize, volblocksize; |
1722 | |
4543 | 1723 if (nvprops == NULL || |
1724 nvlist_lookup_uint64(nvprops, | |
2676 | 1725 zfs_prop_to_name(ZFS_PROP_VOLSIZE), |
1726 &volsize) != 0) { | |
4543 | 1727 nvlist_free(nvprops); |
2676 | 1728 return (EINVAL); |
1729 } | |
1730 | |
4543 | 1731 if ((error = nvlist_lookup_uint64(nvprops, |
2676 | 1732 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), |
1733 &volblocksize)) != 0 && error != ENOENT) { | |
4543 | 1734 nvlist_free(nvprops); |
2676 | 1735 return (EINVAL); |
1736 } | |
1133
335d069294d1
6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents:
1003
diff
changeset
|
1737 |
2676 | 1738 if (error != 0) |
1739 volblocksize = zfs_prop_default_numeric( | |
1740 ZFS_PROP_VOLBLOCKSIZE); | |
1741 | |
1742 if ((error = zvol_check_volblocksize( | |
1743 volblocksize)) != 0 || | |
1744 (error = zvol_check_volsize(volsize, | |
1745 volblocksize)) != 0) { | |
4543 | 1746 nvlist_free(nvprops); |
789 | 1747 return (error); |
2676 | 1748 } |
4577 | 1749 } else if (type == DMU_OST_ZFS) { |
1750 uint64_t version; | |
1751 | |
1752 if (0 == nvlist_lookup_uint64(nvprops, | |
1753 zfs_prop_to_name(ZFS_PROP_VERSION), &version) && | |
1754 (version < ZPL_VERSION_INITIAL || | |
1755 version > ZPL_VERSION)) { | |
1756 nvlist_free(nvprops); | |
1757 return (EINVAL); | |
1758 } | |
2676 | 1759 } |
1133
335d069294d1
6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents:
1003
diff
changeset
|
1760 |
2676 | 1761 error = dmu_objset_create(zc->zc_name, type, NULL, cbfunc, |
4543 | 1762 nvprops); |
789 | 1763 } |
2676 | 1764 |
1765 /* | |
1766 * It would be nice to do this atomically. | |
1767 */ | |
1768 if (error == 0) { | |
4787 | 1769 if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) |
2676 | 1770 (void) dmu_objset_destroy(zc->zc_name); |
1771 } | |
1772 | |
4543 | 1773 nvlist_free(nvprops); |
789 | 1774 return (error); |
1775 } | |
1776 | |
1777 static int | |
2199 | 1778 zfs_ioc_snapshot(zfs_cmd_t *zc) |
1779 { | |
2676 | 1780 if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) |
2199 | 1781 return (EINVAL); |
1782 return (dmu_objset_snapshot(zc->zc_name, | |
2676 | 1783 zc->zc_value, zc->zc_cookie)); |
2199 | 1784 } |
1785 | |
4007 | 1786 int |
2199 | 1787 zfs_unmount_snap(char *name, void *arg) |
789 | 1788 { |
2199 | 1789 char *snapname = arg; |
1790 char *cp; | |
2417 | 1791 vfs_t *vfsp = NULL; |
2199 | 1792 |
1793 /* | |
1794 * Snapshots (which are under .zfs control) must be unmounted | |
1795 * before they can be destroyed. | |
1796 */ | |
1797 | |
1798 if (snapname) { | |
1799 (void) strcat(name, "@"); | |
1800 (void) strcat(name, snapname); | |
1801 vfsp = zfs_get_vfs(name); | |
1802 cp = strchr(name, '@'); | |
1803 *cp = '\0'; | |
2417 | 1804 } else if (strchr(name, '@')) { |
2199 | 1805 vfsp = zfs_get_vfs(name); |
1806 } | |
1807 | |
1808 if (vfsp) { | |
1809 /* | |
1810 * Always force the unmount for snapshots. | |
1811 */ | |
1812 int flag = MS_FORCE; | |
789 | 1813 int err; |
1814 | |
2199 | 1815 if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { |
1816 VFS_RELE(vfsp); | |
1817 return (err); | |
1818 } | |
1819 VFS_RELE(vfsp); | |
1820 if ((err = dounmount(vfsp, flag, kcred)) != 0) | |
1821 return (err); | |
1822 } | |
1823 return (0); | |
1824 } | |
1825 | |
1826 static int | |
1827 zfs_ioc_destroy_snaps(zfs_cmd_t *zc) | |
1828 { | |
1829 int err; | |
789 | 1830 |
2676 | 1831 if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) |
2199 | 1832 return (EINVAL); |
1833 err = dmu_objset_find(zc->zc_name, | |
2676 | 1834 zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); |
2199 | 1835 if (err) |
1836 return (err); | |
2676 | 1837 return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); |
2199 | 1838 } |
1839 | |
1840 static int | |
1841 zfs_ioc_destroy(zfs_cmd_t *zc) | |
1842 { | |
1843 if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { | |
1844 int err = zfs_unmount_snap(zc->zc_name, NULL); | |
1845 if (err) | |
1846 return (err); | |
789 | 1847 } |
1848 | |
1849 return (dmu_objset_destroy(zc->zc_name)); | |
1850 } | |
1851 | |
1852 static int | |
1853 zfs_ioc_rollback(zfs_cmd_t *zc) | |
1854 { | |
1855 return (dmu_objset_rollback(zc->zc_name)); | |
1856 } | |
1857 | |
1858 static int | |
1859 zfs_ioc_rename(zfs_cmd_t *zc) | |
1860 { | |
4490 | 1861 boolean_t recursive = zc->zc_cookie & 1; |
4007 | 1862 |
2676 | 1863 zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; |
1864 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) | |
789 | 1865 return (EINVAL); |
1866 | |
4007 | 1867 /* |
1868 * Unmount snapshot unless we're doing a recursive rename, | |
1869 * in which case the dataset code figures out which snapshots | |
1870 * to unmount. | |
1871 */ | |
1872 if (!recursive && strchr(zc->zc_name, '@') != NULL && | |
789 | 1873 zc->zc_objset_type == DMU_OST_ZFS) { |
2199 | 1874 int err = zfs_unmount_snap(zc->zc_name, NULL); |
1875 if (err) | |
1876 return (err); | |
789 | 1877 } |
1878 | |
4007 | 1879 return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); |
789 | 1880 } |
1881 | |
1882 static int | |
1883 zfs_ioc_recvbackup(zfs_cmd_t *zc) | |
1884 { | |
1885 file_t *fp; | |
1886 int error, fd; | |
2885 | 1887 offset_t new_off; |
789 | 1888 |
3265
967e0fca6143
6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents:
3087
diff
changeset
|
1889 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || |
967e0fca6143
6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents:
3087
diff
changeset
|
1890 strchr(zc->zc_value, '@') == NULL) |
967e0fca6143
6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents:
3087
diff
changeset
|
1891 return (EINVAL); |
967e0fca6143
6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents:
3087
diff
changeset
|
1892 |
789 | 1893 fd = zc->zc_cookie; |
1894 fp = getf(fd); | |
1895 if (fp == NULL) | |
1896 return (EBADF); | |
2676 | 1897 error = dmu_recvbackup(zc->zc_value, &zc->zc_begin_record, |
1898 &zc->zc_cookie, (boolean_t)zc->zc_guid, fp->f_vnode, | |
2665 | 1899 fp->f_offset); |
2885 | 1900 |
1901 new_off = fp->f_offset + zc->zc_cookie; | |
1902 if (VOP_SEEK(fp->f_vnode, fp->f_offset, &new_off) == 0) | |
1903 fp->f_offset = new_off; | |
1904 | |
789 | 1905 releasef(fd); |
1906 return (error); | |
1907 } | |
1908 | |
1909 static int | |
1910 zfs_ioc_sendbackup(zfs_cmd_t *zc) | |
1911 { | |
1912 objset_t *fromsnap = NULL; | |
1913 objset_t *tosnap; | |
1914 file_t *fp; | |
1915 int error; | |
1916 | |
1917 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, | |
1918 DS_MODE_STANDARD | DS_MODE_READONLY, &tosnap); | |
1919 if (error) | |
1920 return (error); | |
1921 | |
2676 | 1922 if (zc->zc_value[0] != '\0') { |
2885 | 1923 char buf[MAXPATHLEN]; |
1924 char *cp; | |
1925 | |
1926 (void) strncpy(buf, zc->zc_name, sizeof (buf)); | |
1927 cp = strchr(buf, '@'); | |
1928 if (cp) | |
1929 *(cp+1) = 0; | |
1930 (void) strncat(buf, zc->zc_value, sizeof (buf)); | |
1931 error = dmu_objset_open(buf, DMU_OST_ANY, | |
789 | 1932 DS_MODE_STANDARD | DS_MODE_READONLY, &fromsnap); |
1933 if (error) { | |
1934 dmu_objset_close(tosnap); | |
1935 return (error); | |
1936 } | |
1937 } | |
1938 | |
1939 fp = getf(zc->zc_cookie); | |
1940 if (fp == NULL) { | |
1941 dmu_objset_close(tosnap); | |
1942 if (fromsnap) | |
1943 dmu_objset_close(fromsnap); | |
1944 return (EBADF); | |
1945 } | |
1946 | |
1947 error = dmu_sendbackup(tosnap, fromsnap, fp->f_vnode); | |
1948 | |
1949 releasef(zc->zc_cookie); | |
1950 if (fromsnap) | |
1951 dmu_objset_close(fromsnap); | |
1952 dmu_objset_close(tosnap); | |
1953 return (error); | |
1954 } | |
1955 | |
1544 | 1956 static int |
1957 zfs_ioc_inject_fault(zfs_cmd_t *zc) | |
1958 { | |
1959 int id, error; | |
1960 | |
1961 error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, | |
1962 &zc->zc_inject_record); | |
1963 | |
1964 if (error == 0) | |
1965 zc->zc_guid = (uint64_t)id; | |
1966 | |
1967 return (error); | |
1968 } | |
1969 | |
1970 static int | |
1971 zfs_ioc_clear_fault(zfs_cmd_t *zc) | |
1972 { | |
1973 return (zio_clear_fault((int)zc->zc_guid)); | |
1974 } | |
1975 | |
1976 static int | |
1977 zfs_ioc_inject_list_next(zfs_cmd_t *zc) | |
1978 { | |
1979 int id = (int)zc->zc_guid; | |
1980 int error; | |
1981 | |
1982 error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), | |
1983 &zc->zc_inject_record); | |
1984 | |
1985 zc->zc_guid = id; | |
1986 | |
1987 return (error); | |
1988 } | |
1989 | |
1990 static int | |
1991 zfs_ioc_error_log(zfs_cmd_t *zc) | |
1992 { | |
1993 spa_t *spa; | |
1994 int error; | |
2676 | 1995 size_t count = (size_t)zc->zc_nvlist_dst_size; |
1544 | 1996 |
1997 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) | |
1998 return (error); | |
1999 | |
2676 | 2000 error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, |
1544 | 2001 &count); |
2002 if (error == 0) | |
2676 | 2003 zc->zc_nvlist_dst_size = count; |
1544 | 2004 else |
2676 | 2005 zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); |
1544 | 2006 |
2007 spa_close(spa, FTAG); | |
2008 | |
2009 return (error); | |
2010 } | |
2011 | |
2012 static int | |
2013 zfs_ioc_clear(zfs_cmd_t *zc) | |
2014 { | |
2015 spa_t *spa; | |
2016 vdev_t *vd; | |
4808 | 2017 uint64_t txg; |
1544 | 2018 int error; |
2019 | |
2020 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) | |
2021 return (error); | |
2022 | |
4451 | 2023 txg = spa_vdev_enter(spa); |
1544 | 2024 |
2676 | 2025 if (zc->zc_guid == 0) { |
1544 | 2026 vd = NULL; |
2676 | 2027 } else if ((vd = spa_lookup_by_guid(spa, zc->zc_guid)) == NULL) { |
4451 | 2028 (void) spa_vdev_exit(spa, NULL, txg, ENODEV); |
1544 | 2029 spa_close(spa, FTAG); |
2030 return (ENODEV); | |
2031 } | |
2032 | |
2033 vdev_clear(spa, vd); | |
2034 | |
4451 | 2035 (void) spa_vdev_exit(spa, NULL, txg, 0); |
1544 | 2036 |
2037 spa_close(spa, FTAG); | |
2038 | |
2039 return (0); | |
2040 } | |
2041 | |
2042 static int | |
2082 | 2043 zfs_ioc_promote(zfs_cmd_t *zc) |
2044 { | |
2417 | 2045 char *cp; |
2046 | |
2047 /* | |
2048 * We don't need to unmount *all* the origin fs's snapshots, but | |
2049 * it's easier. | |
2050 */ | |
2676 | 2051 cp = strchr(zc->zc_value, '@'); |
2417 | 2052 if (cp) |
2053 *cp = '\0'; | |
2676 | 2054 (void) dmu_objset_find(zc->zc_value, |
2417 | 2055 zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); |
2082 | 2056 return (dsl_dataset_promote(zc->zc_name)); |
2057 } | |
2058 | |
4543 | 2059 /* |
2060 * We don't want to have a hard dependency | |
2061 * against some special symbols in sharefs | |
2062 * and nfs. Determine them if needed when | |
2063 * the first file system is shared. | |
2064 * Neither sharefs or nfs are unloadable modules. | |
2065 */ | |
2066 int (*zexport_fs)(void *arg); | |
2067 int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); | |
2068 | |
2069 int zfs_share_inited; | |
2070 ddi_modhandle_t nfs_mod; | |
2071 ddi_modhandle_t sharefs_mod; | |
2072 kmutex_t zfs_share_lock; | |
2073 | |
2074 static int | |
2075 zfs_ioc_share(zfs_cmd_t *zc) | |
2076 { | |
2077 int error; | |
2078 int opcode; | |
2079 | |
2080 if (zfs_share_inited == 0) { | |
2081 mutex_enter(&zfs_share_lock); | |
2082 nfs_mod = ddi_modopen("fs/nfs", KRTLD_MODE_FIRST, &error); | |
2083 sharefs_mod = ddi_modopen("fs/sharefs", | |
2084 KRTLD_MODE_FIRST, &error); | |
2085 if (nfs_mod == NULL || sharefs_mod == NULL) { | |
2086 mutex_exit(&zfs_share_lock); | |
2087 return (ENOSYS); | |
2088 } | |
2089 if (zexport_fs == NULL && ((zexport_fs = (int (*)(void *)) | |
2090 ddi_modsym(nfs_mod, "nfs_export", &error)) == NULL)) { | |
2091 mutex_exit(&zfs_share_lock); | |
2092 return (ENOSYS); | |
2093 } | |
2094 | |
2095 if (zshare_fs == NULL && ((zshare_fs = | |
2096 (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) | |
2097 ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { | |
2098 mutex_exit(&zfs_share_lock); | |
2099 return (ENOSYS); | |
2100 } | |
2101 zfs_share_inited = 1; | |
2102 mutex_exit(&zfs_share_lock); | |
2103 } | |
2104 | |
2105 if (error = zexport_fs((void *)(uintptr_t)zc->zc_share.z_exportdata)) | |
2106 return (error); | |
2107 | |
2108 opcode = (zc->zc_share.z_sharetype == B_TRUE) ? | |
2109 SHAREFS_ADD : SHAREFS_REMOVE; | |
2110 | |
2111 error = zshare_fs(opcode, | |
2112 (void *)(uintptr_t)zc->zc_share.z_sharedata, | |
2113 zc->zc_share.z_sharemax); | |
2114 | |
2115 return (error); | |
2116 | |
2117 } | |
2118 | |
2119 /* | |
2120 * pool destroy and pool export don't log the history as part of zfsdev_ioctl, | |
2121 * but rather zfs_ioc_pool_create, and zfs_ioc_pool_export do the loggin | |
2122 * of those commands. | |
2123 */ | |
789 | 2124 static zfs_ioc_vec_t zfs_ioc_vec[] = { |
4715
e8d212dda064
6535695 Panic: shpp->sh_eof == shpp->sh_pool_create_len, file: ../../common/fs/zfs/spa_history.c, line: 235
ek110237
parents:
4670
diff
changeset
|
2125 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, |
4577 | 2126 { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, |
2127 { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2128 { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, | |
2129 { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, | |
2130 { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, | |
2131 { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, | |
2132 { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2133 { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, | |
2134 { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2135 { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, | |
2136 { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2137 { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2138 { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2139 { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2140 { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2141 { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, | |
2142 { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, | |
4543 | 2143 { zfs_ioc_dataset_list_next, zfs_secpolicy_read, |
4577 | 2144 DATASET_NAME, B_FALSE }, |
4543 | 2145 { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, |
4577 | 2146 DATASET_NAME, B_FALSE }, |
2147 { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, | |
2148 { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, | |
2149 { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, | |
2150 { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, | |
2151 { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, | |
2152 { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, | |
2153 { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, | |
2154 { zfs_ioc_recvbackup, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, | |
2155 { zfs_ioc_sendbackup, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, | |
2156 { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, | |
2157 { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, | |
2158 { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, | |
2159 { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, | |
2160 { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2161 { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, | |
2162 { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, | |
2163 { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, | |
2164 { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, | |
2165 { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, | |
2166 { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2167 { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, | |
2168 { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, | |
2169 { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, | |
4543 | 2170 { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, |
4577 | 2171 DATASET_NAME, B_FALSE }, |
2172 { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE } | |
789 | 2173 }; |
2174 | |
2175 static int | |
2176 zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) | |
2177 { | |
2178 zfs_cmd_t *zc; | |
2179 uint_t vec; | |
2199 | 2180 int error, rc; |
789 | 2181 |
2182 if (getminor(dev) != 0) | |
2183 return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); | |
2184 | |
2185 vec = cmd - ZFS_IOC; | |
4787 | 2186 ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); |
789 | 2187 |
2188 if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) | |
2189 return (EINVAL); | |
2190 | |
2191 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); | |
2192 | |
2193 error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); | |
2194 | |
4787 | 2195 if (error == 0) |
4543 | 2196 error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); |
789 | 2197 |
2198 /* | |
2199 * Ensure that all pool/dataset names are valid before we pass down to | |
2200 * the lower layers. | |
2201 */ | |
2202 if (error == 0) { | |
2203 zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; | |
2204 switch (zfs_ioc_vec[vec].zvec_namecheck) { | |
4577 | 2205 case POOL_NAME: |
789 | 2206 if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) |
2207 error = EINVAL; | |
2208 break; | |
2209 | |
4577 | 2210 case DATASET_NAME: |
789 | 2211 if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) |
2212 error = EINVAL; | |
2213 break; | |
2856 | 2214 |
4577 | 2215 case NO_NAME: |
2856 | 2216 break; |
789 | 2217 } |
2218 } | |
2219 | |
2220 if (error == 0) | |
2221 error = zfs_ioc_vec[vec].zvec_func(zc); | |
2222 | |
2199 | 2223 rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); |
4543 | 2224 if (error == 0) { |
2199 | 2225 error = rc; |
4543 | 2226 if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) |
2227 zfs_log_history(zc); | |
2228 } | |
789 | 2229 |
2230 kmem_free(zc, sizeof (zfs_cmd_t)); | |
2231 return (error); | |
2232 } | |
2233 | |
2234 static int | |
2235 zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) | |
2236 { | |
2237 if (cmd != DDI_ATTACH) | |
2238 return (DDI_FAILURE); | |
2239 | |
2240 if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, | |
2241 DDI_PSEUDO, 0) == DDI_FAILURE) | |
2242 return (DDI_FAILURE); | |
2243 | |
2244 zfs_dip = dip; | |
2245 | |
2246 ddi_report_dev(dip); | |
2247 | |
2248 return (DDI_SUCCESS); | |
2249 } | |
2250 | |
2251 static int | |
2252 zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) | |
2253 { | |
2254 if (spa_busy() || zfs_busy() || zvol_busy()) | |
2255 return (DDI_FAILURE); | |
2256 | |
2257 if (cmd != DDI_DETACH) | |
2258 return (DDI_FAILURE); | |
2259 | |
2260 zfs_dip = NULL; | |
2261 | |
2262 ddi_prop_remove_all(dip); | |
2263 ddi_remove_minor_node(dip, NULL); | |
2264 | |
2265 return (DDI_SUCCESS); | |
2266 } | |
2267 | |
2268 /*ARGSUSED*/ | |
2269 static int | |
2270 zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) | |
2271 { | |
2272 switch (infocmd) { | |
2273 case DDI_INFO_DEVT2DEVINFO: | |
2274 *result = zfs_dip; | |
2275 return (DDI_SUCCESS); | |
2276 | |
2277 case DDI_INFO_DEVT2INSTANCE: | |
849
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2278 *result = (void *)0; |
789 | 2279 return (DDI_SUCCESS); |
2280 } | |
2281 | |
2282 return (DDI_FAILURE); | |
2283 } | |
2284 | |
2285 /* | |
2286 * OK, so this is a little weird. | |
2287 * | |
2288 * /dev/zfs is the control node, i.e. minor 0. | |
2289 * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. | |
2290 * | |
2291 * /dev/zfs has basically nothing to do except serve up ioctls, | |
2292 * so most of the standard driver entry points are in zvol.c. | |
2293 */ | |
2294 static struct cb_ops zfs_cb_ops = { | |
2295 zvol_open, /* open */ | |
2296 zvol_close, /* close */ | |
2297 zvol_strategy, /* strategy */ | |
2298 nodev, /* print */ | |
2299 nodev, /* dump */ | |
2300 zvol_read, /* read */ | |
2301 zvol_write, /* write */ | |
2302 zfsdev_ioctl, /* ioctl */ | |
2303 nodev, /* devmap */ | |
2304 nodev, /* mmap */ | |
2305 nodev, /* segmap */ | |
2306 nochpoll, /* poll */ | |
2307 ddi_prop_op, /* prop_op */ | |
2308 NULL, /* streamtab */ | |
2309 D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ | |
2310 CB_REV, /* version */ | |
3638
6b28ebc717aa
6496357 spec_fsync() is useless on devices that do write caching
billm
parents:
3444
diff
changeset
|
2311 nodev, /* async read */ |
6b28ebc717aa
6496357 spec_fsync() is useless on devices that do write caching
billm
parents:
3444
diff
changeset
|
2312 nodev, /* async write */ |
789 | 2313 }; |
2314 | |
2315 static struct dev_ops zfs_dev_ops = { | |
2316 DEVO_REV, /* version */ | |
2317 0, /* refcnt */ | |
2318 zfs_info, /* info */ | |
2319 nulldev, /* identify */ | |
2320 nulldev, /* probe */ | |
2321 zfs_attach, /* attach */ | |
2322 zfs_detach, /* detach */ | |
2323 nodev, /* reset */ | |
2324 &zfs_cb_ops, /* driver operations */ | |
2325 NULL /* no bus operations */ | |
2326 }; | |
2327 | |
2328 static struct modldrv zfs_modldrv = { | |
4577 | 2329 &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, |
2676 | 2330 &zfs_dev_ops |
789 | 2331 }; |
2332 | |
2333 static struct modlinkage modlinkage = { | |
2334 MODREV_1, | |
2335 (void *)&zfs_modlfs, | |
2336 (void *)&zfs_modldrv, | |
2337 NULL | |
2338 }; | |
2339 | |
4720
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
2340 |
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
2341 uint_t zfs_fsyncer_key; |
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
2342 |
789 | 2343 int |
2344 _init(void) | |
2345 { | |
2346 int error; | |
2347 | |
849
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2348 spa_init(FREAD | FWRITE); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2349 zfs_init(); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2350 zvol_init(); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2351 |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2352 if ((error = mod_install(&modlinkage)) != 0) { |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2353 zvol_fini(); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2354 zfs_fini(); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2355 spa_fini(); |
789 | 2356 return (error); |
849
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
2357 } |
789 | 2358 |
4720
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
2359 tsd_create(&zfs_fsyncer_key, NULL); |
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
2360 |
789 | 2361 error = ldi_ident_from_mod(&modlinkage, &zfs_li); |
2362 ASSERT(error == 0); | |
4543 | 2363 mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); |
789 | 2364 |
2365 return (0); | |
2366 } | |
2367 | |
2368 int | |
2369 _fini(void) | |
2370 { | |
2371 int error; | |
2372 | |
1544 | 2373 if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) |
789 | 2374 return (EBUSY); |
2375 | |
2376 if ((error = mod_remove(&modlinkage)) != 0) | |
2377 return (error); | |
2378 | |
2379 zvol_fini(); | |
2380 zfs_fini(); | |
2381 spa_fini(); | |
4543 | 2382 if (zfs_share_inited) { |
2383 (void) ddi_modclose(nfs_mod); | |
2384 (void) ddi_modclose(sharefs_mod); | |
2385 } | |
789 | 2386 |
4720
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
2387 tsd_destroy(&zfs_fsyncer_key); |
789 | 2388 ldi_ident_release(zfs_li); |
2389 zfs_li = NULL; | |
4543 | 2390 mutex_destroy(&zfs_share_lock); |
789 | 2391 |
2392 return (error); | |
2393 } | |
2394 | |
2395 int | |
2396 _info(struct modinfo *modinfop) | |
2397 { | |
2398 return (mod_info(&modlinkage, modinfop)); | |
2399 } |