IFC to head to catch up the bhyve branch

Approved by:	grehan@
This commit is contained in:
Sean Bruno 2012-01-04 02:01:27 +00:00
commit 80dbff4e99
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/bhyve/; revision=229455
2938 changed files with 286981 additions and 95139 deletions

View File

@ -4,7 +4,7 @@
The compilation of software known as FreeBSD is distributed under the
following terms:
Copyright (c) 1992-2011 The FreeBSD Project. All rights reserved.
Copyright (c) 1992-2012 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

View File

@ -59,8 +59,6 @@ SUBDIR+=games
.endif
.if ${MK_CDDL} != "no"
SUBDIR+=cddl
.else
NO_CTF=1
.endif
SUBDIR+=gnu include
.if ${MK_KERBEROS} != "no"
@ -239,7 +237,7 @@ BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \
BOOTSTRAPPING=${OSRELDATE} \
SSP_CFLAGS= \
-DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT -DWITHOUT_MAN \
-DNO_PIC -DWITHOUT_PROFILE -DNO_SHARED \
-DNO_PIC -DNO_PROFILE -DNO_SHARED \
-DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF
# build-tools stage
@ -278,7 +276,6 @@ LIB32CPUFLAGS= -march=i686 -mmmx -msse -msse2
.else
LIB32CPUFLAGS= -march=${TARGET_CPUTYPE}
.endif
LIB32CPUFLAGS+= -mfancy-math-387
LIB32WMAKEENV= MACHINE=i386 MACHINE_ARCH=i386 \
MACHINE_CPU="i686 mmx sse sse2" \
LD="${LD} -m elf_i386_fbsd -Y P,${LIB32TMP}/usr/lib32" \
@ -438,7 +435,7 @@ _libraries:
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; \
${WMAKE} -DNO_FSCHG -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT \
-DWITHOUT_MAN -DWITHOUT_PROFILE libraries
-DWITHOUT_MAN -DNO_PROFILE libraries
_depend:
@echo
@echo "--------------------------------------------------------------"
@ -1218,6 +1215,9 @@ _startup_libs+= lib/csu/${MACHINE_CPUARCH}
_startup_libs+= gnu/lib/libgcc
_startup_libs+= lib/libcompiler_rt
_startup_libs+= lib/libc
.if ${MK_LIBCPLUSPLUS} != "no"
_startup_libs+= lib/libcxxrt
.endif
gnu/lib/libgcc__L: lib/libc__L
@ -1230,13 +1230,12 @@ _prebuild_libs= ${_kerberos5_lib_libasn1} ${_kerberos5_lib_libhdb} \
${_lib_libgssapi} ${_lib_libipx} \
lib/libkiconv lib/libkvm lib/liblzma lib/libmd \
lib/ncurses/ncurses lib/ncurses/ncursesw \
lib/libopie ${_lib_libthr} \
lib/libopie lib/libpam ${_lib_libthr} \
lib/libradius lib/libsbuf lib/libtacplus \
${_cddl_lib_libumem} \
lib/libutil ${_lib_libypclnt} lib/libz lib/msun \
${_secure_lib_libcrypto} ${_secure_lib_libssh} \
${_secure_lib_libssl} \
lib/libpam
${_secure_lib_libssl}
.if ${MK_LIBTHR} != "no"
_lib_libthr= lib/libthr
@ -1319,12 +1318,12 @@ ${_lib}__PL: .PHONY
cd ${.CURDIR}/${_lib}; \
${MAKE} DIRPRFX=${_lib}/ obj; \
${MAKE} DIRPRFX=${_lib}/ depend; \
${MAKE} -DWITHOUT_PROFILE -DNO_PIC DIRPRFX=${_lib}/ all; \
${MAKE} -DWITHOUT_PROFILE -DNO_PIC DIRPRFX=${_lib}/ install
${MAKE} -DNO_PROFILE -DNO_PIC DIRPRFX=${_lib}/ all; \
${MAKE} -DNO_PROFILE -DNO_PIC DIRPRFX=${_lib}/ install
.endif
.endfor
.for _lib in ${_startup_libs} ${_prebuild_libs} ${_generic_libs}
.for _lib in ${_startup_libs} ${_prebuild_libs:Nlib/libpam} ${_generic_libs}
${_lib}__L: .PHONY
.if exists(${.CURDIR}/${_lib})
${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \
@ -1336,6 +1335,17 @@ ${_lib}__L: .PHONY
.endif
.endfor
# libpam is special: we need to build static PAM modules before
# static PAM library, and dynamic PAM library before dynamic PAM
# modules.
lib/libpam__L: .PHONY
${_+_}@${ECHODIR} "===> lib/libpam (obj,depend,all,install)"; \
cd ${.CURDIR}/lib/libpam; \
${MAKE} DIRPRFX=lib/libpam/ obj; \
${MAKE} DIRPRFX=lib/libpam/ depend; \
${MAKE} DIRPRFX=lib/libpam/ -D_NO_LIBPAM_SO_YET all; \
${MAKE} DIRPRFX=lib/libpam/ -D_NO_LIBPAM_SO_YET install
_prereq_libs: ${_prereq_libs:S/$/__PL/}
_startup_libs: ${_startup_libs:S/$/__L/}
_prebuild_libs: ${_prebuild_libs:S/$/__L/}
@ -1542,7 +1552,7 @@ XDEV_CPUTYPE?=${TARGET_CPUTYPE}
.endif
NOFUN=-DNO_FSCHG -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT \
-DWITHOUT_MAN -DWITHOUT_NLS -DWITHOUT_PROFILE \
-DWITHOUT_MAN -DWITHOUT_NLS -DNO_PROFILE \
-DWITHOUT_KERBEROS -DWITHOUT_RESCUE -DNO_WARNS \
TARGET=${XDEV} TARGET_ARCH=${XDEV_ARCH} \
CPUTYPE=${XDEV_CPUTYPE}
@ -1626,4 +1636,7 @@ _xi-links:
ln -sf ../../${XDTP}/usr/bin/$$i \
../../../../usr/bin/${XDDIR}${OSREL}-$$i; \
done
.else
xdev xdev-buil xdev-install:
@echo "*** Error: Both XDEV and XDEV_ARCH must be defined for \"${.TARGET}\" target"
.endif

View File

@ -38,6 +38,21 @@
# xargs -n1 | sort | uniq -d;
# done
# 20111214: eventtimers(7) moved to eventtimers(4)
OLD_FILES+=usr/share/man/man7/eventtimers.7.gz
# 20111125: amd(4) removed
OLD_FILES+=usr/share/man/man4/amd.4.gz
# 20111125: libodialog removed
OLD_FILES+=usr/lib/libodialog.a
OLD_FILES+=usr/lib/libodialog.so
OLD_LIBS+=usr/lib/libodialog.so.7
OLD_FILES+=usr/lib/libodialog_p.a
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
OLD_FILES+=usr/lib32/libodialog.a
OLD_FILES+=usr/lib32/libodialog.so
OLD_LIBS+=usr/lib32/libodialog.so.7
OLD_FILES+=usr/lib32/libodialog_p.a
.endif
# 20110930: sysinstall removed
OLD_FILES+=usr/sbin/sysinstall
OLD_FILES+=usr/share/man/man8/sysinstall.8.gz

View File

@ -22,6 +22,21 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
machines to maximize performance. (To disable malloc debugging, run
ln -s aj /etc/malloc.conf.)
20111215:
The carp(4) facility has been changed significantly. Configuration
of the CARP protocol via ifconfig(8) has changed, as well as format
of CARP events submitted to devd(8) has changed. See manual pages
for more information. The arpbalance feature of carp(4) is currently
not supported anymore.
Size of struct in_aliasreq, struct in6_aliasreq has changed. User
utilities using SIOCAIFADDR, SIOCAIFADDR_IN6, e.g. ifconfig(8),
need to be recompiled.
20111122:
The acpi_wmi(4) status device /dev/wmistat has been renamed to
/dev/wmistat0.
20111108:
The option VFS_ALLOW_NONMPSAFE option has been added in order to
explicitely support non-MPSAFE filesystems.

View File

@ -87,7 +87,7 @@ static int do_voltag(const char *, int, char **);
#endif
/* Valid changer element types. */
const struct element_type elements[] = {
static const struct element_type elements[] = {
{ "drive", CHET_DT },
{ "picker", CHET_MT },
{ "portal", CHET_IE },
@ -97,7 +97,7 @@ const struct element_type elements[] = {
};
/* Valid commands. */
const struct changer_command commands[] = {
static const struct changer_command commands[] = {
{ "exchange", do_exchange },
{ "getpicker", do_getpicker },
{ "ielem", do_ielem },
@ -112,7 +112,7 @@ const struct changer_command commands[] = {
};
/* Valid special words. */
const struct special_word specials[] = {
static const struct special_word specials[] = {
{ "inv", SW_INVERT },
{ "inv1", SW_INVERT1 },
{ "inv2", SW_INVERT2 },

View File

@ -53,7 +53,8 @@ read_file(char *fn, long n)
errmsg = "cannot close input file";
return ERR;
}
fprintf(stdout, !scripted ? "%lu\n" : "", size);
if (!scripted)
fprintf(stdout, "%lu\n", size);
return current_addr - n;
}
@ -161,7 +162,8 @@ write_file(char *fn, const char *mode, long n, long m)
errmsg = "cannot close output file";
return ERR;
}
fprintf(stdout, !scripted ? "%lu\n" : "", size);
if (!scripted)
fprintf(stdout, "%lu\n", size);
return n ? m - n + 1 : 0;
}

View File

@ -192,9 +192,10 @@ main(volatile int argc, char ** volatile argv)
fputs("?\n", stderr);
errmsg = "warning: file modified";
if (!isatty(0)) {
fprintf(stderr, garrulous ?
"script, line %d: %s\n" :
"", lineno, errmsg);
if (garrulous)
fprintf(stderr,
"script, line %d: %s\n",
lineno, errmsg);
quit(2);
}
clearerr(stdin);
@ -225,27 +226,26 @@ main(volatile int argc, char ** volatile argv)
fputs("?\n", stderr); /* give warning */
errmsg = "warning: file modified";
if (!isatty(0)) {
fprintf(stderr, garrulous ?
"script, line %d: %s\n" :
"", lineno, errmsg);
if (garrulous)
fprintf(stderr, "script, line %d: %s\n",
lineno, errmsg);
quit(2);
}
break;
case FATAL:
if (!isatty(0))
fprintf(stderr, garrulous ?
"script, line %d: %s\n" : "",
lineno, errmsg);
else
fprintf(stderr, garrulous ? "%s\n" : "",
errmsg);
if (!isatty(0)) {
if (garrulous)
fprintf(stderr, "script, line %d: %s\n",
lineno, errmsg);
} else if (garrulous)
fprintf(stderr, "%s\n", errmsg);
quit(3);
default:
fputs("?\n", stderr);
if (!isatty(0)) {
fprintf(stderr, garrulous ?
"script, line %d: %s\n" : "",
lineno, errmsg);
if (garrulous)
fprintf(stderr, "script, line %d: %s\n",
lineno, errmsg);
quit(2);
}
break;

View File

@ -29,7 +29,7 @@
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
.Dd October 30, 2011
.Dd November 22, 2011
.Dt PS 1
.Os
.Sh NAME
@ -98,12 +98,6 @@ The default output format includes, for each process, the process' ID,
controlling terminal, state, CPU time (including both user and system time)
and associated command.
.Pp
The process file system (see
.Xr procfs 5 )
should be mounted when
.Nm
is executed, otherwise not all information will be available.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl a
@ -686,9 +680,6 @@ attempts to automatically determine the terminal width.
.Bl -tag -width ".Pa /boot/kernel/kernel" -compact
.It Pa /boot/kernel/kernel
default system namelist
.It Pa /proc
the mount point of
.Xr procfs 5
.El
.Sh SEE ALSO
.Xr kill 1 ,

View File

@ -130,7 +130,6 @@ struct listinfo {
} l;
};
static int check_procfs(void);
static int addelem_gid(struct listinfo *, const char *);
static int addelem_pid(struct listinfo *, const char *);
static int addelem_tty(struct listinfo *, const char *);
@ -410,14 +409,6 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
/*
* If the user specified ps -e then they want a copy of the process
* environment kvm_getenvv(3) attempts to open /proc/<pid>/mem.
* Check to make sure that procfs is mounted on /proc, otherwise
* print a warning informing the user that output will be incomplete.
*/
if (needenv == 1 && check_procfs() == 0)
warnx("Process environment requires procfs(5)");
/*
* If there arguments after processing all the options, attempt
* to treat them as a list of process ids.
@ -1360,18 +1351,6 @@ kludge_oldps_options(const char *optlist, char *origval, const char *nextarg)
return (newopts);
}
static int
check_procfs(void)
{
struct statfs mnt;
if (statfs("/proc", &mnt) < 0)
return (0);
if (strcmp(mnt.f_fstypename, "procfs") != 0)
return (0);
return (1);
}
static void
usage(void)
{

View File

@ -89,7 +89,7 @@ int oexitstatus; /* saved exit status */
static void evalloop(union node *, int);
static void evalfor(union node *, int);
static void evalcase(union node *, int);
static union node *evalcase(union node *, int);
static void evalsubshell(union node *, int);
static void evalredir(union node *, int);
static void expredir(union node *);
@ -256,7 +256,7 @@ evaltree(union node *n, int flags)
evalfor(n, flags & ~EV_EXIT);
break;
case NCASE:
evalcase(n, flags);
next = evalcase(n, flags);
break;
case NDEFUN:
defun(n->narg.text, n->narg.next);
@ -343,8 +343,6 @@ evalfor(union node *n, int flags)
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
oexitstatus = exitstatus;
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
if (evalskip)
goto out;
}
*arglist.lastp = NULL;
@ -364,13 +362,12 @@ evalfor(union node *n, int flags)
}
}
loopnest--;
out:
popstackmark(&smark);
}
static void
static union node *
evalcase(union node *n, int flags)
{
union node *cp;
@ -383,26 +380,24 @@ evalcase(union node *n, int flags)
oexitstatus = exitstatus;
exitstatus = 0;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
popstackmark(&smark);
while (cp->nclist.next &&
cp->type == NCLISTFALLTHRU) {
if (evalskip != 0)
break;
evaltree(cp->nclist.body,
flags & ~EV_EXIT);
if (evalskip != 0)
return (NULL);
cp = cp->nclist.next;
}
if (evalskip == 0) {
evaltree(cp->nclist.body, flags);
}
goto out;
return (cp->nclist.body);
}
}
}
out:
popstackmark(&smark);
return (NULL);
}
@ -983,7 +978,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
memout.nextc = memout.buf;
memout.bufsize = 64;
mode |= REDIR_BACKQ;
cmdentry.special = 0;
}
savecmdname = commandname;
savetopfile = getcurrentfile();
@ -1004,7 +998,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
* If there is no command word, redirection errors should
* not be fatal but assignment errors should.
*/
if (argc == 0 && !(flags & EV_BACKCMD))
if (argc == 0)
cmdentry.special = 1;
listsetvar(cmdenviron, cmdentry.special ? 0 : VNOSET);
if (argc > 0)

View File

@ -100,6 +100,7 @@ static void tryexec(char *, char **, char **);
static void printentry(struct tblentry *, int);
static struct tblentry *cmdlookup(const char *, int);
static void delete_cmd_entry(void);
static void addcmdentry(const char *, struct cmdentry *);
@ -593,7 +594,7 @@ delete_cmd_entry(void)
* the same name.
*/
void
static void
addcmdentry(const char *name, struct cmdentry *entry)
{
struct tblentry *cmdp;

View File

@ -70,7 +70,6 @@ void find_command(const char *, struct cmdentry *, int, const char *);
int find_builtin(const char *, int *);
void hashcd(void);
void changepath(const char *);
void addcmdentry(const char *, struct cmdentry *);
void defun(const char *, union node *);
int unsetfunc(const char *);
int typecmd_impl(int, char **, int, const char *);

View File

@ -113,6 +113,7 @@ static void expmeta(char *, char *);
static void addfname(char *);
static struct strlist *expsort(struct strlist *);
static struct strlist *msort(struct strlist *, int);
static int patmatch(const char *, const char *, int);
static char *cvtnum(int, char *);
static int collate_range_cmp(wchar_t, wchar_t);
@ -1186,6 +1187,7 @@ expmeta(char *enddir, char *name)
int atend;
int matchdot;
int esc;
int namlen;
metaflag = 0;
start = name;
@ -1284,17 +1286,22 @@ expmeta(char *enddir, char *name)
if (dp->d_name[0] == '.' && ! matchdot)
continue;
if (patmatch(start, dp->d_name, 0)) {
if (enddir + dp->d_namlen + 1 > expdir_end)
namlen = dp->d_namlen;
if (enddir + namlen + 1 > expdir_end)
continue;
memcpy(enddir, dp->d_name, dp->d_namlen + 1);
memcpy(enddir, dp->d_name, namlen + 1);
if (atend)
addfname(expdir);
else {
if (enddir + dp->d_namlen + 2 > expdir_end)
if (dp->d_type != DT_UNKNOWN &&
dp->d_type != DT_DIR &&
dp->d_type != DT_LNK)
continue;
enddir[dp->d_namlen] = '/';
enddir[dp->d_namlen + 1] = '\0';
expmeta(enddir + dp->d_namlen + 1, endname);
if (enddir + namlen + 2 > expdir_end)
continue;
enddir[namlen] = '/';
enddir[namlen + 1] = '\0';
expmeta(enddir + namlen + 1, endname);
}
}
}
@ -1435,61 +1442,67 @@ match_charclass(const char *p, wchar_t chr, const char **end)
* Returns true if the pattern matches the string.
*/
int
static int
patmatch(const char *pattern, const char *string, int squoted)
{
const char *p, *q, *end;
const char *bt_p, *bt_q;
char c;
wchar_t wc, wc2;
p = pattern;
q = string;
bt_p = NULL;
bt_q = NULL;
for (;;) {
switch (c = *p++) {
case '\0':
goto breakloop;
if (*q != '\0')
goto backtrack;
return 1;
case CTLESC:
if (squoted && *q == CTLESC)
q++;
if (*q++ != *p++)
return 0;
goto backtrack;
break;
case CTLQUOTEMARK:
continue;
case '?':
if (squoted && *q == CTLESC)
q++;
if (localeisutf8)
wc = get_wc(&q);
else
wc = (unsigned char)*q++;
if (wc == '\0')
if (*q == '\0')
return 0;
if (localeisutf8) {
wc = get_wc(&q);
/*
* A '?' does not match invalid UTF-8 but a
* '*' does, so backtrack.
*/
if (wc == 0)
goto backtrack;
} else
wc = (unsigned char)*q++;
break;
case '*':
c = *p;
while (c == CTLQUOTEMARK || c == '*')
c = *++p;
if (c != CTLESC && c != CTLQUOTEMARK &&
c != '?' && c != '*' && c != '[') {
while (*q != c) {
if (squoted && *q == CTLESC &&
q[1] == c)
break;
if (*q == '\0')
return 0;
if (squoted && *q == CTLESC)
q++;
q++;
}
}
do {
if (patmatch(p, q, squoted))
return 1;
if (squoted && *q == CTLESC)
q++;
} while (*q++ != '\0');
return 0;
/*
* If the pattern ends here, we know the string
* matches without needing to look at the rest of it.
*/
if (c == '\0')
return 1;
/*
* First try the shortest match for the '*' that
* could work. We can forget any earlier '*' since
* there is no way having it match more characters
* can help us, given that we are already here.
*/
bt_p = p;
bt_q = q;
break;
case '[': {
const char *endp;
int invert, found;
@ -1501,7 +1514,7 @@ patmatch(const char *pattern, const char *string, int squoted)
for (;;) {
while (*endp == CTLQUOTEMARK)
endp++;
if (*endp == '\0')
if (*endp == 0)
goto dft; /* no matching ] */
if (*endp == CTLESC)
endp++;
@ -1516,12 +1529,14 @@ patmatch(const char *pattern, const char *string, int squoted)
found = 0;
if (squoted && *q == CTLESC)
q++;
if (localeisutf8)
chr = get_wc(&q);
else
chr = (unsigned char)*q++;
if (chr == '\0')
if (*q == '\0')
return 0;
if (localeisutf8) {
chr = get_wc(&q);
if (chr == 0)
goto backtrack;
} else
chr = (unsigned char)*q++;
c = *p++;
do {
if (c == CTLQUOTEMARK)
@ -1562,21 +1577,34 @@ patmatch(const char *pattern, const char *string, int squoted)
}
} while ((c = *p++) != ']');
if (found == invert)
return 0;
goto backtrack;
break;
}
dft: default:
if (squoted && *q == CTLESC)
q++;
if (*q++ != c)
if (*q == '\0')
return 0;
if (*q++ == c)
break;
backtrack:
/*
* If we have a mismatch (other than hitting the end
* of the string), go back to the last '*' seen and
* have it match one additional character.
*/
if (bt_p == NULL)
return 0;
if (squoted && *bt_q == CTLESC)
bt_q++;
if (*bt_q == '\0')
return 0;
bt_q++;
p = bt_p;
q = bt_q;
break;
}
}
breakloop:
if (*q != '\0')
return 0;
return 1;
}

View File

@ -60,6 +60,5 @@ union node;
void expandhere(union node *, int);
void expandarg(union node *, struct arglist *, int);
void expari(int);
int patmatch(const char *, const char *, int);
void rmescapes(char *);
int casematch(union node *, const char *);

View File

@ -70,6 +70,8 @@ int displayhist;
static FILE *el_in, *el_out, *el_err;
static char *fc_replace(const char *, char *, char *);
static int not_fcnumber(const char *);
static int str_to_event(const char *, int);
/*
* Set history and editing status. Called whenever the status may
@ -425,7 +427,7 @@ fc_replace(const char *s, char *p, char *r)
return (dest);
}
int
static int
not_fcnumber(const char *s)
{
if (s == NULL)
@ -435,7 +437,7 @@ not_fcnumber(const char *s)
return (!is_number(s));
}
int
static int
str_to_event(const char *str, int last)
{
HistEvent he;

View File

@ -106,6 +106,7 @@ EditLine *el; /* cookie for editline package */
static void pushfile(void);
static int preadfd(void);
static void popstring(void);
#ifdef mkinit
INCLUDE "input.h"
@ -372,7 +373,7 @@ pushstring(char *s, int len, void *ap)
INTON;
}
void
static void
popstring(void)
{
struct strpush *sp = parsefile->strpush;

View File

@ -53,7 +53,6 @@ int preadbuffer(void);
int preadateof(void);
void pungetc(void);
void pushstring(char *, int, void *);
void popstring(void);
void setinputfile(const char *, int);
void setinputfd(int, int);
void setinputstring(char *, int);

View File

@ -79,6 +79,7 @@ int rootshell;
struct jmploc main_handler;
int localeisutf8, initial_localeisutf8;
static void cmdloop(int);
static void read_profile(char *);
static char *find_dot_file(char *);
@ -184,7 +185,7 @@ main(int argc, char *argv[])
* loop; it turns on prompting if the shell is interactive.
*/
void
static void
cmdloop(int top)
{
union node *n;

View File

@ -38,4 +38,3 @@ extern int rootshell; /* true if we aren't a child of the main shell */
extern struct jmploc main_handler; /* top level exception handler */
void readcmdfile(const char *);
void cmdloop(int);

View File

@ -219,16 +219,16 @@ main(int argc __unused, char **argv __unused)
add("`", "CBQUOTE");
add("$", "CVAR");
add("}", "CENDVAR");
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
add("!*?[=~:/-", "CCTL");
/* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
add("!*?[]=~:/-^", "CCTL");
print("dqsyntax");
init();
fputs("\n/* syntax table used when in single quotes */\n", cfile);
add("\n", "CNL");
add("\\", "CSBACK");
add("'", "CENDQUOTE");
/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
add("!*?[=~:/-", "CCTL");
/* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
add("!*?[]=~:/-^", "CCTL");
print("sqsyntax");
init();
fputs("\n/* syntax table used when in arithmetic */\n", cfile);

View File

@ -39,6 +39,4 @@ extern int displayhist;
void histedit(void);
void sethistsize(const char *);
void setterm(const char *);
int not_fcnumber(const char *);
int str_to_event(const char *, int);

View File

@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
*
* equal(s1, s2) Return true if strings are equal.
* scopy(from, to) Copy a string.
* scopyn(from, to, n) Like scopy, but checks for overflow.
* number(s) Convert a string of digits to an integer.
* is_number(s) Return true if s is a string of digits.
*/
@ -66,24 +65,6 @@ char nullstr[1]; /* zero length string */
*/
/*
* scopyn - copy a string from "from" to "to", truncating the string
* if necessary. "To" is always nul terminated, even if
* truncation is performed. "Size" is the size of "to".
*/
void
scopyn(const char *from, char *to, int size)
{
while (--size > 0) {
if ((*to++ = *from++) == '\0')
return;
}
*to = '\0';
}
/*
* prefix -- see if pfx is a prefix of string.
*/

View File

@ -35,7 +35,6 @@
#include <string.h>
void scopyn(const char *, char *, int);
int prefix(const char *, const char *);
int number(const char *);
int is_number(const char *);

View File

@ -52,7 +52,7 @@ struct modes {
* The code in optlist() depends on minus options following regular
* options, i.e. "foo" must immediately precede "-foo".
*/
struct modes cmodes[] = {
static const struct modes cmodes[] = {
{ "cs5", CS5, CSIZE },
{ "cs6", CS6, CSIZE },
{ "cs7", CS7, CSIZE },
@ -94,7 +94,7 @@ struct modes cmodes[] = {
{ NULL, 0, 0 },
};
struct modes imodes[] = {
static const struct modes imodes[] = {
{ "ignbrk", IGNBRK, 0 },
{ "-ignbrk", 0, IGNBRK },
{ "brkint", BRKINT, 0 },
@ -130,7 +130,7 @@ struct modes imodes[] = {
{ NULL, 0, 0 },
};
struct modes lmodes[] = {
static const struct modes lmodes[] = {
{ "echo", ECHO, 0 },
{ "-echo", 0, ECHO },
{ "echoe", ECHOE, 0 },
@ -182,7 +182,7 @@ struct modes lmodes[] = {
{ NULL, 0, 0 },
};
struct modes omodes[] = {
static const struct modes omodes[] = {
{ "opost", OPOST, 0 },
{ "-opost", 0, OPOST },
{ "litout", 0, OPOST },
@ -209,7 +209,7 @@ struct modes omodes[] = {
int
msearch(char ***argvp, struct info *ip)
{
struct modes *mp;
const struct modes *mp;
char *name;
name = **argvp;

View File

@ -119,7 +119,7 @@ enum token_types {
};
static struct t_op {
const char *op_text;
char op_text[4];
short op_num, op_type;
} const ops [] = {
{"-r", FILRD, UNOP},
@ -162,7 +162,7 @@ static struct t_op {
{"-o", BOR, BBINOP},
{"(", LPAREN, PAREN},
{")", RPAREN, PAREN},
{0, 0, 0}
{"", 0, 0}
};
static struct t_op const *t_wp_op;
@ -427,7 +427,7 @@ t_lex(char *s)
t_wp_op = NULL;
return EOI;
}
while (op->op_text) {
while (*op->op_text) {
if (strcmp(s, op->op_text) == 0) {
if (((op->op_type == UNOP || op->op_type == BUNOP)
&& isunopoperand()) ||
@ -456,7 +456,7 @@ isunopoperand(void)
if (nargc == 2)
return parenlevel == 1 && strcmp(s, ")") == 0;
t = *(t_wp + 2);
while (op->op_text) {
while (*op->op_text) {
if (strcmp(s, op->op_text) == 0)
return op->op_type == BINOP &&
(parenlevel == 0 || t[0] != ')' || t[1] != '\0');
@ -478,7 +478,7 @@ islparenoperand(void)
return parenlevel == 1 && strcmp(s, ")") == 0;
if (nargc != 3)
return 0;
while (op->op_text) {
while (*op->op_text) {
if (strcmp(s, op->op_text) == 0)
return op->op_type == BINOP;
op++;

View File

@ -671,9 +671,12 @@ link_prog(dtrace_cmd_t *dcp)
p[0] = '\0'; /* strip .d suffix */
(void) snprintf(dcp->dc_ofile, sizeof (dcp->dc_ofile),
"%s.o", basename(dcp->dc_arg));
} else if (g_cmdc > 1) {
(void) snprintf(dcp->dc_ofile, sizeof (dcp->dc_ofile),
"d.out.%td", dcp - g_cmdv);
} else {
(void) snprintf(dcp->dc_ofile, sizeof (dcp->dc_ofile),
g_cmdc > 1 ? "%s.%d" : "%s", "d.out", (int)(dcp - g_cmdv));
"d.out");
}
if (dtrace_program_link(g_dtp, dcp->dc_prog, DTRACE_D_PROBES,

View File

@ -1,65 +1,79 @@
'\" te
.\" Copyright (c) 2011, Martin Matuska <mm@FreeBSD.org>.
.\" All Rights Reserved.
.\"
.\" 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]
.\"
.\" Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved.
.\" 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]
.\" Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
.TH ZDB 8 "Oct 31, 2005"
.SH NAME
zdb \- ZFS debugger
.SH SYNOPSIS
.LP
.nf
\fBzdb\fR \fIpool\fR
.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
.\"
.\" $FreeBSD$
.\"
.Dd November 26, 2011
.Dt ZDB 8
.Os
.Sh NAME
.Nm zdb
.Nd ZFS debugger
.Sh SYNOPSIS
.Nm
.Ar pool
.Sh DESCRIPTION
The
.Nm
command is used by support engineers to diagnose failures and
gather statistics. Since the
.Tn ZFS
file system is always consistent on disk and is self-repairing,
.Nm
should only be run under the direction by a support engineer.
.Pp
If no arguments are specified,
.Nm
performs basic consistency checks on the pool and associated datasets, and
report any problems detected.
.Nm
Any options supported by this command are internal to Sun and subject to change
at any time.
.SH EXIT STATUS
.sp
.LP
.Sh EXIT STATUS
The following exit values are returned:
.sp
.ne 2
.na
\fB\fB0\fR\fR
.ad
.RS 5n
.Bl -tag -offset 2n -width 2n
.It 0
The pool is consistent.
.RE
.sp
.ne 2
.na
\fB\fB1\fR\fR
.ad
.RS 5n
.It 1
An error was detected.
.RE
.sp
.ne 2
.na
\fB\fB2\fR\fR
.ad
.RS 5n
.It 2
Invalid command line options were specified.
.RE
.SH SEE ALSO
.sp
.LP
zfs(8), zpool(8)
.El
.Sh SEE ALSO
.Xr zfs 8 ,
.Xr zpool 8
.Sh AUTHORS
This manual page is a
.Xr mdoc 7
reimplementation of the
.Tn OpenSolaris
manual page
.Em zdb(1M) ,
modified and customized for
.Fx
and licensed under the
.Tn Common Development and Distribution License
.Pq Tn CDDL .
.Pp
The
.Xr mdoc 7
implementation of this manual page was initially written by
.An Martin Matuska Aq mm@FreeBSD.org .

File diff suppressed because it is too large Load Diff

View File

@ -22,8 +22,9 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2011 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
*/
#include <assert.h>
@ -145,7 +146,7 @@ typedef enum {
HELP_HOLD,
HELP_HOLDS,
HELP_RELEASE,
HELP_DIFF
HELP_DIFF,
} zfs_help_t;
typedef struct zfs_command {
@ -220,8 +221,9 @@ get_usage(zfs_help_t idx)
"\tcreate [-ps] [-b blocksize] [-o property=value] ... "
"-V <size> <volume>\n"));
case HELP_DESTROY:
return (gettext("\tdestroy [-rRf] <filesystem|volume>\n"
"\tdestroy [-rRd] <snapshot>\n"));
return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n"
"\tdestroy [-dnpRrv] "
"<snapshot>[%<snapname>][,...]\n"));
case HELP_GET:
return (gettext("\tget [-rHp] [-d max] "
"[-o \"all\" | field[,...]] [-s source[,...]]\n"
@ -260,7 +262,8 @@ get_usage(zfs_help_t idx)
case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND:
return (gettext("\tsend [-RDp] [-[iI] snapshot] <snapshot>\n"));
return (gettext("\tsend [-DnPpRrv] "
"[-i snapshot | -I snapshot] <snapshot>\n"));
case HELP_SET:
return (gettext("\tset <property=value> "
"<filesystem|volume|snapshot> ...\n"));
@ -296,11 +299,11 @@ get_usage(zfs_help_t idx)
"\tunallow [-r] -s @setname [<perm|@setname>[,...]] "
"<filesystem|volume>\n"));
case HELP_USERSPACE:
return (gettext("\tuserspace [-hniHp] [-o field[,...]] "
return (gettext("\tuserspace [-niHp] [-o field[,...]] "
"[-sS field] ... [-t type[,...]]\n"
"\t <filesystem|snapshot>\n"));
case HELP_GROUPSPACE:
return (gettext("\tgroupspace [-hniHpU] [-o field[,...]] "
return (gettext("\tgroupspace [-niHp] [-o field[,...]] "
"[-sS field] ... [-t type[,...]]\n"
"\t <filesystem|snapshot>\n"));
case HELP_HOLD:
@ -439,6 +442,8 @@ usage(boolean_t requested)
(void) fprintf(fp, "YES NO <size> | none\n");
(void) fprintf(fp, "\t%-15s ", "groupquota@...");
(void) fprintf(fp, "YES NO <size> | none\n");
(void) fprintf(fp, "\t%-15s ", "written@<snap>");
(void) fprintf(fp, " NO NO <size>\n");
(void) fprintf(fp, gettext("\nSizes are specified in bytes "
"with standard units such as K, M, G, etc.\n"));
@ -884,15 +889,23 @@ zfs_do_create(int argc, char **argv)
*/
typedef struct destroy_cbdata {
boolean_t cb_first;
int cb_force;
int cb_recurse;
int cb_error;
int cb_needforce;
int cb_doclones;
boolean_t cb_closezhp;
boolean_t cb_force;
boolean_t cb_recurse;
boolean_t cb_error;
boolean_t cb_doclones;
zfs_handle_t *cb_target;
char *cb_snapname;
boolean_t cb_defer_destroy;
boolean_t cb_verbose;
boolean_t cb_parsable;
boolean_t cb_dryrun;
nvlist_t *cb_nvl;
/* first snap in contiguous run */
zfs_handle_t *cb_firstsnap;
/* previous snap in contiguous run */
zfs_handle_t *cb_prevsnap;
int64_t cb_snapused;
char *cb_snapspec;
} destroy_cbdata_t;
/*
@ -922,7 +935,7 @@ destroy_check_dependent(zfs_handle_t *zhp, void *data)
(void) fprintf(stderr, gettext("use '-r' to destroy "
"the following datasets:\n"));
cbp->cb_first = B_FALSE;
cbp->cb_error = 1;
cbp->cb_error = B_TRUE;
}
(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
@ -943,7 +956,8 @@ destroy_check_dependent(zfs_handle_t *zhp, void *data)
(void) fprintf(stderr, gettext("use '-R' to destroy "
"the following datasets:\n"));
cbp->cb_first = B_FALSE;
cbp->cb_error = 1;
cbp->cb_error = B_TRUE;
cbp->cb_dryrun = B_TRUE;
}
(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
@ -957,7 +971,20 @@ destroy_check_dependent(zfs_handle_t *zhp, void *data)
static int
destroy_callback(zfs_handle_t *zhp, void *data)
{
destroy_cbdata_t *cbp = data;
destroy_cbdata_t *cb = data;
const char *name = zfs_get_name(zhp);
if (cb->cb_verbose) {
if (cb->cb_parsable) {
(void) printf("destroy\t%s\n", name);
} else if (cb->cb_dryrun) {
(void) printf(gettext("would destroy %s\n"),
name);
} else {
(void) printf(gettext("will destroy %s\n"),
name);
}
}
/*
* Ignore pools (which we've already flagged as an error before getting
@ -969,13 +996,12 @@ destroy_callback(zfs_handle_t *zhp, void *data)
return (0);
}
/*
* Bail out on the first error.
*/
if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 ||
zfs_destroy(zhp, cbp->cb_defer_destroy) != 0) {
zfs_close(zhp);
return (-1);
if (!cb->cb_dryrun) {
if (zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
zfs_destroy(zhp, cb->cb_defer_destroy) != 0) {
zfs_close(zhp);
return (-1);
}
}
zfs_close(zhp);
@ -983,39 +1009,142 @@ destroy_callback(zfs_handle_t *zhp, void *data)
}
static int
destroy_snap_clones(zfs_handle_t *zhp, void *arg)
destroy_print_cb(zfs_handle_t *zhp, void *arg)
{
destroy_cbdata_t *cbp = arg;
char thissnap[MAXPATHLEN];
zfs_handle_t *szhp;
boolean_t closezhp = cbp->cb_closezhp;
int rv;
destroy_cbdata_t *cb = arg;
const char *name = zfs_get_name(zhp);
int err = 0;
(void) snprintf(thissnap, sizeof (thissnap),
"%s@%s", zfs_get_name(zhp), cbp->cb_snapname);
libzfs_print_on_error(g_zfs, B_FALSE);
szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT);
libzfs_print_on_error(g_zfs, B_TRUE);
if (szhp) {
/*
* Destroy any clones of this snapshot
*/
if (zfs_iter_dependents(szhp, B_FALSE, destroy_callback,
cbp) != 0) {
zfs_close(szhp);
if (closezhp)
zfs_close(zhp);
return (-1);
if (nvlist_exists(cb->cb_nvl, name)) {
if (cb->cb_firstsnap == NULL)
cb->cb_firstsnap = zfs_handle_dup(zhp);
if (cb->cb_prevsnap != NULL)
zfs_close(cb->cb_prevsnap);
/* this snap continues the current range */
cb->cb_prevsnap = zfs_handle_dup(zhp);
if (cb->cb_verbose) {
if (cb->cb_parsable) {
(void) printf("destroy\t%s\n", name);
} else if (cb->cb_dryrun) {
(void) printf(gettext("would destroy %s\n"),
name);
} else {
(void) printf(gettext("will destroy %s\n"),
name);
}
}
zfs_close(szhp);
} else if (cb->cb_firstsnap != NULL) {
/* end of this range */
uint64_t used = 0;
err = zfs_get_snapused_int(cb->cb_firstsnap,
cb->cb_prevsnap, &used);
cb->cb_snapused += used;
zfs_close(cb->cb_firstsnap);
cb->cb_firstsnap = NULL;
zfs_close(cb->cb_prevsnap);
cb->cb_prevsnap = NULL;
}
zfs_close(zhp);
return (err);
}
static int
destroy_print_snapshots(zfs_handle_t *fs_zhp, destroy_cbdata_t *cb)
{
int err;
assert(cb->cb_firstsnap == NULL);
assert(cb->cb_prevsnap == NULL);
err = zfs_iter_snapshots_sorted(fs_zhp, destroy_print_cb, cb);
if (cb->cb_firstsnap != NULL) {
uint64_t used = 0;
if (err == 0) {
err = zfs_get_snapused_int(cb->cb_firstsnap,
cb->cb_prevsnap, &used);
}
cb->cb_snapused += used;
zfs_close(cb->cb_firstsnap);
cb->cb_firstsnap = NULL;
zfs_close(cb->cb_prevsnap);
cb->cb_prevsnap = NULL;
}
return (err);
}
static int
snapshot_to_nvl_cb(zfs_handle_t *zhp, void *arg)
{
destroy_cbdata_t *cb = arg;
int err = 0;
/* Check for clones. */
if (!cb->cb_doclones) {
cb->cb_target = zhp;
cb->cb_first = B_TRUE;
err = zfs_iter_dependents(zhp, B_TRUE,
destroy_check_dependent, cb);
}
cbp->cb_closezhp = B_TRUE;
rv = zfs_iter_filesystems(zhp, destroy_snap_clones, arg);
if (closezhp)
zfs_close(zhp);
return (rv);
if (err == 0) {
if (nvlist_add_boolean(cb->cb_nvl, zfs_get_name(zhp)))
nomem();
}
zfs_close(zhp);
return (err);
}
static int
gather_snapshots(zfs_handle_t *zhp, void *arg)
{
destroy_cbdata_t *cb = arg;
int err = 0;
err = zfs_iter_snapspec(zhp, cb->cb_snapspec, snapshot_to_nvl_cb, cb);
if (err == ENOENT)
err = 0;
if (err != 0)
goto out;
if (cb->cb_verbose) {
err = destroy_print_snapshots(zhp, cb);
if (err != 0)
goto out;
}
if (cb->cb_recurse)
err = zfs_iter_filesystems(zhp, gather_snapshots, cb);
out:
zfs_close(zhp);
return (err);
}
static int
destroy_clones(destroy_cbdata_t *cb)
{
nvpair_t *pair;
for (pair = nvlist_next_nvpair(cb->cb_nvl, NULL);
pair != NULL;
pair = nvlist_next_nvpair(cb->cb_nvl, pair)) {
zfs_handle_t *zhp = zfs_open(g_zfs, nvpair_name(pair),
ZFS_TYPE_SNAPSHOT);
if (zhp != NULL) {
boolean_t defer = cb->cb_defer_destroy;
int err;
/*
* We can't defer destroy non-snapshots, so set it to
* false while destroying the clones.
*/
cb->cb_defer_destroy = B_FALSE;
err = zfs_iter_dependents(zhp, B_FALSE,
destroy_callback, cb);
cb->cb_defer_destroy = defer;
zfs_close(zhp);
if (err != 0)
return (err);
}
}
return (0);
}
static int
@ -1024,25 +1153,35 @@ zfs_do_destroy(int argc, char **argv)
destroy_cbdata_t cb = { 0 };
int c;
zfs_handle_t *zhp;
char *cp;
char *at;
zfs_type_t type = ZFS_TYPE_DATASET;
/* check options */
while ((c = getopt(argc, argv, "dfrR")) != -1) {
while ((c = getopt(argc, argv, "vpndfrR")) != -1) {
switch (c) {
case 'v':
cb.cb_verbose = B_TRUE;
break;
case 'p':
cb.cb_verbose = B_TRUE;
cb.cb_parsable = B_TRUE;
break;
case 'n':
cb.cb_dryrun = B_TRUE;
break;
case 'd':
cb.cb_defer_destroy = B_TRUE;
type = ZFS_TYPE_SNAPSHOT;
break;
case 'f':
cb.cb_force = 1;
cb.cb_force = B_TRUE;
break;
case 'r':
cb.cb_recurse = 1;
cb.cb_recurse = B_TRUE;
break;
case 'R':
cb.cb_recurse = 1;
cb.cb_doclones = 1;
cb.cb_recurse = B_TRUE;
cb.cb_doclones = B_TRUE;
break;
case '?':
default:
@ -1057,7 +1196,7 @@ zfs_do_destroy(int argc, char **argv)
/* check number of arguments */
if (argc == 0) {
(void) fprintf(stderr, gettext("missing path argument\n"));
(void) fprintf(stderr, gettext("missing dataset argument\n"));
usage(B_FALSE);
}
if (argc > 1) {
@ -1065,92 +1204,118 @@ zfs_do_destroy(int argc, char **argv)
usage(B_FALSE);
}
/*
* If we are doing recursive destroy of a snapshot, then the
* named snapshot may not exist. Go straight to libzfs.
*/
if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) {
int ret;
at = strchr(argv[0], '@');
if (at != NULL) {
int err;
*cp = '\0';
if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL)
/* Build the list of snaps to destroy in cb_nvl. */
if (nvlist_alloc(&cb.cb_nvl, NV_UNIQUE_NAME, 0) != 0)
nomem();
*at = '\0';
zhp = zfs_open(g_zfs, argv[0],
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
if (zhp == NULL)
return (1);
*cp = '@';
cp++;
if (cb.cb_doclones) {
boolean_t defer = cb.cb_defer_destroy;
cb.cb_snapspec = at + 1;
if (gather_snapshots(zfs_handle_dup(zhp), &cb) != 0 ||
cb.cb_error) {
zfs_close(zhp);
nvlist_free(cb.cb_nvl);
return (1);
}
/*
* Temporarily ignore the defer_destroy setting since
* it's not supported for clones.
*/
cb.cb_defer_destroy = B_FALSE;
cb.cb_snapname = cp;
if (destroy_snap_clones(zhp, &cb) != 0) {
zfs_close(zhp);
return (1);
if (nvlist_empty(cb.cb_nvl)) {
(void) fprintf(stderr, gettext("could not find any "
"snapshots to destroy; check snapshot names.\n"));
zfs_close(zhp);
nvlist_free(cb.cb_nvl);
return (1);
}
if (cb.cb_verbose) {
char buf[16];
zfs_nicenum(cb.cb_snapused, buf, sizeof (buf));
if (cb.cb_parsable) {
(void) printf("reclaim\t%llu\n",
cb.cb_snapused);
} else if (cb.cb_dryrun) {
(void) printf(gettext("would reclaim %s\n"),
buf);
} else {
(void) printf(gettext("will reclaim %s\n"),
buf);
}
cb.cb_defer_destroy = defer;
}
ret = zfs_destroy_snaps(zhp, cp, cb.cb_defer_destroy);
zfs_close(zhp);
if (ret) {
(void) fprintf(stderr,
gettext("no snapshots destroyed\n"));
if (!cb.cb_dryrun) {
if (cb.cb_doclones)
err = destroy_clones(&cb);
if (err == 0) {
err = zfs_destroy_snaps_nvl(zhp, cb.cb_nvl,
cb.cb_defer_destroy);
}
}
return (ret != 0);
}
/* Open the given dataset */
if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
return (1);
cb.cb_target = zhp;
/*
* Perform an explicit check for pools before going any further.
*/
if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
(void) fprintf(stderr, gettext("cannot destroy '%s': "
"operation does not apply to pools\n"),
zfs_get_name(zhp));
(void) fprintf(stderr, gettext("use 'zfs destroy -r "
"%s' to destroy all datasets in the pool\n"),
zfs_get_name(zhp));
(void) fprintf(stderr, gettext("use 'zpool destroy %s' "
"to destroy the pool itself\n"), zfs_get_name(zhp));
zfs_close(zhp);
return (1);
nvlist_free(cb.cb_nvl);
if (err != 0)
return (1);
} else {
/* Open the given dataset */
if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
return (1);
cb.cb_target = zhp;
/*
* Perform an explicit check for pools before going any further.
*/
if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
(void) fprintf(stderr, gettext("cannot destroy '%s': "
"operation does not apply to pools\n"),
zfs_get_name(zhp));
(void) fprintf(stderr, gettext("use 'zfs destroy -r "
"%s' to destroy all datasets in the pool\n"),
zfs_get_name(zhp));
(void) fprintf(stderr, gettext("use 'zpool destroy %s' "
"to destroy the pool itself\n"), zfs_get_name(zhp));
zfs_close(zhp);
return (1);
}
/*
* Check for any dependents and/or clones.
*/
cb.cb_first = B_TRUE;
if (!cb.cb_doclones &&
zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
&cb) != 0) {
zfs_close(zhp);
return (1);
}
if (cb.cb_error) {
zfs_close(zhp);
return (1);
}
if (zfs_iter_dependents(zhp, B_FALSE, destroy_callback,
&cb) != 0) {
zfs_close(zhp);
return (1);
}
/*
* Do the real thing. The callback will close the
* handle regardless of whether it succeeds or not.
*/
if (destroy_callback(zhp, &cb) != 0)
return (1);
}
/*
* Check for any dependents and/or clones.
*/
cb.cb_first = B_TRUE;
if (!cb.cb_doclones && !cb.cb_defer_destroy &&
zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
&cb) != 0) {
zfs_close(zhp);
return (1);
}
if (cb.cb_error || (!cb.cb_defer_destroy &&
(zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0))) {
zfs_close(zhp);
return (1);
}
/*
* Do the real thing. The callback will close the handle regardless of
* whether it succeeds or not.
*/
if (destroy_callback(zhp, &cb) != 0)
return (1);
return (0);
}
@ -1249,6 +1414,17 @@ get_callback(zfs_handle_t *zhp, void *data)
(void) strlcpy(buf, "-", sizeof (buf));
}
zprop_print_one_property(zfs_get_name(zhp), cbp,
pl->pl_user_prop, buf, sourcetype, source, NULL);
} else if (zfs_prop_written(pl->pl_user_prop)) {
sourcetype = ZPROP_SRC_LOCAL;
if (zfs_prop_get_written(zhp, pl->pl_user_prop,
buf, sizeof (buf), cbp->cb_literal) != 0) {
sourcetype = ZPROP_SRC_NONE;
(void) strlcpy(buf, "-", sizeof (buf));
}
zprop_print_one_property(zfs_get_name(zhp), cbp,
pl->pl_user_prop, buf, sourcetype, source, NULL);
} else {
@ -1795,8 +1971,8 @@ zfs_do_upgrade(int argc, char **argv)
"---------------\n");
(void) printf(gettext(" 1 Initial ZFS filesystem version\n"));
(void) printf(gettext(" 2 Enhanced directory entries\n"));
(void) printf(gettext(" 3 Case insensitive and File system "
"unique identifier (FUID)\n"));
(void) printf(gettext(" 3 Case insensitive and filesystem "
"user identifier (FUID)\n"));
(void) printf(gettext(" 4 userquota, groupquota "
"properties\n"));
(void) printf(gettext(" 5 System attributes\n"));
@ -2676,6 +2852,13 @@ print_dataset(zfs_handle_t *zhp, zprop_list_t *pl, boolean_t scripted)
else
propstr = property;
right_justify = B_TRUE;
} else if (zfs_prop_written(pl->pl_user_prop)) {
if (zfs_prop_get_written(zhp, pl->pl_user_prop,
property, sizeof (property), B_FALSE) != 0)
propstr = "-";
else
propstr = property;
right_justify = B_TRUE;
} else {
if (nvlist_lookup_nvlist(userprops,
pl->pl_user_prop, &propval) != 0)
@ -3302,9 +3485,6 @@ zfs_do_snapshot(int argc, char **argv)
}
/*
* zfs send [-vDp] -R [-i|-I <@snap>] <fs@snap>
* zfs send [-vDp] [-i|-I <@snap>] <fs@snap>
*
* Send a backup stream to stdout.
*/
static int
@ -3316,11 +3496,11 @@ zfs_do_send(int argc, char **argv)
zfs_handle_t *zhp;
sendflags_t flags = { 0 };
int c, err;
nvlist_t *dbgnv;
nvlist_t *dbgnv = NULL;
boolean_t extraverbose = B_FALSE;
/* check options */
while ((c = getopt(argc, argv, ":i:I:RDpv")) != -1) {
while ((c = getopt(argc, argv, ":i:I:RDpvnP")) != -1) {
switch (c) {
case 'i':
if (fromname)
@ -3339,6 +3519,10 @@ zfs_do_send(int argc, char **argv)
case 'p':
flags.props = B_TRUE;
break;
case 'P':
flags.parsable = B_TRUE;
flags.verbose = B_TRUE;
break;
case 'v':
if (flags.verbose)
extraverbose = B_TRUE;
@ -3347,6 +3531,9 @@ zfs_do_send(int argc, char **argv)
case 'D':
flags.dedup = B_TRUE;
break;
case 'n':
flags.dryrun = B_TRUE;
break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@ -3372,7 +3559,7 @@ zfs_do_send(int argc, char **argv)
usage(B_FALSE);
}
if (isatty(STDOUT_FILENO)) {
if (!flags.dryrun && isatty(STDOUT_FILENO)) {
(void) fprintf(stderr,
gettext("Error: Stream can not be written to a terminal.\n"
"You must redirect standard output.\n"));
@ -3426,10 +3613,10 @@ zfs_do_send(int argc, char **argv)
if (flags.replicate && fromname == NULL)
flags.doall = B_TRUE;
err = zfs_send(zhp, fromname, toname, flags, STDOUT_FILENO, NULL, 0,
err = zfs_send(zhp, fromname, toname, &flags, STDOUT_FILENO, NULL, 0,
extraverbose ? &dbgnv : NULL);
if (extraverbose) {
if (extraverbose && dbgnv != NULL) {
/*
* dump_nvlist prints to stdout, but that's been
* redirected to a file. Make it print to stderr
@ -3510,7 +3697,7 @@ zfs_do_receive(int argc, char **argv)
return (1);
}
err = zfs_receive(g_zfs, argv[0], flags, STDIN_FILENO, NULL);
err = zfs_receive(g_zfs, argv[0], &flags, STDIN_FILENO, NULL);
return (err != 0);
}

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,8 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
* Copyright (c) 2011 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
*/
#include <solaris.h>
@ -68,6 +70,8 @@ static int zpool_do_online(int, char **);
static int zpool_do_offline(int, char **);
static int zpool_do_clear(int, char **);
static int zpool_do_reguid(int, char **);
static int zpool_do_attach(int, char **);
static int zpool_do_detach(int, char **);
static int zpool_do_replace(int, char **);
@ -126,7 +130,8 @@ typedef enum {
HELP_UPGRADE,
HELP_GET,
HELP_SET,
HELP_SPLIT
HELP_SPLIT,
HELP_REGUID
} zpool_help_t;
@ -172,6 +177,7 @@ static zpool_command_t command_table[] = {
{ "import", zpool_do_import, HELP_IMPORT },
{ "export", zpool_do_export, HELP_EXPORT },
{ "upgrade", zpool_do_upgrade, HELP_UPGRADE },
{ "reguid", zpool_do_reguid, HELP_REGUID },
{ NULL },
{ "history", zpool_do_history, HELP_HISTORY },
{ "get", zpool_do_get, HELP_GET },
@ -228,7 +234,7 @@ get_usage(zpool_help_t idx) {
case HELP_OFFLINE:
return (gettext("\toffline [-t] <pool> <device> ...\n"));
case HELP_ONLINE:
return (gettext("\tonline <pool> <device> ...\n"));
return (gettext("\tonline [-e] <pool> <device> ...\n"));
case HELP_REPLACE:
return (gettext("\treplace [-f] <pool> <device> "
"[new-device]\n"));
@ -240,8 +246,7 @@ get_usage(zpool_help_t idx) {
return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
"[count]]\n"));
case HELP_UPGRADE:
return (gettext("\tupgrade\n"
"\tupgrade -v\n"
return (gettext("\tupgrade [-v]\n"
"\tupgrade [-V version] <-a | pool ...>\n"));
case HELP_GET:
return (gettext("\tget <\"all\" | property[,...]> "
@ -252,6 +257,8 @@ get_usage(zpool_help_t idx) {
return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
"\t [-o property=value] <pool> <newpool> "
"[<device> ...]\n"));
case HELP_REGUID:
return (gettext("\treguid <pool>\n"));
}
abort();
@ -1455,6 +1462,7 @@ show_import(nvlist_t *config)
const char *health;
uint_t vsc;
int namewidth;
char *comment;
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
&name) == 0);
@ -1471,9 +1479,9 @@ show_import(nvlist_t *config)
reason = zpool_import_status(config, &msgid);
(void) printf(gettext(" pool: %s\n"), name);
(void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
(void) printf(gettext(" state: %s"), health);
(void) printf(gettext(" pool: %s\n"), name);
(void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
(void) printf(gettext(" state: %s"), health);
if (pool_state == POOL_STATE_DESTROYED)
(void) printf(gettext(" (DESTROYED)"));
(void) printf("\n");
@ -1482,58 +1490,59 @@ show_import(nvlist_t *config)
case ZPOOL_STATUS_MISSING_DEV_R:
case ZPOOL_STATUS_MISSING_DEV_NR:
case ZPOOL_STATUS_BAD_GUID_SUM:
(void) printf(gettext("status: One or more devices are missing "
"from the system.\n"));
(void) printf(gettext(" status: One or more devices are "
"missing from the system.\n"));
break;
case ZPOOL_STATUS_CORRUPT_LABEL_R:
case ZPOOL_STATUS_CORRUPT_LABEL_NR:
(void) printf(gettext("status: One or more devices contains "
(void) printf(gettext(" status: One or more devices contains "
"corrupted data.\n"));
break;
case ZPOOL_STATUS_CORRUPT_DATA:
(void) printf(gettext("status: The pool data is corrupted.\n"));
(void) printf(
gettext(" status: The pool data is corrupted.\n"));
break;
case ZPOOL_STATUS_OFFLINE_DEV:
(void) printf(gettext("status: One or more devices "
(void) printf(gettext(" status: One or more devices "
"are offlined.\n"));
break;
case ZPOOL_STATUS_CORRUPT_POOL:
(void) printf(gettext("status: The pool metadata is "
(void) printf(gettext(" status: The pool metadata is "
"corrupted.\n"));
break;
case ZPOOL_STATUS_VERSION_OLDER:
(void) printf(gettext("status: The pool is formatted using an "
(void) printf(gettext(" status: The pool is formatted using an "
"older on-disk version.\n"));
break;
case ZPOOL_STATUS_VERSION_NEWER:
(void) printf(gettext("status: The pool is formatted using an "
(void) printf(gettext(" status: The pool is formatted using an "
"incompatible version.\n"));
break;
case ZPOOL_STATUS_HOSTID_MISMATCH:
(void) printf(gettext("status: The pool was last accessed by "
(void) printf(gettext(" status: The pool was last accessed by "
"another system.\n"));
break;
case ZPOOL_STATUS_FAULTED_DEV_R:
case ZPOOL_STATUS_FAULTED_DEV_NR:
(void) printf(gettext("status: One or more devices are "
(void) printf(gettext(" status: One or more devices are "
"faulted.\n"));
break;
case ZPOOL_STATUS_BAD_LOG:
(void) printf(gettext("status: An intent log record cannot be "
(void) printf(gettext(" status: An intent log record cannot be "
"read.\n"));
break;
case ZPOOL_STATUS_RESILVERING:
(void) printf(gettext("status: One or more devices were being "
(void) printf(gettext(" status: One or more devices were being "
"resilvered.\n"));
break;
@ -1549,26 +1558,26 @@ show_import(nvlist_t *config)
*/
if (vs->vs_state == VDEV_STATE_HEALTHY) {
if (reason == ZPOOL_STATUS_VERSION_OLDER)
(void) printf(gettext("action: The pool can be "
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric identifier, "
"though\n\tsome features will not be available "
"without an explicit 'zpool upgrade'.\n"));
else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
(void) printf(gettext("action: The pool can be "
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
"identifier and\n\tthe '-f' flag.\n"));
else
(void) printf(gettext("action: The pool can be "
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
"identifier.\n"));
} else if (vs->vs_state == VDEV_STATE_DEGRADED) {
(void) printf(gettext("action: The pool can be imported "
(void) printf(gettext(" action: The pool can be imported "
"despite missing or damaged devices. The\n\tfault "
"tolerance of the pool may be compromised if imported.\n"));
} else {
switch (reason) {
case ZPOOL_STATUS_VERSION_NEWER:
(void) printf(gettext("action: The pool cannot be "
(void) printf(gettext(" action: The pool cannot be "
"imported. Access the pool on a system running "
"newer\n\tsoftware, or recreate the pool from "
"backup.\n"));
@ -1576,16 +1585,20 @@ show_import(nvlist_t *config)
case ZPOOL_STATUS_MISSING_DEV_R:
case ZPOOL_STATUS_MISSING_DEV_NR:
case ZPOOL_STATUS_BAD_GUID_SUM:
(void) printf(gettext("action: The pool cannot be "
(void) printf(gettext(" action: The pool cannot be "
"imported. Attach the missing\n\tdevices and try "
"again.\n"));
break;
default:
(void) printf(gettext("action: The pool cannot be "
(void) printf(gettext(" action: The pool cannot be "
"imported due to damaged devices or data.\n"));
}
}
/* Print the comment attached to the pool. */
if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
(void) printf(gettext("comment: %s\n"), comment);
/*
* If the state is "closed" or "can't open", and the aux state
* is "corrupt data":
@ -1606,7 +1619,7 @@ show_import(nvlist_t *config)
(void) printf(gettext(" see: http://www.sun.com/msg/%s\n"),
msgid);
(void) printf(gettext("config:\n\n"));
(void) printf(gettext(" config:\n\n"));
namewidth = max_width(NULL, nvroot, 0, 0);
if (namewidth < 10)
@ -3321,6 +3334,52 @@ zpool_do_clear(int argc, char **argv)
return (ret);
}
/*
* zpool reguid <pool>
*/
int
zpool_do_reguid(int argc, char **argv)
{
int c;
char *poolname;
zpool_handle_t *zhp;
int ret = 0;
/* check options */
while ((c = getopt(argc, argv, "")) != -1) {
switch (c) {
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
usage(B_FALSE);
}
}
argc -= optind;
argv += optind;
/* get pool name and check number of arguments */
if (argc < 1) {
(void) fprintf(stderr, gettext("missing pool name\n"));
usage(B_FALSE);
}
if (argc > 1) {
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
}
poolname = argv[0];
if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
return (1);
ret = zpool_reguid(zhp);
zpool_close(zhp);
return (ret);
}
typedef struct scrub_cbdata {
int cb_type;
int cb_argc;

View File

@ -1,49 +1,67 @@
'\" te
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved
.\" 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]
.\" Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
.TH ZSTREAMDUMP 1 "Sep 21, 2009"
.SH NAME
zstreamdump \- filter data in zfs send stream
.SH SYNOPSIS
.LP
.nf
\fBzstreamdump\fR [\fB-C\fR] [\fB-v\fR]
.fi
.SH DESCRIPTION
.sp
.LP
The \fBzstreamdump\fR utility reads from the output of the \fBzfs send\fR
command, then displays headers and some statistics from that output. See
\fBzfs\fR(1M).
.SH OPTIONS
.sp
.LP
.\" Copyright (c) 2011, Martin Matuska <mm@FreeBSD.org>.
.\" All Rights Reserved.
.\"
.\" 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]
.\"
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
.\"
.\" $FreeBSD$
.\"
.Dd November 26, 2011
.Dt ZSTREAMDUMP 8
.Os
.Sh NAME
.Nm zdb
.Nd filter data in zfs send stream
.Sh SYNOPSIS
.Nm
.Op Fl C
.Op Fl v
.Sh DESCRIPTION
The
.Nm
utility reads from the output of the
.Qq Nm zfs Cm send
command, then displays headers and some statistics from that output. See
.Xr zfs 8 .
.Pp
The following options are supported:
.sp
.ne 2
.na
\fB\fB-C\fR\fR
.ad
.sp .6
.RS 4n
.Bl -tag -width indent
.It Fl C
Suppress the validation of checksums.
.RE
.sp
.ne 2
.na
\fB\fB-v\fR\fR
.ad
.sp .6
.RS 4n
.It Fl v
Verbose. Dump all headers, not only begin and end headers.
.RE
.SH SEE ALSO
.sp
.LP
zfs(8)
.El
.Sh SEE ALSO
.Xr zfs 8
.Sh AUTHORS
This manual page is a
.Xr mdoc 7
reimplementation of the
.Tn OpenSolaris
manual page
.Em zstreamdump(1M) ,
modified and customized for
.Fx
and licensed under the
.Tn Common Development and Distribution License
.Pq Tn CDDL .
.Pp
The
.Xr mdoc 7
implementation of this manual page was initially written by
.An Martin Matuska Aq mm@FreeBSD.org .

View File

@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
@ -259,6 +260,7 @@ ztest_func_t ztest_vdev_LUN_growth;
ztest_func_t ztest_vdev_add_remove;
ztest_func_t ztest_vdev_aux_add_remove;
ztest_func_t ztest_split_pool;
ztest_func_t ztest_reguid;
uint64_t zopt_always = 0ULL * NANOSEC; /* all the time */
uint64_t zopt_incessant = 1ULL * NANOSEC / 10; /* every 1/10 second */
@ -289,6 +291,7 @@ ztest_info_t ztest_info[] = {
{ ztest_fault_inject, 1, &zopt_sometimes },
{ ztest_ddt_repair, 1, &zopt_sometimes },
{ ztest_dmu_snapshot_hold, 1, &zopt_sometimes },
{ ztest_reguid, 1, &zopt_sometimes },
{ ztest_spa_rename, 1, &zopt_rarely },
{ ztest_scrub, 1, &zopt_rarely },
{ ztest_dsl_dataset_promote_busy, 1, &zopt_rarely },
@ -325,6 +328,7 @@ typedef struct ztest_shared {
uint64_t zs_vdev_aux;
uint64_t zs_alloc;
uint64_t zs_space;
uint64_t zs_guid;
mutex_t zs_vdev_lock;
rwlock_t zs_name_lock;
ztest_info_t zs_info[ZTEST_FUNCS];
@ -4646,7 +4650,7 @@ ztest_ddt_repair(ztest_ds_t *zd, uint64_t id)
object = od[0].od_object;
blocksize = od[0].od_blocksize;
pattern = spa_guid(spa) ^ dmu_objset_fsid_guid(os);
pattern = zs->zs_guid ^ dmu_objset_fsid_guid(os);
ASSERT(object != 0);
@ -4716,6 +4720,31 @@ ztest_scrub(ztest_ds_t *zd, uint64_t id)
(void) spa_scan(spa, POOL_SCAN_SCRUB);
}
/*
* Change the guid for the pool.
*/
/* ARGSUSED */
void
ztest_reguid(ztest_ds_t *zd, uint64_t id)
{
ztest_shared_t *zs = ztest_shared;
spa_t *spa = zs->zs_spa;
uint64_t orig, load;
orig = spa_guid(spa);
load = spa_load_guid(spa);
if (spa_change_guid(spa) != 0)
return;
if (zopt_verbose >= 3) {
(void) printf("Changed guid old %llu -> %llu\n",
(u_longlong_t)orig, (u_longlong_t)spa_guid(spa));
}
VERIFY3U(orig, !=, spa_guid(spa));
VERIFY3U(load, ==, spa_load_guid(spa));
}
/*
* Rename the pool to a different name and then rename it back.
*/
@ -5145,6 +5174,7 @@ ztest_run(ztest_shared_t *zs)
{
thread_t *tid;
spa_t *spa;
objset_t *os;
thread_t resume_tid;
int error;
@ -5176,6 +5206,10 @@ ztest_run(ztest_shared_t *zs)
spa->spa_debug = B_TRUE;
zs->zs_spa = spa;
VERIFY3U(0, ==, dmu_objset_hold(zs->zs_pool, FTAG, &os));
zs->zs_guid = dmu_objset_fsid_guid(os);
dmu_objset_rele(os, FTAG);
spa->spa_dedup_ditto = 2 * ZIO_DEDUPDITTO_MIN;
/*

View File

@ -102,7 +102,7 @@ fixsymbol(Elf *e, Elf_Data *data, size_t idx, int nprobes, char *buf,
int ndx;
while (gelf_getsym(data, j++, &sym) != NULL) {
prb = (dof_probe_t *)(buf + sec->dofs_offset);
prb = (dof_probe_t *)(void *)(buf + sec->dofs_offset);
for (ndx = nprobes; ndx; ndx--, prb += 1) {
funcname = dofstrtab + prb->dofpr_func;

View File

@ -873,7 +873,7 @@ dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
if (pc > sym.st_value) {
(void) snprintf(c, sizeof (c), "%s`%s+0x%llx",
dts.dts_object, dts.dts_name,
pc - sym.st_value);
(u_longlong_t)(pc - sym.st_value));
} else {
(void) snprintf(c, sizeof (c), "%s`%s",
dts.dts_object, dts.dts_name);
@ -886,9 +886,10 @@ dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format,
*/
if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) {
(void) snprintf(c, sizeof (c), "%s`0x%llx",
dts.dts_object, pc);
dts.dts_object, (u_longlong_t)pc);
} else {
(void) snprintf(c, sizeof (c), "0x%llx", pc);
(void) snprintf(c, sizeof (c), "0x%llx",
(u_longlong_t)pc);
}
}

View File

@ -335,7 +335,8 @@ dt_handle_cpudrop(dtrace_hdl_t *dtp, processorid_t cpu,
}
(void) snprintf(s, size, "%llu %sdrop%s on CPU %d\n",
howmany, what == DTRACEDROP_PRINCIPAL ? "" : "aggregation ",
(u_longlong_t)howmany,
what == DTRACEDROP_PRINCIPAL ? "" : "aggregation ",
howmany > 1 ? "s" : "", cpu);
if (dtp->dt_drophdlr == NULL)
@ -427,7 +428,8 @@ dt_handle_status(dtrace_hdl_t *dtp, dtrace_status_t *old, dtrace_status_t *new)
size = sizeof (str);
}
(void) snprintf(s, size, "%llu %s%s%s\n", nval - oval,
(void) snprintf(s, size, "%llu %s%s%s\n",
(u_longlong_t)(nval - oval),
_dt_droptab[i].dtdrt_str, (nval - oval > 1) ? "s" : "",
_dt_droptab[i].dtdrt_msg != NULL ?
_dt_droptab[i].dtdrt_msg : "");

View File

@ -1106,7 +1106,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
static const char dt_prefix[] = "__dtrace";
static const char dt_enabled[] = "enabled";
static const char dt_symprefix[] = "$dtrace";
static const char dt_symfmt[] = "%s%d.%s";
static const char dt_symfmt[] = "%s%ld.%s";
int fd, i, ndx, eprobe, mod = 0;
Elf *elf = NULL;
GElf_Ehdr ehdr;

View File

@ -27,6 +27,7 @@
#if defined(sun)
#include <sys/sysmacros.h>
#endif
#include <sys/isa_defs.h>
#include <strings.h>
#include <unistd.h>

View File

@ -436,7 +436,7 @@ dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
char name[sizeof (i) * 2 + 1];
for (i = 0; i < end; i += size) {
(void) snprintf(name, sizeof (name), "%x", i);
(void) snprintf(name, sizeof (name), "%lx", i);
if (gmatch(name, pattern))
ftp->ftps_offs[ftp->ftps_noffs++] = i;

View File

@ -21,8 +21,8 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
* All rights reserved.
*/
@ -233,6 +233,7 @@ typedef struct splitflags {
*/
extern int zpool_scan(zpool_handle_t *, pool_scan_func_t);
extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *);
extern int zpool_reguid(zpool_handle_t *);
extern int zpool_vdev_online(zpool_handle_t *, const char *, int,
vdev_state_t *);
@ -384,6 +385,7 @@ extern void zpool_explain_recover(libzfs_handle_t *, const char *, int,
* underlying datasets, only the references to them.
*/
extern zfs_handle_t *zfs_open(libzfs_handle_t *, const char *, int);
extern zfs_handle_t *zfs_handle_dup(zfs_handle_t *);
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 *);
@ -417,12 +419,20 @@ extern int zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
uint64_t *propvalue);
extern int zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
char *propbuf, int proplen, boolean_t literal);
extern int zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
uint64_t *propvalue);
extern int zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
char *propbuf, int proplen, boolean_t literal);
extern int zfs_get_snapused_int(zfs_handle_t *firstsnap, zfs_handle_t *lastsnap,
uint64_t *usedp);
extern uint64_t zfs_prop_get_int(zfs_handle_t *, zfs_prop_t);
extern int zfs_prop_inherit(zfs_handle_t *, const char *, boolean_t);
extern const char *zfs_prop_values(zfs_prop_t);
extern int zfs_prop_is_string(zfs_prop_t prop);
extern nvlist_t *zfs_get_user_props(zfs_handle_t *);
extern nvlist_t *zfs_get_recvd_props(zfs_handle_t *);
extern nvlist_t *zfs_get_clones_nvl(zfs_handle_t *);
typedef struct zprop_list {
int pl_prop;
@ -497,6 +507,7 @@ extern int zfs_iter_dependents(zfs_handle_t *, boolean_t, zfs_iter_f, void *);
extern int zfs_iter_filesystems(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_snapshots(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *);
extern int zfs_iter_snapspec(zfs_handle_t *, const char *, zfs_iter_f, void *);
typedef struct get_all_cb {
zfs_handle_t **cb_handles;
@ -517,6 +528,7 @@ extern int zfs_create(libzfs_handle_t *, const char *, zfs_type_t,
extern int zfs_create_ancestors(libzfs_handle_t *, const char *);
extern int zfs_destroy(zfs_handle_t *, boolean_t);
extern int zfs_destroy_snaps(zfs_handle_t *, char *, boolean_t);
extern int zfs_destroy_snaps_nvl(zfs_handle_t *, nvlist_t *, boolean_t);
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);
@ -533,29 +545,34 @@ extern int zfs_rename(zfs_handle_t *, const char *, renameflags_t flags);
typedef struct sendflags {
/* print informational messages (ie, -v was specified) */
int verbose : 1;
boolean_t verbose;
/* recursive send (ie, -R) */
int replicate : 1;
boolean_t replicate;
/* for incrementals, do all intermediate snapshots */
int doall : 1; /* (ie, -I) */
boolean_t doall;
/* if dataset is a clone, do incremental from its origin */
int fromorigin : 1;
boolean_t fromorigin;
/* do deduplication */
int dedup : 1;
boolean_t dedup;
/* send properties (ie, -p) */
int props : 1;
boolean_t props;
/* do not send (no-op, ie. -n) */
boolean_t dryrun;
/* parsable verbose output (ie. -P) */
boolean_t parsable;
} sendflags_t;
typedef boolean_t (snapfilter_cb_t)(zfs_handle_t *, void *);
extern int zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
sendflags_t flags, int outfd, snapfilter_cb_t filter_func,
void *cb_arg, nvlist_t **debugnvp);
extern int zfs_send(zfs_handle_t *, const char *, const char *,
sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
extern int zfs_promote(zfs_handle_t *);
extern int zfs_hold(zfs_handle_t *, const char *, const char *, boolean_t,
@ -575,34 +592,34 @@ extern int zfs_set_fsacl(zfs_handle_t *, boolean_t, nvlist_t *);
typedef struct recvflags {
/* print informational messages (ie, -v was specified) */
int verbose : 1;
boolean_t verbose;
/* the destination is a prefix, not the exact fs (ie, -d) */
int isprefix : 1;
boolean_t isprefix;
/*
* Only the tail of the sent snapshot path is appended to the
* destination to determine the received snapshot name (ie, -e).
*/
int istail : 1;
boolean_t istail;
/* do not actually do the recv, just check if it would work (ie, -n) */
int dryrun : 1;
boolean_t dryrun;
/* rollback/destroy filesystems as necessary (eg, -F) */
int force : 1;
boolean_t force;
/* set "canmount=off" on all modified filesystems */
int canmountoff : 1;
boolean_t canmountoff;
/* byteswap flag is used internally; callers need not specify */
int byteswap : 1;
boolean_t byteswap;
/* do not mount file systems as they are extracted (private) */
int nomount : 1;
boolean_t nomount;
} recvflags_t;
extern int zfs_receive(libzfs_handle_t *, const char *, recvflags_t,
extern int zfs_receive(libzfs_handle_t *, const char *, recvflags_t *,
int, avl_tree_t *);
typedef enum diff_flags {

View File

@ -496,7 +496,7 @@ make_dataset_handle(libzfs_handle_t *hdl, const char *path)
return (zhp);
}
static zfs_handle_t *
zfs_handle_t *
make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
{
zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
@ -513,6 +513,53 @@ make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
return (zhp);
}
zfs_handle_t *
zfs_handle_dup(zfs_handle_t *zhp_orig)
{
zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
if (zhp == NULL)
return (NULL);
zhp->zfs_hdl = zhp_orig->zfs_hdl;
zhp->zpool_hdl = zhp_orig->zpool_hdl;
(void) strlcpy(zhp->zfs_name, zhp_orig->zfs_name,
sizeof (zhp->zfs_name));
zhp->zfs_type = zhp_orig->zfs_type;
zhp->zfs_head_type = zhp_orig->zfs_head_type;
zhp->zfs_dmustats = zhp_orig->zfs_dmustats;
if (zhp_orig->zfs_props != NULL) {
if (nvlist_dup(zhp_orig->zfs_props, &zhp->zfs_props, 0) != 0) {
(void) no_memory(zhp->zfs_hdl);
zfs_close(zhp);
return (NULL);
}
}
if (zhp_orig->zfs_user_props != NULL) {
if (nvlist_dup(zhp_orig->zfs_user_props,
&zhp->zfs_user_props, 0) != 0) {
(void) no_memory(zhp->zfs_hdl);
zfs_close(zhp);
return (NULL);
}
}
if (zhp_orig->zfs_recvd_props != NULL) {
if (nvlist_dup(zhp_orig->zfs_recvd_props,
&zhp->zfs_recvd_props, 0)) {
(void) no_memory(zhp->zfs_hdl);
zfs_close(zhp);
return (NULL);
}
}
zhp->zfs_mntcheck = zhp_orig->zfs_mntcheck;
if (zhp_orig->zfs_mntopts != NULL) {
zhp->zfs_mntopts = zfs_strdup(zhp_orig->zfs_hdl,
zhp_orig->zfs_mntopts);
}
zhp->zfs_props_table = zhp_orig->zfs_props_table;
return (zhp);
}
/*
* Opens the given snapshot, filesystem, or volume. The 'types'
* argument is a mask of acceptable types. The function will print an
@ -876,6 +923,12 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
goto error;
}
continue;
} else if (prop == ZPROP_INVAL && zfs_prop_written(propname)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' is readonly"),
propname);
(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
goto error;
}
if (prop == ZPROP_INVAL) {
@ -1869,8 +1922,6 @@ zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
err = zfs_prop_get(zhp, prop, propbuf, proplen,
NULL, NULL, 0, literal);
zfs_unset_recvd_props_mode(zhp, &cookie);
} else if (zfs_prop_userquota(propname)) {
return (-1);
} else {
nvlist_t *propval;
char *recvdval;
@ -1885,6 +1936,120 @@ zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
return (err == 0 ? 0 : -1);
}
static int
get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
{
nvlist_t *value;
nvpair_t *pair;
value = zfs_get_clones_nvl(zhp);
if (value == NULL)
return (-1);
propbuf[0] = '\0';
for (pair = nvlist_next_nvpair(value, NULL); pair != NULL;
pair = nvlist_next_nvpair(value, pair)) {
if (propbuf[0] != '\0')
(void) strlcat(propbuf, ",", proplen);
(void) strlcat(propbuf, nvpair_name(pair), proplen);
}
return (0);
}
struct get_clones_arg {
uint64_t numclones;
nvlist_t *value;
const char *origin;
char buf[ZFS_MAXNAMELEN];
};
int
get_clones_cb(zfs_handle_t *zhp, void *arg)
{
struct get_clones_arg *gca = arg;
if (gca->numclones == 0) {
zfs_close(zhp);
return (0);
}
if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf),
NULL, NULL, 0, B_TRUE) != 0)
goto out;
if (strcmp(gca->buf, gca->origin) == 0) {
if (nvlist_add_boolean(gca->value, zfs_get_name(zhp)) != 0) {
zfs_close(zhp);
return (no_memory(zhp->zfs_hdl));
}
gca->numclones--;
}
out:
(void) zfs_iter_children(zhp, get_clones_cb, gca);
zfs_close(zhp);
return (0);
}
nvlist_t *
zfs_get_clones_nvl(zfs_handle_t *zhp)
{
nvlist_t *nv, *value;
if (nvlist_lookup_nvlist(zhp->zfs_props,
zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) {
struct get_clones_arg gca;
/*
* if this is a snapshot, then the kernel wasn't able
* to get the clones. Do it by slowly iterating.
*/
if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT)
return (NULL);
if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0)
return (NULL);
if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) {
nvlist_free(nv);
return (NULL);
}
gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES);
gca.value = value;
gca.origin = zhp->zfs_name;
if (gca.numclones != 0) {
zfs_handle_t *root;
char pool[ZFS_MAXNAMELEN];
char *cp = pool;
/* get the pool name */
(void) strlcpy(pool, zhp->zfs_name, sizeof (pool));
(void) strsep(&cp, "/@");
root = zfs_open(zhp->zfs_hdl, pool,
ZFS_TYPE_FILESYSTEM);
(void) get_clones_cb(root, &gca);
}
if (gca.numclones != 0 ||
nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 ||
nvlist_add_nvlist(zhp->zfs_props,
zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) {
nvlist_free(nv);
nvlist_free(value);
return (NULL);
}
nvlist_free(nv);
nvlist_free(value);
verify(0 == nvlist_lookup_nvlist(zhp->zfs_props,
zfs_prop_to_name(ZFS_PROP_CLONES), &nv));
}
verify(nvlist_lookup_nvlist(nv, ZPROP_VALUE, &value) == 0);
return (value);
}
/*
* Retrieve a property from the given object. If 'literal' is specified, then
* numbers are left as exact values. Otherwise, numbers are converted to a
@ -2013,6 +2178,11 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
return (-1);
break;
case ZFS_PROP_CLONES:
if (get_clones_string(zhp, propbuf, proplen) != 0)
return (-1);
break;
case ZFS_PROP_QUOTA:
case ZFS_PROP_REFQUOTA:
case ZFS_PROP_RESERVATION:
@ -2385,7 +2555,7 @@ zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
int err;
zfs_cmd_t zc = { 0 };
(void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
err = userquota_propname_decode(propname,
zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
@ -2437,6 +2607,79 @@ zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
return (0);
}
int
zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
uint64_t *propvalue)
{
int err;
zfs_cmd_t zc = { 0 };
const char *snapname;
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
snapname = strchr(propname, '@') + 1;
if (strchr(snapname, '@')) {
(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
} else {
/* snapname is the short name, append it to zhp's fsname */
char *cp;
(void) strlcpy(zc.zc_value, zhp->zfs_name,
sizeof (zc.zc_value));
cp = strchr(zc.zc_value, '@');
if (cp != NULL)
*cp = '\0';
(void) strlcat(zc.zc_value, "@", sizeof (zc.zc_value));
(void) strlcat(zc.zc_value, snapname, sizeof (zc.zc_value));
}
err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_WRITTEN, &zc);
if (err)
return (err);
*propvalue = zc.zc_cookie;
return (0);
}
int
zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
char *propbuf, int proplen, boolean_t literal)
{
int err;
uint64_t propvalue;
err = zfs_prop_get_written_int(zhp, propname, &propvalue);
if (err)
return (err);
if (literal) {
(void) snprintf(propbuf, proplen, "%llu", propvalue);
} else {
zfs_nicenum(propvalue, propbuf, proplen);
}
return (0);
}
int
zfs_get_snapused_int(zfs_handle_t *firstsnap, zfs_handle_t *lastsnap,
uint64_t *usedp)
{
int err;
zfs_cmd_t zc = { 0 };
(void) strlcpy(zc.zc_name, lastsnap->zfs_name, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_value, firstsnap->zfs_name, sizeof (zc.zc_value));
err = ioctl(lastsnap->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_SNAPS, &zc);
if (err)
return (err);
*usedp = zc.zc_cookie;
return (0);
}
/*
* Returns the name of the given zfs handle.
*/
@ -2455,128 +2698,6 @@ zfs_get_type(const zfs_handle_t *zhp)
return (zhp->zfs_type);
}
static int
zfs_do_list_ioctl(zfs_handle_t *zhp, unsigned long arg, zfs_cmd_t *zc)
{
int rc;
uint64_t orig_cookie;
orig_cookie = zc->zc_cookie;
top:
(void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
rc = ioctl(zhp->zfs_hdl->libzfs_fd, arg, zc);
if (rc == -1) {
switch (errno) {
case ENOMEM:
/* expand nvlist memory and try again */
if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, zc) != 0) {
zcmd_free_nvlists(zc);
return (-1);
}
zc->zc_cookie = orig_cookie;
goto top;
/*
* An errno value of ESRCH indicates normal completion.
* If ENOENT is returned, then the underlying dataset
* has been removed since we obtained the handle.
*/
case ESRCH:
case ENOENT:
rc = 1;
break;
default:
rc = zfs_standard_error(zhp->zfs_hdl, errno,
dgettext(TEXT_DOMAIN,
"cannot iterate filesystems"));
break;
}
}
return (rc);
}
/*
* Iterate over all child filesystems
*/
int
zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
zfs_cmd_t zc = { 0 };
zfs_handle_t *nzhp;
int ret;
if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM)
return (0);
if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT,
&zc)) == 0) {
/*
* Silently ignore errors, as the only plausible explanation is
* that the pool has since been removed.
*/
if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
&zc)) == NULL) {
continue;
}
if ((ret = func(nzhp, data)) != 0) {
zcmd_free_nvlists(&zc);
return (ret);
}
}
zcmd_free_nvlists(&zc);
return ((ret < 0) ? ret : 0);
}
/*
* Iterate over all snapshots
*/
int
zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
zfs_cmd_t zc = { 0 };
zfs_handle_t *nzhp;
int ret;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
return (0);
if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT,
&zc)) == 0) {
if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
&zc)) == NULL) {
continue;
}
if ((ret = func(nzhp, data)) != 0) {
zcmd_free_nvlists(&zc);
return (ret);
}
}
zcmd_free_nvlists(&zc);
return ((ret < 0) ? ret : 0);
}
/*
* Iterate over all children, snapshots and filesystems
*/
int
zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
int ret;
if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
return (ret);
return (zfs_iter_snapshots(zhp, func, data));
}
/*
* Is one dataset name a child dataset of another?
*
@ -2600,18 +2721,19 @@ is_descendant(const char *ds1, const char *ds2)
/*
* Given a complete name, return just the portion that refers to the parent.
* Can return NULL if this is a pool.
* Will return -1 if there is no parent (path is just the name of the
* pool).
*/
static int
parent_name(const char *path, char *buf, size_t buflen)
{
char *loc;
char *slashp;
if ((loc = strrchr(path, '/')) == NULL)
(void) strlcpy(buf, path, buflen);
if ((slashp = strrchr(buf, '/')) == NULL)
return (-1);
(void) strncpy(buf, path, MIN(buflen, loc - path));
buf[loc - path] = '\0';
*slashp = '\0';
return (0);
}
@ -3010,9 +3132,8 @@ zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
}
struct destroydata {
char *snapname;
boolean_t gotone;
boolean_t closezhp;
nvlist_t *nvl;
const char *snapname;
};
static int
@ -3021,24 +3142,19 @@ zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
struct destroydata *dd = arg;
zfs_handle_t *szhp;
char name[ZFS_MAXNAMELEN];
boolean_t closezhp = dd->closezhp;
int rv = 0;
(void) strlcpy(name, zhp->zfs_name, sizeof (name));
(void) strlcat(name, "@", sizeof (name));
(void) strlcat(name, dd->snapname, sizeof (name));
(void) snprintf(name, sizeof (name),
"%s@%s", zhp->zfs_name, dd->snapname);
szhp = make_dataset_handle(zhp->zfs_hdl, name);
if (szhp) {
dd->gotone = B_TRUE;
verify(nvlist_add_boolean(dd->nvl, name) == 0);
zfs_close(szhp);
}
dd->closezhp = B_TRUE;
if (!dd->gotone)
rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, arg);
if (closezhp)
zfs_close(zhp);
rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd);
zfs_close(zhp);
return (rv);
}
@ -3048,29 +3164,45 @@ zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
int
zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
{
zfs_cmd_t zc = { 0 };
int ret;
struct destroydata dd = { 0 };
dd.snapname = snapname;
(void) zfs_check_snap_cb(zhp, &dd);
verify(nvlist_alloc(&dd.nvl, NV_UNIQUE_NAME, 0) == 0);
(void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd);
if (!dd.gotone) {
return (zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
if (nvlist_next_nvpair(dd.nvl, NULL) == NULL) {
ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
zhp->zfs_name, snapname));
zhp->zfs_name, snapname);
} else {
ret = zfs_destroy_snaps_nvl(zhp, dd.nvl, defer);
}
nvlist_free(dd.nvl);
return (ret);
}
/*
* Destroys all the snapshots named in the nvlist. They must be underneath
* the zhp (either snapshots of it, or snapshots of its descendants).
*/
int
zfs_destroy_snaps_nvl(zfs_handle_t *zhp, nvlist_t *snaps, boolean_t defer)
{
int ret;
zfs_cmd_t zc = { 0 };
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
if (zcmd_write_src_nvlist(zhp->zfs_hdl, &zc, snaps) != 0)
return (-1);
zc.zc_defer_destroy = defer;
ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS, &zc);
ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS_NVL, &zc);
if (ret != 0) {
char errbuf[1024];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot destroy '%s@%s'"), zc.zc_name, snapname);
"cannot destroy snapshots in %s"), zc.zc_name);
switch (errno) {
case EEXIST:
@ -3106,7 +3238,7 @@ zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot create '%s'"), target);
/* validate the target name */
/* validate the target/clone name */
if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
@ -3442,42 +3574,6 @@ zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
return (err);
}
/*
* Iterate over all dependents for a given dataset. This includes both
* hierarchical dependents (children) and data dependents (snapshots and
* clones). The bulk of the processing occurs in get_dependents() in
* libzfs_graph.c.
*/
int
zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
zfs_iter_f func, void *data)
{
char **dependents;
size_t count;
int i;
zfs_handle_t *child;
int ret = 0;
if (get_dependents(zhp->zfs_hdl, allowrecursion, zhp->zfs_name,
&dependents, &count) != 0)
return (-1);
for (i = 0; i < count; i++) {
if ((child = make_dataset_handle(zhp->zfs_hdl,
dependents[i])) == NULL)
continue;
if ((ret = func(child, data)) != 0)
break;
}
for (i = 0; i < count; i++)
free(dependents[i]);
free(dependents);
return (ret);
}
/*
* Renames the given dataset.
*/
@ -3947,7 +4043,7 @@ zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
int error;
zfs_useracct_t buf[100];
(void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
zc.zc_objset_type = type;
zc.zc_nvlist_dst = (uintptr_t)buf;

View File

@ -1,653 +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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Iterate over all children of the current object. This includes the normal
* dataset hierarchy, but also arbitrary hierarchies due to clones. We want to
* walk all datasets in the pool, and construct a directed graph of the form:
*
* home
* |
* +----+----+
* | |
* v v ws
* bar baz |
* | |
* v v
* @yesterday ----> foo
*
* In order to construct this graph, we have to walk every dataset in the pool,
* because the clone parent is stored as a property of the child, not the
* parent. The parent only keeps track of the number of clones.
*
* In the normal case (without clones) this would be rather expensive. To avoid
* unnecessary computation, we first try a walk of the subtree hierarchy
* starting from the initial node. At each dataset, we construct a node in the
* graph and an edge leading from its parent. If we don't see any snapshots
* with a non-zero clone count, then we are finished.
*
* If we do find a cloned snapshot, then we finish the walk of the current
* subtree, but indicate that we need to do a complete walk. We then perform a
* global walk of all datasets, avoiding the subtree we already processed.
*
* At the end of this, we'll end up with a directed graph of all relevant (and
* possible some irrelevant) datasets in the system. We need to both find our
* limiting subgraph and determine a safe ordering in which to destroy the
* datasets. We do a topological ordering of our graph starting at our target
* dataset, and then walk the results in reverse.
*
* It's possible for the graph to have cycles if, for example, the user renames
* a clone to be the parent of its origin snapshot. The user can request to
* generate an error in this case, or ignore the cycle and continue.
*
* When removing datasets, we want to destroy the snapshots in chronological
* order (because this is the most efficient method). In order to accomplish
* this, we store the creation transaction group with each vertex and keep each
* vertex's edges sorted according to this value. The topological sort will
* automatically walk the snapshots in the correct order.
*/
#include <assert.h>
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <libzfs.h>
#include "libzfs_impl.h"
#include "zfs_namecheck.h"
#define MIN_EDGECOUNT 4
/*
* Vertex structure. Indexed by dataset name, this structure maintains a list
* of edges to other vertices.
*/
struct zfs_edge;
typedef struct zfs_vertex {
char zv_dataset[ZFS_MAXNAMELEN];
struct zfs_vertex *zv_next;
int zv_visited;
uint64_t zv_txg;
struct zfs_edge **zv_edges;
int zv_edgecount;
int zv_edgealloc;
} zfs_vertex_t;
enum {
VISIT_SEEN = 1,
VISIT_SORT_PRE,
VISIT_SORT_POST
};
/*
* Edge structure. Simply maintains a pointer to the destination vertex. There
* is no need to store the source vertex, since we only use edges in the context
* of the source vertex.
*/
typedef struct zfs_edge {
zfs_vertex_t *ze_dest;
struct zfs_edge *ze_next;
} zfs_edge_t;
#define ZFS_GRAPH_SIZE 1027 /* this could be dynamic some day */
/*
* Graph structure. Vertices are maintained in a hash indexed by dataset name.
*/
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;
/*
* Allocate a new edge pointing to the target vertex.
*/
static zfs_edge_t *
zfs_edge_create(libzfs_handle_t *hdl, zfs_vertex_t *dest)
{
zfs_edge_t *zep = zfs_alloc(hdl, sizeof (zfs_edge_t));
if (zep == NULL)
return (NULL);
zep->ze_dest = dest;
return (zep);
}
/*
* Destroy an edge.
*/
static void
zfs_edge_destroy(zfs_edge_t *zep)
{
free(zep);
}
/*
* Allocate a new vertex with the given name.
*/
static zfs_vertex_t *
zfs_vertex_create(libzfs_handle_t *hdl, const char *dataset)
{
zfs_vertex_t *zvp = zfs_alloc(hdl, sizeof (zfs_vertex_t));
if (zvp == NULL)
return (NULL);
assert(strlen(dataset) < ZFS_MAXNAMELEN);
(void) strlcpy(zvp->zv_dataset, dataset, sizeof (zvp->zv_dataset));
if ((zvp->zv_edges = zfs_alloc(hdl,
MIN_EDGECOUNT * sizeof (void *))) == NULL) {
free(zvp);
return (NULL);
}
zvp->zv_edgealloc = MIN_EDGECOUNT;
return (zvp);
}
/*
* Destroy a vertex. Frees up any associated edges.
*/
static void
zfs_vertex_destroy(zfs_vertex_t *zvp)
{
int i;
for (i = 0; i < zvp->zv_edgecount; i++)
zfs_edge_destroy(zvp->zv_edges[i]);
free(zvp->zv_edges);
free(zvp);
}
/*
* Given a vertex, add an edge to the destination vertex.
*/
static int
zfs_vertex_add_edge(libzfs_handle_t *hdl, zfs_vertex_t *zvp,
zfs_vertex_t *dest)
{
zfs_edge_t *zep = zfs_edge_create(hdl, dest);
if (zep == NULL)
return (-1);
if (zvp->zv_edgecount == zvp->zv_edgealloc) {
void *ptr;
if ((ptr = zfs_realloc(hdl, zvp->zv_edges,
zvp->zv_edgealloc * sizeof (void *),
zvp->zv_edgealloc * 2 * sizeof (void *))) == NULL)
return (-1);
zvp->zv_edges = ptr;
zvp->zv_edgealloc *= 2;
}
zvp->zv_edges[zvp->zv_edgecount++] = zep;
return (0);
}
static int
zfs_edge_compare(const void *a, const void *b)
{
const zfs_edge_t *ea = *((zfs_edge_t **)a);
const zfs_edge_t *eb = *((zfs_edge_t **)b);
if (ea->ze_dest->zv_txg < eb->ze_dest->zv_txg)
return (-1);
if (ea->ze_dest->zv_txg > eb->ze_dest->zv_txg)
return (1);
return (0);
}
/*
* Sort the given vertex edges according to the creation txg of each vertex.
*/
static void
zfs_vertex_sort_edges(zfs_vertex_t *zvp)
{
if (zvp->zv_edgecount == 0)
return;
qsort(zvp->zv_edges, zvp->zv_edgecount, sizeof (void *),
zfs_edge_compare);
}
/*
* Construct a new graph object. We allow the size to be specified as a
* parameter so in the future we can size the hash according to the number of
* datasets in the pool.
*/
static zfs_graph_t *
zfs_graph_create(libzfs_handle_t *hdl, const char *dataset, size_t size)
{
zfs_graph_t *zgp = zfs_alloc(hdl, sizeof (zfs_graph_t));
if (zgp == NULL)
return (NULL);
zgp->zg_size = size;
if ((zgp->zg_hash = zfs_alloc(hdl,
size * sizeof (zfs_vertex_t *))) == NULL) {
free(zgp);
return (NULL);
}
zgp->zg_root = dataset;
zgp->zg_clone_count = 0;
return (zgp);
}
/*
* Destroy a graph object. We have to iterate over all the hash chains,
* destroying each vertex in the process.
*/
static void
zfs_graph_destroy(zfs_graph_t *zgp)
{
int i;
zfs_vertex_t *current, *next;
for (i = 0; i < zgp->zg_size; i++) {
current = zgp->zg_hash[i];
while (current != NULL) {
next = current->zv_next;
zfs_vertex_destroy(current);
current = next;
}
}
free(zgp->zg_hash);
free(zgp);
}
/*
* Graph hash function. Classic bernstein k=33 hash function, taken from
* usr/src/cmd/sgs/tools/common/strhash.c
*/
static size_t
zfs_graph_hash(zfs_graph_t *zgp, const char *str)
{
size_t hash = 5381;
int c;
while ((c = *str++) != 0)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return (hash % zgp->zg_size);
}
/*
* Given a dataset name, finds the associated vertex, creating it if necessary.
*/
static zfs_vertex_t *
zfs_graph_lookup(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset,
uint64_t txg)
{
size_t idx = zfs_graph_hash(zgp, dataset);
zfs_vertex_t *zvp;
for (zvp = zgp->zg_hash[idx]; zvp != NULL; zvp = zvp->zv_next) {
if (strcmp(zvp->zv_dataset, dataset) == 0) {
if (zvp->zv_txg == 0)
zvp->zv_txg = txg;
return (zvp);
}
}
if ((zvp = zfs_vertex_create(hdl, dataset)) == NULL)
return (NULL);
zvp->zv_next = zgp->zg_hash[idx];
zvp->zv_txg = txg;
zgp->zg_hash[idx] = zvp;
zgp->zg_nvertex++;
return (zvp);
}
/*
* Given two dataset names, create an edge between them. For the source vertex,
* mark 'zv_visited' to indicate that we have seen this vertex, and not simply
* created it as a destination of another edge. If 'dest' is NULL, then this
* is an individual vertex (i.e. the starting vertex), so don't add an edge.
*/
static int
zfs_graph_add(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *source,
const char *dest, uint64_t txg)
{
zfs_vertex_t *svp, *dvp;
if ((svp = zfs_graph_lookup(hdl, zgp, source, 0)) == NULL)
return (-1);
svp->zv_visited = VISIT_SEEN;
if (dest != NULL) {
dvp = zfs_graph_lookup(hdl, zgp, dest, txg);
if (dvp == NULL)
return (-1);
if (zfs_vertex_add_edge(hdl, svp, dvp) != 0)
return (-1);
}
return (0);
}
/*
* 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().
*/
static int
iterate_children(libzfs_handle_t *hdl, zfs_graph_t *zgp, const char *dataset)
{
zfs_cmd_t zc = { 0 };
zfs_vertex_t *zvp;
/*
* Look up the source vertex, and avoid it if we've seen it before.
*/
zvp = zfs_graph_lookup(hdl, zgp, dataset, 0);
if (zvp == NULL)
return (-1);
if (zvp->zv_visited == VISIT_SEEN)
return (0);
/*
* Iterate over all children
*/
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))) {
/*
* Get statistics for this dataset, to determine the type of the
* 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.
*/
if (zfs_graph_add(hdl, zgp, dataset, zc.zc_name,
zc.zc_objset_stats.dds_creation_txg) != 0)
return (-1);
/*
* Recursively visit child
*/
if (iterate_children(hdl, zgp, zc.zc_name))
return (-1);
}
/*
* Now iterate over all snapshots.
*/
bzero(&zc, sizeof (zc));
for ((void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
ioctl(hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc) == 0;
(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name))) {
/*
* Get statistics for this dataset, to determine the type of the
* dataset and clone statistics. If this fails, the dataset has
* since been removed, and we're pretty much screwed anyway.
*/
if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0)
continue;
/*
* Add an edge between the parent and the child.
*/
if (zfs_graph_add(hdl, zgp, dataset, zc.zc_name,
zc.zc_objset_stats.dds_creation_txg) != 0)
return (-1);
zgp->zg_clone_count += zc.zc_objset_stats.dds_num_clones;
}
zvp->zv_visited = VISIT_SEEN;
return (0);
}
/*
* 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.
*/
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);
int ret = 0;
if (zgp == NULL)
return (zgp);
if ((strchr(dataset, '/') == NULL) ||
(external_dependents(hdl, zgp, dataset))) {
/*
* Determine pool name and try again.
*/
int len = strcspn(dataset, "/@") + 1;
char *pool = zfs_alloc(hdl, len);
if (pool == NULL) {
zfs_graph_destroy(zgp);
return (NULL);
}
(void) strlcpy(pool, dataset, len);
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) {
zfs_graph_destroy(zgp);
return (NULL);
}
return (zgp);
}
/*
* Given a graph, do a recursive topological sort into the given array. This is
* really just a depth first search, so that the deepest nodes appear first.
* hijack the 'zv_visited' marker to avoid visiting the same vertex twice.
*/
static int
topo_sort(libzfs_handle_t *hdl, boolean_t allowrecursion, char **result,
size_t *idx, zfs_vertex_t *zgv)
{
int i;
if (zgv->zv_visited == VISIT_SORT_PRE && !allowrecursion) {
/*
* If we've already seen this vertex as part of our depth-first
* search, then we have a cyclic dependency, and we must return
* an error.
*/
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"recursive dependency at '%s'"),
zgv->zv_dataset);
return (zfs_error(hdl, EZFS_RECURSIVE,
dgettext(TEXT_DOMAIN,
"cannot determine dependent datasets")));
} else if (zgv->zv_visited >= VISIT_SORT_PRE) {
/*
* If we've already processed this as part of the topological
* sort, then don't bother doing so again.
*/
return (0);
}
zgv->zv_visited = VISIT_SORT_PRE;
/* avoid doing a search if we don't have to */
zfs_vertex_sort_edges(zgv);
for (i = 0; i < zgv->zv_edgecount; i++) {
if (topo_sort(hdl, allowrecursion, result, idx,
zgv->zv_edges[i]->ze_dest) != 0)
return (-1);
}
/* we may have visited this in the course of the above */
if (zgv->zv_visited == VISIT_SORT_POST)
return (0);
if ((result[*idx] = zfs_alloc(hdl,
strlen(zgv->zv_dataset) + 1)) == NULL)
return (-1);
(void) strcpy(result[*idx], zgv->zv_dataset);
*idx += 1;
zgv->zv_visited = VISIT_SORT_POST;
return (0);
}
/*
* The only public interface for this file. Do the dirty work of constructing a
* child list for the given object. Construct the graph, do the toplogical
* sort, and then return the array of strings to the caller.
*
* The 'allowrecursion' parameter controls behavior when cycles are found. If
* it is set, the the cycle is ignored and the results returned as if the cycle
* did not exist. If it is not set, then the routine will generate an error if
* a cycle is found.
*/
int
get_dependents(libzfs_handle_t *hdl, boolean_t allowrecursion,
const char *dataset, char ***result, size_t *count)
{
zfs_graph_t *zgp;
zfs_vertex_t *zvp;
if ((zgp = construct_graph(hdl, dataset)) == NULL)
return (-1);
if ((*result = zfs_alloc(hdl,
zgp->zg_nvertex * sizeof (char *))) == NULL) {
zfs_graph_destroy(zgp);
return (-1);
}
if ((zvp = zfs_graph_lookup(hdl, zgp, dataset, 0)) == NULL) {
free(*result);
zfs_graph_destroy(zgp);
return (-1);
}
*count = 0;
if (topo_sort(hdl, allowrecursion, *result, count, zvp) != 0) {
free(*result);
zfs_graph_destroy(zgp);
return (-1);
}
/*
* Get rid of the last entry, which is our starting vertex and not
* strictly a dependent.
*/
assert(*count > 0);
free((*result)[*count - 1]);
(*count)--;
zfs_graph_destroy(zgp);
return (0);
}

View File

@ -23,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
#ifndef _LIBFS_IMPL_H
@ -116,7 +117,7 @@ struct zpool_handle {
diskaddr_t zpool_start_block;
};
typedef enum {
typedef enum {
PROTO_NFS = 0,
PROTO_SMB = 1,
PROTO_END = 2
@ -148,6 +149,7 @@ int zpool_standard_error_fmt(libzfs_handle_t *, int, const char *, ...);
int get_dependents(libzfs_handle_t *, boolean_t, const char *, char ***,
size_t *);
zfs_handle_t *make_dataset_handle_zc(libzfs_handle_t *, zfs_cmd_t *);
int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t,

View File

@ -20,6 +20,8 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
/*
@ -435,7 +437,7 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
uint_t i, nspares, nl2cache;
boolean_t config_seen;
uint64_t best_txg;
char *name, *hostname;
char *name, *hostname, *comment;
uint64_t version, guid;
uint_t children = 0;
nvlist_t **child = NULL;
@ -524,6 +526,7 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
* version
* pool guid
* name
* comment (if available)
* pool state
* hostid (if available)
* hostname (if available)
@ -545,11 +548,24 @@ get_configs(libzfs_handle_t *hdl, pool_list_t *pl, boolean_t active_ok)
if (nvlist_add_string(config,
ZPOOL_CONFIG_POOL_NAME, name) != 0)
goto nomem;
/*
* COMMENT is optional, don't bail if it's not
* there, instead, set it to NULL.
*/
if (nvlist_lookup_string(tmp,
ZPOOL_CONFIG_COMMENT, &comment) != 0)
comment = NULL;
else if (nvlist_add_string(config,
ZPOOL_CONFIG_COMMENT, comment) != 0)
goto nomem;
verify(nvlist_lookup_uint64(tmp,
ZPOOL_CONFIG_POOL_STATE, &state) == 0);
if (nvlist_add_uint64(config,
ZPOOL_CONFIG_POOL_STATE, state) != 0)
goto nomem;
hostid = 0;
if (nvlist_lookup_uint64(tmp,
ZPOOL_CONFIG_HOSTID, &hostid) == 0) {

View File

@ -0,0 +1,462 @@
/*
* 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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <stddef.h>
#include <libintl.h>
#include <libzfs.h>
#include "libzfs_impl.h"
int
zfs_iter_clones(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
nvlist_t *nvl = zfs_get_clones_nvl(zhp);
nvpair_t *pair;
if (nvl == NULL)
return (0);
for (pair = nvlist_next_nvpair(nvl, NULL); pair != NULL;
pair = nvlist_next_nvpair(nvl, pair)) {
zfs_handle_t *clone = zfs_open(zhp->zfs_hdl, nvpair_name(pair),
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
if (clone != NULL) {
int err = func(clone, data);
if (err != 0)
return (err);
}
}
return (0);
}
static int
zfs_do_list_ioctl(zfs_handle_t *zhp, unsigned long arg, zfs_cmd_t *zc)
{
int rc;
uint64_t orig_cookie;
orig_cookie = zc->zc_cookie;
top:
(void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
rc = ioctl(zhp->zfs_hdl->libzfs_fd, arg, zc);
if (rc == -1) {
switch (errno) {
case ENOMEM:
/* expand nvlist memory and try again */
if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, zc) != 0) {
zcmd_free_nvlists(zc);
return (-1);
}
zc->zc_cookie = orig_cookie;
goto top;
/*
* An errno value of ESRCH indicates normal completion.
* If ENOENT is returned, then the underlying dataset
* has been removed since we obtained the handle.
*/
case ESRCH:
case ENOENT:
rc = 1;
break;
default:
rc = zfs_standard_error(zhp->zfs_hdl, errno,
dgettext(TEXT_DOMAIN,
"cannot iterate filesystems"));
break;
}
}
return (rc);
}
/*
* Iterate over all child filesystems
*/
int
zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
zfs_cmd_t zc = { 0 };
zfs_handle_t *nzhp;
int ret;
if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM)
return (0);
if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT,
&zc)) == 0) {
/*
* Silently ignore errors, as the only plausible explanation is
* that the pool has since been removed.
*/
if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
&zc)) == NULL) {
continue;
}
if ((ret = func(nzhp, data)) != 0) {
zcmd_free_nvlists(&zc);
return (ret);
}
}
zcmd_free_nvlists(&zc);
return ((ret < 0) ? ret : 0);
}
/*
* Iterate over all snapshots
*/
int
zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
zfs_cmd_t zc = { 0 };
zfs_handle_t *nzhp;
int ret;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
return (0);
if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
return (-1);
while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT,
&zc)) == 0) {
if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
&zc)) == NULL) {
continue;
}
if ((ret = func(nzhp, data)) != 0) {
zcmd_free_nvlists(&zc);
return (ret);
}
}
zcmd_free_nvlists(&zc);
return ((ret < 0) ? ret : 0);
}
/*
* Routines for dealing with the sorted snapshot functionality
*/
typedef struct zfs_node {
zfs_handle_t *zn_handle;
avl_node_t zn_avlnode;
} zfs_node_t;
static int
zfs_sort_snaps(zfs_handle_t *zhp, void *data)
{
avl_tree_t *avl = data;
zfs_node_t *node;
zfs_node_t search;
search.zn_handle = zhp;
node = avl_find(avl, &search, NULL);
if (node) {
/*
* If this snapshot was renamed while we were creating the
* AVL tree, it's possible that we already inserted it under
* its old name. Remove the old handle before adding the new
* one.
*/
zfs_close(node->zn_handle);
avl_remove(avl, node);
free(node);
}
node = zfs_alloc(zhp->zfs_hdl, sizeof (zfs_node_t));
node->zn_handle = zhp;
avl_add(avl, node);
return (0);
}
static int
zfs_snapshot_compare(const void *larg, const void *rarg)
{
zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
uint64_t lcreate, rcreate;
/*
* Sort them according to creation time. We use the hidden
* CREATETXG property to get an absolute ordering of snapshots.
*/
lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
if (lcreate < rcreate)
return (-1);
else if (lcreate > rcreate)
return (+1);
else
return (0);
}
int
zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data)
{
int ret = 0;
zfs_node_t *node;
avl_tree_t avl;
void *cookie = NULL;
avl_create(&avl, zfs_snapshot_compare,
sizeof (zfs_node_t), offsetof(zfs_node_t, zn_avlnode));
ret = zfs_iter_snapshots(zhp, zfs_sort_snaps, &avl);
for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
ret |= callback(node->zn_handle, data);
while ((node = avl_destroy_nodes(&avl, &cookie)) != NULL)
free(node);
avl_destroy(&avl);
return (ret);
}
typedef struct {
char *ssa_first;
char *ssa_last;
boolean_t ssa_seenfirst;
boolean_t ssa_seenlast;
zfs_iter_f ssa_func;
void *ssa_arg;
} snapspec_arg_t;
static int
snapspec_cb(zfs_handle_t *zhp, void *arg) {
snapspec_arg_t *ssa = arg;
char *shortsnapname;
int err = 0;
if (ssa->ssa_seenlast)
return (0);
shortsnapname = zfs_strdup(zhp->zfs_hdl,
strchr(zfs_get_name(zhp), '@') + 1);
if (!ssa->ssa_seenfirst && strcmp(shortsnapname, ssa->ssa_first) == 0)
ssa->ssa_seenfirst = B_TRUE;
if (ssa->ssa_seenfirst) {
err = ssa->ssa_func(zhp, ssa->ssa_arg);
} else {
zfs_close(zhp);
}
if (strcmp(shortsnapname, ssa->ssa_last) == 0)
ssa->ssa_seenlast = B_TRUE;
free(shortsnapname);
return (err);
}
/*
* spec is a string like "A,B%C,D"
*
* <snaps>, where <snaps> can be:
* <snap> (single snapshot)
* <snap>%<snap> (range of snapshots, inclusive)
* %<snap> (range of snapshots, starting with earliest)
* <snap>% (range of snapshots, ending with last)
* % (all snapshots)
* <snaps>[,...] (comma separated list of the above)
*
* If a snapshot can not be opened, continue trying to open the others, but
* return ENOENT at the end.
*/
int
zfs_iter_snapspec(zfs_handle_t *fs_zhp, const char *spec_orig,
zfs_iter_f func, void *arg)
{
char buf[ZFS_MAXNAMELEN];
char *comma_separated, *cp;
int err = 0;
int ret = 0;
(void) strlcpy(buf, spec_orig, sizeof (buf));
cp = buf;
while ((comma_separated = strsep(&cp, ",")) != NULL) {
char *pct = strchr(comma_separated, '%');
if (pct != NULL) {
snapspec_arg_t ssa = { 0 };
ssa.ssa_func = func;
ssa.ssa_arg = arg;
if (pct == comma_separated)
ssa.ssa_seenfirst = B_TRUE;
else
ssa.ssa_first = comma_separated;
*pct = '\0';
ssa.ssa_last = pct + 1;
/*
* If there is a lastname specified, make sure it
* exists.
*/
if (ssa.ssa_last[0] != '\0') {
char snapname[ZFS_MAXNAMELEN];
(void) snprintf(snapname, sizeof (snapname),
"%s@%s", zfs_get_name(fs_zhp),
ssa.ssa_last);
if (!zfs_dataset_exists(fs_zhp->zfs_hdl,
snapname, ZFS_TYPE_SNAPSHOT)) {
ret = ENOENT;
continue;
}
}
err = zfs_iter_snapshots_sorted(fs_zhp,
snapspec_cb, &ssa);
if (ret == 0)
ret = err;
if (ret == 0 && (!ssa.ssa_seenfirst ||
(ssa.ssa_last[0] != '\0' && !ssa.ssa_seenlast))) {
ret = ENOENT;
}
} else {
char snapname[ZFS_MAXNAMELEN];
zfs_handle_t *snap_zhp;
(void) snprintf(snapname, sizeof (snapname), "%s@%s",
zfs_get_name(fs_zhp), comma_separated);
snap_zhp = make_dataset_handle(fs_zhp->zfs_hdl,
snapname);
if (snap_zhp == NULL) {
ret = ENOENT;
continue;
}
err = func(snap_zhp, arg);
if (ret == 0)
ret = err;
}
}
return (ret);
}
/*
* Iterate over all children, snapshots and filesystems
*/
int
zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
{
int ret;
if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
return (ret);
return (zfs_iter_snapshots(zhp, func, data));
}
typedef struct iter_stack_frame {
struct iter_stack_frame *next;
zfs_handle_t *zhp;
} iter_stack_frame_t;
typedef struct iter_dependents_arg {
boolean_t first;
boolean_t allowrecursion;
iter_stack_frame_t *stack;
zfs_iter_f func;
void *data;
} iter_dependents_arg_t;
static int
iter_dependents_cb(zfs_handle_t *zhp, void *arg)
{
iter_dependents_arg_t *ida = arg;
int err;
boolean_t first = ida->first;
ida->first = B_FALSE;
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
err = zfs_iter_clones(zhp, iter_dependents_cb, ida);
} else {
iter_stack_frame_t isf;
iter_stack_frame_t *f;
/*
* check if there is a cycle by seeing if this fs is already
* on the stack.
*/
for (f = ida->stack; f != NULL; f = f->next) {
if (f->zhp->zfs_dmustats.dds_guid ==
zhp->zfs_dmustats.dds_guid) {
if (ida->allowrecursion) {
zfs_close(zhp);
return (0);
} else {
zfs_error_aux(zhp->zfs_hdl,
dgettext(TEXT_DOMAIN,
"recursive dependency at '%s'"),
zfs_get_name(zhp));
err = zfs_error(zhp->zfs_hdl,
EZFS_RECURSIVE,
dgettext(TEXT_DOMAIN,
"cannot determine dependent "
"datasets"));
zfs_close(zhp);
return (err);
}
}
}
isf.zhp = zhp;
isf.next = ida->stack;
ida->stack = &isf;
err = zfs_iter_filesystems(zhp, iter_dependents_cb, ida);
if (err == 0)
err = zfs_iter_snapshots(zhp, iter_dependents_cb, ida);
ida->stack = isf.next;
}
if (!first && err == 0)
err = ida->func(zhp, ida->data);
return (err);
}
int
zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
zfs_iter_f func, void *data)
{
iter_dependents_arg_t ida;
ida.allowrecursion = allowrecursion;
ida.stack = NULL;
ida.func = func;
ida.data = data;
ida.first = B_TRUE;
return (iter_dependents_cb(zfs_handle_dup(zhp), &ida));
}

View File

@ -21,6 +21,8 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@ -261,6 +263,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
case ZPOOL_PROP_ALTROOT:
case ZPOOL_PROP_CACHEFILE:
case ZPOOL_PROP_COMMENT:
if (zhp->zpool_props != NULL ||
zpool_get_all_props(zhp) == 0) {
(void) strlcpy(buf,
@ -412,7 +415,7 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
zpool_prop_t prop;
char *strval;
uint64_t intval;
char *slash;
char *slash, *check;
struct stat64 statbuf;
zpool_handle_t *zhp;
nvlist_t *nvroot;
@ -573,6 +576,26 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
*slash = '/';
break;
case ZPOOL_PROP_COMMENT:
for (check = strval; *check != '\0'; check++) {
if (!isprint(*check)) {
zfs_error_aux(hdl,
dgettext(TEXT_DOMAIN,
"comment may only have printable "
"characters"));
(void) zfs_error(hdl, EZFS_BADPROP,
errbuf);
goto error;
}
}
if (strlen(strval) > ZPROP_MAX_COMMENT) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"comment must not exceed %d characters"),
ZPROP_MAX_COMMENT);
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}
break;
case ZPOOL_PROP_READONLY:
if (!flags.import) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@ -3010,6 +3033,26 @@ zpool_vdev_clear(zpool_handle_t *zhp, uint64_t guid)
return (zpool_standard_error(hdl, errno, msg));
}
/*
* Change the GUID for a pool.
*/
int
zpool_reguid(zpool_handle_t *zhp)
{
char msg[1024];
libzfs_handle_t *hdl = zhp->zpool_hdl;
zfs_cmd_t zc = { 0 };
(void) snprintf(msg, sizeof (msg),
dgettext(TEXT_DOMAIN, "cannot reguid '%s'"), zhp->zpool_name);
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
if (zfs_ioctl(hdl, ZFS_IOC_POOL_REGUID, &zc) == 0)
return (0);
return (zpool_standard_error(hdl, errno, msg));
}
/*
* Convert from a devid string to a path.
*/

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
*/
/*
@ -351,6 +352,7 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
switch (error) {
case ENXIO:
case ENODEV:
case EPIPE:
zfs_verror(hdl, EZFS_IO, fmt, ap);
break;
@ -1324,7 +1326,8 @@ addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
* dataset property,
*/
if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL ||
(!zfs_prop_user(propname) && !zfs_prop_userquota(propname)))) {
(!zfs_prop_user(propname) && !zfs_prop_userquota(propname) &&
!zfs_prop_written(propname)))) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"invalid property '%s'"), propname);
return (zfs_error(hdl, EZFS_BADPROP,

View File

@ -228,7 +228,7 @@ usage(void)
"\n"
" Note: if -L labelenv is specified and labelenv is not set in\n"
" the environment, a default value is used.\n",
progname, progname, strlen(progname), " ",
progname, progname, (int)strlen(progname), " ",
progname, progname);
}

View File

@ -18,4 +18,4 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris \
-I${OPENSOLARIS_SYS_DISTDIR}/uts/common \
-DPIC ${PICFLAG}
.include <bsd.prog.mk>
.include <bsd.lib.mk>

View File

@ -20,8 +20,8 @@ SRCS+= libzfs_changelist.c \
libzfs_config.c \
libzfs_dataset.c \
libzfs_diff.c \
libzfs_graph.c \
libzfs_import.c \
libzfs_iter.c \
libzfs_mount.c \
libzfs_pool.c \
libzfs_sendrecv.c \

View File

@ -941,7 +941,7 @@ handle_rtmsg(struct rt_msghdr *rtm)
{
struct sockaddr *addrs[RTAX_MAX];
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct ifa_msghdr ifam;
struct ifma_msghdr *ifmam;
#ifdef RTM_IFANNOUNCE
struct if_announcemsghdr *ifan;
@ -961,17 +961,17 @@ handle_rtmsg(struct rt_msghdr *rtm)
switch (rtm->rtm_type) {
case RTM_NEWADDR:
ifam = (struct ifa_msghdr *)rtm;
mib_extract_addrs(ifam->ifam_addrs, (u_char *)(ifam + 1), addrs);
memcpy(&ifam, rtm, sizeof(ifam));
mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs);
if (addrs[RTAX_IFA] == NULL || addrs[RTAX_NETMASK] == NULL)
break;
sa = (struct sockaddr_in *)(void *)addrs[RTAX_IFA];
if ((ifa = mib_find_ifa(sa->sin_addr)) == NULL) {
/* unknown address */
if ((ifp = mib_find_if_sys(ifam->ifam_index)) == NULL) {
if ((ifp = mib_find_if_sys(ifam.ifam_index)) == NULL) {
syslog(LOG_WARNING, "RTM_NEWADDR for unknown "
"interface %u", ifam->ifam_index);
"interface %u", ifam.ifam_index);
break;
}
if ((ifa = alloc_ifa(ifp->index, sa->sin_addr)) == NULL)
@ -988,8 +988,8 @@ handle_rtmsg(struct rt_msghdr *rtm)
break;
case RTM_DELADDR:
ifam = (struct ifa_msghdr *)rtm;
mib_extract_addrs(ifam->ifam_addrs, (u_char *)(ifam + 1), addrs);
memcpy(&ifam, rtm, sizeof(ifam));
mib_extract_addrs(ifam.ifam_addrs, (u_char *)(&ifam + 1), addrs);
if (addrs[RTAX_IFA] == NULL)
break;

View File

@ -40,6 +40,7 @@
#define snmpmod_h_
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>

View File

@ -37,7 +37,7 @@
*/
#ifdef __GNUC__
typedef unsigned long long int MaybeUInt64;
# define MaybeUInt64_FMT "%Lu"
# define MaybeUInt64_FMT "%llu"
#else
#ifdef _MSC_VER
typedef unsigned __int64 MaybeUInt64;

View File

@ -14,7 +14,7 @@ Full text of the relevant licenses is included below.
University of Illinois/NCSA
Open Source License
Copyright (c) 2009-2010 by the contributors listed in CREDITS.TXT
Copyright (c) 2009-2012 by the contributors listed in CREDITS.TXT
All rights reserved.
@ -55,7 +55,7 @@ SOFTWARE.
==============================================================================
Copyright (c) 2009-2010 by the contributors listed in CREDITS.TXT
Copyright (c) 2009-2012 by the contributors listed in CREDITS.TXT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -74,3 +74,25 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
==============================================================================
Copyrights and Licenses for Third Party Software Distributed with LLVM:
==============================================================================
The LLVM software contains code written by third parties. Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.
The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:
Program Directory
------- ---------
sysinfo lib/asan/sysinfo
mach_override lib/asan/mach_override

View File

@ -106,6 +106,15 @@ si_int __mulvsi3(si_int a, si_int b); // a * b
di_int __mulvdi3(di_int a, di_int b); // a * b
ti_int __mulvti3(ti_int a, ti_int b); // a * b
// Integral arithmetic which returns if overflow
si_int __mulosi4(si_int a, si_int b, int* overflow); // a * b, overflow set to one if result not in signed range
di_int __mulodi4(di_int a, di_int b, int* overflow); // a * b, overflow set to one if result not in signed range
ti_int __muloti4(ti_int a, ti_int b, int* overflow); // a * b, overflow set to
one if result not in signed range
// Integral comparison: a < b -> 0
// a == b -> 1
// a > b -> 2

View File

@ -1,23 +0,0 @@
/* ===------ abi.h - configuration header for compiler-rt -----------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file is a configuration header for compiler-rt.
* This file is not part of the interface of this library.
*
* ===----------------------------------------------------------------------===
*/
#if __ARM_EABI__
# define ARM_EABI_FNALIAS(aeabi_name, name) \
void __aeabi_##aeabi_name() __attribute__((alias("__" #name)));
# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
#else
# define ARM_EABI_FNALIAS(aeabi_name, name)
# define COMPILER_RT_ABI
#endif

View File

@ -11,10 +11,8 @@
*
*===----------------------------------------------------------------------===
*/
#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
/* Returns: absolute value */

View File

@ -11,10 +11,8 @@
*
* ===----------------------------------------------------------------------===
*/
#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
/* Returns: absolute value */

View File

@ -15,7 +15,6 @@
#if __x86_64
#include "int_lib.h"
#include <stdlib.h>
/* Returns: absolute value */

View File

@ -12,8 +12,6 @@
//
//===----------------------------------------------------------------------===//
#include "abi.h"
#define DOUBLE_PRECISION
#include "fp_lib.h"

View File

@ -12,8 +12,6 @@
//
//===----------------------------------------------------------------------===//
#include "abi.h"
#define SINGLE_PRECISION
#include "fp_lib.h"

View File

@ -11,10 +11,8 @@
*
* ===----------------------------------------------------------------------===
*/
#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
/* Returns: a + b */

View File

@ -11,10 +11,8 @@
*
* ===----------------------------------------------------------------------===
*/
#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
/* Returns: a + b */

View File

@ -15,7 +15,6 @@
#if __x86_64
#include "int_lib.h"
#include <stdlib.h>
/* Returns: a + b */

View File

@ -1,291 +0,0 @@
/* ===-- apple_versioning.c - Adds versioning symbols for ld ---------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*/
#if __APPLE__
#if __arm__
#define NOT_HERE_BEFORE_10_6(sym)
#elif __ppc__
#define NOT_HERE_BEFORE_10_6(sym) \
extern const char sym##_tmp3 __asm("$ld$hide$os10.3$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp3 = 0; \
extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp5 = 0;
#else
#define NOT_HERE_BEFORE_10_6(sym) \
extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp5 = 0;
#endif /* __ppc__ */
/* Symbols in libSystem.dylib in 10.6 and later,
* but are in libgcc_s.dylib in earlier versions
*/
NOT_HERE_BEFORE_10_6(__absvdi2)
NOT_HERE_BEFORE_10_6(__absvsi2)
NOT_HERE_BEFORE_10_6(__absvti2)
NOT_HERE_BEFORE_10_6(__addvdi3)
NOT_HERE_BEFORE_10_6(__addvsi3)
NOT_HERE_BEFORE_10_6(__addvti3)
NOT_HERE_BEFORE_10_6(__ashldi3)
NOT_HERE_BEFORE_10_6(__ashlti3)
NOT_HERE_BEFORE_10_6(__ashrdi3)
NOT_HERE_BEFORE_10_6(__ashrti3)
NOT_HERE_BEFORE_10_6(__clear_cache)
NOT_HERE_BEFORE_10_6(__clzdi2)
NOT_HERE_BEFORE_10_6(__clzsi2)
NOT_HERE_BEFORE_10_6(__clzti2)
NOT_HERE_BEFORE_10_6(__cmpdi2)
NOT_HERE_BEFORE_10_6(__cmpti2)
NOT_HERE_BEFORE_10_6(__ctzdi2)
NOT_HERE_BEFORE_10_6(__ctzsi2)
NOT_HERE_BEFORE_10_6(__ctzti2)
NOT_HERE_BEFORE_10_6(__divdc3)
NOT_HERE_BEFORE_10_6(__divdi3)
NOT_HERE_BEFORE_10_6(__divsc3)
NOT_HERE_BEFORE_10_6(__divtc3)
NOT_HERE_BEFORE_10_6(__divti3)
NOT_HERE_BEFORE_10_6(__divxc3)
NOT_HERE_BEFORE_10_6(__enable_execute_stack)
NOT_HERE_BEFORE_10_6(__ffsdi2)
NOT_HERE_BEFORE_10_6(__ffsti2)
NOT_HERE_BEFORE_10_6(__fixdfdi)
NOT_HERE_BEFORE_10_6(__fixdfti)
NOT_HERE_BEFORE_10_6(__fixsfdi)
NOT_HERE_BEFORE_10_6(__fixsfti)
NOT_HERE_BEFORE_10_6(__fixtfdi)
NOT_HERE_BEFORE_10_6(__fixunsdfdi)
NOT_HERE_BEFORE_10_6(__fixunsdfsi)
NOT_HERE_BEFORE_10_6(__fixunsdfti)
NOT_HERE_BEFORE_10_6(__fixunssfdi)
NOT_HERE_BEFORE_10_6(__fixunssfsi)
NOT_HERE_BEFORE_10_6(__fixunssfti)
NOT_HERE_BEFORE_10_6(__fixunstfdi)
NOT_HERE_BEFORE_10_6(__fixunsxfdi)
NOT_HERE_BEFORE_10_6(__fixunsxfsi)
NOT_HERE_BEFORE_10_6(__fixunsxfti)
NOT_HERE_BEFORE_10_6(__fixxfdi)
NOT_HERE_BEFORE_10_6(__fixxfti)
NOT_HERE_BEFORE_10_6(__floatdidf)
NOT_HERE_BEFORE_10_6(__floatdisf)
NOT_HERE_BEFORE_10_6(__floatditf)
NOT_HERE_BEFORE_10_6(__floatdixf)
NOT_HERE_BEFORE_10_6(__floattidf)
NOT_HERE_BEFORE_10_6(__floattisf)
NOT_HERE_BEFORE_10_6(__floattixf)
NOT_HERE_BEFORE_10_6(__floatundidf)
NOT_HERE_BEFORE_10_6(__floatundisf)
NOT_HERE_BEFORE_10_6(__floatunditf)
NOT_HERE_BEFORE_10_6(__floatundixf)
NOT_HERE_BEFORE_10_6(__floatuntidf)
NOT_HERE_BEFORE_10_6(__floatuntisf)
NOT_HERE_BEFORE_10_6(__floatuntixf)
NOT_HERE_BEFORE_10_6(__gcc_personality_v0)
NOT_HERE_BEFORE_10_6(__lshrdi3)
NOT_HERE_BEFORE_10_6(__lshrti3)
NOT_HERE_BEFORE_10_6(__moddi3)
NOT_HERE_BEFORE_10_6(__modti3)
NOT_HERE_BEFORE_10_6(__muldc3)
NOT_HERE_BEFORE_10_6(__muldi3)
NOT_HERE_BEFORE_10_6(__mulsc3)
NOT_HERE_BEFORE_10_6(__multc3)
NOT_HERE_BEFORE_10_6(__multi3)
NOT_HERE_BEFORE_10_6(__mulvdi3)
NOT_HERE_BEFORE_10_6(__mulvsi3)
NOT_HERE_BEFORE_10_6(__mulvti3)
NOT_HERE_BEFORE_10_6(__mulxc3)
NOT_HERE_BEFORE_10_6(__negdi2)
NOT_HERE_BEFORE_10_6(__negti2)
NOT_HERE_BEFORE_10_6(__negvdi2)
NOT_HERE_BEFORE_10_6(__negvsi2)
NOT_HERE_BEFORE_10_6(__negvti2)
NOT_HERE_BEFORE_10_6(__paritydi2)
NOT_HERE_BEFORE_10_6(__paritysi2)
NOT_HERE_BEFORE_10_6(__parityti2)
NOT_HERE_BEFORE_10_6(__popcountdi2)
NOT_HERE_BEFORE_10_6(__popcountsi2)
NOT_HERE_BEFORE_10_6(__popcountti2)
NOT_HERE_BEFORE_10_6(__powidf2)
NOT_HERE_BEFORE_10_6(__powisf2)
NOT_HERE_BEFORE_10_6(__powitf2)
NOT_HERE_BEFORE_10_6(__powixf2)
NOT_HERE_BEFORE_10_6(__subvdi3)
NOT_HERE_BEFORE_10_6(__subvsi3)
NOT_HERE_BEFORE_10_6(__subvti3)
NOT_HERE_BEFORE_10_6(__ucmpdi2)
NOT_HERE_BEFORE_10_6(__ucmpti2)
NOT_HERE_BEFORE_10_6(__udivdi3)
NOT_HERE_BEFORE_10_6(__udivmoddi4)
NOT_HERE_BEFORE_10_6(__udivmodti4)
NOT_HERE_BEFORE_10_6(__udivti3)
NOT_HERE_BEFORE_10_6(__umoddi3)
NOT_HERE_BEFORE_10_6(__umodti3)
#if __ppc__
NOT_HERE_BEFORE_10_6(__gcc_qadd)
NOT_HERE_BEFORE_10_6(__gcc_qdiv)
NOT_HERE_BEFORE_10_6(__gcc_qmul)
NOT_HERE_BEFORE_10_6(__gcc_qsub)
NOT_HERE_BEFORE_10_6(__trampoline_setup)
#endif /* __ppc__ */
#if __arm__ && __DYNAMIC__
#define NOT_HERE_UNTIL_AFTER_4_3(sym) \
extern const char sym##_tmp1 __asm("$ld$hide$os3.0$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp1 = 0; \
extern const char sym##_tmp2 __asm("$ld$hide$os3.1$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp2 = 0; \
extern const char sym##_tmp3 __asm("$ld$hide$os3.2$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp3 = 0; \
extern const char sym##_tmp4 __asm("$ld$hide$os4.0$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
extern const char sym##_tmp5 __asm("$ld$hide$os4.1$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
extern const char sym##_tmp6 __asm("$ld$hide$os4.2$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp6 = 0; \
extern const char sym##_tmp7 __asm("$ld$hide$os4.3$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp7 = 0;
NOT_HERE_UNTIL_AFTER_4_3(__absvdi2)
NOT_HERE_UNTIL_AFTER_4_3(__absvsi2)
NOT_HERE_UNTIL_AFTER_4_3(__adddf3)
NOT_HERE_UNTIL_AFTER_4_3(__adddf3vfp)
NOT_HERE_UNTIL_AFTER_4_3(__addsf3)
NOT_HERE_UNTIL_AFTER_4_3(__addsf3vfp)
NOT_HERE_UNTIL_AFTER_4_3(__addvdi3)
NOT_HERE_UNTIL_AFTER_4_3(__addvsi3)
NOT_HERE_UNTIL_AFTER_4_3(__ashldi3)
NOT_HERE_UNTIL_AFTER_4_3(__ashrdi3)
NOT_HERE_UNTIL_AFTER_4_3(__bswapdi2)
NOT_HERE_UNTIL_AFTER_4_3(__bswapsi2)
NOT_HERE_UNTIL_AFTER_4_3(__clzdi2)
NOT_HERE_UNTIL_AFTER_4_3(__clzsi2)
NOT_HERE_UNTIL_AFTER_4_3(__cmpdi2)
NOT_HERE_UNTIL_AFTER_4_3(__ctzdi2)
NOT_HERE_UNTIL_AFTER_4_3(__ctzsi2)
NOT_HERE_UNTIL_AFTER_4_3(__divdc3)
NOT_HERE_UNTIL_AFTER_4_3(__divdf3)
NOT_HERE_UNTIL_AFTER_4_3(__divdf3vfp)
NOT_HERE_UNTIL_AFTER_4_3(__divdi3)
NOT_HERE_UNTIL_AFTER_4_3(__divsc3)
NOT_HERE_UNTIL_AFTER_4_3(__divsf3)
NOT_HERE_UNTIL_AFTER_4_3(__divsf3vfp)
NOT_HERE_UNTIL_AFTER_4_3(__divsi3)
NOT_HERE_UNTIL_AFTER_4_3(__eqdf2)
NOT_HERE_UNTIL_AFTER_4_3(__eqdf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__eqsf2)
NOT_HERE_UNTIL_AFTER_4_3(__eqsf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__extendsfdf2)
NOT_HERE_UNTIL_AFTER_4_3(__extendsfdf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__ffsdi2)
NOT_HERE_UNTIL_AFTER_4_3(__fixdfdi)
NOT_HERE_UNTIL_AFTER_4_3(__fixdfsi)
NOT_HERE_UNTIL_AFTER_4_3(__fixdfsivfp)
NOT_HERE_UNTIL_AFTER_4_3(__fixsfdi)
NOT_HERE_UNTIL_AFTER_4_3(__fixsfsi)
NOT_HERE_UNTIL_AFTER_4_3(__fixsfsivfp)
NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfdi)
NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfsi)
NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfsivfp)
NOT_HERE_UNTIL_AFTER_4_3(__fixunssfdi)
NOT_HERE_UNTIL_AFTER_4_3(__fixunssfsi)
NOT_HERE_UNTIL_AFTER_4_3(__fixunssfsivfp)
NOT_HERE_UNTIL_AFTER_4_3(__floatdidf)
NOT_HERE_UNTIL_AFTER_4_3(__floatdisf)
NOT_HERE_UNTIL_AFTER_4_3(__floatsidf)
NOT_HERE_UNTIL_AFTER_4_3(__floatsidfvfp)
NOT_HERE_UNTIL_AFTER_4_3(__floatsisf)
NOT_HERE_UNTIL_AFTER_4_3(__floatsisfvfp)
NOT_HERE_UNTIL_AFTER_4_3(__floatundidf)
NOT_HERE_UNTIL_AFTER_4_3(__floatundisf)
NOT_HERE_UNTIL_AFTER_4_3(__floatunsidf)
NOT_HERE_UNTIL_AFTER_4_3(__floatunsisf)
NOT_HERE_UNTIL_AFTER_4_3(__floatunssidfvfp)
NOT_HERE_UNTIL_AFTER_4_3(__floatunssisfvfp)
NOT_HERE_UNTIL_AFTER_4_3(__gedf2)
NOT_HERE_UNTIL_AFTER_4_3(__gedf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__gesf2)
NOT_HERE_UNTIL_AFTER_4_3(__gesf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__gtdf2)
NOT_HERE_UNTIL_AFTER_4_3(__gtdf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__gtsf2)
NOT_HERE_UNTIL_AFTER_4_3(__gtsf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__ledf2)
NOT_HERE_UNTIL_AFTER_4_3(__ledf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__lesf2)
NOT_HERE_UNTIL_AFTER_4_3(__lesf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__lshrdi3)
NOT_HERE_UNTIL_AFTER_4_3(__ltdf2)
NOT_HERE_UNTIL_AFTER_4_3(__ltdf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__ltsf2)
NOT_HERE_UNTIL_AFTER_4_3(__ltsf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__moddi3)
NOT_HERE_UNTIL_AFTER_4_3(__modsi3)
NOT_HERE_UNTIL_AFTER_4_3(__muldc3)
NOT_HERE_UNTIL_AFTER_4_3(__muldf3)
NOT_HERE_UNTIL_AFTER_4_3(__muldf3vfp)
NOT_HERE_UNTIL_AFTER_4_3(__muldi3)
NOT_HERE_UNTIL_AFTER_4_3(__mulsc3)
NOT_HERE_UNTIL_AFTER_4_3(__mulsf3)
NOT_HERE_UNTIL_AFTER_4_3(__mulsf3vfp)
NOT_HERE_UNTIL_AFTER_4_3(__mulvdi3)
NOT_HERE_UNTIL_AFTER_4_3(__mulvsi3)
NOT_HERE_UNTIL_AFTER_4_3(__nedf2)
NOT_HERE_UNTIL_AFTER_4_3(__nedf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__negdi2)
NOT_HERE_UNTIL_AFTER_4_3(__negvdi2)
NOT_HERE_UNTIL_AFTER_4_3(__negvsi2)
NOT_HERE_UNTIL_AFTER_4_3(__nesf2)
NOT_HERE_UNTIL_AFTER_4_3(__nesf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__paritydi2)
NOT_HERE_UNTIL_AFTER_4_3(__paritysi2)
NOT_HERE_UNTIL_AFTER_4_3(__popcountdi2)
NOT_HERE_UNTIL_AFTER_4_3(__popcountsi2)
NOT_HERE_UNTIL_AFTER_4_3(__powidf2)
NOT_HERE_UNTIL_AFTER_4_3(__powisf2)
NOT_HERE_UNTIL_AFTER_4_3(__subdf3)
NOT_HERE_UNTIL_AFTER_4_3(__subdf3vfp)
NOT_HERE_UNTIL_AFTER_4_3(__subsf3)
NOT_HERE_UNTIL_AFTER_4_3(__subsf3vfp)
NOT_HERE_UNTIL_AFTER_4_3(__subvdi3)
NOT_HERE_UNTIL_AFTER_4_3(__subvsi3)
NOT_HERE_UNTIL_AFTER_4_3(__truncdfsf2)
NOT_HERE_UNTIL_AFTER_4_3(__truncdfsf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__ucmpdi2)
NOT_HERE_UNTIL_AFTER_4_3(__udivdi3)
NOT_HERE_UNTIL_AFTER_4_3(__udivmoddi4)
NOT_HERE_UNTIL_AFTER_4_3(__udivsi3)
NOT_HERE_UNTIL_AFTER_4_3(__umoddi3)
NOT_HERE_UNTIL_AFTER_4_3(__umodsi3)
NOT_HERE_UNTIL_AFTER_4_3(__unorddf2)
NOT_HERE_UNTIL_AFTER_4_3(__unorddf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__unordsf2)
NOT_HERE_UNTIL_AFTER_4_3(__unordsf2vfp)
NOT_HERE_UNTIL_AFTER_4_3(__divmodsi4)
NOT_HERE_UNTIL_AFTER_4_3(__udivmodsi4)
#endif // __arm__ && __DYNAMIC__
#else /* !__APPLE__ */
extern int avoid_empty_file;
#endif /* !__APPLE__*/

View File

@ -15,10 +15,11 @@
// Adds two double precision floating point numbers using the Darwin
// calling convention where double arguments are passsed in GPR pairs
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__adddf3vfp)
fmdrr d6, r0, r1 // move first param from r0/r1 pair into d6
fmdrr d7, r2, r3 // move second param from r2/r3 pair into d7
faddd d6, d6, d7
fmrrd r0, r1, d6 // move result back to r0/r1 pair
vmov d6, r0, r1 // move first param from r0/r1 pair into d6
vmov d7, r2, r3 // move second param from r2/r3 pair into d7
vadd.f64 d6, d6, d7
vmov r0, r1, d6 // move result back to r0/r1 pair
bx lr

View File

@ -15,10 +15,11 @@
// Adds two single precision floating point numbers using the Darwin
// calling convention where single arguments are passsed in GPRs
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__addsf3vfp)
fmsr s14, r0 // move first param from r0 into float register
fmsr s15, r1 // move second param from r1 into float register
fadds s14, s14, s15
fmrs r0, s14 // move result back to r0
vmov s14, r0 // move first param from r0 into float register
vmov s15, r1 // move second param from r1 into float register
vadd.f32 s14, s14, s15
vmov r0, s14 // move result back to r0
bx lr

View File

@ -15,10 +15,11 @@
// Divides two double precision floating point numbers using the Darwin
// calling convention where double arguments are passsed in GPR pairs
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__divdf3vfp)
fmdrr d6, r0, r1 // move first param from r0/r1 pair into d6
fmdrr d7, r2, r3 // move second param from r2/r3 pair into d7
fdivd d5, d6, d7
fmrrd r0, r1, d5 // move result back to r0/r1 pair
vmov d6, r0, r1 // move first param from r0/r1 pair into d6
vmov d7, r2, r3 // move second param from r2/r3 pair into d7
vdiv.f64 d5, d6, d7
vmov r0, r1, d5 // move result back to r0/r1 pair
bx lr

View File

@ -15,10 +15,11 @@
// Divides two single precision floating point numbers using the Darwin
// calling convention where single arguments are passsed like 32-bit ints.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__divsf3vfp)
fmsr s14, r0 // move first param from r0 into float register
fmsr s15, r1 // move second param from r1 into float register
fdivs s13, s14, s15
fmrs r0, s13 // move result back to r0
vmov s14, r0 // move first param from r0 into float register
vmov s15, r1 // move second param from r1 into float register
vdiv.f32 s13, s14, s15
vmov r0, s13 // move result back to r0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where double precision arguments are passsed
// like in GPR pairs.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__eqdf2vfp)
fmdrr d6, r0, r1 // load r0/r1 pair in double register
fmdrr d7, r2, r3 // load r2/r3 pair in double register
fcmpd d6, d7
fmstat
vmov d6, r0, r1 // load r0/r1 pair in double register
vmov d7, r2, r3 // load r2/r3 pair in double register
vcmp.f64 d6, d7
vmrs apsr_nzcv, fpscr
moveq r0, #1 // set result register to 1 if equal
movne r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where single precision arguments are passsed
// like 32-bit ints
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__eqsf2vfp)
fmsr s14, r0 // move from GPR 0 to float register
fmsr s15, r1 // move from GPR 1 to float register
fcmps s14, s15
fmstat
vmov s14, r0 // move from GPR 0 to float register
vmov s15, r1 // move from GPR 1 to float register
vcmp.f32 s14, s15
vmrs apsr_nzcv, fpscr
moveq r0, #1 // set result register to 1 if equal
movne r0, #0
bx lr

View File

@ -16,9 +16,10 @@
// Uses Darwin calling convention where a single precision parameter is
// passed in a GPR and a double precision result is returned in R0/R1 pair.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__extendsfdf2vfp)
fmsr s15, r0 // load float register from R0
fcvtds d7, s15 // convert single to double
fmrrd r0, r1, d7 // return result in r0/r1 pair
vmov s15, r0 // load float register from R0
vcvt.f64.f32 d7, s15 // convert single to double
vmov r0, r1, d7 // return result in r0/r1 pair
bx lr

View File

@ -16,9 +16,10 @@
// Uses Darwin calling convention where a double precision parameter is
// passed in GPR register pair.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__fixdfsivfp)
fmdrr d7, r0, r1 // load double register from R0/R1
ftosizd s15, d7 // convert double to 32-bit int into s15
fmrs r0, s15 // move s15 to result register
vmov d7, r0, r1 // load double register from R0/R1
vcvt.s32.f64 s15, d7 // convert double to 32-bit int into s15
vmov r0, s15 // move s15 to result register
bx lr

View File

@ -16,9 +16,10 @@
// Uses Darwin calling convention where a single precision parameter is
// passed in a GPR..
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__fixsfsivfp)
fmsr s15, r0 // load float register from R0
ftosizs s15, s15 // convert single to 32-bit int into s15
fmrs r0, s15 // move s15 to result register
vmov s15, r0 // load float register from R0
vcvt.s32.f32 s15, s15 // convert single to 32-bit int into s15
vmov r0, s15 // move s15 to result register
bx lr

View File

@ -17,9 +17,10 @@
// Uses Darwin calling convention where a double precision parameter is
// passed in GPR register pair.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__fixunsdfsivfp)
fmdrr d7, r0, r1 // load double register from R0/R1
ftouizd s15, d7 // convert double to 32-bit int into s15
fmrs r0, s15 // move s15 to result register
vmov d7, r0, r1 // load double register from R0/R1
vcvt.u32.f64 s15, d7 // convert double to 32-bit int into s15
vmov r0, s15 // move s15 to result register
bx lr

View File

@ -17,9 +17,10 @@
// Uses Darwin calling convention where a single precision parameter is
// passed in a GPR..
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__fixunssfsivfp)
fmsr s15, r0 // load float register from R0
ftouizs s15, s15 // convert single to 32-bit unsigned into s15
fmrs r0, s15 // move s15 to result register
vmov s15, r0 // load float register from R0
vcvt.u32.f32 s15, s15 // convert single to 32-bit unsigned into s15
vmov r0, s15 // move s15 to result register
bx lr

View File

@ -16,9 +16,10 @@
// Uses Darwin calling convention where a double precision result is
// return in GPR register pair.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__floatsidfvfp)
fmsr s15, r0 // move int to float register s15
fsitod d7, s15 // convert 32-bit int in s15 to double in d7
fmrrd r0, r1, d7 // move d7 to result register pair r0/r1
vmov s15, r0 // move int to float register s15
vcvt.f64.s32 d7, s15 // convert 32-bit int in s15 to double in d7
vmov r0, r1, d7 // move d7 to result register pair r0/r1
bx lr

View File

@ -16,9 +16,10 @@
// Uses Darwin calling convention where a single precision result is
// return in a GPR..
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__floatsisfvfp)
fmsr s15, r0 // move int to float register s15
fsitos s15, s15 // convert 32-bit int in s15 to float in s15
fmrs r0, s15 // move s15 to result register
vmov s15, r0 // move int to float register s15
vcvt.f32.s32 s15, s15 // convert 32-bit int in s15 to float in s15
vmov r0, s15 // move s15 to result register
bx lr

View File

@ -16,9 +16,10 @@
// Uses Darwin calling convention where a double precision result is
// return in GPR register pair.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__floatunssidfvfp)
fmsr s15, r0 // move int to float register s15
fuitod d7, s15 // convert 32-bit int in s15 to double in d7
fmrrd r0, r1, d7 // move d7 to result register pair r0/r1
vmov s15, r0 // move int to float register s15
vcvt.f64.u32 d7, s15 // convert 32-bit int in s15 to double in d7
vmov r0, r1, d7 // move d7 to result register pair r0/r1
bx lr

View File

@ -16,9 +16,10 @@
// Uses Darwin calling convention where a single precision result is
// return in a GPR..
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__floatunssisfvfp)
fmsr s15, r0 // move int to float register s15
fuitos s15, s15 // convert 32-bit int in s15 to float in s15
fmrs r0, s15 // move s15 to result register
vmov s15, r0 // move int to float register s15
vcvt.f32.u32 s15, s15 // convert 32-bit int in s15 to float in s15
vmov r0, s15 // move s15 to result register
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where double precision arguments are passsed
// like in GPR pairs.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__gedf2vfp)
fmdrr d6, r0, r1 // load r0/r1 pair in double register
fmdrr d7, r2, r3 // load r2/r3 pair in double register
fcmpd d6, d7
fmstat
vmov d6, r0, r1 // load r0/r1 pair in double register
vmov d7, r2, r3 // load r2/r3 pair in double register
vcmp.f64 d6, d7
vmrs apsr_nzcv, fpscr
movge r0, #1 // set result register to 1 if greater than or equal
movlt r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where single precision arguments are passsed
// like 32-bit ints
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__gesf2vfp)
fmsr s14, r0 // move from GPR 0 to float register
fmsr s15, r1 // move from GPR 1 to float register
fcmps s14, s15
fmstat
vmov s14, r0 // move from GPR 0 to float register
vmov s15, r1 // move from GPR 1 to float register
vcmp.f32 s14, s15
vmrs apsr_nzcv, fpscr
movge r0, #1 // set result register to 1 if greater than or equal
movlt r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where double precision arguments are passsed
// like in GPR pairs.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__gtdf2vfp)
fmdrr d6, r0, r1 // load r0/r1 pair in double register
fmdrr d7, r2, r3 // load r2/r3 pair in double register
fcmpd d6, d7
fmstat
vmov d6, r0, r1 // load r0/r1 pair in double register
vmov d7, r2, r3 // load r2/r3 pair in double register
vcmp.f64 d6, d7
vmrs apsr_nzcv, fpscr
movgt r0, #1 // set result register to 1 if equal
movle r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where single precision arguments are passsed
// like 32-bit ints
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__gtsf2vfp)
fmsr s14, r0 // move from GPR 0 to float register
fmsr s15, r1 // move from GPR 1 to float register
fcmps s14, s15
fmstat
vmov s14, r0 // move from GPR 0 to float register
vmov s15, r1 // move from GPR 1 to float register
vcmp.f32 s14, s15
vmrs apsr_nzcv, fpscr
movgt r0, #1 // set result register to 1 if equal
movle r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where double precision arguments are passsed
// like in GPR pairs.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__ledf2vfp)
fmdrr d6, r0, r1 // load r0/r1 pair in double register
fmdrr d7, r2, r3 // load r2/r3 pair in double register
fcmpd d6, d7
fmstat
vmov d6, r0, r1 // load r0/r1 pair in double register
vmov d7, r2, r3 // load r2/r3 pair in double register
vcmp.f64 d6, d7
vmrs apsr_nzcv, fpscr
movls r0, #1 // set result register to 1 if equal
movhi r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where single precision arguments are passsed
// like 32-bit ints
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__lesf2vfp)
fmsr s14, r0 // move from GPR 0 to float register
fmsr s15, r1 // move from GPR 1 to float register
fcmps s14, s15
fmstat
vmov s14, r0 // move from GPR 0 to float register
vmov s15, r1 // move from GPR 1 to float register
vcmp.f32 s14, s15
vmrs apsr_nzcv, fpscr
movls r0, #1 // set result register to 1 if equal
movhi r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where double precision arguments are passsed
// like in GPR pairs.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__ltdf2vfp)
fmdrr d6, r0, r1 // load r0/r1 pair in double register
fmdrr d7, r2, r3 // load r2/r3 pair in double register
fcmpd d6, d7
fmstat
vmov d6, r0, r1 // load r0/r1 pair in double register
vmov d7, r2, r3 // load r2/r3 pair in double register
vcmp.f64 d6, d7
vmrs apsr_nzcv, fpscr
movmi r0, #1 // set result register to 1 if equal
movpl r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where single precision arguments are passsed
// like 32-bit ints
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__ltsf2vfp)
fmsr s14, r0 // move from GPR 0 to float register
fmsr s15, r1 // move from GPR 1 to float register
fcmps s14, s15
fmstat
vmov s14, r0 // move from GPR 0 to float register
vmov s15, r1 // move from GPR 1 to float register
vcmp.f32 s14, s15
vmrs apsr_nzcv, fpscr
movmi r0, #1 // set result register to 1 if equal
movpl r0, #0
bx lr

View File

@ -15,10 +15,11 @@
// Multiplies two double precision floating point numbers using the Darwin
// calling convention where double arguments are passsed in GPR pairs
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__muldf3vfp)
fmdrr d6, r0, r1 // move first param from r0/r1 pair into d6
fmdrr d7, r2, r3 // move second param from r2/r3 pair into d7
fmuld d6, d6, d7
fmrrd r0, r1, d6 // move result back to r0/r1 pair
vmov d6, r0, r1 // move first param from r0/r1 pair into d6
vmov d7, r2, r3 // move second param from r2/r3 pair into d7
vmul.f64 d6, d6, d7
vmov r0, r1, d6 // move result back to r0/r1 pair
bx lr

View File

@ -15,10 +15,11 @@
// Multiplies two single precision floating point numbers using the Darwin
// calling convention where single arguments are passsed like 32-bit ints.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__mulsf3vfp)
fmsr s14, r0 // move first param from r0 into float register
fmsr s15, r1 // move second param from r1 into float register
fmuls s13, s14, s15
fmrs r0, s13 // move result back to r0
vmov s14, r0 // move first param from r0 into float register
vmov s15, r1 // move second param from r1 into float register
vmul.f32 s13, s14, s15
vmov r0, s13 // move result back to r0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where double precision arguments are passsed
// like in GPR pairs.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__nedf2vfp)
fmdrr d6, r0, r1 // load r0/r1 pair in double register
fmdrr d7, r2, r3 // load r2/r3 pair in double register
fcmpd d6, d7
fmstat
vmov d6, r0, r1 // load r0/r1 pair in double register
vmov d7, r2, r3 // load r2/r3 pair in double register
vcmp.f64 d6, d7
vmrs apsr_nzcv, fpscr
movne r0, #1 // set result register to 0 if unequal
moveq r0, #0
bx lr

View File

@ -15,6 +15,7 @@
// Returns the negation a double precision floating point numbers using the
// Darwin calling convention where double arguments are passsed in GPR pairs.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__negdf2vfp)
eor r1, r1, #-2147483648 // flip sign bit on double in r0/r1 pair

View File

@ -15,6 +15,7 @@
// Returns the negation of a single precision floating point numbers using the
// Darwin calling convention where single arguments are passsed like 32-bit ints
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__negsf2vfp)
eor r0, r0, #-2147483648 // flip sign bit on float in r0

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where single precision arguments are passsed
// like 32-bit ints
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__nesf2vfp)
fmsr s14, r0 // move from GPR 0 to float register
fmsr s15, r1 // move from GPR 1 to float register
fcmps s14, s15
fmstat
vmov s14, r0 // move from GPR 0 to float register
vmov s15, r1 // move from GPR 1 to float register
vcmp.f32 s14, s15
vmrs apsr_nzcv, fpscr
movne r0, #1 // set result register to 1 if unequal
moveq r0, #0
bx lr

View File

@ -15,10 +15,11 @@
// Returns difference between two double precision floating point numbers using
// the Darwin calling convention where double arguments are passsed in GPR pairs
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__subdf3vfp)
fmdrr d6, r0, r1 // move first param from r0/r1 pair into d6
fmdrr d7, r2, r3 // move second param from r2/r3 pair into d7
fsubd d6, d6, d7
fmrrd r0, r1, d6 // move result back to r0/r1 pair
vmov d6, r0, r1 // move first param from r0/r1 pair into d6
vmov d7, r2, r3 // move second param from r2/r3 pair into d7
vsub.f64 d6, d6, d7
vmov r0, r1, d6 // move result back to r0/r1 pair
bx lr

View File

@ -16,10 +16,11 @@
// using the Darwin calling convention where single arguments are passsed
// like 32-bit ints.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__subsf3vfp)
fmsr s14, r0 // move first param from r0 into float register
fmsr s15, r1 // move second param from r1 into float register
fsubs s14, s14, s15
fmrs r0, s14 // move result back to r0
vmov s14, r0 // move first param from r0 into float register
vmov s15, r1 // move second param from r1 into float register
vsub.f32 s14, s14, s15
vmov r0, s14 // move result back to r0
bx lr

View File

@ -16,9 +16,10 @@
// Uses Darwin calling convention where a double precision parameter is
// passed in a R0/R1 pair and a signle precision result is returned in R0.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__truncdfsf2vfp)
fmdrr d7, r0, r1 // load double from r0/r1 pair
fcvtsd s15, d7 // convert double to single (trucate precision)
fmrs r0, s15 // return result in r0
vmov d7, r0, r1 // load double from r0/r1 pair
vcvt.f32.f64 s15, d7 // convert double to single (trucate precision)
vmov r0, s15 // return result in r0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where double precision arguments are passsed
// like in GPR pairs.
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__unorddf2vfp)
fmdrr d6, r0, r1 // load r0/r1 pair in double register
fmdrr d7, r2, r3 // load r2/r3 pair in double register
fcmpd d6, d7
fmstat
vmov d6, r0, r1 // load r0/r1 pair in double register
vmov d7, r2, r3 // load r2/r3 pair in double register
vcmp.f64 d6, d7
vmrs apsr_nzcv, fpscr
movvs r0, #1 // set result register to 1 if "overflow" (any NaNs)
movvc r0, #0
bx lr

View File

@ -16,12 +16,13 @@
// Uses Darwin calling convention where single precision arguments are passsed
// like 32-bit ints
//
.syntax unified
.align 2
DEFINE_COMPILERRT_FUNCTION(__unordsf2vfp)
fmsr s14, r0 // move from GPR 0 to float register
fmsr s15, r1 // move from GPR 1 to float register
fcmps s14, s15
fmstat
vmov s14, r0 // move from GPR 0 to float register
vmov s15, r1 // move from GPR 1 to float register
vcmp.f32 s14, s15
vmrs apsr_nzcv, fpscr
movvs r0, #1 // set result register to 1 if "overflow" (any NaNs)
movvc r0, #0
bx lr

Some files were not shown because too many files have changed in this diff Show More