author | Christopher Siden <chris.siden@delphix.com> |
Mon, 21 May 2012 12:11:39 -0700 | |
changeset 13700 | 2889e2596bd6 |
parent 13524 | f0e12b33f77c |
child 13743 | 95aba6e49b9f |
permissions | -rw-r--r-- |
789 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
1544 | 5 |
* Common Development and Distribution License (the "License"). |
6 |
* You may not use this file except in compliance with the License. |
|
789 | 7 |
* |
8 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 |
* or http://www.opensolaris.org/os/licensing. |
|
10 |
* See the License for the specific language governing permissions |
|
11 |
* and limitations under the License. |
|
12 |
* |
|
13 |
* When distributing Covered Code, include this CDDL HEADER in each |
|
14 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 |
* If applicable, add the following below this CDDL HEADER, with the |
|
16 |
* fields enclosed by brackets "[]" replaced with your own identifying |
|
17 |
* information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 |
* |
|
19 |
* CDDL HEADER END |
|
20 |
*/ |
|
13700
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
21 |
|
789 | 22 |
/* |
12296
7cf402a7f374
6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents:
11876
diff
changeset
|
23 |
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
13700
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
24 |
* Copyright (c) 2012 by Delphix. All rights reserved. |
789 | 25 |
*/ |
26 |
||
27 |
/* |
|
28 |
* Internal utility routines for the ZFS library. |
|
29 |
*/ |
|
30 |
||
31 |
#include <errno.h> |
|
32 |
#include <fcntl.h> |
|
33 |
#include <libintl.h> |
|
34 |
#include <stdarg.h> |
|
35 |
#include <stdio.h> |
|
36 |
#include <stdlib.h> |
|
37 |
#include <strings.h> |
|
38 |
#include <unistd.h> |
|
5094 | 39 |
#include <ctype.h> |
40 |
#include <math.h> |
|
789 | 41 |
#include <sys/mnttab.h> |
3635 | 42 |
#include <sys/mntent.h> |
43 |
#include <sys/types.h> |
|
789 | 44 |
|
45 |
#include <libzfs.h> |
|
46 |
||
47 |
#include "libzfs_impl.h" |
|
4787 | 48 |
#include "zfs_prop.h" |
13700
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
49 |
#include "zfeature_common.h" |
789 | 50 |
|
2082 | 51 |
int |
52 |
libzfs_errno(libzfs_handle_t *hdl) |
|
53 |
{ |
|
54 |
return (hdl->libzfs_error); |
|
55 |
} |
|
789 | 56 |
|
2082 | 57 |
const char * |
58 |
libzfs_error_action(libzfs_handle_t *hdl) |
|
59 |
{ |
|
60 |
return (hdl->libzfs_action); |
|
61 |
} |
|
62 |
||
63 |
const char * |
|
64 |
libzfs_error_description(libzfs_handle_t *hdl) |
|
65 |
{ |
|
66 |
if (hdl->libzfs_desc[0] != '\0') |
|
67 |
return (hdl->libzfs_desc); |
|
789 | 68 |
|
2082 | 69 |
switch (hdl->libzfs_error) { |
70 |
case EZFS_NOMEM: |
|
71 |
return (dgettext(TEXT_DOMAIN, "out of memory")); |
|
72 |
case EZFS_BADPROP: |
|
73 |
return (dgettext(TEXT_DOMAIN, "invalid property value")); |
|
74 |
case EZFS_PROPREADONLY: |
|
13061
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
75 |
return (dgettext(TEXT_DOMAIN, "read-only property")); |
2082 | 76 |
case EZFS_PROPTYPE: |
77 |
return (dgettext(TEXT_DOMAIN, "property doesn't apply to " |
|
78 |
"datasets of this type")); |
|
79 |
case EZFS_PROPNONINHERIT: |
|
80 |
return (dgettext(TEXT_DOMAIN, "property cannot be inherited")); |
|
81 |
case EZFS_PROPSPACE: |
|
82 |
return (dgettext(TEXT_DOMAIN, "invalid quota or reservation")); |
|
83 |
case EZFS_BADTYPE: |
|
84 |
return (dgettext(TEXT_DOMAIN, "operation not applicable to " |
|
85 |
"datasets of this type")); |
|
86 |
case EZFS_BUSY: |
|
87 |
return (dgettext(TEXT_DOMAIN, "pool or dataset is busy")); |
|
88 |
case EZFS_EXISTS: |
|
89 |
return (dgettext(TEXT_DOMAIN, "pool or dataset exists")); |
|
90 |
case EZFS_NOENT: |
|
91 |
return (dgettext(TEXT_DOMAIN, "no such pool or dataset")); |
|
92 |
case EZFS_BADSTREAM: |
|
93 |
return (dgettext(TEXT_DOMAIN, "invalid backup stream")); |
|
94 |
case EZFS_DSREADONLY: |
|
13061
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
95 |
return (dgettext(TEXT_DOMAIN, "dataset is read-only")); |
2082 | 96 |
case EZFS_VOLTOOBIG: |
97 |
return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for " |
|
98 |
"this system")); |
|
99 |
case EZFS_INVALIDNAME: |
|
100 |
return (dgettext(TEXT_DOMAIN, "invalid name")); |
|
101 |
case EZFS_BADRESTORE: |
|
102 |
return (dgettext(TEXT_DOMAIN, "unable to restore to " |
|
103 |
"destination")); |
|
104 |
case EZFS_BADBACKUP: |
|
105 |
return (dgettext(TEXT_DOMAIN, "backup failed")); |
|
106 |
case EZFS_BADTARGET: |
|
107 |
return (dgettext(TEXT_DOMAIN, "invalid target vdev")); |
|
108 |
case EZFS_NODEVICE: |
|
109 |
return (dgettext(TEXT_DOMAIN, "no such device in pool")); |
|
110 |
case EZFS_BADDEV: |
|
111 |
return (dgettext(TEXT_DOMAIN, "invalid device")); |
|
112 |
case EZFS_NOREPLICAS: |
|
113 |
return (dgettext(TEXT_DOMAIN, "no valid replicas")); |
|
114 |
case EZFS_RESILVERING: |
|
115 |
return (dgettext(TEXT_DOMAIN, "currently resilvering")); |
|
116 |
case EZFS_BADVERSION: |
|
13700
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
117 |
return (dgettext(TEXT_DOMAIN, "unsupported version or " |
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
118 |
"feature")); |
2082 | 119 |
case EZFS_POOLUNAVAIL: |
120 |
return (dgettext(TEXT_DOMAIN, "pool is unavailable")); |
|
121 |
case EZFS_DEVOVERFLOW: |
|
122 |
return (dgettext(TEXT_DOMAIN, "too many devices in one vdev")); |
|
123 |
case EZFS_BADPATH: |
|
124 |
return (dgettext(TEXT_DOMAIN, "must be an absolute path")); |
|
125 |
case EZFS_CROSSTARGET: |
|
126 |
return (dgettext(TEXT_DOMAIN, "operation crosses datasets or " |
|
127 |
"pools")); |
|
128 |
case EZFS_ZONED: |
|
129 |
return (dgettext(TEXT_DOMAIN, "dataset in use by local zone")); |
|
130 |
case EZFS_MOUNTFAILED: |
|
131 |
return (dgettext(TEXT_DOMAIN, "mount failed")); |
|
132 |
case EZFS_UMOUNTFAILED: |
|
133 |
return (dgettext(TEXT_DOMAIN, "umount failed")); |
|
3126 | 134 |
case EZFS_UNSHARENFSFAILED: |
2082 | 135 |
return (dgettext(TEXT_DOMAIN, "unshare(1M) failed")); |
3126 | 136 |
case EZFS_SHARENFSFAILED: |
2082 | 137 |
return (dgettext(TEXT_DOMAIN, "share(1M) failed")); |
5331 | 138 |
case EZFS_UNSHARESMBFAILED: |
139 |
return (dgettext(TEXT_DOMAIN, "smb remove share failed")); |
|
140 |
case EZFS_SHARESMBFAILED: |
|
141 |
return (dgettext(TEXT_DOMAIN, "smb add share failed")); |
|
2082 | 142 |
case EZFS_PERM: |
143 |
return (dgettext(TEXT_DOMAIN, "permission denied")); |
|
144 |
case EZFS_NOSPC: |
|
145 |
return (dgettext(TEXT_DOMAIN, "out of space")); |
|
11807
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
146 |
case EZFS_FAULT: |
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
147 |
return (dgettext(TEXT_DOMAIN, "bad address")); |
2082 | 148 |
case EZFS_IO: |
149 |
return (dgettext(TEXT_DOMAIN, "I/O error")); |
|
150 |
case EZFS_INTR: |
|
151 |
return (dgettext(TEXT_DOMAIN, "signal received")); |
|
152 |
case EZFS_ISSPARE: |
|
153 |
return (dgettext(TEXT_DOMAIN, "device is reserved as a hot " |
|
154 |
"spare")); |
|
155 |
case EZFS_INVALCONFIG: |
|
156 |
return (dgettext(TEXT_DOMAIN, "invalid vdev configuration")); |
|
2474
c001ad7e0c25
6368751 libzfs interface for mount/umounting all the file systems for a given pool
eschrock
parents:
2082
diff
changeset
|
157 |
case EZFS_RECURSIVE: |
c001ad7e0c25
6368751 libzfs interface for mount/umounting all the file systems for a given pool
eschrock
parents:
2082
diff
changeset
|
158 |
return (dgettext(TEXT_DOMAIN, "recursive dataset dependency")); |
2926 | 159 |
case EZFS_NOHISTORY: |
160 |
return (dgettext(TEXT_DOMAIN, "no history available")); |
|
3912 | 161 |
case EZFS_POOLPROPS: |
162 |
return (dgettext(TEXT_DOMAIN, "failed to retrieve " |
|
163 |
"pool properties")); |
|
164 |
case EZFS_POOL_NOTSUP: |
|
165 |
return (dgettext(TEXT_DOMAIN, "operation not supported " |
|
166 |
"on this type of pool")); |
|
167 |
case EZFS_POOL_INVALARG: |
|
168 |
return (dgettext(TEXT_DOMAIN, "invalid argument for " |
|
169 |
"this pool operation")); |
|
3978
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
170 |
case EZFS_NAMETOOLONG: |
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
171 |
return (dgettext(TEXT_DOMAIN, "dataset name is too long")); |
4276
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
172 |
case EZFS_OPENFAILED: |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
173 |
return (dgettext(TEXT_DOMAIN, "open failed")); |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
174 |
case EZFS_NOCAP: |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
175 |
return (dgettext(TEXT_DOMAIN, |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
176 |
"disk capacity information could not be retrieved")); |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
177 |
case EZFS_LABELFAILED: |
c42d49ffb16f
6385547 zpool create of a mirror using a device and a slice of a device (of same size) reports an error
taylor
parents:
4180
diff
changeset
|
178 |
return (dgettext(TEXT_DOMAIN, "write of label failed")); |
4543 | 179 |
case EZFS_BADWHO: |
180 |
return (dgettext(TEXT_DOMAIN, "invalid user/group")); |
|
181 |
case EZFS_BADPERM: |
|
182 |
return (dgettext(TEXT_DOMAIN, "invalid permission")); |
|
183 |
case EZFS_BADPERMSET: |
|
184 |
return (dgettext(TEXT_DOMAIN, "invalid permission set name")); |
|
185 |
case EZFS_NODELEGATION: |
|
186 |
return (dgettext(TEXT_DOMAIN, "delegated administration is " |
|
187 |
"disabled on pool")); |
|
5363 | 188 |
case EZFS_BADCACHE: |
189 |
return (dgettext(TEXT_DOMAIN, "invalid or missing cache file")); |
|
5450 | 190 |
case EZFS_ISL2CACHE: |
191 |
return (dgettext(TEXT_DOMAIN, "device is in use as a cache")); |
|
6423 | 192 |
case EZFS_VDEVNOTSUP: |
193 |
return (dgettext(TEXT_DOMAIN, "vdev specification is not " |
|
194 |
"supported")); |
|
7042
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
195 |
case EZFS_NOTSUP: |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
196 |
return (dgettext(TEXT_DOMAIN, "operation not supported " |
46fc4b6db23e
6721094 Setting certain properties on root pools should not be allowed
gw25295
parents:
6865
diff
changeset
|
197 |
"on this dataset")); |
7214
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7042
diff
changeset
|
198 |
case EZFS_ACTIVE_SPARE: |
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7042
diff
changeset
|
199 |
return (dgettext(TEXT_DOMAIN, "pool has active shared spare " |
04c540040a32
6721908 A hot spare "in use" in an exported zpool, is stolen when a disk fails in an imported pool.
lling
parents:
7042
diff
changeset
|
200 |
"device")); |
9701
cc5b64682e64
6803605 should be able to offline log devices
George Wilson <George.Wilson@Sun.COM>
parents:
9396
diff
changeset
|
201 |
case EZFS_UNPLAYED_LOGS: |
cc5b64682e64
6803605 should be able to offline log devices
George Wilson <George.Wilson@Sun.COM>
parents:
9396
diff
changeset
|
202 |
return (dgettext(TEXT_DOMAIN, "log device has unplayed intent " |
cc5b64682e64
6803605 should be able to offline log devices
George Wilson <George.Wilson@Sun.COM>
parents:
9396
diff
changeset
|
203 |
"logs")); |
10242
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
204 |
case EZFS_REFTAG_RELE: |
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
205 |
return (dgettext(TEXT_DOMAIN, "no such tag on this dataset")); |
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
206 |
case EZFS_REFTAG_HOLD: |
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
207 |
return (dgettext(TEXT_DOMAIN, "tag already exists on this " |
c40d075fbca6
PSARC/2009/297 zfs snapshot holds
Chris Kirby <chris.kirby@sun.com>
parents:
9701
diff
changeset
|
208 |
"dataset")); |
10342
108f0058f837
6833815 scheduled snapshots deleted per snapshot policy can lead to replication failures
Chris Kirby <chris.kirby@sun.com>
parents:
10242
diff
changeset
|
209 |
case EZFS_TAGTOOLONG: |
108f0058f837
6833815 scheduled snapshots deleted per snapshot policy can lead to replication failures
Chris Kirby <chris.kirby@sun.com>
parents:
10242
diff
changeset
|
210 |
return (dgettext(TEXT_DOMAIN, "tag too long")); |
11007
216d8396182e
PSARC/2009/557 ZFS send dedup
Lori Alt <Lori.Alt@Sun.COM>
parents:
10817
diff
changeset
|
211 |
case EZFS_PIPEFAILED: |
216d8396182e
PSARC/2009/557 ZFS send dedup
Lori Alt <Lori.Alt@Sun.COM>
parents:
10817
diff
changeset
|
212 |
return (dgettext(TEXT_DOMAIN, "pipe create failed")); |
216d8396182e
PSARC/2009/557 ZFS send dedup
Lori Alt <Lori.Alt@Sun.COM>
parents:
10817
diff
changeset
|
213 |
case EZFS_THREADCREATEFAILED: |
216d8396182e
PSARC/2009/557 ZFS send dedup
Lori Alt <Lori.Alt@Sun.COM>
parents:
10817
diff
changeset
|
214 |
return (dgettext(TEXT_DOMAIN, "thread create failed")); |
11422
42768837421d
PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents:
11022
diff
changeset
|
215 |
case EZFS_POSTSPLIT_ONLINE: |
42768837421d
PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents:
11022
diff
changeset
|
216 |
return (dgettext(TEXT_DOMAIN, "disk was split from this pool " |
42768837421d
PSARC/2009/511 zpool split
Mark J Musante <Mark.Musante@Sun.COM>
parents:
11022
diff
changeset
|
217 |
"into a new one")); |
12296
7cf402a7f374
6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents:
11876
diff
changeset
|
218 |
case EZFS_SCRUBBING: |
7cf402a7f374
6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents:
11876
diff
changeset
|
219 |
return (dgettext(TEXT_DOMAIN, "currently scrubbing; " |
7cf402a7f374
6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents:
11876
diff
changeset
|
220 |
"use 'zpool scrub -s' to cancel current scrub")); |
7cf402a7f374
6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents:
11876
diff
changeset
|
221 |
case EZFS_NO_SCRUB: |
7cf402a7f374
6675946 'zpool status' should show the progress of resilvering for individual disk.
Lin Ling <Lin.Ling@Sun.COM>
parents:
11876
diff
changeset
|
222 |
return (dgettext(TEXT_DOMAIN, "there is no active scrub")); |
13055 | 223 |
case EZFS_DIFF: |
224 |
return (dgettext(TEXT_DOMAIN, "unable to generate diffs")); |
|
225 |
case EZFS_DIFFDATA: |
|
226 |
return (dgettext(TEXT_DOMAIN, "invalid diff data")); |
|
13061
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
227 |
case EZFS_POOLREADONLY: |
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
228 |
return (dgettext(TEXT_DOMAIN, "pool is read-only")); |
2082 | 229 |
case EZFS_UNKNOWN: |
230 |
return (dgettext(TEXT_DOMAIN, "unknown error")); |
|
231 |
default: |
|
2500
12e683f74751
6455228 zpool_mount_datasets() should take an additional flag
eschrock
parents:
2474
diff
changeset
|
232 |
assert(hdl->libzfs_error == 0); |
12e683f74751
6455228 zpool_mount_datasets() should take an additional flag
eschrock
parents:
2474
diff
changeset
|
233 |
return (dgettext(TEXT_DOMAIN, "no error")); |
2082 | 234 |
} |
235 |
} |
|
236 |
||
237 |
/*PRINTFLIKE2*/ |
|
789 | 238 |
void |
2082 | 239 |
zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...) |
789 | 240 |
{ |
241 |
va_list ap; |
|
242 |
||
243 |
va_start(ap, fmt); |
|
244 |
||
2082 | 245 |
(void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc), |
246 |
fmt, ap); |
|
247 |
hdl->libzfs_desc_active = 1; |
|
789 | 248 |
|
249 |
va_end(ap); |
|
250 |
} |
|
251 |
||
2082 | 252 |
static void |
253 |
zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap) |
|
254 |
{ |
|
255 |
(void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action), |
|
256 |
fmt, ap); |
|
257 |
hdl->libzfs_error = error; |
|
258 |
||
259 |
if (hdl->libzfs_desc_active) |
|
260 |
hdl->libzfs_desc_active = 0; |
|
261 |
else |
|
262 |
hdl->libzfs_desc[0] = '\0'; |
|
263 |
||
264 |
if (hdl->libzfs_printerr) { |
|
265 |
if (error == EZFS_UNKNOWN) { |
|
266 |
(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal " |
|
267 |
"error: %s\n"), libzfs_error_description(hdl)); |
|
268 |
abort(); |
|
269 |
} |
|
270 |
||
271 |
(void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action, |
|
3912 | 272 |
libzfs_error_description(hdl)); |
2082 | 273 |
if (error == EZFS_NOMEM) |
274 |
exit(1); |
|
275 |
} |
|
276 |
} |
|
277 |
||
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
278 |
int |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
279 |
zfs_error(libzfs_handle_t *hdl, int error, const char *msg) |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
280 |
{ |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
281 |
return (zfs_error_fmt(hdl, error, "%s", msg)); |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
282 |
} |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
283 |
|
2082 | 284 |
/*PRINTFLIKE3*/ |
285 |
int |
|
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
286 |
zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) |
2082 | 287 |
{ |
288 |
va_list ap; |
|
289 |
||
290 |
va_start(ap, fmt); |
|
291 |
||
292 |
zfs_verror(hdl, error, fmt, ap); |
|
293 |
||
294 |
va_end(ap); |
|
295 |
||
296 |
return (-1); |
|
297 |
} |
|
298 |
||
299 |
static int |
|
300 |
zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt, |
|
301 |
va_list ap) |
|
302 |
{ |
|
303 |
switch (error) { |
|
304 |
case EPERM: |
|
305 |
case EACCES: |
|
306 |
zfs_verror(hdl, EZFS_PERM, fmt, ap); |
|
307 |
return (-1); |
|
308 |
||
4543 | 309 |
case ECANCELED: |
310 |
zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap); |
|
311 |
return (-1); |
|
312 |
||
2082 | 313 |
case EIO: |
314 |
zfs_verror(hdl, EZFS_IO, fmt, ap); |
|
315 |
return (-1); |
|
316 |
||
11807
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
317 |
case EFAULT: |
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
318 |
zfs_verror(hdl, EZFS_FAULT, fmt, ap); |
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
319 |
return (-1); |
73a3c0d27389
6911541 'zfs mount' coredump
Sam Falkner <Sam.Falkner@Sun.COM>
parents:
11422
diff
changeset
|
320 |
|
2082 | 321 |
case EINTR: |
322 |
zfs_verror(hdl, EZFS_INTR, fmt, ap); |
|
323 |
return (-1); |
|
324 |
} |
|
325 |
||
326 |
return (0); |
|
327 |
} |
|
328 |
||
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
329 |
int |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
330 |
zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg) |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
331 |
{ |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
332 |
return (zfs_standard_error_fmt(hdl, error, "%s", msg)); |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
333 |
} |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
334 |
|
2082 | 335 |
/*PRINTFLIKE3*/ |
336 |
int |
|
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
337 |
zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) |
789 | 338 |
{ |
339 |
va_list ap; |
|
340 |
||
341 |
va_start(ap, fmt); |
|
342 |
||
2082 | 343 |
if (zfs_common_error(hdl, error, fmt, ap) != 0) { |
344 |
va_end(ap); |
|
345 |
return (-1); |
|
346 |
} |
|
347 |
||
348 |
switch (error) { |
|
349 |
case ENXIO: |
|
5807
8b40dde8cc40
6609780 zpool dump core when trying to destroy pool
ck153898
parents:
5450
diff
changeset
|
350 |
case ENODEV: |
13524
f0e12b33f77c
1644 add ZFS "clones" property
Matthew Ahrens <matt@delphix.com>
parents:
13512
diff
changeset
|
351 |
case EPIPE: |
2082 | 352 |
zfs_verror(hdl, EZFS_IO, fmt, ap); |
353 |
break; |
|
354 |
||
355 |
case ENOENT: |
|
356 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
357 |
"dataset does not exist")); |
|
358 |
zfs_verror(hdl, EZFS_NOENT, fmt, ap); |
|
359 |
break; |
|
360 |
||
361 |
case ENOSPC: |
|
362 |
case EDQUOT: |
|
363 |
zfs_verror(hdl, EZFS_NOSPC, fmt, ap); |
|
364 |
return (-1); |
|
365 |
||
366 |
case EEXIST: |
|
367 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
368 |
"dataset already exists")); |
|
369 |
zfs_verror(hdl, EZFS_EXISTS, fmt, ap); |
|
370 |
break; |
|
371 |
||
372 |
case EBUSY: |
|
373 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
374 |
"dataset is busy")); |
|
375 |
zfs_verror(hdl, EZFS_BUSY, fmt, ap); |
|
376 |
break; |
|
4543 | 377 |
case EROFS: |
13061
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
378 |
zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); |
4543 | 379 |
break; |
3978
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
380 |
case ENAMETOOLONG: |
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
381 |
zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap); |
2dd668007b7a
6533813 recursive snapshotting resulted in a bad stack overflow
mmusante
parents:
3912
diff
changeset
|
382 |
break; |
5860
4e1dc300d1d7
6580259 onnv ZFS panic with zfs_purgedir in zfs_dir.c
ck153898
parents:
5807
diff
changeset
|
383 |
case ENOTSUP: |
4e1dc300d1d7
6580259 onnv ZFS panic with zfs_purgedir in zfs_dir.c
ck153898
parents:
5807
diff
changeset
|
384 |
zfs_verror(hdl, EZFS_BADVERSION, fmt, ap); |
4e1dc300d1d7
6580259 onnv ZFS panic with zfs_purgedir in zfs_dir.c
ck153898
parents:
5807
diff
changeset
|
385 |
break; |
9234
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
386 |
case EAGAIN: |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
387 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
388 |
"pool I/O is currently suspended")); |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
389 |
zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
390 |
break; |
2082 | 391 |
default: |
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
392 |
zfs_error_aux(hdl, strerror(error)); |
2082 | 393 |
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); |
394 |
break; |
|
789 | 395 |
} |
396 |
||
397 |
va_end(ap); |
|
2082 | 398 |
return (-1); |
789 | 399 |
} |
400 |
||
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
401 |
int |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
402 |
zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg) |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
403 |
{ |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
404 |
return (zpool_standard_error_fmt(hdl, error, "%s", msg)); |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
405 |
} |
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
406 |
|
2082 | 407 |
/*PRINTFLIKE3*/ |
408 |
int |
|
3237
98d0c28f2f5e
6480245 renaming a dataset to something with '%s' will cause segfault
lling
parents:
3126
diff
changeset
|
409 |
zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) |
789 | 410 |
{ |
2082 | 411 |
va_list ap; |
412 |
||
413 |
va_start(ap, fmt); |
|
414 |
||
415 |
if (zfs_common_error(hdl, error, fmt, ap) != 0) { |
|
416 |
va_end(ap); |
|
417 |
return (-1); |
|
418 |
} |
|
419 |
||
420 |
switch (error) { |
|
421 |
case ENODEV: |
|
422 |
zfs_verror(hdl, EZFS_NODEVICE, fmt, ap); |
|
423 |
break; |
|
424 |
||
425 |
case ENOENT: |
|
3912 | 426 |
zfs_error_aux(hdl, |
427 |
dgettext(TEXT_DOMAIN, "no such pool or dataset")); |
|
2082 | 428 |
zfs_verror(hdl, EZFS_NOENT, fmt, ap); |
429 |
break; |
|
430 |
||
431 |
case EEXIST: |
|
432 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
433 |
"pool already exists")); |
|
434 |
zfs_verror(hdl, EZFS_EXISTS, fmt, ap); |
|
435 |
break; |
|
436 |
||
437 |
case EBUSY: |
|
438 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy")); |
|
7341
938f611658fc
6736545 cut and paste error in zpool_standard_error_fmt() trashes error
Eric Schrock <Eric.Schrock@Sun.COM>
parents:
7214
diff
changeset
|
439 |
zfs_verror(hdl, EZFS_BUSY, fmt, ap); |
2082 | 440 |
break; |
441 |
||
442 |
case ENXIO: |
|
443 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
444 |
"one or more devices is currently unavailable")); |
|
445 |
zfs_verror(hdl, EZFS_BADDEV, fmt, ap); |
|
446 |
break; |
|
447 |
||
448 |
case ENAMETOOLONG: |
|
449 |
zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap); |
|
450 |
break; |
|
451 |
||
3912 | 452 |
case ENOTSUP: |
453 |
zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap); |
|
454 |
break; |
|
455 |
||
456 |
case EINVAL: |
|
457 |
zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap); |
|
458 |
break; |
|
459 |
||
4543 | 460 |
case ENOSPC: |
461 |
case EDQUOT: |
|
462 |
zfs_verror(hdl, EZFS_NOSPC, fmt, ap); |
|
463 |
return (-1); |
|
13061
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
464 |
|
9234
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
465 |
case EAGAIN: |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
466 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
467 |
"pool I/O is currently suspended")); |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
468 |
zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap); |
bffdc4fc05c4
6792139 recovering from a suspended pool needs some work
George Wilson <George.Wilson@Sun.COM>
parents:
8811
diff
changeset
|
469 |
break; |
4543 | 470 |
|
13061
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
471 |
case EROFS: |
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
472 |
zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap); |
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
473 |
break; |
bda0decf867b
PSARC 2010/306 Read-only ZFS pools
George Wilson <George.Wilson@Sun.COM>
parents:
13055
diff
changeset
|
474 |
|
2082 | 475 |
default: |
476 |
zfs_error_aux(hdl, strerror(error)); |
|
477 |
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap); |
|
478 |
} |
|
479 |
||
480 |
va_end(ap); |
|
481 |
return (-1); |
|
789 | 482 |
} |
483 |
||
484 |
/* |
|
485 |
* Display an out of memory error message and abort the current program. |
|
486 |
*/ |
|
2082 | 487 |
int |
488 |
no_memory(libzfs_handle_t *hdl) |
|
789 | 489 |
{ |
2082 | 490 |
return (zfs_error(hdl, EZFS_NOMEM, "internal error")); |
789 | 491 |
} |
492 |
||
493 |
/* |
|
494 |
* A safe form of malloc() which will die if the allocation fails. |
|
495 |
*/ |
|
496 |
void * |
|
2082 | 497 |
zfs_alloc(libzfs_handle_t *hdl, size_t size) |
789 | 498 |
{ |
499 |
void *data; |
|
500 |
||
501 |
if ((data = calloc(1, size)) == NULL) |
|
2082 | 502 |
(void) no_memory(hdl); |
789 | 503 |
|
504 |
return (data); |
|
505 |
} |
|
506 |
||
507 |
/* |
|
13055 | 508 |
* A safe form of asprintf() which will die if the allocation fails. |
509 |
*/ |
|
510 |
/*PRINTFLIKE2*/ |
|
511 |
char * |
|
512 |
zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...) |
|
513 |
{ |
|
514 |
va_list ap; |
|
515 |
char *ret; |
|
516 |
int err; |
|
517 |
||
518 |
va_start(ap, fmt); |
|
519 |
||
520 |
err = vasprintf(&ret, fmt, ap); |
|
521 |
||
522 |
va_end(ap); |
|
523 |
||
524 |
if (err < 0) |
|
525 |
(void) no_memory(hdl); |
|
526 |
||
527 |
return (ret); |
|
528 |
} |
|
529 |
||
530 |
/* |
|
2676 | 531 |
* A safe form of realloc(), which also zeroes newly allocated space. |
532 |
*/ |
|
533 |
void * |
|
534 |
zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize) |
|
535 |
{ |
|
536 |
void *ret; |
|
537 |
||
538 |
if ((ret = realloc(ptr, newsize)) == NULL) { |
|
539 |
(void) no_memory(hdl); |
|
540 |
return (NULL); |
|
541 |
} |
|
542 |
||
543 |
bzero((char *)ret + oldsize, (newsize - oldsize)); |
|
544 |
return (ret); |
|
545 |
} |
|
546 |
||
547 |
/* |
|
789 | 548 |
* A safe form of strdup() which will die if the allocation fails. |
549 |
*/ |
|
550 |
char * |
|
2082 | 551 |
zfs_strdup(libzfs_handle_t *hdl, const char *str) |
789 | 552 |
{ |
553 |
char *ret; |
|
554 |
||
555 |
if ((ret = strdup(str)) == NULL) |
|
2082 | 556 |
(void) no_memory(hdl); |
789 | 557 |
|
558 |
return (ret); |
|
559 |
} |
|
560 |
||
561 |
/* |
|
562 |
* Convert a number to an appropriately human-readable output. |
|
563 |
*/ |
|
564 |
void |
|
565 |
zfs_nicenum(uint64_t num, char *buf, size_t buflen) |
|
566 |
{ |
|
567 |
uint64_t n = num; |
|
568 |
int index = 0; |
|
569 |
char u; |
|
570 |
||
571 |
while (n >= 1024) { |
|
1162 | 572 |
n /= 1024; |
789 | 573 |
index++; |
574 |
} |
|
575 |
||
576 |
u = " KMGTPE"[index]; |
|
577 |
||
1162 | 578 |
if (index == 0) { |
789 | 579 |
(void) snprintf(buf, buflen, "%llu", n); |
1162 | 580 |
} else if ((num & ((1ULL << 10 * index) - 1)) == 0) { |
581 |
/* |
|
582 |
* If this is an even multiple of the base, always display |
|
583 |
* without any decimal precision. |
|
584 |
*/ |
|
789 | 585 |
(void) snprintf(buf, buflen, "%llu%c", n, u); |
1162 | 586 |
} else { |
587 |
/* |
|
588 |
* We want to choose a precision that reflects the best choice |
|
589 |
* for fitting in 5 characters. This can get rather tricky when |
|
590 |
* we have numbers that are very close to an order of magnitude. |
|
591 |
* For example, when displaying 10239 (which is really 9.999K), |
|
592 |
* we want only a single place of precision for 10.0K. We could |
|
593 |
* develop some complex heuristics for this, but it's much |
|
594 |
* easier just to try each combination in turn. |
|
595 |
*/ |
|
596 |
int i; |
|
597 |
for (i = 2; i >= 0; i--) { |
|
4451 | 598 |
if (snprintf(buf, buflen, "%.*f%c", i, |
599 |
(double)num / (1ULL << 10 * index), u) <= 5) |
|
1162 | 600 |
break; |
601 |
} |
|
602 |
} |
|
789 | 603 |
} |
2082 | 604 |
|
605 |
void |
|
606 |
libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) |
|
607 |
{ |
|
608 |
hdl->libzfs_printerr = printerr; |
|
609 |
} |
|
610 |
||
611 |
libzfs_handle_t * |
|
612 |
libzfs_init(void) |
|
613 |
{ |
|
614 |
libzfs_handle_t *hdl; |
|
615 |
||
13055 | 616 |
if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) { |
2082 | 617 |
return (NULL); |
618 |
} |
|
619 |
||
2500
12e683f74751
6455228 zpool_mount_datasets() should take an additional flag
eschrock
parents:
2474
diff
changeset
|
620 |
if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { |
2082 | 621 |
free(hdl); |
622 |
return (NULL); |
|
623 |
} |
|
624 |
||
625 |
if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { |
|
626 |
(void) close(hdl->libzfs_fd); |
|
627 |
free(hdl); |
|
628 |
return (NULL); |
|
629 |
} |
|
630 |
||
631 |
hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r"); |
|
632 |
||
4787 | 633 |
zfs_prop_init(); |
5094 | 634 |
zpool_prop_init(); |
13700
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
635 |
zpool_feature_init(); |
8811
f8deccf701cf
6790687 libzfs mnttab caching ignores external changes
Eric Taylor <Eric.Taylor@Sun.COM>
parents:
8343
diff
changeset
|
636 |
libzfs_mnttab_init(hdl); |
4787 | 637 |
|
2082 | 638 |
return (hdl); |
639 |
} |
|
640 |
||
641 |
void |
|
642 |
libzfs_fini(libzfs_handle_t *hdl) |
|
643 |
{ |
|
644 |
(void) close(hdl->libzfs_fd); |
|
645 |
if (hdl->libzfs_mnttab) |
|
646 |
(void) fclose(hdl->libzfs_mnttab); |
|
647 |
if (hdl->libzfs_sharetab) |
|
648 |
(void) fclose(hdl->libzfs_sharetab); |
|
4180
30b15f0bd3c9
6491973 sharemgr: zfs set sharenfs=on is slow with lots of zfs filesystems
dougm
parents:
3978
diff
changeset
|
649 |
zfs_uninit_libshare(hdl); |
4543 | 650 |
if (hdl->libzfs_log_str) |
651 |
(void) free(hdl->libzfs_log_str); |
|
6865 | 652 |
zpool_free_handles(hdl); |
10817
7dfde45252f0
6889826 ZFS retire agent should be able to repair pools
Eric Schrock <Eric.Schrock@Sun.COM>
parents:
10588
diff
changeset
|
653 |
libzfs_fru_clear(hdl, B_TRUE); |
2082 | 654 |
namespace_clear(hdl); |
8811
f8deccf701cf
6790687 libzfs mnttab caching ignores external changes
Eric Taylor <Eric.Taylor@Sun.COM>
parents:
8343
diff
changeset
|
655 |
libzfs_mnttab_fini(hdl); |
2082 | 656 |
free(hdl); |
657 |
} |
|
658 |
||
659 |
libzfs_handle_t * |
|
660 |
zpool_get_handle(zpool_handle_t *zhp) |
|
661 |
{ |
|
662 |
return (zhp->zpool_hdl); |
|
663 |
} |
|
664 |
||
665 |
libzfs_handle_t * |
|
666 |
zfs_get_handle(zfs_handle_t *zhp) |
|
667 |
{ |
|
668 |
return (zhp->zfs_hdl); |
|
669 |
} |
|
2676 | 670 |
|
7538
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
671 |
zpool_handle_t * |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
672 |
zfs_get_pool_handle(const zfs_handle_t *zhp) |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
673 |
{ |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
674 |
return (zhp->zpool_hdl); |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
675 |
} |
18c2451107fd
PSARC 2008/469 Excluding snapshot info from 'zfs list'
Rich Morris <Richard.Morris@Sun.COM>
parents:
7390
diff
changeset
|
676 |
|
2676 | 677 |
/* |
3635 | 678 |
* Given a name, determine whether or not it's a valid path |
679 |
* (starts with '/' or "./"). If so, walk the mnttab trying |
|
680 |
* to match the device number. If not, treat the path as an |
|
681 |
* fs/vol/snap name. |
|
682 |
*/ |
|
683 |
zfs_handle_t * |
|
684 |
zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype) |
|
685 |
{ |
|
686 |
struct stat64 statbuf; |
|
687 |
struct extmnttab entry; |
|
688 |
int ret; |
|
689 |
||
690 |
if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) { |
|
691 |
/* |
|
692 |
* It's not a valid path, assume it's a name of type 'argtype'. |
|
693 |
*/ |
|
694 |
return (zfs_open(hdl, path, argtype)); |
|
695 |
} |
|
696 |
||
697 |
if (stat64(path, &statbuf) != 0) { |
|
698 |
(void) fprintf(stderr, "%s: %s\n", path, strerror(errno)); |
|
699 |
return (NULL); |
|
700 |
} |
|
701 |
||
702 |
rewind(hdl->libzfs_mnttab); |
|
703 |
while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) { |
|
704 |
if (makedevice(entry.mnt_major, entry.mnt_minor) == |
|
705 |
statbuf.st_dev) { |
|
706 |
break; |
|
707 |
} |
|
708 |
} |
|
709 |
if (ret != 0) { |
|
710 |
return (NULL); |
|
711 |
} |
|
712 |
||
713 |
if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { |
|
714 |
(void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"), |
|
715 |
path); |
|
716 |
return (NULL); |
|
717 |
} |
|
718 |
||
719 |
return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM)); |
|
720 |
} |
|
721 |
||
722 |
/* |
|
2676 | 723 |
* Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from |
724 |
* an ioctl(). |
|
725 |
*/ |
|
726 |
int |
|
727 |
zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len) |
|
728 |
{ |
|
729 |
if (len == 0) |
|
12961
b521d551715f
6733267 Allow a pool to be imported with a missing slog
George Wilson <George.Wilson@Sun.COM>
parents:
12296
diff
changeset
|
730 |
len = 16 * 1024; |
2676 | 731 |
zc->zc_nvlist_dst_size = len; |
732 |
if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) |
|
733 |
zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL) |
|
734 |
return (-1); |
|
735 |
||
736 |
return (0); |
|
737 |
} |
|
738 |
||
739 |
/* |
|
740 |
* Called when an ioctl() which returns an nvlist fails with ENOMEM. This will |
|
741 |
* expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was |
|
742 |
* filled in by the kernel to indicate the actual required size. |
|
743 |
*/ |
|
744 |
int |
|
745 |
zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc) |
|
746 |
{ |
|
747 |
free((void *)(uintptr_t)zc->zc_nvlist_dst); |
|
748 |
if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t) |
|
749 |
zfs_alloc(hdl, zc->zc_nvlist_dst_size)) |
|
750 |
== NULL) |
|
751 |
return (-1); |
|
752 |
||
753 |
return (0); |
|
754 |
} |
|
755 |
||
756 |
/* |
|
2885 | 757 |
* Called to free the src and dst nvlists stored in the command structure. |
2676 | 758 |
*/ |
759 |
void |
|
760 |
zcmd_free_nvlists(zfs_cmd_t *zc) |
|
761 |
{ |
|
5094 | 762 |
free((void *)(uintptr_t)zc->zc_nvlist_conf); |
2676 | 763 |
free((void *)(uintptr_t)zc->zc_nvlist_src); |
764 |
free((void *)(uintptr_t)zc->zc_nvlist_dst); |
|
765 |
} |
|
766 |
||
5094 | 767 |
static int |
768 |
zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen, |
|
769 |
nvlist_t *nvl) |
|
2676 | 770 |
{ |
771 |
char *packed; |
|
772 |
size_t len; |
|
773 |
||
774 |
verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0); |
|
775 |
||
776 |
if ((packed = zfs_alloc(hdl, len)) == NULL) |
|
777 |
return (-1); |
|
778 |
||
779 |
verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); |
|
780 |
||
5094 | 781 |
*outnv = (uint64_t)(uintptr_t)packed; |
782 |
*outlen = len; |
|
783 |
||
784 |
return (0); |
|
785 |
} |
|
2676 | 786 |
|
5094 | 787 |
int |
788 |
zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) |
|
789 |
{ |
|
790 |
return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf, |
|
791 |
&zc->zc_nvlist_conf_size, nvl)); |
|
792 |
} |
|
793 |
||
794 |
int |
|
795 |
zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl) |
|
796 |
{ |
|
797 |
return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src, |
|
798 |
&zc->zc_nvlist_src_size, nvl)); |
|
2676 | 799 |
} |
800 |
||
801 |
/* |
|
802 |
* Unpacks an nvlist from the ZFS ioctl command structure. |
|
803 |
*/ |
|
804 |
int |
|
805 |
zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp) |
|
806 |
{ |
|
807 |
if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst, |
|
808 |
zc->zc_nvlist_dst_size, nvlp, 0) != 0) |
|
809 |
return (no_memory(hdl)); |
|
810 |
||
811 |
return (0); |
|
812 |
} |
|
3912 | 813 |
|
5094 | 814 |
int |
815 |
zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc) |
|
816 |
{ |
|
817 |
int error; |
|
818 |
||
819 |
zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str; |
|
820 |
error = ioctl(hdl->libzfs_fd, request, zc); |
|
821 |
if (hdl->libzfs_log_str) { |
|
822 |
free(hdl->libzfs_log_str); |
|
823 |
hdl->libzfs_log_str = NULL; |
|
824 |
} |
|
825 |
zc->zc_history = 0; |
|
826 |
||
827 |
return (error); |
|
828 |
} |
|
829 |
||
830 |
/* |
|
831 |
* ================================================================ |
|
832 |
* API shared by zfs and zpool property management |
|
833 |
* ================================================================ |
|
834 |
*/ |
|
835 |
||
3912 | 836 |
static void |
5094 | 837 |
zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type) |
3912 | 838 |
{ |
5094 | 839 |
zprop_list_t *pl = cbp->cb_proplist; |
3912 | 840 |
int i; |
841 |
char *title; |
|
842 |
size_t len; |
|
843 |
||
844 |
cbp->cb_first = B_FALSE; |
|
845 |
if (cbp->cb_scripted) |
|
846 |
return; |
|
847 |
||
848 |
/* |
|
849 |
* Start with the length of the column headers. |
|
850 |
*/ |
|
851 |
cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME")); |
|
852 |
cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN, |
|
853 |
"PROPERTY")); |
|
854 |
cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN, |
|
855 |
"VALUE")); |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
856 |
cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN, |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
857 |
"RECEIVED")); |
3912 | 858 |
cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN, |
859 |
"SOURCE")); |
|
860 |
||
8269
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
861 |
/* first property is always NAME */ |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
862 |
assert(cbp->cb_proplist->pl_prop == |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
863 |
((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME)); |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
864 |
|
3912 | 865 |
/* |
866 |
* Go through and calculate the widths for each column. For the |
|
867 |
* 'source' column, we kludge it up by taking the worst-case scenario of |
|
868 |
* inheriting from the longest name. This is acceptable because in the |
|
869 |
* majority of cases 'SOURCE' is the last column displayed, and we don't |
|
870 |
* use the width anyway. Note that the 'VALUE' column can be oversized, |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
871 |
* if the name of the property is much longer than any values we find. |
3912 | 872 |
*/ |
873 |
for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { |
|
874 |
/* |
|
875 |
* 'PROPERTY' column |
|
876 |
*/ |
|
5094 | 877 |
if (pl->pl_prop != ZPROP_INVAL) { |
878 |
const char *propname = (type == ZFS_TYPE_POOL) ? |
|
879 |
zpool_prop_to_name(pl->pl_prop) : |
|
880 |
zfs_prop_to_name(pl->pl_prop); |
|
881 |
||
882 |
len = strlen(propname); |
|
3912 | 883 |
if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) |
884 |
cbp->cb_colwidths[GET_COL_PROPERTY] = len; |
|
885 |
} else { |
|
886 |
len = strlen(pl->pl_user_prop); |
|
887 |
if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) |
|
888 |
cbp->cb_colwidths[GET_COL_PROPERTY] = len; |
|
889 |
} |
|
890 |
||
891 |
/* |
|
8269
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
892 |
* 'VALUE' column. The first property is always the 'name' |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
893 |
* property that was tacked on either by /sbin/zfs's |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
894 |
* zfs_do_get() or when calling zprop_expand_list(), so we |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
895 |
* ignore its width. If the user specified the name property |
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
896 |
* to display, then it will be later in the list in any case. |
3912 | 897 |
*/ |
8269
03a7e9050cfd
6674216 "zfs share" doesn't work, but "zfs set sharenfs=on" does
Mark J Musante <Mark.Musante@Sun.COM>
parents:
7538
diff
changeset
|
898 |
if (pl != cbp->cb_proplist && |
3912 | 899 |
pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) |
900 |
cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; |
|
901 |
||
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
902 |
/* 'RECEIVED' column. */ |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
903 |
if (pl != cbp->cb_proplist && |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
904 |
pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD]) |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
905 |
cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width; |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
906 |
|
3912 | 907 |
/* |
908 |
* 'NAME' and 'SOURCE' columns |
|
909 |
*/ |
|
5094 | 910 |
if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME : |
911 |
ZFS_PROP_NAME) && |
|
3912 | 912 |
pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { |
913 |
cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; |
|
914 |
cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + |
|
915 |
strlen(dgettext(TEXT_DOMAIN, "inherited from")); |
|
916 |
} |
|
917 |
} |
|
918 |
||
919 |
/* |
|
920 |
* Now go through and print the headers. |
|
921 |
*/ |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
922 |
for (i = 0; i < ZFS_GET_NCOLS; i++) { |
3912 | 923 |
switch (cbp->cb_columns[i]) { |
924 |
case GET_COL_NAME: |
|
925 |
title = dgettext(TEXT_DOMAIN, "NAME"); |
|
926 |
break; |
|
927 |
case GET_COL_PROPERTY: |
|
928 |
title = dgettext(TEXT_DOMAIN, "PROPERTY"); |
|
929 |
break; |
|
930 |
case GET_COL_VALUE: |
|
931 |
title = dgettext(TEXT_DOMAIN, "VALUE"); |
|
932 |
break; |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
933 |
case GET_COL_RECVD: |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
934 |
title = dgettext(TEXT_DOMAIN, "RECEIVED"); |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
935 |
break; |
3912 | 936 |
case GET_COL_SOURCE: |
937 |
title = dgettext(TEXT_DOMAIN, "SOURCE"); |
|
938 |
break; |
|
939 |
default: |
|
940 |
title = NULL; |
|
941 |
} |
|
942 |
||
943 |
if (title != NULL) { |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
944 |
if (i == (ZFS_GET_NCOLS - 1) || |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
945 |
cbp->cb_columns[i + 1] == GET_COL_NONE) |
3912 | 946 |
(void) printf("%s", title); |
947 |
else |
|
948 |
(void) printf("%-*s ", |
|
949 |
cbp->cb_colwidths[cbp->cb_columns[i]], |
|
950 |
title); |
|
951 |
} |
|
952 |
} |
|
953 |
(void) printf("\n"); |
|
954 |
} |
|
955 |
||
956 |
/* |
|
957 |
* Display a single line of output, according to the settings in the callback |
|
958 |
* structure. |
|
959 |
*/ |
|
960 |
void |
|
5094 | 961 |
zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp, |
962 |
const char *propname, const char *value, zprop_source_t sourcetype, |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
963 |
const char *source, const char *recvd_value) |
3912 | 964 |
{ |
965 |
int i; |
|
966 |
const char *str; |
|
967 |
char buf[128]; |
|
968 |
||
969 |
/* |
|
970 |
* Ignore those source types that the user has chosen to ignore. |
|
971 |
*/ |
|
972 |
if ((sourcetype & cbp->cb_sources) == 0) |
|
973 |
return; |
|
974 |
||
975 |
if (cbp->cb_first) |
|
5094 | 976 |
zprop_print_headers(cbp, cbp->cb_type); |
3912 | 977 |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
978 |
for (i = 0; i < ZFS_GET_NCOLS; i++) { |
3912 | 979 |
switch (cbp->cb_columns[i]) { |
980 |
case GET_COL_NAME: |
|
981 |
str = name; |
|
982 |
break; |
|
983 |
||
984 |
case GET_COL_PROPERTY: |
|
985 |
str = propname; |
|
986 |
break; |
|
987 |
||
988 |
case GET_COL_VALUE: |
|
989 |
str = value; |
|
990 |
break; |
|
991 |
||
992 |
case GET_COL_SOURCE: |
|
993 |
switch (sourcetype) { |
|
5094 | 994 |
case ZPROP_SRC_NONE: |
3912 | 995 |
str = "-"; |
996 |
break; |
|
997 |
||
5094 | 998 |
case ZPROP_SRC_DEFAULT: |
3912 | 999 |
str = "default"; |
1000 |
break; |
|
1001 |
||
5094 | 1002 |
case ZPROP_SRC_LOCAL: |
3912 | 1003 |
str = "local"; |
1004 |
break; |
|
1005 |
||
5094 | 1006 |
case ZPROP_SRC_TEMPORARY: |
3912 | 1007 |
str = "temporary"; |
1008 |
break; |
|
1009 |
||
5094 | 1010 |
case ZPROP_SRC_INHERITED: |
3912 | 1011 |
(void) snprintf(buf, sizeof (buf), |
1012 |
"inherited from %s", source); |
|
1013 |
str = buf; |
|
1014 |
break; |
|
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
1015 |
case ZPROP_SRC_RECEIVED: |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
1016 |
str = "received"; |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
1017 |
break; |
3912 | 1018 |
} |
1019 |
break; |
|
1020 |
||
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
1021 |
case GET_COL_RECVD: |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
1022 |
str = (recvd_value == NULL ? "-" : recvd_value); |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
1023 |
break; |
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
1024 |
|
3912 | 1025 |
default: |
1026 |
continue; |
|
1027 |
} |
|
1028 |
||
11022
63ab26072e41
PSARC 2009/510 ZFS received properties
Tom Erickson <Tom.Erickson@Sun.COM>
parents:
11007
diff
changeset
|
1029 |
if (cbp->cb_columns[i + 1] == GET_COL_NONE) |
3912 | 1030 |
(void) printf("%s", str); |
1031 |
else if (cbp->cb_scripted) |
|
1032 |
(void) printf("%s\t", str); |
|
1033 |
else |
|
1034 |
(void) printf("%-*s ", |
|
1035 |
cbp->cb_colwidths[cbp->cb_columns[i]], |
|
1036 |
str); |
|
1037 |
} |
|
1038 |
||
1039 |
(void) printf("\n"); |
|
1040 |
} |
|
4543 | 1041 |
|
5094 | 1042 |
/* |
1043 |
* Given a numeric suffix, convert the value into a number of bits that the |
|
1044 |
* resulting value must be shifted. |
|
1045 |
*/ |
|
1046 |
static int |
|
1047 |
str2shift(libzfs_handle_t *hdl, const char *buf) |
|
1048 |
{ |
|
1049 |
const char *ends = "BKMGTPEZ"; |
|
1050 |
int i; |
|
1051 |
||
1052 |
if (buf[0] == '\0') |
|
1053 |
return (0); |
|
1054 |
for (i = 0; i < strlen(ends); i++) { |
|
1055 |
if (toupper(buf[0]) == ends[i]) |
|
1056 |
break; |
|
1057 |
} |
|
1058 |
if (i == strlen(ends)) { |
|
1059 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1060 |
"invalid numeric suffix '%s'"), buf); |
|
1061 |
return (-1); |
|
1062 |
} |
|
1063 |
||
1064 |
/* |
|
1065 |
* We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't |
|
1066 |
* allow 'BB' - that's just weird. |
|
1067 |
*/ |
|
1068 |
if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' && |
|
1069 |
toupper(buf[0]) != 'B')) |
|
1070 |
return (10*i); |
|
1071 |
||
1072 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1073 |
"invalid numeric suffix '%s'"), buf); |
|
1074 |
return (-1); |
|
1075 |
} |
|
1076 |
||
1077 |
/* |
|
1078 |
* Convert a string of the form '100G' into a real number. Used when setting |
|
1079 |
* properties or creating a volume. 'buf' is used to place an extended error |
|
1080 |
* message for the caller to use. |
|
1081 |
*/ |
|
4543 | 1082 |
int |
5094 | 1083 |
zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num) |
1084 |
{ |
|
1085 |
char *end; |
|
1086 |
int shift; |
|
1087 |
||
1088 |
*num = 0; |
|
1089 |
||
1090 |
/* Check to see if this looks like a number. */ |
|
1091 |
if ((value[0] < '0' || value[0] > '9') && value[0] != '.') { |
|
1092 |
if (hdl) |
|
1093 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1094 |
"bad numeric value '%s'"), value); |
|
1095 |
return (-1); |
|
1096 |
} |
|
1097 |
||
10817
7dfde45252f0
6889826 ZFS retire agent should be able to repair pools
Eric Schrock <Eric.Schrock@Sun.COM>
parents:
10588
diff
changeset
|
1098 |
/* Rely on strtoull() to process the numeric portion. */ |
5094 | 1099 |
errno = 0; |
8343
655db2375fed
6739553 libzfs_status msgid table is out of sync
Eric Schrock <Eric.Schrock@Sun.COM>
parents:
8269
diff
changeset
|
1100 |
*num = strtoull(value, &end, 10); |
5094 | 1101 |
|
1102 |
/* |
|
1103 |
* Check for ERANGE, which indicates that the value is too large to fit |
|
1104 |
* in a 64-bit value. |
|
1105 |
*/ |
|
1106 |
if (errno == ERANGE) { |
|
1107 |
if (hdl) |
|
1108 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1109 |
"numeric value is too large")); |
|
1110 |
return (-1); |
|
1111 |
} |
|
1112 |
||
1113 |
/* |
|
1114 |
* If we have a decimal value, then do the computation with floating |
|
1115 |
* point arithmetic. Otherwise, use standard arithmetic. |
|
1116 |
*/ |
|
1117 |
if (*end == '.') { |
|
1118 |
double fval = strtod(value, &end); |
|
1119 |
||
1120 |
if ((shift = str2shift(hdl, end)) == -1) |
|
1121 |
return (-1); |
|
1122 |
||
1123 |
fval *= pow(2, shift); |
|
1124 |
||
1125 |
if (fval > UINT64_MAX) { |
|
1126 |
if (hdl) |
|
1127 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1128 |
"numeric value is too large")); |
|
1129 |
return (-1); |
|
1130 |
} |
|
1131 |
||
1132 |
*num = (uint64_t)fval; |
|
1133 |
} else { |
|
1134 |
if ((shift = str2shift(hdl, end)) == -1) |
|
1135 |
return (-1); |
|
1136 |
||
1137 |
/* Check for overflow */ |
|
1138 |
if (shift >= 64 || (*num << shift) >> shift != *num) { |
|
1139 |
if (hdl) |
|
1140 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1141 |
"numeric value is too large")); |
|
1142 |
return (-1); |
|
1143 |
} |
|
1144 |
||
1145 |
*num <<= shift; |
|
1146 |
} |
|
1147 |
||
1148 |
return (0); |
|
1149 |
} |
|
1150 |
||
1151 |
/* |
|
1152 |
* Given a propname=value nvpair to set, parse any numeric properties |
|
1153 |
* (index, boolean, etc) if they are specified as strings and add the |
|
1154 |
* resulting nvpair to the returned nvlist. |
|
1155 |
* |
|
1156 |
* At the DSL layer, all properties are either 64-bit numbers or strings. |
|
1157 |
* We want the user to be able to ignore this fact and specify properties |
|
1158 |
* as native values (numbers, for example) or as strings (to simplify |
|
1159 |
* command line utilities). This also handles converting index types |
|
1160 |
* (compression, checksum, etc) from strings to their on-disk index. |
|
1161 |
*/ |
|
1162 |
int |
|
1163 |
zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop, |
|
1164 |
zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp, |
|
1165 |
const char *errbuf) |
|
4543 | 1166 |
{ |
5094 | 1167 |
data_type_t datatype = nvpair_type(elem); |
1168 |
zprop_type_t proptype; |
|
1169 |
const char *propname; |
|
1170 |
char *value; |
|
1171 |
boolean_t isnone = B_FALSE; |
|
1172 |
||
1173 |
if (type == ZFS_TYPE_POOL) { |
|
1174 |
proptype = zpool_prop_get_type(prop); |
|
1175 |
propname = zpool_prop_to_name(prop); |
|
1176 |
} else { |
|
1177 |
proptype = zfs_prop_get_type(prop); |
|
1178 |
propname = zfs_prop_to_name(prop); |
|
1179 |
} |
|
1180 |
||
1181 |
/* |
|
1182 |
* Convert any properties to the internal DSL value types. |
|
1183 |
*/ |
|
1184 |
*svalp = NULL; |
|
1185 |
*ivalp = 0; |
|
1186 |
||
1187 |
switch (proptype) { |
|
1188 |
case PROP_TYPE_STRING: |
|
1189 |
if (datatype != DATA_TYPE_STRING) { |
|
1190 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1191 |
"'%s' must be a string"), nvpair_name(elem)); |
|
1192 |
goto error; |
|
1193 |
} |
|
1194 |
(void) nvpair_value_string(elem, svalp); |
|
1195 |
if (strlen(*svalp) >= ZFS_MAXPROPLEN) { |
|
1196 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1197 |
"'%s' is too long"), nvpair_name(elem)); |
|
1198 |
goto error; |
|
1199 |
} |
|
1200 |
break; |
|
1201 |
||
1202 |
case PROP_TYPE_NUMBER: |
|
1203 |
if (datatype == DATA_TYPE_STRING) { |
|
1204 |
(void) nvpair_value_string(elem, &value); |
|
1205 |
if (strcmp(value, "none") == 0) { |
|
1206 |
isnone = B_TRUE; |
|
1207 |
} else if (zfs_nicestrtonum(hdl, value, ivalp) |
|
1208 |
!= 0) { |
|
1209 |
goto error; |
|
1210 |
} |
|
1211 |
} else if (datatype == DATA_TYPE_UINT64) { |
|
1212 |
(void) nvpair_value_uint64(elem, ivalp); |
|
1213 |
} else { |
|
1214 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1215 |
"'%s' must be a number"), nvpair_name(elem)); |
|
1216 |
goto error; |
|
1217 |
} |
|
1218 |
||
1219 |
/* |
|
1220 |
* Quota special: force 'none' and don't allow 0. |
|
1221 |
*/ |
|
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1222 |
if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone && |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1223 |
(prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) { |
5094 | 1224 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1225 |
"use 'none' to disable quota/refquota")); |
5094 | 1226 |
goto error; |
1227 |
} |
|
1228 |
break; |
|
1229 |
||
1230 |
case PROP_TYPE_INDEX: |
|
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1231 |
if (datatype != DATA_TYPE_STRING) { |
5094 | 1232 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
1233 |
"'%s' must be a string"), nvpair_name(elem)); |
|
1234 |
goto error; |
|
1235 |
} |
|
1236 |
||
5378
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1237 |
(void) nvpair_value_string(elem, &value); |
111aa1baa84a
PSARC 2007/555 zfs fs-only quotas and reservations
ck153898
parents:
5363
diff
changeset
|
1238 |
|
5094 | 1239 |
if (zprop_string_to_index(prop, value, ivalp, type) != 0) { |
1240 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1241 |
"'%s' must be one of '%s'"), propname, |
|
1242 |
zprop_values(prop, type)); |
|
1243 |
goto error; |
|
1244 |
} |
|
1245 |
break; |
|
1246 |
||
1247 |
default: |
|
1248 |
abort(); |
|
1249 |
} |
|
4543 | 1250 |
|
5094 | 1251 |
/* |
1252 |
* Add the result to our return set of properties. |
|
1253 |
*/ |
|
1254 |
if (*svalp != NULL) { |
|
1255 |
if (nvlist_add_string(ret, propname, *svalp) != 0) { |
|
1256 |
(void) no_memory(hdl); |
|
1257 |
return (-1); |
|
1258 |
} |
|
1259 |
} else { |
|
1260 |
if (nvlist_add_uint64(ret, propname, *ivalp) != 0) { |
|
1261 |
(void) no_memory(hdl); |
|
1262 |
return (-1); |
|
1263 |
} |
|
1264 |
} |
|
1265 |
||
1266 |
return (0); |
|
1267 |
error: |
|
1268 |
(void) zfs_error(hdl, EZFS_BADPROP, errbuf); |
|
1269 |
return (-1); |
|
1270 |
} |
|
1271 |
||
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1272 |
static int |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1273 |
addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1274 |
zfs_type_t type) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1275 |
{ |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1276 |
int prop; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1277 |
zprop_list_t *entry; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1278 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1279 |
prop = zprop_name_to_prop(propname, type); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1280 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1281 |
if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type)) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1282 |
prop = ZPROP_INVAL; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1283 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1284 |
/* |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1285 |
* When no property table entry can be found, return failure if |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1286 |
* this is a pool property or if this isn't a user-defined |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1287 |
* dataset property, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1288 |
*/ |
13700
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
1289 |
if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL && |
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
1290 |
!zpool_prop_feature(propname) && |
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
1291 |
!zpool_prop_unsupported(propname)) || |
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
1292 |
(type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) && |
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
1293 |
!zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) { |
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1294 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1295 |
"invalid property '%s'"), propname); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1296 |
return (zfs_error(hdl, EZFS_BADPROP, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1297 |
dgettext(TEXT_DOMAIN, "bad property list"))); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1298 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1299 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1300 |
if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1301 |
return (-1); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1302 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1303 |
entry->pl_prop = prop; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1304 |
if (prop == ZPROP_INVAL) { |
13700
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
1305 |
if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == |
2889e2596bd6
2619 asynchronous destruction of ZFS file systems
Christopher Siden <chris.siden@delphix.com>
parents:
13524
diff
changeset
|
1306 |
NULL) { |
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1307 |
free(entry); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1308 |
return (-1); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1309 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1310 |
entry->pl_width = strlen(propname); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1311 |
} else { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1312 |
entry->pl_width = zprop_width(prop, &entry->pl_fixed, |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1313 |
type); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1314 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1315 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1316 |
*listp = entry; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1317 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1318 |
return (0); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1319 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1320 |
|
5094 | 1321 |
/* |
1322 |
* Given a comma-separated list of properties, construct a property list |
|
1323 |
* containing both user-defined and native properties. This function will |
|
1324 |
* return a NULL list if 'all' is specified, which can later be expanded |
|
1325 |
* by zprop_expand_list(). |
|
1326 |
*/ |
|
1327 |
int |
|
1328 |
zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp, |
|
1329 |
zfs_type_t type) |
|
1330 |
{ |
|
1331 |
*listp = NULL; |
|
1332 |
||
1333 |
/* |
|
1334 |
* If 'all' is specified, return a NULL list. |
|
1335 |
*/ |
|
1336 |
if (strcmp(props, "all") == 0) |
|
1337 |
return (0); |
|
1338 |
||
1339 |
/* |
|
1340 |
* If no props were specified, return an error. |
|
1341 |
*/ |
|
1342 |
if (props[0] == '\0') { |
|
1343 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1344 |
"no properties specified")); |
|
1345 |
return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN, |
|
1346 |
"bad property list"))); |
|
4543 | 1347 |
} |
5094 | 1348 |
|
1349 |
/* |
|
1350 |
* It would be nice to use getsubopt() here, but the inclusion of column |
|
1351 |
* aliases makes this more effort than it's worth. |
|
1352 |
*/ |
|
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1353 |
while (*props != '\0') { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1354 |
size_t len; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1355 |
char *p; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1356 |
char c; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1357 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1358 |
if ((p = strchr(props, ',')) == NULL) { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1359 |
len = strlen(props); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1360 |
p = props + len; |
5094 | 1361 |
} else { |
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1362 |
len = p - props; |
5094 | 1363 |
} |
1364 |
||
1365 |
/* |
|
1366 |
* Check for empty options. |
|
1367 |
*/ |
|
1368 |
if (len == 0) { |
|
1369 |
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, |
|
1370 |
"empty property name")); |
|
1371 |
return (zfs_error(hdl, EZFS_BADPROP, |
|
1372 |
dgettext(TEXT_DOMAIN, "bad property list"))); |
|
1373 |
} |
|
1374 |
||
1375 |
/* |
|
1376 |
* Check all regular property names. |
|
1377 |
*/ |
|
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1378 |
c = props[len]; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1379 |
props[len] = '\0'; |
5094 | 1380 |
|
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1381 |
if (strcmp(props, "space") == 0) { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1382 |
static char *spaceprops[] = { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1383 |
"name", "avail", "used", "usedbysnapshots", |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1384 |
"usedbydataset", "usedbyrefreservation", |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1385 |
"usedbychildren", NULL |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1386 |
}; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1387 |
int i; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1388 |
|
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1389 |
for (i = 0; spaceprops[i]; i++) { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1390 |
if (addlist(hdl, spaceprops[i], listp, type)) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1391 |
return (-1); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1392 |
listp = &(*listp)->pl_next; |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1393 |
} |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1394 |
} else { |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1395 |
if (addlist(hdl, props, listp, type)) |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1396 |
return (-1); |
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1397 |
listp = &(*listp)->pl_next; |
5094 | 1398 |
} |
1399 |
||
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1400 |
props = p; |
5094 | 1401 |
if (c == ',') |
7390
6d408f0a5fbd
PSARC/2008/518 ZFS space accounting enhancements
Matthew Ahrens <Matthew.Ahrens@Sun.COM>
parents:
7341
diff
changeset
|
1402 |
props++; |
5094 | 1403 |
} |
1404 |
||
1405 |
return (0); |
|
1406 |
} |
|
1407 |
||
1408 |
void |
|
1409 |
zprop_free_list(zprop_list_t *pl) |
|
1410 |
{ |
|
1411 |
zprop_list_t *next; |
|
4543 | 1412 |
|
5094 | 1413 |
while (pl != NULL) { |
1414 |
next = pl->pl_next; |
|
1415 |
free(pl->pl_user_prop); |
|
1416 |
free(pl); |
|
1417 |
pl = next; |
|
1418 |
} |
|
1419 |
} |
|
1420 |
||
1421 |
typedef struct expand_data { |
|
1422 |
zprop_list_t **last; |
|
1423 |
libzfs_handle_t *hdl; |
|
1424 |
zfs_type_t type; |
|
1425 |
} expand_data_t; |
|
1426 |
||
1427 |
int |
|
1428 |
zprop_expand_list_cb(int prop, void *cb) |
|
1429 |
{ |
|
1430 |
zprop_list_t *entry; |
|
1431 |
expand_data_t *edp = cb; |
|
1432 |
||
1433 |
if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL) |
|
1434 |
return (ZPROP_INVAL); |
|
1435 |
||
1436 |
entry->pl_prop = prop; |
|
1437 |
entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type); |
|
1438 |
entry->pl_all = B_TRUE; |
|
1439 |
||
1440 |
*(edp->last) = entry; |
|
1441 |
edp->last = &entry->pl_next; |
|
1442 |
||
1443 |
return (ZPROP_CONT); |
|
4543 | 1444 |
} |
5094 | 1445 |
|
1446 |
int |
|
1447 |
zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type) |
|
1448 |
{ |
|
1449 |
zprop_list_t *entry; |
|
1450 |
zprop_list_t **last; |
|
1451 |
expand_data_t exp; |
|
1452 |
||
1453 |
if (*plp == NULL) { |
|
1454 |
/* |
|
1455 |
* If this is the very first time we've been called for an 'all' |
|
1456 |
* specification, expand the list to include all native |
|
1457 |
* properties. |
|
1458 |
*/ |
|
1459 |
last = plp; |
|
1460 |
||
1461 |
exp.last = last; |
|
1462 |
exp.hdl = hdl; |
|
1463 |
exp.type = type; |
|
1464 |
||
1465 |
if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE, |
|
1466 |
B_FALSE, type) == ZPROP_INVAL) |
|
1467 |
return (-1); |
|
1468 |
||
1469 |
/* |
|
1470 |
* Add 'name' to the beginning of the list, which is handled |
|
1471 |
* specially. |
|
1472 |
*/ |
|
1473 |
if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL) |
|
1474 |
return (-1); |
|
1475 |
||
1476 |
entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : |
|
1477 |
ZFS_PROP_NAME; |
|
1478 |
entry->pl_width = zprop_width(entry->pl_prop, |
|
1479 |
&entry->pl_fixed, type); |
|
1480 |
entry->pl_all = B_TRUE; |
|
1481 |
entry->pl_next = *plp; |
|
1482 |
*plp = entry; |
|
1483 |
} |
|
1484 |
return (0); |
|
1485 |
} |
|
1486 |
||
1487 |
int |
|
1488 |
zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered, |
|
1489 |
zfs_type_t type) |
|
1490 |
{ |
|
1491 |
return (zprop_iter_common(func, cb, show_all, ordered, type)); |
|
1492 |
} |