Mercurial > illumos > illumos-gate
annotate usr/src/uts/common/fs/zfs/zfs_ioctl.c @ 7265:cc18862247da
PSARC/2008/483 ZFS clone -o
PSARC/2008/484 ZFS snapshot properties
6613766 create-time properties for clones
6701797 want user properties on snapshots
author | ahrens |
---|---|
date | Fri, 01 Aug 2008 16:32:18 -0700 |
parents | 04c540040a32 |
children | c9c31ef4c960 |
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 /* | |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. |
789 | 23 * Use is subject to license terms. |
24 */ | |
25 | |
26 #pragma ident "%Z%%M% %I% %E% SMI" | |
27 | |
28 #include <sys/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> | |
5331 | 41 #include <sys/zfs_znode.h> |
789 | 42 #include <sys/zap.h> |
43 #include <sys/spa.h> | |
3912 | 44 #include <sys/spa_impl.h> |
789 | 45 #include <sys/vdev.h> |
3912 | 46 #include <sys/vdev_impl.h> |
789 | 47 #include <sys/dmu.h> |
48 #include <sys/dsl_dir.h> | |
49 #include <sys/dsl_dataset.h> | |
50 #include <sys/dsl_prop.h> | |
4543 | 51 #include <sys/dsl_deleg.h> |
52 #include <sys/dmu_objset.h> | |
789 | 53 #include <sys/ddi.h> |
54 #include <sys/sunddi.h> | |
55 #include <sys/sunldi.h> | |
56 #include <sys/policy.h> | |
57 #include <sys/zone.h> | |
58 #include <sys/nvpair.h> | |
59 #include <sys/pathname.h> | |
60 #include <sys/mount.h> | |
61 #include <sys/sdt.h> | |
62 #include <sys/fs/zfs.h> | |
63 #include <sys/zfs_ctldir.h> | |
5331 | 64 #include <sys/zfs_dir.h> |
2885 | 65 #include <sys/zvol.h> |
4543 | 66 #include <sharefs/share.h> |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
67 #include <sys/dmu_objset.h> |
789 | 68 |
69 #include "zfs_namecheck.h" | |
2676 | 70 #include "zfs_prop.h" |
4543 | 71 #include "zfs_deleg.h" |
789 | 72 |
73 extern struct modlfs zfs_modlfs; | |
74 | |
75 extern void zfs_init(void); | |
76 extern void zfs_fini(void); | |
77 | |
78 ldi_ident_t zfs_li = NULL; | |
79 dev_info_t *zfs_dip; | |
80 | |
81 typedef int zfs_ioc_func_t(zfs_cmd_t *); | |
4543 | 82 typedef int zfs_secpolicy_func_t(zfs_cmd_t *, cred_t *); |
789 | 83 |
84 typedef struct zfs_ioc_vec { | |
85 zfs_ioc_func_t *zvec_func; | |
86 zfs_secpolicy_func_t *zvec_secpolicy; | |
87 enum { | |
4577 | 88 NO_NAME, |
89 POOL_NAME, | |
90 DATASET_NAME | |
4543 | 91 } zvec_namecheck; |
92 boolean_t zvec_his_log; | |
789 | 93 } zfs_ioc_vec_t; |
94 | |
7265 | 95 static void clear_props(char *dataset, nvlist_t *props); |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
96 static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
97 boolean_t *); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
98 int zfs_set_prop_nvlist(const char *, nvlist_t *); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
99 |
789 | 100 /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */ |
101 void | |
102 __dprintf(const char *file, const char *func, int line, const char *fmt, ...) | |
103 { | |
104 const char *newfile; | |
105 char buf[256]; | |
106 va_list adx; | |
107 | |
108 /* | |
109 * Get rid of annoying "../common/" prefix to filename. | |
110 */ | |
111 newfile = strrchr(file, '/'); | |
112 if (newfile != NULL) { | |
113 newfile = newfile + 1; /* Get rid of leading / */ | |
114 } else { | |
115 newfile = file; | |
116 } | |
117 | |
118 va_start(adx, fmt); | |
119 (void) vsnprintf(buf, sizeof (buf), fmt, adx); | |
120 va_end(adx); | |
121 | |
122 /* | |
123 * To get this data, use the zfs-dprintf probe as so: | |
124 * dtrace -q -n 'zfs-dprintf \ | |
125 * /stringof(arg0) == "dbuf.c"/ \ | |
126 * {printf("%s: %s", stringof(arg1), stringof(arg3))}' | |
127 * arg0 = file name | |
128 * arg1 = function name | |
129 * arg2 = line number | |
130 * arg3 = message | |
131 */ | |
132 DTRACE_PROBE4(zfs__dprintf, | |
133 char *, newfile, char *, func, int, line, char *, buf); | |
134 } | |
135 | |
4543 | 136 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
|
137 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
|
138 { |
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 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
|
140 } |
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 |
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 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
|
143 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
|
144 { |
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 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
|
146 |
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 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
|
148 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
|
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 = 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
|
151 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
|
152 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
|
153 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
|
154 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
|
155 } |
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
|
156 |
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
|
157 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
|
158 |
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
|
159 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
|
160 } |
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 |
5375 | 162 /* |
7042
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
163 * Check to see if the named dataset is currently defined as bootable |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
164 */ |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
165 static boolean_t |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
166 zfs_is_bootfs(const char *name) |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
167 { |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
168 spa_t *spa; |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
169 boolean_t ret = B_FALSE; |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
170 |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
171 if (spa_open(name, &spa, FTAG) == 0) { |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
172 if (spa->spa_bootfs) { |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
173 objset_t *os; |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
174 |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
175 if (dmu_objset_open(name, DMU_OST_ZFS, |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
176 DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
177 ret = (dmu_objset_id(os) == spa->spa_bootfs); |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
178 dmu_objset_close(os); |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
179 } |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
180 } |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
181 spa_close(spa, FTAG); |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
182 } |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
183 return (ret); |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
184 } |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
185 |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
186 /* |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
187 * zfs_earlier_version |
5375 | 188 * |
189 * Return non-zero if the spa version is less than requested version. | |
190 */ | |
5331 | 191 static int |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
192 zfs_earlier_version(const char *name, int version) |
5331 | 193 { |
194 spa_t *spa; | |
195 | |
196 if (spa_open(name, &spa, FTAG) == 0) { | |
197 if (spa_version(spa) < version) { | |
198 spa_close(spa, FTAG); | |
199 return (1); | |
200 } | |
201 spa_close(spa, FTAG); | |
202 } | |
203 return (0); | |
204 } | |
205 | |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
206 /* |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
207 * zpl_earlier_version |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
208 * |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
209 * Return TRUE if the ZPL version is less than requested version. |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
210 */ |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
211 static boolean_t |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
212 zpl_earlier_version(const char *name, int version) |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
213 { |
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
214 objset_t *os; |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
215 boolean_t rc = B_TRUE; |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
216 |
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
217 if (dmu_objset_open(name, DMU_OST_ANY, |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
218 DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
219 uint64_t zplversion; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
220 |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
221 if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &zplversion) == 0) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
222 rc = zplversion < version; |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
223 dmu_objset_close(os); |
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
224 } |
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
225 return (rc); |
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
226 } |
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
227 |
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
|
228 static void |
4543 | 229 zfs_log_history(zfs_cmd_t *zc) |
230 { | |
231 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
|
232 char *buf; |
4543 | 233 |
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
|
234 if ((buf = history_str_get(zc)) == NULL) |
4577 | 235 return; |
236 | |
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
|
237 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
|
238 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
|
239 (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
|
240 spa_close(spa, FTAG); |
4543 | 241 } |
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
|
242 history_str_free(buf); |
4543 | 243 } |
244 | |
789 | 245 /* |
246 * Policy for top-level read operations (list pools). Requires no privileges, | |
247 * and can be used in the local zone, as there is no associated dataset. | |
248 */ | |
249 /* ARGSUSED */ | |
250 static int | |
4543 | 251 zfs_secpolicy_none(zfs_cmd_t *zc, cred_t *cr) |
789 | 252 { |
253 return (0); | |
254 } | |
255 | |
256 /* | |
257 * Policy for dataset read operations (list children, get statistics). Requires | |
258 * no privileges, but must be visible in the local zone. | |
259 */ | |
260 /* ARGSUSED */ | |
261 static int | |
4543 | 262 zfs_secpolicy_read(zfs_cmd_t *zc, cred_t *cr) |
789 | 263 { |
264 if (INGLOBALZONE(curproc) || | |
4543 | 265 zone_dataset_visible(zc->zc_name, NULL)) |
789 | 266 return (0); |
267 | |
268 return (ENOENT); | |
269 } | |
270 | |
271 static int | |
272 zfs_dozonecheck(const char *dataset, cred_t *cr) | |
273 { | |
274 uint64_t zoned; | |
275 int writable = 1; | |
276 | |
277 /* | |
278 * The dataset must be visible by this zone -- check this first | |
279 * so they don't see EPERM on something they shouldn't know about. | |
280 */ | |
281 if (!INGLOBALZONE(curproc) && | |
282 !zone_dataset_visible(dataset, &writable)) | |
283 return (ENOENT); | |
284 | |
285 if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL)) | |
286 return (ENOENT); | |
287 | |
288 if (INGLOBALZONE(curproc)) { | |
289 /* | |
290 * If the fs is zoned, only root can access it from the | |
291 * global zone. | |
292 */ | |
293 if (secpolicy_zfs(cr) && zoned) | |
294 return (EPERM); | |
295 } else { | |
296 /* | |
297 * If we are in a local zone, the 'zoned' property must be set. | |
298 */ | |
299 if (!zoned) | |
300 return (EPERM); | |
301 | |
302 /* must be writable by this zone */ | |
303 if (!writable) | |
304 return (EPERM); | |
305 } | |
306 return (0); | |
307 } | |
308 | |
309 int | |
4543 | 310 zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr) |
789 | 311 { |
312 int error; | |
313 | |
4543 | 314 error = zfs_dozonecheck(name, cr); |
315 if (error == 0) { | |
316 error = secpolicy_zfs(cr); | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
317 if (error) |
4543 | 318 error = dsl_deleg_access(name, perm, cr); |
319 } | |
320 return (error); | |
321 } | |
322 | |
323 static int | |
324 zfs_secpolicy_setprop(const char *name, zfs_prop_t prop, cred_t *cr) | |
325 { | |
326 /* | |
327 * Check permissions for special properties. | |
328 */ | |
329 switch (prop) { | |
330 case ZFS_PROP_ZONED: | |
331 /* | |
332 * Disallow setting of 'zoned' from within a local zone. | |
333 */ | |
334 if (!INGLOBALZONE(curproc)) | |
335 return (EPERM); | |
336 break; | |
789 | 337 |
4543 | 338 case ZFS_PROP_QUOTA: |
339 if (!INGLOBALZONE(curproc)) { | |
340 uint64_t zoned; | |
341 char setpoint[MAXNAMELEN]; | |
342 /* | |
343 * Unprivileged users are allowed to modify the | |
344 * quota on things *under* (ie. contained by) | |
345 * the thing they own. | |
346 */ | |
347 if (dsl_prop_get_integer(name, "zoned", &zoned, | |
348 setpoint)) | |
349 return (EPERM); | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
350 if (!zoned || strlen(name) <= strlen(setpoint)) |
4543 | 351 return (EPERM); |
352 } | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
353 break; |
4543 | 354 } |
355 | |
4787 | 356 return (zfs_secpolicy_write_perms(name, zfs_prop_to_name(prop), cr)); |
789 | 357 } |
358 | |
4543 | 359 int |
360 zfs_secpolicy_fsacl(zfs_cmd_t *zc, cred_t *cr) | |
361 { | |
362 int error; | |
363 | |
364 error = zfs_dozonecheck(zc->zc_name, cr); | |
365 if (error) | |
366 return (error); | |
367 | |
368 /* | |
369 * permission to set permissions will be evaluated later in | |
370 * dsl_deleg_can_allow() | |
371 */ | |
372 return (0); | |
373 } | |
374 | |
375 int | |
376 zfs_secpolicy_rollback(zfs_cmd_t *zc, cred_t *cr) | |
377 { | |
378 int error; | |
379 error = zfs_secpolicy_write_perms(zc->zc_name, | |
380 ZFS_DELEG_PERM_ROLLBACK, cr); | |
381 if (error == 0) | |
382 error = zfs_secpolicy_write_perms(zc->zc_name, | |
383 ZFS_DELEG_PERM_MOUNT, cr); | |
384 return (error); | |
385 } | |
386 | |
387 int | |
388 zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr) | |
389 { | |
390 return (zfs_secpolicy_write_perms(zc->zc_name, | |
391 ZFS_DELEG_PERM_SEND, cr)); | |
392 } | |
393 | |
394 int | |
395 zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr) | |
396 { | |
397 if (!INGLOBALZONE(curproc)) | |
398 return (EPERM); | |
399 | |
5367 | 400 if (secpolicy_nfs(cr) == 0) { |
4543 | 401 return (0); |
402 } else { | |
403 vnode_t *vp; | |
404 int error; | |
405 | |
406 if ((error = lookupname(zc->zc_value, UIO_SYSSPACE, | |
407 NO_FOLLOW, NULL, &vp)) != 0) | |
408 return (error); | |
409 | |
410 /* Now make sure mntpnt and dataset are ZFS */ | |
411 | |
412 if (vp->v_vfsp->vfs_fstype != zfsfstype || | |
413 (strcmp((char *)refstr_value(vp->v_vfsp->vfs_resource), | |
414 zc->zc_name) != 0)) { | |
415 VN_RELE(vp); | |
416 return (EPERM); | |
417 } | |
418 | |
419 VN_RELE(vp); | |
420 return (dsl_deleg_access(zc->zc_name, | |
421 ZFS_DELEG_PERM_SHARE, cr)); | |
422 } | |
423 } | |
424 | |
789 | 425 static int |
4543 | 426 zfs_get_parent(const char *datasetname, char *parent, int parentsize) |
789 | 427 { |
428 char *cp; | |
429 | |
430 /* | |
431 * Remove the @bla or /bla from the end of the name to get the parent. | |
432 */ | |
4543 | 433 (void) strncpy(parent, datasetname, parentsize); |
434 cp = strrchr(parent, '@'); | |
789 | 435 if (cp != NULL) { |
436 cp[0] = '\0'; | |
437 } else { | |
4543 | 438 cp = strrchr(parent, '/'); |
789 | 439 if (cp == NULL) |
440 return (ENOENT); | |
441 cp[0] = '\0'; | |
442 } | |
443 | |
4543 | 444 return (0); |
445 } | |
446 | |
447 int | |
448 zfs_secpolicy_destroy_perms(const char *name, cred_t *cr) | |
449 { | |
450 int error; | |
451 | |
452 if ((error = zfs_secpolicy_write_perms(name, | |
453 ZFS_DELEG_PERM_MOUNT, cr)) != 0) | |
454 return (error); | |
455 | |
456 return (zfs_secpolicy_write_perms(name, ZFS_DELEG_PERM_DESTROY, cr)); | |
457 } | |
458 | |
459 static int | |
460 zfs_secpolicy_destroy(zfs_cmd_t *zc, cred_t *cr) | |
461 { | |
462 return (zfs_secpolicy_destroy_perms(zc->zc_name, cr)); | |
463 } | |
464 | |
465 /* | |
466 * Must have sys_config privilege to check the iscsi permission | |
467 */ | |
468 /* ARGSUSED */ | |
469 static int | |
470 zfs_secpolicy_iscsi(zfs_cmd_t *zc, cred_t *cr) | |
471 { | |
472 return (secpolicy_zfs(cr)); | |
473 } | |
474 | |
475 int | |
476 zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr) | |
477 { | |
478 char parentname[MAXNAMELEN]; | |
479 int error; | |
480 | |
481 if ((error = zfs_secpolicy_write_perms(from, | |
482 ZFS_DELEG_PERM_RENAME, cr)) != 0) | |
483 return (error); | |
484 | |
485 if ((error = zfs_secpolicy_write_perms(from, | |
486 ZFS_DELEG_PERM_MOUNT, cr)) != 0) | |
487 return (error); | |
488 | |
489 if ((error = zfs_get_parent(to, parentname, | |
490 sizeof (parentname))) != 0) | |
491 return (error); | |
492 | |
493 if ((error = zfs_secpolicy_write_perms(parentname, | |
494 ZFS_DELEG_PERM_CREATE, cr)) != 0) | |
495 return (error); | |
496 | |
497 if ((error = zfs_secpolicy_write_perms(parentname, | |
498 ZFS_DELEG_PERM_MOUNT, cr)) != 0) | |
499 return (error); | |
500 | |
501 return (error); | |
502 } | |
503 | |
504 static int | |
505 zfs_secpolicy_rename(zfs_cmd_t *zc, cred_t *cr) | |
506 { | |
507 return (zfs_secpolicy_rename_perms(zc->zc_name, zc->zc_value, cr)); | |
508 } | |
509 | |
510 static int | |
511 zfs_secpolicy_promote(zfs_cmd_t *zc, cred_t *cr) | |
512 { | |
513 char parentname[MAXNAMELEN]; | |
514 objset_t *clone; | |
515 int error; | |
516 | |
517 error = zfs_secpolicy_write_perms(zc->zc_name, | |
518 ZFS_DELEG_PERM_PROMOTE, cr); | |
519 if (error) | |
520 return (error); | |
521 | |
522 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
523 DS_MODE_USER | DS_MODE_READONLY, &clone); |
4543 | 524 |
525 if (error == 0) { | |
526 dsl_dataset_t *pclone = NULL; | |
527 dsl_dir_t *dd; | |
528 dd = clone->os->os_dsl_dataset->ds_dir; | |
529 | |
530 rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
531 error = dsl_dataset_hold_obj(dd->dd_pool, |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
532 dd->dd_phys->dd_origin_obj, FTAG, &pclone); |
4543 | 533 rw_exit(&dd->dd_pool->dp_config_rwlock); |
534 if (error) { | |
535 dmu_objset_close(clone); | |
536 return (error); | |
537 } | |
538 | |
539 error = zfs_secpolicy_write_perms(zc->zc_name, | |
540 ZFS_DELEG_PERM_MOUNT, cr); | |
541 | |
542 dsl_dataset_name(pclone, parentname); | |
543 dmu_objset_close(clone); | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
544 dsl_dataset_rele(pclone, FTAG); |
4543 | 545 if (error == 0) |
546 error = zfs_secpolicy_write_perms(parentname, | |
547 ZFS_DELEG_PERM_PROMOTE, cr); | |
548 } | |
549 return (error); | |
550 } | |
551 | |
552 static int | |
553 zfs_secpolicy_receive(zfs_cmd_t *zc, cred_t *cr) | |
554 { | |
555 int error; | |
556 | |
557 if ((error = zfs_secpolicy_write_perms(zc->zc_name, | |
558 ZFS_DELEG_PERM_RECEIVE, cr)) != 0) | |
559 return (error); | |
560 | |
561 if ((error = zfs_secpolicy_write_perms(zc->zc_name, | |
562 ZFS_DELEG_PERM_MOUNT, cr)) != 0) | |
563 return (error); | |
564 | |
565 return (zfs_secpolicy_write_perms(zc->zc_name, | |
566 ZFS_DELEG_PERM_CREATE, cr)); | |
567 } | |
568 | |
569 int | |
570 zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr) | |
571 { | |
572 int error; | |
573 | |
574 if ((error = zfs_secpolicy_write_perms(name, | |
575 ZFS_DELEG_PERM_SNAPSHOT, cr)) != 0) | |
576 return (error); | |
577 | |
578 error = zfs_secpolicy_write_perms(name, | |
579 ZFS_DELEG_PERM_MOUNT, cr); | |
580 | |
581 return (error); | |
582 } | |
583 | |
584 static int | |
585 zfs_secpolicy_snapshot(zfs_cmd_t *zc, cred_t *cr) | |
586 { | |
587 | |
588 return (zfs_secpolicy_snapshot_perms(zc->zc_name, cr)); | |
589 } | |
590 | |
591 static int | |
592 zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr) | |
593 { | |
594 char parentname[MAXNAMELEN]; | |
595 int error; | |
596 | |
597 if ((error = zfs_get_parent(zc->zc_name, parentname, | |
598 sizeof (parentname))) != 0) | |
599 return (error); | |
600 | |
601 if (zc->zc_value[0] != '\0') { | |
602 if ((error = zfs_secpolicy_write_perms(zc->zc_value, | |
603 ZFS_DELEG_PERM_CLONE, cr)) != 0) | |
604 return (error); | |
605 } | |
606 | |
607 if ((error = zfs_secpolicy_write_perms(parentname, | |
608 ZFS_DELEG_PERM_CREATE, cr)) != 0) | |
609 return (error); | |
610 | |
611 error = zfs_secpolicy_write_perms(parentname, | |
612 ZFS_DELEG_PERM_MOUNT, cr); | |
613 | |
614 return (error); | |
615 } | |
616 | |
617 static int | |
618 zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr) | |
619 { | |
620 int error; | |
621 | |
622 error = secpolicy_fs_unmount(cr, NULL); | |
623 if (error) { | |
624 error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr); | |
625 } | |
626 return (error); | |
789 | 627 } |
628 | |
629 /* | |
630 * Policy for pool operations - create/destroy pools, add vdevs, etc. Requires | |
631 * SYS_CONFIG privilege, which is not available in a local zone. | |
632 */ | |
633 /* ARGSUSED */ | |
634 static int | |
4543 | 635 zfs_secpolicy_config(zfs_cmd_t *zc, cred_t *cr) |
789 | 636 { |
637 if (secpolicy_sys_config(cr, B_FALSE) != 0) | |
638 return (EPERM); | |
639 | |
640 return (0); | |
641 } | |
642 | |
643 /* | |
4543 | 644 * Just like zfs_secpolicy_config, except that we will check for |
645 * mount permission on the dataset for permission to create/remove | |
646 * the minor nodes. | |
647 */ | |
648 static int | |
649 zfs_secpolicy_minor(zfs_cmd_t *zc, cred_t *cr) | |
650 { | |
651 if (secpolicy_sys_config(cr, B_FALSE) != 0) { | |
652 return (dsl_deleg_access(zc->zc_name, | |
653 ZFS_DELEG_PERM_MOUNT, cr)); | |
654 } | |
655 | |
656 return (0); | |
657 } | |
658 | |
659 /* | |
1544 | 660 * Policy for fault injection. Requires all privileges. |
661 */ | |
662 /* ARGSUSED */ | |
663 static int | |
4543 | 664 zfs_secpolicy_inject(zfs_cmd_t *zc, cred_t *cr) |
1544 | 665 { |
666 return (secpolicy_zinject(cr)); | |
667 } | |
668 | |
4849
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
669 static int |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
670 zfs_secpolicy_inherit(zfs_cmd_t *zc, cred_t *cr) |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
671 { |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
672 zfs_prop_t prop = zfs_name_to_prop(zc->zc_value); |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
673 |
5094 | 674 if (prop == ZPROP_INVAL) { |
4849
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
675 if (!zfs_prop_user(zc->zc_value)) |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
676 return (EINVAL); |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
677 return (zfs_secpolicy_write_perms(zc->zc_name, |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
678 ZFS_DELEG_PERM_USERPROP, cr)); |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
679 } else { |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
680 if (!zfs_prop_inheritable(prop)) |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
681 return (EINVAL); |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
682 return (zfs_secpolicy_setprop(zc->zc_name, prop, cr)); |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
683 } |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
684 } |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
685 |
1544 | 686 /* |
789 | 687 * Returns the nvlist as specified by the user in the zfs_cmd_t. |
688 */ | |
689 static int | |
5094 | 690 get_nvlist(uint64_t nvl, uint64_t size, nvlist_t **nvp) |
789 | 691 { |
692 char *packed; | |
693 int error; | |
5094 | 694 nvlist_t *list = NULL; |
789 | 695 |
696 /* | |
2676 | 697 * Read in and unpack the user-supplied nvlist. |
789 | 698 */ |
5094 | 699 if (size == 0) |
789 | 700 return (EINVAL); |
701 | |
702 packed = kmem_alloc(size, KM_SLEEP); | |
703 | |
5094 | 704 if ((error = xcopyin((void *)(uintptr_t)nvl, packed, size)) != 0) { |
789 | 705 kmem_free(packed, size); |
706 return (error); | |
707 } | |
708 | |
5094 | 709 if ((error = nvlist_unpack(packed, size, &list, 0)) != 0) { |
789 | 710 kmem_free(packed, size); |
711 return (error); | |
712 } | |
713 | |
714 kmem_free(packed, size); | |
715 | |
5094 | 716 *nvp = list; |
789 | 717 return (0); |
718 } | |
719 | |
720 static int | |
2676 | 721 put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl) |
722 { | |
723 char *packed = NULL; | |
724 size_t size; | |
725 int error; | |
726 | |
727 VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0); | |
728 | |
729 if (size > zc->zc_nvlist_dst_size) { | |
730 error = ENOMEM; | |
731 } else { | |
4611 | 732 packed = kmem_alloc(size, KM_SLEEP); |
2676 | 733 VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE, |
734 KM_SLEEP) == 0); | |
735 error = xcopyout(packed, (void *)(uintptr_t)zc->zc_nvlist_dst, | |
736 size); | |
737 kmem_free(packed, size); | |
738 } | |
739 | |
740 zc->zc_nvlist_dst_size = size; | |
741 return (error); | |
742 } | |
743 | |
744 static int | |
789 | 745 zfs_ioc_pool_create(zfs_cmd_t *zc) |
746 { | |
747 int error; | |
5094 | 748 nvlist_t *config, *props = NULL; |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
749 nvlist_t *rootprops = NULL; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
750 nvlist_t *zplprops = NULL; |
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
|
751 char *buf; |
789 | 752 |
5094 | 753 if (error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, |
754 &config)) | |
4988
db8abd9846d4
6595467 libzfs consumers should be allowed to write their own history (or none at all)
ek110237
parents:
4849
diff
changeset
|
755 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
|
756 |
5094 | 757 if (zc->zc_nvlist_src_size != 0 && (error = |
758 get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { | |
759 nvlist_free(config); | |
760 return (error); | |
761 } | |
762 | |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
763 if (props) { |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
764 nvlist_t *nvl = NULL; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
765 uint64_t version = SPA_VERSION; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
766 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
767 (void) nvlist_lookup_uint64(props, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
768 zpool_prop_to_name(ZPOOL_PROP_VERSION), &version); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
769 if (version < SPA_VERSION_INITIAL || version > SPA_VERSION) { |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
770 error = EINVAL; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
771 goto pool_props_bad; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
772 } |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
773 (void) nvlist_lookup_nvlist(props, ZPOOL_ROOTFS_PROPS, &nvl); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
774 if (nvl) { |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
775 error = nvlist_dup(nvl, &rootprops, KM_SLEEP); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
776 if (error != 0) { |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
777 nvlist_free(config); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
778 nvlist_free(props); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
779 return (error); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
780 } |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
781 (void) nvlist_remove_all(props, ZPOOL_ROOTFS_PROPS); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
782 } |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
783 VERIFY(nvlist_alloc(&zplprops, NV_UNIQUE_NAME, KM_SLEEP) == 0); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
784 error = zfs_fill_zplprops_root(version, rootprops, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
785 zplprops, NULL); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
786 if (error) |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
787 goto pool_props_bad; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
788 } |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
789 |
4988
db8abd9846d4
6595467 libzfs consumers should be allowed to write their own history (or none at all)
ek110237
parents:
4849
diff
changeset
|
790 buf = history_str_get(zc); |
789 | 791 |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
792 error = spa_create(zc->zc_name, config, props, buf, zplprops); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
793 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
794 /* |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
795 * Set the remaining root properties |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
796 */ |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
797 if (!error && |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
798 (error = zfs_set_prop_nvlist(zc->zc_name, rootprops)) != 0) |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
799 (void) spa_destroy(zc->zc_name); |
789 | 800 |
4988
db8abd9846d4
6595467 libzfs consumers should be allowed to write their own history (or none at all)
ek110237
parents:
4849
diff
changeset
|
801 if (buf != NULL) |
db8abd9846d4
6595467 libzfs consumers should be allowed to write their own history (or none at all)
ek110237
parents:
4849
diff
changeset
|
802 history_str_free(buf); |
5094 | 803 |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
804 pool_props_bad: |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
805 nvlist_free(rootprops); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
806 nvlist_free(zplprops); |
789 | 807 nvlist_free(config); |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
808 nvlist_free(props); |
5094 | 809 |
789 | 810 return (error); |
811 } | |
812 | |
813 static int | |
814 zfs_ioc_pool_destroy(zfs_cmd_t *zc) | |
815 { | |
4543 | 816 int error; |
817 zfs_log_history(zc); | |
818 error = spa_destroy(zc->zc_name); | |
819 return (error); | |
789 | 820 } |
821 | |
822 static int | |
823 zfs_ioc_pool_import(zfs_cmd_t *zc) | |
824 { | |
825 int error; | |
5094 | 826 nvlist_t *config, *props = NULL; |
789 | 827 uint64_t guid; |
828 | |
5094 | 829 if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, |
830 &config)) != 0) | |
789 | 831 return (error); |
832 | |
5094 | 833 if (zc->zc_nvlist_src_size != 0 && (error = |
834 get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, &props))) { | |
835 nvlist_free(config); | |
836 return (error); | |
837 } | |
838 | |
789 | 839 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) != 0 || |
1544 | 840 guid != zc->zc_guid) |
789 | 841 error = EINVAL; |
6643
3a34b0dbb107
6625086 changing cachefile doesn't remove old cache on last user
eschrock
parents:
6492
diff
changeset
|
842 else if (zc->zc_cookie) |
3a34b0dbb107
6625086 changing cachefile doesn't remove old cache on last user
eschrock
parents:
6492
diff
changeset
|
843 error = spa_import_faulted(zc->zc_name, config, |
3a34b0dbb107
6625086 changing cachefile doesn't remove old cache on last user
eschrock
parents:
6492
diff
changeset
|
844 props); |
789 | 845 else |
5094 | 846 error = spa_import(zc->zc_name, config, props); |
789 | 847 |
848 nvlist_free(config); | |
849 | |
5094 | 850 if (props) |
851 nvlist_free(props); | |
852 | |
789 | 853 return (error); |
854 } | |
855 | |
856 static int | |
857 zfs_ioc_pool_export(zfs_cmd_t *zc) | |
858 { | |
4543 | 859 int error; |
7214
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7184
diff
changeset
|
860 boolean_t force = (boolean_t)zc->zc_cookie; |
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7184
diff
changeset
|
861 |
4543 | 862 zfs_log_history(zc); |
7214
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7184
diff
changeset
|
863 error = spa_export(zc->zc_name, NULL, force); |
4543 | 864 return (error); |
789 | 865 } |
866 | |
867 static int | |
868 zfs_ioc_pool_configs(zfs_cmd_t *zc) | |
869 { | |
870 nvlist_t *configs; | |
871 int error; | |
872 | |
873 if ((configs = spa_all_configs(&zc->zc_cookie)) == NULL) | |
874 return (EEXIST); | |
875 | |
2676 | 876 error = put_nvlist(zc, configs); |
789 | 877 |
878 nvlist_free(configs); | |
879 | |
880 return (error); | |
881 } | |
882 | |
883 static int | |
884 zfs_ioc_pool_stats(zfs_cmd_t *zc) | |
885 { | |
886 nvlist_t *config; | |
887 int error; | |
1544 | 888 int ret = 0; |
789 | 889 |
2676 | 890 error = spa_get_stats(zc->zc_name, &config, zc->zc_value, |
891 sizeof (zc->zc_value)); | |
789 | 892 |
893 if (config != NULL) { | |
2676 | 894 ret = put_nvlist(zc, config); |
789 | 895 nvlist_free(config); |
1544 | 896 |
897 /* | |
898 * The config may be present even if 'error' is non-zero. | |
899 * In this case we return success, and preserve the real errno | |
900 * in 'zc_cookie'. | |
901 */ | |
902 zc->zc_cookie = error; | |
789 | 903 } else { |
1544 | 904 ret = error; |
789 | 905 } |
906 | |
1544 | 907 return (ret); |
789 | 908 } |
909 | |
910 /* | |
911 * Try to import the given pool, returning pool stats as appropriate so that | |
912 * user land knows which devices are available and overall pool health. | |
913 */ | |
914 static int | |
915 zfs_ioc_pool_tryimport(zfs_cmd_t *zc) | |
916 { | |
917 nvlist_t *tryconfig, *config; | |
918 int error; | |
919 | |
5094 | 920 if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, |
921 &tryconfig)) != 0) | |
789 | 922 return (error); |
923 | |
924 config = spa_tryimport(tryconfig); | |
925 | |
926 nvlist_free(tryconfig); | |
927 | |
928 if (config == NULL) | |
929 return (EINVAL); | |
930 | |
2676 | 931 error = put_nvlist(zc, config); |
789 | 932 nvlist_free(config); |
933 | |
934 return (error); | |
935 } | |
936 | |
937 static int | |
938 zfs_ioc_pool_scrub(zfs_cmd_t *zc) | |
939 { | |
940 spa_t *spa; | |
941 int error; | |
942 | |
2926 | 943 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
944 return (error); | |
945 | |
7046
361307ae060d
6343667 scrub/resilver has to start over when a snapshot is taken
ahrens
parents:
7042
diff
changeset
|
946 error = spa_scrub(spa, zc->zc_cookie); |
2926 | 947 |
948 spa_close(spa, FTAG); | |
949 | |
789 | 950 return (error); |
951 } | |
952 | |
953 static int | |
954 zfs_ioc_pool_freeze(zfs_cmd_t *zc) | |
955 { | |
956 spa_t *spa; | |
957 int error; | |
958 | |
959 error = spa_open(zc->zc_name, &spa, FTAG); | |
960 if (error == 0) { | |
961 spa_freeze(spa); | |
962 spa_close(spa, FTAG); | |
963 } | |
964 return (error); | |
965 } | |
966 | |
967 static int | |
1760 | 968 zfs_ioc_pool_upgrade(zfs_cmd_t *zc) |
969 { | |
970 spa_t *spa; | |
971 int error; | |
972 | |
2926 | 973 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
974 return (error); | |
975 | |
5118
c723b1aa9f79
6607671 Able to zpool upgrade a pool to an unknown version number
lling
parents:
5094
diff
changeset
|
976 if (zc->zc_cookie < spa_version(spa) || zc->zc_cookie > SPA_VERSION) { |
c723b1aa9f79
6607671 Able to zpool upgrade a pool to an unknown version number
lling
parents:
5094
diff
changeset
|
977 spa_close(spa, FTAG); |
c723b1aa9f79
6607671 Able to zpool upgrade a pool to an unknown version number
lling
parents:
5094
diff
changeset
|
978 return (EINVAL); |
c723b1aa9f79
6607671 Able to zpool upgrade a pool to an unknown version number
lling
parents:
5094
diff
changeset
|
979 } |
c723b1aa9f79
6607671 Able to zpool upgrade a pool to an unknown version number
lling
parents:
5094
diff
changeset
|
980 |
5094 | 981 spa_upgrade(spa, zc->zc_cookie); |
2926 | 982 spa_close(spa, FTAG); |
983 | |
984 return (error); | |
985 } | |
986 | |
987 static int | |
988 zfs_ioc_pool_get_history(zfs_cmd_t *zc) | |
989 { | |
990 spa_t *spa; | |
991 char *hist_buf; | |
992 uint64_t size; | |
993 int error; | |
994 | |
995 if ((size = zc->zc_history_len) == 0) | |
996 return (EINVAL); | |
997 | |
998 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) | |
999 return (error); | |
1000 | |
4577 | 1001 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
|
1002 spa_close(spa, FTAG); |
d56571426115
6529406 zpool history needs to bump the on-disk version
ek110237
parents:
3741
diff
changeset
|
1003 return (ENOTSUP); |
d56571426115
6529406 zpool history needs to bump the on-disk version
ek110237
parents:
3741
diff
changeset
|
1004 } |
d56571426115
6529406 zpool history needs to bump the on-disk version
ek110237
parents:
3741
diff
changeset
|
1005 |
2926 | 1006 hist_buf = kmem_alloc(size, KM_SLEEP); |
1007 if ((error = spa_history_get(spa, &zc->zc_history_offset, | |
1008 &zc->zc_history_len, hist_buf)) == 0) { | |
4543 | 1009 error = xcopyout(hist_buf, |
1010 (char *)(uintptr_t)zc->zc_history, | |
2926 | 1011 zc->zc_history_len); |
1012 } | |
1013 | |
1014 spa_close(spa, FTAG); | |
1015 kmem_free(hist_buf, size); | |
1016 return (error); | |
1017 } | |
1018 | |
1019 static int | |
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1020 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
|
1021 { |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1022 int error; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1023 |
3912 | 1024 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
|
1025 return (error); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1026 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1027 return (0); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1028 } |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1029 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1030 static int |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1031 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
|
1032 { |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1033 objset_t *osp; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1034 int error; |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1035 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1036 if ((error = dmu_objset_open(zc->zc_name, DMU_OST_ZFS, |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1037 DS_MODE_USER | DS_MODE_READONLY, &osp)) != 0) |
3444
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1038 return (error); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1039 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
|
1040 sizeof (zc->zc_value)); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1041 dmu_objset_close(osp); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1042 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1043 return (error); |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1044 } |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1045 |
dc160a70a50d
6410433 'zpool status -v' would be more useful with filenames
ek110237
parents:
3265
diff
changeset
|
1046 static int |
789 | 1047 zfs_ioc_vdev_add(zfs_cmd_t *zc) |
1048 { | |
1049 spa_t *spa; | |
1050 int error; | |
6423 | 1051 nvlist_t *config, **l2cache, **spares; |
1052 uint_t nl2cache = 0, nspares = 0; | |
789 | 1053 |
1054 error = spa_open(zc->zc_name, &spa, FTAG); | |
1055 if (error != 0) | |
1056 return (error); | |
1057 | |
5450 | 1058 error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, |
1059 &config); | |
1060 (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_L2CACHE, | |
1061 &l2cache, &nl2cache); | |
1062 | |
6423 | 1063 (void) nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_SPARES, |
1064 &spares, &nspares); | |
1065 | |
3912 | 1066 /* |
1067 * A root pool with concatenated devices is not supported. | |
6423 | 1068 * Thus, can not add a device to a root pool. |
1069 * | |
1070 * Intent log device can not be added to a rootpool because | |
1071 * during mountroot, zil is replayed, a seperated log device | |
1072 * can not be accessed during the mountroot time. | |
1073 * | |
1074 * l2cache and spare devices are ok to be added to a rootpool. | |
3912 | 1075 */ |
6423 | 1076 if (spa->spa_bootfs != 0 && nl2cache == 0 && nspares == 0) { |
3912 | 1077 spa_close(spa, FTAG); |
1078 return (EDOM); | |
1079 } | |
1080 | |
5450 | 1081 if (error == 0) { |
789 | 1082 error = spa_vdev_add(spa, config); |
1083 nvlist_free(config); | |
1084 } | |
1085 spa_close(spa, FTAG); | |
1086 return (error); | |
1087 } | |
1088 | |
1089 static int | |
1090 zfs_ioc_vdev_remove(zfs_cmd_t *zc) | |
1091 { | |
2082 | 1092 spa_t *spa; |
1093 int error; | |
1094 | |
1095 error = spa_open(zc->zc_name, &spa, FTAG); | |
1096 if (error != 0) | |
1097 return (error); | |
1098 error = spa_vdev_remove(spa, zc->zc_guid, B_FALSE); | |
1099 spa_close(spa, FTAG); | |
1100 return (error); | |
789 | 1101 } |
1102 | |
1103 static int | |
4451 | 1104 zfs_ioc_vdev_set_state(zfs_cmd_t *zc) |
789 | 1105 { |
1106 spa_t *spa; | |
1107 int error; | |
4451 | 1108 vdev_state_t newstate = VDEV_STATE_UNKNOWN; |
789 | 1109 |
2926 | 1110 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
789 | 1111 return (error); |
4451 | 1112 switch (zc->zc_cookie) { |
1113 case VDEV_STATE_ONLINE: | |
1114 error = vdev_online(spa, zc->zc_guid, zc->zc_obj, &newstate); | |
1115 break; | |
1116 | |
1117 case VDEV_STATE_OFFLINE: | |
1118 error = vdev_offline(spa, zc->zc_guid, zc->zc_obj); | |
1119 break; | |
789 | 1120 |
4451 | 1121 case VDEV_STATE_FAULTED: |
1122 error = vdev_fault(spa, zc->zc_guid); | |
1123 break; | |
789 | 1124 |
4451 | 1125 case VDEV_STATE_DEGRADED: |
1126 error = vdev_degrade(spa, zc->zc_guid); | |
1127 break; | |
1128 | |
1129 default: | |
1130 error = EINVAL; | |
1131 } | |
1132 zc->zc_cookie = newstate; | |
789 | 1133 spa_close(spa, FTAG); |
1134 return (error); | |
1135 } | |
1136 | |
1137 static int | |
1138 zfs_ioc_vdev_attach(zfs_cmd_t *zc) | |
1139 { | |
1140 spa_t *spa; | |
1141 int replacing = zc->zc_cookie; | |
1142 nvlist_t *config; | |
1143 int error; | |
1144 | |
2926 | 1145 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
789 | 1146 return (error); |
1147 | |
5094 | 1148 if ((error = get_nvlist(zc->zc_nvlist_conf, zc->zc_nvlist_conf_size, |
1149 &config)) == 0) { | |
1544 | 1150 error = spa_vdev_attach(spa, zc->zc_guid, config, replacing); |
789 | 1151 nvlist_free(config); |
1152 } | |
1153 | |
1154 spa_close(spa, FTAG); | |
1155 return (error); | |
1156 } | |
1157 | |
1158 static int | |
1159 zfs_ioc_vdev_detach(zfs_cmd_t *zc) | |
1160 { | |
1161 spa_t *spa; | |
1162 int error; | |
1163 | |
2926 | 1164 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) |
789 | 1165 return (error); |
1166 | |
1544 | 1167 error = spa_vdev_detach(spa, zc->zc_guid, B_FALSE); |
789 | 1168 |
1169 spa_close(spa, FTAG); | |
1170 return (error); | |
1171 } | |
1172 | |
1173 static int | |
1354
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1174 zfs_ioc_vdev_setpath(zfs_cmd_t *zc) |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1175 { |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1176 spa_t *spa; |
2676 | 1177 char *path = zc->zc_value; |
1544 | 1178 uint64_t guid = zc->zc_guid; |
1354
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1179 int error; |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1180 |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1181 error = spa_open(zc->zc_name, &spa, FTAG); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1182 if (error != 0) |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1183 return (error); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1184 |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1185 error = spa_vdev_setpath(spa, guid, path); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1186 spa_close(spa, FTAG); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1187 return (error); |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1188 } |
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1189 |
5367 | 1190 /* |
1191 * inputs: | |
1192 * zc_name name of filesystem | |
1193 * zc_nvlist_dst_size size of buffer for property nvlist | |
1194 * | |
1195 * outputs: | |
1196 * zc_objset_stats stats | |
1197 * zc_nvlist_dst property nvlist | |
1198 * zc_nvlist_dst_size size of property nvlist | |
1199 */ | |
1354
81359ee1ee63
6362672 import gets confused about overlapping slices
eschrock
parents:
1133
diff
changeset
|
1200 static int |
789 | 1201 zfs_ioc_objset_stats(zfs_cmd_t *zc) |
1202 { | |
1203 objset_t *os = NULL; | |
1204 int error; | |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
1354
diff
changeset
|
1205 nvlist_t *nv; |
789 | 1206 |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1207 if (error = dmu_objset_open(zc->zc_name, |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1208 DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) |
789 | 1209 return (error); |
1210 | |
2885 | 1211 dmu_objset_fast_stat(os, &zc->zc_objset_stats); |
789 | 1212 |
2856 | 1213 if (zc->zc_nvlist_dst != 0 && |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1214 (error = dsl_prop_get_all(os, &nv, FALSE)) == 0) { |
2885 | 1215 dmu_objset_stats(os, nv); |
3087 | 1216 /* |
5147
5e950ccc9585
6596190 "zfs list" is slow due to version property
rm160521
parents:
5118
diff
changeset
|
1217 * NB: zvol_get_stats() will read the objset contents, |
3087 | 1218 * which we aren't supposed to do with a |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1219 * DS_MODE_USER hold, because it could be |
3087 | 1220 * inconsistent. So this is a bit of a workaround... |
1221 */ | |
4577 | 1222 if (!zc->zc_objset_stats.dds_inconsistent) { |
1223 if (dmu_objset_type(os) == DMU_OST_ZVOL) | |
1224 VERIFY(zvol_get_stats(os, nv) == 0); | |
1225 } | |
2676 | 1226 error = put_nvlist(zc, nv); |
1356
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
1354
diff
changeset
|
1227 nvlist_free(nv); |
e021b5e4aa0e
6377671 zfs mount -a shouldn't bother checking snapshots
eschrock
parents:
1354
diff
changeset
|
1228 } |
789 | 1229 |
1230 dmu_objset_close(os); | |
1231 return (error); | |
1232 } | |
1233 | |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1234 static int |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1235 nvl_add_zplprop(objset_t *os, nvlist_t *props, zfs_prop_t prop) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1236 { |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1237 uint64_t value; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1238 int error; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1239 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1240 /* |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1241 * zfs_get_zplprop() will either find a value or give us |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1242 * the default value (if there is one). |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1243 */ |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1244 if ((error = zfs_get_zplprop(os, prop, &value)) != 0) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1245 return (error); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1246 VERIFY(nvlist_add_uint64(props, zfs_prop_to_name(prop), value) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1247 return (0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1248 } |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1249 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1250 /* |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1251 * inputs: |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1252 * zc_name name of filesystem |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1253 * zc_nvlist_dst_size size of buffer for zpl property nvlist |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1254 * |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1255 * outputs: |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1256 * zc_nvlist_dst zpl property nvlist |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1257 * zc_nvlist_dst_size size of zpl property nvlist |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1258 */ |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1259 static int |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1260 zfs_ioc_objset_zplprops(zfs_cmd_t *zc) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1261 { |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1262 objset_t *os; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1263 int err; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1264 |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1265 if (err = dmu_objset_open(zc->zc_name, |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1266 DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1267 return (err); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1268 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1269 dmu_objset_fast_stat(os, &zc->zc_objset_stats); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1270 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1271 /* |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1272 * NB: nvl_add_zplprop() will read the objset contents, |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1273 * which we aren't supposed to do with a DS_MODE_USER |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1274 * hold, because it could be inconsistent. |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1275 */ |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1276 if (zc->zc_nvlist_dst != NULL && |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1277 !zc->zc_objset_stats.dds_inconsistent && |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1278 dmu_objset_type(os) == DMU_OST_ZFS) { |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1279 nvlist_t *nv; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1280 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1281 VERIFY(nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1282 if ((err = nvl_add_zplprop(os, nv, ZFS_PROP_VERSION)) == 0 && |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1283 (err = nvl_add_zplprop(os, nv, ZFS_PROP_NORMALIZE)) == 0 && |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1284 (err = nvl_add_zplprop(os, nv, ZFS_PROP_UTF8ONLY)) == 0 && |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1285 (err = nvl_add_zplprop(os, nv, ZFS_PROP_CASE)) == 0) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1286 err = put_nvlist(zc, nv); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1287 nvlist_free(nv); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1288 } else { |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1289 err = ENOENT; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1290 } |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1291 dmu_objset_close(os); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1292 return (err); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1293 } |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1294 |
5367 | 1295 /* |
1296 * inputs: | |
1297 * zc_name name of filesystem | |
1298 * zc_cookie zap cursor | |
1299 * zc_nvlist_dst_size size of buffer for property nvlist | |
1300 * | |
1301 * outputs: | |
1302 * zc_name name of next filesystem | |
1303 * zc_objset_stats stats | |
1304 * zc_nvlist_dst property nvlist | |
1305 * zc_nvlist_dst_size size of property nvlist | |
1306 */ | |
789 | 1307 static int |
1308 zfs_ioc_dataset_list_next(zfs_cmd_t *zc) | |
1309 { | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1310 objset_t *os; |
789 | 1311 int error; |
1312 char *p; | |
1313 | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1314 if (error = dmu_objset_open(zc->zc_name, |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1315 DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os)) { |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1316 if (error == ENOENT) |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1317 error = ESRCH; |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1318 return (error); |
789 | 1319 } |
1320 | |
1321 p = strrchr(zc->zc_name, '/'); | |
1322 if (p == NULL || p[1] != '\0') | |
1323 (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); | |
1324 p = zc->zc_name + strlen(zc->zc_name); | |
1325 | |
1326 do { | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1327 error = dmu_dir_list_next(os, |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1328 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
|
1329 NULL, &zc->zc_cookie); |
789 | 1330 if (error == ENOENT) |
1331 error = ESRCH; | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1332 } while (error == 0 && !INGLOBALZONE(curproc) && |
789 | 1333 !zone_dataset_visible(zc->zc_name, NULL)); |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1334 dmu_objset_close(os); |
789 | 1335 |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1336 /* |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1337 * 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
|
1338 * 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
|
1339 */ |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1340 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
|
1341 error = zfs_ioc_objset_stats(zc); /* fill in the stats */ |
789 | 1342 |
1343 return (error); | |
1344 } | |
1345 | |
5367 | 1346 /* |
1347 * inputs: | |
1348 * zc_name name of filesystem | |
1349 * zc_cookie zap cursor | |
1350 * zc_nvlist_dst_size size of buffer for property nvlist | |
1351 * | |
1352 * outputs: | |
1353 * zc_name name of next snapshot | |
1354 * zc_objset_stats stats | |
1355 * zc_nvlist_dst property nvlist | |
1356 * zc_nvlist_dst_size size of property nvlist | |
1357 */ | |
789 | 1358 static int |
1359 zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) | |
1360 { | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1361 objset_t *os; |
789 | 1362 int error; |
1363 | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1364 error = dmu_objset_open(zc->zc_name, |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1365 DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1366 if (error) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1367 return (error == ENOENT ? ESRCH : error); |
789 | 1368 |
1003 | 1369 /* |
1370 * A dataset name of maximum length cannot have any snapshots, | |
1371 * so exit immediately. | |
1372 */ | |
1373 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
|
1374 dmu_objset_close(os); |
1003 | 1375 return (ESRCH); |
789 | 1376 } |
1377 | |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1378 error = dmu_snapshot_list_next(os, |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1379 sizeof (zc->zc_name) - strlen(zc->zc_name), |
5663
029cc4273b57
6627223 gfs needs to support extended dirent flags
ck153898
parents:
5498
diff
changeset
|
1380 zc->zc_name + strlen(zc->zc_name), NULL, &zc->zc_cookie, NULL); |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1381 dmu_objset_close(os); |
885
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1382 if (error == 0) |
d925b21dba78
6347493 tar of 25K empty directory entries in ZFS takes 30+ seconds ...
ahrens
parents:
849
diff
changeset
|
1383 error = zfs_ioc_objset_stats(zc); /* fill in the stats */ |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1384 else if (error == ENOENT) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1385 error = ESRCH; |
789 | 1386 |
5367 | 1387 /* if we failed, undo the @ that we tacked on to zc_name */ |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1388 if (error) |
5367 | 1389 *strchr(zc->zc_name, '@') = '\0'; |
789 | 1390 return (error); |
1391 } | |
1392 | |
6423 | 1393 int |
4787 | 1394 zfs_set_prop_nvlist(const char *name, nvlist_t *nvl) |
789 | 1395 { |
2676 | 1396 nvpair_t *elem; |
1397 int error; | |
1398 uint64_t intval; | |
1399 char *strval; | |
1400 | |
4543 | 1401 /* |
1402 * First validate permission to set all of the properties | |
1403 */ | |
2676 | 1404 elem = NULL; |
1405 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1406 const char *propname = nvpair_name(elem); |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1407 zfs_prop_t prop = zfs_name_to_prop(propname); |
2676 | 1408 |
5094 | 1409 if (prop == ZPROP_INVAL) { |
2676 | 1410 /* |
1411 * If this is a user-defined property, it must be a | |
1412 * string, and there is no further validation to do. | |
1413 */ | |
1414 if (!zfs_prop_user(propname) || | |
1415 nvpair_type(elem) != DATA_TYPE_STRING) | |
1416 return (EINVAL); | |
1417 | |
5331 | 1418 if (error = zfs_secpolicy_write_perms(name, |
1419 ZFS_DELEG_PERM_USERPROP, CRED())) | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1420 return (error); |
4543 | 1421 continue; |
2676 | 1422 } |
1423 | |
4787 | 1424 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
|
1425 return (error); |
2676 | 1426 |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1427 /* |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1428 * 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
|
1429 */ |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1430 switch (prop) { |
3886
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1431 case ZFS_PROP_COMPRESSION: |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1432 /* |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1433 * 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
|
1434 * 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
|
1435 * we'll catch them later. |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1436 */ |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1437 if (nvpair_type(elem) == DATA_TYPE_UINT64 && |
7042
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1438 nvpair_value_uint64(elem, &intval) == 0) { |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1439 if (intval >= ZIO_COMPRESS_GZIP_1 && |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1440 intval <= ZIO_COMPRESS_GZIP_9 && |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1441 zfs_earlier_version(name, |
5331 | 1442 SPA_VERSION_GZIP_COMPRESSION)) |
1443 return (ENOTSUP); | |
7042
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1444 |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1445 /* |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1446 * If this is a bootable dataset then |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1447 * verify that the compression algorithm |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1448 * is supported for booting. We must return |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1449 * something other than ENOTSUP since it |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1450 * implies a downrev pool version. |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1451 */ |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1452 if (zfs_is_bootfs(name) && |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1453 !BOOTFS_COMPRESS_VALID(intval)) |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
1454 return (ERANGE); |
3886
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1455 } |
3291401d66a6
6536602 add zlib compression support and upgrade to version 1.2.3
ahl
parents:
3863
diff
changeset
|
1456 break; |
4603
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1457 |
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1458 case ZFS_PROP_COPIES: |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1459 if (zfs_earlier_version(name, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1460 SPA_VERSION_DITTO_BLOCKS)) |
5331 | 1461 return (ENOTSUP); |
4603
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1462 break; |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
1463 |
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
1464 case ZFS_PROP_SHARESMB: |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
1465 if (zpl_earlier_version(name, ZPL_VERSION_FUID)) |
5977
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
1466 return (ENOTSUP); |
33727f49aeaa
6654731 sharesmb property should only be settable on CIFS aware ZPL
marks
parents:
5663
diff
changeset
|
1467 break; |
4603
c7840c367d00
6494569 zfs recv -d pool/<doesn't exist> core dumps for top-level filesystem backups
ahrens
parents:
4577
diff
changeset
|
1468 } |
4543 | 1469 } |
1470 | |
1471 elem = NULL; | |
1472 while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { | |
4670
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1473 const char *propname = nvpair_name(elem); |
002728040e28
6580745 "zfs inherit" can be executed by ordinary user
ahrens
parents:
4611
diff
changeset
|
1474 zfs_prop_t prop = zfs_name_to_prop(propname); |
4543 | 1475 |
5094 | 1476 if (prop == ZPROP_INVAL) { |
4543 | 1477 VERIFY(nvpair_value_string(elem, &strval) == 0); |
1478 error = dsl_prop_set(name, propname, 1, | |
1479 strlen(strval) + 1, strval); | |
1480 if (error == 0) | |
1481 continue; | |
1482 else | |
1483 return (error); | |
1484 } | |
2676 | 1485 |
1486 switch (prop) { | |
1487 case ZFS_PROP_QUOTA: | |
1488 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
4577 | 1489 (error = dsl_dir_set_quota(name, intval)) != 0) |
2676 | 1490 return (error); |
1491 break; | |
1492 | |
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1493 case ZFS_PROP_REFQUOTA: |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1494 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1495 (error = dsl_dataset_set_quota(name, intval)) != 0) |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1496 return (error); |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1497 break; |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1498 |
2676 | 1499 case ZFS_PROP_RESERVATION: |
1500 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
1501 (error = dsl_dir_set_reservation(name, | |
1502 intval)) != 0) | |
1503 return (error); | |
1504 break; | |
789 | 1505 |
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1506 case ZFS_PROP_REFRESERVATION: |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1507 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1508 (error = dsl_dataset_set_reservation(name, |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1509 intval)) != 0) |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1510 return (error); |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1511 break; |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5375
diff
changeset
|
1512 |
2676 | 1513 case ZFS_PROP_VOLSIZE: |
1514 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
4787 | 1515 (error = zvol_set_volsize(name, |
1516 ddi_driver_major(zfs_dip), intval)) != 0) | |
2676 | 1517 return (error); |
1518 break; | |
1519 | |
1520 case ZFS_PROP_VOLBLOCKSIZE: | |
1521 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
4577 | 1522 (error = zvol_set_volblocksize(name, intval)) != 0) |
1523 return (error); | |
1524 break; | |
1525 | |
1526 case ZFS_PROP_VERSION: | |
1527 if ((error = nvpair_value_uint64(elem, &intval)) != 0 || | |
1528 (error = zfs_set_version(name, intval)) != 0) | |
2676 | 1529 return (error); |
1530 break; | |
1531 | |
1532 default: | |
1533 if (nvpair_type(elem) == DATA_TYPE_STRING) { | |
1534 if (zfs_prop_get_type(prop) != | |
4787 | 1535 PROP_TYPE_STRING) |
2676 | 1536 return (EINVAL); |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1537 VERIFY(nvpair_value_string(elem, &strval) == 0); |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1538 if ((error = dsl_prop_set(name, |
2676 | 1539 nvpair_name(elem), 1, strlen(strval) + 1, |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1540 strval)) != 0) |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1541 return (error); |
2676 | 1542 } else if (nvpair_type(elem) == DATA_TYPE_UINT64) { |
2885 | 1543 const char *unused; |
1544 | |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1545 VERIFY(nvpair_value_uint64(elem, &intval) == 0); |
2676 | 1546 |
1547 switch (zfs_prop_get_type(prop)) { | |
4787 | 1548 case PROP_TYPE_NUMBER: |
2676 | 1549 break; |
4787 | 1550 case PROP_TYPE_STRING: |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1551 return (EINVAL); |
4787 | 1552 case PROP_TYPE_INDEX: |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1553 if (zfs_prop_index_to_string(prop, |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1554 intval, &unused) != 0) |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1555 return (EINVAL); |
2676 | 1556 break; |
1557 default: | |
4577 | 1558 cmn_err(CE_PANIC, |
1559 "unknown property type"); | |
2676 | 1560 break; |
1561 } | |
1562 | |
2717
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1563 if ((error = dsl_prop_set(name, propname, |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1564 8, 1, &intval)) != 0) |
ed589a32259d
6469385 zfs_set_prop_nvlist range checking is busted
eschrock
parents:
2676
diff
changeset
|
1565 return (error); |
2676 | 1566 } else { |
1567 return (EINVAL); | |
1568 } | |
1569 break; | |
1570 } | |
1571 } | |
1572 | |
1573 return (0); | |
789 | 1574 } |
1575 | |
5367 | 1576 /* |
1577 * inputs: | |
1578 * zc_name name of filesystem | |
1579 * zc_value name of property to inherit | |
1580 * zc_nvlist_src{_size} nvlist of properties to apply | |
7265 | 1581 * zc_cookie clear existing local props? |
5367 | 1582 * |
1583 * outputs: none | |
1584 */ | |
789 | 1585 static int |
2676 | 1586 zfs_ioc_set_prop(zfs_cmd_t *zc) |
789 | 1587 { |
2676 | 1588 nvlist_t *nvl; |
1589 int error; | |
789 | 1590 |
5094 | 1591 if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, |
1592 &nvl)) != 0) | |
2676 | 1593 return (error); |
1594 | |
7265 | 1595 if (zc->zc_cookie) { |
1596 nvlist_t *origprops; | |
1597 objset_t *os; | |
1598 | |
1599 if (dmu_objset_open(zc->zc_name, DMU_OST_ANY, | |
1600 DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { | |
1601 if (dsl_prop_get_all(os, &origprops, TRUE) == 0) { | |
1602 clear_props(zc->zc_name, origprops); | |
1603 nvlist_free(origprops); | |
1604 } | |
1605 dmu_objset_close(os); | |
1606 } | |
1607 | |
1608 } | |
1609 | |
4787 | 1610 error = zfs_set_prop_nvlist(zc->zc_name, nvl); |
4543 | 1611 |
2676 | 1612 nvlist_free(nvl); |
1613 return (error); | |
789 | 1614 } |
1615 | |
5367 | 1616 /* |
1617 * inputs: | |
1618 * zc_name name of filesystem | |
1619 * zc_value name of property to inherit | |
1620 * | |
1621 * outputs: none | |
1622 */ | |
789 | 1623 static int |
4849
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
1624 zfs_ioc_inherit_prop(zfs_cmd_t *zc) |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
1625 { |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
1626 /* the property name has been validated by zfs_secpolicy_inherit() */ |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
1627 return (dsl_prop_set(zc->zc_name, zc->zc_value, 0, 0, NULL)); |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
1628 } |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
1629 |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
1630 static int |
4098
0a182c2128e6
6545726 make ZFS_IOC_POOL_*_PROPS in sync with zfs_ioc_pool_props_*
lling
parents:
4007
diff
changeset
|
1631 zfs_ioc_pool_set_props(zfs_cmd_t *zc) |
3912 | 1632 { |
5094 | 1633 nvlist_t *props; |
3912 | 1634 spa_t *spa; |
5094 | 1635 int error; |
3912 | 1636 |
5094 | 1637 if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, |
1638 &props))) | |
3912 | 1639 return (error); |
1640 | |
1641 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) { | |
5094 | 1642 nvlist_free(props); |
3912 | 1643 return (error); |
1644 } | |
1645 | |
5094 | 1646 error = spa_prop_set(spa, props); |
3912 | 1647 |
5094 | 1648 nvlist_free(props); |
3912 | 1649 spa_close(spa, FTAG); |
1650 | |
1651 return (error); | |
1652 } | |
1653 | |
1654 static int | |
4098
0a182c2128e6
6545726 make ZFS_IOC_POOL_*_PROPS in sync with zfs_ioc_pool_props_*
lling
parents:
4007
diff
changeset
|
1655 zfs_ioc_pool_get_props(zfs_cmd_t *zc) |
3912 | 1656 { |
1657 spa_t *spa; | |
1658 int error; | |
1659 nvlist_t *nvp = NULL; | |
1660 | |
1661 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) | |
1662 return (error); | |
1663 | |
5094 | 1664 error = spa_prop_get(spa, &nvp); |
3912 | 1665 |
1666 if (error == 0 && zc->zc_nvlist_dst != NULL) | |
1667 error = put_nvlist(zc, nvp); | |
1668 else | |
1669 error = EFAULT; | |
1670 | |
1671 spa_close(spa, FTAG); | |
1672 | |
1673 if (nvp) | |
1674 nvlist_free(nvp); | |
1675 return (error); | |
1676 } | |
1677 | |
1678 static int | |
4543 | 1679 zfs_ioc_iscsi_perm_check(zfs_cmd_t *zc) |
1680 { | |
1681 nvlist_t *nvp; | |
1682 int error; | |
1683 uint32_t uid; | |
1684 uint32_t gid; | |
1685 uint32_t *groups; | |
1686 uint_t group_cnt; | |
1687 cred_t *usercred; | |
1688 | |
5094 | 1689 if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, |
1690 &nvp)) != 0) { | |
4543 | 1691 return (error); |
1692 } | |
1693 | |
1694 if ((error = nvlist_lookup_uint32(nvp, | |
1695 ZFS_DELEG_PERM_UID, &uid)) != 0) { | |
1696 nvlist_free(nvp); | |
1697 return (EPERM); | |
1698 } | |
1699 | |
1700 if ((error = nvlist_lookup_uint32(nvp, | |
1701 ZFS_DELEG_PERM_GID, &gid)) != 0) { | |
1702 nvlist_free(nvp); | |
1703 return (EPERM); | |
1704 } | |
1705 | |
1706 if ((error = nvlist_lookup_uint32_array(nvp, ZFS_DELEG_PERM_GROUPS, | |
1707 &groups, &group_cnt)) != 0) { | |
1708 nvlist_free(nvp); | |
1709 return (EPERM); | |
1710 } | |
1711 usercred = cralloc(); | |
1712 if ((crsetugid(usercred, uid, gid) != 0) || | |
1713 (crsetgroups(usercred, group_cnt, (gid_t *)groups) != 0)) { | |
1714 nvlist_free(nvp); | |
1715 crfree(usercred); | |
1716 return (EPERM); | |
1717 } | |
1718 nvlist_free(nvp); | |
1719 error = dsl_deleg_access(zc->zc_name, | |
4787 | 1720 zfs_prop_to_name(ZFS_PROP_SHAREISCSI), usercred); |
4543 | 1721 crfree(usercred); |
1722 return (error); | |
1723 } | |
1724 | |
5367 | 1725 /* |
1726 * inputs: | |
1727 * zc_name name of filesystem | |
1728 * zc_nvlist_src{_size} nvlist of delegated permissions | |
1729 * zc_perm_action allow/unallow flag | |
1730 * | |
1731 * outputs: none | |
1732 */ | |
4543 | 1733 static int |
1734 zfs_ioc_set_fsacl(zfs_cmd_t *zc) | |
1735 { | |
1736 int error; | |
1737 nvlist_t *fsaclnv = NULL; | |
1738 | |
5094 | 1739 if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, |
1740 &fsaclnv)) != 0) | |
4543 | 1741 return (error); |
1742 | |
1743 /* | |
1744 * Verify nvlist is constructed correctly | |
1745 */ | |
1746 if ((error = zfs_deleg_verify_nvlist(fsaclnv)) != 0) { | |
1747 nvlist_free(fsaclnv); | |
1748 return (EINVAL); | |
1749 } | |
1750 | |
1751 /* | |
1752 * If we don't have PRIV_SYS_MOUNT, then validate | |
1753 * that user is allowed to hand out each permission in | |
1754 * the nvlist(s) | |
1755 */ | |
1756 | |
4787 | 1757 error = secpolicy_zfs(CRED()); |
4543 | 1758 if (error) { |
4787 | 1759 if (zc->zc_perm_action == B_FALSE) { |
1760 error = dsl_deleg_can_allow(zc->zc_name, | |
1761 fsaclnv, CRED()); | |
1762 } else { | |
1763 error = dsl_deleg_can_unallow(zc->zc_name, | |
1764 fsaclnv, CRED()); | |
1765 } | |
4543 | 1766 } |
1767 | |
1768 if (error == 0) | |
1769 error = dsl_deleg_set(zc->zc_name, fsaclnv, zc->zc_perm_action); | |
1770 | |
1771 nvlist_free(fsaclnv); | |
1772 return (error); | |
1773 } | |
1774 | |
5367 | 1775 /* |
1776 * inputs: | |
1777 * zc_name name of filesystem | |
1778 * | |
1779 * outputs: | |
1780 * zc_nvlist_src{_size} nvlist of delegated permissions | |
1781 */ | |
4543 | 1782 static int |
1783 zfs_ioc_get_fsacl(zfs_cmd_t *zc) | |
1784 { | |
1785 nvlist_t *nvp; | |
1786 int error; | |
1787 | |
1788 if ((error = dsl_deleg_get(zc->zc_name, &nvp)) == 0) { | |
1789 error = put_nvlist(zc, nvp); | |
1790 nvlist_free(nvp); | |
1791 } | |
1792 | |
1793 return (error); | |
1794 } | |
1795 | |
5367 | 1796 /* |
1797 * inputs: | |
1798 * zc_name name of volume | |
1799 * | |
1800 * outputs: none | |
1801 */ | |
4543 | 1802 static int |
789 | 1803 zfs_ioc_create_minor(zfs_cmd_t *zc) |
1804 { | |
4787 | 1805 return (zvol_create_minor(zc->zc_name, ddi_driver_major(zfs_dip))); |
789 | 1806 } |
1807 | |
5367 | 1808 /* |
1809 * inputs: | |
1810 * zc_name name of volume | |
1811 * | |
1812 * outputs: none | |
1813 */ | |
789 | 1814 static int |
1815 zfs_ioc_remove_minor(zfs_cmd_t *zc) | |
1816 { | |
2676 | 1817 return (zvol_remove_minor(zc->zc_name)); |
789 | 1818 } |
1819 | |
1820 /* | |
1821 * Search the vfs list for a specified resource. Returns a pointer to it | |
1822 * or NULL if no suitable entry is found. The caller of this routine | |
1823 * is responsible for releasing the returned vfs pointer. | |
1824 */ | |
1825 static vfs_t * | |
1826 zfs_get_vfs(const char *resource) | |
1827 { | |
1828 struct vfs *vfsp; | |
1829 struct vfs *vfs_found = NULL; | |
1830 | |
1831 vfs_list_read_lock(); | |
1832 vfsp = rootvfs; | |
1833 do { | |
1834 if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) { | |
1835 VFS_HOLD(vfsp); | |
1836 vfs_found = vfsp; | |
1837 break; | |
1838 } | |
1839 vfsp = vfsp->vfs_next; | |
1840 } while (vfsp != rootvfs); | |
1841 vfs_list_unlock(); | |
1842 return (vfs_found); | |
1843 } | |
1844 | |
4543 | 1845 /* ARGSUSED */ |
789 | 1846 static void |
4543 | 1847 zfs_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) |
789 | 1848 { |
5331 | 1849 zfs_creat_t *zct = arg; |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1850 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1851 zfs_create_fs(os, cr, zct->zct_zplprops, tx); |
5331 | 1852 } |
1853 | |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1854 #define ZFS_PROP_UNDEFINED ((uint64_t)-1) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1855 |
5331 | 1856 /* |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1857 * inputs: |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1858 * createprops list of properties requested by creator |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1859 * default_zplver zpl version to use if unspecified in createprops |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1860 * fuids_ok fuids allowed in this version of the spa? |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1861 * os parent objset pointer (NULL if root fs) |
5331 | 1862 * |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1863 * outputs: |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1864 * zplprops values for the zplprops we attach to the master node object |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1865 * is_ci true if requested file system will be purely case-insensitive |
5331 | 1866 * |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1867 * Determine the settings for utf8only, normalization and |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1868 * casesensitivity. Specific values may have been requested by the |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1869 * creator and/or we can inherit values from the parent dataset. If |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1870 * the file system is of too early a vintage, a creator can not |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1871 * request settings for these properties, even if the requested |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1872 * setting is the default value. We don't actually want to create dsl |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1873 * properties for these, so remove them from the source nvlist after |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1874 * processing. |
5331 | 1875 */ |
1876 static int | |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1877 zfs_fill_zplprops_impl(objset_t *os, uint64_t default_zplver, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1878 boolean_t fuids_ok, nvlist_t *createprops, nvlist_t *zplprops, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1879 boolean_t *is_ci) |
5331 | 1880 { |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1881 uint64_t zplver = default_zplver; |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1882 uint64_t sense = ZFS_PROP_UNDEFINED; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1883 uint64_t norm = ZFS_PROP_UNDEFINED; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1884 uint64_t u8 = ZFS_PROP_UNDEFINED; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1885 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1886 ASSERT(zplprops != NULL); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1887 |
5375 | 1888 /* |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1889 * Pull out creator prop choices, if any. |
5375 | 1890 */ |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1891 if (createprops) { |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1892 (void) nvlist_lookup_uint64(createprops, |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1893 zfs_prop_to_name(ZFS_PROP_VERSION), &zplver); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1894 (void) nvlist_lookup_uint64(createprops, |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1895 zfs_prop_to_name(ZFS_PROP_NORMALIZE), &norm); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1896 (void) nvlist_remove_all(createprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1897 zfs_prop_to_name(ZFS_PROP_NORMALIZE)); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1898 (void) nvlist_lookup_uint64(createprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1899 zfs_prop_to_name(ZFS_PROP_UTF8ONLY), &u8); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1900 (void) nvlist_remove_all(createprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1901 zfs_prop_to_name(ZFS_PROP_UTF8ONLY)); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1902 (void) nvlist_lookup_uint64(createprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1903 zfs_prop_to_name(ZFS_PROP_CASE), &sense); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1904 (void) nvlist_remove_all(createprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1905 zfs_prop_to_name(ZFS_PROP_CASE)); |
5331 | 1906 } |
1907 | |
5375 | 1908 /* |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1909 * If the zpl version requested is whacky or the file system |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1910 * or pool is version is too "young" to support normalization |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1911 * and the creator tried to set a value for one of the props, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1912 * error out. |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1913 */ |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1914 if ((zplver < ZPL_VERSION_INITIAL || zplver > ZPL_VERSION) || |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1915 (zplver >= ZPL_VERSION_FUID && !fuids_ok) || |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1916 (zplver < ZPL_VERSION_NORMALIZATION && |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1917 (norm != ZFS_PROP_UNDEFINED || u8 != ZFS_PROP_UNDEFINED || |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1918 sense != ZFS_PROP_UNDEFINED))) |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1919 return (ENOTSUP); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1920 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1921 /* |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1922 * Put the version in the zplprops |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1923 */ |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1924 VERIFY(nvlist_add_uint64(zplprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1925 zfs_prop_to_name(ZFS_PROP_VERSION), zplver) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1926 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1927 if (norm == ZFS_PROP_UNDEFINED) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1928 VERIFY(zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &norm) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1929 VERIFY(nvlist_add_uint64(zplprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1930 zfs_prop_to_name(ZFS_PROP_NORMALIZE), norm) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1931 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1932 /* |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1933 * If we're normalizing, names must always be valid UTF-8 strings. |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1934 */ |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1935 if (norm) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1936 u8 = 1; |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1937 if (u8 == ZFS_PROP_UNDEFINED) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1938 VERIFY(zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &u8) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1939 VERIFY(nvlist_add_uint64(zplprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1940 zfs_prop_to_name(ZFS_PROP_UTF8ONLY), u8) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1941 |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1942 if (sense == ZFS_PROP_UNDEFINED) |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1943 VERIFY(zfs_get_zplprop(os, ZFS_PROP_CASE, &sense) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1944 VERIFY(nvlist_add_uint64(zplprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1945 zfs_prop_to_name(ZFS_PROP_CASE), sense) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1946 |
6492
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
1947 if (is_ci) |
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
1948 *is_ci = (sense == ZFS_CASE_INSENSITIVE); |
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
1949 |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1950 return (0); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1951 } |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1952 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1953 static int |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1954 zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1955 nvlist_t *zplprops, boolean_t *is_ci) |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1956 { |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1957 boolean_t fuids_ok = B_TRUE; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1958 uint64_t zplver = ZPL_VERSION; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1959 objset_t *os = NULL; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1960 char parentname[MAXNAMELEN]; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1961 char *cp; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1962 int error; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1963 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1964 (void) strlcpy(parentname, dataset, sizeof (parentname)); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1965 cp = strrchr(parentname, '/'); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1966 ASSERT(cp != NULL); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1967 cp[0] = '\0'; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1968 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1969 if (zfs_earlier_version(dataset, SPA_VERSION_FUID)) { |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1970 zplver = ZPL_VERSION_FUID - 1; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1971 fuids_ok = B_FALSE; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1972 } |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1973 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1974 /* |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1975 * Open parent object set so we can inherit zplprop values. |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1976 */ |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1977 if ((error = dmu_objset_open(parentname, DMU_OST_ANY, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1978 DS_MODE_USER | DS_MODE_READONLY, &os)) != 0) |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1979 return (error); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1980 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1981 error = zfs_fill_zplprops_impl(os, zplver, fuids_ok, createprops, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1982 zplprops, is_ci); |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
1983 dmu_objset_close(os); |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1984 return (error); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1985 } |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1986 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1987 static int |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1988 zfs_fill_zplprops_root(uint64_t spa_vers, nvlist_t *createprops, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1989 nvlist_t *zplprops, boolean_t *is_ci) |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1990 { |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1991 boolean_t fuids_ok = B_TRUE; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1992 uint64_t zplver = ZPL_VERSION; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1993 int error; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1994 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1995 if (spa_vers < SPA_VERSION_FUID) { |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1996 zplver = ZPL_VERSION_FUID - 1; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1997 fuids_ok = B_FALSE; |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1998 } |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
1999 |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
2000 error = zfs_fill_zplprops_impl(NULL, zplver, fuids_ok, createprops, |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
2001 zplprops, is_ci); |
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
2002 return (error); |
789 | 2003 } |
2004 | |
5367 | 2005 /* |
2006 * inputs: | |
2007 * zc_objset_type type of objset to create (fs vs zvol) | |
2008 * zc_name name of new objset | |
2009 * zc_value name of snapshot to clone from (may be empty) | |
2010 * zc_nvlist_src{_size} nvlist of properties to apply | |
2011 * | |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2012 * outputs: none |
5367 | 2013 */ |
789 | 2014 static int |
2015 zfs_ioc_create(zfs_cmd_t *zc) | |
2016 { | |
2017 objset_t *clone; | |
2018 int error = 0; | |
5331 | 2019 zfs_creat_t zct; |
4543 | 2020 nvlist_t *nvprops = NULL; |
2021 void (*cbfunc)(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx); | |
789 | 2022 dmu_objset_type_t type = zc->zc_objset_type; |
2023 | |
2024 switch (type) { | |
2025 | |
2026 case DMU_OST_ZFS: | |
2027 cbfunc = zfs_create_cb; | |
2028 break; | |
2029 | |
2030 case DMU_OST_ZVOL: | |
2031 cbfunc = zvol_create_cb; | |
2032 break; | |
2033 | |
2034 default: | |
2199 | 2035 cbfunc = NULL; |
6423 | 2036 break; |
2199 | 2037 } |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2038 if (strchr(zc->zc_name, '@') || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2039 strchr(zc->zc_name, '%')) |
789 | 2040 return (EINVAL); |
2041 | |
2676 | 2042 if (zc->zc_nvlist_src != NULL && |
5094 | 2043 (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, |
2044 &nvprops)) != 0) | |
2676 | 2045 return (error); |
2046 | |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2047 zct.zct_zplprops = NULL; |
5331 | 2048 zct.zct_props = nvprops; |
2049 | |
2676 | 2050 if (zc->zc_value[0] != '\0') { |
789 | 2051 /* |
2052 * We're creating a clone of an existing snapshot. | |
2053 */ | |
2676 | 2054 zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; |
2055 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0) { | |
4543 | 2056 nvlist_free(nvprops); |
789 | 2057 return (EINVAL); |
2676 | 2058 } |
789 | 2059 |
2676 | 2060 error = dmu_objset_open(zc->zc_value, type, |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2061 DS_MODE_USER | DS_MODE_READONLY, &clone); |
2676 | 2062 if (error) { |
4543 | 2063 nvlist_free(nvprops); |
789 | 2064 return (error); |
2676 | 2065 } |
6492
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
2066 |
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
2067 error = dmu_objset_create(zc->zc_name, type, clone, 0, |
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
2068 NULL, NULL); |
5331 | 2069 if (error) { |
2070 dmu_objset_close(clone); | |
2071 nvlist_free(nvprops); | |
2072 return (error); | |
2073 } | |
789 | 2074 dmu_objset_close(clone); |
2075 } else { | |
6492
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
2076 boolean_t is_insensitive = B_FALSE; |
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
2077 |
2676 | 2078 if (cbfunc == NULL) { |
4543 | 2079 nvlist_free(nvprops); |
2199 | 2080 return (EINVAL); |
2676 | 2081 } |
2082 | |
789 | 2083 if (type == DMU_OST_ZVOL) { |
2676 | 2084 uint64_t volsize, volblocksize; |
2085 | |
4543 | 2086 if (nvprops == NULL || |
2087 nvlist_lookup_uint64(nvprops, | |
2676 | 2088 zfs_prop_to_name(ZFS_PROP_VOLSIZE), |
2089 &volsize) != 0) { | |
4543 | 2090 nvlist_free(nvprops); |
2676 | 2091 return (EINVAL); |
2092 } | |
2093 | |
4543 | 2094 if ((error = nvlist_lookup_uint64(nvprops, |
2676 | 2095 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), |
2096 &volblocksize)) != 0 && error != ENOENT) { | |
4543 | 2097 nvlist_free(nvprops); |
2676 | 2098 return (EINVAL); |
2099 } | |
1133
335d069294d1
6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents:
1003
diff
changeset
|
2100 |
2676 | 2101 if (error != 0) |
2102 volblocksize = zfs_prop_default_numeric( | |
2103 ZFS_PROP_VOLBLOCKSIZE); | |
2104 | |
2105 if ((error = zvol_check_volblocksize( | |
2106 volblocksize)) != 0 || | |
2107 (error = zvol_check_volsize(volsize, | |
2108 volblocksize)) != 0) { | |
4543 | 2109 nvlist_free(nvprops); |
789 | 2110 return (error); |
2676 | 2111 } |
4577 | 2112 } else if (type == DMU_OST_ZFS) { |
5331 | 2113 int error; |
2114 | |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2115 /* |
5331 | 2116 * We have to have normalization and |
2117 * case-folding flags correct when we do the | |
2118 * file system creation, so go figure them out | |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2119 * now. |
5331 | 2120 */ |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2121 VERIFY(nvlist_alloc(&zct.zct_zplprops, |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2122 NV_UNIQUE_NAME, KM_SLEEP) == 0); |
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2123 error = zfs_fill_zplprops(zc->zc_name, nvprops, |
7184
9508660f9c27
PSARC 2008/223 Pool root file system properties via zpool(1M)
timh
parents:
7046
diff
changeset
|
2124 zct.zct_zplprops, &is_insensitive); |
5331 | 2125 if (error != 0) { |
2126 nvlist_free(nvprops); | |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2127 nvlist_free(zct.zct_zplprops); |
5331 | 2128 return (error); |
4577 | 2129 } |
2676 | 2130 } |
6492
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
2131 error = dmu_objset_create(zc->zc_name, type, NULL, |
903545192033
6654808 FIGNORECASE lookups in a zfs xattr dir don't provide 'realname' data
timh
parents:
6423
diff
changeset
|
2132 is_insensitive ? DS_FLAG_CI_DATASET : 0, cbfunc, &zct); |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2133 nvlist_free(zct.zct_zplprops); |
789 | 2134 } |
2676 | 2135 |
2136 /* | |
2137 * It would be nice to do this atomically. | |
2138 */ | |
2139 if (error == 0) { | |
4787 | 2140 if ((error = zfs_set_prop_nvlist(zc->zc_name, nvprops)) != 0) |
2676 | 2141 (void) dmu_objset_destroy(zc->zc_name); |
2142 } | |
4543 | 2143 nvlist_free(nvprops); |
789 | 2144 return (error); |
2145 } | |
2146 | |
7265 | 2147 struct snap_prop_arg { |
2148 nvlist_t *nvprops; | |
2149 const char *snapname; | |
2150 }; | |
2151 | |
2152 static int | |
2153 set_snap_props(char *name, void *arg) | |
2154 { | |
2155 struct snap_prop_arg *snpa = arg; | |
2156 int len = strlen(name) + strlen(snpa->snapname) + 2; | |
2157 char *buf = kmem_alloc(len, KM_SLEEP); | |
2158 int err; | |
2159 | |
2160 (void) snprintf(buf, len, "%s@%s", name, snpa->snapname); | |
2161 err = zfs_set_prop_nvlist(buf, snpa->nvprops); | |
2162 if (err) | |
2163 (void) dmu_objset_destroy(buf); | |
2164 kmem_free(buf, len); | |
2165 return (err); | |
2166 } | |
2167 | |
5367 | 2168 /* |
2169 * inputs: | |
2170 * zc_name name of filesystem | |
2171 * zc_value short name of snapshot | |
2172 * zc_cookie recursive flag | |
2173 * | |
2174 * outputs: none | |
2175 */ | |
789 | 2176 static int |
2199 | 2177 zfs_ioc_snapshot(zfs_cmd_t *zc) |
2178 { | |
7265 | 2179 nvlist_t *nvprops = NULL; |
2180 int error; | |
2181 boolean_t recursive = zc->zc_cookie; | |
2182 | |
2676 | 2183 if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) |
2199 | 2184 return (EINVAL); |
7265 | 2185 |
2186 if (zc->zc_nvlist_src != NULL && | |
2187 (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, | |
2188 &nvprops)) != 0) | |
2189 return (error); | |
2190 | |
2191 error = dmu_objset_snapshot(zc->zc_name, zc->zc_value, recursive); | |
2192 | |
2193 /* | |
2194 * It would be nice to do this atomically. | |
2195 */ | |
2196 if (error == 0) { | |
2197 struct snap_prop_arg snpa; | |
2198 snpa.nvprops = nvprops; | |
2199 snpa.snapname = zc->zc_value; | |
2200 if (recursive) { | |
2201 error = dmu_objset_find(zc->zc_name, | |
2202 set_snap_props, &snpa, DS_FIND_CHILDREN); | |
2203 if (error) { | |
2204 (void) dmu_snapshots_destroy(zc->zc_name, | |
2205 zc->zc_value); | |
2206 } | |
2207 } else { | |
2208 error = set_snap_props(zc->zc_name, &snpa); | |
2209 } | |
2210 } | |
2211 nvlist_free(nvprops); | |
2212 return (error); | |
2199 | 2213 } |
2214 | |
4007 | 2215 int |
2199 | 2216 zfs_unmount_snap(char *name, void *arg) |
789 | 2217 { |
2417 | 2218 vfs_t *vfsp = NULL; |
2199 | 2219 |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2220 if (arg) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2221 char *snapname = arg; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2222 int len = strlen(name) + strlen(snapname) + 2; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2223 char *buf = kmem_alloc(len, KM_SLEEP); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2224 |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2225 (void) strcpy(buf, name); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2226 (void) strcat(buf, "@"); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2227 (void) strcat(buf, snapname); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2228 vfsp = zfs_get_vfs(buf); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2229 kmem_free(buf, len); |
2417 | 2230 } else if (strchr(name, '@')) { |
2199 | 2231 vfsp = zfs_get_vfs(name); |
2232 } | |
2233 | |
2234 if (vfsp) { | |
2235 /* | |
2236 * Always force the unmount for snapshots. | |
2237 */ | |
2238 int flag = MS_FORCE; | |
789 | 2239 int err; |
2240 | |
2199 | 2241 if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) { |
2242 VFS_RELE(vfsp); | |
2243 return (err); | |
2244 } | |
2245 VFS_RELE(vfsp); | |
2246 if ((err = dounmount(vfsp, flag, kcred)) != 0) | |
2247 return (err); | |
2248 } | |
2249 return (0); | |
2250 } | |
2251 | |
5367 | 2252 /* |
2253 * inputs: | |
2254 * zc_name name of filesystem | |
2255 * zc_value short name of snapshot | |
2256 * | |
2257 * outputs: none | |
2258 */ | |
2199 | 2259 static int |
2260 zfs_ioc_destroy_snaps(zfs_cmd_t *zc) | |
2261 { | |
2262 int err; | |
789 | 2263 |
2676 | 2264 if (snapshot_namecheck(zc->zc_value, NULL, NULL) != 0) |
2199 | 2265 return (EINVAL); |
2266 err = dmu_objset_find(zc->zc_name, | |
2676 | 2267 zfs_unmount_snap, zc->zc_value, DS_FIND_CHILDREN); |
2199 | 2268 if (err) |
2269 return (err); | |
2676 | 2270 return (dmu_snapshots_destroy(zc->zc_name, zc->zc_value)); |
2199 | 2271 } |
2272 | |
5367 | 2273 /* |
2274 * inputs: | |
2275 * zc_name name of dataset to destroy | |
2276 * zc_objset_type type of objset | |
2277 * | |
2278 * outputs: none | |
2279 */ | |
2199 | 2280 static int |
2281 zfs_ioc_destroy(zfs_cmd_t *zc) | |
2282 { | |
2283 if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS) { | |
2284 int err = zfs_unmount_snap(zc->zc_name, NULL); | |
2285 if (err) | |
2286 return (err); | |
789 | 2287 } |
2288 | |
2289 return (dmu_objset_destroy(zc->zc_name)); | |
2290 } | |
2291 | |
5367 | 2292 /* |
2293 * inputs: | |
5446 | 2294 * zc_name name of dataset to rollback (to most recent snapshot) |
5367 | 2295 * |
2296 * outputs: none | |
2297 */ | |
789 | 2298 static int |
2299 zfs_ioc_rollback(zfs_cmd_t *zc) | |
2300 { | |
5446 | 2301 objset_t *os; |
2302 int error; | |
2303 zfsvfs_t *zfsvfs = NULL; | |
2304 | |
2305 /* | |
2306 * Get the zfsvfs for the receiving objset. There | |
2307 * won't be one if we're operating on a zvol, if the | |
2308 * objset doesn't exist yet, or is not mounted. | |
2309 */ | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2310 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, DS_MODE_USER, &os); |
5446 | 2311 if (error) |
2312 return (error); | |
2313 | |
2314 if (dmu_objset_type(os) == DMU_OST_ZFS) { | |
2315 mutex_enter(&os->os->os_user_ptr_lock); | |
2316 zfsvfs = dmu_objset_get_user(os); | |
2317 if (zfsvfs != NULL) | |
2318 VFS_HOLD(zfsvfs->z_vfs); | |
2319 mutex_exit(&os->os->os_user_ptr_lock); | |
2320 } | |
2321 | |
2322 if (zfsvfs != NULL) { | |
2323 char osname[MAXNAMELEN]; | |
2324 int mode; | |
2325 | |
6083
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2326 error = zfs_suspend_fs(zfsvfs, osname, &mode); |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2327 if (error == 0) { |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2328 int resume_err; |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2329 |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2330 ASSERT(strcmp(osname, zc->zc_name) == 0); |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2331 error = dmu_objset_rollback(os); |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2332 resume_err = zfs_resume_fs(zfsvfs, osname, mode); |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2333 error = error ? error : resume_err; |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2334 } else { |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2335 dmu_objset_close(os); |
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2336 } |
5446 | 2337 VFS_RELE(zfsvfs->z_vfs); |
2338 } else { | |
2339 error = dmu_objset_rollback(os); | |
2340 } | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2341 /* Note, the dmu_objset_rollback() releases the objset for us. */ |
5446 | 2342 |
2343 return (error); | |
789 | 2344 } |
2345 | |
5367 | 2346 /* |
2347 * inputs: | |
2348 * zc_name old name of dataset | |
2349 * zc_value new name of dataset | |
2350 * zc_cookie recursive flag (only valid for snapshots) | |
2351 * | |
2352 * outputs: none | |
2353 */ | |
789 | 2354 static int |
2355 zfs_ioc_rename(zfs_cmd_t *zc) | |
2356 { | |
4490 | 2357 boolean_t recursive = zc->zc_cookie & 1; |
4007 | 2358 |
2676 | 2359 zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2360 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2361 strchr(zc->zc_value, '%')) |
789 | 2362 return (EINVAL); |
2363 | |
4007 | 2364 /* |
2365 * Unmount snapshot unless we're doing a recursive rename, | |
2366 * in which case the dataset code figures out which snapshots | |
2367 * to unmount. | |
2368 */ | |
2369 if (!recursive && strchr(zc->zc_name, '@') != NULL && | |
789 | 2370 zc->zc_objset_type == DMU_OST_ZFS) { |
2199 | 2371 int err = zfs_unmount_snap(zc->zc_name, NULL); |
2372 if (err) | |
2373 return (err); | |
789 | 2374 } |
4007 | 2375 return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive)); |
789 | 2376 } |
2377 | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2378 static void |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2379 clear_props(char *dataset, nvlist_t *props) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2380 { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2381 zfs_cmd_t *zc; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2382 nvpair_t *prop; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2383 |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2384 if (props == NULL) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2385 return; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2386 zc = kmem_alloc(sizeof (zfs_cmd_t), KM_SLEEP); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2387 (void) strcpy(zc->zc_name, dataset); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2388 for (prop = nvlist_next_nvpair(props, NULL); prop; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2389 prop = nvlist_next_nvpair(props, prop)) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2390 (void) strcpy(zc->zc_value, nvpair_name(prop)); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2391 if (zfs_secpolicy_inherit(zc, CRED()) == 0) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2392 (void) zfs_ioc_inherit_prop(zc); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2393 } |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2394 kmem_free(zc, sizeof (zfs_cmd_t)); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2395 } |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2396 |
5367 | 2397 /* |
2398 * inputs: | |
2399 * zc_name name of containing filesystem | |
2400 * zc_nvlist_src{_size} nvlist of properties to apply | |
2401 * zc_value name of snapshot to create | |
2402 * zc_string name of clone origin (if DRR_FLAG_CLONE) | |
2403 * zc_cookie file descriptor to recv from | |
2404 * zc_begin_record the BEGIN record of the stream (not byteswapped) | |
2405 * zc_guid force flag | |
2406 * | |
2407 * outputs: | |
2408 * zc_cookie number of bytes read | |
2409 */ | |
789 | 2410 static int |
5367 | 2411 zfs_ioc_recv(zfs_cmd_t *zc) |
789 | 2412 { |
2413 file_t *fp; | |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2414 objset_t *os; |
5367 | 2415 dmu_recv_cookie_t drc; |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2416 zfsvfs_t *zfsvfs = NULL; |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2417 boolean_t force = (boolean_t)zc->zc_guid; |
789 | 2418 int error, fd; |
5367 | 2419 offset_t off; |
2420 nvlist_t *props = NULL; | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2421 nvlist_t *origprops = NULL; |
5367 | 2422 objset_t *origin = NULL; |
2423 char *tosnap; | |
2424 char tofs[ZFS_MAXNAMELEN]; | |
789 | 2425 |
3265
967e0fca6143
6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents:
3087
diff
changeset
|
2426 if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2427 strchr(zc->zc_value, '@') == NULL || |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2428 strchr(zc->zc_value, '%')) |
3265
967e0fca6143
6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents:
3087
diff
changeset
|
2429 return (EINVAL); |
967e0fca6143
6463140 zfs recv with a snapshot name that has 2 @@ in a row succeeds
ahrens
parents:
3087
diff
changeset
|
2430 |
5367 | 2431 (void) strcpy(tofs, zc->zc_value); |
2432 tosnap = strchr(tofs, '@'); | |
2433 *tosnap = '\0'; | |
2434 tosnap++; | |
2435 | |
2436 if (zc->zc_nvlist_src != NULL && | |
2437 (error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size, | |
2438 &props)) != 0) | |
2439 return (error); | |
2440 | |
789 | 2441 fd = zc->zc_cookie; |
2442 fp = getf(fd); | |
5367 | 2443 if (fp == NULL) { |
2444 nvlist_free(props); | |
789 | 2445 return (EBADF); |
5367 | 2446 } |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2447 |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2448 if (dmu_objset_open(tofs, DMU_OST_ANY, |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2449 DS_MODE_USER | DS_MODE_READONLY, &os) == 0) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2450 /* |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2451 * Try to get the zfsvfs for the receiving objset. |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2452 * There won't be one if we're operating on a zvol, |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2453 * if the objset doesn't exist yet, or is not mounted. |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2454 */ |
5446 | 2455 mutex_enter(&os->os->os_user_ptr_lock); |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2456 if (zfsvfs = dmu_objset_get_user(os)) { |
6083
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2457 if (!mutex_tryenter(&zfsvfs->z_online_recv_lock)) { |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2458 mutex_exit(&os->os->os_user_ptr_lock); |
6083
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2459 dmu_objset_close(os); |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2460 zfsvfs = NULL; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2461 error = EBUSY; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2462 goto out; |
6083
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2463 } |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2464 VFS_HOLD(zfsvfs->z_vfs); |
6083
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2465 } |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2466 mutex_exit(&os->os->os_user_ptr_lock); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2467 |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2468 /* |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2469 * If new properties are supplied, they are to completely |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2470 * replace the existing ones, so stash away the existing ones. |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2471 */ |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2472 if (props) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2473 (void) dsl_prop_get_all(os, &origprops, TRUE); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2474 |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2475 dmu_objset_close(os); |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2476 } |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2477 |
5367 | 2478 if (zc->zc_string[0]) { |
2479 error = dmu_objset_open(zc->zc_string, DMU_OST_ANY, | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2480 DS_MODE_USER | DS_MODE_READONLY, &origin); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2481 if (error) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2482 goto out; |
5367 | 2483 } |
2484 | |
2485 error = dmu_recv_begin(tofs, tosnap, &zc->zc_begin_record, | |
2486 force, origin, zfsvfs != NULL, &drc); | |
2487 if (origin) | |
2488 dmu_objset_close(origin); | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2489 if (error) |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2490 goto out; |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2491 |
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2492 /* |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2493 * Reset properties. We do this before we receive the stream |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2494 * so that the properties are applied to the new data. |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
2495 */ |
5367 | 2496 if (props) { |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2497 clear_props(tofs, origprops); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2498 /* |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2499 * XXX - Note, this is all-or-nothing; should be best-effort. |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2500 */ |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2501 (void) zfs_set_prop_nvlist(tofs, props); |
5367 | 2502 } |
2503 | |
2504 off = fp->f_offset; | |
2505 error = dmu_recv_stream(&drc, fp->f_vnode, &off); | |
2506 | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2507 if (error == 0 && zfsvfs) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2508 char osname[MAXNAMELEN]; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2509 int mode; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2510 |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2511 /* online recv */ |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2512 error = zfs_suspend_fs(zfsvfs, osname, &mode); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2513 if (error == 0) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2514 int resume_err; |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2515 |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2516 error = dmu_recv_end(&drc); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2517 resume_err = zfs_resume_fs(zfsvfs, osname, mode); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2518 error = error ? error : resume_err; |
5367 | 2519 } else { |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2520 dmu_recv_abort_cleanup(&drc); |
5367 | 2521 } |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2522 } else if (error == 0) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2523 error = dmu_recv_end(&drc); |
6083
23e77aa611b1
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
ek110237
parents:
5977
diff
changeset
|
2524 } |
5367 | 2525 |
2526 zc->zc_cookie = off - fp->f_offset; | |
2527 if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) | |
2528 fp->f_offset = off; | |
2885 | 2529 |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2530 /* |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2531 * On error, restore the original props. |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2532 */ |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2533 if (error && props) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2534 clear_props(tofs, props); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2535 (void) zfs_set_prop_nvlist(tofs, origprops); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2536 } |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2537 out: |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2538 if (zfsvfs) { |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2539 mutex_exit(&zfsvfs->z_online_recv_lock); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2540 VFS_RELE(zfsvfs->z_vfs); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2541 } |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2542 nvlist_free(props); |
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2543 nvlist_free(origprops); |
789 | 2544 releasef(fd); |
2545 return (error); | |
2546 } | |
2547 | |
5367 | 2548 /* |
2549 * inputs: | |
2550 * zc_name name of snapshot to send | |
2551 * zc_value short name of incremental fromsnap (may be empty) | |
2552 * zc_cookie file descriptor to send stream to | |
2553 * zc_obj fromorigin flag (mutually exclusive with zc_value) | |
2554 * | |
2555 * outputs: none | |
2556 */ | |
789 | 2557 static int |
5367 | 2558 zfs_ioc_send(zfs_cmd_t *zc) |
789 | 2559 { |
2560 objset_t *fromsnap = NULL; | |
2561 objset_t *tosnap; | |
2562 file_t *fp; | |
2563 int error; | |
5367 | 2564 offset_t off; |
789 | 2565 |
2566 error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2567 DS_MODE_USER | DS_MODE_READONLY, &tosnap); |
789 | 2568 if (error) |
2569 return (error); | |
2570 | |
2676 | 2571 if (zc->zc_value[0] != '\0') { |
2885 | 2572 char buf[MAXPATHLEN]; |
2573 char *cp; | |
2574 | |
2575 (void) strncpy(buf, zc->zc_name, sizeof (buf)); | |
2576 cp = strchr(buf, '@'); | |
2577 if (cp) | |
2578 *(cp+1) = 0; | |
2579 (void) strncat(buf, zc->zc_value, sizeof (buf)); | |
2580 error = dmu_objset_open(buf, DMU_OST_ANY, | |
6689
47572a2f5e73
6610506 Eliminate or improve retry logic from callers of dmu_objset_open()
maybee
parents:
6643
diff
changeset
|
2581 DS_MODE_USER | DS_MODE_READONLY, &fromsnap); |
789 | 2582 if (error) { |
2583 dmu_objset_close(tosnap); | |
2584 return (error); | |
2585 } | |
2586 } | |
2587 | |
2588 fp = getf(zc->zc_cookie); | |
2589 if (fp == NULL) { | |
2590 dmu_objset_close(tosnap); | |
2591 if (fromsnap) | |
2592 dmu_objset_close(fromsnap); | |
2593 return (EBADF); | |
2594 } | |
2595 | |
5367 | 2596 off = fp->f_offset; |
2597 error = dmu_sendbackup(tosnap, fromsnap, zc->zc_obj, fp->f_vnode, &off); | |
2598 | |
2599 if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0) | |
2600 fp->f_offset = off; | |
789 | 2601 releasef(zc->zc_cookie); |
2602 if (fromsnap) | |
2603 dmu_objset_close(fromsnap); | |
2604 dmu_objset_close(tosnap); | |
2605 return (error); | |
2606 } | |
2607 | |
1544 | 2608 static int |
2609 zfs_ioc_inject_fault(zfs_cmd_t *zc) | |
2610 { | |
2611 int id, error; | |
2612 | |
2613 error = zio_inject_fault(zc->zc_name, (int)zc->zc_guid, &id, | |
2614 &zc->zc_inject_record); | |
2615 | |
2616 if (error == 0) | |
2617 zc->zc_guid = (uint64_t)id; | |
2618 | |
2619 return (error); | |
2620 } | |
2621 | |
2622 static int | |
2623 zfs_ioc_clear_fault(zfs_cmd_t *zc) | |
2624 { | |
2625 return (zio_clear_fault((int)zc->zc_guid)); | |
2626 } | |
2627 | |
2628 static int | |
2629 zfs_ioc_inject_list_next(zfs_cmd_t *zc) | |
2630 { | |
2631 int id = (int)zc->zc_guid; | |
2632 int error; | |
2633 | |
2634 error = zio_inject_list_next(&id, zc->zc_name, sizeof (zc->zc_name), | |
2635 &zc->zc_inject_record); | |
2636 | |
2637 zc->zc_guid = id; | |
2638 | |
2639 return (error); | |
2640 } | |
2641 | |
2642 static int | |
2643 zfs_ioc_error_log(zfs_cmd_t *zc) | |
2644 { | |
2645 spa_t *spa; | |
2646 int error; | |
2676 | 2647 size_t count = (size_t)zc->zc_nvlist_dst_size; |
1544 | 2648 |
2649 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) | |
2650 return (error); | |
2651 | |
2676 | 2652 error = spa_get_errlog(spa, (void *)(uintptr_t)zc->zc_nvlist_dst, |
1544 | 2653 &count); |
2654 if (error == 0) | |
2676 | 2655 zc->zc_nvlist_dst_size = count; |
1544 | 2656 else |
2676 | 2657 zc->zc_nvlist_dst_size = spa_get_errlog_size(spa); |
1544 | 2658 |
2659 spa_close(spa, FTAG); | |
2660 | |
2661 return (error); | |
2662 } | |
2663 | |
2664 static int | |
2665 zfs_ioc_clear(zfs_cmd_t *zc) | |
2666 { | |
2667 spa_t *spa; | |
2668 vdev_t *vd; | |
4808 | 2669 uint64_t txg; |
1544 | 2670 int error; |
2671 | |
2672 if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) | |
2673 return (error); | |
2674 | |
5329 | 2675 /* |
2676 * Try to resume any I/Os which may have been suspended | |
2677 * as a result of a complete pool failure. | |
2678 */ | |
2679 if (!list_is_empty(&spa->spa_zio_list)) { | |
2680 if (zio_vdev_resume_io(spa) != 0) { | |
2681 spa_close(spa, FTAG); | |
2682 return (EIO); | |
2683 } | |
2684 } | |
2685 | |
4451 | 2686 txg = spa_vdev_enter(spa); |
1544 | 2687 |
2676 | 2688 if (zc->zc_guid == 0) { |
1544 | 2689 vd = NULL; |
6643
3a34b0dbb107
6625086 changing cachefile doesn't remove old cache on last user
eschrock
parents:
6492
diff
changeset
|
2690 } else { |
3a34b0dbb107
6625086 changing cachefile doesn't remove old cache on last user
eschrock
parents:
6492
diff
changeset
|
2691 vd = spa_lookup_by_guid(spa, zc->zc_guid, B_TRUE); |
5450 | 2692 if (vd == NULL) { |
2693 (void) spa_vdev_exit(spa, NULL, txg, ENODEV); | |
2694 spa_close(spa, FTAG); | |
2695 return (ENODEV); | |
2696 } | |
1544 | 2697 } |
2698 | |
5329 | 2699 vdev_clear(spa, vd, B_TRUE); |
1544 | 2700 |
4451 | 2701 (void) spa_vdev_exit(spa, NULL, txg, 0); |
1544 | 2702 |
2703 spa_close(spa, FTAG); | |
2704 | |
2705 return (0); | |
2706 } | |
2707 | |
5367 | 2708 /* |
2709 * inputs: | |
2710 * zc_name name of filesystem | |
2711 * zc_value name of origin snapshot | |
2712 * | |
2713 * outputs: none | |
2714 */ | |
1544 | 2715 static int |
2082 | 2716 zfs_ioc_promote(zfs_cmd_t *zc) |
2717 { | |
2417 | 2718 char *cp; |
2719 | |
2720 /* | |
2721 * We don't need to unmount *all* the origin fs's snapshots, but | |
2722 * it's easier. | |
2723 */ | |
2676 | 2724 cp = strchr(zc->zc_value, '@'); |
2417 | 2725 if (cp) |
2726 *cp = '\0'; | |
2676 | 2727 (void) dmu_objset_find(zc->zc_value, |
2417 | 2728 zfs_unmount_snap, NULL, DS_FIND_SNAPSHOTS); |
2082 | 2729 return (dsl_dataset_promote(zc->zc_name)); |
2730 } | |
2731 | |
4543 | 2732 /* |
2733 * We don't want to have a hard dependency | |
2734 * against some special symbols in sharefs | |
5331 | 2735 * nfs, and smbsrv. Determine them if needed when |
4543 | 2736 * the first file system is shared. |
5331 | 2737 * Neither sharefs, nfs or smbsrv are unloadable modules. |
4543 | 2738 */ |
5331 | 2739 int (*znfsexport_fs)(void *arg); |
4543 | 2740 int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t); |
5331 | 2741 int (*zsmbexport_fs)(void *arg, boolean_t add_share); |
2742 | |
2743 int zfs_nfsshare_inited; | |
2744 int zfs_smbshare_inited; | |
2745 | |
4543 | 2746 ddi_modhandle_t nfs_mod; |
2747 ddi_modhandle_t sharefs_mod; | |
5331 | 2748 ddi_modhandle_t smbsrv_mod; |
4543 | 2749 kmutex_t zfs_share_lock; |
2750 | |
2751 static int | |
5331 | 2752 zfs_init_sharefs() |
2753 { | |
2754 int error; | |
2755 | |
2756 ASSERT(MUTEX_HELD(&zfs_share_lock)); | |
2757 /* Both NFS and SMB shares also require sharetab support. */ | |
2758 if (sharefs_mod == NULL && ((sharefs_mod = | |
2759 ddi_modopen("fs/sharefs", | |
2760 KRTLD_MODE_FIRST, &error)) == NULL)) { | |
2761 return (ENOSYS); | |
2762 } | |
2763 if (zshare_fs == NULL && ((zshare_fs = | |
2764 (int (*)(enum sharefs_sys_op, share_t *, uint32_t)) | |
2765 ddi_modsym(sharefs_mod, "sharefs_impl", &error)) == NULL)) { | |
2766 return (ENOSYS); | |
2767 } | |
2768 return (0); | |
2769 } | |
2770 | |
2771 static int | |
4543 | 2772 zfs_ioc_share(zfs_cmd_t *zc) |
2773 { | |
2774 int error; | |
2775 int opcode; | |
2776 | |
5331 | 2777 switch (zc->zc_share.z_sharetype) { |
2778 case ZFS_SHARE_NFS: | |
2779 case ZFS_UNSHARE_NFS: | |
2780 if (zfs_nfsshare_inited == 0) { | |
2781 mutex_enter(&zfs_share_lock); | |
2782 if (nfs_mod == NULL && ((nfs_mod = ddi_modopen("fs/nfs", | |
2783 KRTLD_MODE_FIRST, &error)) == NULL)) { | |
2784 mutex_exit(&zfs_share_lock); | |
2785 return (ENOSYS); | |
2786 } | |
2787 if (znfsexport_fs == NULL && | |
2788 ((znfsexport_fs = (int (*)(void *)) | |
2789 ddi_modsym(nfs_mod, | |
2790 "nfs_export", &error)) == NULL)) { | |
2791 mutex_exit(&zfs_share_lock); | |
2792 return (ENOSYS); | |
2793 } | |
2794 error = zfs_init_sharefs(); | |
2795 if (error) { | |
2796 mutex_exit(&zfs_share_lock); | |
2797 return (ENOSYS); | |
2798 } | |
2799 zfs_nfsshare_inited = 1; | |
4543 | 2800 mutex_exit(&zfs_share_lock); |
2801 } | |
5331 | 2802 break; |
2803 case ZFS_SHARE_SMB: | |
2804 case ZFS_UNSHARE_SMB: | |
2805 if (zfs_smbshare_inited == 0) { | |
2806 mutex_enter(&zfs_share_lock); | |
2807 if (smbsrv_mod == NULL && ((smbsrv_mod = | |
2808 ddi_modopen("drv/smbsrv", | |
2809 KRTLD_MODE_FIRST, &error)) == NULL)) { | |
2810 mutex_exit(&zfs_share_lock); | |
2811 return (ENOSYS); | |
2812 } | |
2813 if (zsmbexport_fs == NULL && ((zsmbexport_fs = | |
2814 (int (*)(void *, boolean_t))ddi_modsym(smbsrv_mod, | |
6139
5c743b207bf9
6541120 Configuration is not propagated to SMB kernel module
jb150015
parents:
6083
diff
changeset
|
2815 "smb_server_share", &error)) == NULL)) { |
5331 | 2816 mutex_exit(&zfs_share_lock); |
2817 return (ENOSYS); | |
2818 } | |
2819 error = zfs_init_sharefs(); | |
2820 if (error) { | |
2821 mutex_exit(&zfs_share_lock); | |
2822 return (ENOSYS); | |
2823 } | |
2824 zfs_smbshare_inited = 1; | |
4543 | 2825 mutex_exit(&zfs_share_lock); |
2826 } | |
5331 | 2827 break; |
2828 default: | |
2829 return (EINVAL); | |
4543 | 2830 } |
2831 | |
5331 | 2832 switch (zc->zc_share.z_sharetype) { |
2833 case ZFS_SHARE_NFS: | |
2834 case ZFS_UNSHARE_NFS: | |
2835 if (error = | |
2836 znfsexport_fs((void *) | |
2837 (uintptr_t)zc->zc_share.z_exportdata)) | |
2838 return (error); | |
2839 break; | |
2840 case ZFS_SHARE_SMB: | |
2841 case ZFS_UNSHARE_SMB: | |
2842 if (error = zsmbexport_fs((void *) | |
2843 (uintptr_t)zc->zc_share.z_exportdata, | |
2844 zc->zc_share.z_sharetype == ZFS_SHARE_SMB ? | |
2845 B_TRUE : B_FALSE)) { | |
2846 return (error); | |
2847 } | |
2848 break; | |
2849 } | |
2850 | |
2851 opcode = (zc->zc_share.z_sharetype == ZFS_SHARE_NFS || | |
2852 zc->zc_share.z_sharetype == ZFS_SHARE_SMB) ? | |
4543 | 2853 SHAREFS_ADD : SHAREFS_REMOVE; |
2854 | |
5331 | 2855 /* |
2856 * Add or remove share from sharetab | |
2857 */ | |
4543 | 2858 error = zshare_fs(opcode, |
2859 (void *)(uintptr_t)zc->zc_share.z_sharedata, | |
2860 zc->zc_share.z_sharemax); | |
2861 | |
2862 return (error); | |
2863 | |
2864 } | |
2865 | |
2866 /* | |
4988
db8abd9846d4
6595467 libzfs consumers should be allowed to write their own history (or none at all)
ek110237
parents:
4849
diff
changeset
|
2867 * pool create, destroy, and export don't log the history as part of |
db8abd9846d4
6595467 libzfs consumers should be allowed to write their own history (or none at all)
ek110237
parents:
4849
diff
changeset
|
2868 * zfsdev_ioctl, but rather zfs_ioc_pool_create, and zfs_ioc_pool_export |
db8abd9846d4
6595467 libzfs consumers should be allowed to write their own history (or none at all)
ek110237
parents:
4849
diff
changeset
|
2869 * do the logging of those commands. |
4543 | 2870 */ |
789 | 2871 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
|
2872 { zfs_ioc_pool_create, zfs_secpolicy_config, POOL_NAME, B_FALSE }, |
4577 | 2873 { zfs_ioc_pool_destroy, zfs_secpolicy_config, POOL_NAME, B_FALSE }, |
2874 { zfs_ioc_pool_import, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2875 { zfs_ioc_pool_export, zfs_secpolicy_config, POOL_NAME, B_FALSE }, | |
2876 { zfs_ioc_pool_configs, zfs_secpolicy_none, NO_NAME, B_FALSE }, | |
2877 { zfs_ioc_pool_stats, zfs_secpolicy_read, POOL_NAME, B_FALSE }, | |
2878 { zfs_ioc_pool_tryimport, zfs_secpolicy_config, NO_NAME, B_FALSE }, | |
2879 { zfs_ioc_pool_scrub, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2880 { zfs_ioc_pool_freeze, zfs_secpolicy_config, NO_NAME, B_FALSE }, | |
2881 { zfs_ioc_pool_upgrade, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2882 { zfs_ioc_pool_get_history, zfs_secpolicy_config, POOL_NAME, B_FALSE }, | |
2883 { zfs_ioc_vdev_add, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2884 { zfs_ioc_vdev_remove, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2885 { zfs_ioc_vdev_set_state, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2886 { zfs_ioc_vdev_attach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2887 { zfs_ioc_vdev_detach, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2888 { zfs_ioc_vdev_setpath, zfs_secpolicy_config, POOL_NAME, B_FALSE }, | |
2889 { zfs_ioc_objset_stats, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, | |
5498
334b476844ca
6622831 normalization properties are not preserved by "zfs send"
timh
parents:
5450
diff
changeset
|
2890 { zfs_ioc_objset_zplprops, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, |
4543 | 2891 { zfs_ioc_dataset_list_next, zfs_secpolicy_read, |
4577 | 2892 DATASET_NAME, B_FALSE }, |
4543 | 2893 { zfs_ioc_snapshot_list_next, zfs_secpolicy_read, |
4577 | 2894 DATASET_NAME, B_FALSE }, |
2895 { zfs_ioc_set_prop, zfs_secpolicy_none, DATASET_NAME, B_TRUE }, | |
2896 { zfs_ioc_create_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, | |
2897 { zfs_ioc_remove_minor, zfs_secpolicy_minor, DATASET_NAME, B_FALSE }, | |
2898 { zfs_ioc_create, zfs_secpolicy_create, DATASET_NAME, B_TRUE }, | |
2899 { zfs_ioc_destroy, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, | |
2900 { zfs_ioc_rollback, zfs_secpolicy_rollback, DATASET_NAME, B_TRUE }, | |
2901 { zfs_ioc_rename, zfs_secpolicy_rename, DATASET_NAME, B_TRUE }, | |
5367 | 2902 { zfs_ioc_recv, zfs_secpolicy_receive, DATASET_NAME, B_TRUE }, |
2903 { zfs_ioc_send, zfs_secpolicy_send, DATASET_NAME, B_TRUE }, | |
4577 | 2904 { zfs_ioc_inject_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, |
2905 { zfs_ioc_clear_fault, zfs_secpolicy_inject, NO_NAME, B_FALSE }, | |
2906 { zfs_ioc_inject_list_next, zfs_secpolicy_inject, NO_NAME, B_FALSE }, | |
2907 { zfs_ioc_error_log, zfs_secpolicy_inject, POOL_NAME, B_FALSE }, | |
2908 { zfs_ioc_clear, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2909 { zfs_ioc_promote, zfs_secpolicy_promote, DATASET_NAME, B_TRUE }, | |
2910 { zfs_ioc_destroy_snaps, zfs_secpolicy_destroy, DATASET_NAME, B_TRUE }, | |
2911 { zfs_ioc_snapshot, zfs_secpolicy_snapshot, DATASET_NAME, B_TRUE }, | |
2912 { zfs_ioc_dsobj_to_dsname, zfs_secpolicy_config, POOL_NAME, B_FALSE }, | |
2913 { zfs_ioc_obj_to_path, zfs_secpolicy_config, NO_NAME, B_FALSE }, | |
2914 { zfs_ioc_pool_set_props, zfs_secpolicy_config, POOL_NAME, B_TRUE }, | |
2915 { zfs_ioc_pool_get_props, zfs_secpolicy_read, POOL_NAME, B_FALSE }, | |
2916 { zfs_ioc_set_fsacl, zfs_secpolicy_fsacl, DATASET_NAME, B_TRUE }, | |
2917 { zfs_ioc_get_fsacl, zfs_secpolicy_read, DATASET_NAME, B_FALSE }, | |
4543 | 2918 { zfs_ioc_iscsi_perm_check, zfs_secpolicy_iscsi, |
4577 | 2919 DATASET_NAME, B_FALSE }, |
4849
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
2920 { zfs_ioc_share, zfs_secpolicy_share, DATASET_NAME, B_FALSE }, |
3a61e0a9a953
6536043 arc_byteswap_func_t and dmu_byteswap_func_t are redundant
ahrens
parents:
4808
diff
changeset
|
2921 { zfs_ioc_inherit_prop, zfs_secpolicy_inherit, DATASET_NAME, B_TRUE }, |
789 | 2922 }; |
2923 | |
2924 static int | |
2925 zfsdev_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp) | |
2926 { | |
2927 zfs_cmd_t *zc; | |
2928 uint_t vec; | |
2199 | 2929 int error, rc; |
789 | 2930 |
2931 if (getminor(dev) != 0) | |
2932 return (zvol_ioctl(dev, cmd, arg, flag, cr, rvalp)); | |
2933 | |
2934 vec = cmd - ZFS_IOC; | |
4787 | 2935 ASSERT3U(getmajor(dev), ==, ddi_driver_major(zfs_dip)); |
789 | 2936 |
2937 if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0])) | |
2938 return (EINVAL); | |
2939 | |
2940 zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); | |
2941 | |
2942 error = xcopyin((void *)arg, zc, sizeof (zfs_cmd_t)); | |
2943 | |
4787 | 2944 if (error == 0) |
4543 | 2945 error = zfs_ioc_vec[vec].zvec_secpolicy(zc, cr); |
789 | 2946 |
2947 /* | |
2948 * Ensure that all pool/dataset names are valid before we pass down to | |
2949 * the lower layers. | |
2950 */ | |
2951 if (error == 0) { | |
2952 zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; | |
2953 switch (zfs_ioc_vec[vec].zvec_namecheck) { | |
4577 | 2954 case POOL_NAME: |
789 | 2955 if (pool_namecheck(zc->zc_name, NULL, NULL) != 0) |
2956 error = EINVAL; | |
2957 break; | |
2958 | |
4577 | 2959 case DATASET_NAME: |
789 | 2960 if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0) |
2961 error = EINVAL; | |
2962 break; | |
2856 | 2963 |
4577 | 2964 case NO_NAME: |
2856 | 2965 break; |
789 | 2966 } |
2967 } | |
2968 | |
2969 if (error == 0) | |
2970 error = zfs_ioc_vec[vec].zvec_func(zc); | |
2971 | |
2199 | 2972 rc = xcopyout(zc, (void *)arg, sizeof (zfs_cmd_t)); |
4543 | 2973 if (error == 0) { |
2199 | 2974 error = rc; |
4543 | 2975 if (zfs_ioc_vec[vec].zvec_his_log == B_TRUE) |
2976 zfs_log_history(zc); | |
2977 } | |
789 | 2978 |
2979 kmem_free(zc, sizeof (zfs_cmd_t)); | |
2980 return (error); | |
2981 } | |
2982 | |
2983 static int | |
2984 zfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) | |
2985 { | |
2986 if (cmd != DDI_ATTACH) | |
2987 return (DDI_FAILURE); | |
2988 | |
2989 if (ddi_create_minor_node(dip, "zfs", S_IFCHR, 0, | |
2990 DDI_PSEUDO, 0) == DDI_FAILURE) | |
2991 return (DDI_FAILURE); | |
2992 | |
2993 zfs_dip = dip; | |
2994 | |
2995 ddi_report_dev(dip); | |
2996 | |
2997 return (DDI_SUCCESS); | |
2998 } | |
2999 | |
3000 static int | |
3001 zfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) | |
3002 { | |
3003 if (spa_busy() || zfs_busy() || zvol_busy()) | |
3004 return (DDI_FAILURE); | |
3005 | |
3006 if (cmd != DDI_DETACH) | |
3007 return (DDI_FAILURE); | |
3008 | |
3009 zfs_dip = NULL; | |
3010 | |
3011 ddi_prop_remove_all(dip); | |
3012 ddi_remove_minor_node(dip, NULL); | |
3013 | |
3014 return (DDI_SUCCESS); | |
3015 } | |
3016 | |
3017 /*ARGSUSED*/ | |
3018 static int | |
3019 zfs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) | |
3020 { | |
3021 switch (infocmd) { | |
3022 case DDI_INFO_DEVT2DEVINFO: | |
3023 *result = zfs_dip; | |
3024 return (DDI_SUCCESS); | |
3025 | |
3026 case DDI_INFO_DEVT2INSTANCE: | |
849
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3027 *result = (void *)0; |
789 | 3028 return (DDI_SUCCESS); |
3029 } | |
3030 | |
3031 return (DDI_FAILURE); | |
3032 } | |
3033 | |
3034 /* | |
3035 * OK, so this is a little weird. | |
3036 * | |
3037 * /dev/zfs is the control node, i.e. minor 0. | |
3038 * /dev/zvol/[r]dsk/pool/dataset are the zvols, minor > 0. | |
3039 * | |
3040 * /dev/zfs has basically nothing to do except serve up ioctls, | |
3041 * so most of the standard driver entry points are in zvol.c. | |
3042 */ | |
3043 static struct cb_ops zfs_cb_ops = { | |
3044 zvol_open, /* open */ | |
3045 zvol_close, /* close */ | |
3046 zvol_strategy, /* strategy */ | |
3047 nodev, /* print */ | |
6423 | 3048 zvol_dump, /* dump */ |
789 | 3049 zvol_read, /* read */ |
3050 zvol_write, /* write */ | |
3051 zfsdev_ioctl, /* ioctl */ | |
3052 nodev, /* devmap */ | |
3053 nodev, /* mmap */ | |
3054 nodev, /* segmap */ | |
3055 nochpoll, /* poll */ | |
3056 ddi_prop_op, /* prop_op */ | |
3057 NULL, /* streamtab */ | |
3058 D_NEW | D_MP | D_64BIT, /* Driver compatibility flag */ | |
3059 CB_REV, /* version */ | |
3638
6b28ebc717aa
6496357 spec_fsync() is useless on devices that do write caching
billm
parents:
3444
diff
changeset
|
3060 nodev, /* async read */ |
6b28ebc717aa
6496357 spec_fsync() is useless on devices that do write caching
billm
parents:
3444
diff
changeset
|
3061 nodev, /* async write */ |
789 | 3062 }; |
3063 | |
3064 static struct dev_ops zfs_dev_ops = { | |
3065 DEVO_REV, /* version */ | |
3066 0, /* refcnt */ | |
3067 zfs_info, /* info */ | |
3068 nulldev, /* identify */ | |
3069 nulldev, /* probe */ | |
3070 zfs_attach, /* attach */ | |
3071 zfs_detach, /* detach */ | |
3072 nodev, /* reset */ | |
3073 &zfs_cb_ops, /* driver operations */ | |
3074 NULL /* no bus operations */ | |
3075 }; | |
3076 | |
3077 static struct modldrv zfs_modldrv = { | |
4577 | 3078 &mod_driverops, "ZFS storage pool version " SPA_VERSION_STRING, |
2676 | 3079 &zfs_dev_ops |
789 | 3080 }; |
3081 | |
3082 static struct modlinkage modlinkage = { | |
3083 MODREV_1, | |
3084 (void *)&zfs_modlfs, | |
3085 (void *)&zfs_modldrv, | |
3086 NULL | |
3087 }; | |
3088 | |
4720
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
3089 |
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
3090 uint_t zfs_fsyncer_key; |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
3091 extern uint_t rrw_tsd_key; |
4720
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
3092 |
789 | 3093 int |
3094 _init(void) | |
3095 { | |
3096 int error; | |
3097 | |
849
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3098 spa_init(FREAD | FWRITE); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3099 zfs_init(); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3100 zvol_init(); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3101 |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3102 if ((error = mod_install(&modlinkage)) != 0) { |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3103 zvol_fini(); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3104 zfs_fini(); |
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3105 spa_fini(); |
789 | 3106 return (error); |
849
8d799fd81a9b
6345023 /dev/zfs fails to open once ZFS module is unloaded
bonwick
parents:
789
diff
changeset
|
3107 } |
789 | 3108 |
4720
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
3109 tsd_create(&zfs_fsyncer_key, NULL); |
5326
6752aa2bd5bc
6425096 want online 'zfs recv' (read only and read/write)
ek110237
parents:
5147
diff
changeset
|
3110 tsd_create(&rrw_tsd_key, NULL); |
4720
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
3111 |
789 | 3112 error = ldi_ident_from_mod(&modlinkage, &zfs_li); |
3113 ASSERT(error == 0); | |
4543 | 3114 mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL); |
789 | 3115 |
3116 return (0); | |
3117 } | |
3118 | |
3119 int | |
3120 _fini(void) | |
3121 { | |
3122 int error; | |
3123 | |
1544 | 3124 if (spa_busy() || zfs_busy() || zvol_busy() || zio_injection_enabled) |
789 | 3125 return (EBUSY); |
3126 | |
3127 if ((error = mod_remove(&modlinkage)) != 0) | |
3128 return (error); | |
3129 | |
3130 zvol_fini(); | |
3131 zfs_fini(); | |
3132 spa_fini(); | |
5331 | 3133 if (zfs_nfsshare_inited) |
4543 | 3134 (void) ddi_modclose(nfs_mod); |
5331 | 3135 if (zfs_smbshare_inited) |
3136 (void) ddi_modclose(smbsrv_mod); | |
3137 if (zfs_nfsshare_inited || zfs_smbshare_inited) | |
4543 | 3138 (void) ddi_modclose(sharefs_mod); |
789 | 3139 |
4720
8edc0d2e6f3f
6535160 Lock contention on zl_lock from zil_commit
fr157268
parents:
4715
diff
changeset
|
3140 tsd_destroy(&zfs_fsyncer_key); |
789 | 3141 ldi_ident_release(zfs_li); |
3142 zfs_li = NULL; | |
4543 | 3143 mutex_destroy(&zfs_share_lock); |
789 | 3144 |
3145 return (error); | |
3146 } | |
3147 | |
3148 int | |
3149 _info(struct modinfo *modinfop) | |
3150 { | |
3151 return (mod_info(&modlinkage, modinfop)); | |
3152 } |