mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-30 20:35:03 +01:00
Compare commits
63
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54055718ff | ||
|
|
1f61e76b51 | ||
|
|
69a8884af1 | ||
|
|
510c6cf29a | ||
|
|
c998438538 | ||
|
|
3649c5caff | ||
|
|
76322dbacd | ||
|
|
f9a559a82d | ||
|
|
9070dd1518 | ||
|
|
a54b5e9264 | ||
|
|
38f33e47a0 | ||
|
|
e7b58bcd8d | ||
|
|
d35c52a536 | ||
|
|
bbee93cbf5 | ||
|
|
4679e4f9c4 | ||
|
|
5d7d08d44a | ||
|
|
2b6caead9d | ||
|
|
e8fb91fe8b | ||
|
|
03a76b348d | ||
|
|
575826f183 | ||
|
|
5b37f4de45 | ||
|
|
45e294f985 | ||
|
|
af51f9df3c | ||
|
|
daf0e2ac5e | ||
|
|
4304e5eb17 | ||
|
|
421bcceeb8 | ||
|
|
c1ff6d05f5 | ||
|
|
d550f5d3db | ||
|
|
52ab77523b | ||
|
|
59fbe89293 | ||
|
|
2cfb122f55 | ||
|
|
c4f7dce098 | ||
|
|
6df7da0052 | ||
|
|
b329f45a9a | ||
|
|
04260ee25f | ||
|
|
72f50b48c4 | ||
|
|
563a73f034 | ||
|
|
79c1c663cb | ||
|
|
8fcffe2145 | ||
|
|
6e5c517269 | ||
|
|
34e6868261 | ||
|
|
62309d46fc | ||
|
|
9f5a40581d | ||
|
|
f8cb494d51 | ||
|
|
4e7ac0d6fc | ||
|
|
6e043e1a60 | ||
|
|
23b937f516 | ||
|
|
da2a3ace37 | ||
|
|
1b5ec3f62e | ||
|
|
516148ef3e | ||
|
|
6759c92a8d | ||
|
|
9929416e83 | ||
|
|
7ff6b770c6 | ||
|
|
fec900bd04 | ||
|
|
1b65664c28 | ||
|
|
6794374441 | ||
|
|
2487bb6cb1 | ||
|
|
e175267715 | ||
|
|
98e57db40f | ||
|
|
2a72044563 | ||
|
|
77bbc16437 | ||
|
|
4c1e483f92 | ||
|
|
af333ae2db |
No files matched your search
@@ -4,7 +4,7 @@
|
||||
The compilation of software known as FreeBSD is distributed under the
|
||||
following terms:
|
||||
|
||||
Copyright (c) 1992-2010 The FreeBSD Project. All rights reserved.
|
||||
Copyright (c) 1992-2009 The FreeBSD Project. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
||||
+2
-2
@@ -88,7 +88,7 @@ CLEANDIR= cleandir
|
||||
.endif
|
||||
|
||||
CVS?= cvs
|
||||
CVSFLAGS?= -r RELENG_7_3 -P -d -I!
|
||||
CVSFLAGS?= -r RELENG_7_2 -P -d -I!
|
||||
SUP?= /usr/bin/csup
|
||||
SUPFLAGS?= -g -L 2
|
||||
.if defined(SUPHOST)
|
||||
@@ -985,7 +985,7 @@ build-tools:
|
||||
#
|
||||
# cross-tools: Build cross-building tools
|
||||
#
|
||||
.if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${BOOTSTRAPPING} < 702102
|
||||
.if ${TARGET_ARCH} != ${MACHINE_ARCH}
|
||||
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386"
|
||||
_btxld= usr.sbin/btxld
|
||||
.endif
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
# The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last.
|
||||
#
|
||||
|
||||
# 20091129: pecoff image activator removed
|
||||
.if ${TARGET_ARCH} == "i386"
|
||||
OLD_FILES+=usr/include/machine/pecoff_machdep.h
|
||||
.endif
|
||||
# 20090203: adding_user.8 moved to adding_user.7
|
||||
OLD_FILES+=usr/share/man/man8/adding_user.8.gz
|
||||
# 20080407: pkg_sign has been removed
|
||||
|
||||
@@ -8,40 +8,16 @@ Items affecting the ports and packages system can be found in
|
||||
/usr/ports/UPDATING. Please read that file before running
|
||||
portupgrade.
|
||||
|
||||
20100323:
|
||||
FreeBSD 7.3-RELEASE
|
||||
|
||||
20091129:
|
||||
PECOFF image activator support removed.
|
||||
|
||||
20090831:
|
||||
The newly imported zic(8) produces a new format in the
|
||||
output. Please run tzsetup(8) to install the newly created
|
||||
data to /etc/localtime.
|
||||
|
||||
20090731:
|
||||
The ABI of various structures related to the SYSV IPC API have
|
||||
been changed. Bump __FreeBSD_version to 702105.
|
||||
|
||||
20090606:
|
||||
The components of PmcTools have been upgraded. Please
|
||||
update world and the kernel.
|
||||
|
||||
20090521:
|
||||
The k8temp(4) driver has been renamed to amdtemp(4) since
|
||||
support for K10 and K11 CPU families was added.
|
||||
|
||||
20090520:
|
||||
Update ZFS to version 13. ZFS users will need to re-build
|
||||
and install both kernel and world simultaneously in order
|
||||
for the ZFS tools to work. Existing pools will continue to work
|
||||
without upgrade. If a pool is upgraded it will no longer be
|
||||
usable by older kernel revs. ZFS send / recv between
|
||||
pool version 6 and pool version 13 is not supported.
|
||||
|
||||
20090504:
|
||||
FreeBSD 7.2-RELEASE
|
||||
|
||||
20090422: FreeBSD-SA-09:07.libc, FreeBSD-SA-09:08.openssl
|
||||
Don't leak information via uninitialized space in db(3) records.
|
||||
[09:07]
|
||||
|
||||
Sanity-check string lengths in order to stop OpenSSL crashing
|
||||
when printing corrupt BMPString or UniversalString objects. [09:08]
|
||||
|
||||
20090326:
|
||||
Following bug-fixes to TCP connection state flags, netstat, systat,
|
||||
and sockstat will need to be rebuilt in order to properly print
|
||||
@@ -158,13 +134,13 @@ portupgrade.
|
||||
|
||||
The important thing to note is that the 82575 adapters
|
||||
were supported in the em driver in 7.0, but now needed
|
||||
to be moved into igb, so if you have the affected cards
|
||||
to be moved into igb, so if you have the effected cards
|
||||
be sure and make any script changes to follow the name
|
||||
change.
|
||||
|
||||
There are only 3 PCI ID's affected in this change:
|
||||
There are only 3 PCI ID's effected in this change:
|
||||
0x10A7, 0x10A9, and 0x10D6
|
||||
So you can know ahead of time if they will be affected,
|
||||
So you can know ahead of time if they will be effected,
|
||||
these will now be supported in the igb driver. That
|
||||
driver will also support the new 82576 followon.
|
||||
|
||||
@@ -176,7 +152,7 @@ portupgrade.
|
||||
|
||||
20080724:
|
||||
I have MFC'd in code to support multiple routing tables.
|
||||
See the man pages setfib(1) and setfib(2).
|
||||
see the man pages setfib(1) and setfib(2).
|
||||
This is a backwards compatible version,
|
||||
but to make use of it you need to compile your kernel
|
||||
with options ROUTETABLES=2 (or more up to 16).
|
||||
|
||||
@@ -26,7 +26,6 @@ SUBDIR= cat \
|
||||
mv \
|
||||
pax \
|
||||
ps \
|
||||
pwait \
|
||||
pwd \
|
||||
${_rcp} \
|
||||
realpath \
|
||||
|
||||
@@ -115,7 +115,7 @@ main(int argc, char *argv[])
|
||||
fts_options |= FTS_LOGICAL;
|
||||
}
|
||||
} else
|
||||
fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
|
||||
fts_options = FTS_LOGICAL;
|
||||
|
||||
/* XXX: Why don't chflags and lchflags have compatible prototypes? */
|
||||
if (hflag)
|
||||
|
||||
+1
-1
@@ -339,7 +339,7 @@ setfile(struct stat *fs, int fd)
|
||||
if (!gotstat || fs->st_flags != ts.st_flags)
|
||||
if (fdval ?
|
||||
fchflags(fd, fs->st_flags) :
|
||||
(islink ? lchflags(to.p_path, fs->st_flags) :
|
||||
(islink ? (errno = ENOSYS) :
|
||||
chflags(to.p_path, fs->st_flags))) {
|
||||
warn("chflags: %s", to.p_path);
|
||||
rval = 1;
|
||||
|
||||
@@ -61,20 +61,9 @@ dl_iconv_open(const char *tocode, const char *fromcode)
|
||||
if (iconvlib == NULL)
|
||||
return (iconv_t)-1;
|
||||
iconv_open = (iconv_open_t *)dlfunc(iconvlib, ICONV_OPEN);
|
||||
if (iconv_open == NULL)
|
||||
goto dlfunc_err;
|
||||
dl_iconv = (dl_iconv_t *)dlfunc(iconvlib, ICONV_ENGINE);
|
||||
if (dl_iconv == NULL)
|
||||
goto dlfunc_err;
|
||||
dl_iconv_close = (dl_iconv_close_t *)dlfunc(iconvlib,
|
||||
ICONV_CLOSE);
|
||||
if (dl_iconv_close == NULL)
|
||||
goto dlfunc_err;
|
||||
}
|
||||
return iconv_open(tocode, fromcode);
|
||||
|
||||
dlfunc_err:
|
||||
dlclose(iconvlib);
|
||||
iconvlib = NULL;
|
||||
return (iconv_t)-1;
|
||||
}
|
||||
+2
-7
@@ -78,20 +78,15 @@ this overrides the
|
||||
.Ev BLOCKSIZE
|
||||
specification from the environment.
|
||||
.It Fl H
|
||||
.Dq Human-readable
|
||||
output.
|
||||
"Human-readable" output.
|
||||
Use unit suffixes: Byte, Kilobyte, Megabyte,
|
||||
Gigabyte, Terabyte and Petabyte in order to reduce the number of
|
||||
digits to four or fewer using base 10 for sizes.
|
||||
.It Fl h
|
||||
.Dq Human-readable
|
||||
output.
|
||||
"Human-readable" output.
|
||||
Use unit suffixes: Byte, Kilobyte, Megabyte,
|
||||
Gigabyte, Terabyte and Petabyte in order to reduce the number of
|
||||
digits to four or fewer using base 2 for sizes.
|
||||
Inodes statistics, if enabled with
|
||||
.Fl i ,
|
||||
are always printed in base 10.
|
||||
.It Fl i
|
||||
Include statistics on the number of free inodes.
|
||||
.It Fl k
|
||||
|
||||
+4
-30
@@ -364,23 +364,6 @@ prthumanval(int64_t bytes)
|
||||
(void)printf(" %6s", buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an inode count in "human-readable" format.
|
||||
*/
|
||||
static void
|
||||
prthumanvalinode(int64_t bytes)
|
||||
{
|
||||
char buf[6];
|
||||
int flags;
|
||||
|
||||
flags = HN_NOSPACE | HN_DECIMAL | HN_DIVISOR_1000;
|
||||
|
||||
humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
|
||||
bytes, "", HN_AUTOSCALE, flags);
|
||||
|
||||
(void)printf(" %5s", buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert statfs returned file system size into BLOCKSIZE units.
|
||||
* Attempts to avoid overflow for large file systems.
|
||||
@@ -423,10 +406,8 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
|
||||
mwp->mntfrom, "Filesystem", mwp->total, header,
|
||||
mwp->used, "Used", mwp->avail, "Avail");
|
||||
if (iflag) {
|
||||
mwp->iused = imax(hflag ? 0 : mwp->iused,
|
||||
(int)strlen(" iused"));
|
||||
mwp->ifree = imax(hflag ? 0 : mwp->ifree,
|
||||
(int)strlen("ifree"));
|
||||
mwp->iused = imax(mwp->iused, (int)strlen(" iused"));
|
||||
mwp->ifree = imax(mwp->ifree, (int)strlen("ifree"));
|
||||
(void)printf(" %*s %*s %%iused",
|
||||
mwp->iused - 2, "iused", mwp->ifree, "ifree");
|
||||
}
|
||||
@@ -450,15 +431,8 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
|
||||
if (iflag) {
|
||||
inodes = sfsp->f_files;
|
||||
used = inodes - sfsp->f_ffree;
|
||||
if (hflag) {
|
||||
(void)printf(" ");
|
||||
prthumanvalinode(used);
|
||||
prthumanvalinode(sfsp->f_ffree);
|
||||
} else {
|
||||
(void)printf(" %*jd %*jd", mwp->iused, (intmax_t)used,
|
||||
mwp->ifree, (intmax_t)sfsp->f_ffree);
|
||||
}
|
||||
(void)printf(" %4.0f%% ", inodes == 0 ? 100.0 :
|
||||
(void)printf(" %*jd %*jd %4.0f%% ", mwp->iused, (intmax_t)used,
|
||||
mwp->ifree, (intmax_t)sfsp->f_ffree, inodes == 0 ? 100.0 :
|
||||
(double)used / (double)inodes * 100.0);
|
||||
} else
|
||||
(void)printf(" ");
|
||||
|
||||
@@ -396,7 +396,6 @@ trng_add(char *str)
|
||||
default:
|
||||
paxwarn(1, "Bad option %c with time range %s",
|
||||
*flgpt, str);
|
||||
free(pt);
|
||||
goto out;
|
||||
}
|
||||
++flgpt;
|
||||
|
||||
+1
-2
@@ -39,7 +39,7 @@ extern fixpt_t ccpu;
|
||||
extern int cflag, eval, fscale, nlistread, rawcpu;
|
||||
extern unsigned long mempages;
|
||||
extern time_t now;
|
||||
extern int showthreads, sumrusage, termwidth, totwidth;
|
||||
extern int sumrusage, termwidth, totwidth;
|
||||
extern STAILQ_HEAD(velisthead, varent) varlist;
|
||||
|
||||
__BEGIN_DECLS
|
||||
@@ -71,7 +71,6 @@ void priorityr(KINFO *, VARENT *);
|
||||
void rgroupname(KINFO *, VARENT *);
|
||||
void runame(KINFO *, VARENT *);
|
||||
void rvar(KINFO *, VARENT *);
|
||||
int s_comm(KINFO *);
|
||||
int s_label(KINFO *);
|
||||
int s_rgroupname(KINFO *);
|
||||
int s_runame(KINFO *);
|
||||
|
||||
+9
-12
@@ -79,8 +79,8 @@ static VAR var[] = {
|
||||
CHAR, NULL, 0},
|
||||
{"blocked", "", "sigmask", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
{"caught", "", "sigcatch", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
{"comm", "COMMAND", NULL, LJUST|DSIZ, ucomm, s_comm,
|
||||
COMMLEN + OCOMMLEN + 1, 0, CHAR, NULL, 0},
|
||||
{"comm", "COMMAND", NULL, LJUST, ucomm, NULL, MAXCOMLEN, 0, CHAR,
|
||||
NULL, 0},
|
||||
{"command", "COMMAND", NULL, COMM|LJUST|USER, command, NULL, 16, 0,
|
||||
CHAR, NULL, 0},
|
||||
{"cpu", "CPU", NULL, 0, kvar, NULL, 3, KOFF(ki_estcpu), UINT, "d",
|
||||
@@ -135,13 +135,12 @@ static VAR var[] = {
|
||||
LONG, "ld", 0},
|
||||
{"nvcsw", "NVCSW", NULL, USER, rvar, NULL, 5, ROFF(ru_nvcsw),
|
||||
LONG, "ld", 0},
|
||||
{"nwchan", "NWCHAN", NULL, LJUST, nwchan, NULL, sizeof(void *) * 2, 0,
|
||||
CHAR, NULL, 0},
|
||||
{"nwchan", "NWCHAN", NULL, LJUST, nwchan, NULL, 8, 0, CHAR, NULL, 0},
|
||||
{"oublk", "OUBLK", NULL, USER, rvar, NULL, 4, ROFF(ru_oublock),
|
||||
LONG, "ld", 0},
|
||||
{"oublock", "", "oublk", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
{"paddr", "PADDR", NULL, 0, kvar, NULL, sizeof(void *) * 2,
|
||||
KOFF(ki_paddr), KPTR, "lx", 0},
|
||||
{"paddr", "PADDR", NULL, 0, kvar, NULL, 8, KOFF(ki_paddr), KPTR,
|
||||
"lx", 0},
|
||||
{"pagein", "PAGEIN", NULL, USER, pagein, NULL, 6, 0, CHAR, NULL, 0},
|
||||
{"pcpu", "", "%cpu", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
{"pending", "", "sig", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
@@ -195,13 +194,13 @@ static VAR var[] = {
|
||||
{"tsiz", "TSIZ", NULL, 0, kvar, NULL, 4, KOFF(ki_tsize), PGTOK, "ld", 0},
|
||||
{"tt", "TT ", NULL, 0, tname, NULL, 4, 0, CHAR, NULL, 0},
|
||||
{"tty", "TTY", NULL, LJUST, longtname, NULL, 8, 0, CHAR, NULL, 0},
|
||||
{"ucomm", "UCOMM", NULL, LJUST|DSIZ, ucomm, s_comm,
|
||||
COMMLEN + OCOMMLEN + 1, 0, CHAR, NULL, 0},
|
||||
{"ucomm", "UCOMM", NULL, LJUST, ucomm, NULL, MAXCOMLEN, 0, CHAR, NULL,
|
||||
0},
|
||||
{"uid", "UID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_uid), UINT,
|
||||
UIDFMT, 0},
|
||||
{"upr", "UPR", NULL, 0, upr, NULL, 3, 0, CHAR, NULL, 0},
|
||||
{"uprocp", "UPROCP", NULL, 0, kvar, NULL, sizeof(void *) * 2,
|
||||
KOFF(ki_paddr), KPTR, "lx", 0},
|
||||
{"uprocp", "UPROCP", NULL, 0, kvar, NULL, 8, KOFF(ki_paddr), KPTR,
|
||||
"lx", 0},
|
||||
{"user", "USER", NULL, LJUST|DSIZ, uname, s_uname, USERLEN, 0, CHAR,
|
||||
NULL, 0},
|
||||
{"usrpri", "", "upr", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
@@ -325,8 +324,6 @@ findvar(char *p, int user, char **header)
|
||||
*/
|
||||
rflen = strlen(v->alias) + strlen(hp) + 2;
|
||||
realfmt = malloc(rflen);
|
||||
if (realfmt == NULL)
|
||||
errx(1, "malloc failed");
|
||||
snprintf(realfmt, rflen, "%s=%s", v->alias, hp);
|
||||
parsefmt(realfmt, user);
|
||||
}
|
||||
|
||||
+14
-53
@@ -129,33 +129,25 @@ command(KINFO *k, VARENT *ve)
|
||||
v = ve->var;
|
||||
if (cflag) {
|
||||
/* If it is the last field, then don't pad */
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL) {
|
||||
if (k->ki_d.prefix)
|
||||
(void)printf("%s", k->ki_d.prefix);
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL)
|
||||
(void)printf("%s", k->ki_p->ki_comm);
|
||||
} else
|
||||
else
|
||||
(void)printf("%-*s", v->width, k->ki_p->ki_comm);
|
||||
return;
|
||||
}
|
||||
if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
|
||||
errx(1, "malloc failed");
|
||||
strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
|
||||
if (k->ki_env) {
|
||||
if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1)) == NULL)
|
||||
errx(1, "malloc failed");
|
||||
strvis(vis_env, k->ki_env, VIS_TAB | VIS_NL | VIS_NOSLASH);
|
||||
} else
|
||||
vis_env = NULL;
|
||||
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL) {
|
||||
/* last field */
|
||||
|
||||
if (k->ki_env) {
|
||||
if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1))
|
||||
== NULL)
|
||||
errx(1, "malloc failed");
|
||||
strvis(vis_env, k->ki_env,
|
||||
VIS_TAB | VIS_NL | VIS_NOSLASH);
|
||||
} else
|
||||
vis_env = NULL;
|
||||
|
||||
if (termwidth == UNLIMITED) {
|
||||
if (k->ki_d.prefix)
|
||||
(void)printf("%s", k->ki_d.prefix);
|
||||
if (vis_env)
|
||||
(void)printf("%s ", vis_env);
|
||||
(void)printf("%s", vis_args);
|
||||
@@ -163,9 +155,6 @@ command(KINFO *k, VARENT *ve)
|
||||
left = termwidth - (totwidth - v->width);
|
||||
if (left < 1) /* already wrapped, just use std width */
|
||||
left = v->width;
|
||||
if ((cp = k->ki_d.prefix) != NULL)
|
||||
while (--left >= 0 && *cp)
|
||||
(void)putchar(*cp++);
|
||||
if ((cp = vis_env) != NULL) {
|
||||
while (--left >= 0 && *cp)
|
||||
(void)putchar(*cp++);
|
||||
@@ -175,34 +164,24 @@ command(KINFO *k, VARENT *ve)
|
||||
for (cp = vis_args; --left >= 0 && *cp != '\0';)
|
||||
(void)putchar(*cp++);
|
||||
}
|
||||
if (vis_env != NULL)
|
||||
free(vis_env);
|
||||
} else
|
||||
/* ki_d.prefix & ki_env aren't shown for interim fields */
|
||||
/* XXX env? */
|
||||
(void)printf("%-*.*s", v->width, v->width, vis_args);
|
||||
free(vis_args);
|
||||
if (vis_env != NULL)
|
||||
free(vis_env);
|
||||
}
|
||||
|
||||
void
|
||||
ucomm(KINFO *k, VARENT *ve)
|
||||
{
|
||||
char tmpbuff[COMMLEN + OCOMMLEN + 2];
|
||||
VAR *v;
|
||||
|
||||
v = ve->var;
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL) { /* last field, don't pad */
|
||||
if (k->ki_d.prefix)
|
||||
(void)printf("%s", k->ki_d.prefix);
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL) /* last field, don't pad */
|
||||
(void)printf("%s", k->ki_p->ki_comm);
|
||||
} else {
|
||||
bzero(tmpbuff, sizeof(tmpbuff));
|
||||
if (showthreads && k->ki_p->ki_numthreads > 1)
|
||||
sprintf(tmpbuff, "%s/%s", k->ki_p->ki_comm,
|
||||
k->ki_p->ki_ocomm);
|
||||
else
|
||||
sprintf(tmpbuff, "%s", k->ki_p->ki_comm);
|
||||
(void)printf("%-*s", v->width, tmpbuff);
|
||||
}
|
||||
else
|
||||
(void)printf("%-*s", v->width, k->ki_p->ki_comm);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -580,10 +559,6 @@ elapsed(KINFO *k, VARENT *ve)
|
||||
char obuff[128];
|
||||
|
||||
v = ve->var;
|
||||
if (!k->ki_valid) {
|
||||
(void)printf("%-*s", v->width, "-");
|
||||
return;
|
||||
}
|
||||
val = now - k->ki_p->ki_start.tv_sec;
|
||||
days = val / (24 * 60 * 60);
|
||||
val %= 24 * 60 * 60;
|
||||
@@ -829,20 +804,6 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
s_comm(KINFO *k)
|
||||
{
|
||||
char tmpbuff[COMMLEN + OCOMMLEN + 2];
|
||||
|
||||
bzero(tmpbuff, sizeof(tmpbuff));
|
||||
if (showthreads && k->ki_p->ki_numthreads > 1)
|
||||
sprintf(tmpbuff, "%s/%s", k->ki_p->ki_comm,
|
||||
k->ki_p->ki_ocomm);
|
||||
else
|
||||
sprintf(tmpbuff, "%s", k->ki_p->ki_comm);
|
||||
return (strlen(tmpbuff));
|
||||
}
|
||||
|
||||
int
|
||||
s_label(KINFO *k)
|
||||
{
|
||||
|
||||
+2
-11
@@ -29,7 +29,7 @@
|
||||
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 16, 2009
|
||||
.Dd August 21, 2006
|
||||
.Dt PS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -37,7 +37,7 @@
|
||||
.Nd process status
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl aCcdefHhjlmrSTuvwXxZ
|
||||
.Op Fl aCcefHhjlmrSTuvwXxZ
|
||||
.Op Fl O Ar fmt | Fl o Ar fmt
|
||||
.Op Fl G Ar gid Ns Op , Ns Ar gid Ns Ar ...
|
||||
.Op Fl M Ar core
|
||||
@@ -122,15 +122,6 @@ CPU calculation that ignores
|
||||
.Dq resident
|
||||
time (this normally has
|
||||
no effect).
|
||||
.It Fl d
|
||||
Arrange processes into descendancy order and prefix each command with
|
||||
indentation text showing sibling and parent/child relationships.
|
||||
If either of the
|
||||
.Fl m
|
||||
and
|
||||
.Fl r
|
||||
options are also used, they control how sibling processes are sorted
|
||||
relative to eachother.
|
||||
.It Fl e
|
||||
Display the environment as well.
|
||||
.It Fl f
|
||||
|
||||
+5
-132
@@ -100,7 +100,6 @@ int rawcpu; /* -C */
|
||||
int sumrusage; /* -S */
|
||||
int termwidth; /* Width of the screen (0 == infinity). */
|
||||
int totwidth; /* Calculated-width of requested variables. */
|
||||
int showthreads; /* will threads be shown? */
|
||||
|
||||
struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist);
|
||||
|
||||
@@ -138,7 +137,6 @@ static int addelem_pid(struct listinfo *, const char *);
|
||||
static int addelem_tty(struct listinfo *, const char *);
|
||||
static int addelem_uid(struct listinfo *, const char *);
|
||||
static void add_list(struct listinfo *, const char *);
|
||||
static void descendant_sort(KINFO *, int);
|
||||
static void dynsizevars(KINFO *);
|
||||
static void *expand_list(struct listinfo *);
|
||||
static const char *
|
||||
@@ -164,7 +162,7 @@ static char vfmt[] = "pid,state,time,sl,re,pagein,vsz,rss,lim,tsiz,"
|
||||
"%cpu,%mem,command";
|
||||
static char Zfmt[] = "label";
|
||||
|
||||
#define PS_ARGS "AaCcde" OPT_LAZY_f "G:gHhjLlM:mN:O:o:p:rSTt:U:uvwXxZ"
|
||||
#define PS_ARGS "AaCce" OPT_LAZY_f "G:gHhjLlM:mN:O:o:p:rSTt:U:uvwXxZ"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
@@ -178,8 +176,8 @@ main(int argc, char *argv[])
|
||||
const char *nlistf, *memf;
|
||||
char *cols;
|
||||
int all, ch, elem, flag, _fmt, i, lineno;
|
||||
int descendancy, nentries, nkept, nselectors;
|
||||
int prtheader, wflag, what, xkeep, xkeep_implied;
|
||||
int nentries, nkept, nselectors;
|
||||
int prtheader, showthreads, wflag, what, xkeep, xkeep_implied;
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
|
||||
(void) setlocale(LC_ALL, "");
|
||||
@@ -202,7 +200,7 @@ main(int argc, char *argv[])
|
||||
if (argc > 1)
|
||||
argv[1] = kludge_oldps_options(PS_ARGS, argv[1], argv[2]);
|
||||
|
||||
all = descendancy = _fmt = nselectors = optfatal = 0;
|
||||
all = _fmt = nselectors = optfatal = 0;
|
||||
prtheader = showthreads = wflag = xkeep_implied = 0;
|
||||
xkeep = -1; /* Neither -x nor -X. */
|
||||
init_list(&gidlist, addelem_gid, sizeof(gid_t), "group");
|
||||
@@ -234,9 +232,6 @@ main(int argc, char *argv[])
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
descendancy = 1;
|
||||
break;
|
||||
case 'e': /* XXX set ufmt */
|
||||
needenv = 1;
|
||||
break;
|
||||
@@ -579,8 +574,6 @@ main(int argc, char *argv[])
|
||||
keepit:
|
||||
next_KINFO = &kinfo[nkept];
|
||||
next_KINFO->ki_p = kp;
|
||||
next_KINFO->ki_d.level = 0;
|
||||
next_KINFO->ki_d.prefix = NULL;
|
||||
next_KINFO->ki_pcpu = getpcpu(next_KINFO);
|
||||
if (sortby == SORTMEM)
|
||||
next_KINFO->ki_memsize = kp->ki_tsize +
|
||||
@@ -605,13 +598,6 @@ main(int argc, char *argv[])
|
||||
* sort proc list
|
||||
*/
|
||||
qsort(kinfo, nkept, sizeof(KINFO), pscomp);
|
||||
|
||||
/*
|
||||
* We want things in descendant order
|
||||
*/
|
||||
if (descendancy)
|
||||
descendant_sort(kinfo, nkept);
|
||||
|
||||
/*
|
||||
* For each process, call each variable output function.
|
||||
*/
|
||||
@@ -635,9 +621,6 @@ main(int argc, char *argv[])
|
||||
free_list(&sesslist);
|
||||
free_list(&ttylist);
|
||||
free_list(&uidlist);
|
||||
for (i = 0; i < nkept; i++)
|
||||
free(kinfo[i].ki_d.prefix);
|
||||
free(kinfo);
|
||||
|
||||
exit(eval);
|
||||
}
|
||||
@@ -906,116 +889,6 @@ add_list(struct listinfo *inf, const char *argp)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
descendant_sort(KINFO *ki, int items)
|
||||
{
|
||||
int dst, lvl, maxlvl, n, ndst, nsrc, siblings, src;
|
||||
unsigned char *path;
|
||||
KINFO kn;
|
||||
|
||||
/*
|
||||
* First, sort the entries by descendancy, tracking the descendancy
|
||||
* depth in the ki_d.level field.
|
||||
*/
|
||||
src = 0;
|
||||
maxlvl = 0;
|
||||
while (src < items) {
|
||||
if (ki[src].ki_d.level) {
|
||||
src++;
|
||||
continue;
|
||||
}
|
||||
for (nsrc = 1; src + nsrc < items; nsrc++)
|
||||
if (!ki[src + nsrc].ki_d.level)
|
||||
break;
|
||||
|
||||
for (dst = 0; dst < items; dst++) {
|
||||
if (ki[dst].ki_p->ki_pid == ki[src].ki_p->ki_pid)
|
||||
continue;
|
||||
if (ki[dst].ki_p->ki_pid == ki[src].ki_p->ki_ppid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst == items) {
|
||||
src += nsrc;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ndst = 1; dst + ndst < items; ndst++)
|
||||
if (ki[dst + ndst].ki_d.level <= ki[dst].ki_d.level)
|
||||
break;
|
||||
|
||||
for (n = src; n < src + nsrc; n++) {
|
||||
ki[n].ki_d.level += ki[dst].ki_d.level + 1;
|
||||
if (maxlvl < ki[n].ki_d.level)
|
||||
maxlvl = ki[n].ki_d.level;
|
||||
}
|
||||
|
||||
while (nsrc) {
|
||||
if (src < dst) {
|
||||
kn = ki[src];
|
||||
memmove(ki + src, ki + src + 1,
|
||||
(dst - src + ndst - 1) * sizeof *ki);
|
||||
ki[dst + ndst - 1] = kn;
|
||||
nsrc--;
|
||||
dst--;
|
||||
ndst++;
|
||||
} else if (src != dst + ndst) {
|
||||
kn = ki[src];
|
||||
memmove(ki + dst + ndst + 1, ki + dst + ndst,
|
||||
(src - dst - ndst) * sizeof *ki);
|
||||
ki[dst + ndst] = kn;
|
||||
ndst++;
|
||||
nsrc--;
|
||||
src++;
|
||||
} else {
|
||||
ndst += nsrc;
|
||||
src += nsrc;
|
||||
nsrc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now populate ki_d.prefix (instead of ki_d.level) with the command
|
||||
* prefix used to show descendancies.
|
||||
*/
|
||||
path = malloc((maxlvl + 7) / 8);
|
||||
memset(path, '\0', (maxlvl + 7) / 8);
|
||||
for (src = 0; src < items; src++) {
|
||||
if ((lvl = ki[src].ki_d.level) == 0) {
|
||||
ki[src].ki_d.prefix = NULL;
|
||||
continue;
|
||||
}
|
||||
if ((ki[src].ki_d.prefix = malloc(lvl * 2 + 1)) == NULL)
|
||||
errx(1, "malloc failed");
|
||||
for (n = 0; n < lvl - 2; n++) {
|
||||
ki[src].ki_d.prefix[n * 2] =
|
||||
path[n / 8] & 1 << (n % 8) ? '|' : ' ';
|
||||
ki[src].ki_d.prefix[n * 2 + 1] = ' ';
|
||||
|
||||
}
|
||||
if (n == lvl - 2) {
|
||||
/* Have I any more siblings? */
|
||||
for (siblings = 0, dst = src + 1; dst < items; dst++) {
|
||||
if (ki[dst].ki_d.level > lvl)
|
||||
continue;
|
||||
if (ki[dst].ki_d.level == lvl)
|
||||
siblings = 1;
|
||||
break;
|
||||
}
|
||||
if (siblings)
|
||||
path[n / 8] |= 1 << (n % 8);
|
||||
else
|
||||
path[n / 8] &= ~(1 << (n % 8));
|
||||
ki[src].ki_d.prefix[n * 2] = siblings ? '|' : '`';
|
||||
ki[src].ki_d.prefix[n * 2 + 1] = '-';
|
||||
n++;
|
||||
}
|
||||
strcpy(ki[src].ki_d.prefix + n * 2, "- ");
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
|
||||
static void *
|
||||
expand_list(struct listinfo *inf)
|
||||
{
|
||||
@@ -1332,7 +1205,7 @@ check_procfs(void)
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
#define SINGLE_OPTS "[-aCcde" OPT_LAZY_f "HhjlmrSTuvwXxZ]"
|
||||
#define SINGLE_OPTS "[-aCce" OPT_LAZY_f "HhjlmrSTuvwXxZ]"
|
||||
|
||||
(void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
||||
"usage: ps " SINGLE_OPTS " [-O fmt | -o fmt] [-G gid[,gid...]]",
|
||||
|
||||
@@ -42,10 +42,6 @@ typedef struct kinfo {
|
||||
int ki_valid; /* 1 => uarea stuff valid */
|
||||
double ki_pcpu; /* calculated in main() */
|
||||
segsz_t ki_memsize; /* calculated in main() */
|
||||
union {
|
||||
int level; /* used in decendant_sort() */
|
||||
char *prefix; /* calculated in decendant_sort() */
|
||||
} ki_d;
|
||||
} KINFO;
|
||||
|
||||
/* Variables. */
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= pwait
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -1,78 +0,0 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2004-2009, Jilles Tjoelker
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with
|
||||
.\" or without modification, are permitted provided that the
|
||||
.\" following conditions are met:
|
||||
.\"
|
||||
.\" 1. Redistributions of source code must retain the above
|
||||
.\" copyright notice, this list of conditions and the
|
||||
.\" following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the
|
||||
.\" above copyright notice, this list of conditions and
|
||||
.\" the following disclaimer in the documentation and/or
|
||||
.\" other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
.\" CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
.\" WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
.\" PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
.\" COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
.\" CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
.\" USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
.\" OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 1, 2009
|
||||
.Os
|
||||
.Dt PWAIT 1
|
||||
.Sh NAME
|
||||
.Nm pwait
|
||||
.Nd wait for processes to terminate
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl v
|
||||
.Ar pid
|
||||
\&...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility will wait until each of the given processes has terminated.
|
||||
.Pp
|
||||
The following option is available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl v
|
||||
Print the exit status when each process terminates.
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility returns 0 on success, and >0 if an error occurs.
|
||||
.Pp
|
||||
Invalid pids elicit a warning message but are otherwise ignored.
|
||||
.Sh SEE ALSO
|
||||
.Xr kill 1 ,
|
||||
.Xr pkill 1 ,
|
||||
.Xr ps 1 ,
|
||||
.Xr wait 1 ,
|
||||
.Xr kqueue 2
|
||||
.Sh NOTES
|
||||
.Nm
|
||||
is not a substitute for the
|
||||
.Xr wait 1
|
||||
builtin
|
||||
as it will not clean up any zombies or state in the parent process.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command first appeared in SunOS 5.8.
|
||||
@@ -1,145 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2009, Jilles Tjoelker
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with
|
||||
* or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the
|
||||
* above copyright notice, this list of conditions and
|
||||
* the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: pwait [-v] pid ...\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
/*
|
||||
* pwait - wait for processes to terminate
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int kq;
|
||||
struct kevent *e;
|
||||
int verbose = 0;
|
||||
int opt, nleft, n, i, duplicate, status;
|
||||
long pid;
|
||||
char *s, *end;
|
||||
|
||||
while ((opt = getopt(argc, argv, "v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
kq = kqueue();
|
||||
if (kq == -1)
|
||||
err(1, "kqueue");
|
||||
|
||||
e = malloc(argc * sizeof(struct kevent));
|
||||
if (e == NULL)
|
||||
err(1, "malloc");
|
||||
nleft = 0;
|
||||
for (n = 0; n < argc; n++) {
|
||||
s = argv[n];
|
||||
if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */
|
||||
s += 6;
|
||||
errno = 0;
|
||||
pid = strtol(s, &end, 10);
|
||||
if (pid < 0 || *end != '\0' || errno != 0) {
|
||||
warnx("%s: bad process id", s);
|
||||
continue;
|
||||
}
|
||||
duplicate = 0;
|
||||
for (i = 0; i < nleft; i++)
|
||||
if (e[i].ident == (uintptr_t)pid)
|
||||
duplicate = 1;
|
||||
if (!duplicate) {
|
||||
EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT,
|
||||
0, NULL);
|
||||
if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
|
||||
warn("%ld", pid);
|
||||
else
|
||||
nleft++;
|
||||
}
|
||||
}
|
||||
|
||||
while (nleft > 0) {
|
||||
n = kevent(kq, NULL, 0, e, nleft, NULL);
|
||||
if (n == -1)
|
||||
err(1, "kevent");
|
||||
if (verbose)
|
||||
for (i = 0; i < n; i++) {
|
||||
status = e[i].data;
|
||||
if (WIFEXITED(status))
|
||||
printf("%ld: exited with status %d.\n",
|
||||
(long)e[i].ident,
|
||||
WEXITSTATUS(status));
|
||||
else if (WIFSIGNALED(status))
|
||||
printf("%ld: killed by signal %d.\n",
|
||||
(long)e[i].ident,
|
||||
WTERMSIG(status));
|
||||
else
|
||||
printf("%ld: terminated.\n",
|
||||
(long)e[i].ident);
|
||||
}
|
||||
nleft -= n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+3
-3
@@ -231,7 +231,7 @@ rm_tree(char **argv)
|
||||
else if (!uid &&
|
||||
(p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
|
||||
!(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
|
||||
lchflags(p->fts_accpath,
|
||||
chflags(p->fts_accpath,
|
||||
p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
|
||||
goto err;
|
||||
continue;
|
||||
@@ -250,7 +250,7 @@ rm_tree(char **argv)
|
||||
if (!uid &&
|
||||
(p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
|
||||
!(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
|
||||
rval = lchflags(p->fts_accpath,
|
||||
rval = chflags(p->fts_accpath,
|
||||
p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
|
||||
if (rval == 0) {
|
||||
/*
|
||||
@@ -350,7 +350,7 @@ rm_file(char **argv)
|
||||
if (!uid && !S_ISWHT(sb.st_mode) &&
|
||||
(sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
|
||||
!(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
|
||||
rval = lchflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
|
||||
rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
|
||||
if (rval == 0) {
|
||||
if (S_ISWHT(sb.st_mode))
|
||||
rval = undelete(f);
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ LFLAGS= -8 # 8-bit lex scanner for arithmetic
|
||||
CFLAGS+=-DSHELL -I. -I${.CURDIR}
|
||||
# for debug:
|
||||
# CFLAGS+= -g -DDEBUG=2
|
||||
WARNS?= 2
|
||||
WARNS?= 3
|
||||
WFORMAT=0
|
||||
|
||||
.PATH: ${.CURDIR}/bltin \
|
||||
|
||||
+3
-23
@@ -51,13 +51,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
int yylex(void);
|
||||
|
||||
struct varname
|
||||
{
|
||||
struct varname *next;
|
||||
char name[1];
|
||||
};
|
||||
static struct varname *varnames;
|
||||
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max) \
|
||||
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
||||
@@ -87,14 +80,11 @@ static struct varname *varnames;
|
||||
* If variable doesn't exist, we should initialize
|
||||
* it to zero.
|
||||
*/
|
||||
struct varname *temp;
|
||||
char *temp;
|
||||
if (lookupvar(yytext) == NULL)
|
||||
setvarsafe(yytext, "0", 0);
|
||||
temp = ckmalloc(sizeof(struct varname) +
|
||||
strlen(yytext));
|
||||
temp->next = varnames;
|
||||
varnames = temp;
|
||||
yylval.s_value = strcpy(temp->name, yytext);
|
||||
temp = (char *)ckmalloc(strlen(yytext) + 1);
|
||||
yylval.s_value = strcpy(temp, yytext);
|
||||
|
||||
return ARITH_VAR;
|
||||
}
|
||||
@@ -140,15 +130,5 @@ static struct varname *varnames;
|
||||
void
|
||||
arith_lex_reset(void)
|
||||
{
|
||||
struct varname *name, *next;
|
||||
|
||||
YY_NEW_FILE;
|
||||
|
||||
name = varnames;
|
||||
while (name != NULL) {
|
||||
next = name->next;
|
||||
ckfree(name);
|
||||
name = next;
|
||||
}
|
||||
varnames = NULL;
|
||||
}
|
||||
+2
-5
@@ -773,7 +773,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
INTOFF;
|
||||
savelocalvars = localvars;
|
||||
localvars = NULL;
|
||||
reffunc(cmdentry.u.func);
|
||||
INTON;
|
||||
if (setjmp(jmploc.loc)) {
|
||||
if (exception == EXSHELLPROC)
|
||||
@@ -782,7 +781,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
freeparam(&shellparam);
|
||||
shellparam = saveparam;
|
||||
}
|
||||
unreffunc(cmdentry.u.func);
|
||||
poplocalvars();
|
||||
localvars = savelocalvars;
|
||||
handler = savehandler;
|
||||
@@ -794,12 +792,11 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
mklocal(sp->text);
|
||||
funcnest++;
|
||||
if (flags & EV_TESTED)
|
||||
evaltree(getfuncnode(cmdentry.u.func), EV_TESTED);
|
||||
evaltree(cmdentry.u.func, EV_TESTED);
|
||||
else
|
||||
evaltree(getfuncnode(cmdentry.u.func), 0);
|
||||
evaltree(cmdentry.u.func, 0);
|
||||
funcnest--;
|
||||
INTOFF;
|
||||
unreffunc(cmdentry.u.func);
|
||||
poplocalvars();
|
||||
localvars = savelocalvars;
|
||||
freeparam(&shellparam);
|
||||
|
||||
+4
-4
@@ -285,7 +285,7 @@ printentry(struct tblentry *cmdp, int verbose)
|
||||
out1fmt("function %s", cmdp->cmdname);
|
||||
if (verbose) {
|
||||
INTOFF;
|
||||
name = commandtext(getfuncnode(cmdp->param.func));
|
||||
name = commandtext(cmdp->param.func);
|
||||
out1c(' ');
|
||||
out1str(name);
|
||||
ckfree(name);
|
||||
@@ -582,7 +582,7 @@ deletefuncs(void)
|
||||
while ((cmdp = *pp) != NULL) {
|
||||
if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
*pp = cmdp->next;
|
||||
unreffunc(cmdp->param.func);
|
||||
freefunc(cmdp->param.func);
|
||||
ckfree(cmdp);
|
||||
} else {
|
||||
pp = &cmdp->next;
|
||||
@@ -669,7 +669,7 @@ addcmdentry(char *name, struct cmdentry *entry)
|
||||
INTOFF;
|
||||
cmdp = cmdlookup(name, 1);
|
||||
if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
unreffunc(cmdp->param.func);
|
||||
freefunc(cmdp->param.func);
|
||||
}
|
||||
cmdp->cmdtype = entry->cmdtype;
|
||||
cmdp->param = entry->u;
|
||||
@@ -704,7 +704,7 @@ unsetfunc(char *name)
|
||||
struct tblentry *cmdp;
|
||||
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
|
||||
unreffunc(cmdp->param.func);
|
||||
freefunc(cmdp->param.func);
|
||||
delete_cmd_entry();
|
||||
return (0);
|
||||
}
|
||||
|
||||
+1
-2
@@ -46,12 +46,11 @@ enum {
|
||||
TYPECMD_TYPE /* type */
|
||||
};
|
||||
|
||||
union node;
|
||||
struct cmdentry {
|
||||
int cmdtype;
|
||||
union param {
|
||||
int index;
|
||||
struct funcdef *func;
|
||||
union node *func;
|
||||
} u;
|
||||
int special;
|
||||
};
|
||||
|
||||
+2
-5
@@ -248,11 +248,8 @@ output(char *file)
|
||||
fputs("\tstruct nodelist *next;\n", hfile);
|
||||
fputs("\tunion node *n;\n", hfile);
|
||||
fputs("};\n\n\n", hfile);
|
||||
fputs("struct funcdef;\n", hfile);
|
||||
fputs("struct funcdef *copyfunc(union node *);\n", hfile);
|
||||
fputs("union node *getfuncnode(struct funcdef *);\n", hfile);
|
||||
fputs("void reffunc(struct funcdef *);\n", hfile);
|
||||
fputs("void unreffunc(struct funcdef *);\n", hfile);
|
||||
fputs("union node *copyfunc(union node *);\n", hfile);
|
||||
fputs("void freefunc(union node *);\n", hfile);
|
||||
|
||||
fputs(writer, cfile);
|
||||
while (fgets(line, sizeof line, patfile) != NULL) {
|
||||
|
||||
+9
-37
@@ -35,7 +35,6 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
/*
|
||||
* Routine for dealing with parsed shell commands.
|
||||
*/
|
||||
@@ -61,40 +60,25 @@ STATIC struct nodelist *copynodelist(struct nodelist *);
|
||||
STATIC char *nodesavestr(char *);
|
||||
|
||||
|
||||
struct funcdef {
|
||||
unsigned int refcount;
|
||||
union node n;
|
||||
};
|
||||
|
||||
/*
|
||||
* Make a copy of a parse tree.
|
||||
*/
|
||||
|
||||
struct funcdef *
|
||||
union node *
|
||||
copyfunc(union node *n)
|
||||
{
|
||||
struct funcdef *fn;
|
||||
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
funcblocksize = offsetof(struct funcdef, n);
|
||||
funcblocksize = 0;
|
||||
funcstringsize = 0;
|
||||
calcsize(n);
|
||||
fn = ckmalloc(funcblocksize + funcstringsize);
|
||||
fn->refcount = 1;
|
||||
funcblock = (char *)fn + offsetof(struct funcdef, n);
|
||||
funcstring = (char *)fn + funcblocksize;
|
||||
copynode(n);
|
||||
return fn;
|
||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
||||
funcstring = (char *)funcblock + funcblocksize;
|
||||
return copynode(n);
|
||||
}
|
||||
|
||||
|
||||
union node *
|
||||
getfuncnode(struct funcdef *fn)
|
||||
{
|
||||
return fn == NULL ? NULL : &fn->n;
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
calcsize(union node *n)
|
||||
@@ -160,26 +144,14 @@ nodesavestr(char *s)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
reffunc(struct funcdef *fn)
|
||||
{
|
||||
if (fn)
|
||||
fn->refcount++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decrement the reference count of a function definition, freeing it
|
||||
* if it falls to 0.
|
||||
* Free a parse tree.
|
||||
*/
|
||||
|
||||
void
|
||||
unreffunc(struct funcdef *fn)
|
||||
freefunc(union node *n)
|
||||
{
|
||||
if (fn) {
|
||||
fn->refcount--;
|
||||
if (fn->refcount > 0)
|
||||
return;
|
||||
ckfree(fn);
|
||||
}
|
||||
if (n)
|
||||
ckfree(n);
|
||||
}
|
||||
@@ -250,7 +250,6 @@ pipeline(void)
|
||||
int negate;
|
||||
|
||||
negate = 0;
|
||||
checkkwd = 2;
|
||||
TRACE(("pipeline: entered\n"));
|
||||
while (readtoken() == TNOT)
|
||||
negate = !negate;
|
||||
|
||||
+2
-6
@@ -375,10 +375,6 @@ introduces a comment if used at the beginning of a word.
|
||||
The word starting with
|
||||
.Ql #
|
||||
and the rest of the line are ignored.
|
||||
.Pp
|
||||
.Tn ASCII
|
||||
.Dv NUL
|
||||
characters (character code 0) are not allowed in shell input.
|
||||
.Ss Quoting
|
||||
Quoting is used to remove the special meaning of certain characters
|
||||
or words to the shell, such as operators, whitespace, keywords,
|
||||
@@ -856,7 +852,7 @@ command is:
|
||||
If
|
||||
.Ic in
|
||||
and the following words are omitted,
|
||||
.Ic in Li \&"$@\&"
|
||||
.Ic in Li $@
|
||||
is used instead.
|
||||
The words are expanded, and then the list is executed
|
||||
repeatedly with the variable set to each word in turn.
|
||||
@@ -1071,7 +1067,7 @@ and
|
||||
is
|
||||
.Dq Li "def ghi" ,
|
||||
then
|
||||
.Li \&"$@\&"
|
||||
.Dq Li $@
|
||||
expands to
|
||||
the two arguments:
|
||||
.Bd -literal -offset indent
|
||||
|
||||
@@ -6,5 +6,3 @@ OPENSOLARIS_SYS_DISTDIR= ${.CURDIR}/../../../sys/cddl/contrib/opensolaris
|
||||
IGNORE_PRAGMA= YES
|
||||
|
||||
CFLAGS+= -DNEED_SOLARIS_BOOLEAN
|
||||
|
||||
CSTD?= gnu89
|
||||
@@ -1,36 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _OPENSOLARIS_LIBSHARE_H_
|
||||
#define _OPENSOLARIS_LIBSHARE_H_
|
||||
|
||||
#define SA_OK 0
|
||||
|
||||
#define SA_INIT_CONTROL_API 0
|
||||
|
||||
#endif /* !_OPENSOLARIS_LIBSHARE_H_ */
|
||||
@@ -9,8 +9,6 @@
|
||||
#define MNTTAB _PATH_DEVNULL
|
||||
#define MNT_LINE_MAX 1024
|
||||
|
||||
#define umount2(p, f) unmount(p, f)
|
||||
|
||||
struct mnttab {
|
||||
char *mnt_special;
|
||||
char *mnt_mountp;
|
||||
|
||||
@@ -94,7 +94,11 @@ int
|
||||
devid_get(int fd, ddi_devid_t *retdevid)
|
||||
{
|
||||
|
||||
return (ENOENT);
|
||||
if (ioctl(fd, DIOCGIDENT, retdevid->devid) == -1)
|
||||
return (errno);
|
||||
if (retdevid->devid[0] == '\0')
|
||||
return (ENOENT);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -37,8 +37,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *
|
||||
mntopt(char **p)
|
||||
|
||||
@@ -35,10 +35,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mount.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void
|
||||
build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
|
||||
@@ -87,7 +86,7 @@ zmount(const char *spec, const char *dir, int mflag, char *fstype,
|
||||
assert(optlen > 0);
|
||||
|
||||
optstr = strdup(optptr);
|
||||
assert(optstr != NULL);
|
||||
assert(optptr != NULL);
|
||||
|
||||
iov = NULL;
|
||||
iovlen = 0;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/zone.h>
|
||||
|
||||
zoneid_t
|
||||
int
|
||||
getzoneid(void)
|
||||
{
|
||||
size_t size;
|
||||
@@ -42,5 +42,5 @@ getzoneid(void)
|
||||
size = sizeof(jailid);
|
||||
if (sysctlbyname("security.jail.jailed", &jailid, &size, NULL, 0) == -1)
|
||||
assert(!"No security.jail.jailed sysctl!");
|
||||
return ((zoneid_t)jailid);
|
||||
return (jailid);
|
||||
}
|
||||
@@ -28,18 +28,13 @@ zdb \- ZFS debugger
|
||||
.fi
|
||||
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
.LP
|
||||
The \fBzdb\fR command is used by support engineers to diagnose failures and gather statistics. Since the \fBZFS\fR file system is always consistent on disk and is self-repairing, \fBzdb\fR should only be run under the direction by a support engineer.
|
||||
.sp
|
||||
.LP
|
||||
If no arguments are specified, \fBzdb\fR, performs basic consistency checks on the pool and associated datasets, and report any problems detected.
|
||||
.sp
|
||||
.LP
|
||||
Any options supported by this command are internal to Sun and subject to change at any time.
|
||||
.SH EXIT STATUS
|
||||
|
||||
.sp
|
||||
.LP
|
||||
The following exit values are returned:
|
||||
.sp
|
||||
@@ -76,9 +71,6 @@ Invalid command line options were specified.
|
||||
.RE
|
||||
|
||||
.SH ATTRIBUTES
|
||||
|
||||
.sp
|
||||
|
||||
.LP
|
||||
See \fBattributes\fR(5) for descriptions of the following attributes:
|
||||
.sp
|
||||
@@ -97,6 +89,5 @@ Interface StabilityUnstable
|
||||
.TE
|
||||
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
.LP
|
||||
\fBzfs\fR(1M), \fBzpool\fR(1M), \fBattributes\fR(5)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -233,26 +233,19 @@ typedef struct zil_rec_info {
|
||||
} zil_rec_info_t;
|
||||
|
||||
static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
||||
{ NULL, "Total " },
|
||||
{ zil_prt_rec_create, "TX_CREATE " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR " },
|
||||
{ zil_prt_rec_create, "TX_MKXATTR " },
|
||||
{ zil_prt_rec_create, "TX_SYMLINK " },
|
||||
{ zil_prt_rec_remove, "TX_REMOVE " },
|
||||
{ zil_prt_rec_remove, "TX_RMDIR " },
|
||||
{ zil_prt_rec_link, "TX_LINK " },
|
||||
{ zil_prt_rec_rename, "TX_RENAME " },
|
||||
{ zil_prt_rec_write, "TX_WRITE " },
|
||||
{ zil_prt_rec_truncate, "TX_TRUNCATE " },
|
||||
{ zil_prt_rec_setattr, "TX_SETATTR " },
|
||||
{ zil_prt_rec_acl, "TX_ACL_V0 " },
|
||||
{ zil_prt_rec_acl, "TX_ACL_ACL " },
|
||||
{ zil_prt_rec_create, "TX_CREATE_ACL " },
|
||||
{ zil_prt_rec_create, "TX_CREATE_ATTR " },
|
||||
{ zil_prt_rec_create, "TX_CREATE_ACL_ATTR " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR_ACL " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR_ATTR " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR_ACL_ATTR " },
|
||||
{ NULL, "Total " },
|
||||
{ zil_prt_rec_create, "TX_CREATE " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR " },
|
||||
{ zil_prt_rec_create, "TX_MKXATTR " },
|
||||
{ zil_prt_rec_create, "TX_SYMLINK " },
|
||||
{ zil_prt_rec_remove, "TX_REMOVE " },
|
||||
{ zil_prt_rec_remove, "TX_RMDIR " },
|
||||
{ zil_prt_rec_link, "TX_LINK " },
|
||||
{ zil_prt_rec_rename, "TX_RENAME " },
|
||||
{ zil_prt_rec_write, "TX_WRITE " },
|
||||
{ zil_prt_rec_truncate, "TX_TRUNCATE" },
|
||||
{ zil_prt_rec_setattr, "TX_SETATTR " },
|
||||
{ zil_prt_rec_acl, "TX_ACL " },
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -262,14 +255,12 @@ print_log_record(zilog_t *zilog, lr_t *lr, void *arg, uint64_t claim_txg)
|
||||
int txtype;
|
||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
|
||||
/* reduce size of txtype to strip off TX_CI bit */
|
||||
txtype = lr->lrc_txtype;
|
||||
|
||||
ASSERT(txtype != 0 && (uint_t)txtype < TX_MAX_TYPE);
|
||||
ASSERT(lr->lrc_txg);
|
||||
|
||||
(void) printf("\t\t%s%s len %6llu, txg %llu, seq %llu\n",
|
||||
(lr->lrc_txtype & TX_CI) ? "CI-" : "",
|
||||
(void) printf("\t\t%s len %6llu, txg %llu, seq %llu\n",
|
||||
zil_rec_info[txtype].zri_name,
|
||||
(u_longlong_t)lr->lrc_reclen,
|
||||
(u_longlong_t)lr->lrc_txg,
|
||||
|
||||
+367
-1154
File diff suppressed because it is too large.
Load diff
@@ -19,10 +19,12 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <libintl.h>
|
||||
#include <libuutil.h>
|
||||
#include <stddef.h>
|
||||
@@ -54,43 +56,28 @@ typedef struct zfs_node {
|
||||
|
||||
typedef struct callback_data {
|
||||
uu_avl_t *cb_avl;
|
||||
int cb_flags;
|
||||
int cb_recurse;
|
||||
zfs_type_t cb_types;
|
||||
zfs_sort_column_t *cb_sortcol;
|
||||
zprop_list_t **cb_proplist;
|
||||
zfs_proplist_t **cb_proplist;
|
||||
} callback_data_t;
|
||||
|
||||
uu_avl_pool_t *avl_pool;
|
||||
|
||||
/*
|
||||
* Include snaps if they were requested or if this a zfs list where types
|
||||
* were not specified and the "listsnapshots" property is set on this pool.
|
||||
*/
|
||||
static int
|
||||
zfs_include_snapshots(zfs_handle_t *zhp, callback_data_t *cb)
|
||||
{
|
||||
zpool_handle_t *zph;
|
||||
|
||||
if ((cb->cb_flags & ZFS_ITER_PROP_LISTSNAPS) == 0)
|
||||
return (cb->cb_types & ZFS_TYPE_SNAPSHOT);
|
||||
|
||||
zph = zfs_get_pool_handle(zhp);
|
||||
return (zpool_get_prop_int(zph, ZPOOL_PROP_LISTSNAPS, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
* Called for each dataset. If the object is of an appropriate type,
|
||||
* Called for each dataset. If the object the object is of an appropriate type,
|
||||
* add it to the avl tree and recurse over any children as necessary.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
zfs_callback(zfs_handle_t *zhp, void *data)
|
||||
{
|
||||
callback_data_t *cb = data;
|
||||
int dontclose = 0;
|
||||
int include_snaps = zfs_include_snapshots(zhp, cb);
|
||||
|
||||
if ((zfs_get_type(zhp) & cb->cb_types) ||
|
||||
((zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) && include_snaps)) {
|
||||
/*
|
||||
* If this object is of the appropriate type, add it to the AVL tree.
|
||||
*/
|
||||
if (zfs_get_type(zhp) & cb->cb_types) {
|
||||
uu_avl_index_t idx;
|
||||
zfs_node_t *node = safe_malloc(sizeof (zfs_node_t));
|
||||
|
||||
@@ -113,12 +100,10 @@ zfs_callback(zfs_handle_t *zhp, void *data)
|
||||
/*
|
||||
* Recurse if necessary.
|
||||
*/
|
||||
if (cb->cb_flags & ZFS_ITER_RECURSE) {
|
||||
if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
|
||||
(void) zfs_iter_filesystems(zhp, zfs_callback, data);
|
||||
if ((zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) && include_snaps)
|
||||
(void) zfs_iter_snapshots(zhp, zfs_callback, data);
|
||||
}
|
||||
if (cb->cb_recurse && (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM ||
|
||||
(zfs_get_type(zhp) == ZFS_TYPE_VOLUME && (cb->cb_types &
|
||||
ZFS_TYPE_SNAPSHOT))))
|
||||
(void) zfs_iter_children(zhp, zfs_callback, data);
|
||||
|
||||
if (!dontclose)
|
||||
zfs_close(zhp);
|
||||
@@ -133,7 +118,7 @@ zfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
|
||||
zfs_sort_column_t *col;
|
||||
zfs_prop_t prop;
|
||||
|
||||
if ((prop = zfs_name_to_prop(name)) == ZPROP_INVAL &&
|
||||
if ((prop = zfs_name_to_prop(name)) == ZFS_PROP_INVAL &&
|
||||
!zfs_prop_user(name))
|
||||
return (-1);
|
||||
|
||||
@@ -141,7 +126,7 @@ zfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
|
||||
|
||||
col->sc_prop = prop;
|
||||
col->sc_reverse = reverse;
|
||||
if (prop == ZPROP_INVAL) {
|
||||
if (prop == ZFS_PROP_INVAL) {
|
||||
col->sc_user_prop = safe_malloc(strlen(name) + 1);
|
||||
(void) strcpy(col->sc_user_prop, name);
|
||||
}
|
||||
@@ -258,7 +243,7 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
||||
* Otherwise, we compare 'lnum' and 'rnum'.
|
||||
*/
|
||||
lstr = rstr = NULL;
|
||||
if (psc->sc_prop == ZPROP_INVAL) {
|
||||
if (psc->sc_prop == ZFS_PROP_INVAL) {
|
||||
nvlist_t *luser, *ruser;
|
||||
nvlist_t *lval, *rval;
|
||||
|
||||
@@ -272,10 +257,10 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
||||
|
||||
if (lvalid)
|
||||
verify(nvlist_lookup_string(lval,
|
||||
ZPROP_VALUE, &lstr) == 0);
|
||||
ZFS_PROP_VALUE, &lstr) == 0);
|
||||
if (rvalid)
|
||||
verify(nvlist_lookup_string(rval,
|
||||
ZPROP_VALUE, &rstr) == 0);
|
||||
ZFS_PROP_VALUE, &rstr) == 0);
|
||||
|
||||
} else if (zfs_prop_is_string(psc->sc_prop)) {
|
||||
lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf,
|
||||
@@ -308,7 +293,7 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
||||
|
||||
if (lstr)
|
||||
ret = strcmp(lstr, rstr);
|
||||
else if (lnum < rnum)
|
||||
if (lnum < rnum)
|
||||
ret = -1;
|
||||
else if (lnum > rnum)
|
||||
ret = 1;
|
||||
@@ -324,9 +309,9 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
||||
}
|
||||
|
||||
int
|
||||
zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
||||
zfs_sort_column_t *sortcol, zprop_list_t **proplist,
|
||||
zfs_iter_f callback, void *data)
|
||||
zfs_for_each(int argc, char **argv, boolean_t recurse, zfs_type_t types,
|
||||
zfs_sort_column_t *sortcol, zfs_proplist_t **proplist, zfs_iter_f callback,
|
||||
void *data, boolean_t args_can_be_paths)
|
||||
{
|
||||
callback_data_t cb;
|
||||
int ret = 0;
|
||||
@@ -343,7 +328,7 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
||||
}
|
||||
|
||||
cb.cb_sortcol = sortcol;
|
||||
cb.cb_flags = flags;
|
||||
cb.cb_recurse = recurse;
|
||||
cb.cb_proplist = proplist;
|
||||
cb.cb_types = types;
|
||||
if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL) {
|
||||
@@ -356,7 +341,7 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
||||
/*
|
||||
* If given no arguments, iterate over all datasets.
|
||||
*/
|
||||
cb.cb_flags |= ZFS_ITER_RECURSE;
|
||||
cb.cb_recurse = 1;
|
||||
ret = zfs_iter_root(g_zfs, zfs_callback, &cb);
|
||||
} else {
|
||||
int i;
|
||||
@@ -369,14 +354,14 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
||||
* can take volumes as well.
|
||||
*/
|
||||
argtype = types;
|
||||
if (flags & ZFS_ITER_RECURSE) {
|
||||
if (recurse) {
|
||||
argtype |= ZFS_TYPE_FILESYSTEM;
|
||||
if (types & ZFS_TYPE_SNAPSHOT)
|
||||
argtype |= ZFS_TYPE_VOLUME;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (flags & ZFS_ITER_ARGS_CAN_BE_PATHS) {
|
||||
if (args_can_be_paths) {
|
||||
zhp = zfs_path_to_zhandle(g_zfs, argv[i],
|
||||
argtype);
|
||||
} else {
|
||||
|
||||
@@ -19,13 +19,15 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef ZFS_ITER_H
|
||||
#define ZFS_ITER_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -38,12 +40,8 @@ typedef struct zfs_sort_column {
|
||||
boolean_t sc_reverse;
|
||||
} zfs_sort_column_t;
|
||||
|
||||
#define ZFS_ITER_RECURSE (1 << 0)
|
||||
#define ZFS_ITER_ARGS_CAN_BE_PATHS (1 << 1)
|
||||
#define ZFS_ITER_PROP_LISTSNAPS (1 << 2)
|
||||
|
||||
int zfs_for_each(int, char **, int options, zfs_type_t,
|
||||
zfs_sort_column_t *, zprop_list_t **, zfs_iter_f, void *);
|
||||
int zfs_for_each(int, char **, boolean_t, zfs_type_t, zfs_sort_column_t *,
|
||||
zfs_proplist_t **, zfs_iter_f, void *, boolean_t);
|
||||
int zfs_add_sort_column(zfs_sort_column_t **, const char *, boolean_t);
|
||||
void zfs_free_sort_columns(zfs_sort_column_t *);
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,460 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <libzfs.h>
|
||||
|
||||
#undef verify /* both libzfs.h and zfs_context.h want to define this */
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <sys/dmu.h>
|
||||
#include <sys/dmu_objset.h>
|
||||
#include <sys/dnode.h>
|
||||
#include <sys/vdev_impl.h>
|
||||
|
||||
#include "zinject.h"
|
||||
|
||||
#include <assert.h>
|
||||
#define verify assert
|
||||
|
||||
extern void kernel_init(int);
|
||||
extern void kernel_fini(void);
|
||||
|
||||
static int debug;
|
||||
|
||||
static void
|
||||
ziprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!debug)
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
(void) vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a full path to a file, translate into a dataset name and a relative
|
||||
* path within the dataset. 'dataset' must be at least MAXNAMELEN characters,
|
||||
* and 'relpath' must be at least MAXPATHLEN characters. We also pass a stat64
|
||||
* buffer, which we need later to get the object ID.
|
||||
*/
|
||||
static int
|
||||
parse_pathname(const char *fullpath, char *dataset, char *relpath,
|
||||
struct stat64 *statbuf)
|
||||
{
|
||||
struct statfs sfs;
|
||||
const char *rel;
|
||||
|
||||
if (fullpath[0] != '/') {
|
||||
(void) fprintf(stderr, "invalid object '%s': must be full "
|
||||
"path\n", fullpath);
|
||||
usage();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (strlen(fullpath) >= MAXPATHLEN) {
|
||||
(void) fprintf(stderr, "invalid object; pathname too long\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stat64(fullpath, statbuf) != 0) {
|
||||
(void) fprintf(stderr, "cannot open '%s': %s\n",
|
||||
fullpath, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (statfs(fullpath, &sfs) == -1) {
|
||||
(void) fprintf(stderr, "cannot find mountpoint for '%s': %s\n",
|
||||
fullpath, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (strcmp(sfs.f_fstypename, MNTTYPE_ZFS) != 0) {
|
||||
(void) fprintf(stderr, "invalid path '%s': not a ZFS "
|
||||
"filesystem\n", fullpath);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (strncmp(fullpath, sfs.f_mntonname, strlen(sfs.f_mntonname)) != 0) {
|
||||
(void) fprintf(stderr, "invalid path '%s': mountpoint "
|
||||
"doesn't match path\n", fullpath);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
(void) strcpy(dataset, sfs.f_mntfromname);
|
||||
|
||||
rel = fullpath + strlen(sfs.f_mntonname);
|
||||
if (rel[0] == '/')
|
||||
rel++;
|
||||
(void) strcpy(relpath, rel);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert from a (dataset, path) pair into a (objset, object) pair. Note that
|
||||
* we grab the object number from the inode number, since looking this up via
|
||||
* libzpool is a real pain.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
object_from_path(const char *dataset, const char *path, struct stat64 *statbuf,
|
||||
zinject_record_t *record)
|
||||
{
|
||||
objset_t *os;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Before doing any libzpool operations, call sync() to ensure that the
|
||||
* on-disk state is consistent with the in-core state.
|
||||
*/
|
||||
sync();
|
||||
|
||||
if ((err = dmu_objset_open(dataset, DMU_OST_ZFS,
|
||||
DS_MODE_USER | DS_MODE_READONLY, &os)) != 0) {
|
||||
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
|
||||
dataset, strerror(err));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
record->zi_objset = dmu_objset_id(os);
|
||||
record->zi_object = statbuf->st_ino;
|
||||
|
||||
dmu_objset_close(os);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the real range based on the type, level, and range given.
|
||||
*/
|
||||
static int
|
||||
calculate_range(const char *dataset, err_type_t type, int level, char *range,
|
||||
zinject_record_t *record)
|
||||
{
|
||||
objset_t *os = NULL;
|
||||
dnode_t *dn = NULL;
|
||||
int err;
|
||||
int ret = -1;
|
||||
|
||||
/*
|
||||
* Determine the numeric range from the string.
|
||||
*/
|
||||
if (range == NULL) {
|
||||
/*
|
||||
* If range is unspecified, set the range to [0,-1], which
|
||||
* indicates that the whole object should be treated as an
|
||||
* error.
|
||||
*/
|
||||
record->zi_start = 0;
|
||||
record->zi_end = -1ULL;
|
||||
} else {
|
||||
char *end;
|
||||
|
||||
/* XXX add support for suffixes */
|
||||
record->zi_start = strtoull(range, &end, 10);
|
||||
|
||||
|
||||
if (*end == '\0')
|
||||
record->zi_end = record->zi_start + 1;
|
||||
else if (*end == ',')
|
||||
record->zi_end = strtoull(end + 1, &end, 10);
|
||||
|
||||
if (*end != '\0') {
|
||||
(void) fprintf(stderr, "invalid range '%s': must be "
|
||||
"a numeric range of the form 'start[,end]'\n",
|
||||
range);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TYPE_DATA:
|
||||
break;
|
||||
|
||||
case TYPE_DNODE:
|
||||
/*
|
||||
* If this is a request to inject faults into the dnode, then we
|
||||
* must translate the current (objset,object) pair into an
|
||||
* offset within the metadnode for the objset. Specifying any
|
||||
* kind of range with type 'dnode' is illegal.
|
||||
*/
|
||||
if (range != NULL) {
|
||||
(void) fprintf(stderr, "range cannot be specified when "
|
||||
"type is 'dnode'\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
record->zi_start = record->zi_object * sizeof (dnode_phys_t);
|
||||
record->zi_end = record->zi_start + sizeof (dnode_phys_t);
|
||||
record->zi_object = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the dnode associated with object, so we can calculate the block
|
||||
* size.
|
||||
*/
|
||||
if ((err = dmu_objset_open(dataset, DMU_OST_ANY,
|
||||
DS_MODE_USER | DS_MODE_READONLY, &os)) != 0) {
|
||||
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
|
||||
dataset, strerror(err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (record->zi_object == 0) {
|
||||
dn = os->os->os_meta_dnode;
|
||||
} else {
|
||||
err = dnode_hold(os->os, record->zi_object, FTAG, &dn);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr, "failed to hold dnode "
|
||||
"for object %llu\n",
|
||||
(u_longlong_t)record->zi_object);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ziprintf("data shift: %d\n", (int)dn->dn_datablkshift);
|
||||
ziprintf(" ind shift: %d\n", (int)dn->dn_indblkshift);
|
||||
|
||||
/*
|
||||
* Translate range into block IDs.
|
||||
*/
|
||||
if (record->zi_start != 0 || record->zi_end != -1ULL) {
|
||||
record->zi_start >>= dn->dn_datablkshift;
|
||||
record->zi_end >>= dn->dn_datablkshift;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check level, and then translate level 0 blkids into ranges
|
||||
* appropriate for level of indirection.
|
||||
*/
|
||||
record->zi_level = level;
|
||||
if (level > 0) {
|
||||
ziprintf("level 0 blkid range: [%llu, %llu]\n",
|
||||
record->zi_start, record->zi_end);
|
||||
|
||||
if (level >= dn->dn_nlevels) {
|
||||
(void) fprintf(stderr, "level %d exceeds max level "
|
||||
"of object (%d)\n", level, dn->dn_nlevels - 1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (record->zi_start != 0 || record->zi_end != 0) {
|
||||
int shift = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
|
||||
|
||||
for (; level > 0; level--) {
|
||||
record->zi_start >>= shift;
|
||||
record->zi_end >>= shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (dn) {
|
||||
if (dn != os->os->os_meta_dnode)
|
||||
dnode_rele(dn, FTAG);
|
||||
}
|
||||
if (os)
|
||||
dmu_objset_close(os);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
translate_record(err_type_t type, const char *object, const char *range,
|
||||
int level, zinject_record_t *record, char *poolname, char *dataset)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char *slash;
|
||||
struct stat64 statbuf;
|
||||
int ret = -1;
|
||||
|
||||
kernel_init(FREAD);
|
||||
|
||||
debug = (getenv("ZINJECT_DEBUG") != NULL);
|
||||
|
||||
ziprintf("translating: %s\n", object);
|
||||
|
||||
if (MOS_TYPE(type)) {
|
||||
/*
|
||||
* MOS objects are treated specially.
|
||||
*/
|
||||
switch (type) {
|
||||
case TYPE_MOS:
|
||||
record->zi_type = 0;
|
||||
break;
|
||||
case TYPE_MOSDIR:
|
||||
record->zi_type = DMU_OT_OBJECT_DIRECTORY;
|
||||
break;
|
||||
case TYPE_METASLAB:
|
||||
record->zi_type = DMU_OT_OBJECT_ARRAY;
|
||||
break;
|
||||
case TYPE_CONFIG:
|
||||
record->zi_type = DMU_OT_PACKED_NVLIST;
|
||||
break;
|
||||
case TYPE_BPLIST:
|
||||
record->zi_type = DMU_OT_BPLIST;
|
||||
break;
|
||||
case TYPE_SPACEMAP:
|
||||
record->zi_type = DMU_OT_SPACE_MAP;
|
||||
break;
|
||||
case TYPE_ERRLOG:
|
||||
record->zi_type = DMU_OT_ERROR_LOG;
|
||||
break;
|
||||
}
|
||||
|
||||
dataset[0] = '\0';
|
||||
(void) strcpy(poolname, object);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a full path into a (dataset, file) pair.
|
||||
*/
|
||||
if (parse_pathname(object, dataset, path, &statbuf) != 0)
|
||||
goto err;
|
||||
|
||||
ziprintf(" dataset: %s\n", dataset);
|
||||
ziprintf(" path: %s\n", path);
|
||||
|
||||
/*
|
||||
* Convert (dataset, file) into (objset, object)
|
||||
*/
|
||||
if (object_from_path(dataset, path, &statbuf, record) != 0)
|
||||
goto err;
|
||||
|
||||
ziprintf("raw objset: %llu\n", record->zi_objset);
|
||||
ziprintf("raw object: %llu\n", record->zi_object);
|
||||
|
||||
/*
|
||||
* For the given object, calculate the real (type, level, range)
|
||||
*/
|
||||
if (calculate_range(dataset, type, level, (char *)range, record) != 0)
|
||||
goto err;
|
||||
|
||||
ziprintf(" objset: %llu\n", record->zi_objset);
|
||||
ziprintf(" object: %llu\n", record->zi_object);
|
||||
if (record->zi_start == 0 &&
|
||||
record->zi_end == -1ULL)
|
||||
ziprintf(" range: all\n");
|
||||
else
|
||||
ziprintf(" range: [%llu, %llu]\n", record->zi_start,
|
||||
record->zi_end);
|
||||
|
||||
/*
|
||||
* Copy the pool name
|
||||
*/
|
||||
(void) strcpy(poolname, dataset);
|
||||
if ((slash = strchr(poolname, '/')) != NULL)
|
||||
*slash = '\0';
|
||||
|
||||
ret = 0;
|
||||
|
||||
err:
|
||||
kernel_fini();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
translate_raw(const char *str, zinject_record_t *record)
|
||||
{
|
||||
/*
|
||||
* A raw bookmark of the form objset:object:level:blkid, where each
|
||||
* number is a hexidecimal value.
|
||||
*/
|
||||
if (sscanf(str, "%llx:%llx:%x:%llx", (u_longlong_t *)&record->zi_objset,
|
||||
(u_longlong_t *)&record->zi_object, &record->zi_level,
|
||||
(u_longlong_t *)&record->zi_start) != 4) {
|
||||
(void) fprintf(stderr, "bad raw spec '%s': must be of the form "
|
||||
"'objset:object:level:blkid'\n", str);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
record->zi_end = record->zi_start;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
translate_device(const char *pool, const char *device, err_type_t label_type,
|
||||
zinject_record_t *record)
|
||||
{
|
||||
char *end;
|
||||
zpool_handle_t *zhp;
|
||||
nvlist_t *tgt;
|
||||
boolean_t isspare, iscache;
|
||||
|
||||
/*
|
||||
* Given a device name or GUID, create an appropriate injection record
|
||||
* with zi_guid set.
|
||||
*/
|
||||
if ((zhp = zpool_open(g_zfs, pool)) == NULL)
|
||||
return (-1);
|
||||
|
||||
record->zi_guid = strtoull(device, &end, 16);
|
||||
if (record->zi_guid == 0 || *end != '\0') {
|
||||
tgt = zpool_find_vdev(zhp, device, &isspare, &iscache, NULL);
|
||||
|
||||
if (tgt == NULL) {
|
||||
(void) fprintf(stderr, "cannot find device '%s' in "
|
||||
"pool '%s'\n", device, pool);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
|
||||
&record->zi_guid) == 0);
|
||||
}
|
||||
|
||||
switch (label_type) {
|
||||
case TYPE_LABEL_UBERBLOCK:
|
||||
record->zi_start = offsetof(vdev_label_t, vl_uberblock[0]);
|
||||
record->zi_end = record->zi_start + VDEV_UBERBLOCK_RING - 1;
|
||||
break;
|
||||
case TYPE_LABEL_NVLIST:
|
||||
record->zi_start = offsetof(vdev_label_t, vl_vdev_phys);
|
||||
record->zi_end = record->zi_start + VDEV_PHYS_SIZE - 1;
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -1,771 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* ZFS Fault Injector
|
||||
*
|
||||
* This userland component takes a set of options and uses libzpool to translate
|
||||
* from a user-visible object type and name to an internal representation.
|
||||
* There are two basic types of faults: device faults and data faults.
|
||||
*
|
||||
*
|
||||
* DEVICE FAULTS
|
||||
*
|
||||
* Errors can be injected into a particular vdev using the '-d' option. This
|
||||
* option takes a path or vdev GUID to uniquely identify the device within a
|
||||
* pool. There are two types of errors that can be injected, EIO and ENXIO,
|
||||
* that can be controlled through the '-e' option. The default is ENXIO. For
|
||||
* EIO failures, any attempt to read data from the device will return EIO, but
|
||||
* subsequent attempt to reopen the device will succeed. For ENXIO failures,
|
||||
* any attempt to read from the device will return EIO, but any attempt to
|
||||
* reopen the device will also return ENXIO.
|
||||
* For label faults, the -L option must be specified. This allows faults
|
||||
* to be injected into either the nvlist or uberblock region of all the labels
|
||||
* for the specified device.
|
||||
*
|
||||
* This form of the command looks like:
|
||||
*
|
||||
* zinject -d device [-e errno] [-L <uber | nvlist>] pool
|
||||
*
|
||||
*
|
||||
* DATA FAULTS
|
||||
*
|
||||
* We begin with a tuple of the form:
|
||||
*
|
||||
* <type,level,range,object>
|
||||
*
|
||||
* type A string describing the type of data to target. Each type
|
||||
* implicitly describes how to interpret 'object'. Currently,
|
||||
* the following values are supported:
|
||||
*
|
||||
* data User data for a file
|
||||
* dnode Dnode for a file or directory
|
||||
*
|
||||
* The following MOS objects are special. Instead of injecting
|
||||
* errors on a particular object or blkid, we inject errors across
|
||||
* all objects of the given type.
|
||||
*
|
||||
* mos Any data in the MOS
|
||||
* mosdir object directory
|
||||
* config pool configuration
|
||||
* bplist blkptr list
|
||||
* spacemap spacemap
|
||||
* metaslab metaslab
|
||||
* errlog persistent error log
|
||||
*
|
||||
* level Object level. Defaults to '0', not applicable to all types. If
|
||||
* a range is given, this corresponds to the indirect block
|
||||
* corresponding to the specific range.
|
||||
*
|
||||
* range A numerical range [start,end) within the object. Defaults to
|
||||
* the full size of the file.
|
||||
*
|
||||
* object A string describing the logical location of the object. For
|
||||
* files and directories (currently the only supported types),
|
||||
* this is the path of the object on disk.
|
||||
*
|
||||
* This is translated, via libzpool, into the following internal representation:
|
||||
*
|
||||
* <type,objset,object,level,range>
|
||||
*
|
||||
* These types should be self-explanatory. This tuple is then passed to the
|
||||
* kernel via a special ioctl() to initiate fault injection for the given
|
||||
* object. Note that 'type' is not strictly necessary for fault injection, but
|
||||
* is used when translating existing faults into a human-readable string.
|
||||
*
|
||||
*
|
||||
* The command itself takes one of the forms:
|
||||
*
|
||||
* zinject
|
||||
* zinject <-a | -u pool>
|
||||
* zinject -c <id|all>
|
||||
* zinject [-q] <-t type> [-f freq] [-u] [-a] [-m] [-e errno] [-l level]
|
||||
* [-r range] <object>
|
||||
* zinject [-f freq] [-a] [-m] [-u] -b objset:object:level:start:end pool
|
||||
*
|
||||
* With no arguments, the command prints all currently registered injection
|
||||
* handlers, with their numeric identifiers.
|
||||
*
|
||||
* The '-c' option will clear the given handler, or all handlers if 'all' is
|
||||
* specified.
|
||||
*
|
||||
* The '-e' option takes a string describing the errno to simulate. This must
|
||||
* be either 'io' or 'checksum'. In most cases this will result in the same
|
||||
* behavior, but RAID-Z will produce a different set of ereports for this
|
||||
* situation.
|
||||
*
|
||||
* The '-a', '-u', and '-m' flags toggle internal flush behavior. If '-a' is
|
||||
* specified, then the ARC cache is flushed appropriately. If '-u' is
|
||||
* specified, then the underlying SPA is unloaded. Either of these flags can be
|
||||
* specified independently of any other handlers. The '-m' flag automatically
|
||||
* does an unmount and remount of the underlying dataset to aid in flushing the
|
||||
* cache.
|
||||
*
|
||||
* The '-f' flag controls the frequency of errors injected, expressed as a
|
||||
* integer percentage between 1 and 100. The default is 100.
|
||||
*
|
||||
* The this form is responsible for actually injecting the handler into the
|
||||
* framework. It takes the arguments described above, translates them to the
|
||||
* internal tuple using libzpool, and then issues an ioctl() to register the
|
||||
* handler.
|
||||
*
|
||||
* The final form can target a specific bookmark, regardless of whether a
|
||||
* human-readable interface has been designed. It allows developers to specify
|
||||
* a particular block by number.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/fs/zfs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <libzfs.h>
|
||||
|
||||
#undef verify /* both libzfs.h and zfs_context.h want to define this */
|
||||
|
||||
#include "zinject.h"
|
||||
|
||||
libzfs_handle_t *g_zfs;
|
||||
int zfs_fd;
|
||||
|
||||
#ifndef ECKSUM
|
||||
#define ECKSUM EBADE
|
||||
#endif
|
||||
|
||||
static const char *errtable[TYPE_INVAL] = {
|
||||
"data",
|
||||
"dnode",
|
||||
"mos",
|
||||
"mosdir",
|
||||
"metaslab",
|
||||
"config",
|
||||
"bplist",
|
||||
"spacemap",
|
||||
"errlog",
|
||||
"uber",
|
||||
"nvlist"
|
||||
};
|
||||
|
||||
static err_type_t
|
||||
name_to_type(const char *arg)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TYPE_INVAL; i++)
|
||||
if (strcmp(errtable[i], arg) == 0)
|
||||
return (i);
|
||||
|
||||
return (TYPE_INVAL);
|
||||
}
|
||||
|
||||
static const char *
|
||||
type_to_name(uint64_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case DMU_OT_OBJECT_DIRECTORY:
|
||||
return ("mosdir");
|
||||
case DMU_OT_OBJECT_ARRAY:
|
||||
return ("metaslab");
|
||||
case DMU_OT_PACKED_NVLIST:
|
||||
return ("config");
|
||||
case DMU_OT_BPLIST:
|
||||
return ("bplist");
|
||||
case DMU_OT_SPACE_MAP:
|
||||
return ("spacemap");
|
||||
case DMU_OT_ERROR_LOG:
|
||||
return ("errlog");
|
||||
default:
|
||||
return ("-");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print usage message.
|
||||
*/
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
(void) printf(
|
||||
"usage:\n"
|
||||
"\n"
|
||||
"\tzinject\n"
|
||||
"\n"
|
||||
"\t\tList all active injection records.\n"
|
||||
"\n"
|
||||
"\tzinject -c <id|all>\n"
|
||||
"\n"
|
||||
"\t\tClear the particular record (if given a numeric ID), or\n"
|
||||
"\t\tall records if 'all' is specificed.\n"
|
||||
"\n"
|
||||
"\tzinject -d device [-e errno] [-L <nvlist|uber>] pool\n"
|
||||
"\t\tInject a fault into a particular device or the device's\n"
|
||||
"\t\tlabel. Label injection can either be 'nvlist' or 'uber'.\n"
|
||||
"\t\t'errno' can either be 'nxio' (the default) or 'io'.\n"
|
||||
"\n"
|
||||
"\tzinject -b objset:object:level:blkid pool\n"
|
||||
"\n"
|
||||
"\t\tInject an error into pool 'pool' with the numeric bookmark\n"
|
||||
"\t\tspecified by the remaining tuple. Each number is in\n"
|
||||
"\t\thexidecimal, and only one block can be specified.\n"
|
||||
"\n"
|
||||
"\tzinject [-q] <-t type> [-e errno] [-l level] [-r range]\n"
|
||||
"\t [-a] [-m] [-u] [-f freq] <object>\n"
|
||||
"\n"
|
||||
"\t\tInject an error into the object specified by the '-t' option\n"
|
||||
"\t\tand the object descriptor. The 'object' parameter is\n"
|
||||
"\t\tinterperted depending on the '-t' option.\n"
|
||||
"\n"
|
||||
"\t\t-q\tQuiet mode. Only print out the handler number added.\n"
|
||||
"\t\t-e\tInject a specific error. Must be either 'io' or\n"
|
||||
"\t\t\t'checksum'. Default is 'io'.\n"
|
||||
"\t\t-l\tInject error at a particular block level. Default is "
|
||||
"0.\n"
|
||||
"\t\t-m\tAutomatically remount underlying filesystem.\n"
|
||||
"\t\t-r\tInject error over a particular logical range of an\n"
|
||||
"\t\t\tobject. Will be translated to the appropriate blkid\n"
|
||||
"\t\t\trange according to the object's properties.\n"
|
||||
"\t\t-a\tFlush the ARC cache. Can be specified without any\n"
|
||||
"\t\t\tassociated object.\n"
|
||||
"\t\t-u\tUnload the associated pool. Can be specified with only\n"
|
||||
"\t\t\ta pool object.\n"
|
||||
"\t\t-f\tOnly inject errors a fraction of the time. Expressed as\n"
|
||||
"\t\t\ta percentage between 1 and 100.\n"
|
||||
"\n"
|
||||
"\t-t data\t\tInject an error into the plain file contents of a\n"
|
||||
"\t\t\tfile. The object must be specified as a complete path\n"
|
||||
"\t\t\tto a file on a ZFS filesystem.\n"
|
||||
"\n"
|
||||
"\t-t dnode\tInject an error into the metadnode in the block\n"
|
||||
"\t\t\tcorresponding to the dnode for a file or directory. The\n"
|
||||
"\t\t\t'-r' option is incompatible with this mode. The object\n"
|
||||
"\t\t\tis specified as a complete path to a file or directory\n"
|
||||
"\t\t\ton a ZFS filesystem.\n"
|
||||
"\n"
|
||||
"\t-t <mos>\tInject errors into the MOS for objects of the given\n"
|
||||
"\t\t\ttype. Valid types are: mos, mosdir, config, bplist,\n"
|
||||
"\t\t\tspacemap, metaslab, errlog. The only valid <object> is\n"
|
||||
"\t\t\tthe poolname.\n");
|
||||
}
|
||||
|
||||
static int
|
||||
iter_handlers(int (*func)(int, const char *, zinject_record_t *, void *),
|
||||
void *data)
|
||||
{
|
||||
zfs_cmd_t zc;
|
||||
int ret;
|
||||
|
||||
zc.zc_guid = 0;
|
||||
|
||||
while (ioctl(zfs_fd, ZFS_IOC_INJECT_LIST_NEXT, &zc) == 0)
|
||||
if ((ret = func((int)zc.zc_guid, zc.zc_name,
|
||||
&zc.zc_inject_record, data)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
print_data_handler(int id, const char *pool, zinject_record_t *record,
|
||||
void *data)
|
||||
{
|
||||
int *count = data;
|
||||
|
||||
if (record->zi_guid != 0)
|
||||
return (0);
|
||||
|
||||
if (*count == 0) {
|
||||
(void) printf("%3s %-15s %-6s %-6s %-8s %3s %-15s\n",
|
||||
"ID", "POOL", "OBJSET", "OBJECT", "TYPE", "LVL", "RANGE");
|
||||
(void) printf("--- --------------- ------ "
|
||||
"------ -------- --- ---------------\n");
|
||||
}
|
||||
|
||||
*count += 1;
|
||||
|
||||
(void) printf("%3d %-15s %-6llu %-6llu %-8s %3d ", id, pool,
|
||||
(u_longlong_t)record->zi_objset, (u_longlong_t)record->zi_object,
|
||||
type_to_name(record->zi_type), record->zi_level);
|
||||
|
||||
if (record->zi_start == 0 &&
|
||||
record->zi_end == -1ULL)
|
||||
(void) printf("all\n");
|
||||
else
|
||||
(void) printf("[%llu, %llu]\n", (u_longlong_t)record->zi_start,
|
||||
(u_longlong_t)record->zi_end);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
print_device_handler(int id, const char *pool, zinject_record_t *record,
|
||||
void *data)
|
||||
{
|
||||
int *count = data;
|
||||
|
||||
if (record->zi_guid == 0)
|
||||
return (0);
|
||||
|
||||
if (*count == 0) {
|
||||
(void) printf("%3s %-15s %s\n", "ID", "POOL", "GUID");
|
||||
(void) printf("--- --------------- ----------------\n");
|
||||
}
|
||||
|
||||
*count += 1;
|
||||
|
||||
(void) printf("%3d %-15s %llx\n", id, pool,
|
||||
(u_longlong_t)record->zi_guid);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print all registered error handlers. Returns the number of handlers
|
||||
* registered.
|
||||
*/
|
||||
static int
|
||||
print_all_handlers(void)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
(void) iter_handlers(print_device_handler, &count);
|
||||
(void) printf("\n");
|
||||
count = 0;
|
||||
(void) iter_handlers(print_data_handler, &count);
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
cancel_one_handler(int id, const char *pool, zinject_record_t *record,
|
||||
void *data)
|
||||
{
|
||||
zfs_cmd_t zc;
|
||||
|
||||
zc.zc_guid = (uint64_t)id;
|
||||
|
||||
if (ioctl(zfs_fd, ZFS_IOC_CLEAR_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to remove handler %d: %s\n",
|
||||
id, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all fault injection handlers.
|
||||
*/
|
||||
static int
|
||||
cancel_all_handlers(void)
|
||||
{
|
||||
int ret = iter_handlers(cancel_one_handler, NULL);
|
||||
|
||||
(void) printf("removed all registered handlers\n");
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a specific fault injection handler.
|
||||
*/
|
||||
static int
|
||||
cancel_handler(int id)
|
||||
{
|
||||
zfs_cmd_t zc;
|
||||
|
||||
zc.zc_guid = (uint64_t)id;
|
||||
|
||||
if (ioctl(zfs_fd, ZFS_IOC_CLEAR_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to remove handler %d: %s\n",
|
||||
id, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
(void) printf("removed handler %d\n", id);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a new fault injection handler.
|
||||
*/
|
||||
static int
|
||||
register_handler(const char *pool, int flags, zinject_record_t *record,
|
||||
int quiet)
|
||||
{
|
||||
zfs_cmd_t zc;
|
||||
|
||||
(void) strcpy(zc.zc_name, pool);
|
||||
zc.zc_inject_record = *record;
|
||||
zc.zc_guid = flags;
|
||||
|
||||
if (ioctl(zfs_fd, ZFS_IOC_INJECT_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to add handler: %s\n",
|
||||
strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (flags & ZINJECT_NULL)
|
||||
return (0);
|
||||
|
||||
if (quiet) {
|
||||
(void) printf("%llu\n", (u_longlong_t)zc.zc_guid);
|
||||
} else {
|
||||
(void) printf("Added handler %llu with the following "
|
||||
"properties:\n", (u_longlong_t)zc.zc_guid);
|
||||
(void) printf(" pool: %s\n", pool);
|
||||
if (record->zi_guid) {
|
||||
(void) printf(" vdev: %llx\n",
|
||||
(u_longlong_t)record->zi_guid);
|
||||
} else {
|
||||
(void) printf("objset: %llu\n",
|
||||
(u_longlong_t)record->zi_objset);
|
||||
(void) printf("object: %llu\n",
|
||||
(u_longlong_t)record->zi_object);
|
||||
(void) printf(" type: %llu\n",
|
||||
(u_longlong_t)record->zi_type);
|
||||
(void) printf(" level: %d\n", record->zi_level);
|
||||
if (record->zi_start == 0 &&
|
||||
record->zi_end == -1ULL)
|
||||
(void) printf(" range: all\n");
|
||||
else
|
||||
(void) printf(" range: [%llu, %llu)\n",
|
||||
(u_longlong_t)record->zi_start,
|
||||
(u_longlong_t)record->zi_end);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
char *range = NULL;
|
||||
char *cancel = NULL;
|
||||
char *end;
|
||||
char *raw = NULL;
|
||||
char *device = NULL;
|
||||
int level = 0;
|
||||
int quiet = 0;
|
||||
int error = 0;
|
||||
int domount = 0;
|
||||
err_type_t type = TYPE_INVAL;
|
||||
err_type_t label = TYPE_INVAL;
|
||||
zinject_record_t record = { 0 };
|
||||
char pool[MAXNAMELEN];
|
||||
char dataset[MAXNAMELEN];
|
||||
zfs_handle_t *zhp;
|
||||
int ret;
|
||||
int flags = 0;
|
||||
|
||||
if ((g_zfs = libzfs_init()) == NULL) {
|
||||
(void) fprintf(stderr, "internal error: failed to "
|
||||
"initialize ZFS library\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
libzfs_print_on_error(g_zfs, B_TRUE);
|
||||
|
||||
if ((zfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
|
||||
(void) fprintf(stderr, "failed to open ZFS device\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
/*
|
||||
* No arguments. Print the available handlers. If there are no
|
||||
* available handlers, direct the user to '-h' for help
|
||||
* information.
|
||||
*/
|
||||
if (print_all_handlers() == 0) {
|
||||
(void) printf("No handlers registered.\n");
|
||||
(void) printf("Run 'zinject -h' for usage "
|
||||
"information.\n");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
while ((c = getopt(argc, argv, ":ab:d:f:qhc:t:l:mr:e:uL:")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
flags |= ZINJECT_FLUSH_ARC;
|
||||
break;
|
||||
case 'b':
|
||||
raw = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
cancel = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
device = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
if (strcasecmp(optarg, "io") == 0) {
|
||||
error = EIO;
|
||||
} else if (strcasecmp(optarg, "checksum") == 0) {
|
||||
error = ECKSUM;
|
||||
} else if (strcasecmp(optarg, "nxio") == 0) {
|
||||
error = ENXIO;
|
||||
} else {
|
||||
(void) fprintf(stderr, "invalid error type "
|
||||
"'%s': must be 'io', 'checksum' or "
|
||||
"'nxio'\n", optarg);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
record.zi_freq = atoi(optarg);
|
||||
if (record.zi_freq < 1 || record.zi_freq > 100) {
|
||||
(void) fprintf(stderr, "frequency range must "
|
||||
"be in the range (0, 100]\n");
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return (0);
|
||||
case 'l':
|
||||
level = (int)strtol(optarg, &end, 10);
|
||||
if (*end != '\0') {
|
||||
(void) fprintf(stderr, "invalid level '%s': "
|
||||
"must be an integer\n", optarg);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
domount = 1;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case 'r':
|
||||
range = optarg;
|
||||
break;
|
||||
case 't':
|
||||
if ((type = name_to_type(optarg)) == TYPE_INVAL &&
|
||||
!MOS_TYPE(type)) {
|
||||
(void) fprintf(stderr, "invalid type '%s'\n",
|
||||
optarg);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
flags |= ZINJECT_UNLOAD_SPA;
|
||||
break;
|
||||
case 'L':
|
||||
if ((label = name_to_type(optarg)) == TYPE_INVAL &&
|
||||
!LABEL_TYPE(type)) {
|
||||
(void) fprintf(stderr, "invalid label type "
|
||||
"'%s'\n", optarg);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
(void) fprintf(stderr, "option -%c requires an "
|
||||
"operand\n", optopt);
|
||||
usage();
|
||||
return (1);
|
||||
case '?':
|
||||
(void) fprintf(stderr, "invalid option '%c'\n",
|
||||
optopt);
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (cancel != NULL) {
|
||||
/*
|
||||
* '-c' is invalid with any other options.
|
||||
*/
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0) {
|
||||
(void) fprintf(stderr, "cancel (-c) incompatible with "
|
||||
"any other options\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
if (argc != 0) {
|
||||
(void) fprintf(stderr, "extraneous argument to '-c'\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (strcmp(cancel, "all") == 0) {
|
||||
return (cancel_all_handlers());
|
||||
} else {
|
||||
int id = (int)strtol(cancel, &end, 10);
|
||||
if (*end != '\0') {
|
||||
(void) fprintf(stderr, "invalid handle id '%s':"
|
||||
" must be an integer or 'all'\n", cancel);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
return (cancel_handler(id));
|
||||
}
|
||||
}
|
||||
|
||||
if (device != NULL) {
|
||||
/*
|
||||
* Device (-d) injection uses a completely different mechanism
|
||||
* for doing injection, so handle it separately here.
|
||||
*/
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0) {
|
||||
(void) fprintf(stderr, "device (-d) incompatible with "
|
||||
"data error injection\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (argc != 1) {
|
||||
(void) fprintf(stderr, "device (-d) injection requires "
|
||||
"a single pool name\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
(void) strcpy(pool, argv[0]);
|
||||
dataset[0] = '\0';
|
||||
|
||||
if (error == ECKSUM) {
|
||||
(void) fprintf(stderr, "device error type must be "
|
||||
"'io' or 'nxio'\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (translate_device(pool, device, label, &record) != 0)
|
||||
return (1);
|
||||
if (!error)
|
||||
error = ENXIO;
|
||||
} else if (raw != NULL) {
|
||||
if (range != NULL || type != TYPE_INVAL || level != 0) {
|
||||
(void) fprintf(stderr, "raw (-b) format with "
|
||||
"any other options\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (argc != 1) {
|
||||
(void) fprintf(stderr, "raw (-b) format expects a "
|
||||
"single pool name\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
(void) strcpy(pool, argv[0]);
|
||||
dataset[0] = '\0';
|
||||
|
||||
if (error == ENXIO) {
|
||||
(void) fprintf(stderr, "data error type must be "
|
||||
"'checksum' or 'io'\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (translate_raw(raw, &record) != 0)
|
||||
return (1);
|
||||
if (!error)
|
||||
error = EIO;
|
||||
} else if (type == TYPE_INVAL) {
|
||||
if (flags == 0) {
|
||||
(void) fprintf(stderr, "at least one of '-b', '-d', "
|
||||
"'-t', '-a', or '-u' must be specified\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (argc == 1 && (flags & ZINJECT_UNLOAD_SPA)) {
|
||||
(void) strcpy(pool, argv[0]);
|
||||
dataset[0] = '\0';
|
||||
} else if (argc != 0) {
|
||||
(void) fprintf(stderr, "extraneous argument for "
|
||||
"'-f'\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
flags |= ZINJECT_NULL;
|
||||
} else {
|
||||
if (argc != 1) {
|
||||
(void) fprintf(stderr, "missing object\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (error == ENXIO) {
|
||||
(void) fprintf(stderr, "data error type must be "
|
||||
"'checksum' or 'io'\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (translate_record(type, argv[0], range, level, &record, pool,
|
||||
dataset) != 0)
|
||||
return (1);
|
||||
if (!error)
|
||||
error = EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is pool-wide metadata, unmount everything. The ioctl() will
|
||||
* unload the pool, so that we trigger spa-wide reopen of metadata next
|
||||
* time we access the pool.
|
||||
*/
|
||||
if (dataset[0] != '\0' && domount) {
|
||||
if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
|
||||
return (1);
|
||||
|
||||
if (zfs_unmount(zhp, NULL, 0) != 0)
|
||||
return (1);
|
||||
}
|
||||
|
||||
record.zi_error = error;
|
||||
|
||||
ret = register_handler(pool, flags, &record, quiet);
|
||||
|
||||
if (dataset[0] != '\0' && domount)
|
||||
ret = (zfs_mount(zhp, NULL, 0) != 0);
|
||||
|
||||
libzfs_fini(g_zfs);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _ZINJECT_H
|
||||
#define _ZINJECT_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/zfs_ioctl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
TYPE_DATA, /* plain file contents */
|
||||
TYPE_DNODE, /* metadnode contents */
|
||||
TYPE_MOS, /* all MOS data */
|
||||
TYPE_MOSDIR, /* MOS object directory */
|
||||
TYPE_METASLAB, /* metaslab objects */
|
||||
TYPE_CONFIG, /* MOS config */
|
||||
TYPE_BPLIST, /* block pointer list */
|
||||
TYPE_SPACEMAP, /* space map objects */
|
||||
TYPE_ERRLOG, /* persistent error log */
|
||||
TYPE_LABEL_UBERBLOCK, /* label specific uberblock */
|
||||
TYPE_LABEL_NVLIST, /* label specific nvlist */
|
||||
TYPE_INVAL
|
||||
} err_type_t;
|
||||
|
||||
#define MOS_TYPE(t) \
|
||||
((t) >= TYPE_MOS && (t) < TYPE_LABEL_UBERBLOCK)
|
||||
|
||||
#define LABEL_TYPE(t) \
|
||||
((t) >= TYPE_LABEL_UBERBLOCK && (t) < TYPE_INVAL)
|
||||
|
||||
int translate_record(err_type_t type, const char *object, const char *range,
|
||||
int level, zinject_record_t *record, char *poolname, char *dataset);
|
||||
int translate_raw(const char *raw, zinject_record_t *record);
|
||||
int translate_device(const char *pool, const char *device,
|
||||
err_type_t label_type, zinject_record_t *record);
|
||||
void usage(void);
|
||||
|
||||
extern libzfs_handle_t *g_zfs;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ZINJECT_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -53,7 +53,6 @@ struct zpool_list {
|
||||
boolean_t zl_findall;
|
||||
uu_avl_t *zl_avl;
|
||||
uu_avl_pool_t *zl_pool;
|
||||
zprop_list_t **zl_proplist;
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -82,12 +81,6 @@ add_pool(zpool_handle_t *zhp, void *data)
|
||||
node->zn_handle = zhp;
|
||||
uu_avl_node_init(node, &node->zn_avlnode, zlp->zl_pool);
|
||||
if (uu_avl_find(zlp->zl_avl, node, NULL, &idx) == NULL) {
|
||||
if (zlp->zl_proplist &&
|
||||
zpool_expand_proplist(zhp, zlp->zl_proplist) != 0) {
|
||||
zpool_close(zhp);
|
||||
free(node);
|
||||
return (-1);
|
||||
}
|
||||
uu_avl_insert(zlp->zl_avl, node, idx);
|
||||
} else {
|
||||
zpool_close(zhp);
|
||||
@@ -105,7 +98,7 @@ add_pool(zpool_handle_t *zhp, void *data)
|
||||
* line.
|
||||
*/
|
||||
zpool_list_t *
|
||||
pool_list_get(int argc, char **argv, zprop_list_t **proplist, int *err)
|
||||
pool_list_get(int argc, char **argv, zpool_proplist_t **proplist, int *err)
|
||||
{
|
||||
zpool_list_t *zlp;
|
||||
|
||||
@@ -121,8 +114,6 @@ pool_list_get(int argc, char **argv, zprop_list_t **proplist, int *err)
|
||||
UU_DEFAULT)) == NULL)
|
||||
zpool_no_memory();
|
||||
|
||||
zlp->zl_proplist = proplist;
|
||||
|
||||
if (argc == 0) {
|
||||
(void) zpool_iter(g_zfs, add_pool, zlp);
|
||||
zlp->zl_findall = B_TRUE;
|
||||
@@ -132,12 +123,13 @@ pool_list_get(int argc, char **argv, zprop_list_t **proplist, int *err)
|
||||
for (i = 0; i < argc; i++) {
|
||||
zpool_handle_t *zhp;
|
||||
|
||||
if (zhp = zpool_open_canfail(g_zfs, argv[i])) {
|
||||
if (add_pool(zhp, zlp) != 0)
|
||||
if ((zhp = zpool_open_canfail(g_zfs,
|
||||
argv[i])) != NULL && add_pool(zhp, zlp) == 0) {
|
||||
if (proplist &&
|
||||
zpool_expand_proplist(zhp, proplist) != 0)
|
||||
*err = B_TRUE;
|
||||
} else {
|
||||
} else
|
||||
*err = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +228,7 @@ pool_list_count(zpool_list_t *zlp)
|
||||
*/
|
||||
int
|
||||
for_each_pool(int argc, char **argv, boolean_t unavail,
|
||||
zprop_list_t **proplist, zpool_iter_f func, void *data)
|
||||
zpool_proplist_t **proplist, zpool_iter_f func, void *data)
|
||||
{
|
||||
zpool_list_t *list;
|
||||
int ret = 0;
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -77,28 +77,3 @@ zpool_no_memory(void)
|
||||
gettext("internal error: out of memory\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of logs in supplied nvlist
|
||||
*/
|
||||
uint_t
|
||||
num_logs(nvlist_t *nv)
|
||||
{
|
||||
uint_t nlogs = 0;
|
||||
uint_t c, children;
|
||||
nvlist_t **child;
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0)
|
||||
return (0);
|
||||
|
||||
for (c = 0; c < children; c++) {
|
||||
uint64_t is_log = B_FALSE;
|
||||
|
||||
(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
|
||||
&is_log);
|
||||
if (is_log)
|
||||
nlogs++;
|
||||
}
|
||||
return (nlogs);
|
||||
}
|
||||
@@ -19,13 +19,15 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef ZPOOL_UTIL_H
|
||||
#define ZPOOL_UTIL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <libnvpair.h>
|
||||
#include <libzfs.h>
|
||||
|
||||
@@ -39,24 +41,22 @@ extern "C" {
|
||||
void *safe_malloc(size_t);
|
||||
char *safe_strdup(const char *);
|
||||
void zpool_no_memory(void);
|
||||
uint_t num_logs(nvlist_t *nv);
|
||||
|
||||
/*
|
||||
* Virtual device functions
|
||||
*/
|
||||
|
||||
nvlist_t *make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
|
||||
boolean_t isreplace, boolean_t dryrun, int argc, char **argv);
|
||||
nvlist_t *make_root_vdev(nvlist_t *poolconfig, int force, int check_rep,
|
||||
boolean_t isreplace, int argc, char **argv);
|
||||
|
||||
/*
|
||||
* Pool list functions
|
||||
*/
|
||||
int for_each_pool(int, char **, boolean_t unavail, zprop_list_t **,
|
||||
int for_each_pool(int, char **, boolean_t unavail, zpool_proplist_t **,
|
||||
zpool_iter_f, void *);
|
||||
|
||||
typedef struct zpool_list zpool_list_t;
|
||||
|
||||
zpool_list_t *pool_list_get(int, char **, zprop_list_t **, int *);
|
||||
zpool_list_t *pool_list_get(int, char **, zpool_proplist_t **, int *);
|
||||
void pool_list_update(zpool_list_t *);
|
||||
int pool_list_iter(zpool_list_t *, int unavail, zpool_iter_f, void *);
|
||||
void pool_list_free(zpool_list_t *);
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Functions to convert between a list of vdevs and an nvlist representing the
|
||||
* configuration. Each entry in the list can be one of:
|
||||
@@ -46,8 +48,8 @@
|
||||
* Hot spares are a special case, and passed down as an array of disk vdevs, at
|
||||
* the same level as the root of the vdev tree.
|
||||
*
|
||||
* The only function exported by this file is 'make_root_vdev'. The
|
||||
* function performs several passes:
|
||||
* The only function exported by this file is 'get_vdev_spec'. The function
|
||||
* performs several passes:
|
||||
*
|
||||
* 1. Construct the vdev specification. Performs syntax validation and
|
||||
* makes sure each device is valid.
|
||||
@@ -57,7 +59,6 @@
|
||||
* 3. Check for replication errors if the 'force' flag is not specified.
|
||||
* validates that the replication level is consistent across the
|
||||
* entire pool.
|
||||
* 4. Call libzfs to label any whole disks with an EFI label.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@@ -75,6 +76,8 @@
|
||||
#include <sys/mntent.h>
|
||||
#include <libgeom.h>
|
||||
|
||||
#include <libzfs.h>
|
||||
|
||||
#include "zpool_util.h"
|
||||
|
||||
/*
|
||||
@@ -108,105 +111,53 @@ vdev_error(const char *fmt, ...)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that a file is valid. All we can do in this case is check that it's
|
||||
* not in use by another pool, and not in use by swap.
|
||||
* Validate a GEOM provider.
|
||||
*/
|
||||
static int
|
||||
check_file(const char *file, boolean_t force, boolean_t isspare)
|
||||
{
|
||||
char *name;
|
||||
int fd;
|
||||
int ret = 0;
|
||||
int err;
|
||||
pool_state_t state;
|
||||
boolean_t inuse;
|
||||
|
||||
#if 0
|
||||
if (dm_inuse_swap(file, &err)) {
|
||||
if (err)
|
||||
libdiskmgt_error(err);
|
||||
else
|
||||
vdev_error(gettext("%s is currently used by swap. "
|
||||
"Please see swap(1M).\n"), file);
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fd = open(file, O_RDONLY)) < 0)
|
||||
return (0);
|
||||
|
||||
if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) == 0 && inuse) {
|
||||
const char *desc;
|
||||
|
||||
switch (state) {
|
||||
case POOL_STATE_ACTIVE:
|
||||
desc = gettext("active");
|
||||
break;
|
||||
|
||||
case POOL_STATE_EXPORTED:
|
||||
desc = gettext("exported");
|
||||
break;
|
||||
|
||||
case POOL_STATE_POTENTIALLY_ACTIVE:
|
||||
desc = gettext("potentially active");
|
||||
break;
|
||||
|
||||
default:
|
||||
desc = gettext("unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow hot spares to be shared between pools.
|
||||
*/
|
||||
if (state == POOL_STATE_SPARE && isspare)
|
||||
return (0);
|
||||
|
||||
if (state == POOL_STATE_ACTIVE ||
|
||||
state == POOL_STATE_SPARE || !force) {
|
||||
switch (state) {
|
||||
case POOL_STATE_SPARE:
|
||||
vdev_error(gettext("%s is reserved as a hot "
|
||||
"spare for pool %s\n"), file, name);
|
||||
break;
|
||||
default:
|
||||
vdev_error(gettext("%s is part of %s pool "
|
||||
"'%s'\n"), file, desc, name);
|
||||
break;
|
||||
}
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free(name);
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
check_provider(const char *name, boolean_t force, boolean_t isspare)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
struct gmesh mesh;
|
||||
struct gclass *mp;
|
||||
struct ggeom *gp;
|
||||
struct gprovider *pp;
|
||||
int rv;
|
||||
|
||||
if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV) - 1) != 0)
|
||||
snprintf(path, sizeof(path), "%s%s", _PATH_DEV, name);
|
||||
else
|
||||
strlcpy(path, name, sizeof(path));
|
||||
/* XXX: What to do with isspare? */
|
||||
|
||||
return (check_file(path, force, isspare));
|
||||
if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
|
||||
name += sizeof(_PATH_DEV) - 1;
|
||||
|
||||
rv = geom_gettree(&mesh);
|
||||
assert(rv == 0);
|
||||
|
||||
pp = NULL;
|
||||
LIST_FOREACH(mp, &mesh.lg_class, lg_class) {
|
||||
LIST_FOREACH(gp, &mp->lg_geom, lg_geom) {
|
||||
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
|
||||
if (strcmp(pp->lg_name, name) == 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
rv = -1;
|
||||
if (pp == NULL)
|
||||
vdev_error("no such provider %s\n", name);
|
||||
else {
|
||||
int acr, acw, ace;
|
||||
|
||||
VERIFY(sscanf(pp->lg_mode, "r%dw%de%d", &acr, &acw, &ace) == 3);
|
||||
if (acw == 0 && ace == 0)
|
||||
rv = 0;
|
||||
else
|
||||
vdev_error("%s is in use (%s)\n", name, pp->lg_mode);
|
||||
}
|
||||
geom_deletetree(&mesh);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* By "whole disk" we mean an entire physical disk (something we can
|
||||
* label, toggle the write cache on, etc.) as opposed to the full
|
||||
* capacity of a pseudo-device such as lofi or did. We act as if we
|
||||
* are labeling the disk, which should be a pretty good test of whether
|
||||
* it's a viable device or not. Returns B_TRUE if it is and B_FALSE if
|
||||
* it isn't.
|
||||
*/
|
||||
static boolean_t
|
||||
is_whole_disk(const char *name)
|
||||
is_provider(const char *name)
|
||||
{
|
||||
int fd;
|
||||
|
||||
@@ -216,8 +167,8 @@ is_whole_disk(const char *name)
|
||||
return (B_TRUE);
|
||||
}
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Create a leaf vdev. Determine if this is a GEOM provider.
|
||||
* Valid forms for a leaf vdev are:
|
||||
@@ -225,8 +176,8 @@ is_whole_disk(const char *name)
|
||||
* /dev/xxx Complete path to a GEOM provider
|
||||
* xxx Shorthand for /dev/xxx
|
||||
*/
|
||||
static nvlist_t *
|
||||
make_leaf_vdev(const char *arg, uint64_t is_log)
|
||||
nvlist_t *
|
||||
make_leaf_vdev(const char *arg)
|
||||
{
|
||||
char ident[DISK_IDENT_SIZE], path[MAXPATHLEN];
|
||||
struct stat64 statbuf;
|
||||
@@ -234,72 +185,16 @@ make_leaf_vdev(const char *arg, uint64_t is_log)
|
||||
char *type = NULL;
|
||||
boolean_t wholedisk = B_FALSE;
|
||||
|
||||
/*
|
||||
* Determine what type of vdev this is, and put the full path into
|
||||
* 'path'. We detect whether this is a device of file afterwards by
|
||||
* checking the st_mode of the file.
|
||||
*/
|
||||
if (arg[0] == '/') {
|
||||
/*
|
||||
* Complete device or file path. Exact type is determined by
|
||||
* examining the file descriptor afterwards.
|
||||
*/
|
||||
wholedisk = is_whole_disk(arg);
|
||||
if (!wholedisk && (stat64(arg, &statbuf) != 0)) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot open '%s': %s\n"),
|
||||
arg, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
if (strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
|
||||
strlcpy(path, arg, sizeof (path));
|
||||
else
|
||||
snprintf(path, sizeof (path), "%s%s", _PATH_DEV, arg);
|
||||
|
||||
(void) strlcpy(path, arg, sizeof (path));
|
||||
} else {
|
||||
/*
|
||||
* This may be a short path for a device, or it could be total
|
||||
* gibberish. Check to see if it's a known device in
|
||||
* /dev/dsk/. As part of this check, see if we've been given a
|
||||
* an entire disk (minus the slice number).
|
||||
*/
|
||||
if (strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
|
||||
strlcpy(path, arg, sizeof (path));
|
||||
else
|
||||
snprintf(path, sizeof (path), "%s%s", _PATH_DEV, arg);
|
||||
wholedisk = is_whole_disk(path);
|
||||
if (!wholedisk && (stat64(path, &statbuf) != 0)) {
|
||||
/*
|
||||
* If we got ENOENT, then the user gave us
|
||||
* gibberish, so try to direct them with a
|
||||
* reasonable error message. Otherwise,
|
||||
* regurgitate strerror() since it's the best we
|
||||
* can do.
|
||||
*/
|
||||
if (errno == ENOENT) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot open '%s': no such "
|
||||
"GEOM provider\n"), arg);
|
||||
(void) fprintf(stderr,
|
||||
gettext("must be a full path or "
|
||||
"shorthand device name\n"));
|
||||
return (NULL);
|
||||
} else {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot open '%s': %s\n"),
|
||||
path, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether this is a device or a file.
|
||||
*/
|
||||
if (wholedisk) {
|
||||
if (is_provider(path))
|
||||
type = VDEV_TYPE_DISK;
|
||||
} else if (S_ISREG(statbuf.st_mode)) {
|
||||
type = VDEV_TYPE_FILE;
|
||||
} else {
|
||||
else {
|
||||
(void) fprintf(stderr, gettext("cannot use '%s': must be a "
|
||||
"GEOM provider or regular file\n"), path);
|
||||
"GEOM provider\n"), path);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -311,7 +206,6 @@ make_leaf_vdev(const char *arg, uint64_t is_log)
|
||||
verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
|
||||
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
|
||||
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
|
||||
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
|
||||
if (strcmp(type, VDEV_TYPE_DISK) == 0)
|
||||
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
(uint64_t)B_FALSE) == 0);
|
||||
@@ -373,14 +267,12 @@ typedef struct replication_level {
|
||||
uint64_t zprl_parity;
|
||||
} replication_level_t;
|
||||
|
||||
#define ZPOOL_FUZZ (16 * 1024 * 1024)
|
||||
|
||||
/*
|
||||
* Given a list of toplevel vdevs, return the current replication level. If
|
||||
* the config is inconsistent, then NULL is returned. If 'fatal' is set, then
|
||||
* an error message will be displayed for each self-inconsistent vdev.
|
||||
*/
|
||||
static replication_level_t *
|
||||
replication_level_t *
|
||||
get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
{
|
||||
nvlist_t **top;
|
||||
@@ -399,20 +291,10 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
|
||||
lastrep.zprl_type = NULL;
|
||||
for (t = 0; t < toplevels; t++) {
|
||||
uint64_t is_log = B_FALSE;
|
||||
|
||||
nv = top[t];
|
||||
|
||||
/*
|
||||
* For separate logs we ignore the top level vdev replication
|
||||
* constraints.
|
||||
*/
|
||||
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log);
|
||||
if (is_log)
|
||||
continue;
|
||||
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
|
||||
|
||||
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE,
|
||||
&type) == 0);
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0) {
|
||||
/*
|
||||
@@ -446,7 +328,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
}
|
||||
|
||||
/*
|
||||
* The 'dontreport' variable indicates that we've
|
||||
* The 'dontreport' variable indicatest that we've
|
||||
* already reported an error for this spec, so don't
|
||||
* bother doing it again.
|
||||
*/
|
||||
@@ -467,7 +349,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
ZPOOL_CONFIG_TYPE, &childtype) == 0);
|
||||
|
||||
/*
|
||||
* If this is a replacing or spare vdev, then
|
||||
* If this is a a replacing or spare vdev, then
|
||||
* get the real first child of the vdev.
|
||||
*/
|
||||
if (strcmp(childtype,
|
||||
@@ -527,30 +409,22 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
*/
|
||||
if ((fd = open(path, O_RDONLY)) >= 0) {
|
||||
err = fstat64(fd, &statbuf);
|
||||
if (err == 0 &&
|
||||
S_ISCHR(statbuf.st_mode)) {
|
||||
err = ioctl(fd, DIOCGMEDIASIZE,
|
||||
&statbuf.st_size);
|
||||
}
|
||||
(void) close(fd);
|
||||
} else {
|
||||
err = stat64(path, &statbuf);
|
||||
}
|
||||
|
||||
if (err != 0 || statbuf.st_size == 0)
|
||||
continue;
|
||||
|
||||
size = statbuf.st_size;
|
||||
|
||||
/*
|
||||
* Also make sure that devices and
|
||||
* slices have a consistent size. If
|
||||
* they differ by a significant amount
|
||||
* (~16MB) then report an error.
|
||||
* Also check the size of each device. If they
|
||||
* differ, then report an error.
|
||||
*/
|
||||
if (!dontreport &&
|
||||
(vdev_size != -1ULL &&
|
||||
(labs(size - vdev_size) >
|
||||
ZPOOL_FUZZ))) {
|
||||
if (!dontreport && vdev_size != -1ULL &&
|
||||
size != vdev_size) {
|
||||
if (ret != NULL)
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
@@ -632,11 +506,9 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
* has a consistent replication level, then we ignore any errors. Otherwise,
|
||||
* report any difference between the two.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
check_replication(nvlist_t *config, nvlist_t *newroot)
|
||||
{
|
||||
nvlist_t **child;
|
||||
uint_t children;
|
||||
replication_level_t *current = NULL, *new;
|
||||
int ret;
|
||||
|
||||
@@ -652,23 +524,6 @@ check_replication(nvlist_t *config, nvlist_t *newroot)
|
||||
if ((current = get_replication(nvroot, B_FALSE)) == NULL)
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* for spares there may be no children, and therefore no
|
||||
* replication level to check
|
||||
*/
|
||||
if ((nvlist_lookup_nvlist_array(newroot, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0) || (children == 0)) {
|
||||
free(current);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If all we have is logs then there's no replication level to check.
|
||||
*/
|
||||
if (num_logs(newroot) == children) {
|
||||
free(current);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the replication level of the new vdev spec, reporting any
|
||||
@@ -766,7 +621,7 @@ is_spare(nvlist_t *config, const char *path)
|
||||
* Go through and find any devices that are in use. We rely on libdiskmgt for
|
||||
* the majority of this task.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
|
||||
int isspare)
|
||||
{
|
||||
@@ -798,9 +653,6 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
|
||||
if (strcmp(type, VDEV_TYPE_DISK) == 0)
|
||||
ret = check_provider(path, force, isspare);
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_FILE) == 0)
|
||||
ret = check_file(path, force, isspare);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -816,17 +668,10 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
|
||||
isreplacing, B_TRUE)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
|
||||
&child, &children) == 0)
|
||||
for (c = 0; c < children; c++)
|
||||
if ((ret = check_in_use(config, child[c], force,
|
||||
isreplacing, B_FALSE)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
const char *
|
||||
is_grouping(const char *type, int *mindev)
|
||||
{
|
||||
if (strcmp(type, "raidz") == 0 || strcmp(type, "raidz1") == 0) {
|
||||
@@ -853,18 +698,6 @@ is_grouping(const char *type, int *mindev)
|
||||
return (VDEV_TYPE_SPARE);
|
||||
}
|
||||
|
||||
if (strcmp(type, "log") == 0) {
|
||||
if (mindev != NULL)
|
||||
*mindev = 1;
|
||||
return (VDEV_TYPE_LOG);
|
||||
}
|
||||
|
||||
if (strcmp(type, "cache") == 0) {
|
||||
if (mindev != NULL)
|
||||
*mindev = 1;
|
||||
return (VDEV_TYPE_L2CACHE);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -877,21 +710,14 @@ is_grouping(const char *type, int *mindev)
|
||||
nvlist_t *
|
||||
construct_spec(int argc, char **argv)
|
||||
{
|
||||
nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
|
||||
int t, toplevels, mindev, nspares, nlogs, nl2cache;
|
||||
nvlist_t *nvroot, *nv, **top, **spares;
|
||||
int t, toplevels, mindev, nspares;
|
||||
const char *type;
|
||||
uint64_t is_log;
|
||||
boolean_t seen_logs;
|
||||
|
||||
top = NULL;
|
||||
toplevels = 0;
|
||||
spares = NULL;
|
||||
l2cache = NULL;
|
||||
nspares = 0;
|
||||
nlogs = 0;
|
||||
nl2cache = 0;
|
||||
is_log = B_FALSE;
|
||||
seen_logs = B_FALSE;
|
||||
|
||||
while (argc > 0) {
|
||||
nv = NULL;
|
||||
@@ -904,56 +730,12 @@ construct_spec(int argc, char **argv)
|
||||
nvlist_t **child = NULL;
|
||||
int c, children = 0;
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
|
||||
if (spares != NULL) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: 'spare' can be "
|
||||
"specified only once\n"));
|
||||
return (NULL);
|
||||
}
|
||||
is_log = B_FALSE;
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_LOG) == 0) {
|
||||
if (seen_logs) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: 'log' can be "
|
||||
"specified only once\n"));
|
||||
return (NULL);
|
||||
}
|
||||
seen_logs = B_TRUE;
|
||||
is_log = B_TRUE;
|
||||
argc--;
|
||||
argv++;
|
||||
/*
|
||||
* A log is not a real grouping device.
|
||||
* We just set is_log and continue.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
|
||||
if (l2cache != NULL) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: 'cache' can be "
|
||||
"specified only once\n"));
|
||||
return (NULL);
|
||||
}
|
||||
is_log = B_FALSE;
|
||||
}
|
||||
|
||||
if (is_log) {
|
||||
if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: unsupported 'log' "
|
||||
"device: %s\n"), type);
|
||||
return (NULL);
|
||||
}
|
||||
nlogs++;
|
||||
if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
|
||||
spares != NULL) {
|
||||
(void) fprintf(stderr, gettext("invalid vdev "
|
||||
"specification: 'spare' can be "
|
||||
"specified only once\n"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
for (c = 1; c < argc; c++) {
|
||||
@@ -964,8 +746,7 @@ construct_spec(int argc, char **argv)
|
||||
children * sizeof (nvlist_t *));
|
||||
if (child == NULL)
|
||||
zpool_no_memory();
|
||||
if ((nv = make_leaf_vdev(argv[c], B_FALSE))
|
||||
== NULL)
|
||||
if ((nv = make_leaf_vdev(argv[c])) == NULL)
|
||||
return (NULL);
|
||||
child[children - 1] = nv;
|
||||
}
|
||||
@@ -984,17 +765,11 @@ construct_spec(int argc, char **argv)
|
||||
spares = child;
|
||||
nspares = children;
|
||||
continue;
|
||||
} else if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
|
||||
l2cache = child;
|
||||
nl2cache = children;
|
||||
continue;
|
||||
} else {
|
||||
verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
|
||||
0) == 0);
|
||||
verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
|
||||
type) == 0);
|
||||
verify(nvlist_add_uint64(nv,
|
||||
ZPOOL_CONFIG_IS_LOG, is_log) == 0);
|
||||
if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
|
||||
verify(nvlist_add_uint64(nv,
|
||||
ZPOOL_CONFIG_NPARITY,
|
||||
@@ -1013,10 +788,8 @@ construct_spec(int argc, char **argv)
|
||||
* We have a device. Pass off to make_leaf_vdev() to
|
||||
* construct the appropriate nvlist describing the vdev.
|
||||
*/
|
||||
if ((nv = make_leaf_vdev(argv[0], is_log)) == NULL)
|
||||
if ((nv = make_leaf_vdev(argv[0])) == NULL)
|
||||
return (NULL);
|
||||
if (is_log)
|
||||
nlogs++;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
@@ -1028,19 +801,13 @@ construct_spec(int argc, char **argv)
|
||||
top[toplevels - 1] = nv;
|
||||
}
|
||||
|
||||
if (toplevels == 0 && nspares == 0 && nl2cache == 0) {
|
||||
if (toplevels == 0 && nspares == 0) {
|
||||
(void) fprintf(stderr, gettext("invalid vdev "
|
||||
"specification: at least one toplevel vdev must be "
|
||||
"specified\n"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (seen_logs && nlogs == 0) {
|
||||
(void) fprintf(stderr, gettext("invalid vdev specification: "
|
||||
"log requires at least 1 device\n"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, create nvroot and add all top-level vdevs to it.
|
||||
*/
|
||||
@@ -1052,26 +819,18 @@ construct_spec(int argc, char **argv)
|
||||
if (nspares != 0)
|
||||
verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
|
||||
spares, nspares) == 0);
|
||||
if (nl2cache != 0)
|
||||
verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
|
||||
l2cache, nl2cache) == 0);
|
||||
|
||||
for (t = 0; t < toplevels; t++)
|
||||
nvlist_free(top[t]);
|
||||
for (t = 0; t < nspares; t++)
|
||||
nvlist_free(spares[t]);
|
||||
for (t = 0; t < nl2cache; t++)
|
||||
nvlist_free(l2cache[t]);
|
||||
if (spares)
|
||||
free(spares);
|
||||
if (l2cache)
|
||||
free(l2cache);
|
||||
free(top);
|
||||
|
||||
return (nvroot);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get and validate the contents of the given vdev specification. This ensures
|
||||
* that the nvlist returned is well-formed, that all the devices exist, and that
|
||||
@@ -1083,11 +842,11 @@ construct_spec(int argc, char **argv)
|
||||
* added, even if they appear in use.
|
||||
*/
|
||||
nvlist_t *
|
||||
make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
|
||||
boolean_t isreplacing, boolean_t dryrun, int argc, char **argv)
|
||||
make_root_vdev(nvlist_t *poolconfig, int force, int check_rep,
|
||||
boolean_t isreplacing, int argc, char **argv)
|
||||
{
|
||||
nvlist_t *newroot;
|
||||
nvlist_t *poolconfig = NULL;
|
||||
|
||||
is_force = force;
|
||||
|
||||
/*
|
||||
@@ -1098,9 +857,6 @@ make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
|
||||
if ((newroot = construct_spec(argc, argv)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (zhp && ((poolconfig = zpool_get_config(zhp, NULL)) == NULL))
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Validate each device to make sure that its not shared with another
|
||||
* subsystem. We do this even if 'force' is set, because there are some
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -39,7 +39,7 @@ extern "C" {
|
||||
|
||||
#if defined(__STDC__)
|
||||
#if __STDC_VERSION__ - 0 >= 199901L
|
||||
extern void __assert(const char *, const char *, int);
|
||||
extern void __assert_c99(const char *, const char *, int, const char *);
|
||||
#else
|
||||
extern void __assert(const char *, const char *, int);
|
||||
#endif /* __STDC_VERSION__ - 0 >= 199901L */
|
||||
@@ -70,7 +70,8 @@ extern void _assert();
|
||||
|
||||
#if defined(__STDC__)
|
||||
#if __STDC_VERSION__ - 0 >= 199901L
|
||||
#define assert(EX) (void)((EX) || (__assert(#EX, __FILE__, __LINE__), 0))
|
||||
#define assert(EX) (void)((EX) || \
|
||||
(__assert_c99(#EX, __FILE__, __LINE__, __func__), 0))
|
||||
#else
|
||||
#define assert(EX) (void)((EX) || (__assert(#EX, __FILE__, __LINE__), 0))
|
||||
#endif /* __STDC_VERSION__ - 0 >= 199901L */
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -19,10 +20,11 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
/* Libintl is a library of advanced internationalization functions. */
|
||||
|
||||
#ifndef _LIBINTL_H
|
||||
#define _LIBINTL_H
|
||||
@@ -61,9 +63,6 @@ typedef long wchar_t;
|
||||
|
||||
#define TEXTDOMAINMAX 256
|
||||
|
||||
#define __GNU_GETTEXT_SUPPORTED_REVISION(m) \
|
||||
((((m) == 0) || ((m) == 1)) ? 1 : -1)
|
||||
|
||||
#ifdef __STDC__
|
||||
extern char *dcgettext(const char *, const char *, const int);
|
||||
extern char *dgettext(const char *, const char *);
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -18,9 +19,8 @@
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -81,12 +81,12 @@ typedef lwp_cond_t cond_t;
|
||||
* Because we have to deal with C++, we cannot redefine this one as that one.
|
||||
*/
|
||||
typedef struct _rwlock {
|
||||
int32_t readers; /* rwstate word */
|
||||
int32_t readers; /* -1 == writer else # of readers */
|
||||
uint16_t type;
|
||||
uint16_t magic;
|
||||
mutex_t mutex; /* used with process-shared rwlocks */
|
||||
cond_t readercv; /* used only to indicate ownership */
|
||||
cond_t writercv; /* used only to indicate ownership */
|
||||
mutex_t mutex; /* used to indicate ownership */
|
||||
cond_t readercv; /* unused */
|
||||
cond_t writercv; /* unused */
|
||||
} rwlock_t;
|
||||
|
||||
#ifdef __STDC__
|
||||
@@ -111,7 +111,6 @@ int cond_signal(cond_t *);
|
||||
int cond_broadcast(cond_t *);
|
||||
int mutex_init(mutex_t *, int, void *);
|
||||
int mutex_destroy(mutex_t *);
|
||||
int mutex_consistent(mutex_t *);
|
||||
int mutex_lock(mutex_t *);
|
||||
int mutex_trylock(mutex_t *);
|
||||
int mutex_unlock(mutex_t *);
|
||||
@@ -153,7 +152,6 @@ int cond_signal();
|
||||
int cond_broadcast();
|
||||
int mutex_init();
|
||||
int mutex_destroy();
|
||||
int mutex_consistent();
|
||||
int mutex_lock();
|
||||
int mutex_trylock();
|
||||
int mutex_unlock();
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <pthread_np.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
@@ -53,7 +52,6 @@ typedef pthread_rwlock_t rwlock_t;
|
||||
#define mutex_lock(l) pthread_mutex_lock(l)
|
||||
#define mutex_trylock(l) pthread_mutex_trylock(l)
|
||||
#define mutex_unlock(l) pthread_mutex_unlock(l)
|
||||
#define mutex_owned(l) pthread_mutex_isowned_np(l)
|
||||
#define rwlock_init(l,f,a) pthread_rwlock_init(l,NULL)
|
||||
#define rwlock_destroy(l) pthread_rwlock_destroy(l)
|
||||
#define rw_rdlock(l) pthread_rwlock_rdlock(l)
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -19,13 +20,12 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#include "libnvpair.h"
|
||||
@@ -137,12 +137,6 @@ nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth)
|
||||
(void) fprintf(fp, " 0x%llx", (u_longlong_t)val);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_DOUBLE: {
|
||||
double val;
|
||||
(void) nvpair_value_double(nvp, &val);
|
||||
(void) fprintf(fp, " 0x%llf", val);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_STRING: {
|
||||
char *val;
|
||||
(void) nvpair_value_string(nvp, &val);
|
||||
@@ -270,348 +264,3 @@ nvlist_print(FILE *fp, nvlist_t *nvl)
|
||||
{
|
||||
nvlist_print_with_indent(fp, nvl, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if string 'value' matches 'nvp' value. The 'value' string is
|
||||
* converted, depending on the type of 'nvp', prior to match. For numeric
|
||||
* types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
|
||||
* is an array type, 'ai' is the index into the array against which we are
|
||||
* checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
|
||||
* in a regex_t compilation of value in 'value_regex' to trigger regular
|
||||
* expression string match instead of simple strcmp().
|
||||
*
|
||||
* Return 1 on match, 0 on no-match, and -1 on error. If the error is
|
||||
* related to value syntax error and 'ep' is non-NULL, *ep will point into
|
||||
* the 'value' string at the location where the error exists.
|
||||
*
|
||||
* NOTE: It may be possible to move the non-regex_t version of this into
|
||||
* common code used by library/kernel/boot.
|
||||
*/
|
||||
int
|
||||
nvpair_value_match_regex(nvpair_t *nvp, int ai,
|
||||
char *value, regex_t *value_regex, char **ep)
|
||||
{
|
||||
char *evalue;
|
||||
uint_t a_len;
|
||||
int sr;
|
||||
|
||||
if (ep)
|
||||
*ep = NULL;
|
||||
|
||||
if ((nvp == NULL) || (value == NULL))
|
||||
return (-1); /* error fail match - invalid args */
|
||||
|
||||
/* make sure array and index combination make sense */
|
||||
if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
|
||||
(!nvpair_type_is_array(nvp) && (ai >= 0)))
|
||||
return (-1); /* error fail match - bad index */
|
||||
|
||||
/* non-string values should be single 'chunk' */
|
||||
if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
|
||||
(nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
|
||||
value += strspn(value, " \t");
|
||||
evalue = value + strcspn(value, " \t");
|
||||
if (*evalue) {
|
||||
if (ep)
|
||||
*ep = evalue;
|
||||
return (-1); /* error fail match - syntax */
|
||||
}
|
||||
}
|
||||
|
||||
sr = EOF;
|
||||
switch (nvpair_type(nvp)) {
|
||||
case DATA_TYPE_STRING: {
|
||||
char *val;
|
||||
|
||||
/* check string value for match */
|
||||
if (nvpair_value_string(nvp, &val) == 0) {
|
||||
if (value_regex) {
|
||||
if (regexec(value_regex, val,
|
||||
(size_t)0, NULL, 0) == 0)
|
||||
return (1); /* match */
|
||||
} else {
|
||||
if (strcmp(value, val) == 0)
|
||||
return (1); /* match */
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_STRING_ARRAY: {
|
||||
char **val_array;
|
||||
|
||||
/* check indexed string value of array for match */
|
||||
if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len)) {
|
||||
if (value_regex) {
|
||||
if (regexec(value_regex, val_array[ai],
|
||||
(size_t)0, NULL, 0) == 0)
|
||||
return (1);
|
||||
} else {
|
||||
if (strcmp(value, val_array[ai]) == 0)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_BYTE: {
|
||||
uchar_t val, val_arg;
|
||||
|
||||
/* scanf uchar_t from value and check for match */
|
||||
sr = sscanf(value, "%c", &val_arg);
|
||||
if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_BYTE_ARRAY: {
|
||||
uchar_t *val_array, val_arg;
|
||||
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%c", &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT8: {
|
||||
int8_t val, val_arg;
|
||||
|
||||
/* scanf int8_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi8, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int8(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT8_ARRAY: {
|
||||
int8_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi8, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT8: {
|
||||
uint8_t val, val_arg;
|
||||
|
||||
/* scanf uint8_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint8(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT8_ARRAY: {
|
||||
uint8_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT16: {
|
||||
int16_t val, val_arg;
|
||||
|
||||
/* scanf int16_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi16, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int16(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT16_ARRAY: {
|
||||
int16_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi16, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT16: {
|
||||
uint16_t val, val_arg;
|
||||
|
||||
/* scanf uint16_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint16(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT16_ARRAY: {
|
||||
uint16_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT32: {
|
||||
int32_t val, val_arg;
|
||||
|
||||
/* scanf int32_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi32, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int32(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT32_ARRAY: {
|
||||
int32_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi32, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT32: {
|
||||
uint32_t val, val_arg;
|
||||
|
||||
/* scanf uint32_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint32(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT32_ARRAY: {
|
||||
uint32_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT64: {
|
||||
int64_t val, val_arg;
|
||||
|
||||
/* scanf int64_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi64, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int64(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT64_ARRAY: {
|
||||
int64_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi64, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT64: {
|
||||
uint64_t val_arg, val;
|
||||
|
||||
/* scanf uint64_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint64(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT64_ARRAY: {
|
||||
uint64_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_BOOLEAN_VALUE: {
|
||||
boolean_t val, val_arg;
|
||||
|
||||
/* scanf boolean_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi32, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_boolean_value(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_BOOLEAN_ARRAY: {
|
||||
boolean_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi32, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_boolean_array(nvp,
|
||||
&val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_HRTIME:
|
||||
case DATA_TYPE_NVLIST:
|
||||
case DATA_TYPE_NVLIST_ARRAY:
|
||||
case DATA_TYPE_BOOLEAN:
|
||||
case DATA_TYPE_DOUBLE:
|
||||
case DATA_TYPE_UNKNOWN:
|
||||
default:
|
||||
/*
|
||||
* unknown/unsupported data type
|
||||
*/
|
||||
return (-1); /* error fail match */
|
||||
}
|
||||
|
||||
/*
|
||||
* check to see if sscanf failed conversion, return approximate
|
||||
* pointer to problem
|
||||
*/
|
||||
if (sr != 1) {
|
||||
if (ep)
|
||||
*ep = value;
|
||||
return (-1); /* error fail match - syntax */
|
||||
}
|
||||
|
||||
return (0); /* fail match */
|
||||
}
|
||||
|
||||
int
|
||||
nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
|
||||
{
|
||||
return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -19,7 +20,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -31,15 +32,12 @@
|
||||
#include <sys/nvpair.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <regex.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void nvlist_print(FILE *, nvlist_t *);
|
||||
int nvpair_value_match(nvpair_t *, int, char *, char **);
|
||||
int nvpair_value_match_regex(nvpair_t *, int, char *, regex_t *, char **);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -19,13 +20,15 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _LIBUUTIL_H
|
||||
#define _LIBUUTIL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <solaris.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
@@ -146,7 +149,6 @@ extern int uu_open_tmp(const char *dir, uint_t uflags);
|
||||
/*PRINTFLIKE1*/
|
||||
extern char *uu_msprintf(const char *format, ...);
|
||||
extern void *uu_zalloc(size_t);
|
||||
extern char *uu_strdup(const char *);
|
||||
extern void uu_free(void *);
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -20,7 +21,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -29,6 +30,16 @@
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <solaris.h>
|
||||
|
||||
/*
|
||||
* We don't bind to the internal libc interfaces if this is a
|
||||
* native build.
|
||||
*/
|
||||
#ifndef NATIVE_BUILD
|
||||
#include "c_synonyms.h"
|
||||
#endif
|
||||
|
||||
#include <libuutil.h>
|
||||
#include <libuutil_impl.h>
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -19,10 +20,12 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include "libuutil_common.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
@@ -51,22 +54,6 @@ uu_free(void *p)
|
||||
free(p);
|
||||
}
|
||||
|
||||
char *
|
||||
uu_strdup(const char *str)
|
||||
{
|
||||
char *buf = NULL;
|
||||
|
||||
if (str != NULL) {
|
||||
size_t sz;
|
||||
|
||||
sz = strlen(str) + 1;
|
||||
buf = uu_zalloc(sz);
|
||||
if (buf != NULL)
|
||||
(void) memcpy(buf, str, sz);
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
char *
|
||||
uu_msprintf(const char *format, ...)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -120,8 +120,7 @@ uu_avl_pool_destroy(uu_avl_pool_t *pp)
|
||||
UU_PTR_ENCODE(&pp->uap_null_avl)) {
|
||||
uu_panic("uu_avl_pool_destroy: Pool \"%.*s\" (%p) has "
|
||||
"outstanding avls, or is corrupt.\n",
|
||||
(int)sizeof (pp->uap_name), pp->uap_name,
|
||||
(void *)pp);
|
||||
sizeof (pp->uap_name), pp->uap_name, pp);
|
||||
}
|
||||
}
|
||||
(void) pthread_mutex_lock(&uu_apool_list_lock);
|
||||
@@ -143,14 +142,14 @@ uu_avl_node_init(void *base, uu_avl_node_t *np, uu_avl_pool_t *pp)
|
||||
if (offset + sizeof (*np) > pp->uap_objsize) {
|
||||
uu_panic("uu_avl_node_init(%p, %p, %p (\"%s\")): "
|
||||
"offset %ld doesn't fit in object (size %ld)\n",
|
||||
base, (void *)np, (void *)pp, pp->uap_name,
|
||||
(long)offset, (long)pp->uap_objsize);
|
||||
base, np, pp, pp->uap_name, offset,
|
||||
pp->uap_objsize);
|
||||
}
|
||||
if (offset != pp->uap_nodeoffset) {
|
||||
uu_panic("uu_avl_node_init(%p, %p, %p (\"%s\")): "
|
||||
"offset %ld doesn't match pool's offset (%ld)\n",
|
||||
base, (void *)np, (void *)pp, pp->uap_name,
|
||||
(long)offset, (long)pp->uap_objsize);
|
||||
base, np, pp, pp->uap_name, offset,
|
||||
pp->uap_objsize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,12 +166,12 @@ uu_avl_node_fini(void *base, uu_avl_node_t *np, uu_avl_pool_t *pp)
|
||||
if (na[0] == DEAD_MARKER && na[1] == DEAD_MARKER) {
|
||||
uu_panic("uu_avl_node_fini(%p, %p, %p (\"%s\")): "
|
||||
"node already finied\n",
|
||||
base, (void *)np, (void *)pp, pp->uap_name);
|
||||
base, np, pp, pp->uap_name);
|
||||
}
|
||||
if (na[0] != POOL_TO_MARKER(pp) || na[1] != 0) {
|
||||
uu_panic("uu_avl_node_fini(%p, %p, %p (\"%s\")): "
|
||||
"node corrupt, in tree, or in different pool\n",
|
||||
base, (void *)np, (void *)pp, pp->uap_name);
|
||||
base, np, pp, pp->uap_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,13 +251,12 @@ uu_avl_destroy(uu_avl_t *ap)
|
||||
|
||||
if (ap->ua_debug) {
|
||||
if (avl_numnodes(&ap->ua_tree) != 0) {
|
||||
uu_panic("uu_avl_destroy(%p): tree not empty\n",
|
||||
(void *)ap);
|
||||
uu_panic("uu_avl_destroy(%p): tree not empty\n", ap);
|
||||
}
|
||||
if (ap->ua_null_walk.uaw_next != &ap->ua_null_walk ||
|
||||
ap->ua_null_walk.uaw_prev != &ap->ua_null_walk) {
|
||||
uu_panic("uu_avl_destroy(%p): outstanding walkers\n",
|
||||
(void *)ap);
|
||||
ap);
|
||||
}
|
||||
}
|
||||
(void) pthread_mutex_lock(&pp->uap_lock);
|
||||
@@ -443,7 +441,7 @@ uu_avl_remove(uu_avl_t *ap, void *elem)
|
||||
(void) _avl_walk_advance(wp, ap);
|
||||
} else if (wp->uaw_next_result != NULL) {
|
||||
uu_panic("uu_avl_remove(%p, %p): active non-robust "
|
||||
"walker\n", (void *)ap, elem);
|
||||
"walker\n", ap, elem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,19 +497,19 @@ uu_avl_insert(uu_avl_t *ap, void *elem, uu_avl_index_t idx)
|
||||
if (na[1] != 0)
|
||||
uu_panic("uu_avl_insert(%p, %p, %p): node already "
|
||||
"in tree, or corrupt\n",
|
||||
(void *)ap, elem, (void *)idx);
|
||||
ap, elem, idx);
|
||||
if (na[0] == 0)
|
||||
uu_panic("uu_avl_insert(%p, %p, %p): node not "
|
||||
"initialized\n",
|
||||
(void *)ap, elem, (void *)idx);
|
||||
ap, elem, idx);
|
||||
if (na[0] != POOL_TO_MARKER(pp))
|
||||
uu_panic("uu_avl_insert(%p, %p, %p): node from "
|
||||
"other pool, or corrupt\n",
|
||||
(void *)ap, elem, (void *)idx);
|
||||
ap, elem, idx);
|
||||
|
||||
if (!INDEX_VALID(ap, idx))
|
||||
uu_panic("uu_avl_insert(%p, %p, %p): %s\n",
|
||||
(void *)ap, elem, (void *)idx,
|
||||
ap, elem, idx,
|
||||
INDEX_CHECK(idx)? "outdated index" :
|
||||
"invalid index");
|
||||
|
||||
@@ -528,8 +526,8 @@ uu_avl_nearest_next(uu_avl_t *ap, uu_avl_index_t idx)
|
||||
{
|
||||
if (ap->ua_debug && !INDEX_VALID(ap, idx))
|
||||
uu_panic("uu_avl_nearest_next(%p, %p): %s\n",
|
||||
(void *)ap, (void *)idx, INDEX_CHECK(idx)?
|
||||
"outdated index" : "invalid index");
|
||||
ap, idx, INDEX_CHECK(idx)? "outdated index" :
|
||||
"invalid index");
|
||||
return (avl_nearest(&ap->ua_tree, INDEX_DECODE(idx), AVL_AFTER));
|
||||
}
|
||||
|
||||
@@ -538,8 +536,8 @@ uu_avl_nearest_prev(uu_avl_t *ap, uu_avl_index_t idx)
|
||||
{
|
||||
if (ap->ua_debug && !INDEX_VALID(ap, idx))
|
||||
uu_panic("uu_avl_nearest_prev(%p, %p): %s\n",
|
||||
(void *)ap, (void *)idx, INDEX_CHECK(idx)?
|
||||
"outdated index" : "invalid index");
|
||||
ap, idx, INDEX_CHECK(idx)? "outdated index" :
|
||||
"invalid index");
|
||||
return (avl_nearest(&ap->ua_tree, INDEX_DECODE(idx), AVL_BEFORE));
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#define FACILITY_FMT "%s (%s): "
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -19,7 +20,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -116,8 +117,7 @@ uu_list_pool_destroy(uu_list_pool_t *pp)
|
||||
UU_PTR_ENCODE(&pp->ulp_null_list)) {
|
||||
uu_panic("uu_list_pool_destroy: Pool \"%.*s\" (%p) has "
|
||||
"outstanding lists, or is corrupt.\n",
|
||||
(int)sizeof (pp->ulp_name), pp->ulp_name,
|
||||
(void *)pp);
|
||||
sizeof (pp->ulp_name), pp->ulp_name, pp);
|
||||
}
|
||||
}
|
||||
(void) pthread_mutex_lock(&uu_lpool_list_lock);
|
||||
@@ -139,14 +139,14 @@ uu_list_node_init(void *base, uu_list_node_t *np_arg, uu_list_pool_t *pp)
|
||||
if (offset + sizeof (*np) > pp->ulp_objsize) {
|
||||
uu_panic("uu_list_node_init(%p, %p, %p (\"%s\")): "
|
||||
"offset %ld doesn't fit in object (size %ld)\n",
|
||||
base, (void *)np, (void *)pp, pp->ulp_name,
|
||||
(long)offset, (long)pp->ulp_objsize);
|
||||
base, np, pp, pp->ulp_name, offset,
|
||||
pp->ulp_objsize);
|
||||
}
|
||||
if (offset != pp->ulp_nodeoffset) {
|
||||
uu_panic("uu_list_node_init(%p, %p, %p (\"%s\")): "
|
||||
"offset %ld doesn't match pool's offset (%ld)\n",
|
||||
base, (void *)np, (void *)pp, pp->ulp_name,
|
||||
(long)offset, (long)pp->ulp_objsize);
|
||||
base, np, pp, pp->ulp_name, offset,
|
||||
pp->ulp_objsize);
|
||||
}
|
||||
}
|
||||
np->uln_next = POOL_TO_MARKER(pp);
|
||||
@@ -163,13 +163,13 @@ uu_list_node_fini(void *base, uu_list_node_t *np_arg, uu_list_pool_t *pp)
|
||||
np->uln_prev == NULL) {
|
||||
uu_panic("uu_list_node_fini(%p, %p, %p (\"%s\")): "
|
||||
"node already finied\n",
|
||||
base, (void *)np_arg, (void *)pp, pp->ulp_name);
|
||||
base, np_arg, pp, pp->ulp_name);
|
||||
}
|
||||
if (np->uln_next != POOL_TO_MARKER(pp) ||
|
||||
np->uln_prev != NULL) {
|
||||
uu_panic("uu_list_node_fini(%p, %p, %p (\"%s\")): "
|
||||
"node corrupt or on list\n",
|
||||
base, (void *)np_arg, (void *)pp, pp->ulp_name);
|
||||
base, np_arg, pp, pp->ulp_name);
|
||||
}
|
||||
}
|
||||
np->uln_next = NULL;
|
||||
@@ -190,7 +190,7 @@ uu_list_create(uu_list_pool_t *pp, void *parent, uint32_t flags)
|
||||
if (pp->ulp_debug)
|
||||
uu_panic("uu_list_create(%p, ...): requested "
|
||||
"UU_LIST_SORTED, but pool has no comparison func\n",
|
||||
(void *)pp);
|
||||
pp);
|
||||
uu_set_error(UU_ERROR_NOT_SUPPORTED);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -236,16 +236,16 @@ uu_list_destroy(uu_list_t *lp)
|
||||
if (lp->ul_null_node.uln_next != &lp->ul_null_node ||
|
||||
lp->ul_null_node.uln_prev != &lp->ul_null_node) {
|
||||
uu_panic("uu_list_destroy(%p): list not empty\n",
|
||||
(void *)lp);
|
||||
lp);
|
||||
}
|
||||
if (lp->ul_numnodes != 0) {
|
||||
uu_panic("uu_list_destroy(%p): numnodes is nonzero, "
|
||||
"but list is empty\n", (void *)lp);
|
||||
"but list is empty\n", lp);
|
||||
}
|
||||
if (lp->ul_null_walk.ulw_next != &lp->ul_null_walk ||
|
||||
lp->ul_null_walk.ulw_prev != &lp->ul_null_walk) {
|
||||
uu_panic("uu_list_destroy(%p): outstanding walkers\n",
|
||||
(void *)lp);
|
||||
lp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,14 +266,13 @@ list_insert(uu_list_t *lp, uu_list_node_impl_t *np, uu_list_node_impl_t *prev,
|
||||
if (lp->ul_debug) {
|
||||
if (next->uln_prev != prev || prev->uln_next != next)
|
||||
uu_panic("insert(%p): internal error: %p and %p not "
|
||||
"neighbors\n", (void *)lp, (void *)next,
|
||||
(void *)prev);
|
||||
"neighbors\n", lp, next, prev);
|
||||
|
||||
if (np->uln_next != POOL_TO_MARKER(lp->ul_pool) ||
|
||||
np->uln_prev != NULL) {
|
||||
uu_panic("insert(%p): elem %p node %p corrupt, "
|
||||
"not initialized, or already in a list.\n",
|
||||
(void *)lp, NODE_TO_ELEM(lp, np), (void *)np);
|
||||
lp, NODE_TO_ELEM(lp, np), np);
|
||||
}
|
||||
/*
|
||||
* invalidate outstanding uu_list_index_ts.
|
||||
@@ -300,12 +299,12 @@ uu_list_insert(uu_list_t *lp, void *elem, uu_list_index_t idx)
|
||||
if (lp->ul_debug) {
|
||||
if (!INDEX_VALID(lp, idx))
|
||||
uu_panic("uu_list_insert(%p, %p, %p): %s\n",
|
||||
(void *)lp, elem, (void *)idx,
|
||||
lp, elem, idx,
|
||||
INDEX_CHECK(idx)? "outdated index" :
|
||||
"invalid index");
|
||||
if (np->uln_prev == NULL)
|
||||
uu_panic("uu_list_insert(%p, %p, %p): out-of-date "
|
||||
"index\n", (void *)lp, elem, (void *)idx);
|
||||
"index\n", lp, elem, idx);
|
||||
}
|
||||
|
||||
list_insert(lp, ELEM_TO_NODE(lp, elem), np->uln_prev, np);
|
||||
@@ -355,12 +354,11 @@ uu_list_nearest_next(uu_list_t *lp, uu_list_index_t idx)
|
||||
if (lp->ul_debug) {
|
||||
if (!INDEX_VALID(lp, idx))
|
||||
uu_panic("uu_list_nearest_next(%p, %p): %s\n",
|
||||
(void *)lp, (void *)idx,
|
||||
INDEX_CHECK(idx)? "outdated index" :
|
||||
lp, idx, INDEX_CHECK(idx)? "outdated index" :
|
||||
"invalid index");
|
||||
if (np->uln_prev == NULL)
|
||||
uu_panic("uu_list_nearest_next(%p, %p): out-of-date "
|
||||
"index\n", (void *)lp, (void *)idx);
|
||||
"index\n", lp, idx);
|
||||
}
|
||||
|
||||
if (np == &lp->ul_null_node)
|
||||
@@ -380,11 +378,11 @@ uu_list_nearest_prev(uu_list_t *lp, uu_list_index_t idx)
|
||||
if (lp->ul_debug) {
|
||||
if (!INDEX_VALID(lp, idx))
|
||||
uu_panic("uu_list_nearest_prev(%p, %p): %s\n",
|
||||
(void *)lp, (void *)idx, INDEX_CHECK(idx)?
|
||||
"outdated index" : "invalid index");
|
||||
lp, idx, INDEX_CHECK(idx)? "outdated index" :
|
||||
"invalid index");
|
||||
if (np->uln_prev == NULL)
|
||||
uu_panic("uu_list_nearest_prev(%p, %p): out-of-date "
|
||||
"index\n", (void *)lp, (void *)idx);
|
||||
"index\n", lp, idx);
|
||||
}
|
||||
|
||||
if ((np = np->uln_prev) == &lp->ul_null_node)
|
||||
@@ -411,11 +409,6 @@ list_walk_init(uu_list_walk_t *wp, uu_list_t *lp, uint32_t flags)
|
||||
wp->ulw_next_result = lp->ul_null_node.uln_prev;
|
||||
|
||||
if (lp->ul_debug || robust) {
|
||||
/*
|
||||
* Add this walker to the list's list of walkers so
|
||||
* uu_list_remove() can advance us if somebody tries to
|
||||
* remove ulw_next_result.
|
||||
*/
|
||||
wp->ulw_next = next = &lp->ul_null_walk;
|
||||
wp->ulw_prev = prev = next->ulw_prev;
|
||||
next->ulw_prev = wp;
|
||||
@@ -545,7 +538,7 @@ uu_list_remove(uu_list_t *lp, void *elem)
|
||||
if (lp->ul_debug) {
|
||||
if (np->uln_prev == NULL)
|
||||
uu_panic("uu_list_remove(%p, %p): elem not on list\n",
|
||||
(void *)lp, elem);
|
||||
lp, elem);
|
||||
/*
|
||||
* invalidate outstanding uu_list_index_ts.
|
||||
*/
|
||||
@@ -563,7 +556,7 @@ uu_list_remove(uu_list_t *lp, void *elem)
|
||||
(void) list_walk_advance(wp, lp);
|
||||
} else if (wp->ulw_next_result != NULL) {
|
||||
uu_panic("uu_list_remove(%p, %p): active non-robust "
|
||||
"walker\n", (void *)lp, elem);
|
||||
"walker\n", lp, elem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,8 +578,8 @@ uu_list_teardown(uu_list_t *lp, void **cookie)
|
||||
* XXX: disable list modification until list is empty
|
||||
*/
|
||||
if (lp->ul_debug && *cookie != NULL)
|
||||
uu_panic("uu_list_teardown(%p, %p): unexpected cookie\n",
|
||||
(void *)lp, (void *)cookie);
|
||||
uu_panic("uu_list_teardown(%p, %p): unexpected cookie\n", lp,
|
||||
cookie);
|
||||
|
||||
ep = uu_list_first(lp);
|
||||
if (ep)
|
||||
@@ -606,12 +599,12 @@ uu_list_insert_before(uu_list_t *lp, void *target, void *elem)
|
||||
if (np->uln_prev == NULL)
|
||||
uu_panic("uu_list_insert_before(%p, %p, %p): %p is "
|
||||
"not currently on a list\n",
|
||||
(void *)lp, target, elem, target);
|
||||
lp, target, elem, target);
|
||||
}
|
||||
if (lp->ul_sorted) {
|
||||
if (lp->ul_debug)
|
||||
uu_panic("uu_list_insert_before(%p, ...): list is "
|
||||
"UU_LIST_SORTED\n", (void *)lp);
|
||||
"UU_LIST_SORTED\n", lp);
|
||||
uu_set_error(UU_ERROR_NOT_SUPPORTED);
|
||||
return (-1);
|
||||
}
|
||||
@@ -632,12 +625,12 @@ uu_list_insert_after(uu_list_t *lp, void *target, void *elem)
|
||||
if (np->uln_prev == NULL)
|
||||
uu_panic("uu_list_insert_after(%p, %p, %p): %p is "
|
||||
"not currently on a list\n",
|
||||
(void *)lp, target, elem, target);
|
||||
lp, target, elem, target);
|
||||
}
|
||||
if (lp->ul_sorted) {
|
||||
if (lp->ul_debug)
|
||||
uu_panic("uu_list_insert_after(%p, ...): list is "
|
||||
"UU_LIST_SORTED\n", (void *)lp);
|
||||
"UU_LIST_SORTED\n", lp);
|
||||
uu_set_error(UU_ERROR_NOT_SUPPORTED);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@@ -20,20 +20,21 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _LIBZFS_H
|
||||
#define _LIBZFS_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <assert.h>
|
||||
#include <libnvpair.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/varargs.h>
|
||||
#include <sys/fs/zfs.h>
|
||||
#include <sys/avl.h>
|
||||
#include <sys/zfs_ioctl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -46,7 +47,6 @@ extern "C" {
|
||||
#define ZFS_MAXNAMELEN MAXNAMELEN
|
||||
#define ZPOOL_MAXNAMELEN MAXNAMELEN
|
||||
#define ZFS_MAXPROPLEN MAXPATHLEN
|
||||
#define ZPOOL_MAXPROPLEN MAXPATHLEN
|
||||
|
||||
/*
|
||||
* libzfs errors
|
||||
@@ -99,61 +99,9 @@ enum {
|
||||
EZFS_POOL_NOTSUP, /* ops not supported for this type of pool */
|
||||
EZFS_POOL_INVALARG, /* invalid argument for this pool operation */
|
||||
EZFS_NAMETOOLONG, /* dataset name is too long */
|
||||
EZFS_OPENFAILED, /* open of device failed */
|
||||
EZFS_NOCAP, /* couldn't get capacity */
|
||||
EZFS_LABELFAILED, /* write of label failed */
|
||||
EZFS_ISCSISVCUNAVAIL, /* iscsi service unavailable */
|
||||
EZFS_BADWHO, /* invalid permission who */
|
||||
EZFS_BADPERM, /* invalid permission */
|
||||
EZFS_BADPERMSET, /* invalid permission set name */
|
||||
EZFS_NODELEGATION, /* delegated administration is disabled */
|
||||
EZFS_PERMRDONLY, /* pemissions are readonly */
|
||||
EZFS_UNSHARESMBFAILED, /* failed to unshare over smb */
|
||||
EZFS_SHARESMBFAILED, /* failed to share over smb */
|
||||
EZFS_BADCACHE, /* bad cache file */
|
||||
EZFS_ISL2CACHE, /* device is for the level 2 ARC */
|
||||
EZFS_VDEVNOTSUP, /* unsupported vdev type */
|
||||
EZFS_NOTSUP, /* ops not supported on this dataset */
|
||||
EZFS_ACTIVE_SPARE, /* pool has active shared spare devices */
|
||||
EZFS_UNKNOWN
|
||||
};
|
||||
|
||||
/*
|
||||
* The following data structures are all part
|
||||
* of the zfs_allow_t data structure which is
|
||||
* used for printing 'allow' permissions.
|
||||
* It is a linked list of zfs_allow_t's which
|
||||
* then contain avl tree's for user/group/sets/...
|
||||
* and each one of the entries in those trees have
|
||||
* avl tree's for the permissions they belong to and
|
||||
* whether they are local,descendent or local+descendent
|
||||
* permissions. The AVL trees are used primarily for
|
||||
* sorting purposes, but also so that we can quickly find
|
||||
* a given user and or permission.
|
||||
*/
|
||||
typedef struct zfs_perm_node {
|
||||
avl_node_t z_node;
|
||||
char z_pname[MAXPATHLEN];
|
||||
} zfs_perm_node_t;
|
||||
|
||||
typedef struct zfs_allow_node {
|
||||
avl_node_t z_node;
|
||||
char z_key[MAXPATHLEN]; /* name, such as joe */
|
||||
avl_tree_t z_localdescend; /* local+descendent perms */
|
||||
avl_tree_t z_local; /* local permissions */
|
||||
avl_tree_t z_descend; /* descendent permissions */
|
||||
} zfs_allow_node_t;
|
||||
|
||||
typedef struct zfs_allow {
|
||||
struct zfs_allow *z_next;
|
||||
char z_setpoint[MAXPATHLEN];
|
||||
avl_tree_t z_sets;
|
||||
avl_tree_t z_crperms;
|
||||
avl_tree_t z_user;
|
||||
avl_tree_t z_group;
|
||||
avl_tree_t z_everyone;
|
||||
} zfs_allow_t;
|
||||
|
||||
/*
|
||||
* Basic handle types
|
||||
*/
|
||||
@@ -183,9 +131,12 @@ extern zpool_handle_t *zpool_open(libzfs_handle_t *, const char *);
|
||||
extern zpool_handle_t *zpool_open_canfail(libzfs_handle_t *, const char *);
|
||||
extern void zpool_close(zpool_handle_t *);
|
||||
extern const char *zpool_get_name(zpool_handle_t *);
|
||||
extern uint64_t zpool_get_guid(zpool_handle_t *);
|
||||
extern uint64_t zpool_get_space_used(zpool_handle_t *);
|
||||
extern uint64_t zpool_get_space_total(zpool_handle_t *);
|
||||
extern int zpool_get_root(zpool_handle_t *, char *, size_t);
|
||||
extern int zpool_get_state(zpool_handle_t *);
|
||||
extern char *zpool_state_to_name(vdev_state_t, vdev_aux_t);
|
||||
extern void zpool_free_handles(libzfs_handle_t *);
|
||||
extern uint64_t zpool_get_version(zpool_handle_t *);
|
||||
|
||||
/*
|
||||
* Iterate over all active pools in the system.
|
||||
@@ -197,7 +148,7 @@ extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *);
|
||||
* Functions to create and destroy pools
|
||||
*/
|
||||
extern int zpool_create(libzfs_handle_t *, const char *, nvlist_t *,
|
||||
nvlist_t *, nvlist_t *);
|
||||
const char *);
|
||||
extern int zpool_destroy(zpool_handle_t *);
|
||||
extern int zpool_add(zpool_handle_t *, nvlist_t *);
|
||||
|
||||
@@ -205,33 +156,22 @@ extern int zpool_add(zpool_handle_t *, nvlist_t *);
|
||||
* Functions to manipulate pool and vdev state
|
||||
*/
|
||||
extern int zpool_scrub(zpool_handle_t *, pool_scrub_type_t);
|
||||
extern int zpool_clear(zpool_handle_t *, const char *);
|
||||
|
||||
extern int zpool_vdev_online(zpool_handle_t *, const char *, int,
|
||||
vdev_state_t *);
|
||||
extern int zpool_vdev_offline(zpool_handle_t *, const char *, boolean_t);
|
||||
extern int zpool_vdev_attach(zpool_handle_t *, const char *,
|
||||
const char *, nvlist_t *, int);
|
||||
extern int zpool_vdev_online(zpool_handle_t *, const char *);
|
||||
extern int zpool_vdev_offline(zpool_handle_t *, const char *, int);
|
||||
extern int zpool_vdev_attach(zpool_handle_t *, const char *, const char *,
|
||||
nvlist_t *, int);
|
||||
extern int zpool_vdev_detach(zpool_handle_t *, const char *);
|
||||
extern int zpool_vdev_remove(zpool_handle_t *, const char *);
|
||||
|
||||
extern int zpool_vdev_fault(zpool_handle_t *, uint64_t);
|
||||
extern int zpool_vdev_degrade(zpool_handle_t *, uint64_t);
|
||||
extern int zpool_vdev_clear(zpool_handle_t *, uint64_t);
|
||||
|
||||
extern nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *,
|
||||
boolean_t *, boolean_t *);
|
||||
extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, char *);
|
||||
extern int zpool_clear(zpool_handle_t *, const char *);
|
||||
extern nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *);
|
||||
|
||||
/*
|
||||
* Functions to manage pool properties
|
||||
*/
|
||||
extern int zpool_set_prop(zpool_handle_t *, const char *, const char *);
|
||||
extern int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *,
|
||||
size_t proplen, zprop_source_t *);
|
||||
extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t,
|
||||
zprop_source_t *);
|
||||
|
||||
extern int zpool_get_prop(zpool_handle_t *, zfs_prop_t, char *,
|
||||
size_t proplen, zfs_source_t *);
|
||||
extern const char *zpool_prop_to_name(zpool_prop_t);
|
||||
extern const char *zpool_prop_values(zpool_prop_t);
|
||||
|
||||
@@ -254,11 +194,6 @@ typedef enum {
|
||||
ZPOOL_STATUS_FAILING_DEV, /* device experiencing errors */
|
||||
ZPOOL_STATUS_VERSION_NEWER, /* newer on-disk version */
|
||||
ZPOOL_STATUS_HOSTID_MISMATCH, /* last accessed by another system */
|
||||
ZPOOL_STATUS_IO_FAILURE_WAIT, /* failed I/O, failmode 'wait' */
|
||||
ZPOOL_STATUS_IO_FAILURE_CONTINUE, /* failed I/O, failmode 'continue' */
|
||||
ZPOOL_STATUS_FAULTED_DEV_R, /* faulted device with replicas */
|
||||
ZPOOL_STATUS_FAULTED_DEV_NR, /* faulted device with no replicas */
|
||||
ZPOOL_STATUS_BAD_LOG, /* cannot read log chain(s) */
|
||||
|
||||
/*
|
||||
* The following are not faults per se, but still an error possibly
|
||||
@@ -288,39 +223,26 @@ extern int zpool_get_errlog(zpool_handle_t *, nvlist_t **);
|
||||
/*
|
||||
* Import and export functions
|
||||
*/
|
||||
extern int zpool_export(zpool_handle_t *, boolean_t);
|
||||
extern int zpool_export(zpool_handle_t *);
|
||||
extern int zpool_import(libzfs_handle_t *, nvlist_t *, const char *,
|
||||
char *altroot);
|
||||
extern int zpool_import_props(libzfs_handle_t *, nvlist_t *, const char *,
|
||||
nvlist_t *, boolean_t);
|
||||
const char *);
|
||||
|
||||
/*
|
||||
* Search for pools to import
|
||||
*/
|
||||
extern nvlist_t *zpool_find_import(libzfs_handle_t *, int, char **);
|
||||
extern nvlist_t *zpool_find_import_cached(libzfs_handle_t *, const char *,
|
||||
char *, uint64_t);
|
||||
extern nvlist_t *zpool_find_import_byname(libzfs_handle_t *, int, char **,
|
||||
char *);
|
||||
extern nvlist_t *zpool_find_import_byguid(libzfs_handle_t *, int, char **,
|
||||
uint64_t);
|
||||
extern nvlist_t *zpool_find_import_activeok(libzfs_handle_t *, int, char **);
|
||||
|
||||
/*
|
||||
* Miscellaneous pool functions
|
||||
*/
|
||||
struct zfs_cmd;
|
||||
|
||||
extern char *zpool_vdev_name(libzfs_handle_t *, zpool_handle_t *, nvlist_t *);
|
||||
extern int zpool_upgrade(zpool_handle_t *, uint64_t);
|
||||
extern int zpool_upgrade(zpool_handle_t *);
|
||||
extern int zpool_get_history(zpool_handle_t *, nvlist_t **);
|
||||
extern void zpool_set_history_str(const char *subcommand, int argc,
|
||||
char **argv, char *history_str);
|
||||
extern int zpool_stage_history(libzfs_handle_t *, const char *);
|
||||
extern void zpool_log_history(libzfs_handle_t *, int, char **, const char *,
|
||||
boolean_t, boolean_t);
|
||||
extern void zpool_obj_to_path(zpool_handle_t *, uint64_t, uint64_t, char *,
|
||||
size_t len);
|
||||
extern int zfs_ioctl(libzfs_handle_t *, unsigned long, struct zfs_cmd *);
|
||||
extern int zpool_get_physpath(zpool_handle_t *, char *);
|
||||
|
||||
/*
|
||||
* Basic handle manipulations. These functions do not create or destroy the
|
||||
* underlying datasets, only the references to them.
|
||||
@@ -329,84 +251,65 @@ extern zfs_handle_t *zfs_open(libzfs_handle_t *, const char *, int);
|
||||
extern void zfs_close(zfs_handle_t *);
|
||||
extern zfs_type_t zfs_get_type(const zfs_handle_t *);
|
||||
extern const char *zfs_get_name(const zfs_handle_t *);
|
||||
extern zpool_handle_t *zfs_get_pool_handle(const zfs_handle_t *);
|
||||
|
||||
/*
|
||||
* Property management functions. Some functions are shared with the kernel,
|
||||
* and are found in sys/fs/zfs.h.
|
||||
*/
|
||||
|
||||
/*
|
||||
* zfs dataset property management
|
||||
*/
|
||||
extern const char *zfs_prop_default_string(zfs_prop_t);
|
||||
extern uint64_t zfs_prop_default_numeric(zfs_prop_t);
|
||||
extern const char *zfs_prop_column_name(zfs_prop_t);
|
||||
extern boolean_t zfs_prop_align_right(zfs_prop_t);
|
||||
|
||||
extern nvlist_t *zfs_valid_proplist(libzfs_handle_t *, zfs_type_t,
|
||||
nvlist_t *, uint64_t, zfs_handle_t *, const char *);
|
||||
|
||||
extern const char *zfs_prop_to_name(zfs_prop_t);
|
||||
extern int zfs_prop_set(zfs_handle_t *, const char *, const char *);
|
||||
extern int zfs_prop_get(zfs_handle_t *, zfs_prop_t, char *, size_t,
|
||||
zprop_source_t *, char *, size_t, boolean_t);
|
||||
zfs_source_t *, char *, size_t, boolean_t);
|
||||
extern int zfs_prop_get_numeric(zfs_handle_t *, zfs_prop_t, uint64_t *,
|
||||
zprop_source_t *, char *, size_t);
|
||||
zfs_source_t *, char *, size_t);
|
||||
extern uint64_t zfs_prop_get_int(zfs_handle_t *, zfs_prop_t);
|
||||
extern const char *zfs_prop_get_string(zfs_handle_t *, zfs_prop_t);
|
||||
extern int zfs_prop_inherit(zfs_handle_t *, const char *);
|
||||
extern const char *zfs_prop_values(zfs_prop_t);
|
||||
extern int zfs_prop_valid_for_type(zfs_prop_t, int);
|
||||
extern const char *zfs_prop_default_string(zfs_prop_t prop);
|
||||
extern uint64_t zfs_prop_default_numeric(zfs_prop_t);
|
||||
extern int zfs_prop_is_string(zfs_prop_t prop);
|
||||
extern nvlist_t *zfs_get_user_props(zfs_handle_t *);
|
||||
extern const char *zfs_prop_column_name(zfs_prop_t);
|
||||
extern boolean_t zfs_prop_align_right(zfs_prop_t);
|
||||
extern void nicebool(int value, char *buf, size_t buflen);
|
||||
|
||||
typedef struct zprop_list {
|
||||
int pl_prop;
|
||||
typedef struct zfs_proplist {
|
||||
zfs_prop_t pl_prop;
|
||||
char *pl_user_prop;
|
||||
struct zprop_list *pl_next;
|
||||
struct zfs_proplist *pl_next;
|
||||
boolean_t pl_all;
|
||||
size_t pl_width;
|
||||
boolean_t pl_fixed;
|
||||
} zprop_list_t;
|
||||
} zfs_proplist_t;
|
||||
|
||||
extern int zfs_expand_proplist(zfs_handle_t *, zprop_list_t **);
|
||||
typedef zfs_proplist_t zpool_proplist_t;
|
||||
|
||||
extern int zfs_get_proplist(libzfs_handle_t *, char *, zfs_proplist_t **);
|
||||
extern int zpool_get_proplist(libzfs_handle_t *, char *, zpool_proplist_t **);
|
||||
extern int zfs_expand_proplist(zfs_handle_t *, zfs_proplist_t **);
|
||||
extern int zpool_expand_proplist(zpool_handle_t *, zpool_proplist_t **);
|
||||
extern void zfs_free_proplist(zfs_proplist_t *);
|
||||
extern nvlist_t *zfs_get_user_props(zfs_handle_t *);
|
||||
|
||||
#define ZFS_MOUNTPOINT_NONE "none"
|
||||
#define ZFS_MOUNTPOINT_LEGACY "legacy"
|
||||
|
||||
/*
|
||||
* zpool property management
|
||||
* Functions for printing properties from zfs/zpool
|
||||
*/
|
||||
extern int zpool_expand_proplist(zpool_handle_t *, zprop_list_t **);
|
||||
extern const char *zpool_prop_default_string(zpool_prop_t);
|
||||
extern uint64_t zpool_prop_default_numeric(zpool_prop_t);
|
||||
extern const char *zpool_prop_column_name(zpool_prop_t);
|
||||
extern boolean_t zpool_prop_align_right(zpool_prop_t);
|
||||
|
||||
/*
|
||||
* Functions shared by zfs and zpool property management.
|
||||
*/
|
||||
extern int zprop_iter(zprop_func func, void *cb, boolean_t show_all,
|
||||
boolean_t ordered, zfs_type_t type);
|
||||
extern int zprop_get_list(libzfs_handle_t *, char *, zprop_list_t **,
|
||||
zfs_type_t);
|
||||
extern void zprop_free_list(zprop_list_t *);
|
||||
|
||||
/*
|
||||
* Functions for printing zfs or zpool properties
|
||||
*/
|
||||
typedef struct zprop_get_cbdata {
|
||||
typedef struct libzfs_get_cbdata {
|
||||
int cb_sources;
|
||||
int cb_columns[4];
|
||||
int cb_colwidths[5];
|
||||
boolean_t cb_scripted;
|
||||
boolean_t cb_literal;
|
||||
boolean_t cb_first;
|
||||
zprop_list_t *cb_proplist;
|
||||
zfs_type_t cb_type;
|
||||
} zprop_get_cbdata_t;
|
||||
zfs_proplist_t *cb_proplist;
|
||||
} libzfs_get_cbdata_t;
|
||||
|
||||
void zprop_print_one_property(const char *, zprop_get_cbdata_t *,
|
||||
const char *, const char *, zprop_source_t, const char *);
|
||||
void libzfs_print_one_property(const char *, libzfs_get_cbdata_t *,
|
||||
const char *, const char *, zfs_source_t, const char *);
|
||||
|
||||
#define GET_COL_NAME 1
|
||||
#define GET_COL_PROPERTY 2
|
||||
@@ -428,61 +331,26 @@ extern int zfs_iter_snapshots(zfs_handle_t *, zfs_iter_f, void *);
|
||||
*/
|
||||
extern int zfs_create(libzfs_handle_t *, const char *, zfs_type_t,
|
||||
nvlist_t *);
|
||||
extern int zfs_create_ancestors(libzfs_handle_t *, const char *);
|
||||
extern int zfs_destroy(zfs_handle_t *);
|
||||
extern int zfs_destroy_snaps(zfs_handle_t *, char *);
|
||||
extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *);
|
||||
extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *);
|
||||
extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
|
||||
extern int zfs_rename(zfs_handle_t *, const char *, boolean_t);
|
||||
extern int zfs_send(zfs_handle_t *, const char *, const char *,
|
||||
boolean_t, boolean_t, boolean_t, boolean_t, int);
|
||||
extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t);
|
||||
extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, int);
|
||||
extern int zfs_rename(zfs_handle_t *, const char *, int);
|
||||
extern int zfs_send(zfs_handle_t *, const char *, int);
|
||||
extern int zfs_receive(libzfs_handle_t *, const char *, int, int, int,
|
||||
boolean_t, int);
|
||||
extern int zfs_promote(zfs_handle_t *);
|
||||
|
||||
typedef struct recvflags {
|
||||
/* print informational messages (ie, -v was specified) */
|
||||
int verbose : 1;
|
||||
|
||||
/* the destination is a prefix, not the exact fs (ie, -d) */
|
||||
int isprefix : 1;
|
||||
|
||||
/* do not actually do the recv, just check if it would work (ie, -n) */
|
||||
int dryrun : 1;
|
||||
|
||||
/* rollback/destroy filesystems as necessary (eg, -F) */
|
||||
int force : 1;
|
||||
|
||||
/* set "canmount=off" on all modified filesystems */
|
||||
int canmountoff : 1;
|
||||
|
||||
/* byteswap flag is used internally; callers need not specify */
|
||||
int byteswap : 1;
|
||||
} recvflags_t;
|
||||
|
||||
extern int zfs_receive(libzfs_handle_t *, const char *, recvflags_t,
|
||||
int, avl_tree_t *);
|
||||
|
||||
/*
|
||||
* Miscellaneous functions.
|
||||
*/
|
||||
extern const char *zfs_type_to_name(zfs_type_t);
|
||||
extern void zfs_refresh_properties(zfs_handle_t *);
|
||||
extern int zfs_name_valid(const char *, zfs_type_t);
|
||||
extern int zfs_disable(zfs_handle_t *);
|
||||
extern int zfs_enable(zfs_handle_t *);
|
||||
extern zfs_handle_t *zfs_path_to_zhandle(libzfs_handle_t *, char *, zfs_type_t);
|
||||
extern boolean_t zfs_dataset_exists(libzfs_handle_t *, const char *,
|
||||
zfs_type_t);
|
||||
extern int zfs_spa_version(zfs_handle_t *, int *);
|
||||
|
||||
/*
|
||||
* dataset permission functions.
|
||||
*/
|
||||
extern int zfs_perm_set(zfs_handle_t *, nvlist_t *);
|
||||
extern int zfs_perm_remove(zfs_handle_t *, nvlist_t *);
|
||||
extern int zfs_build_perms(zfs_handle_t *, char *, char *,
|
||||
zfs_deleg_who_type_t, zfs_deleg_inherit_t, nvlist_t **nvlist_t);
|
||||
extern int zfs_perm_get(zfs_handle_t *, zfs_allow_t **);
|
||||
extern void zfs_free_allows(zfs_allow_t *);
|
||||
extern void zfs_deleg_permissions(void);
|
||||
|
||||
/*
|
||||
* Mount support functions.
|
||||
@@ -501,27 +369,15 @@ extern int zfs_share(zfs_handle_t *);
|
||||
extern int zfs_unshare(zfs_handle_t *);
|
||||
|
||||
/*
|
||||
* Protocol-specific share support functions.
|
||||
* Protocol-specifc share support functions.
|
||||
*/
|
||||
extern boolean_t zfs_is_shared_nfs(zfs_handle_t *, char **);
|
||||
extern boolean_t zfs_is_shared_smb(zfs_handle_t *, char **);
|
||||
extern int zfs_share_nfs(zfs_handle_t *);
|
||||
extern int zfs_share_smb(zfs_handle_t *);
|
||||
extern int zfs_shareall(zfs_handle_t *);
|
||||
extern int zfs_unshare_nfs(zfs_handle_t *, const char *);
|
||||
extern int zfs_unshare_smb(zfs_handle_t *, const char *);
|
||||
extern int zfs_unshareall_nfs(zfs_handle_t *);
|
||||
extern int zfs_unshareall_smb(zfs_handle_t *);
|
||||
extern int zfs_unshareall_bypath(zfs_handle_t *, const char *);
|
||||
extern int zfs_unshareall(zfs_handle_t *);
|
||||
extern boolean_t zfs_is_shared_iscsi(zfs_handle_t *);
|
||||
extern int zfs_share_iscsi(zfs_handle_t *);
|
||||
extern int zfs_unshare_iscsi(zfs_handle_t *);
|
||||
#ifdef TODO
|
||||
extern int zfs_iscsi_perm_check(libzfs_handle_t *, char *, ucred_t *);
|
||||
#endif
|
||||
extern int zfs_deleg_share_nfs(libzfs_handle_t *, char *, char *,
|
||||
void *, void *, int, zfs_share_op_t);
|
||||
|
||||
/*
|
||||
* FreeBSD-specific jail support function.
|
||||
@@ -545,6 +401,12 @@ extern int zfs_jail(zfs_handle_t *, int, int);
|
||||
extern void zfs_nicenum(uint64_t, char *, size_t);
|
||||
extern int zfs_nicestrtonum(libzfs_handle_t *, const char *, uint64_t *);
|
||||
|
||||
/*
|
||||
* Pool destroy special. Remove the device information without destroying
|
||||
* the underlying dataset.
|
||||
*/
|
||||
extern int zfs_remove_link(zfs_handle_t *);
|
||||
|
||||
/*
|
||||
* Given a device or file, determine if it is part of a pool.
|
||||
*/
|
||||
@@ -562,9 +424,6 @@ extern int zpool_read_label(int, nvlist_t **);
|
||||
extern int zpool_create_zvol_links(zpool_handle_t *);
|
||||
extern int zpool_remove_zvol_links(zpool_handle_t *);
|
||||
|
||||
/* is this zvol valid for use as a dump device? */
|
||||
extern int zvol_check_dump_config(char *);
|
||||
|
||||
/*
|
||||
* Enable and disable datasets within a pool by mounting/unmounting and
|
||||
* sharing/unsharing them.
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* Portions Copyright 2007 Ramprakash Jelari
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <libintl.h>
|
||||
#include <libuutil.h>
|
||||
#include <stddef.h>
|
||||
@@ -65,21 +65,18 @@ typedef struct prop_changenode {
|
||||
int cn_shared;
|
||||
int cn_mounted;
|
||||
int cn_zoned;
|
||||
boolean_t cn_needpost; /* is postfix() needed? */
|
||||
uu_list_node_t cn_listnode;
|
||||
} prop_changenode_t;
|
||||
|
||||
struct prop_changelist {
|
||||
zfs_prop_t cl_prop;
|
||||
zfs_prop_t cl_realprop;
|
||||
zfs_prop_t cl_shareprop; /* used with sharenfs/sharesmb */
|
||||
uu_list_pool_t *cl_pool;
|
||||
uu_list_t *cl_list;
|
||||
boolean_t cl_waslegacy;
|
||||
boolean_t cl_allchildren;
|
||||
boolean_t cl_alldependents;
|
||||
int cl_mflags; /* Mount flags */
|
||||
int cl_gflags; /* Gather request flags */
|
||||
int cl_flags;
|
||||
boolean_t cl_haszonedchild;
|
||||
boolean_t cl_sorted;
|
||||
};
|
||||
@@ -87,8 +84,7 @@ struct prop_changelist {
|
||||
/*
|
||||
* If the property is 'mountpoint', go through and unmount filesystems as
|
||||
* necessary. We don't do the same for 'sharenfs', because we can just re-share
|
||||
* with different options without interrupting service. We do handle 'sharesmb'
|
||||
* since there may be old resource names that need to be removed.
|
||||
* with different options without interrupting service.
|
||||
*/
|
||||
int
|
||||
changelist_prefix(prop_changelist_t *clp)
|
||||
@@ -96,19 +92,11 @@ changelist_prefix(prop_changelist_t *clp)
|
||||
prop_changenode_t *cn;
|
||||
int ret = 0;
|
||||
|
||||
if (clp->cl_prop != ZFS_PROP_MOUNTPOINT &&
|
||||
clp->cl_prop != ZFS_PROP_SHARESMB)
|
||||
if (clp->cl_prop != ZFS_PROP_MOUNTPOINT)
|
||||
return (0);
|
||||
|
||||
for (cn = uu_list_first(clp->cl_list); cn != NULL;
|
||||
cn = uu_list_next(clp->cl_list, cn)) {
|
||||
|
||||
/* if a previous loop failed, set the remaining to false */
|
||||
if (ret == -1) {
|
||||
cn->cn_needpost = B_FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are in the global zone, but this dataset is exported
|
||||
* to a local zone, do nothing.
|
||||
@@ -126,11 +114,8 @@ changelist_prefix(prop_changelist_t *clp)
|
||||
(void) zfs_unshare_iscsi(cn->cn_handle);
|
||||
|
||||
if (zvol_remove_link(cn->cn_handle->zfs_hdl,
|
||||
cn->cn_handle->zfs_name) != 0) {
|
||||
cn->cn_handle->zfs_name) != 0)
|
||||
ret = -1;
|
||||
cn->cn_needpost = B_FALSE;
|
||||
(void) zfs_share_iscsi(cn->cn_handle);
|
||||
}
|
||||
break;
|
||||
|
||||
case ZFS_PROP_VOLSIZE:
|
||||
@@ -141,28 +126,10 @@ changelist_prefix(prop_changelist_t *clp)
|
||||
(void) zfs_unshare_iscsi(cn->cn_handle);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Do the property specific processing.
|
||||
*/
|
||||
switch (clp->cl_prop) {
|
||||
case ZFS_PROP_MOUNTPOINT:
|
||||
if (zfs_unmount(cn->cn_handle, NULL,
|
||||
clp->cl_mflags) != 0) {
|
||||
ret = -1;
|
||||
cn->cn_needpost = B_FALSE;
|
||||
}
|
||||
break;
|
||||
case ZFS_PROP_SHARESMB:
|
||||
(void) zfs_unshare_smb(cn->cn_handle, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (zfs_unmount(cn->cn_handle, NULL, clp->cl_flags) != 0)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret == -1)
|
||||
(void) changelist_postfix(clp);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -180,8 +147,7 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
{
|
||||
prop_changenode_t *cn;
|
||||
char shareopts[ZFS_MAXPROPLEN];
|
||||
int errors = 0;
|
||||
libzfs_handle_t *hdl;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* If we're changing the mountpoint, attempt to destroy the underlying
|
||||
@@ -196,29 +162,12 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
if (clp->cl_prop == ZFS_PROP_MOUNTPOINT)
|
||||
remove_mountpoint(cn->cn_handle);
|
||||
|
||||
/*
|
||||
* It is possible that the changelist_prefix() used libshare
|
||||
* to unshare some entries. Since libshare caches data, an
|
||||
* attempt to reshare during postfix can fail unless libshare
|
||||
* is uninitialized here so that it will reinitialize later.
|
||||
*/
|
||||
if (cn->cn_handle != NULL) {
|
||||
hdl = cn->cn_handle->zfs_hdl;
|
||||
assert(hdl != NULL);
|
||||
zfs_uninit_libshare(hdl);
|
||||
}
|
||||
|
||||
/*
|
||||
* We walk the datasets in reverse, because we want to mount any parent
|
||||
* datasets before mounting the children. We walk all datasets even if
|
||||
* there are errors.
|
||||
* datasets before mounting the children.
|
||||
*/
|
||||
for (cn = uu_list_last(clp->cl_list); cn != NULL;
|
||||
cn = uu_list_prev(clp->cl_list, cn)) {
|
||||
|
||||
boolean_t sharenfs;
|
||||
boolean_t sharesmb;
|
||||
|
||||
/*
|
||||
* If we are in the global zone, but this dataset is exported
|
||||
* to a local zone, do nothing.
|
||||
@@ -226,11 +175,6 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
|
||||
continue;
|
||||
|
||||
/* Only do post-processing if it's required */
|
||||
if (!cn->cn_needpost)
|
||||
continue;
|
||||
cn->cn_needpost = B_FALSE;
|
||||
|
||||
zfs_refresh_properties(cn->cn_handle);
|
||||
|
||||
if (ZFS_IS_VOLUME(cn->cn_handle)) {
|
||||
@@ -241,7 +185,7 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
if (clp->cl_realprop == ZFS_PROP_NAME &&
|
||||
zvol_create_link(cn->cn_handle->zfs_hdl,
|
||||
cn->cn_handle->zfs_name) != 0) {
|
||||
errors++;
|
||||
ret = -1;
|
||||
} else if (cn->cn_shared ||
|
||||
clp->cl_prop == ZFS_PROP_SHAREISCSI) {
|
||||
if (zfs_prop_get(cn->cn_handle,
|
||||
@@ -249,55 +193,43 @@ changelist_postfix(prop_changelist_t *clp)
|
||||
sizeof (shareopts), NULL, NULL, 0,
|
||||
B_FALSE) == 0 &&
|
||||
strcmp(shareopts, "off") == 0) {
|
||||
errors +=
|
||||
zfs_unshare_iscsi(cn->cn_handle);
|
||||
ret = zfs_unshare_iscsi(cn->cn_handle);
|
||||
} else {
|
||||
errors +=
|
||||
zfs_share_iscsi(cn->cn_handle);
|
||||
ret = zfs_share_iscsi(cn->cn_handle);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remount if previously mounted or mountpoint was legacy,
|
||||
* or sharenfs or sharesmb property is set.
|
||||
*/
|
||||
sharenfs = ((zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARENFS,
|
||||
shareopts, sizeof (shareopts), NULL, NULL, 0,
|
||||
B_FALSE) == 0) && (strcmp(shareopts, "off") != 0));
|
||||
|
||||
sharesmb = ((zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARESMB,
|
||||
shareopts, sizeof (shareopts), NULL, NULL, 0,
|
||||
B_FALSE) == 0) && (strcmp(shareopts, "off") != 0));
|
||||
|
||||
if ((cn->cn_mounted || clp->cl_waslegacy || sharenfs ||
|
||||
sharesmb) && !zfs_is_mounted(cn->cn_handle, NULL) &&
|
||||
if ((clp->cl_waslegacy || cn->cn_mounted) &&
|
||||
!zfs_is_mounted(cn->cn_handle, NULL) &&
|
||||
zfs_mount(cn->cn_handle, NULL, 0) != 0)
|
||||
errors++;
|
||||
ret = -1;
|
||||
|
||||
/*
|
||||
* We always re-share even if the filesystem is currently
|
||||
* shared, so that we can adopt any new options.
|
||||
*/
|
||||
if (sharenfs)
|
||||
errors += zfs_share_nfs(cn->cn_handle);
|
||||
else if (cn->cn_shared || clp->cl_waslegacy)
|
||||
errors += zfs_unshare_nfs(cn->cn_handle, NULL);
|
||||
if (sharesmb)
|
||||
errors += zfs_share_smb(cn->cn_handle);
|
||||
else if (cn->cn_shared || clp->cl_waslegacy)
|
||||
errors += zfs_unshare_smb(cn->cn_handle, NULL);
|
||||
if (cn->cn_shared ||
|
||||
(clp->cl_prop == ZFS_PROP_SHARENFS && clp->cl_waslegacy)) {
|
||||
if (zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARENFS,
|
||||
shareopts, sizeof (shareopts), NULL, NULL, 0,
|
||||
B_FALSE) == 0 && strcmp(shareopts, "off") == 0) {
|
||||
ret = zfs_unshare_nfs(cn->cn_handle, NULL);
|
||||
} else {
|
||||
ret = zfs_share_nfs(cn->cn_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (errors ? -1 : 0);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this "dataset" a child of "parent"?
|
||||
*/
|
||||
boolean_t
|
||||
static boolean_t
|
||||
isa_child_of(const char *dataset, const char *parent)
|
||||
{
|
||||
int len;
|
||||
@@ -348,22 +280,21 @@ changelist_rename(prop_changelist_t *clp, const char *src, const char *dst)
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a gathered changelist for the 'sharenfs' or 'sharesmb' property,
|
||||
* unshare all the datasets in the list.
|
||||
* Given a gathered changelist for the 'sharenfs' property, unshare all the
|
||||
* datasets in the list.
|
||||
*/
|
||||
int
|
||||
changelist_unshare(prop_changelist_t *clp, zfs_share_proto_t *proto)
|
||||
changelist_unshare(prop_changelist_t *clp)
|
||||
{
|
||||
prop_changenode_t *cn;
|
||||
int ret = 0;
|
||||
|
||||
if (clp->cl_prop != ZFS_PROP_SHARENFS &&
|
||||
clp->cl_prop != ZFS_PROP_SHARESMB)
|
||||
if (clp->cl_prop != ZFS_PROP_SHARENFS)
|
||||
return (0);
|
||||
|
||||
for (cn = uu_list_first(clp->cl_list); cn != NULL;
|
||||
cn = uu_list_next(clp->cl_list, cn)) {
|
||||
if (zfs_unshare_proto(cn->cn_handle, NULL, proto) != 0)
|
||||
if (zfs_unshare_nfs(cn->cn_handle, NULL) != 0)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
@@ -385,14 +316,14 @@ changelist_haszonedchild(prop_changelist_t *clp)
|
||||
* Remove a node from a gathered list.
|
||||
*/
|
||||
void
|
||||
changelist_remove(prop_changelist_t *clp, const char *name)
|
||||
changelist_remove(zfs_handle_t *zhp, prop_changelist_t *clp)
|
||||
{
|
||||
prop_changenode_t *cn;
|
||||
|
||||
for (cn = uu_list_first(clp->cl_list); cn != NULL;
|
||||
cn = uu_list_next(clp->cl_list, cn)) {
|
||||
|
||||
if (strcmp(cn->cn_handle->zfs_name, name) == 0) {
|
||||
if (strcmp(cn->cn_handle->zfs_name, zhp->zfs_name) == 0) {
|
||||
uu_list_remove(clp->cl_list, cn);
|
||||
zfs_close(cn->cn_handle);
|
||||
free(cn);
|
||||
@@ -432,8 +363,7 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
char property[ZFS_MAXPROPLEN];
|
||||
char where[64];
|
||||
prop_changenode_t *cn;
|
||||
zprop_source_t sourcetype;
|
||||
zprop_source_t share_sourcetype;
|
||||
zfs_source_t sourcetype;
|
||||
|
||||
/*
|
||||
* We only want to unmount/unshare those filesystems that may inherit
|
||||
@@ -453,25 +383,8 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are "watching" sharenfs or sharesmb
|
||||
* then check out the companion property which is tracked
|
||||
* in cl_shareprop
|
||||
*/
|
||||
if (clp->cl_shareprop != ZPROP_INVAL &&
|
||||
zfs_prop_get(zhp, clp->cl_shareprop, property,
|
||||
sizeof (property), &share_sourcetype, where, sizeof (where),
|
||||
B_FALSE) != 0) {
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (clp->cl_alldependents || clp->cl_allchildren ||
|
||||
sourcetype == ZPROP_SRC_DEFAULT ||
|
||||
sourcetype == ZPROP_SRC_INHERITED ||
|
||||
(clp->cl_shareprop != ZPROP_INVAL &&
|
||||
(share_sourcetype == ZPROP_SRC_DEFAULT ||
|
||||
share_sourcetype == ZPROP_SRC_INHERITED))) {
|
||||
sourcetype == ZFS_SRC_DEFAULT || sourcetype == ZFS_SRC_INHERITED) {
|
||||
if ((cn = zfs_alloc(zfs_get_handle(zhp),
|
||||
sizeof (prop_changenode_t))) == NULL) {
|
||||
zfs_close(zhp);
|
||||
@@ -479,11 +392,9 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
}
|
||||
|
||||
cn->cn_handle = zhp;
|
||||
cn->cn_mounted = (clp->cl_gflags & CL_GATHER_MOUNT_ALWAYS) ||
|
||||
zfs_is_mounted(zhp, NULL);
|
||||
cn->cn_mounted = zfs_is_mounted(zhp, NULL);
|
||||
cn->cn_shared = zfs_is_shared(zhp);
|
||||
cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
|
||||
cn->cn_needpost = B_TRUE;
|
||||
|
||||
/* Indicate if any child is exported to a local zone. */
|
||||
if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned)
|
||||
@@ -556,8 +467,7 @@ compare_mountpoints(const void *a, const void *b, void *unused)
|
||||
* mark whether it was shared beforehand.
|
||||
*/
|
||||
prop_changelist_t *
|
||||
changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
int mnt_flags)
|
||||
changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int flags)
|
||||
{
|
||||
prop_changelist_t *clp;
|
||||
prop_changenode_t *cn;
|
||||
@@ -574,8 +484,7 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
* order, regardless of their position in the hierarchy.
|
||||
*/
|
||||
if (prop == ZFS_PROP_NAME || prop == ZFS_PROP_ZONED ||
|
||||
prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS ||
|
||||
prop == ZFS_PROP_SHARESMB) {
|
||||
prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS) {
|
||||
compare = compare_mountpoints;
|
||||
clp->cl_sorted = B_TRUE;
|
||||
}
|
||||
@@ -593,8 +502,7 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
|
||||
clp->cl_list = uu_list_create(clp->cl_pool, NULL,
|
||||
clp->cl_sorted ? UU_LIST_SORTED : 0);
|
||||
clp->cl_gflags = gather_flags;
|
||||
clp->cl_mflags = mnt_flags;
|
||||
clp->cl_flags = flags;
|
||||
|
||||
if (clp->cl_list == NULL) {
|
||||
assert(uu_error() == UU_ERROR_NO_MEMORY);
|
||||
@@ -621,8 +529,6 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
clp->cl_prop = ZFS_PROP_MOUNTPOINT;
|
||||
} else if (prop == ZFS_PROP_VOLSIZE) {
|
||||
clp->cl_prop = ZFS_PROP_MOUNTPOINT;
|
||||
} else if (prop == ZFS_PROP_VERSION) {
|
||||
clp->cl_prop = ZFS_PROP_MOUNTPOINT;
|
||||
} else {
|
||||
clp->cl_prop = prop;
|
||||
}
|
||||
@@ -630,19 +536,9 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
|
||||
if (clp->cl_prop != ZFS_PROP_MOUNTPOINT &&
|
||||
clp->cl_prop != ZFS_PROP_SHARENFS &&
|
||||
clp->cl_prop != ZFS_PROP_SHARESMB &&
|
||||
clp->cl_prop != ZFS_PROP_SHAREISCSI)
|
||||
return (clp);
|
||||
|
||||
/*
|
||||
* If watching SHARENFS or SHARESMB then
|
||||
* also watch its companion property.
|
||||
*/
|
||||
if (clp->cl_prop == ZFS_PROP_SHARENFS)
|
||||
clp->cl_shareprop = ZFS_PROP_SHARESMB;
|
||||
else if (clp->cl_prop == ZFS_PROP_SHARESMB)
|
||||
clp->cl_shareprop = ZFS_PROP_SHARENFS;
|
||||
|
||||
if (clp->cl_alldependents) {
|
||||
if (zfs_iter_dependents(zhp, B_TRUE, change_one, clp) != 0) {
|
||||
changelist_free(clp);
|
||||
@@ -658,7 +554,7 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
* and can't tell the difference.
|
||||
*/
|
||||
if ((temp = zfs_open(zhp->zfs_hdl, zfs_get_name(zhp),
|
||||
ZFS_TYPE_DATASET)) == NULL) {
|
||||
ZFS_TYPE_ANY)) == NULL) {
|
||||
changelist_free(clp);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -675,11 +571,9 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
}
|
||||
|
||||
cn->cn_handle = temp;
|
||||
cn->cn_mounted = (clp->cl_gflags & CL_GATHER_MOUNT_ALWAYS) ||
|
||||
zfs_is_mounted(temp, NULL);
|
||||
cn->cn_mounted = zfs_is_mounted(temp, NULL);
|
||||
cn->cn_shared = zfs_is_shared(temp);
|
||||
cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
|
||||
cn->cn_needpost = B_TRUE;
|
||||
|
||||
uu_list_node_init(cn, &cn->cn_listnode, clp->cl_pool);
|
||||
if (clp->cl_sorted) {
|
||||
@@ -692,22 +586,14 @@ changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int gather_flags,
|
||||
}
|
||||
|
||||
/*
|
||||
* If the mountpoint property was previously 'legacy', or 'none',
|
||||
* record it as the behavior of changelist_postfix() will be different.
|
||||
* If the property was previously 'legacy' or 'none', record this fact,
|
||||
* as the behavior of changelist_postfix() will be different.
|
||||
*/
|
||||
if ((clp->cl_prop == ZFS_PROP_MOUNTPOINT) &&
|
||||
(zfs_prop_get(zhp, prop, property, sizeof (property),
|
||||
if (zfs_prop_get(zhp, prop, property, sizeof (property),
|
||||
NULL, NULL, 0, B_FALSE) == 0 &&
|
||||
(strcmp(property, "legacy") == 0 ||
|
||||
strcmp(property, "none") == 0))) {
|
||||
/*
|
||||
* do not automatically mount ex-legacy datasets if
|
||||
* we specifically set canmount to noauto
|
||||
*/
|
||||
if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) !=
|
||||
ZFS_CANMOUNT_NOAUTO)
|
||||
clp->cl_waslegacy = B_TRUE;
|
||||
}
|
||||
(strcmp(property, "legacy") == 0 || strcmp(property, "none") == 0 ||
|
||||
strcmp(property, "off") == 0))
|
||||
clp->cl_waslegacy = B_TRUE;
|
||||
|
||||
return (clp);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -126,8 +126,6 @@ typedef struct zfs_graph {
|
||||
zfs_vertex_t **zg_hash;
|
||||
size_t zg_size;
|
||||
size_t zg_nvertex;
|
||||
const char *zg_root;
|
||||
int zg_clone_count;
|
||||
} zfs_graph_t;
|
||||
|
||||
/*
|
||||
@@ -257,7 +255,7 @@ zfs_vertex_sort_edges(zfs_vertex_t *zvp)
|
||||
* datasets in the pool.
|
||||
*/
|
||||
static zfs_graph_t *
|
||||
zfs_graph_create(libzfs_handle_t *hdl, const char *dataset, size_t size)
|
||||
zfs_graph_create(libzfs_handle_t *hdl, size_t size)
|
||||
{
|
||||
zfs_graph_t *zgp = zfs_alloc(hdl, sizeof (zfs_graph_t));
|
||||
|
||||
@@ -271,9 +269,6 @@ zfs_graph_create(libzfs_handle_t *hdl, const char *dataset, size_t size)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
zgp->zg_root = dataset;
|
||||
zgp->zg_clone_count = 0;
|
||||
|
||||
return (zgp);
|
||||
}
|
||||
|
||||
@@ -372,16 +367,17 @@ zfs_graph_add(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *source,
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over all children of the given dataset, adding any vertices
|
||||
* as necessary. Returns -1 if there was an error, or 0 otherwise.
|
||||
* This is a simple recursive algorithm - the ZFS namespace typically
|
||||
* is very flat. We manually invoke the necessary ioctl() calls to
|
||||
* avoid the overhead and additional semantics of zfs_open().
|
||||
* Iterate over all children of the given dataset, adding any vertices as
|
||||
* necessary. Returns 0 if no cloned snapshots were seen, -1 if there was an
|
||||
* error, or 1 otherwise. This is a simple recursive algorithm - the ZFS
|
||||
* namespace typically is very flat. We manually invoke the necessary ioctl()
|
||||
* calls to avoid the overhead and additional semantics of zfs_open().
|
||||
*/
|
||||
static int
|
||||
iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
|
||||
{
|
||||
zfs_cmd_t zc = { 0 };
|
||||
int ret = 0, err;
|
||||
zfs_vertex_t *zvp;
|
||||
|
||||
/*
|
||||
@@ -394,8 +390,18 @@ iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Iterate over all children
|
||||
* We check the clone parent here instead of within the loop, so that if
|
||||
* the root dataset has been promoted from a clone, we find its parent
|
||||
* appropriately.
|
||||
*/
|
||||
(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
|
||||
if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0 &&
|
||||
zc.zc_objset_stats.dds_clone_of[0] != '\0') {
|
||||
if (zfs_graph_add(hdl, zgp, zc.zc_objset_stats.dds_clone_of,
|
||||
zc.zc_name, zc.zc_objset_stats.dds_creation_txg) != 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
|
||||
ioctl(hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0;
|
||||
(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) {
|
||||
@@ -411,23 +417,9 @@ iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
|
||||
* dataset and clone statistics. If this fails, the dataset has
|
||||
* since been removed, and we're pretty much screwed anyway.
|
||||
*/
|
||||
zc.zc_objset_stats.dds_origin[0] = '\0';
|
||||
if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0)
|
||||
continue;
|
||||
|
||||
if (zc.zc_objset_stats.dds_origin[0] != '\0') {
|
||||
if (zfs_graph_add(hdl, zgp,
|
||||
zc.zc_objset_stats.dds_origin, zc.zc_name,
|
||||
zc.zc_objset_stats.dds_creation_txg) != 0)
|
||||
return (-1);
|
||||
/*
|
||||
* Count origins only if they are contained in the graph
|
||||
*/
|
||||
if (isa_child_of(zc.zc_objset_stats.dds_origin,
|
||||
zgp->zg_root))
|
||||
zgp->zg_clone_count--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an edge between the parent and the child.
|
||||
*/
|
||||
@@ -436,10 +428,19 @@ iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Recursively visit child
|
||||
* Iterate over all children
|
||||
*/
|
||||
if (iterate_children(hdl, zgp, zc.zc_name))
|
||||
err = iterate_children(hdl, zgp, zc.zc_name);
|
||||
if (err == -1)
|
||||
return (-1);
|
||||
else if (err == 1)
|
||||
ret = 1;
|
||||
|
||||
/*
|
||||
* Indicate if we found a dataset with a non-zero clone count.
|
||||
*/
|
||||
if (zc.zc_objset_stats.dds_num_clones != 0)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -466,84 +467,67 @@ iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
|
||||
zc.zc_objset_stats.dds_creation_txg) != 0)
|
||||
return (-1);
|
||||
|
||||
zgp->zg_clone_count += zc.zc_objset_stats.dds_num_clones;
|
||||
/*
|
||||
* Indicate if we found a dataset with a non-zero clone count.
|
||||
*/
|
||||
if (zc.zc_objset_stats.dds_num_clones != 0)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
zvp->zv_visited = VISIT_SEEN;
|
||||
|
||||
return (0);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns false if there are no snapshots with dependent clones in this
|
||||
* subtree or if all of those clones are also in this subtree. Returns
|
||||
* true if there is an error or there are external dependents.
|
||||
*/
|
||||
static boolean_t
|
||||
external_dependents(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
|
||||
{
|
||||
zfs_cmd_t zc = { 0 };
|
||||
|
||||
/*
|
||||
* Check whether this dataset is a clone or has clones since
|
||||
* iterate_children() only checks the children.
|
||||
*/
|
||||
(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
|
||||
if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0)
|
||||
return (B_TRUE);
|
||||
|
||||
if (zc.zc_objset_stats.dds_origin[0] != '\0') {
|
||||
if (zfs_graph_add(hdl, zgp,
|
||||
zc.zc_objset_stats.dds_origin, zc.zc_name,
|
||||
zc.zc_objset_stats.dds_creation_txg) != 0)
|
||||
return (B_TRUE);
|
||||
if (isa_child_of(zc.zc_objset_stats.dds_origin, dataset))
|
||||
zgp->zg_clone_count--;
|
||||
}
|
||||
|
||||
if ((zc.zc_objset_stats.dds_num_clones) ||
|
||||
iterate_children(hdl, zgp, dataset))
|
||||
return (B_TRUE);
|
||||
|
||||
return (zgp->zg_clone_count != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a complete graph of all necessary vertices. First, iterate over
|
||||
* only our object's children. If no cloned snapshots are found, or all of
|
||||
* the cloned snapshots are in this subtree then return a graph of the subtree.
|
||||
* Otherwise, start at the root of the pool and iterate over all datasets.
|
||||
* Construct a complete graph of all necessary vertices. First, we iterate over
|
||||
* only our object's children. If we don't find any cloned snapshots, then we
|
||||
* simple return that. Otherwise, we have to start at the pool root and iterate
|
||||
* over all datasets.
|
||||
*/
|
||||
static zfs_graph_t *
|
||||
construct_graph(libzfs_handle_t *hdl, const char *dataset)
|
||||
{
|
||||
zfs_graph_t *zgp = zfs_graph_create(hdl, dataset, ZFS_GRAPH_SIZE);
|
||||
zfs_graph_t *zgp = zfs_graph_create(hdl, ZFS_GRAPH_SIZE);
|
||||
zfs_cmd_t zc = { 0 };
|
||||
int ret = 0;
|
||||
|
||||
if (zgp == NULL)
|
||||
return (zgp);
|
||||
|
||||
if ((strchr(dataset, '/') == NULL) ||
|
||||
(external_dependents(hdl, zgp, dataset))) {
|
||||
/*
|
||||
* We need to explicitly check whether this dataset has clones or not,
|
||||
* since iterate_children() only checks the children.
|
||||
*/
|
||||
(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
|
||||
(void) ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc);
|
||||
|
||||
if (zc.zc_objset_stats.dds_num_clones != 0 ||
|
||||
(ret = iterate_children(hdl, zgp, dataset)) != 0) {
|
||||
/*
|
||||
* Determine pool name and try again.
|
||||
*/
|
||||
int len = strcspn(dataset, "/@") + 1;
|
||||
char *pool = zfs_alloc(hdl, len);
|
||||
char *pool, *slash;
|
||||
|
||||
if (pool == NULL) {
|
||||
zfs_graph_destroy(zgp);
|
||||
return (NULL);
|
||||
}
|
||||
(void) strlcpy(pool, dataset, len);
|
||||
if ((slash = strchr(dataset, '/')) != NULL ||
|
||||
(slash = strchr(dataset, '@')) != NULL) {
|
||||
pool = zfs_alloc(hdl, slash - dataset + 1);
|
||||
if (pool == NULL) {
|
||||
zfs_graph_destroy(zgp);
|
||||
return (NULL);
|
||||
}
|
||||
(void) strncpy(pool, dataset, slash - dataset);
|
||||
pool[slash - dataset] = '\0';
|
||||
|
||||
if (iterate_children(hdl, zgp, pool) == -1 ||
|
||||
zfs_graph_add(hdl, zgp, pool, NULL, 0) != 0) {
|
||||
free(pool);
|
||||
zfs_graph_destroy(zgp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (iterate_children(hdl, zgp, pool) == -1 ||
|
||||
zfs_graph_add(hdl, zgp, pool, NULL, 0) != 0) {
|
||||
free(pool);
|
||||
zfs_graph_destroy(zgp);
|
||||
return (NULL);
|
||||
}
|
||||
free(pool);
|
||||
}
|
||||
|
||||
if (ret == -1 || zfs_graph_add(hdl, zgp, dataset, NULL, 0) != 0) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* CDDL HEADER SART
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
@@ -20,21 +20,21 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _LIBFS_IMPL_H
|
||||
#define _LIBFS_IMPL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/dmu.h>
|
||||
#include <sys/fs/zfs.h>
|
||||
#include <sys/zfs_ioctl.h>
|
||||
#include <sys/zfs_acl.h>
|
||||
#include <sys/spa.h>
|
||||
#include <sys/nvpair.h>
|
||||
|
||||
#include <libshare.h>
|
||||
#include <libuutil.h>
|
||||
#include <libzfs.h>
|
||||
|
||||
@@ -42,33 +42,22 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef VERIFY
|
||||
#undef VERIFY
|
||||
#endif
|
||||
#define VERIFY verify
|
||||
|
||||
struct libzfs_handle {
|
||||
int libzfs_error;
|
||||
int libzfs_fd;
|
||||
FILE *libzfs_mnttab;
|
||||
FILE *libzfs_sharetab;
|
||||
zpool_handle_t *libzfs_pool_handles;
|
||||
uu_avl_pool_t *libzfs_ns_avlpool;
|
||||
uu_avl_t *libzfs_ns_avl;
|
||||
uint64_t libzfs_ns_gen;
|
||||
int libzfs_desc_active;
|
||||
char libzfs_action[1024];
|
||||
char libzfs_desc[1024];
|
||||
char *libzfs_log_str;
|
||||
int libzfs_printerr;
|
||||
void *libzfs_sharehdl; /* libshare handle */
|
||||
uint_t libzfs_shareflags;
|
||||
};
|
||||
#define ZFSSHARE_MISS 0x01 /* Didn't find entry in cache */
|
||||
|
||||
struct zfs_handle {
|
||||
libzfs_handle_t *zfs_hdl;
|
||||
zpool_handle_t *zpool_hdl;
|
||||
char zfs_name[ZFS_MAXNAMELEN];
|
||||
zfs_type_t zfs_type; /* type including snapshot */
|
||||
zfs_type_t zfs_head_type; /* type excluding snapshot */
|
||||
@@ -77,6 +66,7 @@ struct zfs_handle {
|
||||
nvlist_t *zfs_user_props;
|
||||
boolean_t zfs_mntcheck;
|
||||
char *zfs_mntopts;
|
||||
char zfs_root[MAXPATHLEN];
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -87,33 +77,14 @@ struct zfs_handle {
|
||||
|
||||
struct zpool_handle {
|
||||
libzfs_handle_t *zpool_hdl;
|
||||
zpool_handle_t *zpool_next;
|
||||
char zpool_name[ZPOOL_MAXNAMELEN];
|
||||
int zpool_state;
|
||||
size_t zpool_config_size;
|
||||
nvlist_t *zpool_config;
|
||||
nvlist_t *zpool_old_config;
|
||||
nvlist_t *zpool_props;
|
||||
diskaddr_t zpool_start_block;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PROTO_NFS = 0,
|
||||
PROTO_SMB = 1,
|
||||
PROTO_END = 2
|
||||
} zfs_share_proto_t;
|
||||
|
||||
/*
|
||||
* The following can be used as a bitmask and any new values
|
||||
* added must preserve that capability.
|
||||
*/
|
||||
typedef enum {
|
||||
SHARED_NOT_SHARED = 0x0,
|
||||
SHARED_ISCSI = 0x1,
|
||||
SHARED_NFS = 0x2,
|
||||
SHARED_SMB = 0x4
|
||||
} zfs_share_type_t;
|
||||
|
||||
int zfs_error(libzfs_handle_t *, int, const char *);
|
||||
int zfs_error_fmt(libzfs_handle_t *, int, const char *, ...);
|
||||
void zfs_error_aux(libzfs_handle_t *, const char *, ...);
|
||||
@@ -130,24 +101,20 @@ int zpool_standard_error_fmt(libzfs_handle_t *, int, const char *, ...);
|
||||
int get_dependents(libzfs_handle_t *, boolean_t, const char *, char ***,
|
||||
size_t *);
|
||||
|
||||
int zfs_expand_proplist_common(libzfs_handle_t *, zfs_proplist_t **,
|
||||
zfs_type_t);
|
||||
int zfs_get_proplist_common(libzfs_handle_t *, char *, zfs_proplist_t **,
|
||||
zfs_type_t);
|
||||
zfs_prop_t zfs_prop_iter_common(zfs_prop_f, void *, zfs_type_t, boolean_t);
|
||||
zfs_prop_t zfs_name_to_prop_common(const char *, zfs_type_t);
|
||||
|
||||
int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t,
|
||||
nvlist_t *, char **, uint64_t *, const char *);
|
||||
int zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp,
|
||||
zfs_type_t type);
|
||||
|
||||
/*
|
||||
* Use this changelist_gather() flag to force attempting mounts
|
||||
* on each change node regardless of whether or not it is currently
|
||||
* mounted.
|
||||
*/
|
||||
#define CL_GATHER_MOUNT_ALWAYS 1
|
||||
nvlist_t *zfs_validate_properties(libzfs_handle_t *, zfs_type_t, char *,
|
||||
nvlist_t *, uint64_t, zfs_handle_t *zhp, const char *errbuf);
|
||||
|
||||
typedef struct prop_changelist prop_changelist_t;
|
||||
|
||||
int zcmd_alloc_dst_nvlist(libzfs_handle_t *, zfs_cmd_t *, size_t);
|
||||
int zcmd_write_src_nvlist(libzfs_handle_t *, zfs_cmd_t *, nvlist_t *);
|
||||
int zcmd_write_conf_nvlist(libzfs_handle_t *, zfs_cmd_t *, nvlist_t *);
|
||||
int zcmd_write_src_nvlist(libzfs_handle_t *, zfs_cmd_t *, nvlist_t *, size_t *);
|
||||
int zcmd_expand_dst_nvlist(libzfs_handle_t *, zfs_cmd_t *);
|
||||
int zcmd_read_dst_nvlist(libzfs_handle_t *, zfs_cmd_t *, nvlist_t **);
|
||||
void zcmd_free_nvlists(zfs_cmd_t *);
|
||||
@@ -155,15 +122,13 @@ void zcmd_free_nvlists(zfs_cmd_t *);
|
||||
int changelist_prefix(prop_changelist_t *);
|
||||
int changelist_postfix(prop_changelist_t *);
|
||||
void changelist_rename(prop_changelist_t *, const char *, const char *);
|
||||
void changelist_remove(prop_changelist_t *, const char *);
|
||||
void changelist_remove(zfs_handle_t *, prop_changelist_t *);
|
||||
void changelist_free(prop_changelist_t *);
|
||||
prop_changelist_t *changelist_gather(zfs_handle_t *, zfs_prop_t, int, int);
|
||||
int changelist_unshare(prop_changelist_t *, zfs_share_proto_t *);
|
||||
prop_changelist_t *changelist_gather(zfs_handle_t *, zfs_prop_t, int);
|
||||
int changelist_unshare(prop_changelist_t *);
|
||||
int changelist_haszonedchild(prop_changelist_t *);
|
||||
|
||||
void remove_mountpoint(zfs_handle_t *);
|
||||
int create_parents(libzfs_handle_t *, char *, int);
|
||||
boolean_t isa_child_of(const char *dataset, const char *parent);
|
||||
|
||||
zfs_handle_t *make_dataset_handle(libzfs_handle_t *, const char *);
|
||||
|
||||
@@ -172,23 +137,10 @@ int zpool_open_silent(libzfs_handle_t *, const char *, zpool_handle_t **);
|
||||
int zvol_create_link(libzfs_handle_t *, const char *);
|
||||
int zvol_remove_link(libzfs_handle_t *, const char *);
|
||||
int zpool_iter_zvol(zpool_handle_t *, int (*)(const char *, void *), void *);
|
||||
boolean_t zpool_name_valid(libzfs_handle_t *, boolean_t, const char *);
|
||||
|
||||
void namespace_clear(libzfs_handle_t *);
|
||||
|
||||
/*
|
||||
* libshare (sharemgr) interfaces used internally.
|
||||
*/
|
||||
|
||||
extern int zfs_init_libshare(libzfs_handle_t *, int);
|
||||
extern void zfs_uninit_libshare(libzfs_handle_t *);
|
||||
extern int zfs_parse_options(char *, zfs_share_proto_t);
|
||||
|
||||
extern int zfs_unshare_proto(zfs_handle_t *zhp,
|
||||
const char *, zfs_share_proto_t *);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
/*
|
||||
* This is FreeBSD version of ioctl, because Solaris' ioctl() updates
|
||||
* zc_nvlist_dst_size even if an error is returned, on FreeBSD if an
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -213,13 +213,11 @@ add_config(libzfs_handle_t *hdl, pool_list_t *pl, const char *path,
|
||||
name_entry_t *ne;
|
||||
|
||||
/*
|
||||
* If this is a hot spare not currently in use or level 2 cache
|
||||
* device, add it to the list of names to translate, but don't do
|
||||
* anything else.
|
||||
* If this is a hot spare not currently in use, add it to the list of
|
||||
* names to translate, but don't do anything else.
|
||||
*/
|
||||
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
|
||||
&state) == 0 &&
|
||||
(state == POOL_STATE_SPARE || state == POOL_STATE_L2CACHE) &&
|
||||
&state) == 0 && state == POOL_STATE_SPARE &&
|
||||
nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, &vdev_guid) == 0) {
|
||||
if ((ne = zfs_alloc(hdl, sizeof (name_entry_t))) == NULL)
|
||||
return (-1);
|
||||
@@ -363,46 +361,6 @@ pool_active(libzfs_handle_t *hdl, const char *name, uint64_t guid,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static nvlist_t *
|
||||
refresh_config(libzfs_handle_t *hdl, nvlist_t *config)
|
||||
{
|
||||
nvlist_t *nvl;
|
||||
zfs_cmd_t zc = { 0 };
|
||||
int err;
|
||||
|
||||
if (zcmd_write_conf_nvlist(hdl, &zc, config) != 0)
|
||||
return (NULL);
|
||||
|
||||
if (zcmd_alloc_dst_nvlist(hdl, &zc,
|
||||
zc.zc_nvlist_conf_size * 2) != 0) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
while ((err = ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_TRYIMPORT,
|
||||
&zc)) != 0 && errno == ENOMEM) {
|
||||
if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
(void) zpool_standard_error(hdl, errno,
|
||||
dgettext(TEXT_DOMAIN, "cannot discover pools"));
|
||||
zcmd_free_nvlists(&zc);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (zcmd_read_dst_nvlist(hdl, &zc, &nvl) != 0) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
zcmd_free_nvlists(&zc);
|
||||
return (nvl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert our list of pools into the definitive set of configurations. We
|
||||
* start by picking the best config for each toplevel vdev. Once that's done,
|
||||
@@ -411,25 +369,26 @@ refresh_config(libzfs_handle_t *hdl, nvlist_t *config)
|
||||
* return to the user.
|
||||
*/
|
||||
static nvlist_t *
|
||||
get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
|
||||
get_configs(libzfs_handle_t *hdl, pool_list_t *pl)
|
||||
{
|
||||
pool_entry_t *pe;
|
||||
vdev_entry_t *ve;
|
||||
config_entry_t *ce;
|
||||
nvlist_t *ret = NULL, *config = NULL, *tmp, *nvtop, *nvroot;
|
||||
nvlist_t **spares, **l2cache;
|
||||
uint_t i, nspares, nl2cache;
|
||||
nvlist_t **spares;
|
||||
uint_t i, nspares;
|
||||
boolean_t config_seen;
|
||||
uint64_t best_txg;
|
||||
char *name, *hostname;
|
||||
zfs_cmd_t zc = { 0 };
|
||||
uint64_t version, guid;
|
||||
size_t len;
|
||||
int err;
|
||||
uint_t children = 0;
|
||||
nvlist_t **child = NULL;
|
||||
uint_t c;
|
||||
boolean_t isactive;
|
||||
uint64_t hostid;
|
||||
nvlist_t *nvl;
|
||||
boolean_t found_one = B_FALSE;
|
||||
|
||||
if (nvlist_alloc(&ret, 0, 0) != 0)
|
||||
goto nomem;
|
||||
@@ -611,13 +570,6 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
|
||||
}
|
||||
nvlist_free(nvroot);
|
||||
|
||||
/*
|
||||
* zdb uses this path to report on active pools that were
|
||||
* imported or created using -R.
|
||||
*/
|
||||
if (active_ok)
|
||||
goto add_pool;
|
||||
|
||||
/*
|
||||
* Determine if this pool is currently active, in which case we
|
||||
* can't actually import it.
|
||||
@@ -636,11 +588,41 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((nvl = refresh_config(hdl, config)) == NULL)
|
||||
/*
|
||||
* Try to do the import in order to get vdev state.
|
||||
*/
|
||||
if (zcmd_write_src_nvlist(hdl, &zc, config, &len) != 0)
|
||||
goto error;
|
||||
|
||||
nvlist_free(config);
|
||||
config = nvl;
|
||||
config = NULL;
|
||||
|
||||
if (zcmd_alloc_dst_nvlist(hdl, &zc, len * 2) != 0) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((err = ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_TRYIMPORT,
|
||||
&zc)) != 0 && errno == ENOMEM) {
|
||||
if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
(void) zpool_standard_error(hdl, errno,
|
||||
dgettext(TEXT_DOMAIN, "cannot discover pools"));
|
||||
zcmd_free_nvlists(&zc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
zcmd_free_nvlists(&zc);
|
||||
|
||||
/*
|
||||
* Go through and update the paths for spares, now that we have
|
||||
@@ -656,17 +638,6 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the paths for l2cache devices.
|
||||
*/
|
||||
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
|
||||
&l2cache, &nl2cache) == 0) {
|
||||
for (i = 0; i < nl2cache; i++) {
|
||||
if (fix_paths(l2cache[i], pl->names) != 0)
|
||||
goto nomem;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the original information read from the actual label.
|
||||
*/
|
||||
@@ -681,7 +652,6 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
|
||||
hostname) == 0);
|
||||
}
|
||||
|
||||
add_pool:
|
||||
/*
|
||||
* Add this pool to the list of configs.
|
||||
*/
|
||||
@@ -690,16 +660,10 @@ add_pool:
|
||||
if (nvlist_add_nvlist(ret, name, config) != 0)
|
||||
goto nomem;
|
||||
|
||||
found_one = B_TRUE;
|
||||
nvlist_free(config);
|
||||
config = NULL;
|
||||
}
|
||||
|
||||
if (!found_one) {
|
||||
nvlist_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
|
||||
nomem:
|
||||
@@ -718,9 +682,8 @@ error:
|
||||
* Return the offset of the given label.
|
||||
*/
|
||||
static uint64_t
|
||||
label_offset(uint64_t size, int l)
|
||||
label_offset(size_t size, int l)
|
||||
{
|
||||
ASSERT(P2PHASE_TYPED(size, sizeof (vdev_label_t), uint64_t) == 0);
|
||||
return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
|
||||
0 : size - VDEV_LABELS * sizeof (vdev_label_t)));
|
||||
}
|
||||
@@ -735,20 +698,19 @@ zpool_read_label(int fd, nvlist_t **config)
|
||||
struct stat64 statbuf;
|
||||
int l;
|
||||
vdev_label_t *label;
|
||||
uint64_t state, txg, size;
|
||||
uint64_t state, txg;
|
||||
|
||||
*config = NULL;
|
||||
|
||||
if (fstat64(fd, &statbuf) == -1)
|
||||
return (0);
|
||||
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
|
||||
|
||||
if ((label = malloc(sizeof (vdev_label_t))) == NULL)
|
||||
return (-1);
|
||||
|
||||
for (l = 0; l < VDEV_LABELS; l++) {
|
||||
if (pread64(fd, label, sizeof (vdev_label_t),
|
||||
label_offset(size, l)) != sizeof (vdev_label_t))
|
||||
if (pread(fd, label, sizeof (vdev_label_t),
|
||||
label_offset(statbuf.st_size, l)) != sizeof (vdev_label_t))
|
||||
continue;
|
||||
|
||||
if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
|
||||
@@ -756,12 +718,12 @@ zpool_read_label(int fd, nvlist_t **config)
|
||||
continue;
|
||||
|
||||
if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE,
|
||||
&state) != 0 || state > POOL_STATE_L2CACHE) {
|
||||
&state) != 0 || state > POOL_STATE_SPARE) {
|
||||
nvlist_free(*config);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state != POOL_STATE_SPARE && state != POOL_STATE_L2CACHE &&
|
||||
if (state != POOL_STATE_SPARE &&
|
||||
(nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_TXG,
|
||||
&txg) != 0 || txg == 0)) {
|
||||
nvlist_free(*config);
|
||||
@@ -777,20 +739,31 @@ zpool_read_label(int fd, nvlist_t **config)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
geom_find_import(libzfs_handle_t *hdl, pool_list_t *pools)
|
||||
/*
|
||||
* Given a list of directories to search, find all pools stored on disk. This
|
||||
* includes partial pools which are not available to import. If no args are
|
||||
* given (argc is 0), then the default directory (/dev) is searched.
|
||||
*/
|
||||
nvlist_t *
|
||||
zpool_find_import(libzfs_handle_t *hdl, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char path[MAXPATHLEN];
|
||||
nvlist_t *ret = NULL, *config;
|
||||
int fd;
|
||||
pool_list_t pools = { 0 };
|
||||
pool_entry_t *pe, *penext;
|
||||
vdev_entry_t *ve, *venext;
|
||||
config_entry_t *ce, *cenext;
|
||||
name_entry_t *ne, *nenext;
|
||||
struct gmesh mesh;
|
||||
struct gclass *mp;
|
||||
struct ggeom *gp;
|
||||
struct gprovider *pp;
|
||||
nvlist_t *config;
|
||||
int fd, ret = 0;
|
||||
|
||||
/*
|
||||
* Go through and read the label configuration information from every
|
||||
* GEOM provider, organizing the information according to pool GUID
|
||||
* possible device, organizing the information according to pool GUID
|
||||
* and toplevel GUID.
|
||||
*/
|
||||
|
||||
@@ -800,183 +773,32 @@ geom_find_import(libzfs_handle_t *hdl, pool_list_t *pools)
|
||||
LIST_FOREACH(mp, &mesh.lg_class, lg_class) {
|
||||
LIST_FOREACH(gp, &mp->lg_geom, lg_geom) {
|
||||
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
|
||||
if ((fd = g_open(pp->lg_name, 0)) < 0)
|
||||
continue;
|
||||
|
||||
(void) snprintf(path, sizeof (path), "%s%s",
|
||||
_PATH_DEV, pp->lg_name);
|
||||
|
||||
if ((fd = open64(path, O_RDONLY)) < 0)
|
||||
continue;
|
||||
|
||||
if ((zpool_read_label(fd, &config)) != 0) {
|
||||
(void) g_close(fd);
|
||||
(void) no_memory(hdl);
|
||||
goto error;
|
||||
}
|
||||
|
||||
(void) g_close(fd);
|
||||
(void) close(fd);
|
||||
|
||||
if (config == NULL)
|
||||
continue;
|
||||
|
||||
if (add_config(hdl, pools, path, config) != 0) {
|
||||
ret = -1;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
error:
|
||||
geom_deletetree(&mesh);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a list of directories to search, find all pools stored on disk. This
|
||||
* includes partial pools which are not available to import. If no args are
|
||||
* given (argc is 0), then the default directory (/dev/dsk) is searched.
|
||||
* poolname or guid (but not both) are provided by the caller when trying
|
||||
* to import a specific pool.
|
||||
*/
|
||||
static nvlist_t *
|
||||
zpool_find_import_impl(libzfs_handle_t *hdl, int argc, char **argv,
|
||||
boolean_t active_ok, char *poolname, uint64_t guid)
|
||||
{
|
||||
int i;
|
||||
DIR *dirp = NULL;
|
||||
struct dirent64 *dp;
|
||||
char path[MAXPATHLEN];
|
||||
char *end;
|
||||
size_t pathleft;
|
||||
struct stat64 statbuf;
|
||||
nvlist_t *ret = NULL, *config;
|
||||
static char *default_dir = "/dev/dsk";
|
||||
int fd;
|
||||
pool_list_t pools = { 0 };
|
||||
pool_entry_t *pe, *penext;
|
||||
vdev_entry_t *ve, *venext;
|
||||
config_entry_t *ce, *cenext;
|
||||
name_entry_t *ne, *nenext;
|
||||
|
||||
verify(poolname == NULL || guid == 0);
|
||||
|
||||
if (argc == 0) {
|
||||
argc = 1;
|
||||
argv = &default_dir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through and read the label configuration information from every
|
||||
* possible device, organizing the information according to pool GUID
|
||||
* and toplevel GUID.
|
||||
*/
|
||||
for (i = 0; i < argc; i++) {
|
||||
char *rdsk;
|
||||
int dfd;
|
||||
|
||||
/* use realpath to normalize the path */
|
||||
if (realpath(argv[i], path) == 0) {
|
||||
(void) zfs_error_fmt(hdl, EZFS_BADPATH,
|
||||
dgettext(TEXT_DOMAIN, "cannot open '%s'"),
|
||||
argv[i]);
|
||||
goto error;
|
||||
}
|
||||
end = &path[strlen(path)];
|
||||
*end++ = '/';
|
||||
*end = 0;
|
||||
pathleft = &path[sizeof (path)] - end;
|
||||
|
||||
if (strcmp(argv[i], default_dir) == 0) {
|
||||
geom_find_import(hdl, &pools);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Using raw devices instead of block devices when we're
|
||||
* reading the labels skips a bunch of slow operations during
|
||||
* close(2) processing, so we replace /dev/dsk with /dev/rdsk.
|
||||
*/
|
||||
if (strcmp(path, "/dev/dsk/") == 0)
|
||||
rdsk = "/dev/rdsk/";
|
||||
else
|
||||
rdsk = path;
|
||||
|
||||
if ((dirp = opendir(rdsk)) == NULL) {
|
||||
zfs_error_aux(hdl, strerror(errno));
|
||||
(void) zfs_error_fmt(hdl, EZFS_BADPATH,
|
||||
dgettext(TEXT_DOMAIN, "cannot open '%s'"),
|
||||
rdsk);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is not MT-safe, but we have no MT consumers of libzfs
|
||||
*/
|
||||
while ((dp = readdir64(dirp)) != NULL) {
|
||||
const char *name = dp->d_name;
|
||||
if (name[0] == '.' &&
|
||||
(name[1] == 0 || (name[1] == '.' && name[2] == 0)))
|
||||
continue;
|
||||
|
||||
(void) snprintf(path, sizeof (path), "%s/%s", rdsk,
|
||||
dp->d_name);
|
||||
|
||||
if ((fd = open64(path, O_RDONLY)) < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Ignore failed stats. We only want regular
|
||||
* files, character devs and block devs.
|
||||
*/
|
||||
if (fstat64(fd, &statbuf) != 0 ||
|
||||
(!S_ISREG(statbuf.st_mode) &&
|
||||
!S_ISCHR(statbuf.st_mode) &&
|
||||
!S_ISBLK(statbuf.st_mode))) {
|
||||
(void) close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((zpool_read_label(fd, &config)) != 0) {
|
||||
(void) close(fd);
|
||||
(void) no_memory(hdl);
|
||||
goto error;
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
|
||||
if (config != NULL) {
|
||||
boolean_t matched = B_TRUE;
|
||||
|
||||
if (poolname != NULL) {
|
||||
char *pname;
|
||||
|
||||
matched = nvlist_lookup_string(config,
|
||||
ZPOOL_CONFIG_POOL_NAME,
|
||||
&pname) == 0 &&
|
||||
strcmp(poolname, pname) == 0;
|
||||
} else if (guid != 0) {
|
||||
uint64_t this_guid;
|
||||
|
||||
matched = nvlist_lookup_uint64(config,
|
||||
ZPOOL_CONFIG_POOL_GUID,
|
||||
&this_guid) == 0 &&
|
||||
guid == this_guid;
|
||||
}
|
||||
if (!matched) {
|
||||
nvlist_free(config);
|
||||
config = NULL;
|
||||
continue;
|
||||
}
|
||||
/* use the non-raw path for the config */
|
||||
(void) strlcpy(end, name, pathleft);
|
||||
if (add_config(hdl, &pools, path, config) != 0)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
(void) closedir(dirp);
|
||||
dirp = NULL;
|
||||
}
|
||||
|
||||
ret = get_configs(hdl, &pools, active_ok);
|
||||
geom_deletetree(&mesh);
|
||||
|
||||
ret = get_configs(hdl, &pools);
|
||||
|
||||
error:
|
||||
for (pe = pools.pools; pe != NULL; pe = penext) {
|
||||
@@ -1001,158 +823,9 @@ error:
|
||||
free(ne);
|
||||
}
|
||||
|
||||
if (dirp)
|
||||
(void) closedir(dirp);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
nvlist_t *
|
||||
zpool_find_import(libzfs_handle_t *hdl, int argc, char **argv)
|
||||
{
|
||||
return (zpool_find_import_impl(hdl, argc, argv, B_FALSE, NULL, 0));
|
||||
}
|
||||
|
||||
nvlist_t *
|
||||
zpool_find_import_byname(libzfs_handle_t *hdl, int argc, char **argv,
|
||||
char *pool)
|
||||
{
|
||||
return (zpool_find_import_impl(hdl, argc, argv, B_FALSE, pool, 0));
|
||||
}
|
||||
|
||||
nvlist_t *
|
||||
zpool_find_import_byguid(libzfs_handle_t *hdl, int argc, char **argv,
|
||||
uint64_t guid)
|
||||
{
|
||||
return (zpool_find_import_impl(hdl, argc, argv, B_FALSE, NULL, guid));
|
||||
}
|
||||
|
||||
nvlist_t *
|
||||
zpool_find_import_activeok(libzfs_handle_t *hdl, int argc, char **argv)
|
||||
{
|
||||
return (zpool_find_import_impl(hdl, argc, argv, B_TRUE, NULL, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a cache file, return the contents as a list of importable pools.
|
||||
* poolname or guid (but not both) are provided by the caller when trying
|
||||
* to import a specific pool.
|
||||
*/
|
||||
nvlist_t *
|
||||
zpool_find_import_cached(libzfs_handle_t *hdl, const char *cachefile,
|
||||
char *poolname, uint64_t guid)
|
||||
{
|
||||
char *buf;
|
||||
int fd;
|
||||
struct stat64 statbuf;
|
||||
nvlist_t *raw, *src, *dst;
|
||||
nvlist_t *pools;
|
||||
nvpair_t *elem;
|
||||
char *name;
|
||||
uint64_t this_guid;
|
||||
boolean_t active;
|
||||
|
||||
verify(poolname == NULL || guid == 0);
|
||||
|
||||
if ((fd = open(cachefile, O_RDONLY)) < 0) {
|
||||
zfs_error_aux(hdl, "%s", strerror(errno));
|
||||
(void) zfs_error(hdl, EZFS_BADCACHE,
|
||||
dgettext(TEXT_DOMAIN, "failed to open cache file"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (fstat64(fd, &statbuf) != 0) {
|
||||
zfs_error_aux(hdl, "%s", strerror(errno));
|
||||
(void) close(fd);
|
||||
(void) zfs_error(hdl, EZFS_BADCACHE,
|
||||
dgettext(TEXT_DOMAIN, "failed to get size of cache file"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((buf = zfs_alloc(hdl, statbuf.st_size)) == NULL) {
|
||||
(void) close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
|
||||
(void) close(fd);
|
||||
free(buf);
|
||||
(void) zfs_error(hdl, EZFS_BADCACHE,
|
||||
dgettext(TEXT_DOMAIN,
|
||||
"failed to read cache file contents"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
|
||||
if (nvlist_unpack(buf, statbuf.st_size, &raw, 0) != 0) {
|
||||
free(buf);
|
||||
(void) zfs_error(hdl, EZFS_BADCACHE,
|
||||
dgettext(TEXT_DOMAIN,
|
||||
"invalid or corrupt cache file contents"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
/*
|
||||
* Go through and get the current state of the pools and refresh their
|
||||
* state.
|
||||
*/
|
||||
if (nvlist_alloc(&pools, 0, 0) != 0) {
|
||||
(void) no_memory(hdl);
|
||||
nvlist_free(raw);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
elem = NULL;
|
||||
while ((elem = nvlist_next_nvpair(raw, elem)) != NULL) {
|
||||
verify(nvpair_value_nvlist(elem, &src) == 0);
|
||||
|
||||
verify(nvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME,
|
||||
&name) == 0);
|
||||
if (poolname != NULL && strcmp(poolname, name) != 0)
|
||||
continue;
|
||||
|
||||
verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID,
|
||||
&this_guid) == 0);
|
||||
if (guid != 0) {
|
||||
verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID,
|
||||
&this_guid) == 0);
|
||||
if (guid != this_guid)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pool_active(hdl, name, this_guid, &active) != 0) {
|
||||
nvlist_free(raw);
|
||||
nvlist_free(pools);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (active)
|
||||
continue;
|
||||
|
||||
if ((dst = refresh_config(hdl, src)) == NULL) {
|
||||
nvlist_free(raw);
|
||||
nvlist_free(pools);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (nvlist_add_nvlist(pools, nvpair_name(elem), dst) != 0) {
|
||||
(void) no_memory(hdl);
|
||||
nvlist_free(dst);
|
||||
nvlist_free(raw);
|
||||
nvlist_free(pools);
|
||||
return (NULL);
|
||||
}
|
||||
nvlist_free(dst);
|
||||
}
|
||||
|
||||
nvlist_free(raw);
|
||||
return (pools);
|
||||
}
|
||||
|
||||
|
||||
boolean_t
|
||||
find_guid(nvlist_t *nv, uint64_t guid)
|
||||
{
|
||||
@@ -1174,28 +847,27 @@ find_guid(nvlist_t *nv, uint64_t guid)
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
typedef struct aux_cbdata {
|
||||
const char *cb_type;
|
||||
typedef struct spare_cbdata {
|
||||
uint64_t cb_guid;
|
||||
zpool_handle_t *cb_zhp;
|
||||
} aux_cbdata_t;
|
||||
} spare_cbdata_t;
|
||||
|
||||
static int
|
||||
find_aux(zpool_handle_t *zhp, void *data)
|
||||
find_spare(zpool_handle_t *zhp, void *data)
|
||||
{
|
||||
aux_cbdata_t *cbp = data;
|
||||
nvlist_t **list;
|
||||
uint_t i, count;
|
||||
spare_cbdata_t *cbp = data;
|
||||
nvlist_t **spares;
|
||||
uint_t i, nspares;
|
||||
uint64_t guid;
|
||||
nvlist_t *nvroot;
|
||||
|
||||
verify(nvlist_lookup_nvlist(zhp->zpool_config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvroot) == 0);
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nvroot, cbp->cb_type,
|
||||
&list, &count) == 0) {
|
||||
for (i = 0; i < count; i++) {
|
||||
verify(nvlist_lookup_uint64(list[i],
|
||||
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
|
||||
&spares, &nspares) == 0) {
|
||||
for (i = 0; i < nspares; i++) {
|
||||
verify(nvlist_lookup_uint64(spares[i],
|
||||
ZPOOL_CONFIG_GUID, &guid) == 0);
|
||||
if (guid == cbp->cb_guid) {
|
||||
cbp->cb_zhp = zhp;
|
||||
@@ -1224,7 +896,7 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
|
||||
zpool_handle_t *zhp;
|
||||
nvlist_t *pool_config;
|
||||
uint64_t stateval, isspare;
|
||||
aux_cbdata_t cb = { 0 };
|
||||
spare_cbdata_t cb = { 0 };
|
||||
boolean_t isactive;
|
||||
|
||||
*inuse = B_FALSE;
|
||||
@@ -1242,7 +914,7 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
|
||||
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID,
|
||||
&vdev_guid) == 0);
|
||||
|
||||
if (stateval != POOL_STATE_SPARE && stateval != POOL_STATE_L2CACHE) {
|
||||
if (stateval != POOL_STATE_SPARE) {
|
||||
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
|
||||
&name) == 0);
|
||||
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
|
||||
@@ -1321,24 +993,7 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
|
||||
*/
|
||||
cb.cb_zhp = NULL;
|
||||
cb.cb_guid = vdev_guid;
|
||||
cb.cb_type = ZPOOL_CONFIG_SPARES;
|
||||
if (zpool_iter(hdl, find_aux, &cb) == 1) {
|
||||
name = (char *)zpool_get_name(cb.cb_zhp);
|
||||
ret = TRUE;
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case POOL_STATE_L2CACHE:
|
||||
|
||||
/*
|
||||
* Check if any pool is currently using this l2cache device.
|
||||
*/
|
||||
cb.cb_zhp = NULL;
|
||||
cb.cb_guid = vdev_guid;
|
||||
cb.cb_type = ZPOOL_CONFIG_L2CACHE;
|
||||
if (zpool_iter(hdl, find_aux, &cb) == 1) {
|
||||
if (zpool_iter(hdl, find_spare, &cb) == 1) {
|
||||
name = (char *)zpool_get_name(cb.cb_zhp);
|
||||
ret = TRUE;
|
||||
} else {
|
||||
@@ -1353,8 +1008,6 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
|
||||
|
||||
if (ret) {
|
||||
if ((*namestr = zfs_strdup(hdl, name)) == NULL) {
|
||||
if (cb.cb_zhp)
|
||||
zpool_close(cb.cb_zhp);
|
||||
nvlist_free(config);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -19,16 +19,18 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* This file contains the functions which analyze the status of a pool. This
|
||||
* include both the status of an active pool, as well as the status exported
|
||||
* pools. Returns one of the ZPOOL_STATUS_* defines describing the status of
|
||||
* the pool. This status is independent (to a certain degree) from the state of
|
||||
* the pool. A pool's state describes only whether or not it is capable of
|
||||
* the pool. A pool's state descsribes only whether or not it is capable of
|
||||
* providing the necessary fault tolerance for data. The status describes the
|
||||
* overall status of devices. A pool that is online can still have a device
|
||||
* that is experiencing errors.
|
||||
@@ -45,7 +47,7 @@
|
||||
#include "libzfs_impl.h"
|
||||
|
||||
/*
|
||||
* Message ID table. This must be kept in sync with the ZPOOL_STATUS_* defines
|
||||
* Message ID table. This must be kep in sync with the ZPOOL_STATUS_* defines
|
||||
* in libzfs.h. Note that there are some status results which go past the end
|
||||
* of this table, and hence have no associated message ID.
|
||||
*/
|
||||
@@ -60,10 +62,26 @@ static char *zfs_msgid_table[] = {
|
||||
"ZFS-8000-8A",
|
||||
"ZFS-8000-9P",
|
||||
"ZFS-8000-A5",
|
||||
"ZFS-8000-EY",
|
||||
"ZFS-8000-HC",
|
||||
"ZFS-8000-JQ",
|
||||
"ZFS-8000-K4",
|
||||
"ZFS-8000-EY"
|
||||
};
|
||||
|
||||
/*
|
||||
* If the pool is active, a certain class of static errors is overridden by the
|
||||
* faults as analayzed by FMA. These faults have separate knowledge articles,
|
||||
* and the article referred to by 'zpool status' must match that indicated by
|
||||
* the syslog error message. We override missing data as well as corrupt pool.
|
||||
*/
|
||||
static char *zfs_msgid_table_active[] = {
|
||||
"ZFS-8000-14",
|
||||
"ZFS-8000-D3", /* overridden */
|
||||
"ZFS-8000-D3", /* overridden */
|
||||
"ZFS-8000-4J",
|
||||
"ZFS-8000-5E",
|
||||
"ZFS-8000-6X",
|
||||
"ZFS-8000-CS", /* overridden */
|
||||
"ZFS-8000-8A",
|
||||
"ZFS-8000-9P",
|
||||
"ZFS-8000-CS", /* overridden */
|
||||
};
|
||||
|
||||
#define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0]))
|
||||
@@ -76,18 +94,11 @@ vdev_missing(uint64_t state, uint64_t aux, uint64_t errs)
|
||||
aux == VDEV_AUX_OPEN_FAILED);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
vdev_faulted(uint64_t state, uint64_t aux, uint64_t errs)
|
||||
{
|
||||
return (state == VDEV_STATE_FAULTED);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
vdev_errors(uint64_t state, uint64_t aux, uint64_t errs)
|
||||
{
|
||||
return (state == VDEV_STATE_DEGRADED || errs != 0);
|
||||
return (errs != 0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -152,9 +163,9 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t))
|
||||
* following:
|
||||
*
|
||||
* - Check for a complete and valid configuration
|
||||
* - Look for any faulted or missing devices in a non-replicated config
|
||||
* - Look for any missing devices in a non-replicated config
|
||||
* - Check for any data errors
|
||||
* - Check for any faulted or missing devices in a replicated config
|
||||
* - Check for any missing devices in a replicated config
|
||||
* - Look for any devices showing errors
|
||||
* - Check for any resilvering devices
|
||||
*
|
||||
@@ -170,7 +181,6 @@ check_status(nvlist_t *config, boolean_t isimport)
|
||||
uint64_t nerr;
|
||||
uint64_t version;
|
||||
uint64_t stateval;
|
||||
uint64_t suspended;
|
||||
uint64_t hostid = 0;
|
||||
|
||||
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
|
||||
@@ -205,30 +215,8 @@ check_status(nvlist_t *config, boolean_t isimport)
|
||||
return (ZPOOL_STATUS_BAD_GUID_SUM);
|
||||
|
||||
/*
|
||||
* Check whether the pool has suspended due to failed I/O.
|
||||
* Missing devices in non-replicated config.
|
||||
*/
|
||||
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED,
|
||||
&suspended) == 0) {
|
||||
if (suspended == ZIO_FAILURE_MODE_CONTINUE)
|
||||
return (ZPOOL_STATUS_IO_FAILURE_CONTINUE);
|
||||
return (ZPOOL_STATUS_IO_FAILURE_WAIT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Could not read a log.
|
||||
*/
|
||||
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
|
||||
vs->vs_aux == VDEV_AUX_BAD_LOG) {
|
||||
return (ZPOOL_STATUS_BAD_LOG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bad devices in non-replicated config.
|
||||
*/
|
||||
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
|
||||
find_vdev_problem(nvroot, vdev_faulted))
|
||||
return (ZPOOL_STATUS_FAULTED_DEV_NR);
|
||||
|
||||
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
|
||||
find_vdev_problem(nvroot, vdev_missing))
|
||||
return (ZPOOL_STATUS_MISSING_DEV_NR);
|
||||
@@ -256,8 +244,6 @@ check_status(nvlist_t *config, boolean_t isimport)
|
||||
/*
|
||||
* Missing devices in a replicated config.
|
||||
*/
|
||||
if (find_vdev_problem(nvroot, vdev_faulted))
|
||||
return (ZPOOL_STATUS_FAULTED_DEV_R);
|
||||
if (find_vdev_problem(nvroot, vdev_missing))
|
||||
return (ZPOOL_STATUS_MISSING_DEV_R);
|
||||
if (find_vdev_problem(nvroot, vdev_broken))
|
||||
@@ -284,7 +270,7 @@ check_status(nvlist_t *config, boolean_t isimport)
|
||||
/*
|
||||
* Outdated, but usable, version
|
||||
*/
|
||||
if (version < SPA_VERSION)
|
||||
if (version < ZFS_VERSION)
|
||||
return (ZPOOL_STATUS_VERSION_OLDER);
|
||||
|
||||
return (ZPOOL_STATUS_OK);
|
||||
@@ -298,7 +284,7 @@ zpool_get_status(zpool_handle_t *zhp, char **msgid)
|
||||
if (ret >= NMSGID)
|
||||
*msgid = NULL;
|
||||
else
|
||||
*msgid = zfs_msgid_table[ret];
|
||||
*msgid = zfs_msgid_table_active[ret];
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Internal utility routines for the ZFS library.
|
||||
*/
|
||||
@@ -35,8 +37,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <sys/mnttab.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/types.h>
|
||||
@@ -44,7 +44,6 @@
|
||||
#include <libzfs.h>
|
||||
|
||||
#include "libzfs_impl.h"
|
||||
#include "zfs_prop.h"
|
||||
|
||||
int
|
||||
libzfs_errno(libzfs_handle_t *hdl)
|
||||
@@ -134,14 +133,6 @@ libzfs_error_description(libzfs_handle_t *hdl)
|
||||
return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
|
||||
case EZFS_SHARENFSFAILED:
|
||||
return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
|
||||
case EZFS_UNSHARESMBFAILED:
|
||||
return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
|
||||
case EZFS_SHARESMBFAILED:
|
||||
return (dgettext(TEXT_DOMAIN, "smb add share failed"));
|
||||
case EZFS_ISCSISVCUNAVAIL:
|
||||
return (dgettext(TEXT_DOMAIN,
|
||||
"iscsitgt service need to be enabled by "
|
||||
"a privileged user"));
|
||||
case EZFS_DEVLINKS:
|
||||
return (dgettext(TEXT_DOMAIN, "failed to create /dev links"));
|
||||
case EZFS_PERM:
|
||||
@@ -178,38 +169,6 @@ libzfs_error_description(libzfs_handle_t *hdl)
|
||||
"this pool operation"));
|
||||
case EZFS_NAMETOOLONG:
|
||||
return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
|
||||
case EZFS_OPENFAILED:
|
||||
return (dgettext(TEXT_DOMAIN, "open failed"));
|
||||
case EZFS_NOCAP:
|
||||
return (dgettext(TEXT_DOMAIN,
|
||||
"disk capacity information could not be retrieved"));
|
||||
case EZFS_LABELFAILED:
|
||||
return (dgettext(TEXT_DOMAIN, "write of label failed"));
|
||||
case EZFS_BADWHO:
|
||||
return (dgettext(TEXT_DOMAIN, "invalid user/group"));
|
||||
case EZFS_BADPERM:
|
||||
return (dgettext(TEXT_DOMAIN, "invalid permission"));
|
||||
case EZFS_BADPERMSET:
|
||||
return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
|
||||
case EZFS_NODELEGATION:
|
||||
return (dgettext(TEXT_DOMAIN, "delegated administration is "
|
||||
"disabled on pool"));
|
||||
case EZFS_PERMRDONLY:
|
||||
return (dgettext(TEXT_DOMAIN, "snapshot permissions cannot be"
|
||||
" modified"));
|
||||
case EZFS_BADCACHE:
|
||||
return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
|
||||
case EZFS_ISL2CACHE:
|
||||
return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
|
||||
case EZFS_VDEVNOTSUP:
|
||||
return (dgettext(TEXT_DOMAIN, "vdev specification is not "
|
||||
"supported"));
|
||||
case EZFS_NOTSUP:
|
||||
return (dgettext(TEXT_DOMAIN, "operation not supported "
|
||||
"on this dataset"));
|
||||
case EZFS_ACTIVE_SPARE:
|
||||
return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
|
||||
"device"));
|
||||
case EZFS_UNKNOWN:
|
||||
return (dgettext(TEXT_DOMAIN, "unknown error"));
|
||||
default:
|
||||
@@ -290,10 +249,6 @@ zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
|
||||
zfs_verror(hdl, EZFS_PERM, fmt, ap);
|
||||
return (-1);
|
||||
|
||||
case ECANCELED:
|
||||
zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
|
||||
return (-1);
|
||||
|
||||
case EIO:
|
||||
zfs_verror(hdl, EZFS_IO, fmt, ap);
|
||||
return (-1);
|
||||
@@ -325,9 +280,9 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
switch (error) {
|
||||
case ENXIO:
|
||||
case ENODEV:
|
||||
zfs_verror(hdl, EZFS_IO, fmt, ap);
|
||||
break;
|
||||
|
||||
@@ -353,17 +308,11 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
|
||||
"dataset is busy"));
|
||||
zfs_verror(hdl, EZFS_BUSY, fmt, ap);
|
||||
break;
|
||||
case EROFS:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"snapshot permissions cannot be modified"));
|
||||
zfs_verror(hdl, EZFS_PERMRDONLY, fmt, ap);
|
||||
break;
|
||||
|
||||
case ENAMETOOLONG:
|
||||
zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
|
||||
break;
|
||||
case ENOTSUP:
|
||||
zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
|
||||
break;
|
||||
|
||||
default:
|
||||
zfs_error_aux(hdl, strerror(errno));
|
||||
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
|
||||
@@ -412,7 +361,7 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
|
||||
|
||||
case EBUSY:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
|
||||
zfs_verror(hdl, EZFS_BUSY, fmt, ap);
|
||||
zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
|
||||
break;
|
||||
|
||||
case ENXIO:
|
||||
@@ -433,11 +382,6 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
|
||||
zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
|
||||
break;
|
||||
|
||||
case ENOSPC:
|
||||
case EDQUOT:
|
||||
zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
|
||||
return (-1);
|
||||
|
||||
default:
|
||||
zfs_error_aux(hdl, strerror(error));
|
||||
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
|
||||
@@ -539,8 +483,9 @@ zfs_nicenum(uint64_t num, char *buf, size_t buflen)
|
||||
*/
|
||||
int i;
|
||||
for (i = 2; i >= 0; i--) {
|
||||
if (snprintf(buf, buflen, "%.*f%c", i,
|
||||
(double)num / (1ULL << 10 * index), u) <= 5)
|
||||
(void) snprintf(buf, buflen, "%.*f%c", i,
|
||||
(double)num / (1ULL << 10 * index), u);
|
||||
if (strlen(buf) <= 5)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -593,9 +538,6 @@ libzfs_init(void)
|
||||
|
||||
hdl->libzfs_sharetab = fopen(ZFS_EXPORTS_PATH, "r");
|
||||
|
||||
zfs_prop_init();
|
||||
zpool_prop_init();
|
||||
|
||||
return (hdl);
|
||||
}
|
||||
|
||||
@@ -607,10 +549,6 @@ libzfs_fini(libzfs_handle_t *hdl)
|
||||
(void) fclose(hdl->libzfs_mnttab);
|
||||
if (hdl->libzfs_sharetab)
|
||||
(void) fclose(hdl->libzfs_sharetab);
|
||||
zfs_uninit_libshare(hdl);
|
||||
if (hdl->libzfs_log_str)
|
||||
(void) free(hdl->libzfs_log_str);
|
||||
zpool_free_handles(hdl);
|
||||
namespace_clear(hdl);
|
||||
free(hdl);
|
||||
}
|
||||
@@ -627,12 +565,6 @@ zfs_get_handle(zfs_handle_t *zhp)
|
||||
return (zhp->zfs_hdl);
|
||||
}
|
||||
|
||||
zpool_handle_t *
|
||||
zfs_get_pool_handle(const zfs_handle_t *zhp)
|
||||
{
|
||||
return (zhp->zpool_hdl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a name, determine whether or not it's a valid path
|
||||
* (starts with '/' or "./"). If so, walk the mnttab trying
|
||||
@@ -705,14 +637,13 @@ zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
|
||||
void
|
||||
zcmd_free_nvlists(zfs_cmd_t *zc)
|
||||
{
|
||||
free((void *)(uintptr_t)zc->zc_nvlist_conf);
|
||||
free((void *)(uintptr_t)zc->zc_nvlist_src);
|
||||
free((void *)(uintptr_t)zc->zc_nvlist_dst);
|
||||
}
|
||||
|
||||
static int
|
||||
zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
|
||||
nvlist_t *nvl)
|
||||
int
|
||||
zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl,
|
||||
size_t *size)
|
||||
{
|
||||
char *packed;
|
||||
size_t len;
|
||||
@@ -724,26 +655,14 @@ zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
|
||||
|
||||
verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
|
||||
|
||||
*outnv = (uint64_t)(uintptr_t)packed;
|
||||
*outlen = len;
|
||||
zc->zc_nvlist_src = (uint64_t)(uintptr_t)packed;
|
||||
zc->zc_nvlist_src_size = len;
|
||||
|
||||
if (size)
|
||||
*size = len;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
|
||||
{
|
||||
return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
|
||||
&zc->zc_nvlist_conf_size, nvl));
|
||||
}
|
||||
|
||||
int
|
||||
zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
|
||||
{
|
||||
return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
|
||||
&zc->zc_nvlist_src_size, nvl));
|
||||
}
|
||||
|
||||
/*
|
||||
* Unpacks an nvlist from the ZFS ioctl command structure.
|
||||
*/
|
||||
@@ -757,32 +676,10 @@ zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
zfs_ioctl(libzfs_handle_t *hdl, unsigned long request, zfs_cmd_t *zc)
|
||||
{
|
||||
int error;
|
||||
|
||||
zc->zc_history = (uint64_t)(uintptr_t)hdl->libzfs_log_str;
|
||||
error = ioctl(hdl->libzfs_fd, request, zc);
|
||||
if (hdl->libzfs_log_str) {
|
||||
free(hdl->libzfs_log_str);
|
||||
hdl->libzfs_log_str = NULL;
|
||||
}
|
||||
zc->zc_history = 0;
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* ================================================================
|
||||
* API shared by zfs and zpool property management
|
||||
* ================================================================
|
||||
*/
|
||||
|
||||
static void
|
||||
zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
|
||||
zfs_print_prop_headers(libzfs_get_cbdata_t *cbp)
|
||||
{
|
||||
zprop_list_t *pl = cbp->cb_proplist;
|
||||
zfs_proplist_t *pl = cbp->cb_proplist;
|
||||
int i;
|
||||
char *title;
|
||||
size_t len;
|
||||
@@ -814,12 +711,8 @@ zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
|
||||
/*
|
||||
* 'PROPERTY' column
|
||||
*/
|
||||
if (pl->pl_prop != ZPROP_INVAL) {
|
||||
const char *propname = (type == ZFS_TYPE_POOL) ?
|
||||
zpool_prop_to_name(pl->pl_prop) :
|
||||
zfs_prop_to_name(pl->pl_prop);
|
||||
|
||||
len = strlen(propname);
|
||||
if (pl->pl_prop != ZFS_PROP_INVAL) {
|
||||
len = strlen(zfs_prop_to_name(pl->pl_prop));
|
||||
if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
|
||||
cbp->cb_colwidths[GET_COL_PROPERTY] = len;
|
||||
} else {
|
||||
@@ -838,8 +731,7 @@ zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
|
||||
/*
|
||||
* 'NAME' and 'SOURCE' columns
|
||||
*/
|
||||
if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
|
||||
ZFS_PROP_NAME) &&
|
||||
if (pl->pl_prop == ZFS_PROP_NAME &&
|
||||
pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
|
||||
cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
|
||||
cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
|
||||
@@ -885,8 +777,8 @@ zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
|
||||
* structure.
|
||||
*/
|
||||
void
|
||||
zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
|
||||
const char *propname, const char *value, zprop_source_t sourcetype,
|
||||
libzfs_print_one_property(const char *name, libzfs_get_cbdata_t *cbp,
|
||||
const char *propname, const char *value, zfs_source_t sourcetype,
|
||||
const char *source)
|
||||
{
|
||||
int i;
|
||||
@@ -900,7 +792,7 @@ zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
|
||||
return;
|
||||
|
||||
if (cbp->cb_first)
|
||||
zprop_print_headers(cbp, cbp->cb_type);
|
||||
zfs_print_prop_headers(cbp);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
switch (cbp->cb_columns[i]) {
|
||||
@@ -918,23 +810,23 @@ zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
|
||||
|
||||
case GET_COL_SOURCE:
|
||||
switch (sourcetype) {
|
||||
case ZPROP_SRC_NONE:
|
||||
case ZFS_SRC_NONE:
|
||||
str = "-";
|
||||
break;
|
||||
|
||||
case ZPROP_SRC_DEFAULT:
|
||||
case ZFS_SRC_DEFAULT:
|
||||
str = "default";
|
||||
break;
|
||||
|
||||
case ZPROP_SRC_LOCAL:
|
||||
case ZFS_SRC_LOCAL:
|
||||
str = "local";
|
||||
break;
|
||||
|
||||
case ZPROP_SRC_TEMPORARY:
|
||||
case ZFS_SRC_TEMPORARY:
|
||||
str = "temporary";
|
||||
break;
|
||||
|
||||
case ZPROP_SRC_INHERITED:
|
||||
case ZFS_SRC_INHERITED:
|
||||
(void) snprintf(buf, sizeof (buf),
|
||||
"inherited from %s", source);
|
||||
str = buf;
|
||||
@@ -959,451 +851,3 @@ zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
|
||||
|
||||
(void) printf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a numeric suffix, convert the value into a number of bits that the
|
||||
* resulting value must be shifted.
|
||||
*/
|
||||
static int
|
||||
str2shift(libzfs_handle_t *hdl, const char *buf)
|
||||
{
|
||||
const char *ends = "BKMGTPEZ";
|
||||
int i;
|
||||
|
||||
if (buf[0] == '\0')
|
||||
return (0);
|
||||
for (i = 0; i < strlen(ends); i++) {
|
||||
if (toupper(buf[0]) == ends[i])
|
||||
break;
|
||||
}
|
||||
if (i == strlen(ends)) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"invalid numeric suffix '%s'"), buf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't
|
||||
* allow 'BB' - that's just weird.
|
||||
*/
|
||||
if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
|
||||
toupper(buf[0]) != 'B'))
|
||||
return (10*i);
|
||||
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"invalid numeric suffix '%s'"), buf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a string of the form '100G' into a real number. Used when setting
|
||||
* properties or creating a volume. 'buf' is used to place an extended error
|
||||
* message for the caller to use.
|
||||
*/
|
||||
int
|
||||
zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
|
||||
{
|
||||
char *end;
|
||||
int shift;
|
||||
|
||||
*num = 0;
|
||||
|
||||
/* Check to see if this looks like a number. */
|
||||
if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
|
||||
if (hdl)
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"bad numeric value '%s'"), value);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Rely on stroll() to process the numeric portion. */
|
||||
errno = 0;
|
||||
*num = strtoll(value, &end, 10);
|
||||
|
||||
/*
|
||||
* Check for ERANGE, which indicates that the value is too large to fit
|
||||
* in a 64-bit value.
|
||||
*/
|
||||
if (errno == ERANGE) {
|
||||
if (hdl)
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"numeric value is too large"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a decimal value, then do the computation with floating
|
||||
* point arithmetic. Otherwise, use standard arithmetic.
|
||||
*/
|
||||
if (*end == '.') {
|
||||
double fval = strtod(value, &end);
|
||||
|
||||
if ((shift = str2shift(hdl, end)) == -1)
|
||||
return (-1);
|
||||
|
||||
fval *= pow(2, shift);
|
||||
|
||||
if (fval > UINT64_MAX) {
|
||||
if (hdl)
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"numeric value is too large"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
*num = (uint64_t)fval;
|
||||
} else {
|
||||
if ((shift = str2shift(hdl, end)) == -1)
|
||||
return (-1);
|
||||
|
||||
/* Check for overflow */
|
||||
if (shift >= 64 || (*num << shift) >> shift != *num) {
|
||||
if (hdl)
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"numeric value is too large"));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
*num <<= shift;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a propname=value nvpair to set, parse any numeric properties
|
||||
* (index, boolean, etc) if they are specified as strings and add the
|
||||
* resulting nvpair to the returned nvlist.
|
||||
*
|
||||
* At the DSL layer, all properties are either 64-bit numbers or strings.
|
||||
* We want the user to be able to ignore this fact and specify properties
|
||||
* as native values (numbers, for example) or as strings (to simplify
|
||||
* command line utilities). This also handles converting index types
|
||||
* (compression, checksum, etc) from strings to their on-disk index.
|
||||
*/
|
||||
int
|
||||
zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
|
||||
zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
|
||||
const char *errbuf)
|
||||
{
|
||||
data_type_t datatype = nvpair_type(elem);
|
||||
zprop_type_t proptype;
|
||||
const char *propname;
|
||||
char *value;
|
||||
boolean_t isnone = B_FALSE;
|
||||
|
||||
if (type == ZFS_TYPE_POOL) {
|
||||
proptype = zpool_prop_get_type(prop);
|
||||
propname = zpool_prop_to_name(prop);
|
||||
} else {
|
||||
proptype = zfs_prop_get_type(prop);
|
||||
propname = zfs_prop_to_name(prop);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert any properties to the internal DSL value types.
|
||||
*/
|
||||
*svalp = NULL;
|
||||
*ivalp = 0;
|
||||
|
||||
switch (proptype) {
|
||||
case PROP_TYPE_STRING:
|
||||
if (datatype != DATA_TYPE_STRING) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"'%s' must be a string"), nvpair_name(elem));
|
||||
goto error;
|
||||
}
|
||||
(void) nvpair_value_string(elem, svalp);
|
||||
if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"'%s' is too long"), nvpair_name(elem));
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_TYPE_NUMBER:
|
||||
if (datatype == DATA_TYPE_STRING) {
|
||||
(void) nvpair_value_string(elem, &value);
|
||||
if (strcmp(value, "none") == 0) {
|
||||
isnone = B_TRUE;
|
||||
} else if (zfs_nicestrtonum(hdl, value, ivalp)
|
||||
!= 0) {
|
||||
goto error;
|
||||
}
|
||||
} else if (datatype == DATA_TYPE_UINT64) {
|
||||
(void) nvpair_value_uint64(elem, ivalp);
|
||||
} else {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"'%s' must be a number"), nvpair_name(elem));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Quota special: force 'none' and don't allow 0.
|
||||
*/
|
||||
if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
|
||||
(prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"use 'none' to disable quota/refquota"));
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_TYPE_INDEX:
|
||||
if (datatype != DATA_TYPE_STRING) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"'%s' must be a string"), nvpair_name(elem));
|
||||
goto error;
|
||||
}
|
||||
|
||||
(void) nvpair_value_string(elem, &value);
|
||||
|
||||
if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"'%s' must be one of '%s'"), propname,
|
||||
zprop_values(prop, type));
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the result to our return set of properties.
|
||||
*/
|
||||
if (*svalp != NULL) {
|
||||
if (nvlist_add_string(ret, propname, *svalp) != 0) {
|
||||
(void) no_memory(hdl);
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
|
||||
(void) no_memory(hdl);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
error:
|
||||
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
|
||||
zfs_type_t type)
|
||||
{
|
||||
int prop;
|
||||
zprop_list_t *entry;
|
||||
|
||||
prop = zprop_name_to_prop(propname, type);
|
||||
|
||||
if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
|
||||
prop = ZPROP_INVAL;
|
||||
|
||||
/*
|
||||
* When no property table entry can be found, return failure if
|
||||
* this is a pool property or if this isn't a user-defined
|
||||
* dataset property,
|
||||
*/
|
||||
if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL ||
|
||||
!zfs_prop_user(propname))) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"invalid property '%s'"), propname);
|
||||
return (zfs_error(hdl, EZFS_BADPROP,
|
||||
dgettext(TEXT_DOMAIN, "bad property list")));
|
||||
}
|
||||
|
||||
if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
|
||||
return (-1);
|
||||
|
||||
entry->pl_prop = prop;
|
||||
if (prop == ZPROP_INVAL) {
|
||||
if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) == NULL) {
|
||||
free(entry);
|
||||
return (-1);
|
||||
}
|
||||
entry->pl_width = strlen(propname);
|
||||
} else {
|
||||
entry->pl_width = zprop_width(prop, &entry->pl_fixed,
|
||||
type);
|
||||
}
|
||||
|
||||
*listp = entry;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a comma-separated list of properties, construct a property list
|
||||
* containing both user-defined and native properties. This function will
|
||||
* return a NULL list if 'all' is specified, which can later be expanded
|
||||
* by zprop_expand_list().
|
||||
*/
|
||||
int
|
||||
zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
|
||||
zfs_type_t type)
|
||||
{
|
||||
*listp = NULL;
|
||||
|
||||
/*
|
||||
* If 'all' is specified, return a NULL list.
|
||||
*/
|
||||
if (strcmp(props, "all") == 0)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* If no props were specified, return an error.
|
||||
*/
|
||||
if (props[0] == '\0') {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"no properties specified"));
|
||||
return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
|
||||
"bad property list")));
|
||||
}
|
||||
|
||||
/*
|
||||
* It would be nice to use getsubopt() here, but the inclusion of column
|
||||
* aliases makes this more effort than it's worth.
|
||||
*/
|
||||
while (*props != '\0') {
|
||||
size_t len;
|
||||
char *p;
|
||||
char c;
|
||||
|
||||
if ((p = strchr(props, ',')) == NULL) {
|
||||
len = strlen(props);
|
||||
p = props + len;
|
||||
} else {
|
||||
len = p - props;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for empty options.
|
||||
*/
|
||||
if (len == 0) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"empty property name"));
|
||||
return (zfs_error(hdl, EZFS_BADPROP,
|
||||
dgettext(TEXT_DOMAIN, "bad property list")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check all regular property names.
|
||||
*/
|
||||
c = props[len];
|
||||
props[len] = '\0';
|
||||
|
||||
if (strcmp(props, "space") == 0) {
|
||||
static char *spaceprops[] = {
|
||||
"name", "avail", "used", "usedbysnapshots",
|
||||
"usedbydataset", "usedbyrefreservation",
|
||||
"usedbychildren", NULL
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; spaceprops[i]; i++) {
|
||||
if (addlist(hdl, spaceprops[i], listp, type))
|
||||
return (-1);
|
||||
listp = &(*listp)->pl_next;
|
||||
}
|
||||
} else {
|
||||
if (addlist(hdl, props, listp, type))
|
||||
return (-1);
|
||||
listp = &(*listp)->pl_next;
|
||||
}
|
||||
|
||||
props = p;
|
||||
if (c == ',')
|
||||
props++;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
zprop_free_list(zprop_list_t *pl)
|
||||
{
|
||||
zprop_list_t *next;
|
||||
|
||||
while (pl != NULL) {
|
||||
next = pl->pl_next;
|
||||
free(pl->pl_user_prop);
|
||||
free(pl);
|
||||
pl = next;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct expand_data {
|
||||
zprop_list_t **last;
|
||||
libzfs_handle_t *hdl;
|
||||
zfs_type_t type;
|
||||
} expand_data_t;
|
||||
|
||||
int
|
||||
zprop_expand_list_cb(int prop, void *cb)
|
||||
{
|
||||
zprop_list_t *entry;
|
||||
expand_data_t *edp = cb;
|
||||
|
||||
if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
|
||||
return (ZPROP_INVAL);
|
||||
|
||||
entry->pl_prop = prop;
|
||||
entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
|
||||
entry->pl_all = B_TRUE;
|
||||
|
||||
*(edp->last) = entry;
|
||||
edp->last = &entry->pl_next;
|
||||
|
||||
return (ZPROP_CONT);
|
||||
}
|
||||
|
||||
int
|
||||
zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
|
||||
{
|
||||
zprop_list_t *entry;
|
||||
zprop_list_t **last;
|
||||
expand_data_t exp;
|
||||
|
||||
if (*plp == NULL) {
|
||||
/*
|
||||
* If this is the very first time we've been called for an 'all'
|
||||
* specification, expand the list to include all native
|
||||
* properties.
|
||||
*/
|
||||
last = plp;
|
||||
|
||||
exp.last = last;
|
||||
exp.hdl = hdl;
|
||||
exp.type = type;
|
||||
|
||||
if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
|
||||
B_FALSE, type) == ZPROP_INVAL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Add 'name' to the beginning of the list, which is handled
|
||||
* specially.
|
||||
*/
|
||||
if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
|
||||
return (-1);
|
||||
|
||||
entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
|
||||
ZFS_PROP_NAME;
|
||||
entry->pl_width = zprop_width(entry->pl_prop,
|
||||
&entry->pl_fixed, type);
|
||||
entry->pl_all = B_TRUE;
|
||||
entry->pl_next = *plp;
|
||||
*plp = entry;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
|
||||
zfs_type_t type)
|
||||
{
|
||||
return (zprop_iter_common(func, cb, show_all, ordered, type));
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -101,24 +101,20 @@ void
|
||||
zmutex_init(kmutex_t *mp)
|
||||
{
|
||||
mp->m_owner = NULL;
|
||||
mp->initialized = B_TRUE;
|
||||
(void) _mutex_init(&mp->m_lock, USYNC_THREAD, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
zmutex_destroy(kmutex_t *mp)
|
||||
{
|
||||
ASSERT(mp->initialized == B_TRUE);
|
||||
ASSERT(mp->m_owner == NULL);
|
||||
(void) _mutex_destroy(&(mp)->m_lock);
|
||||
mp->m_owner = (void *)-1UL;
|
||||
mp->initialized = B_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
mutex_enter(kmutex_t *mp)
|
||||
{
|
||||
ASSERT(mp->initialized == B_TRUE);
|
||||
ASSERT(mp->m_owner != (void *)-1UL);
|
||||
ASSERT(mp->m_owner != curthread);
|
||||
VERIFY(mutex_lock(&mp->m_lock) == 0);
|
||||
@@ -129,7 +125,6 @@ mutex_enter(kmutex_t *mp)
|
||||
int
|
||||
mutex_tryenter(kmutex_t *mp)
|
||||
{
|
||||
ASSERT(mp->initialized == B_TRUE);
|
||||
ASSERT(mp->m_owner != (void *)-1UL);
|
||||
if (mutex_trylock(&mp->m_lock) == 0) {
|
||||
ASSERT(mp->m_owner == NULL);
|
||||
@@ -143,7 +138,6 @@ mutex_tryenter(kmutex_t *mp)
|
||||
void
|
||||
mutex_exit(kmutex_t *mp)
|
||||
{
|
||||
ASSERT(mp->initialized == B_TRUE);
|
||||
ASSERT(mp->m_owner == curthread);
|
||||
mp->m_owner = NULL;
|
||||
VERIFY(mutex_unlock(&mp->m_lock) == 0);
|
||||
@@ -152,7 +146,6 @@ mutex_exit(kmutex_t *mp)
|
||||
void *
|
||||
mutex_owner(kmutex_t *mp)
|
||||
{
|
||||
ASSERT(mp->initialized == B_TRUE);
|
||||
return (mp->m_owner);
|
||||
}
|
||||
|
||||
@@ -167,7 +160,7 @@ rw_init(krwlock_t *rwlp, char *name, int type, void *arg)
|
||||
{
|
||||
rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
|
||||
rwlp->rw_owner = NULL;
|
||||
rwlp->initialized = B_TRUE;
|
||||
rwlp->rw_count = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -175,23 +168,22 @@ rw_destroy(krwlock_t *rwlp)
|
||||
{
|
||||
rwlock_destroy(&rwlp->rw_lock);
|
||||
rwlp->rw_owner = (void *)-1UL;
|
||||
rwlp->initialized = B_FALSE;
|
||||
rwlp->rw_count = -2;
|
||||
}
|
||||
|
||||
void
|
||||
rw_enter(krwlock_t *rwlp, krw_t rw)
|
||||
{
|
||||
//ASSERT(!RW_LOCK_HELD(rwlp));
|
||||
ASSERT(rwlp->initialized == B_TRUE);
|
||||
ASSERT(rwlp->rw_owner != (void *)-1UL);
|
||||
ASSERT(rwlp->rw_owner != curthread);
|
||||
|
||||
if (rw == RW_READER) {
|
||||
VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
|
||||
(void) rw_rdlock(&rwlp->rw_lock);
|
||||
ASSERT(rwlp->rw_count >= 0);
|
||||
atomic_add_int(&rwlp->rw_count, 1);
|
||||
} else {
|
||||
VERIFY(rw_wrlock(&rwlp->rw_lock) == 0);
|
||||
(void) rw_wrlock(&rwlp->rw_lock);
|
||||
ASSERT(rwlp->rw_count == 0);
|
||||
rwlp->rw_count = -1;
|
||||
rwlp->rw_owner = curthread;
|
||||
@@ -201,7 +193,6 @@ rw_enter(krwlock_t *rwlp, krw_t rw)
|
||||
void
|
||||
rw_exit(krwlock_t *rwlp)
|
||||
{
|
||||
ASSERT(rwlp->initialized == B_TRUE);
|
||||
ASSERT(rwlp->rw_owner != (void *)-1UL);
|
||||
|
||||
if (rwlp->rw_owner == curthread) {
|
||||
@@ -214,7 +205,7 @@ rw_exit(krwlock_t *rwlp)
|
||||
ASSERT(rwlp->rw_count > 0);
|
||||
atomic_add_int(&rwlp->rw_count, -1);
|
||||
}
|
||||
VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
|
||||
(void) rw_unlock(&rwlp->rw_lock);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -222,7 +213,6 @@ rw_tryenter(krwlock_t *rwlp, krw_t rw)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ASSERT(rwlp->initialized == B_TRUE);
|
||||
ASSERT(rwlp->rw_owner != (void *)-1UL);
|
||||
ASSERT(rwlp->rw_owner != curthread);
|
||||
|
||||
@@ -251,7 +241,6 @@ rw_tryenter(krwlock_t *rwlp, krw_t rw)
|
||||
int
|
||||
rw_tryupgrade(krwlock_t *rwlp)
|
||||
{
|
||||
ASSERT(rwlp->initialized == B_TRUE);
|
||||
ASSERT(rwlp->rw_owner != (void *)-1UL);
|
||||
|
||||
return (0);
|
||||
@@ -433,10 +422,9 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
|
||||
int x3, vnode_t *startvp, int fd)
|
||||
int x3, vnode_t *startvp)
|
||||
{
|
||||
char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
|
||||
int ret;
|
||||
@@ -444,7 +432,6 @@ vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
|
||||
ASSERT(startvp == rootdir);
|
||||
(void) sprintf(realpath, "/%s", path);
|
||||
|
||||
/* fd ignored for now, need if want to simulate nbmand support */
|
||||
ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
|
||||
|
||||
umem_free(realpath, strlen(path) + 2);
|
||||
@@ -482,7 +469,7 @@ vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
|
||||
}
|
||||
|
||||
void
|
||||
vn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td)
|
||||
vn_close(vnode_t *vp)
|
||||
{
|
||||
close(vp->v_fd);
|
||||
spa_strfree(vp->v_path);
|
||||
@@ -670,8 +657,7 @@ kobj_open_file(char *name)
|
||||
vnode_t *vp;
|
||||
|
||||
/* set vp as the _fd field of the file */
|
||||
if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
|
||||
-1) != 0)
|
||||
if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir) != 0)
|
||||
return ((void *)-1UL);
|
||||
|
||||
file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
|
||||
@@ -693,7 +679,7 @@ kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
|
||||
void
|
||||
kobj_close_file(struct _buf *file)
|
||||
{
|
||||
vn_close((vnode_t *)file->_fd, 0, NULL, NULL);
|
||||
vn_close((vnode_t *)file->_fd);
|
||||
umem_free(file, sizeof (struct _buf));
|
||||
}
|
||||
|
||||
@@ -704,7 +690,7 @@ kobj_get_filesize(struct _buf *file, uint64_t *size)
|
||||
vnode_t *vp = (vnode_t *)file->_fd;
|
||||
|
||||
if (fstat64(vp->v_fd, &st) == -1) {
|
||||
vn_close(vp, 0, NULL, NULL);
|
||||
vn_close(vp);
|
||||
return (errno);
|
||||
}
|
||||
*size = st.st_size;
|
||||
@@ -760,11 +746,10 @@ highbit(ulong_t i)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int random_fd = -1, urandom_fd = -1;
|
||||
|
||||
static int
|
||||
random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
|
||||
random_get_bytes_common(uint8_t *ptr, size_t len, char *devname)
|
||||
{
|
||||
int fd = open(devname, O_RDONLY);
|
||||
size_t resid = len;
|
||||
ssize_t bytes;
|
||||
|
||||
@@ -772,24 +757,26 @@ random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
|
||||
|
||||
while (resid != 0) {
|
||||
bytes = read(fd, ptr, resid);
|
||||
ASSERT3S(bytes, >=, 0);
|
||||
ASSERT(bytes >= 0);
|
||||
ptr += bytes;
|
||||
resid -= bytes;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
random_get_bytes(uint8_t *ptr, size_t len)
|
||||
{
|
||||
return (random_get_bytes_common(ptr, len, random_fd));
|
||||
return (random_get_bytes_common(ptr, len, "/dev/random"));
|
||||
}
|
||||
|
||||
int
|
||||
random_get_pseudo_bytes(uint8_t *ptr, size_t len)
|
||||
{
|
||||
return (random_get_bytes_common(ptr, len, urandom_fd));
|
||||
return (random_get_bytes_common(ptr, len, "/dev/urandom"));
|
||||
}
|
||||
|
||||
int
|
||||
@@ -828,11 +815,7 @@ kernel_init(int mode)
|
||||
dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
|
||||
(double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
|
||||
|
||||
snprintf(hw_serial, sizeof (hw_serial), "%lu",
|
||||
(unsigned long)gethostid());
|
||||
|
||||
VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1);
|
||||
VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1);
|
||||
snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid());
|
||||
|
||||
spa_init(mode);
|
||||
}
|
||||
@@ -841,12 +824,6 @@ void
|
||||
kernel_fini(void)
|
||||
{
|
||||
spa_fini();
|
||||
|
||||
close(random_fd);
|
||||
close(urandom_fd);
|
||||
|
||||
random_fd = -1;
|
||||
urandom_fd = -1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -873,62 +850,3 @@ z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
uid_t
|
||||
crgetuid(cred_t *cr)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
gid_t
|
||||
crgetgid(cred_t *cr)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
crgetngroups(cred_t *cr)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
gid_t *
|
||||
crgetgroups(cred_t *cr)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
ksiddomain_t *
|
||||
ksid_lookupdomain(const char *dom)
|
||||
{
|
||||
ksiddomain_t *kd;
|
||||
|
||||
kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
|
||||
kd->kd_name = spa_strdup(dom);
|
||||
return (kd);
|
||||
}
|
||||
|
||||
void
|
||||
ksiddomain_rele(ksiddomain_t *ksid)
|
||||
{
|
||||
spa_strfree(ksid->kd_name);
|
||||
umem_free(ksid, sizeof (ksiddomain_t));
|
||||
}
|
||||
@@ -19,13 +19,15 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_ZFS_CONTEXT_H
|
||||
#define _SYS_ZFS_CONTEXT_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -62,7 +64,6 @@ extern "C" {
|
||||
#include <fsshare.h>
|
||||
#include <sys/note.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/cred.h>
|
||||
#include <sys/atomic.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/bitmap.h>
|
||||
@@ -77,10 +78,8 @@ extern "C" {
|
||||
#include <sys/debug.h>
|
||||
#include <sys/sdt.h>
|
||||
#include <sys/kstat.h>
|
||||
#include <sys/u8_textprep.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/sysevent/eventdefs.h>
|
||||
#include <machine/atomic.h>
|
||||
|
||||
#define ZFS_EXPORTS_PATH "/etc/zfs/exports"
|
||||
@@ -117,12 +116,11 @@ extern void vcmn_err(int, const char *, __va_list);
|
||||
extern void panic(const char *, ...);
|
||||
extern void vpanic(const char *, __va_list);
|
||||
|
||||
#define fm_panic panic
|
||||
|
||||
/* This definition is copied from assert.h. */
|
||||
#if defined(__STDC__)
|
||||
#if __STDC_VERSION__ - 0 >= 199901L
|
||||
#define verify(EX) (void)((EX) || (__assert(#EX, __FILE__, __LINE__), 0))
|
||||
#define verify(EX) (void)((EX) || \
|
||||
(__assert_c99(#EX, __FILE__, __LINE__, __func__), 0))
|
||||
#else
|
||||
#define verify(EX) (void)((EX) || (__assert(#EX, __FILE__, __LINE__), 0))
|
||||
#endif /* __STDC_VERSION__ - 0 >= 199901L */
|
||||
@@ -169,16 +167,11 @@ _NOTE(CONSTCOND) } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DTrace SDT probes have different signatures in userland than they do in
|
||||
* Dtrace SDT probes have different signatures in userland than they do in
|
||||
* kernel. If they're being used in kernel code, re-define them out of
|
||||
* existence for their counterparts in libzpool.
|
||||
*/
|
||||
|
||||
#ifdef DTRACE_PROBE
|
||||
#undef DTRACE_PROBE
|
||||
#define DTRACE_PROBE(a) ((void)0)
|
||||
#endif /* DTRACE_PROBE */
|
||||
|
||||
#ifdef DTRACE_PROBE1
|
||||
#undef DTRACE_PROBE1
|
||||
#define DTRACE_PROBE1(a, b, c) ((void)0)
|
||||
@@ -219,9 +212,8 @@ extern kthread_t *zk_thread_create(void (*func)(), void *arg);
|
||||
* Mutexes
|
||||
*/
|
||||
typedef struct kmutex {
|
||||
void *m_owner;
|
||||
boolean_t initialized;
|
||||
mutex_t m_lock;
|
||||
void *m_owner;
|
||||
mutex_t m_lock;
|
||||
} kmutex_t;
|
||||
|
||||
#define MUTEX_DEFAULT USYNC_THREAD
|
||||
@@ -251,7 +243,6 @@ extern void *mutex_owner(kmutex_t *mp);
|
||||
typedef struct krwlock {
|
||||
int rw_count;
|
||||
void *rw_owner;
|
||||
boolean_t initialized;
|
||||
rwlock_t rw_lock;
|
||||
} krwlock_t;
|
||||
|
||||
@@ -262,7 +253,6 @@ typedef int krw_t;
|
||||
#define RW_DEFAULT USYNC_THREAD
|
||||
|
||||
#undef RW_READ_HELD
|
||||
#define RW_READ_HELD(x) ((x)->rw_owner == NULL && (x)->rw_count > 0)
|
||||
|
||||
#undef RW_WRITE_HELD
|
||||
#define RW_WRITE_HELD(x) ((x)->rw_owner == curthread)
|
||||
@@ -277,11 +267,6 @@ extern void rw_exit(krwlock_t *rwlp);
|
||||
extern int rw_lock_held(krwlock_t *rwlp);
|
||||
#define rw_downgrade(rwlp) do { } while (0)
|
||||
|
||||
extern uid_t crgetuid(cred_t *cr);
|
||||
extern gid_t crgetgid(cred_t *cr);
|
||||
extern int crgetngroups(cred_t *cr);
|
||||
extern gid_t *crgetgroups(cred_t *cr);
|
||||
|
||||
/*
|
||||
* Condition variables
|
||||
*/
|
||||
@@ -300,8 +285,6 @@ extern void cv_broadcast(kcondvar_t *cv);
|
||||
* Kernel memory
|
||||
*/
|
||||
#define KM_SLEEP UMEM_NOFAIL
|
||||
#define KM_PUSHPAGE KM_SLEEP
|
||||
#define KM_ZERO 0
|
||||
#define KM_NOSLEEP UMEM_DEFAULT
|
||||
#define KMC_NODEBUG UMC_NODEBUG
|
||||
#define kmem_alloc(_s, _f) umem_alloc(_s, _f)
|
||||
@@ -339,9 +322,6 @@ extern void taskq_destroy(taskq_t *);
|
||||
extern void taskq_wait(taskq_t *);
|
||||
extern int taskq_member(taskq_t *, void *);
|
||||
|
||||
#define XVA_MAPSIZE 3
|
||||
#define XVA_MAGIC 0x78766174
|
||||
|
||||
/*
|
||||
* vnodes
|
||||
*/
|
||||
@@ -351,94 +331,44 @@ typedef struct vnode {
|
||||
char *v_path;
|
||||
} vnode_t;
|
||||
|
||||
|
||||
typedef struct xoptattr {
|
||||
timestruc_t xoa_createtime; /* Create time of file */
|
||||
uint8_t xoa_archive;
|
||||
uint8_t xoa_system;
|
||||
uint8_t xoa_readonly;
|
||||
uint8_t xoa_hidden;
|
||||
uint8_t xoa_nounlink;
|
||||
uint8_t xoa_immutable;
|
||||
uint8_t xoa_appendonly;
|
||||
uint8_t xoa_nodump;
|
||||
uint8_t xoa_settable;
|
||||
uint8_t xoa_opaque;
|
||||
uint8_t xoa_av_quarantined;
|
||||
uint8_t xoa_av_modified;
|
||||
} xoptattr_t;
|
||||
|
||||
typedef struct vattr {
|
||||
uint_t va_mask; /* bit-mask of attributes */
|
||||
u_offset_t va_size; /* file size in bytes */
|
||||
} vattr_t;
|
||||
|
||||
|
||||
typedef struct xvattr {
|
||||
vattr_t xva_vattr; /* Embedded vattr structure */
|
||||
uint32_t xva_magic; /* Magic Number */
|
||||
uint32_t xva_mapsize; /* Size of attr bitmap (32-bit words) */
|
||||
uint32_t *xva_rtnattrmapp; /* Ptr to xva_rtnattrmap[] */
|
||||
uint32_t xva_reqattrmap[XVA_MAPSIZE]; /* Requested attrs */
|
||||
uint32_t xva_rtnattrmap[XVA_MAPSIZE]; /* Returned attrs */
|
||||
xoptattr_t xva_xoptattrs; /* Optional attributes */
|
||||
} xvattr_t;
|
||||
|
||||
typedef struct vsecattr {
|
||||
uint_t vsa_mask; /* See below */
|
||||
int vsa_aclcnt; /* ACL entry count */
|
||||
void *vsa_aclentp; /* pointer to ACL entries */
|
||||
int vsa_dfaclcnt; /* default ACL entry count */
|
||||
void *vsa_dfaclentp; /* pointer to default ACL entries */
|
||||
size_t vsa_aclentsz; /* ACE size in bytes of vsa_aclentp */
|
||||
} vsecattr_t;
|
||||
|
||||
#define AT_TYPE 0x00001
|
||||
#define AT_MODE 0x00002
|
||||
#define AT_UID 0x00004
|
||||
#define AT_GID 0x00008
|
||||
#define AT_FSID 0x00010
|
||||
#define AT_NODEID 0x00020
|
||||
#define AT_NLINK 0x00040
|
||||
#define AT_SIZE 0x00080
|
||||
#define AT_ATIME 0x00100
|
||||
#define AT_MTIME 0x00200
|
||||
#define AT_CTIME 0x00400
|
||||
#define AT_RDEV 0x00800
|
||||
#define AT_BLKSIZE 0x01000
|
||||
#define AT_NBLOCKS 0x02000
|
||||
#define AT_SEQ 0x08000
|
||||
#define AT_XVATTR 0x10000
|
||||
#define AT_TYPE 0x0001
|
||||
#define AT_MODE 0x0002
|
||||
#define AT_UID 0x0004
|
||||
#define AT_GID 0x0008
|
||||
#define AT_FSID 0x0010
|
||||
#define AT_NODEID 0x0020
|
||||
#define AT_NLINK 0x0040
|
||||
#define AT_SIZE 0x0080
|
||||
#define AT_ATIME 0x0100
|
||||
#define AT_MTIME 0x0200
|
||||
#define AT_CTIME 0x0400
|
||||
#define AT_RDEV 0x0800
|
||||
#define AT_BLKSIZE 0x1000
|
||||
#define AT_NBLOCKS 0x2000
|
||||
#define AT_SEQ 0x8000
|
||||
|
||||
#define CRCREAT 0
|
||||
|
||||
#define VOP_CLOSE(vp, f, c, o, cr, ct) 0
|
||||
#define VOP_PUTPAGE(vp, of, sz, fl, cr, ct) 0
|
||||
#define VOP_GETATTR(vp, vap, cr, td) ((vap)->va_size = (vp)->v_size, 0)
|
||||
#define VOP_CLOSE(vp, f, c, o, cr) 0
|
||||
#define VOP_PUTPAGE(vp, of, sz, fl, cr) 0
|
||||
#define VOP_GETATTR(vp, vap, fl, cr) ((vap)->va_size = (vp)->v_size, 0)
|
||||
|
||||
#define VOP_FSYNC(vp, f, cr, ct) fsync((vp)->v_fd)
|
||||
#define VOP_FSYNC(vp, f, cr) fsync((vp)->v_fd)
|
||||
|
||||
#define VN_RELE(vp) vn_close(vp, 0, NULL, NULL)
|
||||
#define VN_RELE_ASYNC(vp, taskq) vn_close(vp, 0, NULL, NULL)
|
||||
|
||||
#define vn_lock(vp, type, td)
|
||||
#define VOP_UNLOCK(vp, type, td)
|
||||
#ifdef VFS_LOCK_GIANT
|
||||
#undef VFS_LOCK_GIANT
|
||||
#endif
|
||||
#define VFS_LOCK_GIANT(mp) 0
|
||||
#ifdef VFS_UNLOCK_GIANT
|
||||
#undef VFS_UNLOCK_GIANT
|
||||
#endif
|
||||
#define VFS_UNLOCK_GIANT(vfslocked)
|
||||
#define VN_RELE(vp) vn_close(vp)
|
||||
|
||||
extern int vn_open(char *path, int x1, int oflags, int mode, vnode_t **vpp,
|
||||
int x2, int x3);
|
||||
extern int vn_openat(char *path, int x1, int oflags, int mode, vnode_t **vpp,
|
||||
int x2, int x3, vnode_t *vp, int fd);
|
||||
int x2, int x3, vnode_t *vp);
|
||||
extern int vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len,
|
||||
offset_t offset, int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp);
|
||||
extern void vn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td);
|
||||
extern void vn_close(vnode_t *vp);
|
||||
|
||||
#define vn_remove(path, x1, x2) remove(path)
|
||||
#define vn_rename(from, to, seg) rename((from), (to))
|
||||
@@ -467,9 +397,8 @@ extern void delay(clock_t ticks);
|
||||
|
||||
#define CPU_SEQID (thr_self() & (max_ncpus - 1))
|
||||
|
||||
#ifndef ptob
|
||||
#define ptob(x) ((x) * PAGESIZE)
|
||||
#endif
|
||||
#define kcred NULL
|
||||
#define CRED() NULL
|
||||
|
||||
extern uint64_t physmem;
|
||||
|
||||
@@ -526,31 +455,11 @@ struct bootstat {
|
||||
uint64_t st_size;
|
||||
};
|
||||
|
||||
typedef struct ace_object {
|
||||
uid_t a_who;
|
||||
uint32_t a_access_mask;
|
||||
uint16_t a_flags;
|
||||
uint16_t a_type;
|
||||
uint8_t a_obj_type[16];
|
||||
uint8_t a_inherit_obj_type[16];
|
||||
} ace_object_t;
|
||||
|
||||
|
||||
#define ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
|
||||
#define ACE_ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
|
||||
#define ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
|
||||
#define ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
|
||||
|
||||
extern struct _buf *kobj_open_file(char *name);
|
||||
extern int kobj_read_file(struct _buf *file, char *buf, unsigned size,
|
||||
unsigned off);
|
||||
extern void kobj_close_file(struct _buf *file);
|
||||
extern int kobj_get_filesize(struct _buf *file, uint64_t *size);
|
||||
extern int zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr);
|
||||
extern int zfs_secpolicy_rename_perms(const char *from, const char *to,
|
||||
cred_t *cr);
|
||||
extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr);
|
||||
extern zoneid_t getzoneid(void);
|
||||
/* Random compatibility stuff. */
|
||||
#define lbolt (gethrtime() >> 23)
|
||||
#define lbolt64 (gethrtime() >> 23)
|
||||
@@ -573,32 +482,18 @@ struct file {
|
||||
#define FCREAT O_CREAT
|
||||
#define FOFFMAX 0x0
|
||||
|
||||
/* SID stuff */
|
||||
typedef struct ksiddomain {
|
||||
uint_t kd_ref;
|
||||
uint_t kd_len;
|
||||
char *kd_name;
|
||||
} ksiddomain_t;
|
||||
|
||||
ksiddomain_t *ksid_lookupdomain(const char *);
|
||||
void ksiddomain_rele(ksiddomain_t *);
|
||||
|
||||
#define SX_SYSINIT(name, lock, desc)
|
||||
|
||||
#define SYSCTL_DECL(...)
|
||||
#define SYSCTL_NODE(...)
|
||||
#define SYSCTL_INT(...)
|
||||
#define SYSCTL_UINT(...)
|
||||
#define SYSCTL_ULONG(...)
|
||||
#define SYSCTL_QUAD(...)
|
||||
#ifdef TUNABLE_INT
|
||||
#undef TUNABLE_INT
|
||||
#undef TUNABLE_ULONG
|
||||
#undef TUNABLE_QUAD
|
||||
#endif
|
||||
#define TUNABLE_INT(...)
|
||||
#define TUNABLE_ULONG(...)
|
||||
#define TUNABLE_QUAD(...)
|
||||
|
||||
/* Errors */
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -19,7 +20,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -176,9 +177,6 @@ taskq_create(const char *name, int nthreads, pri_t pri,
|
||||
int t;
|
||||
|
||||
rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL);
|
||||
mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL);
|
||||
cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL);
|
||||
tq->tq_flags = flags | TASKQ_ACTIVE;
|
||||
tq->tq_active = nthreads;
|
||||
tq->tq_nthreads = nthreads;
|
||||
@@ -232,9 +230,6 @@ taskq_destroy(taskq_t *tq)
|
||||
kmem_free(tq->tq_threadlist, nthreads * sizeof (thread_t));
|
||||
|
||||
rw_destroy(&tq->tq_threadlock);
|
||||
mutex_destroy(&tq->tq_lock);
|
||||
cv_destroy(&tq->tq_dispatch_cv);
|
||||
cv_destroy(&tq->tq_wait_cv);
|
||||
|
||||
kmem_free(tq, sizeof (taskq_t));
|
||||
}
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/zfs_context.h>
|
||||
#include <sys/avl.h>
|
||||
@@ -65,58 +67,46 @@ nicenum(uint64_t num, char *buf)
|
||||
}
|
||||
|
||||
static void
|
||||
show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
|
||||
show_vdev_stats(const char *desc, nvlist_t *nv, int indent)
|
||||
{
|
||||
vdev_stat_t *vs;
|
||||
vdev_stat_t v0 = { 0 };
|
||||
uint64_t sec;
|
||||
uint64_t is_log = 0;
|
||||
nvlist_t **child;
|
||||
uint_t c, children;
|
||||
vdev_stat_t *vs;
|
||||
uint64_t sec;
|
||||
char used[6], avail[6];
|
||||
char rops[6], wops[6], rbytes[6], wbytes[6], rerr[6], werr[6], cerr[6];
|
||||
char *prefix = "";
|
||||
|
||||
if (indent == 0 && desc != NULL) {
|
||||
(void) printf(" "
|
||||
if (indent == 0) {
|
||||
(void) printf(" "
|
||||
" capacity operations bandwidth ---- errors ----\n");
|
||||
(void) printf("description "
|
||||
(void) printf("description "
|
||||
"used avail read write read write read write cksum\n");
|
||||
}
|
||||
|
||||
if (desc != NULL) {
|
||||
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log);
|
||||
VERIFY(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
|
||||
(uint64_t **)&vs, &c) == 0);
|
||||
|
||||
if (is_log)
|
||||
prefix = "log ";
|
||||
sec = MAX(1, vs->vs_timestamp / NANOSEC);
|
||||
|
||||
if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS,
|
||||
(uint64_t **)&vs, &c) != 0)
|
||||
vs = &v0;
|
||||
nicenum(vs->vs_alloc, used);
|
||||
nicenum(vs->vs_space - vs->vs_alloc, avail);
|
||||
nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops);
|
||||
nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops);
|
||||
nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes);
|
||||
nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes);
|
||||
nicenum(vs->vs_read_errors, rerr);
|
||||
nicenum(vs->vs_write_errors, werr);
|
||||
nicenum(vs->vs_checksum_errors, cerr);
|
||||
|
||||
sec = MAX(1, vs->vs_timestamp / NANOSEC);
|
||||
(void) printf("%*s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
|
||||
indent, "",
|
||||
indent - 19 - (vs->vs_space ? 0 : 12), desc,
|
||||
vs->vs_space ? 6 : 0, vs->vs_space ? used : "",
|
||||
vs->vs_space ? 6 : 0, vs->vs_space ? avail : "",
|
||||
rops, wops, rbytes, wbytes, rerr, werr, cerr);
|
||||
|
||||
nicenum(vs->vs_alloc, used);
|
||||
nicenum(vs->vs_space - vs->vs_alloc, avail);
|
||||
nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops);
|
||||
nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops);
|
||||
nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes);
|
||||
nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes);
|
||||
nicenum(vs->vs_read_errors, rerr);
|
||||
nicenum(vs->vs_write_errors, werr);
|
||||
nicenum(vs->vs_checksum_errors, cerr);
|
||||
|
||||
(void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
|
||||
indent, "",
|
||||
prefix,
|
||||
indent + strlen(prefix) - 25 - (vs->vs_space ? 0 : 12),
|
||||
desc,
|
||||
vs->vs_space ? 6 : 0, vs->vs_space ? used : "",
|
||||
vs->vs_space ? 6 : 0, vs->vs_space ? avail : "",
|
||||
rops, wops, rbytes, wbytes, rerr, werr, cerr);
|
||||
}
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ctype, &child, &children) != 0)
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0)
|
||||
return;
|
||||
|
||||
for (c = 0; c < children; c++) {
|
||||
@@ -130,7 +120,7 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
|
||||
(void) strcpy(tname, cname);
|
||||
if (nvlist_lookup_uint64(cnv, ZPOOL_CONFIG_NPARITY, &np) == 0)
|
||||
tname[strlen(tname)] = '0' + np;
|
||||
show_vdev_stats(tname, ctype, cnv, indent + 2);
|
||||
show_vdev_stats(tname, cnv, indent + 2);
|
||||
free(tname);
|
||||
}
|
||||
}
|
||||
@@ -141,16 +131,14 @@ show_pool_stats(spa_t *spa)
|
||||
nvlist_t *config, *nvroot;
|
||||
char *name;
|
||||
|
||||
VERIFY(spa_get_stats(spa_name(spa), &config, NULL, 0) == 0);
|
||||
spa_config_enter(spa, RW_READER, FTAG);
|
||||
config = spa_config_generate(spa, NULL, -1ULL, B_TRUE);
|
||||
spa_config_exit(spa, FTAG);
|
||||
|
||||
VERIFY(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvroot) == 0);
|
||||
VERIFY(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
|
||||
&name) == 0);
|
||||
|
||||
show_vdev_stats(name, ZPOOL_CONFIG_CHILDREN, nvroot, 0);
|
||||
show_vdev_stats(NULL, ZPOOL_CONFIG_L2CACHE, nvroot, 0);
|
||||
show_vdev_stats(NULL, ZPOOL_CONFIG_SPARES, nvroot, 0);
|
||||
|
||||
nvlist_free(config);
|
||||
show_vdev_stats(name, nvroot, 0);
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@ SUBDIR= drti \
|
||||
|
||||
.if ${MK_ZFS} != "no"
|
||||
_libzfs= libzfs
|
||||
.if ${MK_LIBTHR} != "no"
|
||||
.if ${MK_LIBTHR} != "no" || ${MK_LIBKSE} != "no"
|
||||
_libzpool= libzpool
|
||||
.endif
|
||||
.endif
|
||||
|
||||
@@ -10,8 +10,8 @@ SRCS= libnvpair.c \
|
||||
nvpair_alloc_fixed.c \
|
||||
nvpair.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
||||
CFLAGS+= -I${.CURDIR}/../../../include # XXX
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
@@ -10,17 +10,14 @@ DPADD= ${LIBUTIL}
|
||||
LDADD= -lutil
|
||||
|
||||
SRCS= deviceid.c \
|
||||
fsshare.c \
|
||||
mkdirp.c \
|
||||
mnttab.c \
|
||||
mkdirp.c \
|
||||
zmount.c \
|
||||
fsshare.c \
|
||||
zone.c
|
||||
|
||||
SRCS+= zfs_deleg.c \
|
||||
zfs_namecheck.c \
|
||||
SRCS+= zfs_namecheck.c \
|
||||
zfs_prop.c \
|
||||
zpool_prop.c \
|
||||
zprop_common.c \
|
||||
libzfs_dataset.c \
|
||||
libzfs_util.c \
|
||||
libzfs_graph.c \
|
||||
@@ -29,7 +26,6 @@ SRCS+= zfs_deleg.c \
|
||||
libzfs_changelist.c \
|
||||
libzfs_config.c \
|
||||
libzfs_import.c \
|
||||
libzfs_sendrecv.c \
|
||||
libzfs_status.c
|
||||
|
||||
CFLAGS+= -DZFS_NO_ACL
|
||||
|
||||
@@ -13,13 +13,11 @@
|
||||
# ATOMIC_SRCS
|
||||
.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "ia64"
|
||||
.PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/atomic/${MACHINE_ARCH}
|
||||
ATOMIC_SRCS= opensolaris_atomic.S
|
||||
ATOMIC_SRCS= atomic.S
|
||||
.else
|
||||
.PATH: ${.CURDIR}/../../../sys/cddl/compat/opensolaris/kern
|
||||
ATOMIC_SRCS= opensolaris_atomic.c
|
||||
.endif
|
||||
# UNICODE_SRCS
|
||||
.PATH: ${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/unicode
|
||||
|
||||
LIB= zpool
|
||||
|
||||
@@ -27,11 +25,9 @@ ZFS_COMMON_SRCS= ${ZFS_COMMON_OBJS:C/.o$/.c/} vdev_file.c
|
||||
ZFS_SHARED_SRCS= ${ZFS_SHARED_OBJS:C/.o$/.c/}
|
||||
KERNEL_SRCS= kernel.c taskq.c util.c
|
||||
LIST_SRCS= list.c
|
||||
UNICODE_SRCS= u8_textprep.c
|
||||
|
||||
SRCS= ${ZFS_COMMON_SRCS} ${ZFS_SHARED_SRCS} \
|
||||
${KERNEL_SRCS} ${LIST_SRCS} ${ATOMIC_SRCS} \
|
||||
${UNICODE_SRCS}
|
||||
${KERNEL_SRCS} ${LIST_SRCS} ${ATOMIC_SRCS}
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
|
||||
@@ -44,13 +40,6 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/lib/libumem
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair
|
||||
# XXX: pthread doesn't have mutex_owned() equivalent, so we need to look
|
||||
# into libthr private structures. That's sooo evil, but it's only for
|
||||
# ZFS debugging tools needs.
|
||||
CFLAGS+= -DWANTS_MUTEX_OWNED
|
||||
CFLAGS+= -I${.CURDIR}/../../../lib/libpthread/thread
|
||||
CFLAGS+= -I${.CURDIR}/../../../lib/libpthread/sys
|
||||
CFLAGS+= -I${.CURDIR}/../../../lib/libthr/arch/${MACHINE_ARCH}/include
|
||||
|
||||
DPADD= ${LIBPTHREAD} ${LIBZ}
|
||||
LDADD= -lpthread -lz
|
||||
@@ -58,6 +47,4 @@ LDADD= -lpthread -lz
|
||||
# atomic.S doesn't like profiling.
|
||||
NO_PROFILE=
|
||||
|
||||
CSTD= c99
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
@@ -1,11 +1,10 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/zpool \
|
||||
${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/zpool
|
||||
|
||||
PROG= zpool
|
||||
MAN= zpool.8
|
||||
SRCS= zpool_main.c zpool_vdev.c zpool_iter.c zpool_util.c zfs_comutil.c
|
||||
SRCS= zpool_main.c zpool_vdev.c zpool_iter.c zpool_util.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
|
||||
@@ -16,7 +15,6 @@ CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libumem/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys
|
||||
|
||||
@@ -7,12 +7,10 @@ SUBDIR= \
|
||||
ctfdump \
|
||||
ctfmerge \
|
||||
sgsmsg \
|
||||
${_zinject} \
|
||||
${_ztest}
|
||||
|
||||
.if ${MK_ZFS} != "no"
|
||||
_zinject= zinject
|
||||
.if ${MK_LIBTHR} != "no"
|
||||
.if ${MK_LIBTHR} != "no" || ${MK_LIBKSE} != "no"
|
||||
_ztest= ztest
|
||||
.endif
|
||||
.endif
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../contrib/opensolaris/cmd/zinject
|
||||
|
||||
PROG= zinject
|
||||
SRCS= zinject.c translate.c
|
||||
NO_MAN=
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
||||
CFLAGS+= -I${.CURDIR}/../../compat/opensolaris/include
|
||||
CFLAGS+= -I${.CURDIR}/../../compat/opensolaris/lib/libumem
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/lib/libzfs/common
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/lib/libzpool/common
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/lib/libnvpair
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/head
|
||||
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
||||
|
||||
DPADD= ${LIBAVL} ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBUMEM} ${LIBUUTIL} \
|
||||
${LIBZFS} ${LIBZPOOL} ${LIBUUTIL}
|
||||
LDADD= -lavl -lgeom -lm -lnvpair -lumem -luutil -lzfs -lzpool
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -1,24 +1,22 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../..//contrib/opensolaris/cmd/ztest
|
||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/ztest
|
||||
|
||||
PROG= ztest
|
||||
NO_MAN=
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
||||
CFLAGS+= -I${.CURDIR}/../../compat/opensolaris/include
|
||||
CFLAGS+= -I${.CURDIR}/../../compat/opensolaris/lib/libumem
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/lib/libzpool/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
||||
CFLAGS+= -I${.CURDIR}/../../contrib/opensolaris/head
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
|
||||
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
||||
|
||||
DPADD= ${LIBM} ${LIBNVPAIR} ${LIBUMEM} ${LIBZPOOL} \
|
||||
${LIBPTHREAD} ${LIBZ} ${LIBAVL}
|
||||
LDADD= -lm -lnvpair -lumem -lzpool -lpthread -lz -lavl
|
||||
|
||||
CSTD= c99
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -6,7 +6,7 @@ SUBDIR= dtrace \
|
||||
${_zdb}
|
||||
|
||||
.if ${MK_ZFS} != "no"
|
||||
.if ${MK_LIBTHR} != "no"
|
||||
.if ${MK_LIBTHR} != "no" || ${MK_LIBKSE} != "no"
|
||||
_zdb= zdb
|
||||
.endif
|
||||
.endif
|
||||
|
||||
@@ -9,9 +9,6 @@ SRCS= zdb.c zdb_il.c
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
|
||||
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
|
||||
@@ -19,10 +16,8 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys
|
||||
CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
|
||||
CFLAGS+= -I${.CURDIR}/../../lib/libumem
|
||||
|
||||
DPADD= ${LIBAVL} ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBPTHREAD} ${LIBUMEM} \
|
||||
${LIBUUTIL} ${LIBZ} ${LIBZFS} ${LIBZPOOL}
|
||||
LDADD= -lavl -lgeom -lm -lnvpair -lpthread -lumem -luutil -lz -lzfs -lzpool
|
||||
|
||||
CSTD= c99
|
||||
DPADD= ${LIBM} ${LIBNVPAIR} ${LIBUMEM} ${LIBZPOOL} \
|
||||
${LIBPTHREAD} ${LIBZ} ${LIBAVL}
|
||||
LDADD= -lm -lnvpair -lumem -lzpool -lpthread -lz -lavl
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
+6
-289
@@ -1,295 +1,17 @@
|
||||
--- 9.4-ESV released ---
|
||||
|
||||
2831. [security] Do not attempt to validate or cache
|
||||
out-of-bailiwick data returned with a secure
|
||||
answer; it must be re-fetched from its original
|
||||
source and validated in that context. [RT #20819]
|
||||
|
||||
2828. [security] Cached CNAME or DNAME RR could be returned to clients
|
||||
without DNSSEC validation. [RT #20737]
|
||||
|
||||
2827. [security] Bogus NXDOMAIN could be cached as if valid. [RT #20712]
|
||||
|
||||
2797. [bug] Don't decrement the dispatch manager's maxbuffers.
|
||||
[RT #20613]
|
||||
|
||||
2790. [bug] Handle DS queries to stub zones. [RT #20440]
|
||||
|
||||
2772. [security] When validating, track whether pending data was from
|
||||
the additional section or not and only return it if
|
||||
validates as secure. [RT #20438]
|
||||
|
||||
--- 9.4-ESVb1 released ---
|
||||
|
||||
2698. [cleanup] configure --enable-libbind is deprecated. [RT #20090]
|
||||
|
||||
2697. [port] win32: ensure that S_IFMT, S_IFDIR, S_IFCHR and
|
||||
S_IFREG are defined after including <isc/stat.h>.
|
||||
[RT #20309]
|
||||
|
||||
2690. [bug] win32: fix isc_thread_key_getspecific() prototype.
|
||||
[RT #20315]
|
||||
|
||||
2689. [bug] Correctly handle snprintf result. [RT #20306]
|
||||
|
||||
2688. [bug] Use INTERFACE_F_POINTTOPOINT, not IFF_POINTOPOINT,
|
||||
to decide to fetch the destination address. [RT #20305]
|
||||
|
||||
2681. [bug] IPSECKEY RR of gateway type 3 was not correctly
|
||||
decoded. [RT #20269]
|
||||
|
||||
2672. [bug] Don't enable searching in 'host' when doing reverse
|
||||
lookups. [RT #20218]
|
||||
|
||||
2525. [experimental] New logging category "query-errors" to provide detailed
|
||||
internal information about query failures, especially
|
||||
about server failures. (backported as a special
|
||||
exception to the general policy) [RT #19027]
|
||||
|
||||
2670. [bug] Unexpected connect failures failed to log enough
|
||||
information to be useful. [RT #20205]
|
||||
|
||||
2649. [bug] Set the domain for forward only zones. [RT #19944]
|
||||
|
||||
2648. [port] win32: isc_time_seconds() was broken. [RT #19900]
|
||||
|
||||
2646. [bug] Incorrect cleanup on error in socket.c. [RT #19987]
|
||||
|
||||
2642. [bug] nsupdate could dump core on solaris when reading
|
||||
improperly formatted key files. [RT #20015]
|
||||
|
||||
2640. [security] A specially crafted update packet will cause named
|
||||
to exit. [RT #20000]
|
||||
|
||||
2637. [func] Rationalize dnssec-signzone's signwithkey() calling.
|
||||
[RT #19959]
|
||||
|
||||
2635. [bug] isc_inet_ntop() incorrectly handled 0.0/16 addresses.
|
||||
[RT #19716]
|
||||
|
||||
2633. [bug] Handle 15 bit rand() functions. [RT #19783]
|
||||
|
||||
2632. [func] util/kit.sh: warn if documentation appears to be out of
|
||||
date. [RT #19922]
|
||||
|
||||
2623. [bug] Named started seaches for DS non-optimally. [RT #19915]
|
||||
|
||||
2621. [doc] Made copyright boilterplate consistent. [RT #19833]
|
||||
|
||||
2920. [bug] Delay thawing the zone until the reload of it has
|
||||
completed successfully. [RT #19750]
|
||||
|
||||
2618. [bug] The sdb and sdlz db_interator_seek() methods could
|
||||
loop infinitely. [RT #19847]
|
||||
|
||||
2617. [bug] ifconfig.sh failed to emit an error message when
|
||||
run from the wrong location. [RT #19375]
|
||||
|
||||
2616. [bug] 'host' used the nameservers from resolv.conf even
|
||||
when a explicit nameserver was specified. [RT #19852]
|
||||
|
||||
2615. [bug] "__attribute__((unused))" was in the wrong place
|
||||
for ia64 gcc builds. [RT #19854]
|
||||
|
||||
2614. [port] win32: 'named -v' should automatically be executed
|
||||
in the foreground. [RT #19844]
|
||||
|
||||
2610. [port] sunos: Change #2363 was not complete. [RT #19796]
|
||||
|
||||
2606. [bug] "delegation-only" was not being accepted in
|
||||
delegation-only type zones. [RT #19717]
|
||||
|
||||
2605. [bug] Accept DS responses from delegation only zones.
|
||||
[RT # 19296]
|
||||
|
||||
2603. [port] win32: handle .exe extension of named-checkzone and
|
||||
named-comilezone argv[0] names under windows.
|
||||
[RT #19767]
|
||||
|
||||
2602. [port] win32: fix debugging command line build of libisccfg.
|
||||
[RT #19767]
|
||||
|
||||
2599. [bug] Address rapid memory growth when validation fails.
|
||||
[RT #19654]
|
||||
|
||||
2595. [bug] Fix unknown extended rcodes in dig. [RT #19625]
|
||||
|
||||
2592. [bug] Treat "any" as a type in nsupdate. [RT #19455]
|
||||
|
||||
2591. [bug] named could die when processing a update in
|
||||
removed_orphaned_ds(). [RT #19507]
|
||||
|
||||
2589. [bug] dns_db_unregister() failed to clear '*dbimp'.
|
||||
[RT #19626]
|
||||
|
||||
2586. [bug] Missing cleanup of SIG rdataset in searching a DLZ DB
|
||||
or SDB. [RT #19577]
|
||||
|
||||
2584. [bug] alpha: gcc optimization could break atomic operations.
|
||||
[RT #19227]
|
||||
|
||||
2583. [port] netbsd: provide a control to not add the compile
|
||||
date to the version string, -DNO_VERSION_DATE.
|
||||
|
||||
2582. [bug] Don't emit warning log message when we attempt to
|
||||
remove non-existant journal. [RT #19516]
|
||||
|
||||
2581. [contrib] dlz/mysql set MYSQL_OPT_RECONNECT option on connection.
|
||||
Requires MySQL 5.0.19 or later. [RT #19084]
|
||||
--- 9.4.3-P2 released ---
|
||||
|
||||
2579. [bug] DNSSEC lookaside validation failed to handle unknown
|
||||
algorithms. [RT #19479]
|
||||
|
||||
2573. [bug] Replacing a non-CNAME record with a CNAME record in a
|
||||
single transaction in a signed zone failed. [RT #19397]
|
||||
|
||||
2568. [bug] Report when the write to indicate a otherwise
|
||||
successful start fails. [RT #19360]
|
||||
|
||||
2567. [bug] dst__privstruct_writefile() could miss write errors.
|
||||
write_public_key() could miss write errors.
|
||||
[RT #19360]
|
||||
|
||||
2564. [bug] Only take EDNS fallback steps when processing timeouts.
|
||||
[RT #19405]
|
||||
|
||||
2563. [bug] Dig could leak a socket causing it to wait forever
|
||||
to exit. [RT #19359]
|
||||
|
||||
2562. [doc] ARM: miscellaneous improvements, reorganization,
|
||||
and some new content.
|
||||
|
||||
2561. [doc] Add isc-config.sh(1) man page. [RT #16378]
|
||||
|
||||
2557. [cleanup] PCI compliance:
|
||||
* new libisc log module file
|
||||
* isc_dir_chroot() now also changes the working
|
||||
directory to "/".
|
||||
* additional INSISTs
|
||||
* additional logging when files can't be removed.
|
||||
|
||||
2553. [bug] Reference leak on DNSSEC validation errors. [RT #19291]
|
||||
|
||||
2552. [bug] zero-no-soa-ttl-cache was not being honoured.
|
||||
[RT #19340]
|
||||
|
||||
2551. [bug] Potential Reference leak on return. [RT #19341]
|
||||
|
||||
2550. [bug] Check --with-openssl=<path> finds <openssl/opensslv.h>.
|
||||
[RT #19343]
|
||||
|
||||
2549. [port] linux: define NR_OPEN if not currently defined.
|
||||
[RT #19344]
|
||||
|
||||
2547. [bug] openssl_link.c:mem_realloc() could reference an
|
||||
out-of-range area of the source buffer. New public
|
||||
function isc_mem_reallocate() was introduced to address
|
||||
this bug. [RT #19313]
|
||||
|
||||
2545. [doc] ARM: Legal hostname checking (check-names) is
|
||||
for SRV RDATA too. [RT #19304]
|
||||
|
||||
2544. [cleanup] Removed unused structure members in adb.c. [RT #19225]
|
||||
|
||||
2542. [doc] Update the description of dig +adflag. [RT #19290]
|
||||
|
||||
2539. [security] Update the interaction between recursion, allow-query,
|
||||
allow-query-cache and allow-recursion. [RT #19198]
|
||||
|
||||
2536. [cleanup] Silence some warnings when -Werror=format-security is
|
||||
specified. [RT #19083]
|
||||
|
||||
2535. [bug] dig +showsearch and +trace interacted badly. [RT #19091]
|
||||
|
||||
2532. [bug] dig: check the question section of the response to
|
||||
see if it matches the asked question. [RT #18495]
|
||||
|
||||
2531. [bug] Change #2207 was incomplete. [RT #19098]
|
||||
|
||||
2529. [cleanup] Upgrade libtool to silence complaints from recent
|
||||
version of autoconf. [RT #18657]
|
||||
|
||||
2528. [cleanup] Silence spurious configure warning about
|
||||
--datarootdir [RT #19096]
|
||||
|
||||
2527. [bug] named could reuse cache on reload with
|
||||
enabling/disabling validation. [RT #19119]
|
||||
|
||||
2523. [bug] Random type rdata freed by dns_nsec_typepresent().
|
||||
[RT #19112]
|
||||
--- 9.4.3-P1 released ---
|
||||
|
||||
2522. [security] Handle -1 from DSA_do_verify().
|
||||
|
||||
2521. [bug] Improve epoll cross compilation support. [RT #19047]
|
||||
|
||||
2519. [bug] dig/host with -4 or -6 didn't work if more than two
|
||||
nameserver addresses of the excluded address family
|
||||
preceded in resolv.conf. [RT #19081]
|
||||
|
||||
2517. [bug] dig +trace with -4 or -6 failed when it chose a
|
||||
nameserver address of the excluded address type.
|
||||
[RT #18843]
|
||||
|
||||
2516. [bug] glue sort for responses was performed even when not
|
||||
needed. [RT #19039]
|
||||
|
||||
2514. [bug] dig/host failed with -4 or -6 when resolv.conf contains
|
||||
a nameserver of the excluded address family.
|
||||
[RT #18848]
|
||||
|
||||
2511. [cleanup] dns_rdata_tofmttext() add const to linebreak.
|
||||
[RT #18885]
|
||||
|
||||
2510. [bug] "dig +sigchase" could trigger REQUIRE failures.
|
||||
[RT #19033]
|
||||
|
||||
2509. [bug] Specifying a fixed query source port was broken.
|
||||
[RT #19051]
|
||||
|
||||
2506. [port] solaris: Check at configure time if
|
||||
hack_shutup_pthreadonceinit is needed. [RT #19037]
|
||||
|
||||
2505. [port] Treat amd64 similarly to x86_64 when determining
|
||||
atomic operation support. [RT #19031]
|
||||
|
||||
2504. [bug] Address race condition in the socket code. [RT #18899]
|
||||
|
||||
2503. [port] linux: improve compatibility with Linux Standard
|
||||
Base. [RT #18793]
|
||||
|
||||
2500. [contrib] contrib/sdb/pgsql/zonetodb.c called non-existent
|
||||
function. [RT #18582]
|
||||
|
||||
2499. [port] solaris: lib/lwres/getaddrinfo.c namespace clash.
|
||||
[RT #18837]
|
||||
|
||||
2498. [bug] Removed a bogus function argument used with
|
||||
ISC_SOCKET_USE_POLLWATCH: it could cause compiler
|
||||
warning or crash named with the debug 1 level
|
||||
of logging. [RT #18917]
|
||||
|
||||
2495. [bug] Tighten RRSIG checks. [RT #18795]
|
||||
|
||||
2494. [bug] dns/sdlz.h and dns/dlz.h were not being installed.
|
||||
[RT #18826]
|
||||
|
||||
2487. [bug] Give TCP connections longer to complete. [RT #18675]
|
||||
|
||||
2485. [bug] Change update's the handling of obscured RRSIG
|
||||
records. Not all orphand DS records were being
|
||||
removed. [RT #18828]
|
||||
|
||||
2479. [bug] xfrout:covers was not properly initalized. [RT #18801]
|
||||
|
||||
2478. [bug] 'addresses' could be used uninitalized in
|
||||
configure_forward(). [RT #18800]
|
||||
|
||||
2476. [doc] ARM: improve documentation for max-journal-size and
|
||||
ixfr-from-differences. [RT #15909] [RT #18541]
|
||||
|
||||
2400. [bug] Log if kqueue()/epoll_create()/open(/dev/poll) fails.
|
||||
[RT #18297]
|
||||
|
||||
--- 9.4.3 released ---
|
||||
|
||||
2490. [port] aix: work around a kernel bug where IPV6_RECVPKTINFO
|
||||
@@ -305,7 +27,7 @@
|
||||
|
||||
2473. [port] linux: raise the limit on open files to the possible
|
||||
maximum value before spawning threads; 'files'
|
||||
specified in named.conf doesn't seem to work with
|
||||
specified in named.conf doesn't seem to work with
|
||||
threads as expected. [RT #18784]
|
||||
|
||||
2472. [port] linux: check the number of available cpu's before
|
||||
@@ -328,11 +50,10 @@
|
||||
2465. [bug] Adb's handling of lame addresses was different
|
||||
for IPv4 and IPv6. [RT #18738]
|
||||
|
||||
2463. [port] linux: POSIX doesn't include the IPv6 Advanced Socket
|
||||
2463. [port] linux: POSIX doesn't include the IPv6 Advanced Socket
|
||||
API and glibc hides parts of the IPv6 Advanced Socket
|
||||
API as a result. This is stupid as it breaks how the
|
||||
two halves (Basic and Advanced) of the IPv6 Socket API
|
||||
were designed to be used but we have to live with it.
|
||||
two halves (Basic and Advanced) of the IPv6 Socket API were designed to be used but we have to live with it.
|
||||
Define _GNU_SOURCE to pull in the IPv6 Advanced Socket
|
||||
API. [RT #18388]
|
||||
|
||||
@@ -438,10 +159,6 @@
|
||||
for select(). To enable this, set ISC_SOCKET_MAXSOCKETS
|
||||
at compilation time. [RT #18433]
|
||||
|
||||
Note: with changes #2469 and #2421 above, there is no
|
||||
need to tweak ISC_SOCKET_MAXSOCKETS at compilation time
|
||||
any more.
|
||||
|
||||
2410. [bug] Correctly delete m_versionInfo. [RT #18432]
|
||||
|
||||
2408. [bug] A duplicate TCP dispatch event could be sent, which
|
||||
@@ -513,7 +230,7 @@
|
||||
2380. [bug] dns_view_find() was not returning NXDOMAIN/NXRRSET
|
||||
proofs which, in turn, caused validation failures
|
||||
for insecure zones immediately below a secure zone
|
||||
the server was authoritative for. [RT #18112]
|
||||
the server was authoritative for. [RT #18112]
|
||||
|
||||
2379. [contrib] queryperf/gen-data-queryperf.py: removed redundant
|
||||
TLDs and supported RRs with TTLs [RT #17972]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
|
||||
Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
|
||||
Copyright (C) 1996-2003 Internet Software Consortium.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
@@ -13,7 +13,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
$Id: COPYRIGHT,v 1.9.18.7 2010/01/07 23:46:07 tbox Exp $
|
||||
$Id: COPYRIGHT,v 1.9.18.5 2008/01/02 23:46:02 tbox Exp $
|
||||
|
||||
Portions Copyright (C) 1996-2001 Nominum, Inc.
|
||||
|
||||
|
||||
+13
-17
@@ -1,6 +1,6 @@
|
||||
Frequently Asked Questions about BIND 9
|
||||
|
||||
Copyright © 2004-2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
Copyright © 2004-2008 Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
Copyright © 2000-2003 Internet Software Consortium.
|
||||
|
||||
@@ -153,29 +153,24 @@ A: BIND 9.3 and later: Use TSIG to select the appropriate view.
|
||||
|
||||
Master 10.0.1.1:
|
||||
key "external" {
|
||||
algorithm hmac-sha256;
|
||||
secret "xxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
algorithm hmac-md5;
|
||||
secret "xxxxxxxx";
|
||||
};
|
||||
view "internal" {
|
||||
match-clients { !key external; // reject message ment for the
|
||||
// external view.
|
||||
10.0.1/24; }; // accept from these addresses.
|
||||
match-clients { !key external; 10.0.1/24; };
|
||||
...
|
||||
};
|
||||
view "external" {
|
||||
match-clients { key external; any; };
|
||||
server 10.0.1.2 { keys external; }; // tag messages from the
|
||||
// external view to the
|
||||
// other servers for the
|
||||
// view.
|
||||
server 10.0.1.2 { keys external; };
|
||||
recursion no;
|
||||
...
|
||||
};
|
||||
|
||||
Slave 10.0.1.2:
|
||||
key "external" {
|
||||
algorithm hmac-sha256;
|
||||
secret "xxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
algorithm hmac-md5;
|
||||
secret "xxxxxxxx";
|
||||
};
|
||||
view "internal" {
|
||||
match-clients { !key external; 10.0.1/24; };
|
||||
@@ -225,13 +220,13 @@ A: You choose one view to be master and the second a slave and transfer
|
||||
|
||||
Master 10.0.1.1:
|
||||
key "external" {
|
||||
algorithm hmac-sha256;
|
||||
secret "xxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
algorithm hmac-md5;
|
||||
secret "xxxxxxxx";
|
||||
};
|
||||
|
||||
key "mykey" {
|
||||
algorithm hmac-sha256;
|
||||
secret "yyyyyyyyyyyyyyyyyyyyyyyy";
|
||||
algorithm hmac-md5;
|
||||
secret "yyyyyyyy";
|
||||
};
|
||||
|
||||
view "internal" {
|
||||
@@ -605,7 +600,7 @@ Q: Why do queries for NSEC3 records fail to return the NSEC3 record?
|
||||
|
||||
A: NSEC3 records are strictly meta data and can only be returned in the
|
||||
authority section. This is done so that signing the zone using NSEC3
|
||||
records does not bring names into existence that do not exist in the
|
||||
records does not bring names into existance that do not exist in the
|
||||
unsigned version of the zone.
|
||||
|
||||
5. Operating-System Specific Questions
|
||||
@@ -830,6 +825,7 @@ A: /dev/random is not configured. Use rndcontrol(8) to tell the kernel to
|
||||
use certain interrupts as a source of random events. You can make this
|
||||
permanent by setting rand_irqs in /etc/rc.conf.
|
||||
|
||||
/etc/rc.conf
|
||||
rand_irqs="3 14 15"
|
||||
|
||||
See also <http://people.freebsd.org/~dougb/randomness.html>.
|
||||
|
||||
+14
-19
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []>
|
||||
<!--
|
||||
- Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
- Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
|
||||
- Copyright (C) 2000-2003 Internet Software Consortium.
|
||||
-
|
||||
- Permission to use, copy, modify, and/or distribute this software for any
|
||||
@@ -17,7 +17,7 @@
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- $Id: FAQ.xml,v 1.4.4.29 2009/10/06 01:33:54 tbox Exp $ -->
|
||||
<!-- $Id: FAQ.xml,v 1.4.4.24 2008/09/10 01:32:25 tbox Exp $ -->
|
||||
|
||||
<article class="faq">
|
||||
<title>Frequently Asked Questions about BIND 9</title>
|
||||
@@ -28,7 +28,6 @@
|
||||
<year>2006</year>
|
||||
<year>2007</year>
|
||||
<year>2008</year>
|
||||
<year>2009</year>
|
||||
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
|
||||
</copyright>
|
||||
<copyright>
|
||||
@@ -319,29 +318,24 @@ Slave: 10.0.1.3 (internal), 10.0.1.4 (external, IP alias)
|
||||
<programlisting>
|
||||
Master 10.0.1.1:
|
||||
key "external" {
|
||||
algorithm hmac-sha256;
|
||||
secret "xxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
algorithm hmac-md5;
|
||||
secret "xxxxxxxx";
|
||||
};
|
||||
view "internal" {
|
||||
match-clients { !key external; // reject message ment for the
|
||||
// external view.
|
||||
10.0.1/24; }; // accept from these addresses.
|
||||
match-clients { !key external; 10.0.1/24; };
|
||||
...
|
||||
};
|
||||
view "external" {
|
||||
match-clients { key external; any; };
|
||||
server 10.0.1.2 { keys external; }; // tag messages from the
|
||||
// external view to the
|
||||
// other servers for the
|
||||
// view.
|
||||
server 10.0.1.2 { keys external; };
|
||||
recursion no;
|
||||
...
|
||||
};
|
||||
|
||||
Slave 10.0.1.2:
|
||||
key "external" {
|
||||
algorithm hmac-sha256;
|
||||
secret "xxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
algorithm hmac-md5;
|
||||
secret "xxxxxxxx";
|
||||
};
|
||||
view "internal" {
|
||||
match-clients { !key external; 10.0.1/24; };
|
||||
@@ -429,13 +423,13 @@ named-checkzone example.com tmp</programlisting>
|
||||
<programlisting>
|
||||
Master 10.0.1.1:
|
||||
key "external" {
|
||||
algorithm hmac-sha256;
|
||||
secret "xxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
algorithm hmac-md5;
|
||||
secret "xxxxxxxx";
|
||||
};
|
||||
|
||||
key "mykey" {
|
||||
algorithm hmac-sha256;
|
||||
secret "yyyyyyyyyyyyyyyyyyyyyyyy";
|
||||
algorithm hmac-md5;
|
||||
secret "yyyyyyyy";
|
||||
};
|
||||
|
||||
view "internal" {
|
||||
@@ -1073,7 +1067,7 @@ empty:
|
||||
NSEC3 records are strictly meta data and can only be
|
||||
returned in the authority section. This is done so that
|
||||
signing the zone using NSEC3 records does not bring names
|
||||
into existence that do not exist in the unsigned version
|
||||
into existance that do not exist in the unsigned version
|
||||
of the zone.
|
||||
</para>
|
||||
</answer>
|
||||
@@ -1476,6 +1470,7 @@ options {
|
||||
</para>
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
/etc/rc.conf
|
||||
rand_irqs="3 14 15"</programlisting>
|
||||
</informalexample>
|
||||
<para>
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
|
||||
|
||||
FreeBSD maintainer's guide to updating BIND 9
|
||||
=============================================
|
||||
|
||||
1) Obtain the latest source distribution from the ISC's FTP server
|
||||
(ftp://ftp.isc.org/isc/bind9/)
|
||||
|
||||
2) Unpack the tarball in a suitable directory, and cd into the new
|
||||
source directory.
|
||||
|
||||
3) Remove unwanted files and directories:
|
||||
|
||||
$ while read pattern ; do rm -rf $pattern ; done \
|
||||
</usr/src/contrib/bind9/FREEBSD-Xlist
|
||||
|
||||
Make sure that took care of everything, and if it didn't, make sure
|
||||
to update FREEBSD-Xlist so you won't miss it the next time. A good
|
||||
way to do this is to run a test import and see if any new files
|
||||
show up:
|
||||
|
||||
$ cvs -q -n import src/contrib/bind9 ISC x | grep \^N
|
||||
|
||||
4) Import the sources:
|
||||
|
||||
$ cvs import -m "Vendor import of BIND 9.X.Y" \
|
||||
src/contrib/bind9 ISC BIND_9_X_Y
|
||||
|
||||
5) Resolve conflicts.
|
||||
|
||||
As of 2 June 2007, we have no local patches against BIND 9; thus
|
||||
there are no conflicts to merge. This may change at a later date.
|
||||
|
||||
5a) Remove any files that are no longer in the tarball from the vendor branch.
|
||||
|
||||
6) Remove any references to the {bin,lib}/tests and docutil
|
||||
directories from the configure and Makefile templates:
|
||||
|
||||
$ sed -i.orig -e '/\/tests/d; /docutil/d; /\/xsl/d;' \
|
||||
configure.in Makefile.in */Makefile.in
|
||||
|
||||
Please do not commit this change, as it would unnecessarily take
|
||||
files off the vendor branch. You only need this to generate
|
||||
config.h.
|
||||
|
||||
7) Generate and run configure:
|
||||
|
||||
$ aclocal
|
||||
$ autoheader
|
||||
$ autoconf
|
||||
$ ./configure --prefix=/usr \
|
||||
--infodir=/usr/share/info --mandir=/usr/share/man \
|
||||
--enable-threads --enable-libbind --disable-ipv6 \
|
||||
--enable-getifaddrs --disable-linux-caps \
|
||||
--with-openssl=/usr --with-randomdev=/dev/random
|
||||
|
||||
Note that we intentionally disable IPv6 support on the configure
|
||||
command line; src/lib/bind/config.mk will re-enable it at compile
|
||||
time if WITHOUT_INET6 is not defined.
|
||||
|
||||
8) Copy the following generated files to src/lib/bind and commit them:
|
||||
|
||||
Path in src/contrib/bind9 Path in src/lib/bind
|
||||
------------------------------------------------------------
|
||||
s=/usr/src/lib/bind
|
||||
cp config.h ${s}/config.h
|
||||
cp lib/bind/config.h ${s}/bind/config.h
|
||||
cp lib/bind/port_after.h ${s}/bind/port_after.h
|
||||
cp lib/bind/port_before.h ${s}/bind/port_before.h
|
||||
cp lib/isc/include/isc/platform.h ${s}/isc/isc/platform.h
|
||||
cp lib/lwres/include/lwres/netdb.h ${s}/lwres/lwres/netdb.h
|
||||
cp lib/lwres/include/lwres/platform.h ${s}/lwres/lwres/platform.h
|
||||
|
||||
Do not commit any other file that was modified or created in
|
||||
steps 6) or 7).
|
||||
|
||||
9) cd src/lib/bind/dns && make -DMAINTAINER_MODE generate && rm gen
|
||||
Commit the new versions of the files generated.
|
||||
|
||||
The following directories contain Makefiles for bits and pieces of
|
||||
BIND 9:
|
||||
|
||||
FreeBSD directory ISC directory
|
||||
========================================================
|
||||
src/lib/bind bind9/lib
|
||||
src/lib/bind/bind bind9/lib/bind
|
||||
src/lib/bind/bind9 bind9/lib/bind9
|
||||
src/lib/bind/dns bind9/lib/dns
|
||||
src/lib/bind/isc bind9/lib/isc
|
||||
src/lib/bind/isccc bind9/lib/isccc
|
||||
src/lib/bind/isccfg bind9/lib/isccfg
|
||||
src/lib/bind/lwres bind9/lib/lwres
|
||||
src/share/doc/bind9 bind9/doc/{arm,misc}
|
||||
src/usr.bin/dig bind9/bin/dig
|
||||
src/usr.bin/host bind9/bin/dig
|
||||
src/usr.bin/nslookup bind9/bin/dig
|
||||
src/usr.bin/nsupdate bind9/bin/nsupdate
|
||||
src/usr.sbin/dnssec-keygen bind9/bin/dnssec
|
||||
src/usr.sbin/dnssec-signzone bind9/bin/dnssec
|
||||
src/usr.sbin/named bind9/bin/named
|
||||
src/usr.sbin/named-checkconf bind9/bin/check
|
||||
src/usr.sbin/named-checkzone bind9/bin/check
|
||||
src/usr.sbin/rndc bind9/bin/rndc
|
||||
src/usr.sbin/rndc-confgen bind9/bin/rndc
|
||||
|
||||
Make sure that the lists of sources, headers and man pages in each
|
||||
FreeBSD Makefile accurately reflects those in the corresponding ISC
|
||||
Makefile. Please strive to keep those lists in the same order and
|
||||
with line breaks in the same places to ease future comparisons.
|
||||
|
||||
A) Build and test.
|
||||
|
||||
B) Lather, rinse, repeat.
|
||||
|
||||
C) Commit when everything builds cleanly and works properly.
|
||||
|
||||
-- [email protected]
|
||||
-- [email protected]
|
||||
|
||||
$FreeBSD$
|
||||
@@ -0,0 +1,67 @@
|
||||
# $FreeBSD$
|
||||
|
||||
# Misc. stuff
|
||||
.cvsignore
|
||||
aclocal.m4
|
||||
config.h.in
|
||||
configure
|
||||
contrib
|
||||
docutil
|
||||
|
||||
# Tests
|
||||
bin/tests
|
||||
lib/tests
|
||||
|
||||
# Doc stuff
|
||||
doc/arm/latex-fixup.pl
|
||||
doc/xsl
|
||||
|
||||
# Windows directories
|
||||
bin/check/win32
|
||||
bin/dig/win32
|
||||
bin/dnssec/win32
|
||||
bin/named/win32
|
||||
bin/nsupdate/win32
|
||||
bin/rndc/win32
|
||||
bin/win32
|
||||
config.h.win32
|
||||
lib/bind9/win32
|
||||
lib/dns/gen-win32.h
|
||||
lib/dns/win32
|
||||
lib/isc/win32
|
||||
lib/isccc/win32
|
||||
lib/isccfg/win32
|
||||
lib/lwres/win32
|
||||
lib/win32
|
||||
win32utils
|
||||
|
||||
# Various ports to other OSs
|
||||
lib/bind/port/aix*
|
||||
lib/bind/port/aux3
|
||||
lib/bind/port/bsdos
|
||||
lib/bind/port/bsdos2
|
||||
lib/bind/port/cygwin
|
||||
lib/bind/port/darwin
|
||||
lib/bind/port/decunix
|
||||
lib/bind/port/hpux
|
||||
lib/bind/port/hpux10
|
||||
lib/bind/port/hpux9
|
||||
lib/bind/port/irix
|
||||
lib/bind/port/linux
|
||||
lib/bind/port/lynxos
|
||||
lib/bind/port/mpe
|
||||
lib/bind/port/netbsd
|
||||
lib/bind/port/next
|
||||
lib/bind/port/openbsd
|
||||
lib/bind/port/prand_conf
|
||||
lib/bind/port/qnx
|
||||
lib/bind/port/rhapsody
|
||||
lib/bind/port/sco42
|
||||
lib/bind/port/sco50
|
||||
lib/bind/port/solaris
|
||||
lib/bind/port/sunos
|
||||
lib/bind/port/ultrix
|
||||
lib/bind/port/unixware20
|
||||
lib/bind/port/unixware212
|
||||
lib/bind/port/unixware7
|
||||
lib/bind/port/unknown
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
|
||||
# Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
|
||||
# Copyright (C) 1998-2002 Internet Software Consortium.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
@@ -13,7 +13,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.43.18.8 2009/02/20 23:46:01 tbox Exp $
|
||||
# $Id: Makefile.in,v 1.43.18.6 2007/09/03 23:46:21 tbox Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@@ -24,12 +24,6 @@ top_srcdir = @top_srcdir@
|
||||
SUBDIRS = make lib bin doc @LIBBIND@
|
||||
TARGETS =
|
||||
|
||||
MANPAGES = isc-config.sh.1
|
||||
|
||||
HTMLPAGES = isc-config.sh.html
|
||||
|
||||
MANOBJS = ${MANPAGES} ${HTMLPAGES}
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
distclean::
|
||||
@@ -49,19 +43,12 @@ distclean::
|
||||
maintainer-clean::
|
||||
rm -f configure
|
||||
|
||||
docclean manclean maintainer-clean::
|
||||
rm -f ${MANOBJS}
|
||||
|
||||
doc man:: ${MANOBJS}
|
||||
|
||||
installdirs:
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} \
|
||||
${DESTDIR}${localstatedir}/run ${DESTDIR}${sysconfdir}
|
||||
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1
|
||||
|
||||
install:: isc-config.sh installdirs
|
||||
${INSTALL_SCRIPT} isc-config.sh ${DESTDIR}${bindir}
|
||||
${INSTALL_DATA} ${srcdir}/isc-config.sh.1 ${DESTDIR}${mandir}/man1
|
||||
|
||||
tags:
|
||||
rm -f TAGS
|
||||
|
||||
+12
-23
@@ -27,8 +27,8 @@ BIND 9
|
||||
- Improved Portability Architecture
|
||||
|
||||
|
||||
BIND version 9 development has been under written by the following
|
||||
organisations:
|
||||
BIND version 9 development has been underwritten by the following
|
||||
organizations:
|
||||
|
||||
Sun Microsystems, Inc.
|
||||
Hewlett Packard
|
||||
@@ -42,16 +42,6 @@ BIND 9
|
||||
Stichting NLnet - NLnet Foundation
|
||||
Nominum, Inc.
|
||||
|
||||
BIND 9.4-ESV (Extended Support Version)
|
||||
|
||||
BIND 9.4-ESV is the Extended Support Version of BIND 9.4
|
||||
and incorporates the final maintenance release fixing bugs
|
||||
in BIND 9.4.3.
|
||||
|
||||
BIND 9.4-ESV will be supported until December 31, 2010, at
|
||||
which time you will need to upgrade to the current release
|
||||
of BIND.
|
||||
|
||||
BIND 9.4.3
|
||||
|
||||
BIND 9.4.3 is a maintenance release, fixing bugs in 9.4.2.
|
||||
@@ -77,7 +67,7 @@ BIND 9.4.0
|
||||
Implemented "additional section caching" (or "acache"), an
|
||||
internal cache framework for additional section content to
|
||||
improve response performance. Several configuration options
|
||||
were provided to control the behaviour.
|
||||
were provided to control the behavior.
|
||||
|
||||
New notify type 'master-only'. Enable notify for master
|
||||
zones only.
|
||||
@@ -86,14 +76,13 @@ BIND 9.4.0
|
||||
|
||||
rndc now allows addresses to be set in the server clauses.
|
||||
|
||||
New option "allow-query-cache". This lets "allow-query"
|
||||
be used to specify the default zone access level rather
|
||||
than having to have every zone override the global value.
|
||||
"allow-query-cache" can be set at both the options and view
|
||||
levels. If "allow-query-cache" is not set then "allow-recursion"
|
||||
is used if set, otherwise "allow-query" is used if set
|
||||
unless "recursion no;" is set in which case "none;" is used,
|
||||
otherwise the default (localhost; localnets;) is used.
|
||||
New option "allow-query-cache". This lets allow-query be
|
||||
used to specify the default zone access level rather than
|
||||
having to have every zone override the global value.
|
||||
allow-query-cache can be set at both the options and view
|
||||
levels. If allow-query-cache is not set then allow-recursion
|
||||
is used if set, otherwise allow-query is used if set, otherwise
|
||||
the default (localhost; localnets;) is used.
|
||||
|
||||
rndc: the source address can now be specified.
|
||||
|
||||
@@ -161,12 +150,12 @@ BIND 9.4.0
|
||||
options for dnssec-signzone specify the input and output
|
||||
formats.
|
||||
|
||||
dnssec-signzone can now randomise signature end times
|
||||
dnssec-signzone can now randomize signature end times
|
||||
(dnssec-signzone -j jitter).
|
||||
|
||||
Add support for CH A record.
|
||||
|
||||
Add additional zone data consistency checks. named-checkzone
|
||||
Add additional zone data consistancy checks. named-checkzone
|
||||
has extended checking of NS, MX and SRV record and the hosts
|
||||
they reference. named has extended post zone load checks.
|
||||
New zone options: check-mx and integrity-check.
|
||||
|
||||
@@ -55,7 +55,7 @@ at least specify `--with-idn' option to enable IDN support.
|
||||
|
||||
`--with-libiconv' assumes that your C compiler has `-R'
|
||||
option, and that the option adds the specified run-time path
|
||||
to an executable binary. If `-R' option of your compiler has
|
||||
to an exacutable binary. If `-R' option of your compiler has
|
||||
different meaning, or your compiler lacks the option, you
|
||||
should use `--with-iconv' option instead. Binary command
|
||||
without run-time path information might be unexecutable.
|
||||
@@ -68,7 +68,7 @@ at least specify `--with-idn' option to enable IDN support.
|
||||
specified, `--with-iconv' is prior to `--with-libiconv'.
|
||||
|
||||
--with-iconv=ICONV_LIBSPEC
|
||||
If your libc doesn't provide iconv(), you need to specify the
|
||||
If your libc doens't provide iconv(), you need to specify the
|
||||
library containing iconv() with this option. `ICONV_LIBSPEC'
|
||||
is the argument(s) to `cc' or `ld' to link the library, for
|
||||
example, `--with-iconv="-L/usr/local/lib -liconv"'.
|
||||
@@ -82,7 +82,7 @@ at least specify `--with-idn' option to enable IDN support.
|
||||
this option is not specified, `-L${PREFIX}/lib -lidnkit' is
|
||||
assumed, where ${PREFIX} is the installation prefix specified
|
||||
with `--with-idn' option above. You may need to use this
|
||||
option to specify extra arguments, for example,
|
||||
option to specify extra argments, for example,
|
||||
`--with-idnlib="-L/usr/local/lib -R/usr/local/lib -lidnkit"'.
|
||||
|
||||
Please consult `README' for other configuration options.
|
||||
@@ -109,4 +109,4 @@ about idnkit and this patch.
|
||||
Bug reports and comments on this kit should be sent to
|
||||
[email protected] and [email protected], respectively.
|
||||
|
||||
; $Id: README.idnkit,v 1.2.2.3 2009/01/19 00:36:25 marka Exp $
|
||||
; $Id: README.idnkit,v 1.2.2.2 2005/09/12 02:12:08 marka Exp $
|
||||
Loaded 100 of 2443 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user