diff --git a/Makefile.inc1 b/Makefile.inc1 index c07cd5167cea..9b036f43106e 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -113,6 +113,8 @@ _REDUNDENT_LIB_DIRS+= ${LOCAL_LIB_DIRS:M${_DIR}*} .for _DIR in ${LOCAL_LIB_DIRS} .if empty(_REDUNDENT_LIB_DIRS:M${_DIR}) && exists(${.CURDIR}/${_DIR}/Makefile) SUBDIR+= ${_DIR} +.else +.warning ${_DIR} not added to SUBDIR list. See UPDATING 20141121. .endif .endfor .endif @@ -261,7 +263,8 @@ BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \ MK_HTML=no MK_INFO=no NO_LINT=yes MK_MAN=no \ -DNO_PIC MK_PROFILE=no -DNO_SHARED \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ - MK_CLANG_FULL=no MK_LLDB=no MK_TESTS=no + MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ + MK_LLDB=no MK_TESTS=no # build-tools stage TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \ @@ -271,7 +274,9 @@ TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \ BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ -DNO_LINT \ - -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no MK_CLANG_FULL=no MK_LLDB=no MK_TESTS=no + -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ + MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ + MK_LLDB=no MK_TESTS=no # cross-tools stage XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \ @@ -524,8 +529,9 @@ _worldtmp: -p ${WORLDTMP}/usr/lib >/dev/null .endif .if ${MK_TESTS} != "no" + mkdir -p ${WORLDTMP}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ - -p ${WORLDTMP}/usr >/dev/null + -p ${WORLDTMP}${TESTSBASE} >/dev/null .endif .for _mtree in ${LOCAL_MTREE} mtree -deU -f ${.CURDIR}/${_mtree} -p ${WORLDTMP} > /dev/null @@ -788,7 +794,7 @@ _zoneinfo= zic tzsetup ITOOLS= [ awk cap_mkdb cat chflags chmod chown \ date echo egrep find grep id install ${_install-info} \ ln lockf make mkdir mtree mv pwd_mkdb \ - rm sed services_mkdb sh sysctl test true uname wc ${_zoneinfo} \ + rm sed services_mkdb sh strip sysctl test true uname wc ${_zoneinfo} \ ${LOCAL_ITOOLS} # Needed for share/man @@ -864,8 +870,9 @@ distributeworld installworld: _installcheck_world -p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib >/dev/null .endif .if ${MK_TESTS} != "no" && ${dist} == "tests" + -mkdir -p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ - -p ${DESTDIR}/${DISTDIR}/${dist}/usr >/dev/null + -p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE} >/dev/null .endif .if defined(NO_ROOT) ${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.root.dist | \ @@ -1474,7 +1481,8 @@ NXBMAKE= ${NXBENV} ${MAKE} \ MK_HTML=no MK_INFO=no NO_LINT=yes MK_MAN=no \ -DNO_PIC MK_PROFILE=no -DNO_SHARED \ -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \ - MK_CLANG_FULL=no MK_LLDB=no + MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \ + MK_LLDB=no native-xtools: .MAKE mkdir -p ${OBJTREE}/nxb-bin/bin @@ -2083,8 +2091,9 @@ _xi-mtree: mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \ -p ${XDDESTDIR}/usr/include >/dev/null .if ${MK_TESTS} != "no" + mkdir -p ${XDDESTDIR}${TESTSBASE} mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \ - -p ${XDDESTDIR}/usr >/dev/null + -p ${XDDESTDIR}${TESTSBASE} >/dev/null .endif .ORDER: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries diff --git a/UPDATING b/UPDATING index b9a7b3552fb9..89a2de7deb1f 100644 --- a/UPDATING +++ b/UPDATING @@ -31,6 +31,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20141121: + The handling of LOCAL_LIB_DIRS has been altered to skip addition of + directories to top level SUBDIR variable when their parent + directory is included in LOCAL_DIRS. Users with build systems with + such hierarchies and without SUBDIR entries in the parent + directory Makefiles should add them or add the directories to + LOCAL_DIRS. + 20141109: faith(4) and faithd(8) has been removed from base system. It has been obsolete for a very long time. diff --git a/bin/sh/output.c b/bin/sh/output.c index c6d118f11535..39b722fdba23 100644 --- a/bin/sh/output.c +++ b/bin/sh/output.c @@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include "shell.h" #include "syntax.h" @@ -111,42 +113,86 @@ outstr(const char *p, struct output *file) outbin(p, strlen(p), file); } +static void +byteseq(int ch, struct output *file) +{ + char seq[4]; + + seq[0] = '\\'; + seq[1] = (ch >> 6 & 0x3) + '0'; + seq[2] = (ch >> 3 & 0x7) + '0'; + seq[3] = (ch & 0x7) + '0'; + outbin(seq, 4, file); +} + +static void +outdqstr(const char *p, struct output *file) +{ + const char *end; + mbstate_t mbs; + size_t clen; + wchar_t wc; + + memset(&mbs, '\0', sizeof(mbs)); + end = p + strlen(p); + outstr("$'", file); + while ((clen = mbrtowc(&wc, p, end - p + 1, &mbs)) != 0) { + if (clen == (size_t)-2) { + while (p < end) + byteseq(*p++, file); + break; + } + if (clen == (size_t)-1) { + memset(&mbs, '\0', sizeof(mbs)); + byteseq(*p++, file); + continue; + } + if (wc == L'\n') + outcslow('\n', file), p++; + else if (wc == L'\r') + outstr("\\r", file), p++; + else if (wc == L'\t') + outstr("\\t", file), p++; + else if (!iswprint(wc)) { + for (; clen > 0; clen--) + byteseq(*p++, file); + } else { + if (wc == L'\'' || wc == L'\\') + outcslow('\\', file); + outbin(p, clen, file); + p += clen; + } + } + outcslow('\'', file); +} + /* Like outstr(), but quote for re-input into the shell. */ void outqstr(const char *p, struct output *file) { - char ch; - int inquotes; + int i; if (p[0] == '\0') { outstr("''", file); return; } - if (p[strcspn(p, "|&;<>()$`\\\"' \t\n*?[~#=")] == '\0' || + for (i = 0; p[i] != '\0'; i++) { + if ((p[i] > '\0' && p[i] < ' ' && p[i] != '\n') || + (p[i] & 0x80) != 0 || p[i] == '\'') { + outdqstr(p, file); + return; + } + } + + if (p[strcspn(p, "|&;<>()$`\\\" \n*?[~#=")] == '\0' || strcmp(p, "[") == 0) { outstr(p, file); return; } - inquotes = 0; - while ((ch = *p++) != '\0') { - switch (ch) { - case '\'': - /* Can't quote single quotes inside single quotes. */ - if (inquotes) - outcslow('\'', file); - inquotes = 0; - outstr("\\'", file); - break; - default: - if (!inquotes) - outcslow('\'', file); - inquotes = 1; - outc(ch, file); - } - } - if (inquotes) - outcslow('\'', file); + outcslow('\'', file); + outstr(p, file); + outcslow('\'', file); } void diff --git a/bin/sh/tests/execution/Makefile b/bin/sh/tests/execution/Makefile index 2653d5ffe799..638492bb96ad 100644 --- a/bin/sh/tests/execution/Makefile +++ b/bin/sh/tests/execution/Makefile @@ -44,6 +44,7 @@ FILES+= set-n4.0 FILES+= set-x1.0 FILES+= set-x2.0 FILES+= set-x3.0 +FILES+= set-x4.0 FILES+= shellproc1.0 FILES+= subshell1.0 subshell1.0.stdout FILES+= subshell2.0 diff --git a/bin/sh/tests/execution/set-x4.0 b/bin/sh/tests/execution/set-x4.0 new file mode 100644 index 000000000000..0904766ccdd1 --- /dev/null +++ b/bin/sh/tests/execution/set-x4.0 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +key=`printf '\r\t\001\200\300'` +r=`{ set -x; : "$key"; } 2>&1 >/dev/null` +case $r in +*[![:print:]]*) echo fail; exit 3 +esac diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c index 47ab7bf9a1db..34912cd8dfb0 100644 --- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c +++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c @@ -1184,7 +1184,7 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp, print_indirect(bp, zb, dnp); if (BP_GET_LEVEL(bp) > 0 && !BP_IS_HOLE(bp)) { - uint32_t flags = ARC_WAIT; + arc_flags_t flags = ARC_FLAG_WAIT; int i; blkptr_t *cbp; int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT; @@ -1884,8 +1884,8 @@ dump_dir(objset_t *os) if (dds.dds_type == DMU_OST_META) { dds.dds_creation_txg = TXG_INITIAL; usedobjs = BP_GET_FILL(os->os_rootbp); - refdbytes = os->os_spa->spa_dsl_pool-> - dp_mos_dir->dd_phys->dd_used_bytes; + refdbytes = dsl_dir_phys(os->os_spa->spa_dsl_pool->dp_mos_dir)-> + dd_used_bytes; } else { dmu_objset_space(os, &refdbytes, &scratch, &usedobjs, &scratch); } diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c index ccd4f9b7fb8d..fc86eb795220 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c @@ -110,7 +110,7 @@ dtrace_dof_init(void) Elf32_Ehdr *elf; #endif dof_helper_t dh; - Link_map *lmp; + Link_map *lmp = NULL; #if defined(sun) Lmid_t lmid; #else diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c index 9698a720b112..aadc1f96deaa 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c @@ -24,7 +24,7 @@ * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright (c) 2012 Pawel Jakub Dawidek . * All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #include @@ -193,9 +193,6 @@ zfs_iter_bookmarks(zfs_handle_t *zhp, zfs_iter_f func, void *data) fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATETXG)); fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_CREATION)); - /* Allocate an nvlist to hold the bookmarks. */ - bmarks = fnvlist_alloc(); - if ((err = lzc_get_bookmarks(zhp->zfs_name, props, &bmarks)) != 0) goto out; diff --git a/contrib/binutils/gas/config/tc-ppc.c b/contrib/binutils/gas/config/tc-ppc.c index 1ecd99faea5d..940633b6a3f7 100644 --- a/contrib/binutils/gas/config/tc-ppc.c +++ b/contrib/binutils/gas/config/tc-ppc.c @@ -2509,108 +2509,156 @@ md_assemble (char *str) (char *) NULL, 0); } #ifdef OBJ_ELF - else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED) + else { - /* Some TLS tweaks. */ - switch (reloc) + if (ex.X_op == O_symbol && str[0] == '(') { - default: - break; - case BFD_RELOC_PPC_TLS: - insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2, - (char *) NULL, 0); - break; - /* We'll only use the 32 (or 64) bit form of these relocations - in constants. Instructions get the 16 bit form. */ - case BFD_RELOC_PPC_DTPREL: - reloc = BFD_RELOC_PPC_DTPREL16; - break; - case BFD_RELOC_PPC_TPREL: - reloc = BFD_RELOC_PPC_TPREL16; - break; - } + const char *sym_name = S_GET_NAME (ex.X_add_symbol); + if (sym_name[0] == '.') + ++sym_name; - /* For the absolute forms of branches, convert the PC - relative form back into the absolute. */ - if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) - { - switch (reloc) + if (strcasecmp (sym_name, "__tls_get_addr") == 0) { - case BFD_RELOC_PPC_B26: - reloc = BFD_RELOC_PPC_BA26; - break; - case BFD_RELOC_PPC_B16: - reloc = BFD_RELOC_PPC_BA16; - break; - case BFD_RELOC_PPC_B16_BRTAKEN: - reloc = BFD_RELOC_PPC_BA16_BRTAKEN; - break; - case BFD_RELOC_PPC_B16_BRNTAKEN: - reloc = BFD_RELOC_PPC_BA16_BRNTAKEN; - break; - default: - break; + expressionS tls_exp; + + hold = input_line_pointer; + input_line_pointer = str + 1; + expression (&tls_exp); + if (tls_exp.X_op == O_symbol) + { + reloc = BFD_RELOC_UNUSED; + if (strncasecmp (input_line_pointer, "@tlsgd)", 7) == 0) + { + reloc = BFD_RELOC_PPC_TLSGD; + input_line_pointer += 7; + } + else if (strncasecmp (input_line_pointer, "@tlsld)", 7) == 0) + { + reloc = BFD_RELOC_PPC_TLSLD; + input_line_pointer += 7; + } + if (reloc != BFD_RELOC_UNUSED) + { + SKIP_WHITESPACE (); + str = input_line_pointer; + + if (fc >= MAX_INSN_FIXUPS) + as_fatal (_("too many fixups")); + fixups[fc].exp = tls_exp; + fixups[fc].opindex = *opindex_ptr; + fixups[fc].reloc = reloc; + ++fc; + } + } + input_line_pointer = hold; } } - if (ppc_obj64 - && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0) + if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED) { + /* Some TLS tweaks. */ switch (reloc) { - case BFD_RELOC_16: - reloc = BFD_RELOC_PPC64_ADDR16_DS; - break; - case BFD_RELOC_LO16: - reloc = BFD_RELOC_PPC64_ADDR16_LO_DS; - break; - case BFD_RELOC_16_GOTOFF: - reloc = BFD_RELOC_PPC64_GOT16_DS; - break; - case BFD_RELOC_LO16_GOTOFF: - reloc = BFD_RELOC_PPC64_GOT16_LO_DS; - break; - case BFD_RELOC_LO16_PLTOFF: - reloc = BFD_RELOC_PPC64_PLT16_LO_DS; - break; - case BFD_RELOC_16_BASEREL: - reloc = BFD_RELOC_PPC64_SECTOFF_DS; - break; - case BFD_RELOC_LO16_BASEREL: - reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS; - break; - case BFD_RELOC_PPC_TOC16: - reloc = BFD_RELOC_PPC64_TOC16_DS; - break; - case BFD_RELOC_PPC64_TOC16_LO: - reloc = BFD_RELOC_PPC64_TOC16_LO_DS; - break; - case BFD_RELOC_PPC64_PLTGOT16: - reloc = BFD_RELOC_PPC64_PLTGOT16_DS; - break; - case BFD_RELOC_PPC64_PLTGOT16_LO: - reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS; - break; - case BFD_RELOC_PPC_DTPREL16: - reloc = BFD_RELOC_PPC64_DTPREL16_DS; - break; - case BFD_RELOC_PPC_DTPREL16_LO: - reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS; - break; - case BFD_RELOC_PPC_TPREL16: - reloc = BFD_RELOC_PPC64_TPREL16_DS; - break; - case BFD_RELOC_PPC_TPREL16_LO: - reloc = BFD_RELOC_PPC64_TPREL16_LO_DS; - break; - case BFD_RELOC_PPC_GOT_DTPREL16: - case BFD_RELOC_PPC_GOT_DTPREL16_LO: - case BFD_RELOC_PPC_GOT_TPREL16: - case BFD_RELOC_PPC_GOT_TPREL16_LO: - break; default: - as_bad (_("unsupported relocation for DS offset field")); break; + + case BFD_RELOC_PPC_TLS: + insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2, + (char *) NULL, 0); + break; + + /* We'll only use the 32 (or 64) bit form of these relocations + in constants. Instructions get the 16 bit form. */ + case BFD_RELOC_PPC_DTPREL: + reloc = BFD_RELOC_PPC_DTPREL16; + break; + case BFD_RELOC_PPC_TPREL: + reloc = BFD_RELOC_PPC_TPREL16; + break; + } + + /* For the absolute forms of branches, convert the PC + relative form back into the absolute. */ + if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) + { + switch (reloc) + { + case BFD_RELOC_PPC_B26: + reloc = BFD_RELOC_PPC_BA26; + break; + case BFD_RELOC_PPC_B16: + reloc = BFD_RELOC_PPC_BA16; + break; + case BFD_RELOC_PPC_B16_BRTAKEN: + reloc = BFD_RELOC_PPC_BA16_BRTAKEN; + break; + case BFD_RELOC_PPC_B16_BRNTAKEN: + reloc = BFD_RELOC_PPC_BA16_BRNTAKEN; + break; + default: + break; + } + } + + if (ppc_obj64 + && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0) + { + switch (reloc) + { + case BFD_RELOC_16: + reloc = BFD_RELOC_PPC64_ADDR16_DS; + break; + case BFD_RELOC_LO16: + reloc = BFD_RELOC_PPC64_ADDR16_LO_DS; + break; + case BFD_RELOC_16_GOTOFF: + reloc = BFD_RELOC_PPC64_GOT16_DS; + break; + case BFD_RELOC_LO16_GOTOFF: + reloc = BFD_RELOC_PPC64_GOT16_LO_DS; + break; + case BFD_RELOC_LO16_PLTOFF: + reloc = BFD_RELOC_PPC64_PLT16_LO_DS; + break; + case BFD_RELOC_16_BASEREL: + reloc = BFD_RELOC_PPC64_SECTOFF_DS; + break; + case BFD_RELOC_LO16_BASEREL: + reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS; + break; + case BFD_RELOC_PPC_TOC16: + reloc = BFD_RELOC_PPC64_TOC16_DS; + break; + case BFD_RELOC_PPC64_TOC16_LO: + reloc = BFD_RELOC_PPC64_TOC16_LO_DS; + break; + case BFD_RELOC_PPC64_PLTGOT16: + reloc = BFD_RELOC_PPC64_PLTGOT16_DS; + break; + case BFD_RELOC_PPC64_PLTGOT16_LO: + reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS; + break; + case BFD_RELOC_PPC_DTPREL16: + reloc = BFD_RELOC_PPC64_DTPREL16_DS; + break; + case BFD_RELOC_PPC_DTPREL16_LO: + reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS; + break; + case BFD_RELOC_PPC_TPREL16: + reloc = BFD_RELOC_PPC64_TPREL16_DS; + break; + case BFD_RELOC_PPC_TPREL16_LO: + reloc = BFD_RELOC_PPC64_TPREL16_LO_DS; + break; + case BFD_RELOC_PPC_GOT_DTPREL16: + case BFD_RELOC_PPC_GOT_DTPREL16_LO: + case BFD_RELOC_PPC_GOT_TPREL16: + case BFD_RELOC_PPC_GOT_TPREL16_LO: + break; + default: + as_bad (_("unsupported relocation for DS offset field")); + break; + } } } @@ -2618,12 +2666,11 @@ md_assemble (char *str) if (fc >= MAX_INSN_FIXUPS) as_fatal (_("too many fixups")); fixups[fc].exp = ex; - fixups[fc].opindex = 0; + fixups[fc].opindex = *opindex_ptr; fixups[fc].reloc = reloc; ++fc; } -#endif /* OBJ_ELF */ - +#else /* OBJ_ELF */ else { /* We need to generate a fixup for this expression. */ @@ -2634,6 +2681,7 @@ md_assemble (char *str) fixups[fc].reloc = BFD_RELOC_UNUSED; ++fc; } +#endif /* OBJ_ELF */ if (need_paren) { @@ -5908,6 +5956,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) break; case BFD_RELOC_PPC_TLS: + case BFD_RELOC_PPC_TLSLD: + case BFD_RELOC_PPC_TLSGD: break; case BFD_RELOC_PPC_DTPMOD: diff --git a/contrib/elftoolchain/elfcopy/main.c b/contrib/elftoolchain/elfcopy/main.c index 3689f355fecd..240ca5634cde 100644 --- a/contrib/elftoolchain/elfcopy/main.c +++ b/contrib/elftoolchain/elfcopy/main.c @@ -1109,7 +1109,8 @@ strip_main(struct elfcopy *ecp, int argc, char **argv) if (ecp->strip == 0 && ((ecp->flags & DISCARD_LOCAL) == 0) && - ((ecp->flags & DISCARD_LLABEL) == 0)) + ((ecp->flags & DISCARD_LLABEL) == 0) && + lookup_symop_list(ecp, NULL, SYMOP_STRIP) == NULL) ecp->strip = STRIP_ALL; if (optind == argc) strip_usage(); diff --git a/contrib/elftoolchain/elfcopy/segments.c b/contrib/elftoolchain/elfcopy/segments.c index 853c728e8f37..d358e5c3695d 100644 --- a/contrib/elftoolchain/elfcopy/segments.c +++ b/contrib/elftoolchain/elfcopy/segments.c @@ -439,7 +439,7 @@ copy_phdr(struct elfcopy *ecp) seg->fsz = seg->msz = 0; for (i = 0; i < seg->nsec; i++) { s = seg->v_sec[i]; - seg->msz = s->off + s->sz - seg->off; + seg->msz = s->vma + s->sz - seg->addr; if (s->type != SHT_NOBITS) seg->fsz = seg->msz; } diff --git a/contrib/elftoolchain/readelf/Makefile b/contrib/elftoolchain/readelf/Makefile new file mode 100644 index 000000000000..09c8650cda6a --- /dev/null +++ b/contrib/elftoolchain/readelf/Makefile @@ -0,0 +1,15 @@ +# $Id: Makefile 2076 2011-10-27 03:50:33Z jkoshy $ + +TOP= .. + +PROG= readelf +SRCS= readelf.c + +WARNS?= 6 + +DPADD= ${LIBDWARF} ${LIBELF} +LDADD= -ldwarf -lelftc -lelf + +MAN1= readelf.1 + +.include "${TOP}/mk/elftoolchain.prog.mk" diff --git a/contrib/elftoolchain/readelf/readelf.1 b/contrib/elftoolchain/readelf/readelf.1 new file mode 100644 index 000000000000..9a6efe58fab0 --- /dev/null +++ b/contrib/elftoolchain/readelf/readelf.1 @@ -0,0 +1,197 @@ +.\" Copyright (c) 2009,2011 Joseph Koshy +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer +.\" in this position and unchanged. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: readelf.1 2577 2012-09-13 16:07:04Z jkoshy $ +.\" +.Dd September 13, 2012 +.Os +.Dt READELF 1 +.Sh NAME +.Nm readelf +.Nd display information about ELF objects +.Sh SYNOPSIS +.Nm +.Op Fl a | Fl -all +.Op Fl c | Fl -archive-index +.Op Fl d | Fl -dynamic +.Op Fl e | Fl -headers +.Op Fl g | Fl -section-groups +.Op Fl h | Fl -file-header +.Op Fl l | Fl -program-headers +.Op Fl n | Fl -notes +.Op Fl p Ar section | Fl -string-dump Ns = Ns Ar section +.Op Fl r | Fl -relocs +.Op Fl t | Fl -section-details +.Op Fl x Ar section | Fl -hex-dump Ns = Ns Ar section +.Op Fl v | Fl -version +.Oo +.Fl w Ns Oo Ns Ar afilmoprsFLR Ns Oc | +.Fl -debug-dump Ns Op Ns = Ns Ar long-option-name , Ns ... +.Oc +.Op Fl A | Fl -arch-specific +.Op Fl D | Fl -use-dynamic +.Op Fl H | Fl -help +.Op Fl I | Fl -histogram +.Op Fl N | -full-section-name +.Op Fl S | Fl -sections | Fl -section-headers +.Op Fl V | Fl -version-info +.Op Fl W | Fl -wide +.Ar file... +.Sh DESCRIPTION +The +.Nm +utility displays information about ELF objects and +.Xr ar 1 +archives. +.Pp +The +.Nm +utility recognizes the following options: +.Bl -tag -width indent +.It Fl a | Fl -all +Turn on the following flags: +.Fl d , +.Fl h , +.Fl I , +.Fl l , +.Fl r , +.Fl s , +.Fl A , +.Fl S +and +.Fl V . +.It Fl c | Fl -archive-index +Print the archive symbol table for archives. +.It Fl d | Fl -dynamic +Print the contents of the +.Li SHT_DYNAMIC +sections in the ELF object. +.It Fl e | Fl -headers +Print all program, file and section headers in the ELF object. +.It Fl g | Fl -section-groups +This option is recognized, but is ignored. +.It Fl h | Fl -file-header +Print the file header of the ELF object. +.It Fl l | Fl -program-headers +Print the content of the program header table for the object. +.It Fl n | Fl -notes +Print the contents of +.Li PT_NOTE +segments or +.Li SHT_NOTE +sections present in the ELF object. +.It Fl p Ar section | Fl -string-dump Ns = Ns Ar section +Print the contents of the specified section as printable strings. +The argument +.Ar section +should be the name of a section or a numeric section index. +.It Fl r | Fl -relocs +Print relocation information. +.It Fl s | Fl -syms | Fl -symbols +Print symbol tables. +.It Fl t | Fl -section-details +Print additional information about sections, such as the flags +fields in section headers. +.It Fl v | Fl -version +Prints a version identifier for +.Nm +and exits. +.It Fl w Ns Oo afilmoprsFLR Oc | Xo +.Fl -debug-dump Ns Op Ns = Ns Ar long-option-name , Ns ... +.Xc +Display DWARF information. +The +.Fl w +option is used with the short options in the following +table; the +.Fl -debug-dump +option is used with a comma-separated list of the corresponding long +option names: +.Bl -column ".Em Short Option" "aranges|ranges" +.It Em Short Option Ta Em Long Option Ta Em Description +.It a Ta abbrev Ta Show abbreviation information. +.It f Ta frames Ta Show frame information, displaying frame instructions. +.It i Ta info Ta Show debugging information entries. +.It l Ta rawline Ta Show line information in raw form. +.It m Ta macro Ta Show macro information. +.It o Ta loc Ta Show location list information. +.It p Ta pubnames Ta Show global names. +.It r Ta aranges|ranges Ta Show address range information. +.It s Ta str Ta Show the debug string table. +.It F Ta Ta Show frame information, displaying register rules. +.It L Ta decodedline Ta Show line information in decoded form. +.It R Ta Ranges Ta Show range lists. +.El +.Pp +If no sub-options are specified, the default is to show information +corresponding to the +.Ar a , f , i, l , o , p , r , s +and +.Ar R +short options. +.It Fl x Ar section | Fl -hex-dump Ns = Ns Ar section +Display the contents of the specified section in hexadecimal. +The argument +.Ar section +should be the name of a section or a numeric section index. +.It Fl A | Fl -arch-specific +This option is accepted but is currently unimplemented. +.It Fl D | Fl -use-dynamic +Print the symbol table specified by the +.Li DT_SYMTAB +entry in the +.Dq Li .dynamic +section. +.It Fl H | Fl -help +Print a help message. +.It Fl I | Fl -histogram +Print information on bucket list lengths for sections of type +.Li SHT_HASH +and +.Li SHT_GNU_HASH . +.It Fl N | Fl -full-section-name +This option is accepted but is currently unimplemented. +.It Fl S | Fl -sections | Fl -section-headers +Print information in the section headers for each ELF object. +.It Fl V | Fl -version-info +Print symbol versioning information. +.It Fl W | Fl -wide +Print information about ELF structures using one long line per +structure. +If this option is not specified, +.Nm +will list information in the headers of 64 bit ELF objects on two +separate lines. +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr nm 1 , +.Xr addr2line 1 , +.Xr elfcopy 1 , +.Sh AUTHORS +The +.Nm +utility was written by +.An "Kai Wang" Aq kaiwang27@users.sourceforge.net . diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c new file mode 100644 index 000000000000..779a7ba9e875 --- /dev/null +++ b/contrib/elftoolchain/readelf/readelf.c @@ -0,0 +1,6845 @@ +/*- + * Copyright (c) 2009,2010 Kai Wang + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "_elftc.h" + +ELFTC_VCSID("$Id: readelf.c 2946 2013-05-26 08:00:11Z kaiwang27 $"); + +/* + * readelf(1) options. + */ +#define RE_AA 0x00000001 +#define RE_C 0x00000002 +#define RE_DD 0x00000004 +#define RE_D 0x00000008 +#define RE_G 0x00000010 +#define RE_H 0x00000020 +#define RE_II 0x00000040 +#define RE_I 0x00000080 +#define RE_L 0x00000100 +#define RE_NN 0x00000200 +#define RE_N 0x00000400 +#define RE_P 0x00000800 +#define RE_R 0x00001000 +#define RE_SS 0x00002000 +#define RE_S 0x00004000 +#define RE_T 0x00008000 +#define RE_U 0x00010000 +#define RE_VV 0x00020000 +#define RE_WW 0x00040000 +#define RE_W 0x00080000 +#define RE_X 0x00100000 + +/* + * dwarf dump options. + */ +#define DW_A 0x00000001 +#define DW_FF 0x00000002 +#define DW_F 0x00000004 +#define DW_I 0x00000008 +#define DW_LL 0x00000010 +#define DW_L 0x00000020 +#define DW_M 0x00000040 +#define DW_O 0x00000080 +#define DW_P 0x00000100 +#define DW_RR 0x00000200 +#define DW_R 0x00000400 +#define DW_S 0x00000800 + +#define DW_DEFAULT_OPTIONS (DW_A | DW_F | DW_I | DW_L | DW_O | DW_P | \ + DW_R | DW_RR | DW_S) + +/* + * readelf(1) run control flags. + */ +#define DISPLAY_FILENAME 0x0001 + +/* + * Internal data structure for sections. + */ +struct section { + const char *name; /* section name */ + Elf_Scn *scn; /* section scn */ + uint64_t off; /* section offset */ + uint64_t sz; /* section size */ + uint64_t entsize; /* section entsize */ + uint64_t align; /* section alignment */ + uint64_t type; /* section type */ + uint64_t flags; /* section flags */ + uint64_t addr; /* section virtual addr */ + uint32_t link; /* section link ndx */ + uint32_t info; /* section info ndx */ +}; + +struct dumpop { + union { + size_t si; /* section index */ + const char *sn; /* section name */ + } u; + enum { + DUMP_BY_INDEX = 0, + DUMP_BY_NAME + } type; /* dump type */ +#define HEX_DUMP 0x0001 +#define STR_DUMP 0x0002 + int op; /* dump operation */ + STAILQ_ENTRY(dumpop) dumpop_list; +}; + +struct symver { + const char *name; + int type; +}; + +/* + * Structure encapsulates the global data for readelf(1). + */ +struct readelf { + const char *filename; /* current processing file. */ + int options; /* command line options. */ + int flags; /* run control flags. */ + int dop; /* dwarf dump options. */ + Elf *elf; /* underlying ELF descriptor. */ + Elf *ar; /* archive ELF descriptor. */ + Dwarf_Debug dbg; /* DWARF handle. */ + GElf_Ehdr ehdr; /* ELF header. */ + int ec; /* ELF class. */ + size_t shnum; /* #sections. */ + struct section *vd_s; /* Verdef section. */ + struct section *vn_s; /* Verneed section. */ + struct section *vs_s; /* Versym section. */ + uint16_t *vs; /* Versym array. */ + int vs_sz; /* Versym array size. */ + struct symver *ver; /* Version array. */ + int ver_sz; /* Size of version array. */ + struct section *sl; /* list of sections. */ + STAILQ_HEAD(, dumpop) v_dumpop; /* list of dump ops. */ + uint64_t (*dw_read)(Elf_Data *, uint64_t *, int); + uint64_t (*dw_decode)(uint8_t **, int); +}; + +enum options +{ + OPTION_DEBUG_DUMP +}; + +static struct option longopts[] = { + {"all", no_argument, NULL, 'a'}, + {"arch-specific", no_argument, NULL, 'A'}, + {"archive-index", no_argument, NULL, 'c'}, + {"debug-dump", optional_argument, NULL, OPTION_DEBUG_DUMP}, + {"dynamic", no_argument, NULL, 'd'}, + {"file-header", no_argument, NULL, 'h'}, + {"full-section-name", no_argument, NULL, 'N'}, + {"headers", no_argument, NULL, 'e'}, + {"help", no_argument, 0, 'H'}, + {"hex-dump", required_argument, NULL, 'x'}, + {"histogram", no_argument, NULL, 'I'}, + {"notes", no_argument, NULL, 'n'}, + {"program-headers", no_argument, NULL, 'l'}, + {"relocs", no_argument, NULL, 'r'}, + {"sections", no_argument, NULL, 'S'}, + {"section-headers", no_argument, NULL, 'S'}, + {"section-groups", no_argument, NULL, 'g'}, + {"section-details", no_argument, NULL, 't'}, + {"segments", no_argument, NULL, 'l'}, + {"string-dump", required_argument, NULL, 'p'}, + {"symbols", no_argument, NULL, 's'}, + {"syms", no_argument, NULL, 's'}, + {"unwind", no_argument, NULL, 'u'}, + {"use-dynamic", no_argument, NULL, 'D'}, + {"version-info", no_argument, 0, 'V'}, + {"version", no_argument, 0, 'v'}, + {"wide", no_argument, 0, 'W'}, + {NULL, 0, NULL, 0} +}; + +struct eflags_desc { + uint64_t flag; + const char *desc; +}; + +struct mips_option { + uint64_t flag; + const char *desc; +}; + +static void add_dumpop(struct readelf *re, size_t si, const char *sn, int op, + int t); +static const char *aeabi_adv_simd_arch(uint64_t simd); +static const char *aeabi_align_needed(uint64_t an); +static const char *aeabi_align_preserved(uint64_t ap); +static const char *aeabi_arm_isa(uint64_t ai); +static const char *aeabi_cpu_arch(uint64_t arch); +static const char *aeabi_cpu_arch_profile(uint64_t pf); +static const char *aeabi_div(uint64_t du); +static const char *aeabi_enum_size(uint64_t es); +static const char *aeabi_fp_16bit_format(uint64_t fp16); +static const char *aeabi_fp_arch(uint64_t fp); +static const char *aeabi_fp_denormal(uint64_t fd); +static const char *aeabi_fp_exceptions(uint64_t fe); +static const char *aeabi_fp_hpext(uint64_t fh); +static const char *aeabi_fp_number_model(uint64_t fn); +static const char *aeabi_fp_optm_goal(uint64_t fog); +static const char *aeabi_fp_rounding(uint64_t fr); +static const char *aeabi_hardfp(uint64_t hfp); +static const char *aeabi_mpext(uint64_t mp); +static const char *aeabi_optm_goal(uint64_t og); +static const char *aeabi_pcs_config(uint64_t pcs); +static const char *aeabi_pcs_got(uint64_t got); +static const char *aeabi_pcs_r9(uint64_t r9); +static const char *aeabi_pcs_ro(uint64_t ro); +static const char *aeabi_pcs_rw(uint64_t rw); +static const char *aeabi_pcs_wchar_t(uint64_t wt); +static const char *aeabi_t2ee(uint64_t t2ee); +static const char *aeabi_thumb_isa(uint64_t ti); +static const char *aeabi_fp_user_exceptions(uint64_t fu); +static const char *aeabi_unaligned_access(uint64_t ua); +static const char *aeabi_vfp_args(uint64_t va); +static const char *aeabi_virtual(uint64_t vt); +static const char *aeabi_wmmx_arch(uint64_t wmmx); +static const char *aeabi_wmmx_args(uint64_t wa); +static const char *elf_class(unsigned int class); +static const char *elf_endian(unsigned int endian); +static const char *elf_machine(unsigned int mach); +static const char *elf_osabi(unsigned int abi); +static const char *elf_type(unsigned int type); +static const char *elf_ver(unsigned int ver); +static const char *dt_type(unsigned int mach, unsigned int dtype); +static void dump_ar(struct readelf *re, int); +static void dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe); +static void dump_attributes(struct readelf *re); +static uint8_t *dump_compatibility_tag(uint8_t *p); +static void dump_dwarf(struct readelf *re); +static void dump_eflags(struct readelf *re, uint64_t e_flags); +static void dump_elf(struct readelf *re); +static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab); +static void dump_dynamic(struct readelf *re); +static void dump_liblist(struct readelf *re); +static void dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe); +static void dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz); +static void dump_mips_options(struct readelf *re, struct section *s); +static void dump_mips_option_flags(const char *name, struct mips_option *opt, + uint64_t info); +static void dump_mips_reginfo(struct readelf *re, struct section *s); +static void dump_mips_specific_info(struct readelf *re); +static void dump_notes(struct readelf *re); +static void dump_notes_content(struct readelf *re, const char *buf, size_t sz, + off_t off); +static void dump_svr4_hash(struct section *s); +static void dump_svr4_hash64(struct readelf *re, struct section *s); +static void dump_gnu_hash(struct readelf *re, struct section *s); +static void dump_hash(struct readelf *re); +static void dump_phdr(struct readelf *re); +static void dump_ppc_attributes(uint8_t *p, uint8_t *pe); +static void dump_symtab(struct readelf *re, int i); +static void dump_symtabs(struct readelf *re); +static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p); +static void dump_ver(struct readelf *re); +static void dump_verdef(struct readelf *re, int dump); +static void dump_verneed(struct readelf *re, int dump); +static void dump_versym(struct readelf *re); +static struct dumpop *find_dumpop(struct readelf *re, size_t si, const char *sn, + int op, int t); +static const char *get_string(struct readelf *re, int strtab, size_t off); +static const char *get_symbol_name(struct readelf *re, int symtab, int i); +static uint64_t get_symbol_value(struct readelf *re, int symtab, int i); +static void load_sections(struct readelf *re); +static const char *mips_abi_fp(uint64_t fp); +static const char *note_type(unsigned int osabi, unsigned int et, + unsigned int nt); +static const char *option_kind(uint8_t kind); +static const char *phdr_type(unsigned int ptype); +static const char *ppc_abi_fp(uint64_t fp); +static const char *ppc_abi_vector(uint64_t vec); +static const char *r_type(unsigned int mach, unsigned int type); +static void readelf_usage(void); +static void readelf_version(void); +static void search_ver(struct readelf *re); +static const char *section_type(unsigned int mach, unsigned int stype); +static const char *st_bind(unsigned int sbind); +static const char *st_shndx(unsigned int shndx); +static const char *st_type(unsigned int stype); +static const char *st_vis(unsigned int svis); +static const char *top_tag(unsigned int tag); +static void unload_sections(struct readelf *re); +static uint64_t _read_lsb(Elf_Data *d, uint64_t *offsetp, + int bytes_to_read); +static uint64_t _read_msb(Elf_Data *d, uint64_t *offsetp, + int bytes_to_read); +static uint64_t _decode_lsb(uint8_t **data, int bytes_to_read); +static uint64_t _decode_msb(uint8_t **data, int bytes_to_read); +static int64_t _decode_sleb128(uint8_t **dp); +static uint64_t _decode_uleb128(uint8_t **dp); + +static struct eflags_desc arm_eflags_desc[] = { + {EF_ARM_RELEXEC, "relocatable executable"}, + {EF_ARM_HASENTRY, "has entry point"}, + {EF_ARM_SYMSARESORTED, "sorted symbol tables"}, + {EF_ARM_DYNSYMSUSESEGIDX, "dynamic symbols use segment index"}, + {EF_ARM_MAPSYMSFIRST, "mapping symbols precede others"}, + {EF_ARM_BE8, "BE8"}, + {EF_ARM_LE8, "LE8"}, + {EF_ARM_INTERWORK, "interworking enabled"}, + {EF_ARM_APCS_26, "uses APCS/26"}, + {EF_ARM_APCS_FLOAT, "uses APCS/float"}, + {EF_ARM_PIC, "position independent"}, + {EF_ARM_ALIGN8, "8 bit structure alignment"}, + {EF_ARM_NEW_ABI, "uses new ABI"}, + {EF_ARM_OLD_ABI, "uses old ABI"}, + {EF_ARM_SOFT_FLOAT, "software FP"}, + {EF_ARM_VFP_FLOAT, "VFP"}, + {EF_ARM_MAVERICK_FLOAT, "Maverick FP"}, + {0, NULL} +}; + +static struct eflags_desc mips_eflags_desc[] = { + {EF_MIPS_NOREORDER, "noreorder"}, + {EF_MIPS_PIC, "pic"}, + {EF_MIPS_CPIC, "cpic"}, + {EF_MIPS_UCODE, "ugen_reserved"}, + {EF_MIPS_ABI2, "abi2"}, + {EF_MIPS_OPTIONS_FIRST, "odk first"}, + {EF_MIPS_ARCH_ASE_MDMX, "mdmx"}, + {EF_MIPS_ARCH_ASE_M16, "mips16"}, + {0, NULL} +}; + +static struct eflags_desc powerpc_eflags_desc[] = { + {EF_PPC_EMB, "emb"}, + {EF_PPC_RELOCATABLE, "relocatable"}, + {EF_PPC_RELOCATABLE_LIB, "relocatable-lib"}, + {0, NULL} +}; + +static struct eflags_desc sparc_eflags_desc[] = { + {EF_SPARC_32PLUS, "v8+"}, + {EF_SPARC_SUN_US1, "ultrasparcI"}, + {EF_SPARC_HAL_R1, "halr1"}, + {EF_SPARC_SUN_US3, "ultrasparcIII"}, + {0, NULL} +}; + +static const char * +elf_osabi(unsigned int abi) +{ + static char s_abi[32]; + + switch(abi) { + case ELFOSABI_SYSV: return "SYSV"; + case ELFOSABI_HPUX: return "HPUS"; + case ELFOSABI_NETBSD: return "NetBSD"; + case ELFOSABI_GNU: return "GNU"; + case ELFOSABI_HURD: return "HURD"; + case ELFOSABI_86OPEN: return "86OPEN"; + case ELFOSABI_SOLARIS: return "Solaris"; + case ELFOSABI_AIX: return "AIX"; + case ELFOSABI_IRIX: return "IRIX"; + case ELFOSABI_FREEBSD: return "FreeBSD"; + case ELFOSABI_TRU64: return "TRU64"; + case ELFOSABI_MODESTO: return "MODESTO"; + case ELFOSABI_OPENBSD: return "OpenBSD"; + case ELFOSABI_OPENVMS: return "OpenVMS"; + case ELFOSABI_NSK: return "NSK"; + case ELFOSABI_ARM: return "ARM"; + case ELFOSABI_STANDALONE: return "StandAlone"; + default: + snprintf(s_abi, sizeof(s_abi), "", abi); + return (s_abi); + } +}; + +static const char * +elf_machine(unsigned int mach) +{ + static char s_mach[32]; + + switch (mach) { + case EM_NONE: return "Unknown machine"; + case EM_M32: return "AT&T WE32100"; + case EM_SPARC: return "Sun SPARC"; + case EM_386: return "Intel i386"; + case EM_68K: return "Motorola 68000"; + case EM_88K: return "Motorola 88000"; + case EM_860: return "Intel i860"; + case EM_MIPS: return "MIPS R3000 Big-Endian only"; + case EM_S370: return "IBM System/370"; + case EM_MIPS_RS3_LE: return "MIPS R3000 Little-Endian"; + case EM_PARISC: return "HP PA-RISC"; + case EM_VPP500: return "Fujitsu VPP500"; + case EM_SPARC32PLUS: return "SPARC v8plus"; + case EM_960: return "Intel 80960"; + case EM_PPC: return "PowerPC 32-bit"; + case EM_PPC64: return "PowerPC 64-bit"; + case EM_S390: return "IBM System/390"; + case EM_V800: return "NEC V800"; + case EM_FR20: return "Fujitsu FR20"; + case EM_RH32: return "TRW RH-32"; + case EM_RCE: return "Motorola RCE"; + case EM_ARM: return "ARM"; + case EM_SH: return "Hitachi SH"; + case EM_SPARCV9: return "SPARC v9 64-bit"; + case EM_TRICORE: return "Siemens TriCore embedded processor"; + case EM_ARC: return "Argonaut RISC Core"; + case EM_H8_300: return "Hitachi H8/300"; + case EM_H8_300H: return "Hitachi H8/300H"; + case EM_H8S: return "Hitachi H8S"; + case EM_H8_500: return "Hitachi H8/500"; + case EM_IA_64: return "Intel IA-64 Processor"; + case EM_MIPS_X: return "Stanford MIPS-X"; + case EM_COLDFIRE: return "Motorola ColdFire"; + case EM_68HC12: return "Motorola M68HC12"; + case EM_MMA: return "Fujitsu MMA"; + case EM_PCP: return "Siemens PCP"; + case EM_NCPU: return "Sony nCPU"; + case EM_NDR1: return "Denso NDR1 microprocessor"; + case EM_STARCORE: return "Motorola Star*Core processor"; + case EM_ME16: return "Toyota ME16 processor"; + case EM_ST100: return "STMicroelectronics ST100 processor"; + case EM_TINYJ: return "Advanced Logic Corp. TinyJ processor"; + case EM_X86_64: return "Advanced Micro Devices x86-64"; + case EM_PDSP: return "Sony DSP Processor"; + case EM_FX66: return "Siemens FX66 microcontroller"; + case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 microcontroller"; + case EM_ST7: return "STmicroelectronics ST7 8-bit microcontroller"; + case EM_68HC16: return "Motorola MC68HC16 microcontroller"; + case EM_68HC11: return "Motorola MC68HC11 microcontroller"; + case EM_68HC08: return "Motorola MC68HC08 microcontroller"; + case EM_68HC05: return "Motorola MC68HC05 microcontroller"; + case EM_SVX: return "Silicon Graphics SVx"; + case EM_ST19: return "STMicroelectronics ST19 8-bit mc"; + case EM_VAX: return "Digital VAX"; + case EM_CRIS: return "Axis Communications 32-bit embedded processor"; + case EM_JAVELIN: return "Infineon Tech. 32bit embedded processor"; + case EM_FIREPATH: return "Element 14 64-bit DSP Processor"; + case EM_ZSP: return "LSI Logic 16-bit DSP Processor"; + case EM_MMIX: return "Donald Knuth's educational 64-bit proc"; + case EM_HUANY: return "Harvard University MI object files"; + case EM_PRISM: return "SiTera Prism"; + case EM_AVR: return "Atmel AVR 8-bit microcontroller"; + case EM_FR30: return "Fujitsu FR30"; + case EM_D10V: return "Mitsubishi D10V"; + case EM_D30V: return "Mitsubishi D30V"; + case EM_V850: return "NEC v850"; + case EM_M32R: return "Mitsubishi M32R"; + case EM_MN10300: return "Matsushita MN10300"; + case EM_MN10200: return "Matsushita MN10200"; + case EM_PJ: return "picoJava"; + case EM_OPENRISC: return "OpenRISC 32-bit embedded processor"; + case EM_ARC_A5: return "ARC Cores Tangent-A5"; + case EM_XTENSA: return "Tensilica Xtensa Architecture"; + case EM_VIDEOCORE: return "Alphamosaic VideoCore processor"; + case EM_TMM_GPP: return "Thompson Multimedia General Purpose Processor"; + case EM_NS32K: return "National Semiconductor 32000 series"; + case EM_TPC: return "Tenor Network TPC processor"; + case EM_SNP1K: return "Trebia SNP 1000 processor"; + case EM_ST200: return "STMicroelectronics ST200 microcontroller"; + case EM_IP2K: return "Ubicom IP2xxx microcontroller family"; + case EM_MAX: return "MAX Processor"; + case EM_CR: return "National Semiconductor CompactRISC microprocessor"; + case EM_F2MC16: return "Fujitsu F2MC16"; + case EM_MSP430: return "TI embedded microcontroller msp430"; + case EM_BLACKFIN: return "Analog Devices Blackfin (DSP) processor"; + case EM_SE_C33: return "S1C33 Family of Seiko Epson processors"; + case EM_SEP: return "Sharp embedded microprocessor"; + case EM_ARCA: return "Arca RISC Microprocessor"; + case EM_UNICORE: return "Microprocessor series from PKU-Unity Ltd"; + default: + snprintf(s_mach, sizeof(s_mach), "", mach); + return (s_mach); + } + +} + +static const char * +elf_class(unsigned int class) +{ + static char s_class[32]; + + switch (class) { + case ELFCLASSNONE: return "none"; + case ELFCLASS32: return "ELF32"; + case ELFCLASS64: return "ELF64"; + default: + snprintf(s_class, sizeof(s_class), "", class); + return (s_class); + } +} + +static const char * +elf_endian(unsigned int endian) +{ + static char s_endian[32]; + + switch (endian) { + case ELFDATANONE: return "none"; + case ELFDATA2LSB: return "2's complement, little endian"; + case ELFDATA2MSB: return "2's complement, big endian"; + default: + snprintf(s_endian, sizeof(s_endian), "", endian); + return (s_endian); + } +} + +static const char * +elf_type(unsigned int type) +{ + static char s_type[32]; + + switch (type) { + case ET_NONE: return "NONE (None)"; + case ET_REL: return "REL (Relocatable file)"; + case ET_EXEC: return "EXEC (Executable file)"; + case ET_DYN: return "DYN (Shared object file)"; + case ET_CORE: return "CORE (Core file)"; + default: + if (type >= ET_LOPROC) + snprintf(s_type, sizeof(s_type), "", type); + else if (type >= ET_LOOS && type <= ET_HIOS) + snprintf(s_type, sizeof(s_type), "", type); + else + snprintf(s_type, sizeof(s_type), "", + type); + return (s_type); + } +} + +static const char * +elf_ver(unsigned int ver) +{ + static char s_ver[32]; + + switch (ver) { + case EV_CURRENT: return "(current)"; + case EV_NONE: return "(none)"; + default: + snprintf(s_ver, sizeof(s_ver), "", + ver); + return (s_ver); + } +} + +static const char * +phdr_type(unsigned int ptype) +{ + static char s_ptype[32]; + + switch (ptype) { + case PT_NULL: return "NULL"; + case PT_LOAD: return "LOAD"; + case PT_DYNAMIC: return "DYNAMIC"; + case PT_INTERP: return "INTERP"; + case PT_NOTE: return "NOTE"; + case PT_SHLIB: return "SHLIB"; + case PT_PHDR: return "PHDR"; + case PT_TLS: return "TLS"; + case PT_GNU_EH_FRAME: return "GNU_EH_FRAME"; + case PT_GNU_STACK: return "GNU_STACK"; + case PT_GNU_RELRO: return "GNU_RELRO"; + default: + if (ptype >= PT_LOPROC && ptype <= PT_HIPROC) + snprintf(s_ptype, sizeof(s_ptype), "LOPROC+%#x", + ptype - PT_LOPROC); + else if (ptype >= PT_LOOS && ptype <= PT_HIOS) + snprintf(s_ptype, sizeof(s_ptype), "LOOS+%#x", + ptype - PT_LOOS); + else + snprintf(s_ptype, sizeof(s_ptype), "", + ptype); + return (s_ptype); + } +} + +static const char * +section_type(unsigned int mach, unsigned int stype) +{ + static char s_stype[32]; + + if (stype >= SHT_LOPROC && stype <= SHT_HIPROC) { + switch (mach) { + case EM_X86_64: + switch (stype) { + case SHT_AMD64_UNWIND: return "AMD64_UNWIND"; + default: + break; + } + break; + case EM_MIPS: + case EM_MIPS_RS3_LE: + switch (stype) { + case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST"; + case SHT_MIPS_MSYM: return "MIPS_MSYM"; + case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT"; + case SHT_MIPS_GPTAB: return "MIPS_GPTAB"; + case SHT_MIPS_UCODE: return "MIPS_UCODE"; + case SHT_MIPS_DEBUG: return "MIPS_DEBUG"; + case SHT_MIPS_REGINFO: return "MIPS_REGINFO"; + case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE"; + case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM"; + case SHT_MIPS_RELD: return "MIPS_RELD"; + case SHT_MIPS_IFACE: return "MIPS_IFACE"; + case SHT_MIPS_CONTENT: return "MIPS_CONTENT"; + case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS"; + case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM"; + case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST"; + case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS"; + case SHT_MIPS_DWARF: return "MIPS_DWARF"; + case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL"; + case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; + case SHT_MIPS_EVENTS: return "MIPS_EVENTS"; + case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE"; + case SHT_MIPS_PIXIE: return "MIPS_PIXIE"; + case SHT_MIPS_XLATE: return "MIPS_XLATE"; + case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG"; + case SHT_MIPS_WHIRL: return "MIPS_WHIRL"; + case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION"; + case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; + case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION"; + default: + break; + } + break; + default: + break; + } + + snprintf(s_stype, sizeof(s_stype), "LOPROC+%#x", + stype - SHT_LOPROC); + return (s_stype); + } + + switch (stype) { + case SHT_NULL: return "NULL"; + case SHT_PROGBITS: return "PROGBITS"; + case SHT_SYMTAB: return "SYMTAB"; + case SHT_STRTAB: return "STRTAB"; + case SHT_RELA: return "RELA"; + case SHT_HASH: return "HASH"; + case SHT_DYNAMIC: return "DYNAMIC"; + case SHT_NOTE: return "NOTE"; + case SHT_NOBITS: return "NOBITS"; + case SHT_REL: return "REL"; + case SHT_SHLIB: return "SHLIB"; + case SHT_DYNSYM: return "DYNSYM"; + case SHT_INIT_ARRAY: return "INIT_ARRAY"; + case SHT_FINI_ARRAY: return "FINI_ARRAY"; + case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY"; + case SHT_GROUP: return "GROUP"; + case SHT_SYMTAB_SHNDX: return "SYMTAB_SHNDX"; + case SHT_SUNW_dof: return "SUNW_dof"; + case SHT_SUNW_cap: return "SUNW_cap"; + case SHT_GNU_HASH: return "GNU_HASH"; + case SHT_SUNW_ANNOTATE: return "SUNW_ANNOTATE"; + case SHT_SUNW_DEBUGSTR: return "SUNW_DEBUGSTR"; + case SHT_SUNW_DEBUG: return "SUNW_DEBUG"; + case SHT_SUNW_move: return "SUNW_move"; + case SHT_SUNW_COMDAT: return "SUNW_COMDAT"; + case SHT_SUNW_syminfo: return "SUNW_syminfo"; + case SHT_SUNW_verdef: return "SUNW_verdef"; + case SHT_SUNW_verneed: return "SUNW_verneed"; + case SHT_SUNW_versym: return "SUNW_versym"; + default: + if (stype >= SHT_LOOS && stype <= SHT_HIOS) + snprintf(s_stype, sizeof(s_stype), "LOOS+%#x", + stype - SHT_LOOS); + else if (stype >= SHT_LOUSER) + snprintf(s_stype, sizeof(s_stype), "LOUSER+%#x", + stype - SHT_LOUSER); + else + snprintf(s_stype, sizeof(s_stype), "", + stype); + return (s_stype); + } +} + +static const char * +dt_type(unsigned int mach, unsigned int dtype) +{ + static char s_dtype[32]; + + if (dtype >= DT_LOPROC && dtype <= DT_HIPROC) { + switch (mach) { + case EM_ARM: + switch (dtype) { + case DT_ARM_SYMTABSZ: + return "ARM_SYMTABSZ"; + default: + break; + } + break; + case EM_MIPS: + case EM_MIPS_RS3_LE: + switch (dtype) { + case DT_MIPS_RLD_VERSION: + return "MIPS_RLD_VERSION"; + case DT_MIPS_TIME_STAMP: + return "MIPS_TIME_STAMP"; + case DT_MIPS_ICHECKSUM: + return "MIPS_ICHECKSUM"; + case DT_MIPS_IVERSION: + return "MIPS_IVERSION"; + case DT_MIPS_FLAGS: + return "MIPS_FLAGS"; + case DT_MIPS_BASE_ADDRESS: + return "MIPS_BASE_ADDRESS"; + case DT_MIPS_CONFLICT: + return "MIPS_CONFLICT"; + case DT_MIPS_LIBLIST: + return "MIPS_LIBLIST"; + case DT_MIPS_LOCAL_GOTNO: + return "MIPS_LOCAL_GOTNO"; + case DT_MIPS_CONFLICTNO: + return "MIPS_CONFLICTNO"; + case DT_MIPS_LIBLISTNO: + return "MIPS_LIBLISTNO"; + case DT_MIPS_SYMTABNO: + return "MIPS_SYMTABNO"; + case DT_MIPS_UNREFEXTNO: + return "MIPS_UNREFEXTNO"; + case DT_MIPS_GOTSYM: + return "MIPS_GOTSYM"; + case DT_MIPS_HIPAGENO: + return "MIPS_HIPAGENO"; + case DT_MIPS_RLD_MAP: + return "MIPS_RLD_MAP"; + case DT_MIPS_DELTA_CLASS: + return "MIPS_DELTA_CLASS"; + case DT_MIPS_DELTA_CLASS_NO: + return "MIPS_DELTA_CLASS_NO"; + case DT_MIPS_DELTA_INSTANCE: + return "MIPS_DELTA_INSTANCE"; + case DT_MIPS_DELTA_INSTANCE_NO: + return "MIPS_DELTA_INSTANCE_NO"; + case DT_MIPS_DELTA_RELOC: + return "MIPS_DELTA_RELOC"; + case DT_MIPS_DELTA_RELOC_NO: + return "MIPS_DELTA_RELOC_NO"; + case DT_MIPS_DELTA_SYM: + return "MIPS_DELTA_SYM"; + case DT_MIPS_DELTA_SYM_NO: + return "MIPS_DELTA_SYM_NO"; + case DT_MIPS_DELTA_CLASSSYM: + return "MIPS_DELTA_CLASSSYM"; + case DT_MIPS_DELTA_CLASSSYM_NO: + return "MIPS_DELTA_CLASSSYM_NO"; + case DT_MIPS_CXX_FLAGS: + return "MIPS_CXX_FLAGS"; + case DT_MIPS_PIXIE_INIT: + return "MIPS_PIXIE_INIT"; + case DT_MIPS_SYMBOL_LIB: + return "MIPS_SYMBOL_LIB"; + case DT_MIPS_LOCALPAGE_GOTIDX: + return "MIPS_LOCALPAGE_GOTIDX"; + case DT_MIPS_LOCAL_GOTIDX: + return "MIPS_LOCAL_GOTIDX"; + case DT_MIPS_HIDDEN_GOTIDX: + return "MIPS_HIDDEN_GOTIDX"; + case DT_MIPS_PROTECTED_GOTIDX: + return "MIPS_PROTECTED_GOTIDX"; + case DT_MIPS_OPTIONS: + return "MIPS_OPTIONS"; + case DT_MIPS_INTERFACE: + return "MIPS_INTERFACE"; + case DT_MIPS_DYNSTR_ALIGN: + return "MIPS_DYNSTR_ALIGN"; + case DT_MIPS_INTERFACE_SIZE: + return "MIPS_INTERFACE_SIZE"; + case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: + return "MIPS_RLD_TEXT_RESOLVE_ADDR"; + case DT_MIPS_PERF_SUFFIX: + return "MIPS_PERF_SUFFIX"; + case DT_MIPS_COMPACT_SIZE: + return "MIPS_COMPACT_SIZE"; + case DT_MIPS_GP_VALUE: + return "MIPS_GP_VALUE"; + case DT_MIPS_AUX_DYNAMIC: + return "MIPS_AUX_DYNAMIC"; + case DT_MIPS_PLTGOT: + return "MIPS_PLTGOT"; + case DT_MIPS_RLD_OBJ_UPDATE: + return "MIPS_RLD_OBJ_UPDATE"; + case DT_MIPS_RWPLT: + return "MIPS_RWPLT"; + default: + break; + } + break; + case EM_SPARC: + case EM_SPARC32PLUS: + case EM_SPARCV9: + switch (dtype) { + case DT_SPARC_REGISTER: + return "DT_SPARC_REGISTER"; + default: + break; + } + break; + default: + break; + } + snprintf(s_dtype, sizeof(s_dtype), "", dtype); + return (s_dtype); + } + + switch (dtype) { + case DT_NULL: return "NULL"; + case DT_NEEDED: return "NEEDED"; + case DT_PLTRELSZ: return "PLTRELSZ"; + case DT_PLTGOT: return "PLTGOT"; + case DT_HASH: return "HASH"; + case DT_STRTAB: return "STRTAB"; + case DT_SYMTAB: return "SYMTAB"; + case DT_RELA: return "RELA"; + case DT_RELASZ: return "RELASZ"; + case DT_RELAENT: return "RELAENT"; + case DT_STRSZ: return "STRSZ"; + case DT_SYMENT: return "SYMENT"; + case DT_INIT: return "INIT"; + case DT_FINI: return "FINI"; + case DT_SONAME: return "SONAME"; + case DT_RPATH: return "RPATH"; + case DT_SYMBOLIC: return "SYMBOLIC"; + case DT_REL: return "REL"; + case DT_RELSZ: return "RELSZ"; + case DT_RELENT: return "RELENT"; + case DT_PLTREL: return "PLTREL"; + case DT_DEBUG: return "DEBUG"; + case DT_TEXTREL: return "TEXTREL"; + case DT_JMPREL: return "JMPREL"; + case DT_BIND_NOW: return "BIND_NOW"; + case DT_INIT_ARRAY: return "INIT_ARRAY"; + case DT_FINI_ARRAY: return "FINI_ARRAY"; + case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ"; + case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ"; + case DT_RUNPATH: return "RUNPATH"; + case DT_FLAGS: return "FLAGS"; + case DT_PREINIT_ARRAY: return "PREINIT_ARRAY"; + case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; + case DT_MAXPOSTAGS: return "MAXPOSTAGS"; + case DT_SUNW_AUXILIARY: return "SUNW_AUXILIARY"; + case DT_SUNW_RTLDINF: return "SUNW_RTLDINF"; + case DT_SUNW_FILTER: return "SUNW_FILTER"; + case DT_SUNW_CAP: return "SUNW_CAP"; + case DT_CHECKSUM: return "CHECKSUM"; + case DT_PLTPADSZ: return "PLTPADSZ"; + case DT_MOVEENT: return "MOVEENT"; + case DT_MOVESZ: return "MOVESZ"; + case DT_FEATURE_1: return "FEATURE_1"; + case DT_POSFLAG_1: return "POSFLAG_1"; + case DT_SYMINSZ: return "SYMINSZ"; + case DT_SYMINENT: return "SYMINENT"; + case DT_GNU_HASH: return "GNU_HASH"; + case DT_GNU_CONFLICT: return "GNU_CONFLICT"; + case DT_GNU_LIBLIST: return "GNU_LIBLIST"; + case DT_CONFIG: return "CONFIG"; + case DT_DEPAUDIT: return "DEPAUDIT"; + case DT_AUDIT: return "AUDIT"; + case DT_PLTPAD: return "PLTPAD"; + case DT_MOVETAB: return "MOVETAB"; + case DT_SYMINFO: return "SYMINFO"; + case DT_VERSYM: return "VERSYM"; + case DT_RELACOUNT: return "RELACOUNT"; + case DT_RELCOUNT: return "RELCOUNT"; + case DT_FLAGS_1: return "FLAGS_1"; + case DT_VERDEF: return "VERDEF"; + case DT_VERDEFNUM: return "VERDEFNUM"; + case DT_VERNEED: return "VERNEED"; + case DT_VERNEEDNUM: return "VERNEEDNUM"; + case DT_AUXILIARY: return "AUXILIARY"; + case DT_USED: return "USED"; + case DT_FILTER: return "FILTER"; + case DT_GNU_PRELINKED: return "GNU_PRELINKED"; + case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ"; + case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ"; + default: + snprintf(s_dtype, sizeof(s_dtype), "", dtype); + return (s_dtype); + } +} + +static const char * +st_bind(unsigned int sbind) +{ + static char s_sbind[32]; + + switch (sbind) { + case STB_LOCAL: return "LOCAL"; + case STB_GLOBAL: return "GLOBAL"; + case STB_WEAK: return "WEAK"; + default: + if (sbind >= STB_LOOS && sbind <= STB_HIOS) + return "OS"; + else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC) + return "PROC"; + else + snprintf(s_sbind, sizeof(s_sbind), "", + sbind); + return (s_sbind); + } +} + +static const char * +st_type(unsigned int stype) +{ + static char s_stype[32]; + + switch (stype) { + case STT_NOTYPE: return "NOTYPE"; + case STT_OBJECT: return "OBJECT"; + case STT_FUNC: return "FUNC"; + case STT_SECTION: return "SECTION"; + case STT_FILE: return "FILE"; + case STT_COMMON: return "COMMON"; + case STT_TLS: return "TLS"; + default: + if (stype >= STT_LOOS && stype <= STT_HIOS) + snprintf(s_stype, sizeof(s_stype), "OS+%#x", + stype - STT_LOOS); + else if (stype >= STT_LOPROC && stype <= STT_HIPROC) + snprintf(s_stype, sizeof(s_stype), "PROC+%#x", + stype - STT_LOPROC); + else + snprintf(s_stype, sizeof(s_stype), "", + stype); + return (s_stype); + } +} + +static const char * +st_vis(unsigned int svis) +{ + static char s_svis[32]; + + switch(svis) { + case STV_DEFAULT: return "DEFAULT"; + case STV_INTERNAL: return "INTERNAL"; + case STV_HIDDEN: return "HIDDEN"; + case STV_PROTECTED: return "PROTECTED"; + default: + snprintf(s_svis, sizeof(s_svis), "", svis); + return (s_svis); + } +} + +static const char * +st_shndx(unsigned int shndx) +{ + static char s_shndx[32]; + + switch (shndx) { + case SHN_UNDEF: return "UND"; + case SHN_ABS: return "ABS"; + case SHN_COMMON: return "COM"; + default: + if (shndx >= SHN_LOPROC && shndx <= SHN_HIPROC) + return "PRC"; + else if (shndx >= SHN_LOOS && shndx <= SHN_HIOS) + return "OS"; + else + snprintf(s_shndx, sizeof(s_shndx), "%u", shndx); + return (s_shndx); + } +} + +static struct { + const char *ln; + char sn; + int value; +} section_flag[] = { + {"WRITE", 'W', SHF_WRITE}, + {"ALLOC", 'A', SHF_ALLOC}, + {"EXEC", 'X', SHF_EXECINSTR}, + {"MERGE", 'M', SHF_MERGE}, + {"STRINGS", 'S', SHF_STRINGS}, + {"INFO LINK", 'I', SHF_INFO_LINK}, + {"OS NONCONF", 'O', SHF_OS_NONCONFORMING}, + {"GROUP", 'G', SHF_GROUP}, + {"TLS", 'T', SHF_TLS}, + {NULL, 0, 0} +}; + +static const char * +r_type(unsigned int mach, unsigned int type) +{ + switch(mach) { + case EM_NONE: return ""; + case EM_386: + switch(type) { + case 0: return "R_386_NONE"; + case 1: return "R_386_32"; + case 2: return "R_386_PC32"; + case 3: return "R_386_GOT32"; + case 4: return "R_386_PLT32"; + case 5: return "R_386_COPY"; + case 6: return "R_386_GLOB_DAT"; + case 7: return "R_386_JMP_SLOT"; + case 8: return "R_386_RELATIVE"; + case 9: return "R_386_GOTOFF"; + case 10: return "R_386_GOTPC"; + case 14: return "R_386_TLS_TPOFF"; + case 15: return "R_386_TLS_IE"; + case 16: return "R_386_TLS_GOTIE"; + case 17: return "R_386_TLS_LE"; + case 18: return "R_386_TLS_GD"; + case 19: return "R_386_TLS_LDM"; + case 24: return "R_386_TLS_GD_32"; + case 25: return "R_386_TLS_GD_PUSH"; + case 26: return "R_386_TLS_GD_CALL"; + case 27: return "R_386_TLS_GD_POP"; + case 28: return "R_386_TLS_LDM_32"; + case 29: return "R_386_TLS_LDM_PUSH"; + case 30: return "R_386_TLS_LDM_CALL"; + case 31: return "R_386_TLS_LDM_POP"; + case 32: return "R_386_TLS_LDO_32"; + case 33: return "R_386_TLS_IE_32"; + case 34: return "R_386_TLS_LE_32"; + case 35: return "R_386_TLS_DTPMOD32"; + case 36: return "R_386_TLS_DTPOFF32"; + case 37: return "R_386_TLS_TPOFF32"; + default: return ""; + } + case EM_ARM: + switch(type) { + case 0: return "R_ARM_NONE"; + case 1: return "R_ARM_PC24"; + case 2: return "R_ARM_ABS32"; + case 3: return "R_ARM_REL32"; + case 4: return "R_ARM_PC13"; + case 5: return "R_ARM_ABS16"; + case 6: return "R_ARM_ABS12"; + case 7: return "R_ARM_THM_ABS5"; + case 8: return "R_ARM_ABS8"; + case 9: return "R_ARM_SBREL32"; + case 10: return "R_ARM_THM_PC22"; + case 11: return "R_ARM_THM_PC8"; + case 12: return "R_ARM_AMP_VCALL9"; + case 13: return "R_ARM_SWI24"; + case 14: return "R_ARM_THM_SWI8"; + case 15: return "R_ARM_XPC25"; + case 16: return "R_ARM_THM_XPC22"; + case 20: return "R_ARM_COPY"; + case 21: return "R_ARM_GLOB_DAT"; + case 22: return "R_ARM_JUMP_SLOT"; + case 23: return "R_ARM_RELATIVE"; + case 24: return "R_ARM_GOTOFF"; + case 25: return "R_ARM_GOTPC"; + case 26: return "R_ARM_GOT32"; + case 27: return "R_ARM_PLT32"; + case 100: return "R_ARM_GNU_VTENTRY"; + case 101: return "R_ARM_GNU_VTINHERIT"; + case 250: return "R_ARM_RSBREL32"; + case 251: return "R_ARM_THM_RPC22"; + case 252: return "R_ARM_RREL32"; + case 253: return "R_ARM_RABS32"; + case 254: return "R_ARM_RPC24"; + case 255: return "R_ARM_RBASE"; + default: return ""; + } + case EM_IA_64: + switch(type) { + case 0: return "R_IA_64_NONE"; + case 33: return "R_IA_64_IMM14"; + case 34: return "R_IA_64_IMM22"; + case 35: return "R_IA_64_IMM64"; + case 36: return "R_IA_64_DIR32MSB"; + case 37: return "R_IA_64_DIR32LSB"; + case 38: return "R_IA_64_DIR64MSB"; + case 39: return "R_IA_64_DIR64LSB"; + case 42: return "R_IA_64_GPREL22"; + case 43: return "R_IA_64_GPREL64I"; + case 44: return "R_IA_64_GPREL32MSB"; + case 45: return "R_IA_64_GPREL32LSB"; + case 46: return "R_IA_64_GPREL64MSB"; + case 47: return "R_IA_64_GPREL64LSB"; + case 50: return "R_IA_64_LTOFF22"; + case 51: return "R_IA_64_LTOFF64I"; + case 58: return "R_IA_64_PLTOFF22"; + case 59: return "R_IA_64_PLTOFF64I"; + case 62: return "R_IA_64_PLTOFF64MSB"; + case 63: return "R_IA_64_PLTOFF64LSB"; + case 67: return "R_IA_64_FPTR64I"; + case 68: return "R_IA_64_FPTR32MSB"; + case 69: return "R_IA_64_FPTR32LSB"; + case 70: return "R_IA_64_FPTR64MSB"; + case 71: return "R_IA_64_FPTR64LSB"; + case 72: return "R_IA_64_PCREL60B"; + case 73: return "R_IA_64_PCREL21B"; + case 74: return "R_IA_64_PCREL21M"; + case 75: return "R_IA_64_PCREL21F"; + case 76: return "R_IA_64_PCREL32MSB"; + case 77: return "R_IA_64_PCREL32LSB"; + case 78: return "R_IA_64_PCREL64MSB"; + case 79: return "R_IA_64_PCREL64LSB"; + case 82: return "R_IA_64_LTOFF_FPTR22"; + case 83: return "R_IA_64_LTOFF_FPTR64I"; + case 84: return "R_IA_64_LTOFF_FPTR32MSB"; + case 85: return "R_IA_64_LTOFF_FPTR32LSB"; + case 86: return "R_IA_64_LTOFF_FPTR64MSB"; + case 87: return "R_IA_64_LTOFF_FPTR64LSB"; + case 92: return "R_IA_64_SEGREL32MSB"; + case 93: return "R_IA_64_SEGREL32LSB"; + case 94: return "R_IA_64_SEGREL64MSB"; + case 95: return "R_IA_64_SEGREL64LSB"; + case 100: return "R_IA_64_SECREL32MSB"; + case 101: return "R_IA_64_SECREL32LSB"; + case 102: return "R_IA_64_SECREL64MSB"; + case 103: return "R_IA_64_SECREL64LSB"; + case 108: return "R_IA_64_REL32MSB"; + case 109: return "R_IA_64_REL32LSB"; + case 110: return "R_IA_64_REL64MSB"; + case 111: return "R_IA_64_REL64LSB"; + case 116: return "R_IA_64_LTV32MSB"; + case 117: return "R_IA_64_LTV32LSB"; + case 118: return "R_IA_64_LTV64MSB"; + case 119: return "R_IA_64_LTV64LSB"; + case 121: return "R_IA_64_PCREL21BI"; + case 122: return "R_IA_64_PCREL22"; + case 123: return "R_IA_64_PCREL64I"; + case 128: return "R_IA_64_IPLTMSB"; + case 129: return "R_IA_64_IPLTLSB"; + case 133: return "R_IA_64_SUB"; + case 134: return "R_IA_64_LTOFF22X"; + case 135: return "R_IA_64_LDXMOV"; + case 145: return "R_IA_64_TPREL14"; + case 146: return "R_IA_64_TPREL22"; + case 147: return "R_IA_64_TPREL64I"; + case 150: return "R_IA_64_TPREL64MSB"; + case 151: return "R_IA_64_TPREL64LSB"; + case 154: return "R_IA_64_LTOFF_TPREL22"; + case 166: return "R_IA_64_DTPMOD64MSB"; + case 167: return "R_IA_64_DTPMOD64LSB"; + case 170: return "R_IA_64_LTOFF_DTPMOD22"; + case 177: return "R_IA_64_DTPREL14"; + case 178: return "R_IA_64_DTPREL22"; + case 179: return "R_IA_64_DTPREL64I"; + case 180: return "R_IA_64_DTPREL32MSB"; + case 181: return "R_IA_64_DTPREL32LSB"; + case 182: return "R_IA_64_DTPREL64MSB"; + case 183: return "R_IA_64_DTPREL64LSB"; + case 186: return "R_IA_64_LTOFF_DTPREL22"; + default: return ""; + } + case EM_MIPS: + switch(type) { + case 0: return "R_MIPS_NONE"; + case 1: return "R_MIPS_16"; + case 2: return "R_MIPS_32"; + case 3: return "R_MIPS_REL32"; + case 4: return "R_MIPS_26"; + case 5: return "R_MIPS_HI16"; + case 6: return "R_MIPS_LO16"; + case 7: return "R_MIPS_GPREL16"; + case 8: return "R_MIPS_LITERAL"; + case 9: return "R_MIPS_GOT16"; + case 10: return "R_MIPS_PC16"; + case 11: return "R_MIPS_CALL16"; + case 12: return "R_MIPS_GPREL32"; + case 21: return "R_MIPS_GOTHI16"; + case 22: return "R_MIPS_GOTLO16"; + case 30: return "R_MIPS_CALLHI16"; + case 31: return "R_MIPS_CALLLO16"; + default: return ""; + } + case EM_PPC: + switch(type) { + case 0: return "R_PPC_NONE"; + case 1: return "R_PPC_ADDR32"; + case 2: return "R_PPC_ADDR24"; + case 3: return "R_PPC_ADDR16"; + case 4: return "R_PPC_ADDR16_LO"; + case 5: return "R_PPC_ADDR16_HI"; + case 6: return "R_PPC_ADDR16_HA"; + case 7: return "R_PPC_ADDR14"; + case 8: return "R_PPC_ADDR14_BRTAKEN"; + case 9: return "R_PPC_ADDR14_BRNTAKEN"; + case 10: return "R_PPC_REL24"; + case 11: return "R_PPC_REL14"; + case 12: return "R_PPC_REL14_BRTAKEN"; + case 13: return "R_PPC_REL14_BRNTAKEN"; + case 14: return "R_PPC_GOT16"; + case 15: return "R_PPC_GOT16_LO"; + case 16: return "R_PPC_GOT16_HI"; + case 17: return "R_PPC_GOT16_HA"; + case 18: return "R_PPC_PLTREL24"; + case 19: return "R_PPC_COPY"; + case 20: return "R_PPC_GLOB_DAT"; + case 21: return "R_PPC_JMP_SLOT"; + case 22: return "R_PPC_RELATIVE"; + case 23: return "R_PPC_LOCAL24PC"; + case 24: return "R_PPC_UADDR32"; + case 25: return "R_PPC_UADDR16"; + case 26: return "R_PPC_REL32"; + case 27: return "R_PPC_PLT32"; + case 28: return "R_PPC_PLTREL32"; + case 29: return "R_PPC_PLT16_LO"; + case 30: return "R_PPC_PLT16_HI"; + case 31: return "R_PPC_PLT16_HA"; + case 32: return "R_PPC_SDAREL16"; + case 33: return "R_PPC_SECTOFF"; + case 34: return "R_PPC_SECTOFF_LO"; + case 35: return "R_PPC_SECTOFF_HI"; + case 36: return "R_PPC_SECTOFF_HA"; + case 67: return "R_PPC_TLS"; + case 68: return "R_PPC_DTPMOD32"; + case 69: return "R_PPC_TPREL16"; + case 70: return "R_PPC_TPREL16_LO"; + case 71: return "R_PPC_TPREL16_HI"; + case 72: return "R_PPC_TPREL16_HA"; + case 73: return "R_PPC_TPREL32"; + case 74: return "R_PPC_DTPREL16"; + case 75: return "R_PPC_DTPREL16_LO"; + case 76: return "R_PPC_DTPREL16_HI"; + case 77: return "R_PPC_DTPREL16_HA"; + case 78: return "R_PPC_DTPREL32"; + case 79: return "R_PPC_GOT_TLSGD16"; + case 80: return "R_PPC_GOT_TLSGD16_LO"; + case 81: return "R_PPC_GOT_TLSGD16_HI"; + case 82: return "R_PPC_GOT_TLSGD16_HA"; + case 83: return "R_PPC_GOT_TLSLD16"; + case 84: return "R_PPC_GOT_TLSLD16_LO"; + case 85: return "R_PPC_GOT_TLSLD16_HI"; + case 86: return "R_PPC_GOT_TLSLD16_HA"; + case 87: return "R_PPC_GOT_TPREL16"; + case 88: return "R_PPC_GOT_TPREL16_LO"; + case 89: return "R_PPC_GOT_TPREL16_HI"; + case 90: return "R_PPC_GOT_TPREL16_HA"; + case 101: return "R_PPC_EMB_NADDR32"; + case 102: return "R_PPC_EMB_NADDR16"; + case 103: return "R_PPC_EMB_NADDR16_LO"; + case 104: return "R_PPC_EMB_NADDR16_HI"; + case 105: return "R_PPC_EMB_NADDR16_HA"; + case 106: return "R_PPC_EMB_SDAI16"; + case 107: return "R_PPC_EMB_SDA2I16"; + case 108: return "R_PPC_EMB_SDA2REL"; + case 109: return "R_PPC_EMB_SDA21"; + case 110: return "R_PPC_EMB_MRKREF"; + case 111: return "R_PPC_EMB_RELSEC16"; + case 112: return "R_PPC_EMB_RELST_LO"; + case 113: return "R_PPC_EMB_RELST_HI"; + case 114: return "R_PPC_EMB_RELST_HA"; + case 115: return "R_PPC_EMB_BIT_FLD"; + case 116: return "R_PPC_EMB_RELSDA"; + default: return ""; + } + case EM_SPARC: + case EM_SPARCV9: + switch(type) { + case 0: return "R_SPARC_NONE"; + case 1: return "R_SPARC_8"; + case 2: return "R_SPARC_16"; + case 3: return "R_SPARC_32"; + case 4: return "R_SPARC_DISP8"; + case 5: return "R_SPARC_DISP16"; + case 6: return "R_SPARC_DISP32"; + case 7: return "R_SPARC_WDISP30"; + case 8: return "R_SPARC_WDISP22"; + case 9: return "R_SPARC_HI22"; + case 10: return "R_SPARC_22"; + case 11: return "R_SPARC_13"; + case 12: return "R_SPARC_LO10"; + case 13: return "R_SPARC_GOT10"; + case 14: return "R_SPARC_GOT13"; + case 15: return "R_SPARC_GOT22"; + case 16: return "R_SPARC_PC10"; + case 17: return "R_SPARC_PC22"; + case 18: return "R_SPARC_WPLT30"; + case 19: return "R_SPARC_COPY"; + case 20: return "R_SPARC_GLOB_DAT"; + case 21: return "R_SPARC_JMP_SLOT"; + case 22: return "R_SPARC_RELATIVE"; + case 23: return "R_SPARC_UA32"; + case 24: return "R_SPARC_PLT32"; + case 25: return "R_SPARC_HIPLT22"; + case 26: return "R_SPARC_LOPLT10"; + case 27: return "R_SPARC_PCPLT32"; + case 28: return "R_SPARC_PCPLT22"; + case 29: return "R_SPARC_PCPLT10"; + case 30: return "R_SPARC_10"; + case 31: return "R_SPARC_11"; + case 32: return "R_SPARC_64"; + case 33: return "R_SPARC_OLO10"; + case 34: return "R_SPARC_HH22"; + case 35: return "R_SPARC_HM10"; + case 36: return "R_SPARC_LM22"; + case 37: return "R_SPARC_PC_HH22"; + case 38: return "R_SPARC_PC_HM10"; + case 39: return "R_SPARC_PC_LM22"; + case 40: return "R_SPARC_WDISP16"; + case 41: return "R_SPARC_WDISP19"; + case 42: return "R_SPARC_GLOB_JMP"; + case 43: return "R_SPARC_7"; + case 44: return "R_SPARC_5"; + case 45: return "R_SPARC_6"; + case 46: return "R_SPARC_DISP64"; + case 47: return "R_SPARC_PLT64"; + case 48: return "R_SPARC_HIX22"; + case 49: return "R_SPARC_LOX10"; + case 50: return "R_SPARC_H44"; + case 51: return "R_SPARC_M44"; + case 52: return "R_SPARC_L44"; + case 53: return "R_SPARC_REGISTER"; + case 54: return "R_SPARC_UA64"; + case 55: return "R_SPARC_UA16"; + case 56: return "R_SPARC_TLS_GD_HI22"; + case 57: return "R_SPARC_TLS_GD_LO10"; + case 58: return "R_SPARC_TLS_GD_ADD"; + case 59: return "R_SPARC_TLS_GD_CALL"; + case 60: return "R_SPARC_TLS_LDM_HI22"; + case 61: return "R_SPARC_TLS_LDM_LO10"; + case 62: return "R_SPARC_TLS_LDM_ADD"; + case 63: return "R_SPARC_TLS_LDM_CALL"; + case 64: return "R_SPARC_TLS_LDO_HIX22"; + case 65: return "R_SPARC_TLS_LDO_LOX10"; + case 66: return "R_SPARC_TLS_LDO_ADD"; + case 67: return "R_SPARC_TLS_IE_HI22"; + case 68: return "R_SPARC_TLS_IE_LO10"; + case 69: return "R_SPARC_TLS_IE_LD"; + case 70: return "R_SPARC_TLS_IE_LDX"; + case 71: return "R_SPARC_TLS_IE_ADD"; + case 72: return "R_SPARC_TLS_LE_HIX22"; + case 73: return "R_SPARC_TLS_LE_LOX10"; + case 74: return "R_SPARC_TLS_DTPMOD32"; + case 75: return "R_SPARC_TLS_DTPMOD64"; + case 76: return "R_SPARC_TLS_DTPOFF32"; + case 77: return "R_SPARC_TLS_DTPOFF64"; + case 78: return "R_SPARC_TLS_TPOFF32"; + case 79: return "R_SPARC_TLS_TPOFF64"; + default: return ""; + } + case EM_X86_64: + switch(type) { + case 0: return "R_X86_64_NONE"; + case 1: return "R_X86_64_64"; + case 2: return "R_X86_64_PC32"; + case 3: return "R_X86_64_GOT32"; + case 4: return "R_X86_64_PLT32"; + case 5: return "R_X86_64_COPY"; + case 6: return "R_X86_64_GLOB_DAT"; + case 7: return "R_X86_64_JMP_SLOT"; + case 8: return "R_X86_64_RELATIVE"; + case 9: return "R_X86_64_GOTPCREL"; + case 10: return "R_X86_64_32"; + case 11: return "R_X86_64_32S"; + case 12: return "R_X86_64_16"; + case 13: return "R_X86_64_PC16"; + case 14: return "R_X86_64_8"; + case 15: return "R_X86_64_PC8"; + case 16: return "R_X86_64_DTPMOD64"; + case 17: return "R_X86_64_DTPOFF64"; + case 18: return "R_X86_64_TPOFF64"; + case 19: return "R_X86_64_TLSGD"; + case 20: return "R_X86_64_TLSLD"; + case 21: return "R_X86_64_DTPOFF32"; + case 22: return "R_X86_64_GOTTPOFF"; + case 23: return "R_X86_64_TPOFF32"; + default: return ""; + } + default: return ""; + } +} + +static const char * +note_type(unsigned int osabi, unsigned int et, unsigned int nt) +{ + static char s_nt[32]; + + if (et == ET_CORE) { + switch (nt) { + case NT_PRSTATUS: + return "NT_PRSTATUS (Process status)"; + case NT_FPREGSET: + return "NT_FPREGSET (Floating point information)"; + case NT_PRPSINFO: + return "NT_PRPSINFO (Process information)"; + case NT_AUXV: + return "NT_AUXV (Auxiliary vector)"; + case NT_PRXFPREG: + return "NT_PRXFPREG (Linux user_xfpregs structure)"; + case NT_PSTATUS: + return "NT_PSTATUS (Linux process status)"; + case NT_FPREGS: + return "NT_FPREGS (Linux floating point regset)"; + case NT_PSINFO: + return "NT_PSINFO (Linux process information)"; + case NT_LWPSTATUS: + return "NT_LWPSTATUS (Linux lwpstatus_t type)"; + case NT_LWPSINFO: + return "NT_LWPSINFO (Linux lwpinfo_t type)"; + default: + snprintf(s_nt, sizeof(s_nt), "", nt); + return (s_nt); + } + } else { + switch (nt) { + case NT_ABI_TAG: + switch (osabi) { + case ELFOSABI_FREEBSD: + return "NT_FREEBSD_ABI_TAG"; + case ELFOSABI_NETBSD: + return "NT_NETBSD_IDENT"; + case ELFOSABI_OPENBSD: + return "NT_OPENBSD_IDENT"; + default: + return "NT_GNU_ABI_TAG"; + } + case NT_GNU_HWCAP: + return "NT_GNU_HWCAP (Hardware capabilities)"; + case NT_GNU_BUILD_ID: + return "NT_GNU_BUILD_ID (Build id set by ld(1))"; + case NT_GNU_GOLD_VERSION: + return "NT_GNU_GOLD_VERSION (GNU gold version)"; + default: + snprintf(s_nt, sizeof(s_nt), "", nt); + return (s_nt); + } + } +} + +static struct { + const char *name; + int value; +} l_flag[] = { + {"EXACT_MATCH", LL_EXACT_MATCH}, + {"IGNORE_INT_VER", LL_IGNORE_INT_VER}, + {"REQUIRE_MINOR", LL_REQUIRE_MINOR}, + {"EXPORTS", LL_EXPORTS}, + {"DELAY_LOAD", LL_DELAY_LOAD}, + {"DELTA", LL_DELTA}, + {NULL, 0} +}; + +static struct mips_option mips_exceptions_option[] = { + {OEX_PAGE0, "PAGE0"}, + {OEX_SMM, "SMM"}, + {OEX_PRECISEFP, "PRECISEFP"}, + {OEX_DISMISS, "DISMISS"}, + {0, NULL} +}; + +static struct mips_option mips_pad_option[] = { + {OPAD_PREFIX, "PREFIX"}, + {OPAD_POSTFIX, "POSTFIX"}, + {OPAD_SYMBOL, "SYMBOL"}, + {0, NULL} +}; + +static struct mips_option mips_hwpatch_option[] = { + {OHW_R4KEOP, "R4KEOP"}, + {OHW_R8KPFETCH, "R8KPFETCH"}, + {OHW_R5KEOP, "R5KEOP"}, + {OHW_R5KCVTL, "R5KCVTL"}, + {0, NULL} +}; + +static struct mips_option mips_hwa_option[] = { + {OHWA0_R4KEOP_CHECKED, "R4KEOP_CHECKED"}, + {OHWA0_R4KEOP_CLEAN, "R4KEOP_CLEAN"}, + {0, NULL} +}; + +static struct mips_option mips_hwo_option[] = { + {OHWO0_FIXADE, "FIXADE"}, + {0, NULL} +}; + +static const char * +option_kind(uint8_t kind) +{ + static char s_kind[32]; + + switch (kind) { + case ODK_NULL: return "NULL"; + case ODK_REGINFO: return "REGINFO"; + case ODK_EXCEPTIONS: return "EXCEPTIONS"; + case ODK_PAD: return "PAD"; + case ODK_HWPATCH: return "HWPATCH"; + case ODK_FILL: return "FILL"; + case ODK_TAGS: return "TAGS"; + case ODK_HWAND: return "HWAND"; + case ODK_HWOR: return "HWOR"; + case ODK_GP_GROUP: return "GP_GROUP"; + case ODK_IDENT: return "IDENT"; + default: + snprintf(s_kind, sizeof(s_kind), "", kind); + return (s_kind); + } +} + +static const char * +top_tag(unsigned int tag) +{ + static char s_top_tag[32]; + + switch (tag) { + case 1: return "File Attributes"; + case 2: return "Section Attributes"; + case 3: return "Symbol Attributes"; + default: + snprintf(s_top_tag, sizeof(s_top_tag), "Unknown tag: %u", tag); + return (s_top_tag); + } +} + +static const char * +aeabi_cpu_arch(uint64_t arch) +{ + static char s_cpu_arch[32]; + + switch (arch) { + case 0: return "Pre-V4"; + case 1: return "ARM v4"; + case 2: return "ARM v4T"; + case 3: return "ARM v5T"; + case 4: return "ARM v5TE"; + case 5: return "ARM v5TEJ"; + case 6: return "ARM v6"; + case 7: return "ARM v6KZ"; + case 8: return "ARM v6T2"; + case 9: return "ARM v6K"; + case 10: return "ARM v7"; + case 11: return "ARM v6-M"; + case 12: return "ARM v6S-M"; + case 13: return "ARM v7E-M"; + default: + snprintf(s_cpu_arch, sizeof(s_cpu_arch), + "Unknown (%ju)", (uintmax_t) arch); + return (s_cpu_arch); + } +} + +static const char * +aeabi_cpu_arch_profile(uint64_t pf) +{ + static char s_arch_profile[32]; + + switch (pf) { + case 0: + return "Not applicable"; + case 0x41: /* 'A' */ + return "Application Profile"; + case 0x52: /* 'R' */ + return "Real-Time Profile"; + case 0x4D: /* 'M' */ + return "Microcontroller Profile"; + case 0x53: /* 'S' */ + return "Application or Real-Time Profile"; + default: + snprintf(s_arch_profile, sizeof(s_arch_profile), + "Unknown (%ju)\n", (uintmax_t) pf); + return (s_arch_profile); + } +} + +static const char * +aeabi_arm_isa(uint64_t ai) +{ + static char s_ai[32]; + + switch (ai) { + case 0: return "No"; + case 1: return "Yes"; + default: + snprintf(s_ai, sizeof(s_ai), "Unknown (%ju)\n", + (uintmax_t) ai); + return (s_ai); + } +} + +static const char * +aeabi_thumb_isa(uint64_t ti) +{ + static char s_ti[32]; + + switch (ti) { + case 0: return "No"; + case 1: return "16-bit Thumb"; + case 2: return "32-bit Thumb"; + default: + snprintf(s_ti, sizeof(s_ti), "Unknown (%ju)\n", + (uintmax_t) ti); + return (s_ti); + } +} + +static const char * +aeabi_fp_arch(uint64_t fp) +{ + static char s_fp_arch[32]; + + switch (fp) { + case 0: return "No"; + case 1: return "VFPv1"; + case 2: return "VFPv2"; + case 3: return "VFPv3"; + case 4: return "VFPv3-D16"; + case 5: return "VFPv4"; + case 6: return "VFPv4-D16"; + default: + snprintf(s_fp_arch, sizeof(s_fp_arch), "Unknown (%ju)", + (uintmax_t) fp); + return (s_fp_arch); + } +} + +static const char * +aeabi_wmmx_arch(uint64_t wmmx) +{ + static char s_wmmx[32]; + + switch (wmmx) { + case 0: return "No"; + case 1: return "WMMXv1"; + case 2: return "WMMXv2"; + default: + snprintf(s_wmmx, sizeof(s_wmmx), "Unknown (%ju)", + (uintmax_t) wmmx); + return (s_wmmx); + } +} + +static const char * +aeabi_adv_simd_arch(uint64_t simd) +{ + static char s_simd[32]; + + switch (simd) { + case 0: return "No"; + case 1: return "NEONv1"; + case 2: return "NEONv2"; + default: + snprintf(s_simd, sizeof(s_simd), "Unknown (%ju)", + (uintmax_t) simd); + return (s_simd); + } +} + +static const char * +aeabi_pcs_config(uint64_t pcs) +{ + static char s_pcs[32]; + + switch (pcs) { + case 0: return "None"; + case 1: return "Bare platform"; + case 2: return "Linux"; + case 3: return "Linux DSO"; + case 4: return "Palm OS 2004"; + case 5: return "Palm OS (future)"; + case 6: return "Symbian OS 2004"; + case 7: return "Symbian OS (future)"; + default: + snprintf(s_pcs, sizeof(s_pcs), "Unknown (%ju)", + (uintmax_t) pcs); + return (s_pcs); + } +} + +static const char * +aeabi_pcs_r9(uint64_t r9) +{ + static char s_r9[32]; + + switch (r9) { + case 0: return "V6"; + case 1: return "SB"; + case 2: return "TLS pointer"; + case 3: return "Unused"; + default: + snprintf(s_r9, sizeof(s_r9), "Unknown (%ju)", (uintmax_t) r9); + return (s_r9); + } +} + +static const char * +aeabi_pcs_rw(uint64_t rw) +{ + static char s_rw[32]; + + switch (rw) { + case 0: return "Absolute"; + case 1: return "PC-relative"; + case 2: return "SB-relative"; + case 3: return "None"; + default: + snprintf(s_rw, sizeof(s_rw), "Unknown (%ju)", (uintmax_t) rw); + return (s_rw); + } +} + +static const char * +aeabi_pcs_ro(uint64_t ro) +{ + static char s_ro[32]; + + switch (ro) { + case 0: return "Absolute"; + case 1: return "PC-relative"; + case 2: return "None"; + default: + snprintf(s_ro, sizeof(s_ro), "Unknown (%ju)", (uintmax_t) ro); + return (s_ro); + } +} + +static const char * +aeabi_pcs_got(uint64_t got) +{ + static char s_got[32]; + + switch (got) { + case 0: return "None"; + case 1: return "direct"; + case 2: return "indirect via GOT"; + default: + snprintf(s_got, sizeof(s_got), "Unknown (%ju)", + (uintmax_t) got); + return (s_got); + } +} + +static const char * +aeabi_pcs_wchar_t(uint64_t wt) +{ + static char s_wt[32]; + + switch (wt) { + case 0: return "None"; + case 2: return "wchar_t size 2"; + case 4: return "wchar_t size 4"; + default: + snprintf(s_wt, sizeof(s_wt), "Unknown (%ju)", (uintmax_t) wt); + return (s_wt); + } +} + +static const char * +aeabi_enum_size(uint64_t es) +{ + static char s_es[32]; + + switch (es) { + case 0: return "None"; + case 1: return "smallest"; + case 2: return "32-bit"; + case 3: return "visible 32-bit"; + default: + snprintf(s_es, sizeof(s_es), "Unknown (%ju)", (uintmax_t) es); + return (s_es); + } +} + +static const char * +aeabi_align_needed(uint64_t an) +{ + static char s_align_n[64]; + + switch (an) { + case 0: return "No"; + case 1: return "8-byte align"; + case 2: return "4-byte align"; + case 3: return "Reserved"; + default: + if (an >= 4 && an <= 12) + snprintf(s_align_n, sizeof(s_align_n), "8-byte align" + " and up to 2^%ju-byte extended align", + (uintmax_t) an); + else + snprintf(s_align_n, sizeof(s_align_n), "Unknown (%ju)", + (uintmax_t) an); + return (s_align_n); + } +} + +static const char * +aeabi_align_preserved(uint64_t ap) +{ + static char s_align_p[128]; + + switch (ap) { + case 0: return "No"; + case 1: return "8-byte align"; + case 2: return "8-byte align and SP % 8 == 0"; + case 3: return "Reserved"; + default: + if (ap >= 4 && ap <= 12) + snprintf(s_align_p, sizeof(s_align_p), "8-byte align" + " and SP %% 8 == 0 and up to 2^%ju-byte extended" + " align", (uintmax_t) ap); + else + snprintf(s_align_p, sizeof(s_align_p), "Unknown (%ju)", + (uintmax_t) ap); + return (s_align_p); + } +} + +static const char * +aeabi_fp_rounding(uint64_t fr) +{ + static char s_fp_r[32]; + + switch (fr) { + case 0: return "Unused"; + case 1: return "Needed"; + default: + snprintf(s_fp_r, sizeof(s_fp_r), "Unknown (%ju)", + (uintmax_t) fr); + return (s_fp_r); + } +} + +static const char * +aeabi_fp_denormal(uint64_t fd) +{ + static char s_fp_d[32]; + + switch (fd) { + case 0: return "Unused"; + case 1: return "Needed"; + case 2: return "Sign Only"; + default: + snprintf(s_fp_d, sizeof(s_fp_d), "Unknown (%ju)", + (uintmax_t) fd); + return (s_fp_d); + } +} + +static const char * +aeabi_fp_exceptions(uint64_t fe) +{ + static char s_fp_e[32]; + + switch (fe) { + case 0: return "Unused"; + case 1: return "Needed"; + default: + snprintf(s_fp_e, sizeof(s_fp_e), "Unknown (%ju)", + (uintmax_t) fe); + return (s_fp_e); + } +} + +static const char * +aeabi_fp_user_exceptions(uint64_t fu) +{ + static char s_fp_u[32]; + + switch (fu) { + case 0: return "Unused"; + case 1: return "Needed"; + default: + snprintf(s_fp_u, sizeof(s_fp_u), "Unknown (%ju)", + (uintmax_t) fu); + return (s_fp_u); + } +} + +static const char * +aeabi_fp_number_model(uint64_t fn) +{ + static char s_fp_n[32]; + + switch (fn) { + case 0: return "Unused"; + case 1: return "IEEE 754 normal"; + case 2: return "RTABI"; + case 3: return "IEEE 754"; + default: + snprintf(s_fp_n, sizeof(s_fp_n), "Unknown (%ju)", + (uintmax_t) fn); + return (s_fp_n); + } +} + +static const char * +aeabi_fp_16bit_format(uint64_t fp16) +{ + static char s_fp_16[64]; + + switch (fp16) { + case 0: return "None"; + case 1: return "IEEE 754"; + case 2: return "VFPv3/Advanced SIMD (alternative format)"; + default: + snprintf(s_fp_16, sizeof(s_fp_16), "Unknown (%ju)", + (uintmax_t) fp16); + return (s_fp_16); + } +} + +static const char * +aeabi_mpext(uint64_t mp) +{ + static char s_mp[32]; + + switch (mp) { + case 0: return "Not allowed"; + case 1: return "Allowed"; + default: + snprintf(s_mp, sizeof(s_mp), "Unknown (%ju)", + (uintmax_t) mp); + return (s_mp); + } +} + +static const char * +aeabi_div(uint64_t du) +{ + static char s_du[32]; + + switch (du) { + case 0: return "Yes (V7-R/V7-M)"; + case 1: return "No"; + case 2: return "Yes (V7-A)"; + default: + snprintf(s_du, sizeof(s_du), "Unknown (%ju)", + (uintmax_t) du); + return (s_du); + } +} + +static const char * +aeabi_t2ee(uint64_t t2ee) +{ + static char s_t2ee[32]; + + switch (t2ee) { + case 0: return "Not allowed"; + case 1: return "Allowed"; + default: + snprintf(s_t2ee, sizeof(s_t2ee), "Unknown(%ju)", + (uintmax_t) t2ee); + return (s_t2ee); + } + +} + +static const char * +aeabi_hardfp(uint64_t hfp) +{ + static char s_hfp[32]; + + switch (hfp) { + case 0: return "Tag_FP_arch"; + case 1: return "only SP"; + case 2: return "only DP"; + case 3: return "both SP and DP"; + default: + snprintf(s_hfp, sizeof(s_hfp), "Unknown (%ju)", + (uintmax_t) hfp); + return (s_hfp); + } +} + +static const char * +aeabi_vfp_args(uint64_t va) +{ + static char s_va[32]; + + switch (va) { + case 0: return "AAPCS (base variant)"; + case 1: return "AAPCS (VFP variant)"; + case 2: return "toolchain-specific"; + default: + snprintf(s_va, sizeof(s_va), "Unknown (%ju)", (uintmax_t) va); + return (s_va); + } +} + +static const char * +aeabi_wmmx_args(uint64_t wa) +{ + static char s_wa[32]; + + switch (wa) { + case 0: return "AAPCS (base variant)"; + case 1: return "Intel WMMX"; + case 2: return "toolchain-specific"; + default: + snprintf(s_wa, sizeof(s_wa), "Unknown(%ju)", (uintmax_t) wa); + return (s_wa); + } +} + +static const char * +aeabi_unaligned_access(uint64_t ua) +{ + static char s_ua[32]; + + switch (ua) { + case 0: return "Not allowed"; + case 1: return "Allowed"; + default: + snprintf(s_ua, sizeof(s_ua), "Unknown(%ju)", (uintmax_t) ua); + return (s_ua); + } +} + +static const char * +aeabi_fp_hpext(uint64_t fh) +{ + static char s_fh[32]; + + switch (fh) { + case 0: return "Not allowed"; + case 1: return "Allowed"; + default: + snprintf(s_fh, sizeof(s_fh), "Unknown(%ju)", (uintmax_t) fh); + return (s_fh); + } +} + +static const char * +aeabi_optm_goal(uint64_t og) +{ + static char s_og[32]; + + switch (og) { + case 0: return "None"; + case 1: return "Speed"; + case 2: return "Speed aggressive"; + case 3: return "Space"; + case 4: return "Space aggressive"; + case 5: return "Debugging"; + case 6: return "Best Debugging"; + default: + snprintf(s_og, sizeof(s_og), "Unknown(%ju)", (uintmax_t) og); + return (s_og); + } +} + +static const char * +aeabi_fp_optm_goal(uint64_t fog) +{ + static char s_fog[32]; + + switch (fog) { + case 0: return "None"; + case 1: return "Speed"; + case 2: return "Speed aggressive"; + case 3: return "Space"; + case 4: return "Space aggressive"; + case 5: return "Accurary"; + case 6: return "Best Accurary"; + default: + snprintf(s_fog, sizeof(s_fog), "Unknown(%ju)", + (uintmax_t) fog); + return (s_fog); + } +} + +static const char * +aeabi_virtual(uint64_t vt) +{ + static char s_virtual[64]; + + switch (vt) { + case 0: return "No"; + case 1: return "TrustZone"; + case 2: return "Virtualization extension"; + case 3: return "TrustZone and virtualization extension"; + default: + snprintf(s_virtual, sizeof(s_virtual), "Unknown(%ju)", + (uintmax_t) vt); + return (s_virtual); + } +} + +static struct { + uint64_t tag; + const char *s_tag; + const char *(*get_desc)(uint64_t val); +} aeabi_tags[] = { + {4, "Tag_CPU_raw_name", NULL}, + {5, "Tag_CPU_name", NULL}, + {6, "Tag_CPU_arch", aeabi_cpu_arch}, + {7, "Tag_CPU_arch_profile", aeabi_cpu_arch_profile}, + {8, "Tag_ARM_ISA_use", aeabi_arm_isa}, + {9, "Tag_THUMB_ISA_use", aeabi_thumb_isa}, + {10, "Tag_FP_arch", aeabi_fp_arch}, + {11, "Tag_WMMX_arch", aeabi_wmmx_arch}, + {12, "Tag_Advanced_SIMD_arch", aeabi_adv_simd_arch}, + {13, "Tag_PCS_config", aeabi_pcs_config}, + {14, "Tag_ABI_PCS_R9_use", aeabi_pcs_r9}, + {15, "Tag_ABI_PCS_RW_data", aeabi_pcs_rw}, + {16, "Tag_ABI_PCS_RO_data", aeabi_pcs_ro}, + {17, "Tag_ABI_PCS_GOT_use", aeabi_pcs_got}, + {18, "Tag_ABI_PCS_wchar_t", aeabi_pcs_wchar_t}, + {19, "Tag_ABI_FP_rounding", aeabi_fp_rounding}, + {20, "Tag_ABI_FP_denormal", aeabi_fp_denormal}, + {21, "Tag_ABI_FP_exceptions", aeabi_fp_exceptions}, + {22, "Tag_ABI_FP_user_exceptions", aeabi_fp_user_exceptions}, + {23, "Tag_ABI_FP_number_model", aeabi_fp_number_model}, + {24, "Tag_ABI_align_needed", aeabi_align_needed}, + {25, "Tag_ABI_align_preserved", aeabi_align_preserved}, + {26, "Tag_ABI_enum_size", aeabi_enum_size}, + {27, "Tag_ABI_HardFP_use", aeabi_hardfp}, + {28, "Tag_ABI_VFP_args", aeabi_vfp_args}, + {29, "Tag_ABI_WMMX_args", aeabi_wmmx_args}, + {30, "Tag_ABI_optimization_goals", aeabi_optm_goal}, + {31, "Tag_ABI_FP_optimization_goals", aeabi_fp_optm_goal}, + {32, "Tag_compatibility", NULL}, + {34, "Tag_CPU_unaligned_access", aeabi_unaligned_access}, + {36, "Tag_FP_HP_extension", aeabi_fp_hpext}, + {38, "Tag_ABI_FP_16bit_format", aeabi_fp_16bit_format}, + {42, "Tag_MPextension_use", aeabi_mpext}, + {44, "Tag_DIV_use", aeabi_div}, + {64, "Tag_nodefaults", NULL}, + {65, "Tag_also_compatible_with", NULL}, + {66, "Tag_T2EE_use", aeabi_t2ee}, + {67, "Tag_conformance", NULL}, + {68, "Tag_Virtualization_use", aeabi_virtual}, + {70, "Tag_MPextension_use", aeabi_mpext}, +}; + +static const char * +mips_abi_fp(uint64_t fp) +{ + static char s_mips_abi_fp[64]; + + switch (fp) { + case 0: return "N/A"; + case 1: return "Hard float (double precision)"; + case 2: return "Hard float (single precision)"; + case 3: return "Soft float"; + case 4: return "64-bit float (-mips32r2 -mfp64)"; + default: + snprintf(s_mips_abi_fp, sizeof(s_mips_abi_fp), "Unknown(%ju)", + (uintmax_t) fp); + return (s_mips_abi_fp); + } +} + +static const char * +ppc_abi_fp(uint64_t fp) +{ + static char s_ppc_abi_fp[64]; + + switch (fp) { + case 0: return "N/A"; + case 1: return "Hard float (double precision)"; + case 2: return "Soft float"; + case 3: return "Hard float (single precision)"; + default: + snprintf(s_ppc_abi_fp, sizeof(s_ppc_abi_fp), "Unknown(%ju)", + (uintmax_t) fp); + return (s_ppc_abi_fp); + } +} + +static const char * +ppc_abi_vector(uint64_t vec) +{ + static char s_vec[64]; + + switch (vec) { + case 0: return "N/A"; + case 1: return "Generic purpose registers"; + case 2: return "AltiVec registers"; + case 3: return "SPE registers"; + default: + snprintf(s_vec, sizeof(s_vec), "Unknown(%ju)", (uintmax_t) vec); + return (s_vec); + } +} + +static void +dump_ehdr(struct readelf *re) +{ + size_t shnum, shstrndx; + int i; + + printf("ELF Header:\n"); + + /* e_ident[]. */ + printf(" Magic: "); + for (i = 0; i < EI_NIDENT; i++) + printf("%.2x ", re->ehdr.e_ident[i]); + putchar('\n'); + + /* EI_CLASS. */ + printf("%-37s%s\n", " Class:", elf_class(re->ehdr.e_ident[EI_CLASS])); + + /* EI_DATA. */ + printf("%-37s%s\n", " Data:", elf_endian(re->ehdr.e_ident[EI_DATA])); + + /* EI_VERSION. */ + printf("%-37s%d %s\n", " Version:", re->ehdr.e_ident[EI_VERSION], + elf_ver(re->ehdr.e_ident[EI_VERSION])); + + /* EI_OSABI. */ + printf("%-37s%s\n", " OS/ABI:", elf_osabi(re->ehdr.e_ident[EI_OSABI])); + + /* EI_ABIVERSION. */ + printf("%-37s%d\n", " ABI Version:", re->ehdr.e_ident[EI_ABIVERSION]); + + /* e_type. */ + printf("%-37s%s\n", " Type:", elf_type(re->ehdr.e_type)); + + /* e_machine. */ + printf("%-37s%s\n", " Machine:", elf_machine(re->ehdr.e_machine)); + + /* e_version. */ + printf("%-37s%#x\n", " Version:", re->ehdr.e_version); + + /* e_entry. */ + printf("%-37s%#jx\n", " Entry point address:", + (uintmax_t)re->ehdr.e_entry); + + /* e_phoff. */ + printf("%-37s%ju (bytes into file)\n", " Start of program headers:", + (uintmax_t)re->ehdr.e_phoff); + + /* e_shoff. */ + printf("%-37s%ju (bytes into file)\n", " Start of section headers:", + (uintmax_t)re->ehdr.e_shoff); + + /* e_flags. */ + printf("%-37s%#x", " Flags:", re->ehdr.e_flags); + dump_eflags(re, re->ehdr.e_flags); + putchar('\n'); + + /* e_ehsize. */ + printf("%-37s%u (bytes)\n", " Size of this header:", + re->ehdr.e_ehsize); + + /* e_phentsize. */ + printf("%-37s%u (bytes)\n", " Size of program headers:", + re->ehdr.e_phentsize); + + /* e_phnum. */ + printf("%-37s%u\n", " Number of program headers:", re->ehdr.e_phnum); + + /* e_shentsize. */ + printf("%-37s%u (bytes)\n", " Size of section headers:", + re->ehdr.e_shentsize); + + /* e_shnum. */ + printf("%-37s%u", " Number of section headers:", re->ehdr.e_shnum); + if (re->ehdr.e_shnum == SHN_UNDEF) { + /* Extended section numbering is in use. */ + if (elf_getshnum(re->elf, &shnum)) + printf(" (%ju)", (uintmax_t)shnum); + } + putchar('\n'); + + /* e_shstrndx. */ + printf("%-37s%u", " Section header string table index:", + re->ehdr.e_shstrndx); + if (re->ehdr.e_shstrndx == SHN_XINDEX) { + /* Extended section numbering is in use. */ + if (elf_getshstrndx(re->elf, &shstrndx)) + printf(" (%ju)", (uintmax_t)shstrndx); + } + putchar('\n'); +} + +static void +dump_eflags(struct readelf *re, uint64_t e_flags) +{ + struct eflags_desc *edesc; + int arm_eabi; + + edesc = NULL; + switch (re->ehdr.e_machine) { + case EM_ARM: + arm_eabi = (e_flags & EF_ARM_EABIMASK) >> 24; + if (arm_eabi == 0) + printf(", GNU EABI"); + else if (arm_eabi <= 5) + printf(", Version%d EABI", arm_eabi); + edesc = arm_eflags_desc; + break; + case EM_MIPS: + case EM_MIPS_RS3_LE: + switch ((e_flags & EF_MIPS_ARCH) >> 28) { + case 0: printf(", mips1"); break; + case 1: printf(", mips2"); break; + case 2: printf(", mips3"); break; + case 3: printf(", mips4"); break; + case 4: printf(", mips5"); break; + case 5: printf(", mips32"); break; + case 6: printf(", mips64"); break; + case 7: printf(", mips32r2"); break; + case 8: printf(", mips64r2"); break; + default: break; + } + switch ((e_flags & 0x00FF0000) >> 16) { + case 0x81: printf(", 3900"); break; + case 0x82: printf(", 4010"); break; + case 0x83: printf(", 4100"); break; + case 0x85: printf(", 4650"); break; + case 0x87: printf(", 4120"); break; + case 0x88: printf(", 4111"); break; + case 0x8a: printf(", sb1"); break; + case 0x8b: printf(", octeon"); break; + case 0x8c: printf(", xlr"); break; + case 0x91: printf(", 5400"); break; + case 0x98: printf(", 5500"); break; + case 0x99: printf(", 9000"); break; + case 0xa0: printf(", loongson-2e"); break; + case 0xa1: printf(", loongson-2f"); break; + default: break; + } + switch ((e_flags & 0x0000F000) >> 12) { + case 1: printf(", o32"); break; + case 2: printf(", o64"); break; + case 3: printf(", eabi32"); break; + case 4: printf(", eabi64"); break; + default: break; + } + edesc = mips_eflags_desc; + break; + case EM_PPC: + case EM_PPC64: + edesc = powerpc_eflags_desc; + break; + case EM_SPARC: + case EM_SPARC32PLUS: + case EM_SPARCV9: + switch ((e_flags & EF_SPARCV9_MM)) { + case EF_SPARCV9_TSO: printf(", tso"); break; + case EF_SPARCV9_PSO: printf(", pso"); break; + case EF_SPARCV9_MM: printf(", rmo"); break; + default: break; + } + edesc = sparc_eflags_desc; + break; + default: + break; + } + + if (edesc != NULL) { + while (edesc->desc != NULL) { + if (e_flags & edesc->flag) + printf(", %s", edesc->desc); + edesc++; + } + } +} + +static void +dump_phdr(struct readelf *re) +{ + const char *rawfile; + GElf_Phdr phdr; + size_t phnum; + int i, j; + +#define PH_HDR "Type", "Offset", "VirtAddr", "PhysAddr", "FileSiz", \ + "MemSiz", "Flg", "Align" +#define PH_CT phdr_type(phdr.p_type), (uintmax_t)phdr.p_offset, \ + (uintmax_t)phdr.p_vaddr, (uintmax_t)phdr.p_paddr, \ + (uintmax_t)phdr.p_filesz, (uintmax_t)phdr.p_memsz, \ + phdr.p_flags & PF_R ? 'R' : ' ', \ + phdr.p_flags & PF_W ? 'W' : ' ', \ + phdr.p_flags & PF_X ? 'E' : ' ', \ + (uintmax_t)phdr.p_align + + if (elf_getphnum(re->elf, &phnum) == 0) { + warnx("elf_getphnum failed: %s", elf_errmsg(-1)); + return; + } + if (phnum == 0) { + printf("\nThere are no program headers in this file.\n"); + return; + } + + printf("\nElf file type is %s", elf_type(re->ehdr.e_type)); + printf("\nEntry point 0x%jx\n", (uintmax_t)re->ehdr.e_entry); + printf("There are %ju program headers, starting at offset %ju\n", + (uintmax_t)phnum, (uintmax_t)re->ehdr.e_phoff); + + /* Dump program headers. */ + printf("\nProgram Headers:\n"); + if (re->ec == ELFCLASS32) + printf(" %-15s%-9s%-11s%-11s%-8s%-8s%-4s%s\n", PH_HDR); + else if (re->options & RE_WW) + printf(" %-15s%-9s%-19s%-19s%-9s%-9s%-4s%s\n", PH_HDR); + else + printf(" %-15s%-19s%-19s%s\n %-19s%-20s" + "%-7s%s\n", PH_HDR); + for (i = 0; (size_t) i < phnum; i++) { + if (gelf_getphdr(re->elf, i, &phdr) != &phdr) { + warnx("gelf_getphdr failed: %s", elf_errmsg(-1)); + continue; + } + /* TODO: Add arch-specific segment type dump. */ + if (re->ec == ELFCLASS32) + printf(" %-14.14s 0x%6.6jx 0x%8.8jx 0x%8.8jx " + "0x%5.5jx 0x%5.5jx %c%c%c %#jx\n", PH_CT); + else if (re->options & RE_WW) + printf(" %-14.14s 0x%6.6jx 0x%16.16jx 0x%16.16jx " + "0x%6.6jx 0x%6.6jx %c%c%c %#jx\n", PH_CT); + else + printf(" %-14.14s 0x%16.16jx 0x%16.16jx 0x%16.16jx\n" + " 0x%16.16jx 0x%16.16jx %c%c%c" + " %#jx\n", PH_CT); + if (phdr.p_type == PT_INTERP) { + if ((rawfile = elf_rawfile(re->elf, NULL)) == NULL) { + warnx("elf_rawfile failed: %s", elf_errmsg(-1)); + continue; + } + printf(" [Requesting program interpreter: %s]\n", + rawfile + phdr.p_offset); + } + } + + /* Dump section to segment mapping. */ + if (re->shnum == 0) + return; + printf("\n Section to Segment mapping:\n"); + printf(" Segment Sections...\n"); + for (i = 0; (size_t)i < phnum; i++) { + if (gelf_getphdr(re->elf, i, &phdr) != &phdr) { + warnx("gelf_getphdr failed: %s", elf_errmsg(-1)); + continue; + } + printf(" %2.2d ", i); + /* skip NULL section. */ + for (j = 1; (size_t)j < re->shnum; j++) + if (re->sl[j].off >= phdr.p_offset && + re->sl[j].off + re->sl[j].sz <= + phdr.p_offset + phdr.p_memsz) + printf("%s ", re->sl[j].name); + printf("\n"); + } +#undef PH_HDR +#undef PH_CT +} + +static char * +section_flags(struct readelf *re, struct section *s) +{ +#define BUF_SZ 256 + static char buf[BUF_SZ]; + int i, p, nb; + + p = 0; + nb = re->ec == ELFCLASS32 ? 8 : 16; + if (re->options & RE_T) { + snprintf(buf, BUF_SZ, "[%*.*jx]: ", nb, nb, + (uintmax_t)s->flags); + p += nb + 4; + } + for (i = 0; section_flag[i].ln != NULL; i++) { + if ((s->flags & section_flag[i].value) == 0) + continue; + if (re->options & RE_T) { + snprintf(&buf[p], BUF_SZ - p, "%s, ", + section_flag[i].ln); + p += strlen(section_flag[i].ln) + 2; + } else + buf[p++] = section_flag[i].sn; + } + if (re->options & RE_T && p > nb + 4) + p -= 2; + buf[p] = '\0'; + + return (buf); +} + +static void +dump_shdr(struct readelf *re) +{ + struct section *s; + int i; + +#define S_HDR "[Nr] Name", "Type", "Addr", "Off", "Size", "ES", \ + "Flg", "Lk", "Inf", "Al" +#define S_HDRL "[Nr] Name", "Type", "Address", "Offset", "Size", \ + "EntSize", "Flags", "Link", "Info", "Align" +#define ST_HDR "[Nr] Name", "Type", "Addr", "Off", "Size", "ES", \ + "Lk", "Inf", "Al", "Flags" +#define ST_HDRL "[Nr] Name", "Type", "Address", "Offset", "Link", \ + "Size", "EntSize", "Info", "Align", "Flags" +#define S_CT i, s->name, section_type(re->ehdr.e_machine, s->type), \ + (uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\ + (uintmax_t)s->entsize, section_flags(re, s), \ + s->link, s->info, (uintmax_t)s->align +#define ST_CT i, s->name, section_type(re->ehdr.e_machine, s->type), \ + (uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\ + (uintmax_t)s->entsize, s->link, s->info, \ + (uintmax_t)s->align, section_flags(re, s) +#define ST_CTL i, s->name, section_type(re->ehdr.e_machine, s->type), \ + (uintmax_t)s->addr, (uintmax_t)s->off, s->link, \ + (uintmax_t)s->sz, (uintmax_t)s->entsize, s->info, \ + (uintmax_t)s->align, section_flags(re, s) + + if (re->shnum == 0) { + printf("\nThere are no sections in this file.\n"); + return; + } + printf("There are %ju section headers, starting at offset 0x%jx:\n", + (uintmax_t)re->shnum, (uintmax_t)re->ehdr.e_shoff); + printf("\nSection Headers:\n"); + if (re->ec == ELFCLASS32) { + if (re->options & RE_T) + printf(" %s\n %-16s%-9s%-7s%-7s%-5s%-3s%-4s%s\n" + "%12s\n", ST_HDR); + else + printf(" %-23s%-16s%-9s%-7s%-7s%-3s%-4s%-3s%-4s%s\n", + S_HDR); + } else if (re->options & RE_WW) { + if (re->options & RE_T) + printf(" %s\n %-16s%-17s%-7s%-7s%-5s%-3s%-4s%s\n" + "%12s\n", ST_HDR); + else + printf(" %-23s%-16s%-17s%-7s%-7s%-3s%-4s%-3s%-4s%s\n", + S_HDR); + } else { + if (re->options & RE_T) + printf(" %s\n %-18s%-17s%-18s%s\n %-18s" + "%-17s%-18s%s\n%12s\n", ST_HDRL); + else + printf(" %-23s%-17s%-18s%s\n %-18s%-17s%-7s%" + "-6s%-6s%s\n", S_HDRL); + } + for (i = 0; (size_t)i < re->shnum; i++) { + s = &re->sl[i]; + if (re->ec == ELFCLASS32) { + if (re->options & RE_T) + printf(" [%2d] %s\n %-15.15s %8.8jx" + " %6.6jx %6.6jx %2.2jx %2u %3u %2ju\n" + " %s\n", ST_CT); + else + printf(" [%2d] %-17.17s %-15.15s %8.8jx" + " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n", + S_CT); + } else if (re->options & RE_WW) { + if (re->options & RE_T) + printf(" [%2d] %s\n %-15.15s %16.16jx" + " %6.6jx %6.6jx %2.2jx %2u %3u %2ju\n" + " %s\n", ST_CT); + else + printf(" [%2d] %-17.17s %-15.15s %16.16jx" + " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n", + S_CT); + } else { + if (re->options & RE_T) + printf(" [%2d] %s\n %-15.15s %16.16jx" + " %16.16jx %u\n %16.16jx %16.16jx" + " %-16u %ju\n %s\n", ST_CTL); + else + printf(" [%2d] %-17.17s %-15.15s %16.16jx" + " %8.8jx\n %16.16jx %16.16jx " + "%3s %2u %3u %ju\n", S_CT); + } + } + if ((re->options & RE_T) == 0) + printf("Key to Flags:\n W (write), A (alloc)," + " X (execute), M (merge), S (strings)\n" + " I (info), L (link order), G (group), x (unknown)\n" + " O (extra OS processing required)" + " o (OS specific), p (processor specific)\n"); + +#undef S_HDR +#undef S_HDRL +#undef ST_HDR +#undef ST_HDRL +#undef S_CT +#undef ST_CT +#undef ST_CTL +} + +static void +dump_dynamic(struct readelf *re) +{ + GElf_Dyn dyn; + Elf_Data *d; + struct section *s; + int elferr, i, is_dynamic, j, jmax, nentries; + + is_dynamic = 0; + + for (i = 0; (size_t)i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type != SHT_DYNAMIC) + continue; + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + continue; + } + if (d->d_size <= 0) + continue; + + is_dynamic = 1; + + /* Determine the actual number of table entries. */ + nentries = 0; + jmax = (int) (s->sz / s->entsize); + + for (j = 0; j < jmax; j++) { + if (gelf_getdyn(d, j, &dyn) != &dyn) { + warnx("gelf_getdyn failed: %s", + elf_errmsg(-1)); + continue; + } + nentries ++; + if (dyn.d_tag == DT_NULL) + break; + } + + printf("\nDynamic section at offset 0x%jx", (uintmax_t)s->off); + printf(" contains %u entries:\n", nentries); + + if (re->ec == ELFCLASS32) + printf("%5s%12s%28s\n", "Tag", "Type", "Name/Value"); + else + printf("%5s%20s%28s\n", "Tag", "Type", "Name/Value"); + + for (j = 0; j < nentries; j++) { + if (gelf_getdyn(d, j, &dyn) != &dyn) + continue; + /* Dump dynamic entry type. */ + if (re->ec == ELFCLASS32) + printf(" 0x%8.8jx", (uintmax_t)dyn.d_tag); + else + printf(" 0x%16.16jx", (uintmax_t)dyn.d_tag); + printf(" %-20s", dt_type(re->ehdr.e_machine, + dyn.d_tag)); + /* Dump dynamic entry value. */ + dump_dyn_val(re, &dyn, s->link); + } + } + + if (!is_dynamic) + printf("\nThere is no dynamic section in this file.\n"); +} + +static char * +timestamp(time_t ti) +{ + static char ts[32]; + struct tm *t; + + t = gmtime(&ti); + snprintf(ts, sizeof(ts), "%04d-%02d-%02dT%02d:%02d:%02d", + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, + t->tm_min, t->tm_sec); + + return (ts); +} + +static const char * +dyn_str(struct readelf *re, uint32_t stab, uint64_t d_val) +{ + const char *name; + + if (stab == SHN_UNDEF) + name = "ERROR"; + else if ((name = elf_strptr(re->elf, stab, d_val)) == NULL) { + (void) elf_errno(); /* clear error */ + name = "ERROR"; + } + + return (name); +} + +static void +dump_arch_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab) +{ + const char *name; + + switch (re->ehdr.e_machine) { + case EM_MIPS: + case EM_MIPS_RS3_LE: + switch (dyn->d_tag) { + case DT_MIPS_RLD_VERSION: + case DT_MIPS_LOCAL_GOTNO: + case DT_MIPS_CONFLICTNO: + case DT_MIPS_LIBLISTNO: + case DT_MIPS_SYMTABNO: + case DT_MIPS_UNREFEXTNO: + case DT_MIPS_GOTSYM: + case DT_MIPS_HIPAGENO: + case DT_MIPS_DELTA_CLASS_NO: + case DT_MIPS_DELTA_INSTANCE_NO: + case DT_MIPS_DELTA_RELOC_NO: + case DT_MIPS_DELTA_SYM_NO: + case DT_MIPS_DELTA_CLASSSYM_NO: + case DT_MIPS_LOCALPAGE_GOTIDX: + case DT_MIPS_LOCAL_GOTIDX: + case DT_MIPS_HIDDEN_GOTIDX: + case DT_MIPS_PROTECTED_GOTIDX: + printf(" %ju\n", (uintmax_t) dyn->d_un.d_val); + break; + case DT_MIPS_ICHECKSUM: + case DT_MIPS_FLAGS: + case DT_MIPS_BASE_ADDRESS: + case DT_MIPS_CONFLICT: + case DT_MIPS_LIBLIST: + case DT_MIPS_RLD_MAP: + case DT_MIPS_DELTA_CLASS: + case DT_MIPS_DELTA_INSTANCE: + case DT_MIPS_DELTA_RELOC: + case DT_MIPS_DELTA_SYM: + case DT_MIPS_DELTA_CLASSSYM: + case DT_MIPS_CXX_FLAGS: + case DT_MIPS_PIXIE_INIT: + case DT_MIPS_SYMBOL_LIB: + case DT_MIPS_OPTIONS: + case DT_MIPS_INTERFACE: + case DT_MIPS_DYNSTR_ALIGN: + case DT_MIPS_INTERFACE_SIZE: + case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: + case DT_MIPS_COMPACT_SIZE: + case DT_MIPS_GP_VALUE: + case DT_MIPS_AUX_DYNAMIC: + case DT_MIPS_PLTGOT: + case DT_MIPS_RLD_OBJ_UPDATE: + case DT_MIPS_RWPLT: + printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val); + break; + case DT_MIPS_IVERSION: + case DT_MIPS_PERF_SUFFIX: + case DT_AUXILIARY: + case DT_FILTER: + name = dyn_str(re, stab, dyn->d_un.d_val); + printf(" %s\n", name); + break; + case DT_MIPS_TIME_STAMP: + printf(" %s\n", timestamp(dyn->d_un.d_val)); + break; + } + break; + default: + printf("\n"); + break; + } +} + +static void +dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab) +{ + const char *name; + + if (dyn->d_tag >= DT_LOPROC && dyn->d_tag <= DT_HIPROC) { + dump_arch_dyn_val(re, dyn, stab); + return; + } + + /* These entry values are index into the string table. */ + name = NULL; + if (dyn->d_tag == DT_NEEDED || dyn->d_tag == DT_SONAME || + dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH) + name = dyn_str(re, stab, dyn->d_un.d_val); + + switch(dyn->d_tag) { + case DT_NULL: + case DT_PLTGOT: + case DT_HASH: + case DT_STRTAB: + case DT_SYMTAB: + case DT_RELA: + case DT_INIT: + case DT_SYMBOLIC: + case DT_REL: + case DT_DEBUG: + case DT_TEXTREL: + case DT_JMPREL: + case DT_FINI: + case DT_VERDEF: + case DT_VERNEED: + case DT_VERSYM: + case DT_GNU_HASH: + case DT_GNU_LIBLIST: + case DT_GNU_CONFLICT: + printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val); + break; + case DT_PLTRELSZ: + case DT_RELASZ: + case DT_RELAENT: + case DT_STRSZ: + case DT_SYMENT: + case DT_RELSZ: + case DT_RELENT: + case DT_INIT_ARRAYSZ: + case DT_FINI_ARRAYSZ: + case DT_GNU_CONFLICTSZ: + case DT_GNU_LIBLISTSZ: + printf(" %ju (bytes)\n", (uintmax_t) dyn->d_un.d_val); + break; + case DT_RELACOUNT: + case DT_RELCOUNT: + case DT_VERDEFNUM: + case DT_VERNEEDNUM: + printf(" %ju\n", (uintmax_t) dyn->d_un.d_val); + break; + case DT_NEEDED: + printf(" Shared library: [%s]\n", name); + break; + case DT_SONAME: + printf(" Library soname: [%s]\n", name); + break; + case DT_RPATH: + printf(" Library rpath: [%s]\n", name); + break; + case DT_RUNPATH: + printf(" Library runpath: [%s]\n", name); + break; + case DT_PLTREL: + printf(" %s\n", dt_type(re->ehdr.e_machine, dyn->d_un.d_val)); + break; + case DT_GNU_PRELINKED: + printf(" %s\n", timestamp(dyn->d_un.d_val)); + break; + default: + printf("\n"); + } +} + +static void +dump_rel(struct readelf *re, struct section *s, Elf_Data *d) +{ + GElf_Rel r; + const char *symname; + uint64_t symval; + int i, len; + +#define REL_HDR "r_offset", "r_info", "r_type", "st_value", "st_name" +#define REL_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ + r_type(re->ehdr.e_machine, ELF32_R_TYPE(r.r_info)), \ + (uintmax_t)symval, symname +#define REL_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ + r_type(re->ehdr.e_machine, ELF64_R_TYPE(r.r_info)), \ + (uintmax_t)symval, symname + + printf("\nRelocation section (%s):\n", s->name); + if (re->ec == ELFCLASS32) + printf("%-8s %-8s %-19s %-8s %s\n", REL_HDR); + else { + if (re->options & RE_WW) + printf("%-16s %-16s %-24s %-16s %s\n", REL_HDR); + else + printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR); + } + len = d->d_size / s->entsize; + for (i = 0; i < len; i++) { + if (gelf_getrel(d, i, &r) != &r) { + warnx("gelf_getrel failed: %s", elf_errmsg(-1)); + continue; + } + symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info)); + symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info)); + if (re->ec == ELFCLASS32) { + r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info), + ELF64_R_TYPE(r.r_info)); + printf("%8.8jx %8.8jx %-19.19s %8.8jx %s\n", REL_CT32); + } else { + if (re->options & RE_WW) + printf("%16.16jx %16.16jx %-24.24s" + " %16.16jx %s\n", REL_CT64); + else + printf("%12.12jx %12.12jx %-19.19s" + " %16.16jx %s\n", REL_CT64); + } + } + +#undef REL_HDR +#undef REL_CT +} + +static void +dump_rela(struct readelf *re, struct section *s, Elf_Data *d) +{ + GElf_Rela r; + const char *symname; + uint64_t symval; + int i, len; + +#define RELA_HDR "r_offset", "r_info", "r_type", "st_value", \ + "st_name + r_addend" +#define RELA_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ + r_type(re->ehdr.e_machine, ELF32_R_TYPE(r.r_info)), \ + (uintmax_t)symval, symname +#define RELA_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ + r_type(re->ehdr.e_machine, ELF64_R_TYPE(r.r_info)), \ + (uintmax_t)symval, symname + + printf("\nRelocation section with addend (%s):\n", s->name); + if (re->ec == ELFCLASS32) + printf("%-8s %-8s %-19s %-8s %s\n", RELA_HDR); + else { + if (re->options & RE_WW) + printf("%-16s %-16s %-24s %-16s %s\n", RELA_HDR); + else + printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR); + } + len = d->d_size / s->entsize; + for (i = 0; i < len; i++) { + if (gelf_getrela(d, i, &r) != &r) { + warnx("gelf_getrel failed: %s", elf_errmsg(-1)); + continue; + } + symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info)); + symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info)); + if (re->ec == ELFCLASS32) { + r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info), + ELF64_R_TYPE(r.r_info)); + printf("%8.8jx %8.8jx %-19.19s %8.8jx %s", RELA_CT32); + printf(" + %x\n", (uint32_t) r.r_addend); + } else { + if (re->options & RE_WW) + printf("%16.16jx %16.16jx %-24.24s" + " %16.16jx %s", RELA_CT64); + else + printf("%12.12jx %12.12jx %-19.19s" + " %16.16jx %s", RELA_CT64); + printf(" + %jx\n", (uintmax_t) r.r_addend); + } + } + +#undef RELA_HDR +#undef RELA_CT +} + +static void +dump_reloc(struct readelf *re) +{ + struct section *s; + Elf_Data *d; + int i, elferr; + + for (i = 0; (size_t)i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type == SHT_REL || s->type == SHT_RELA) { + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(elferr)); + continue; + } + if (s->type == SHT_REL) + dump_rel(re, s, d); + else + dump_rela(re, s, d); + } + } +} + +static void +dump_symtab(struct readelf *re, int i) +{ + struct section *s; + Elf_Data *d; + GElf_Sym sym; + const char *name; + int elferr, stab, j; + + s = &re->sl[i]; + stab = s->link; + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(elferr)); + return; + } + if (d->d_size <= 0) + return; + printf("Symbol table (%s)", s->name); + printf(" contains %ju entries:\n", s->sz / s->entsize); + printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type", + "Bind", "Vis", "Ndx", "Name"); + + for (j = 0; (uint64_t)j < s->sz / s->entsize; j++) { + if (gelf_getsym(d, j, &sym) != &sym) { + warnx("gelf_getsym failed: %s", elf_errmsg(-1)); + continue; + } + printf("%6d:", j); + printf(" %16.16jx", (uintmax_t)sym.st_value); + printf(" %5ju", sym.st_size); + printf(" %-7s", st_type(GELF_ST_TYPE(sym.st_info))); + printf(" %-6s", st_bind(GELF_ST_BIND(sym.st_info))); + printf(" %-8s", st_vis(GELF_ST_VISIBILITY(sym.st_other))); + printf(" %3s", st_shndx(sym.st_shndx)); + if ((name = elf_strptr(re->elf, stab, sym.st_name)) != NULL) + printf(" %s", name); + /* Append symbol version string for SHT_DYNSYM symbol table. */ + if (s->type == SHT_DYNSYM && re->ver != NULL && + re->vs != NULL && re->vs[j] > 1) { + if (re->vs[j] & 0x8000 || + re->ver[re->vs[j] & 0x7fff].type == 0) + printf("@%s (%d)", + re->ver[re->vs[j] & 0x7fff].name, + re->vs[j] & 0x7fff); + else + printf("@@%s (%d)", re->ver[re->vs[j]].name, + re->vs[j]); + } + putchar('\n'); + } + +} + +static void +dump_symtabs(struct readelf *re) +{ + GElf_Dyn dyn; + Elf_Data *d; + struct section *s; + uint64_t dyn_off; + int elferr, i; + + /* + * If -D is specified, only dump the symbol table specified by + * the DT_SYMTAB entry in the .dynamic section. + */ + dyn_off = 0; + if (re->options & RE_DD) { + s = NULL; + for (i = 0; (size_t)i < re->shnum; i++) + if (re->sl[i].type == SHT_DYNAMIC) { + s = &re->sl[i]; + break; + } + if (s == NULL) + return; + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + return; + } + if (d->d_size <= 0) + return; + + for (i = 0; (uint64_t)i < s->sz / s->entsize; i++) { + if (gelf_getdyn(d, i, &dyn) != &dyn) { + warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); + continue; + } + if (dyn.d_tag == DT_SYMTAB) { + dyn_off = dyn.d_un.d_val; + break; + } + } + } + + /* Find and dump symbol tables. */ + for (i = 0; (size_t)i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type == SHT_SYMTAB || s->type == SHT_DYNSYM) { + if (re->options & RE_DD) { + if (dyn_off == s->addr) { + dump_symtab(re, i); + break; + } + } else + dump_symtab(re, i); + } + } +} + +static void +dump_svr4_hash(struct section *s) +{ + Elf_Data *d; + uint32_t *buf; + uint32_t nbucket, nchain; + uint32_t *bucket, *chain; + uint32_t *bl, *c, maxl, total; + int elferr, i, j; + + /* Read and parse the content of .hash section. */ + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(elferr)); + return; + } + if (d->d_size < 2 * sizeof(uint32_t)) { + warnx(".hash section too small"); + return; + } + buf = d->d_buf; + nbucket = buf[0]; + nchain = buf[1]; + if (nbucket <= 0 || nchain <= 0) { + warnx("Malformed .hash section"); + return; + } + if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) { + warnx("Malformed .hash section"); + return; + } + bucket = &buf[2]; + chain = &buf[2 + nbucket]; + + maxl = 0; + if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) + errx(EXIT_FAILURE, "calloc failed"); + for (i = 0; (uint32_t)i < nbucket; i++) + for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j]) + if (++bl[i] > maxl) + maxl = bl[i]; + if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) + errx(EXIT_FAILURE, "calloc failed"); + for (i = 0; (uint32_t)i < nbucket; i++) + c[bl[i]]++; + printf("\nHistogram for bucket list length (total of %u buckets):\n", + nbucket); + printf(" Length\tNumber\t\t%% of total\tCoverage\n"); + total = 0; + for (i = 0; (uint32_t)i <= maxl; i++) { + total += c[i] * i; + printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i], + c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1)); + } + free(c); + free(bl); +} + +static void +dump_svr4_hash64(struct readelf *re, struct section *s) +{ + Elf_Data *d, dst; + uint64_t *buf; + uint64_t nbucket, nchain; + uint64_t *bucket, *chain; + uint64_t *bl, *c, maxl, total; + int elferr, i, j; + + /* + * ALPHA uses 64-bit hash entries. Since libelf assumes that + * .hash section contains only 32-bit entry, an explicit + * gelf_xlatetom is needed here. + */ + (void) elf_errno(); + if ((d = elf_rawdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_rawdata failed: %s", + elf_errmsg(elferr)); + return; + } + d->d_type = ELF_T_XWORD; + memcpy(&dst, d, sizeof(Elf_Data)); + if (gelf_xlatetom(re->elf, &dst, d, + re->ehdr.e_ident[EI_DATA]) != &dst) { + warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); + return; + } + if (dst.d_size < 2 * sizeof(uint64_t)) { + warnx(".hash section too small"); + return; + } + buf = dst.d_buf; + nbucket = buf[0]; + nchain = buf[1]; + if (nbucket <= 0 || nchain <= 0) { + warnx("Malformed .hash section"); + return; + } + if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) { + warnx("Malformed .hash section"); + return; + } + bucket = &buf[2]; + chain = &buf[2 + nbucket]; + + maxl = 0; + if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) + errx(EXIT_FAILURE, "calloc failed"); + for (i = 0; (uint32_t)i < nbucket; i++) + for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j]) + if (++bl[i] > maxl) + maxl = bl[i]; + if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) + errx(EXIT_FAILURE, "calloc failed"); + for (i = 0; (uint64_t)i < nbucket; i++) + c[bl[i]]++; + printf("Histogram for bucket list length (total of %ju buckets):\n", + (uintmax_t)nbucket); + printf(" Length\tNumber\t\t%% of total\tCoverage\n"); + total = 0; + for (i = 0; (uint64_t)i <= maxl; i++) { + total += c[i] * i; + printf("%7u\t%-10ju\t(%5.1f%%)\t%5.1f%%\n", i, (uintmax_t)c[i], + c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1)); + } + free(c); + free(bl); +} + +static void +dump_gnu_hash(struct readelf *re, struct section *s) +{ + struct section *ds; + Elf_Data *d; + uint32_t *buf; + uint32_t *bucket, *chain; + uint32_t nbucket, nchain, symndx, maskwords, shift2; + uint32_t *bl, *c, maxl, total; + int elferr, dynsymcount, i, j; + + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(elferr)); + return; + } + if (d->d_size < 4 * sizeof(uint32_t)) { + warnx(".gnu.hash section too small"); + return; + } + buf = d->d_buf; + nbucket = buf[0]; + symndx = buf[1]; + maskwords = buf[2]; + shift2 = buf[3]; + buf += 4; + ds = &re->sl[s->link]; + dynsymcount = ds->sz / ds->entsize; + nchain = dynsymcount - symndx; + if (d->d_size != 4 * sizeof(uint32_t) + maskwords * + (re->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + + (nbucket + nchain) * sizeof(uint32_t)) { + warnx("Malformed .gnu.hash section"); + return; + } + bucket = buf + (re->ec == ELFCLASS32 ? maskwords : maskwords * 2); + chain = bucket + nbucket; + + maxl = 0; + if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) + errx(EXIT_FAILURE, "calloc failed"); + for (i = 0; (uint32_t)i < nbucket; i++) + for (j = bucket[i]; j > 0 && (uint32_t)j - symndx < nchain; + j++) { + if (++bl[i] > maxl) + maxl = bl[i]; + if (chain[j - symndx] & 1) + break; + } + if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) + errx(EXIT_FAILURE, "calloc failed"); + for (i = 0; (uint32_t)i < nbucket; i++) + c[bl[i]]++; + printf("Histogram for bucket list length (total of %u buckets):\n", + nbucket); + printf(" Length\tNumber\t\t%% of total\tCoverage\n"); + total = 0; + for (i = 0; (uint32_t)i <= maxl; i++) { + total += c[i] * i; + printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i], + c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1)); + } + free(c); + free(bl); +} + +static void +dump_hash(struct readelf *re) +{ + struct section *s; + int i; + + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type == SHT_HASH || s->type == SHT_GNU_HASH) { + if (s->type == SHT_GNU_HASH) + dump_gnu_hash(re, s); + else if (re->ehdr.e_machine == EM_ALPHA && + s->entsize == 8) + dump_svr4_hash64(re, s); + else + dump_svr4_hash(s); + } + } +} + +static void +dump_notes(struct readelf *re) +{ + struct section *s; + const char *rawfile; + GElf_Phdr phdr; + Elf_Data *d; + size_t phnum; + int i, elferr; + + if (re->ehdr.e_type == ET_CORE) { + /* + * Search program headers in the core file for + * PT_NOTE entry. + */ + if (elf_getphnum(re->elf, &phnum) == 0) { + warnx("elf_getphnum failed: %s", elf_errmsg(-1)); + return; + } + if (phnum == 0) + return; + if ((rawfile = elf_rawfile(re->elf, NULL)) == NULL) { + warnx("elf_rawfile failed: %s", elf_errmsg(-1)); + return; + } + for (i = 0; (size_t) i < phnum; i++) { + if (gelf_getphdr(re->elf, i, &phdr) != &phdr) { + warnx("gelf_getphdr failed: %s", + elf_errmsg(-1)); + continue; + } + if (phdr.p_type == PT_NOTE) + dump_notes_content(re, rawfile + phdr.p_offset, + phdr.p_filesz, phdr.p_offset); + } + + } else { + /* + * For objects other than core files, Search for + * SHT_NOTE sections. + */ + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type == SHT_NOTE) { + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(elferr)); + continue; + } + dump_notes_content(re, d->d_buf, d->d_size, + s->off); + } + } + } +} + +static void +dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off) +{ + Elf_Note *note; + const char *end; + + printf("\nNotes at offset %#010jx with length %#010jx:\n", + (uintmax_t) off, (uintmax_t) sz); + printf(" %-13s %-15s %s\n", "Owner", "Data size", "Description"); + end = buf + sz; + while (buf < end) { + note = (Elf_Note *)(uintptr_t) buf; + printf(" %-13s %#010jx", (char *)(uintptr_t) (note + 1), + (uintmax_t) note->n_descsz); + printf(" %s\n", note_type(re->ehdr.e_ident[EI_OSABI], + re->ehdr.e_type, note->n_type)); + buf += sizeof(Elf_Note); + if (re->ec == ELFCLASS32) + buf += roundup2(note->n_namesz, 4) + + roundup2(note->n_descsz, 4); + else + buf += roundup2(note->n_namesz, 8) + + roundup2(note->n_descsz, 8); + } +} + +/* + * Symbol versioning sections are the same for 32bit and 64bit + * ELF objects. + */ +#define Elf_Verdef Elf32_Verdef +#define Elf_Verdaux Elf32_Verdaux +#define Elf_Verneed Elf32_Verneed +#define Elf_Vernaux Elf32_Vernaux + +#define SAVE_VERSION_NAME(x, n, t) \ + do { \ + while (x >= re->ver_sz) { \ + nv = realloc(re->ver, \ + sizeof(*re->ver) * re->ver_sz * 2); \ + if (nv == NULL) { \ + warn("realloc failed"); \ + free(re->ver); \ + return; \ + } \ + re->ver = nv; \ + for (i = re->ver_sz; i < re->ver_sz * 2; i++) { \ + re->ver[i].name = NULL; \ + re->ver[i].type = 0; \ + } \ + re->ver_sz *= 2; \ + } \ + if (x > 1) { \ + re->ver[x].name = n; \ + re->ver[x].type = t; \ + } \ + } while (0) + + +static void +dump_verdef(struct readelf *re, int dump) +{ + struct section *s; + struct symver *nv; + Elf_Data *d; + Elf_Verdef *vd; + Elf_Verdaux *vda; + uint8_t *buf, *end, *buf2; + const char *name; + int elferr, i, j; + + if ((s = re->vd_s) == NULL) + return; + + if (re->ver == NULL) { + re->ver_sz = 16; + if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) == + NULL) { + warn("calloc failed"); + return; + } + re->ver[0].name = "*local*"; + re->ver[1].name = "*global*"; + } + + if (dump) + printf("\nVersion definition section (%s):\n", s->name); + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(elferr)); + return; + } + if (d->d_size == 0) + return; + + buf = d->d_buf; + end = buf + d->d_size; + while (buf + sizeof(Elf_Verdef) <= end) { + vd = (Elf_Verdef *) (uintptr_t) buf; + if (dump) { + printf(" 0x%4.4lx", (unsigned long) + (buf - (uint8_t *)d->d_buf)); + printf(" vd_version: %u vd_flags: %d" + " vd_ndx: %u vd_cnt: %u", vd->vd_version, + vd->vd_flags, vd->vd_ndx, vd->vd_cnt); + } + buf2 = buf + vd->vd_aux; + j = 0; + while (buf2 + sizeof(Elf_Verdaux) <= end && j < vd->vd_cnt) { + vda = (Elf_Verdaux *) (uintptr_t) buf2; + name = get_string(re, s->link, vda->vda_name); + if (j == 0) { + if (dump) + printf(" vda_name: %s\n", name); + SAVE_VERSION_NAME((int)vd->vd_ndx, name, 1); + } else if (dump) + printf(" 0x%4.4lx parent: %s\n", + (unsigned long) (buf2 - + (uint8_t *)d->d_buf), name); + if (vda->vda_next == 0) + break; + buf2 += vda->vda_next; + j++; + } + if (vd->vd_next == 0) + break; + buf += vd->vd_next; + } +} + +static void +dump_verneed(struct readelf *re, int dump) +{ + struct section *s; + struct symver *nv; + Elf_Data *d; + Elf_Verneed *vn; + Elf_Vernaux *vna; + uint8_t *buf, *end, *buf2; + const char *name; + int elferr, i, j; + + if ((s = re->vn_s) == NULL) + return; + + if (re->ver == NULL) { + re->ver_sz = 16; + if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) == + NULL) { + warn("calloc failed"); + return; + } + re->ver[0].name = "*local*"; + re->ver[1].name = "*global*"; + } + + if (dump) + printf("\nVersion needed section (%s):\n", s->name); + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(elferr)); + return; + } + if (d->d_size == 0) + return; + + buf = d->d_buf; + end = buf + d->d_size; + while (buf + sizeof(Elf_Verneed) <= end) { + vn = (Elf_Verneed *) (uintptr_t) buf; + if (dump) { + printf(" 0x%4.4lx", (unsigned long) + (buf - (uint8_t *)d->d_buf)); + printf(" vn_version: %u vn_file: %s vn_cnt: %u\n", + vn->vn_version, + get_string(re, s->link, vn->vn_file), + vn->vn_cnt); + } + buf2 = buf + vn->vn_aux; + j = 0; + while (buf2 + sizeof(Elf_Vernaux) <= end && j < vn->vn_cnt) { + vna = (Elf32_Vernaux *) (uintptr_t) buf2; + if (dump) + printf(" 0x%4.4lx", (unsigned long) + (buf2 - (uint8_t *)d->d_buf)); + name = get_string(re, s->link, vna->vna_name); + if (dump) + printf(" vna_name: %s vna_flags: %u" + " vna_other: %u\n", name, + vna->vna_flags, vna->vna_other); + SAVE_VERSION_NAME((int)vna->vna_other, name, 0); + if (vna->vna_next == 0) + break; + buf2 += vna->vna_next; + j++; + } + if (vn->vn_next == 0) + break; + buf += vn->vn_next; + } +} + +static void +dump_versym(struct readelf *re) +{ + int i; + + if (re->vs_s == NULL || re->ver == NULL || re->vs == NULL) + return; + printf("\nVersion symbol section (%s):\n", re->vs_s->name); + for (i = 0; i < re->vs_sz; i++) { + if ((i & 3) == 0) { + if (i > 0) + putchar('\n'); + printf(" %03x:", i); + } + if (re->vs[i] & 0x8000) + printf(" %3xh %-12s ", re->vs[i] & 0x7fff, + re->ver[re->vs[i] & 0x7fff].name); + else + printf(" %3x %-12s ", re->vs[i], + re->ver[re->vs[i]].name); + } + putchar('\n'); +} + +static void +dump_ver(struct readelf *re) +{ + + if (re->vs_s && re->ver && re->vs) + dump_versym(re); + if (re->vd_s) + dump_verdef(re, 1); + if (re->vn_s) + dump_verneed(re, 1); +} + +static void +search_ver(struct readelf *re) +{ + struct section *s; + Elf_Data *d; + int elferr, i; + + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type == SHT_SUNW_versym) + re->vs_s = s; + if (s->type == SHT_SUNW_verneed) + re->vn_s = s; + if (s->type == SHT_SUNW_verdef) + re->vd_s = s; + } + if (re->vd_s) + dump_verdef(re, 0); + if (re->vn_s) + dump_verneed(re, 0); + if (re->vs_s && re->ver != NULL) { + (void) elf_errno(); + if ((d = elf_getdata(re->vs_s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(elferr)); + return; + } + if (d->d_size == 0) + return; + re->vs = d->d_buf; + re->vs_sz = d->d_size / sizeof(Elf32_Half); + } +} + +#undef Elf_Verdef +#undef Elf_Verdaux +#undef Elf_Verneed +#undef Elf_Vernaux +#undef SAVE_VERSION_NAME + +/* + * Elf32_Lib and Elf64_Lib are identical. + */ +#define Elf_Lib Elf32_Lib + +static void +dump_liblist(struct readelf *re) +{ + struct section *s; + struct tm *t; + time_t ti; + char tbuf[20]; + Elf_Data *d; + Elf_Lib *lib; + int i, j, k, elferr, first; + + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type != SHT_GNU_LIBLIST) + continue; + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(elferr)); + continue; + } + if (d->d_size <= 0) + continue; + lib = d->d_buf; + printf("\nLibrary list section '%s' ", s->name); + printf("contains %ju entries:\n", s->sz / s->entsize); + printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp", + "Checksum", "Version", "Flags"); + for (j = 0; (uint64_t) j < s->sz / s->entsize; j++) { + printf("%3d: ", j); + printf("%-20.20s ", + get_string(re, s->link, lib->l_name)); + ti = lib->l_time_stamp; + t = gmtime(&ti); + snprintf(tbuf, sizeof(tbuf), "%04d-%02d-%02dT%02d:%02d" + ":%2d", t->tm_year + 1900, t->tm_mon + 1, + t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + printf("%-19.19s ", tbuf); + printf("0x%08x ", lib->l_checksum); + printf("%-7d %#x", lib->l_version, lib->l_flags); + if (lib->l_flags != 0) { + first = 1; + putchar('('); + for (k = 0; l_flag[k].name != NULL; k++) { + if ((l_flag[k].value & lib->l_flags) == + 0) + continue; + if (!first) + putchar(','); + else + first = 0; + printf("%s", l_flag[k].name); + } + putchar(')'); + } + putchar('\n'); + lib++; + } + } +} + +#undef Elf_Lib + +static uint8_t * +dump_unknown_tag(uint64_t tag, uint8_t *p) +{ + uint64_t val; + + /* + * According to ARM EABI: For tags > 32, even numbered tags have + * a ULEB128 param and odd numbered ones have NUL-terminated + * string param. This rule probably also applies for tags <= 32 + * if the object arch is not ARM. + */ + + printf(" Tag_unknown_%ju: ", (uintmax_t) tag); + + if (tag & 1) { + printf("%s\n", (char *) p); + p += strlen((char *) p) + 1; + } else { + val = _decode_uleb128(&p); + printf("%ju\n", (uintmax_t) val); + } + + return (p); +} + +static uint8_t * +dump_compatibility_tag(uint8_t *p) +{ + uint64_t val; + + val = _decode_uleb128(&p); + printf("flag = %ju, vendor = %s\n", val, p); + p += strlen((char *) p) + 1; + + return (p); +} + +static void +dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) +{ + uint64_t tag, val; + size_t i; + int found, desc; + + (void) re; + + while (p < pe) { + tag = _decode_uleb128(&p); + found = desc = 0; + for (i = 0; i < sizeof(aeabi_tags) / sizeof(aeabi_tags[0]); + i++) { + if (tag == aeabi_tags[i].tag) { + found = 1; + printf(" %s: ", aeabi_tags[i].s_tag); + if (aeabi_tags[i].get_desc) { + desc = 1; + val = _decode_uleb128(&p); + printf("%s\n", + aeabi_tags[i].get_desc(val)); + } + break; + } + if (tag < aeabi_tags[i].tag) + break; + } + if (!found) { + p = dump_unknown_tag(tag, p); + continue; + } + if (desc) + continue; + + switch (tag) { + case 4: /* Tag_CPU_raw_name */ + case 5: /* Tag_CPU_name */ + case 67: /* Tag_conformance */ + printf("%s\n", (char *) p); + p += strlen((char *) p) + 1; + break; + case 32: /* Tag_compatibility */ + p = dump_compatibility_tag(p); + break; + case 64: /* Tag_nodefaults */ + /* ignored, written as 0. */ + (void) _decode_uleb128(&p); + printf("True\n"); + break; + case 65: /* Tag_also_compatible_with */ + val = _decode_uleb128(&p); + /* Must be Tag_CPU_arch */ + if (val != 6) { + printf("unknown\n"); + break; + } + val = _decode_uleb128(&p); + printf("%s\n", aeabi_cpu_arch(val)); + /* Skip NUL terminator. */ + p++; + break; + default: + putchar('\n'); + break; + } + } +} + +#ifndef Tag_GNU_MIPS_ABI_FP +#define Tag_GNU_MIPS_ABI_FP 4 +#endif + +static void +dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) +{ + uint64_t tag, val; + + (void) re; + + while (p < pe) { + tag = _decode_uleb128(&p); + switch (tag) { + case Tag_GNU_MIPS_ABI_FP: + val = _decode_uleb128(&p); + printf(" Tag_GNU_MIPS_ABI_FP: %s\n", mips_abi_fp(val)); + break; + case 32: /* Tag_compatibility */ + p = dump_compatibility_tag(p); + break; + default: + p = dump_unknown_tag(tag, p); + break; + } + } +} + +#ifndef Tag_GNU_Power_ABI_FP +#define Tag_GNU_Power_ABI_FP 4 +#endif + +#ifndef Tag_GNU_Power_ABI_Vector +#define Tag_GNU_Power_ABI_Vector 8 +#endif + +static void +dump_ppc_attributes(uint8_t *p, uint8_t *pe) +{ + uint64_t tag, val; + + while (p < pe) { + tag = _decode_uleb128(&p); + switch (tag) { + case Tag_GNU_Power_ABI_FP: + val = _decode_uleb128(&p); + printf(" Tag_GNU_Power_ABI_FP: %s\n", ppc_abi_fp(val)); + break; + case Tag_GNU_Power_ABI_Vector: + val = _decode_uleb128(&p); + printf(" Tag_GNU_Power_ABI_Vector: %s\n", + ppc_abi_vector(val)); + break; + case 32: /* Tag_compatibility */ + p = dump_compatibility_tag(p); + break; + default: + p = dump_unknown_tag(tag, p); + break; + } + } +} + +static void +dump_attributes(struct readelf *re) +{ + struct section *s; + Elf_Data *d; + uint8_t *p, *sp; + size_t len, seclen, nlen, sublen; + uint64_t val; + int tag, i, elferr; + + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->type != SHT_GNU_ATTRIBUTES && + (re->ehdr.e_machine != EM_ARM || s->type != SHT_LOPROC + 3)) + continue; + (void) elf_errno(); + if ((d = elf_rawdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_rawdata failed: %s", + elf_errmsg(elferr)); + continue; + } + if (d->d_size <= 0) + continue; + p = d->d_buf; + if (*p != 'A') { + printf("Unknown Attribute Section Format: %c\n", + (char) *p); + continue; + } + len = d->d_size - 1; + p++; + while (len > 0) { + seclen = re->dw_decode(&p, 4); + if (seclen > len) { + warnx("invalid attribute section length"); + break; + } + len -= seclen; + printf("Attribute Section: %s\n", (char *) p); + nlen = strlen((char *) p) + 1; + p += nlen; + seclen -= nlen + 4; + while (seclen > 0) { + sp = p; + tag = *p++; + sublen = re->dw_decode(&p, 4); + if (sublen > seclen) { + warnx("invalid attribute sub-section" + " length"); + break; + } + seclen -= sublen; + printf("%s", top_tag(tag)); + if (tag == 2 || tag == 3) { + putchar(':'); + for (;;) { + val = _decode_uleb128(&p); + if (val == 0) + break; + printf(" %ju", (uintmax_t) val); + } + } + putchar('\n'); + if (re->ehdr.e_machine == EM_ARM && + s->type == SHT_LOPROC + 3) + dump_arm_attributes(re, p, sp + sublen); + else if (re->ehdr.e_machine == EM_MIPS || + re->ehdr.e_machine == EM_MIPS_RS3_LE) + dump_mips_attributes(re, p, + sp + sublen); + else if (re->ehdr.e_machine == EM_PPC) + dump_ppc_attributes(p, sp + sublen); + p = sp + sublen; + } + } + } +} + +static void +dump_mips_specific_info(struct readelf *re) +{ + struct section *s; + int i, options_found; + + options_found = 0; + s = NULL; + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->name != NULL && (!strcmp(s->name, ".MIPS.options") || + (s->type == SHT_MIPS_OPTIONS))) { + dump_mips_options(re, s); + options_found = 1; + } + } + + /* + * According to SGI mips64 spec, .reginfo should be ignored if + * .MIPS.options section is present. + */ + if (!options_found) { + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->name != NULL && (!strcmp(s->name, ".reginfo") || + (s->type == SHT_MIPS_REGINFO))) + dump_mips_reginfo(re, s); + } + } +} + +static void +dump_mips_reginfo(struct readelf *re, struct section *s) +{ + Elf_Data *d; + int elferr; + + (void) elf_errno(); + if ((d = elf_rawdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_rawdata failed: %s", + elf_errmsg(elferr)); + return; + } + if (d->d_size <= 0) + return; + + printf("\nSection '%s' contains %ju entries:\n", s->name, + s->sz / s->entsize); + dump_mips_odk_reginfo(re, d->d_buf, d->d_size); +} + +static void +dump_mips_options(struct readelf *re, struct section *s) +{ + Elf_Data *d; + uint32_t info; + uint16_t sndx; + uint8_t *p, *pe; + uint8_t kind, size; + int elferr; + + (void) elf_errno(); + if ((d = elf_rawdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_rawdata failed: %s", + elf_errmsg(elferr)); + return; + } + if (d->d_size == 0) + return; + + printf("\nSection %s contains:\n", s->name); + p = d->d_buf; + pe = p + d->d_size; + while (p < pe) { + kind = re->dw_decode(&p, 1); + size = re->dw_decode(&p, 1); + sndx = re->dw_decode(&p, 2); + info = re->dw_decode(&p, 4); + switch (kind) { + case ODK_REGINFO: + dump_mips_odk_reginfo(re, p, size - 8); + break; + case ODK_EXCEPTIONS: + printf(" EXCEPTIONS FPU_MIN: %#x\n", + info & OEX_FPU_MIN); + printf("%11.11s FPU_MAX: %#x\n", "", + info & OEX_FPU_MAX); + dump_mips_option_flags("", mips_exceptions_option, + info); + break; + case ODK_PAD: + printf(" %-10.10s section: %ju\n", "OPAD", + (uintmax_t) sndx); + dump_mips_option_flags("", mips_pad_option, info); + break; + case ODK_HWPATCH: + dump_mips_option_flags("HWPATCH", mips_hwpatch_option, + info); + break; + case ODK_HWAND: + dump_mips_option_flags("HWAND", mips_hwa_option, info); + break; + case ODK_HWOR: + dump_mips_option_flags("HWOR", mips_hwo_option, info); + break; + case ODK_FILL: + printf(" %-10.10s %#jx\n", "FILL", (uintmax_t) info); + break; + case ODK_TAGS: + printf(" %-10.10s\n", "TAGS"); + break; + case ODK_GP_GROUP: + printf(" %-10.10s GP group number: %#x\n", "GP_GROUP", + info & 0xFFFF); + if (info & 0x10000) + printf(" %-10.10s GP group is " + "self-contained\n", ""); + break; + case ODK_IDENT: + printf(" %-10.10s default GP group number: %#x\n", + "IDENT", info & 0xFFFF); + if (info & 0x10000) + printf(" %-10.10s default GP group is " + "self-contained\n", ""); + break; + case ODK_PAGESIZE: + printf(" %-10.10s\n", "PAGESIZE"); + break; + default: + break; + } + p += size - 8; + } +} + +static void +dump_mips_option_flags(const char *name, struct mips_option *opt, uint64_t info) +{ + int first; + + first = 1; + for (; opt->desc != NULL; opt++) { + if (info & opt->flag) { + printf(" %-10.10s %s\n", first ? name : "", + opt->desc); + first = 0; + } + } +} + +static void +dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz) +{ + uint32_t ri_gprmask; + uint32_t ri_cprmask[4]; + uint64_t ri_gp_value; + uint8_t *pe; + int i; + + pe = p + sz; + while (p < pe) { + ri_gprmask = re->dw_decode(&p, 4); + /* Skip ri_pad padding field for mips64. */ + if (re->ec == ELFCLASS64) + re->dw_decode(&p, 4); + for (i = 0; i < 4; i++) + ri_cprmask[i] = re->dw_decode(&p, 4); + if (re->ec == ELFCLASS32) + ri_gp_value = re->dw_decode(&p, 4); + else + ri_gp_value = re->dw_decode(&p, 8); + printf(" %s ", option_kind(ODK_REGINFO)); + printf("ri_gprmask: 0x%08jx\n", (uintmax_t) ri_gprmask); + for (i = 0; i < 4; i++) + printf("%11.11s ri_cprmask[%d]: 0x%08jx\n", "", i, + (uintmax_t) ri_cprmask[i]); + printf("%12.12s", ""); + printf("ri_gp_value: %#jx\n", (uintmax_t) ri_gp_value); + } +} + +static void +dump_arch_specific_info(struct readelf *re) +{ + + dump_liblist(re); + dump_attributes(re); + + switch (re->ehdr.e_machine) { + case EM_MIPS: + case EM_MIPS_RS3_LE: + dump_mips_specific_info(re); + default: + break; + } +} + +static void +dump_dwarf_line(struct readelf *re) +{ + struct section *s; + Dwarf_Die die; + Dwarf_Error de; + Dwarf_Half tag, version, pointer_size; + Dwarf_Unsigned offset, endoff, length, hdrlen, dirndx, mtime, fsize; + Dwarf_Small minlen, defstmt, lrange, opbase, oplen; + Elf_Data *d; + char *pn; + uint64_t address, file, line, column, isa, opsize, udelta; + int64_t sdelta; + uint8_t *p, *pe; + int8_t lbase; + int is_stmt, basic_block, end_sequence; + int prologue_end, epilogue_begin; + int i, dwarf_size, elferr, ret; + + printf("\nDump of debug contents of section .debug_line:\n"); + + s = NULL; + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->name != NULL && !strcmp(s->name, ".debug_line")) + break; + } + if ((size_t) i >= re->shnum) + return; + + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + return; + } + if (d->d_size <= 0) + return; + + while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL, + NULL, &de)) == DW_DLV_OK) { + die = NULL; + while (dwarf_siblingof(re->dbg, die, &die, &de) == DW_DLV_OK) { + if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_tag failed: %s", + dwarf_errmsg(de)); + return; + } + /* XXX: What about DW_TAG_partial_unit? */ + if (tag == DW_TAG_compile_unit) + break; + } + if (die == NULL) { + warnx("could not find DW_TAG_compile_unit die"); + return; + } + if (dwarf_attrval_unsigned(die, DW_AT_stmt_list, &offset, + &de) != DW_DLV_OK) + continue; + + length = re->dw_read(d, &offset, 4); + if (length == 0xffffffff) { + dwarf_size = 8; + length = re->dw_read(d, &offset, 8); + } else + dwarf_size = 4; + + if (length > d->d_size - offset) { + warnx("invalid .dwarf_line section"); + continue; + } + + endoff = offset + length; + version = re->dw_read(d, &offset, 2); + hdrlen = re->dw_read(d, &offset, dwarf_size); + minlen = re->dw_read(d, &offset, 1); + defstmt = re->dw_read(d, &offset, 1); + lbase = re->dw_read(d, &offset, 1); + lrange = re->dw_read(d, &offset, 1); + opbase = re->dw_read(d, &offset, 1); + + printf("\n"); + printf(" Length:\t\t\t%ju\n", (uintmax_t) length); + printf(" DWARF version:\t\t%u\n", version); + printf(" Prologue Length:\t\t%ju\n", (uintmax_t) hdrlen); + printf(" Minimum Instruction Length:\t%u\n", minlen); + printf(" Initial value of 'is_stmt':\t%u\n", defstmt); + printf(" Line Base:\t\t\t%d\n", lbase); + printf(" Line Range:\t\t\t%u\n", lrange); + printf(" Opcode Base:\t\t\t%u\n", opbase); + (void) dwarf_get_address_size(re->dbg, &pointer_size, &de); + printf(" (Pointer size:\t\t%u)\n", pointer_size); + + printf("\n"); + printf(" Opcodes:\n"); + for (i = 1; i < opbase; i++) { + oplen = re->dw_read(d, &offset, 1); + printf(" Opcode %d has %u args\n", i, oplen); + } + + printf("\n"); + printf(" The Directory Table:\n"); + p = (uint8_t *) d->d_buf + offset; + while (*p != '\0') { + printf(" %s\n", (char *) p); + p += strlen((char *) p) + 1; + } + + p++; + printf("\n"); + printf(" The File Name Table:\n"); + printf(" Entry\tDir\tTime\tSize\tName\n"); + i = 0; + while (*p != '\0') { + i++; + pn = (char *) p; + p += strlen(pn) + 1; + dirndx = _decode_uleb128(&p); + mtime = _decode_uleb128(&p); + fsize = _decode_uleb128(&p); + printf(" %d\t%ju\t%ju\t%ju\t%s\n", i, + (uintmax_t) dirndx, (uintmax_t) mtime, + (uintmax_t) fsize, pn); + } + +#define RESET_REGISTERS \ + do { \ + address = 0; \ + file = 1; \ + line = 1; \ + column = 0; \ + is_stmt = defstmt; \ + basic_block = 0; \ + end_sequence = 0; \ + prologue_end = 0; \ + epilogue_begin = 0; \ + } while(0) + +#define LINE(x) (lbase + (((x) - opbase) % lrange)) +#define ADDRESS(x) ((((x) - opbase) / lrange) * minlen) + + p++; + pe = (uint8_t *) d->d_buf + endoff; + printf("\n"); + printf(" Line Number Statements:\n"); + + RESET_REGISTERS; + + while (p < pe) { + + if (*p == 0) { + /* + * Extended Opcodes. + */ + p++; + opsize = _decode_uleb128(&p); + printf(" Extended opcode %u: ", *p); + switch (*p) { + case DW_LNE_end_sequence: + p++; + end_sequence = 1; + RESET_REGISTERS; + printf("End of Sequence\n"); + break; + case DW_LNE_set_address: + p++; + address = re->dw_decode(&p, + pointer_size); + printf("set Address to %#jx\n", + (uintmax_t) address); + break; + case DW_LNE_define_file: + p++; + pn = (char *) p; + p += strlen(pn) + 1; + dirndx = _decode_uleb128(&p); + mtime = _decode_uleb128(&p); + fsize = _decode_uleb128(&p); + printf("define new file: %s\n", pn); + break; + default: + /* Unrecognized extened opcodes. */ + p += opsize; + printf("unknown opcode\n"); + } + } else if (*p > 0 && *p < opbase) { + /* + * Standard Opcodes. + */ + switch(*p++) { + case DW_LNS_copy: + basic_block = 0; + prologue_end = 0; + epilogue_begin = 0; + printf(" Copy\n"); + break; + case DW_LNS_advance_pc: + udelta = _decode_uleb128(&p) * + minlen; + address += udelta; + printf(" Advance PC by %ju to %#jx\n", + (uintmax_t) udelta, + (uintmax_t) address); + break; + case DW_LNS_advance_line: + sdelta = _decode_sleb128(&p); + line += sdelta; + printf(" Advance Line by %jd to %ju\n", + (intmax_t) sdelta, + (uintmax_t) line); + break; + case DW_LNS_set_file: + file = _decode_uleb128(&p); + printf(" Set File to %ju\n", + (uintmax_t) file); + break; + case DW_LNS_set_column: + column = _decode_uleb128(&p); + printf(" Set Column to %ju\n", + (uintmax_t) column); + break; + case DW_LNS_negate_stmt: + is_stmt = !is_stmt; + printf(" Set is_stmt to %d\n", is_stmt); + break; + case DW_LNS_set_basic_block: + basic_block = 1; + printf(" Set basic block flag\n"); + break; + case DW_LNS_const_add_pc: + address += ADDRESS(255); + printf(" Advance PC by constant %ju" + " to %#jx\n", + (uintmax_t) ADDRESS(255), + (uintmax_t) address); + break; + case DW_LNS_fixed_advance_pc: + udelta = re->dw_decode(&p, 2); + address += udelta; + printf(" Advance PC by fixed value " + "%ju to %#jx\n", + (uintmax_t) udelta, + (uintmax_t) address); + break; + case DW_LNS_set_prologue_end: + prologue_end = 1; + printf(" Set prologue end flag\n"); + break; + case DW_LNS_set_epilogue_begin: + epilogue_begin = 1; + printf(" Set epilogue begin flag\n"); + break; + case DW_LNS_set_isa: + isa = _decode_uleb128(&p); + printf(" Set isa to %ju\n", isa); + break; + default: + /* Unrecognized extended opcodes. */ + printf(" Unknown extended opcode %u\n", + *(p - 1)); + break; + } + + } else { + /* + * Special Opcodes. + */ + line += LINE(*p); + address += ADDRESS(*p); + basic_block = 0; + prologue_end = 0; + epilogue_begin = 0; + printf(" Special opcode %u: advance Address " + "by %ju to %#jx and Line by %jd to %ju\n", + *p - opbase, (uintmax_t) ADDRESS(*p), + (uintmax_t) address, (intmax_t) LINE(*p), + (uintmax_t) line); + p++; + } + + + } + } + if (ret == DW_DLV_ERROR) + warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); + +#undef RESET_REGISTERS +#undef LINE +#undef ADDRESS +} + +static void +dump_dwarf_line_decoded(struct readelf *re) +{ + Dwarf_Die die; + Dwarf_Line *linebuf, ln; + Dwarf_Addr lineaddr; + Dwarf_Signed linecount, srccount; + Dwarf_Unsigned lineno, fn; + Dwarf_Error de; + const char *dir, *file; + char **srcfiles; + int i, ret; + + printf("Decoded dump of debug contents of section .debug_line:\n\n"); + while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL, + NULL, &de)) == DW_DLV_OK) { + if (dwarf_siblingof(re->dbg, NULL, &die, &de) != DW_DLV_OK) + continue; + if (dwarf_attrval_string(die, DW_AT_name, &file, &de) != + DW_DLV_OK) + file = NULL; + if (dwarf_attrval_string(die, DW_AT_comp_dir, &dir, &de) != + DW_DLV_OK) + dir = NULL; + printf("CU: "); + if (dir && file) + printf("%s/", dir); + if (file) + printf("%s", file); + putchar('\n'); + printf("%-37s %11s %s\n", "Filename", "Line Number", + "Starting Address"); + if (dwarf_srclines(die, &linebuf, &linecount, &de) != DW_DLV_OK) + continue; + if (dwarf_srcfiles(die, &srcfiles, &srccount, &de) != DW_DLV_OK) + continue; + for (i = 0; i < linecount; i++) { + ln = linebuf[i]; + if (dwarf_line_srcfileno(ln, &fn, &de) != DW_DLV_OK) + continue; + if (dwarf_lineno(ln, &lineno, &de) != DW_DLV_OK) + continue; + if (dwarf_lineaddr(ln, &lineaddr, &de) != DW_DLV_OK) + continue; + printf("%-37s %11ju %#18jx\n", + basename(srcfiles[fn - 1]), (uintmax_t) lineno, + (uintmax_t) lineaddr); + } + putchar('\n'); + } +} + +static void +dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level) +{ + Dwarf_Attribute *attr_list; + Dwarf_Die ret_die; + Dwarf_Off dieoff, cuoff, culen; + Dwarf_Unsigned ate, v_udata; + Dwarf_Signed attr_count, v_sdata; + Dwarf_Off v_off; + Dwarf_Addr v_addr; + Dwarf_Half tag, attr, form; + Dwarf_Block *v_block; + Dwarf_Bool v_bool; + Dwarf_Error de; + const char *tag_str, *attr_str, *ate_str; + char *v_str; + uint8_t *b; + int i, j, abc, ret; + + if (dwarf_dieoffset(die, &dieoff, &de) != DW_DLV_OK) { + warnx("dwarf_dieoffset failed: %s", dwarf_errmsg(de)); + goto cont_search; + } + + printf("<%d><%jx>: ", level, (uintmax_t) dieoff); + + if (dwarf_die_CU_offset_range(die, &cuoff, &culen, &de) != DW_DLV_OK) { + warnx("dwarf_die_CU_offset_range failed: %s", + dwarf_errmsg(de)); + cuoff = 0; + } + + abc = dwarf_die_abbrev_code(die); + if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); + goto cont_search; + } + if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) { + warnx("dwarf_get_TAG_name failed"); + goto cont_search; + } + + printf("Abbrev Number: %d (%s)\n", abc, tag_str); + + if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) != + DW_DLV_OK) { + if (ret == DW_DLV_ERROR) + warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de)); + goto cont_search; + } + + for (i = 0; i < attr_count; i++) { + if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) { + warnx("dwarf_whatform failed: %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) { + warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_get_AT_name(attr, &attr_str) != DW_DLV_OK) { + warnx("dwarf_get_AT_name failed"); + continue; + } + printf(" %-18s: ", attr_str); + switch (form) { + case DW_FORM_ref_addr: + if (dwarf_global_formref(attr_list[i], &v_off, &de) != + DW_DLV_OK) { + warnx("dwarf_global_formref failed: %s", + dwarf_errmsg(de)); + continue; + } + printf("<%jx>", (uintmax_t) v_off); + break; + + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + if (dwarf_formref(attr_list[i], &v_off, &de) != + DW_DLV_OK) { + warnx("dwarf_formref failed: %s", + dwarf_errmsg(de)); + continue; + } + v_off += cuoff; + printf("<%jx>", (uintmax_t) v_off); + break; + + case DW_FORM_addr: + if (dwarf_formaddr(attr_list[i], &v_addr, &de) != + DW_DLV_OK) { + warnx("dwarf_formaddr failed: %s", + dwarf_errmsg(de)); + continue; + } + printf("%#jx", (uintmax_t) v_addr); + break; + + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_udata: + if (dwarf_formudata(attr_list[i], &v_udata, &de) != + DW_DLV_OK) { + warnx("dwarf_formudata failed: %s", + dwarf_errmsg(de)); + continue; + } + printf("%ju", (uintmax_t) v_udata); + break; + + case DW_FORM_sdata: + if (dwarf_formsdata(attr_list[i], &v_sdata, &de) != + DW_DLV_OK) { + warnx("dwarf_formudata failed: %s", + dwarf_errmsg(de)); + continue; + } + printf("%jd", (intmax_t) v_sdata); + break; + + case DW_FORM_flag: + if (dwarf_formflag(attr_list[i], &v_bool, &de) != + DW_DLV_OK) { + warnx("dwarf_formflag failed: %s", + dwarf_errmsg(de)); + continue; + } + printf("%jd", (intmax_t) v_bool); + break; + + case DW_FORM_string: + case DW_FORM_strp: + if (dwarf_formstring(attr_list[i], &v_str, &de) != + DW_DLV_OK) { + warnx("dwarf_formstring failed: %s", + dwarf_errmsg(de)); + continue; + } + if (form == DW_FORM_string) + printf("%s", v_str); + else + printf("(indirect string) %s", v_str); + break; + + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + if (dwarf_formblock(attr_list[i], &v_block, &de) != + DW_DLV_OK) { + warnx("dwarf_formblock failed: %s", + dwarf_errmsg(de)); + continue; + } + printf("%ju byte block:", v_block->bl_len); + b = v_block->bl_data; + for (j = 0; (Dwarf_Unsigned) j < v_block->bl_len; j++) + printf(" %x", b[j]); + break; + } + switch (attr) { + case DW_AT_encoding: + if (dwarf_attrval_unsigned(die, attr, &ate, &de) != + DW_DLV_OK) + break; + if (dwarf_get_ATE_name(ate, &ate_str) != DW_DLV_OK) + break; + printf("\t(%s)", &ate_str[strlen("DW_ATE_")]); + break; + default: + break; + } + putchar('\n'); + } + + +cont_search: + /* Search children. */ + ret = dwarf_child(die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_child: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + dump_dwarf_die(re, ret_die, level + 1); + + /* Search sibling. */ + ret = dwarf_siblingof(re->dbg, die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_siblingof: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + dump_dwarf_die(re, ret_die, level); + + dwarf_dealloc(re->dbg, die, DW_DLA_DIE); +} + +static void +dump_dwarf_info(struct readelf *re) +{ + struct section *s; + Dwarf_Die die; + Dwarf_Error de; + Dwarf_Half tag, version, pointer_size; + Dwarf_Off cu_offset, cu_length; + Dwarf_Off aboff; + Elf_Data *d; + int i, elferr, ret; + + printf("\nDump of debug contents of section .debug_info:\n"); + + s = NULL; + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->name != NULL && !strcmp(s->name, ".debug_info")) + break; + } + if ((size_t) i >= re->shnum) + return; + + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + return; + } + if (d->d_size <= 0) + return; + + while ((ret = dwarf_next_cu_header(re->dbg, NULL, &version, &aboff, + &pointer_size, NULL, &de)) == DW_DLV_OK) { + die = NULL; + while (dwarf_siblingof(re->dbg, die, &die, &de) == DW_DLV_OK) { + if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_tag failed: %s", + dwarf_errmsg(de)); + return; + } + /* XXX: What about DW_TAG_partial_unit? */ + if (tag == DW_TAG_compile_unit) + break; + } + if (die == NULL) { + warnx("could not find DW_TAG_compile_unit die"); + return; + } + + if (dwarf_die_CU_offset_range(die, &cu_offset, &cu_length, + &de) != DW_DLV_OK) { + warnx("dwarf_die_CU_offset failed: %s", + dwarf_errmsg(de)); + continue; + } + + printf(" Compilation Unit @ %jd:\n", (intmax_t) cu_offset); + printf(" Length:\t\t%jd\n", (intmax_t) cu_length); + printf(" Version:\t\t%u\n", version); + printf(" Abbrev Offset:\t%ju\n", (uintmax_t) aboff); + printf(" Pointer Size:\t%u\n", pointer_size); + + dump_dwarf_die(re, die, 0); + } + if (ret == DW_DLV_ERROR) + warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); +} + +static void +dump_dwarf_abbrev(struct readelf *re) +{ + Dwarf_Abbrev ab; + Dwarf_Off aboff, atoff; + Dwarf_Unsigned length, attr_count; + Dwarf_Signed flag, form; + Dwarf_Half tag, attr; + Dwarf_Error de; + const char *tag_str, *attr_str, *form_str; + int i, j, ret; + + printf("\nContents of section .debug_abbrev:\n\n"); + + while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, &aboff, + NULL, NULL, &de)) == DW_DLV_OK) { + printf(" Number TAG\n"); + i = 0; + while ((ret = dwarf_get_abbrev(re->dbg, aboff, &ab, &length, + &attr_count, &de)) == DW_DLV_OK) { + if (length == 1) { + dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV); + break; + } + aboff += length; + printf("%4d", ++i); + if (dwarf_get_abbrev_tag(ab, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_get_abbrev_tag failed: %s", + dwarf_errmsg(de)); + goto next_abbrev; + } + if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) { + warnx("dwarf_get_TAG_name failed"); + goto next_abbrev; + } + if (dwarf_get_abbrev_children_flag(ab, &flag, &de) != + DW_DLV_OK) { + warnx("dwarf_get_abbrev_children_flag failed:" + " %s", dwarf_errmsg(de)); + goto next_abbrev; + } + printf(" %s %s\n", tag_str, + flag ? "[has children]" : "[no children]"); + for (j = 0; (Dwarf_Unsigned) j < attr_count; j++) { + if (dwarf_get_abbrev_entry(ab, (Dwarf_Signed) j, + &attr, &form, &atoff, &de) != DW_DLV_OK) { + warnx("dwarf_get_abbrev_entry failed:" + " %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_get_AT_name(attr, &attr_str) != + DW_DLV_OK) { + warnx("dwarf_get_AT_name failed"); + continue; + } + if (dwarf_get_FORM_name(form, &form_str) != + DW_DLV_OK) { + warnx("dwarf_get_FORM_name failed"); + continue; + } + printf(" %-18s %s\n", attr_str, form_str); + } + next_abbrev: + dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV); + } + if (ret != DW_DLV_OK) + warnx("dwarf_get_abbrev: %s", dwarf_errmsg(de)); + } + if (ret == DW_DLV_ERROR) + warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); +} + +static void +dump_dwarf_pubnames(struct readelf *re) +{ + struct section *s; + Dwarf_Off die_off; + Dwarf_Unsigned offset, length, nt_cu_offset, nt_cu_length; + Dwarf_Signed cnt; + Dwarf_Global *globs; + Dwarf_Half nt_version; + Dwarf_Error de; + Elf_Data *d; + char *glob_name; + int i, dwarf_size, elferr; + + printf("\nContents of the .debug_pubnames section:\n"); + + s = NULL; + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->name != NULL && !strcmp(s->name, ".debug_pubnames")) + break; + } + if ((size_t) i >= re->shnum) + return; + + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + return; + } + if (d->d_size <= 0) + return; + + /* Read in .debug_pubnames section table header. */ + offset = 0; + length = re->dw_read(d, &offset, 4); + if (length == 0xffffffff) { + dwarf_size = 8; + length = re->dw_read(d, &offset, 8); + } else + dwarf_size = 4; + + if (length > d->d_size - offset) { + warnx("invalid .dwarf_pubnames section"); + return; + } + + nt_version = re->dw_read(d, &offset, 2); + nt_cu_offset = re->dw_read(d, &offset, dwarf_size); + nt_cu_length = re->dw_read(d, &offset, dwarf_size); + printf(" Length:\t\t\t\t%ju\n", (uintmax_t) length); + printf(" Version:\t\t\t\t%u\n", nt_version); + printf(" Offset into .debug_info section:\t%ju\n", + (uintmax_t) nt_cu_offset); + printf(" Size of area in .debug_info section:\t%ju\n", + (uintmax_t) nt_cu_length); + + if (dwarf_get_globals(re->dbg, &globs, &cnt, &de) != DW_DLV_OK) { + warnx("dwarf_get_globals failed: %s", dwarf_errmsg(de)); + return; + } + + printf("\n Offset Name\n"); + for (i = 0; i < cnt; i++) { + if (dwarf_globname(globs[i], &glob_name, &de) != DW_DLV_OK) { + warnx("dwarf_globname failed: %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_global_die_offset(globs[i], &die_off, &de) != + DW_DLV_OK) { + warnx("dwarf_global_die_offset failed: %s", + dwarf_errmsg(de)); + continue; + } + printf(" %-11ju %s\n", (uintmax_t) die_off, glob_name); + } +} + +static void +dump_dwarf_aranges(struct readelf *re) +{ + struct section *s; + Dwarf_Arange *aranges; + Dwarf_Addr start; + Dwarf_Unsigned offset, length, as_cu_offset; + Dwarf_Off die_off; + Dwarf_Signed cnt; + Dwarf_Half as_version, as_addrsz, as_segsz; + Dwarf_Error de; + Elf_Data *d; + int i, dwarf_size, elferr; + + printf("\nContents of section .debug_aranges:\n"); + + s = NULL; + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->name != NULL && !strcmp(s->name, ".debug_aranges")) + break; + } + if ((size_t) i >= re->shnum) + return; + + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + return; + } + if (d->d_size <= 0) + return; + + /* Read in the .debug_aranges section table header. */ + offset = 0; + length = re->dw_read(d, &offset, 4); + if (length == 0xffffffff) { + dwarf_size = 8; + length = re->dw_read(d, &offset, 8); + } else + dwarf_size = 4; + + if (length > d->d_size - offset) { + warnx("invalid .dwarf_aranges section"); + return; + } + + as_version = re->dw_read(d, &offset, 2); + as_cu_offset = re->dw_read(d, &offset, dwarf_size); + as_addrsz = re->dw_read(d, &offset, 1); + as_segsz = re->dw_read(d, &offset, 1); + + printf(" Length:\t\t\t%ju\n", (uintmax_t) length); + printf(" Version:\t\t\t%u\n", as_version); + printf(" Offset into .debug_info:\t%ju\n", (uintmax_t) as_cu_offset); + printf(" Pointer Size:\t\t\t%u\n", as_addrsz); + printf(" Segment Size:\t\t\t%u\n", as_segsz); + + if (dwarf_get_aranges(re->dbg, &aranges, &cnt, &de) != DW_DLV_OK) { + warnx("dwarf_get_aranges failed: %s", dwarf_errmsg(de)); + return; + } + + printf("\n Address Length\n"); + for (i = 0; i < cnt; i++) { + if (dwarf_get_arange_info(aranges[i], &start, &length, + &die_off, &de) != DW_DLV_OK) { + warnx("dwarf_get_arange_info failed: %s", + dwarf_errmsg(de)); + continue; + } + printf(" %08jx %ju\n", (uintmax_t) start, + (uintmax_t) length); + } +} + +static void +dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, Dwarf_Addr base) +{ + Dwarf_Attribute *attr_list; + Dwarf_Ranges *ranges; + Dwarf_Die ret_die; + Dwarf_Error de; + Dwarf_Addr base0; + Dwarf_Half attr; + Dwarf_Signed attr_count, cnt; + Dwarf_Unsigned off, bytecnt; + int i, j, ret; + + if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) != + DW_DLV_OK) { + if (ret == DW_DLV_ERROR) + warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de)); + goto cont_search; + } + + for (i = 0; i < attr_count; i++) { + if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) { + warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de)); + continue; + } + if (attr != DW_AT_ranges) + continue; + if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) { + warnx("dwarf_formudata failed: %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_get_ranges(re->dbg, (Dwarf_Off) off, &ranges, &cnt, + &bytecnt, &de) != DW_DLV_OK) + continue; + base0 = base; + for (j = 0; j < cnt; j++) { + printf(" %08jx ", (uintmax_t) off); + if (ranges[j].dwr_type == DW_RANGES_END) { + printf("%s\n", ""); + continue; + } else if (ranges[j].dwr_type == + DW_RANGES_ADDRESS_SELECTION) { + base0 = ranges[j].dwr_addr2; + continue; + } + if (re->ec == ELFCLASS32) + printf("%08jx %08jx\n", + ranges[j].dwr_addr1 + base0, + ranges[j].dwr_addr2 + base0); + else + printf("%016jx %016jx\n", + ranges[j].dwr_addr1 + base0, + ranges[j].dwr_addr2 + base0); + } + } + +cont_search: + /* Search children. */ + ret = dwarf_child(die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_child: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + dump_dwarf_ranges_foreach(re, ret_die, base); + + /* Search sibling. */ + ret = dwarf_siblingof(re->dbg, die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_siblingof: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + dump_dwarf_ranges_foreach(re, ret_die, base); +} + +static void +dump_dwarf_ranges(struct readelf *re) +{ + Dwarf_Ranges *ranges; + Dwarf_Die die; + Dwarf_Signed cnt; + Dwarf_Unsigned bytecnt; + Dwarf_Half tag; + Dwarf_Error de; + Dwarf_Unsigned lowpc; + int ret; + + if (dwarf_get_ranges(re->dbg, 0, &ranges, &cnt, &bytecnt, &de) != + DW_DLV_OK) + return; + + printf("Contents of the .debug_ranges section:\n\n"); + if (re->ec == ELFCLASS32) + printf(" %-8s %-8s %s\n", "Offset", "Begin", "End"); + else + printf(" %-8s %-16s %s\n", "Offset", "Begin", "End"); + + while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL, + NULL, &de)) == DW_DLV_OK) { + die = NULL; + if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK) + continue; + if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); + continue; + } + /* XXX: What about DW_TAG_partial_unit? */ + lowpc = 0; + if (tag == DW_TAG_compile_unit) { + if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lowpc, + &de) != DW_DLV_OK) + lowpc = 0; + } + + dump_dwarf_ranges_foreach(re, die, (Dwarf_Addr) lowpc); + } + putchar('\n'); +} + +static void +dump_dwarf_macinfo(struct readelf *re) +{ + Dwarf_Unsigned offset; + Dwarf_Signed cnt; + Dwarf_Macro_Details *md; + Dwarf_Error de; + const char *mi_str; + int i; + +#define _MAX_MACINFO_ENTRY 65535 + + printf("\nContents of section .debug_macinfo:\n\n"); + + offset = 0; + while (dwarf_get_macro_details(re->dbg, offset, _MAX_MACINFO_ENTRY, + &cnt, &md, &de) == DW_DLV_OK) { + for (i = 0; i < cnt; i++) { + offset = md[i].dmd_offset + 1; + if (md[i].dmd_type == 0) + break; + if (dwarf_get_MACINFO_name(md[i].dmd_type, &mi_str) != + DW_DLV_OK) { + warnx("dwarf_get_MACINFO_name failed: %s", + dwarf_errmsg(de)); + continue; + } + printf(" %s", mi_str); + switch (md[i].dmd_type) { + case DW_MACINFO_define: + case DW_MACINFO_undef: + printf(" - lineno : %jd macro : %s\n", + (intmax_t) md[i].dmd_lineno, + md[i].dmd_macro); + break; + case DW_MACINFO_start_file: + printf(" - lineno : %jd filenum : %jd\n", + (intmax_t) md[i].dmd_lineno, + (intmax_t) md[i].dmd_fileindex); + break; + default: + putchar('\n'); + break; + } + } + } + +#undef _MAX_MACINFO_ENTRY +} + +static void +dump_dwarf_frame_inst(Dwarf_Cie cie, uint8_t *insts, Dwarf_Unsigned len, + Dwarf_Unsigned caf, Dwarf_Signed daf, Dwarf_Addr pc, Dwarf_Debug dbg) +{ + Dwarf_Frame_Op *oplist; + Dwarf_Signed opcnt, delta; + Dwarf_Small op; + Dwarf_Error de; + const char *op_str; + int i; + + if (dwarf_expand_frame_instructions(cie, insts, len, &oplist, + &opcnt, &de) != DW_DLV_OK) { + warnx("dwarf_expand_frame_instructions failed: %s", + dwarf_errmsg(de)); + return; + } + + for (i = 0; i < opcnt; i++) { + if (oplist[i].fp_base_op != 0) + op = oplist[i].fp_base_op << 6; + else + op = oplist[i].fp_extended_op; + if (dwarf_get_CFA_name(op, &op_str) != DW_DLV_OK) { + warnx("dwarf_get_CFA_name failed: %s", + dwarf_errmsg(de)); + continue; + } + printf(" %s", op_str); + switch (op) { + case DW_CFA_advance_loc: + delta = oplist[i].fp_offset * caf; + pc += delta; + printf(": %ju to %08jx", (uintmax_t) delta, + (uintmax_t) pc); + break; + case DW_CFA_offset: + case DW_CFA_offset_extended: + case DW_CFA_offset_extended_sf: + delta = oplist[i].fp_offset * daf; + printf(": r%u at cfa%+jd", oplist[i].fp_register, + (intmax_t) delta); + break; + case DW_CFA_restore: + printf(": r%u", oplist[i].fp_register); + break; + case DW_CFA_set_loc: + pc = oplist[i].fp_offset; + printf(": to %08jx", (uintmax_t) pc); + break; + case DW_CFA_advance_loc1: + case DW_CFA_advance_loc2: + case DW_CFA_advance_loc4: + pc += oplist[i].fp_offset; + printf(": %jd to %08jx", (intmax_t) oplist[i].fp_offset, + (uintmax_t) pc); + break; + case DW_CFA_def_cfa: + printf(": r%u ofs %ju", oplist[i].fp_register, + (uintmax_t) oplist[i].fp_offset); + break; + case DW_CFA_def_cfa_sf: + printf(": r%u ofs %jd", oplist[i].fp_register, + (intmax_t) (oplist[i].fp_offset * daf)); + break; + case DW_CFA_def_cfa_register: + printf(": r%u", oplist[i].fp_register); + break; + case DW_CFA_def_cfa_offset: + printf(": %ju", (uintmax_t) oplist[i].fp_offset); + break; + case DW_CFA_def_cfa_offset_sf: + printf(": %jd", (intmax_t) (oplist[i].fp_offset * daf)); + break; + default: + break; + } + putchar('\n'); + } + + dwarf_dealloc(dbg, oplist, DW_DLA_FRAME_BLOCK); +} + +static char * +get_regoff_str(Dwarf_Half reg, Dwarf_Addr off) +{ + static char rs[16]; + + if (reg == DW_FRAME_UNDEFINED_VAL || reg == DW_FRAME_REG_INITIAL_VALUE) + snprintf(rs, sizeof(rs), "%c", 'u'); + else if (reg == DW_FRAME_CFA_COL) + snprintf(rs, sizeof(rs), "c%+jd", (intmax_t) off); + else + snprintf(rs, sizeof(rs), "r%u%+jd", reg, (intmax_t) off); + + return (rs); +} + +static int +dump_dwarf_frame_regtable(Dwarf_Fde fde, Dwarf_Addr pc, Dwarf_Unsigned func_len, + Dwarf_Half cie_ra) +{ + Dwarf_Regtable rt; + Dwarf_Addr row_pc, end_pc, pre_pc, cur_pc; + Dwarf_Error de; + char rn[16]; + char *vec; + int i; + +#define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7)) +#define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7))) +#define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7))) +#define RT(x) rt.rules[(x)] + + vec = calloc((DW_REG_TABLE_SIZE + 7) / 8, 1); + if (vec == NULL) + err(EXIT_FAILURE, "calloc failed"); + + pre_pc = ~((Dwarf_Addr) 0); + cur_pc = pc; + end_pc = pc + func_len; + for (; cur_pc < end_pc; cur_pc++) { + if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc, + &de) != DW_DLV_OK) { + warnx("dwarf_get_fde_info_for_all_regs failed: %s\n", + dwarf_errmsg(de)); + return (-1); + } + if (row_pc == pre_pc) + continue; + pre_pc = row_pc; + for (i = 1; i < DW_REG_TABLE_SIZE; i++) { + if (rt.rules[i].dw_regnum != DW_FRAME_REG_INITIAL_VALUE) + BIT_SET(vec, i); + } + } + + printf(" LOC CFA "); + for (i = 1; i < DW_REG_TABLE_SIZE; i++) { + if (BIT_ISSET(vec, i)) { + if ((Dwarf_Half) i == cie_ra) + printf("ra "); + else { + snprintf(rn, sizeof(rn), "r%d", i); + printf("%-5s", rn); + } + } + } + putchar('\n'); + + pre_pc = ~((Dwarf_Addr) 0); + cur_pc = pc; + end_pc = pc + func_len; + for (; cur_pc < end_pc; cur_pc++) { + if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc, + &de) != DW_DLV_OK) { + warnx("dwarf_get_fde_info_for_all_regs failed: %s\n", + dwarf_errmsg(de)); + return (-1); + } + if (row_pc == pre_pc) + continue; + pre_pc = row_pc; + printf("%08jx ", (uintmax_t) row_pc); + printf("%-8s ", get_regoff_str(RT(0).dw_regnum, + RT(0).dw_offset)); + for (i = 1; i < DW_REG_TABLE_SIZE; i++) { + if (BIT_ISSET(vec, i)) { + printf("%-5s", get_regoff_str(RT(i).dw_regnum, + RT(i).dw_offset)); + } + } + putchar('\n'); + } + + free(vec); + + return (0); + +#undef BIT_SET +#undef BIT_CLR +#undef BIT_ISSET +#undef RT +} + +static void +dump_dwarf_frame_section(struct readelf *re, struct section *s, int alt) +{ + Dwarf_Cie *cie_list, cie, pre_cie; + Dwarf_Fde *fde_list, fde; + Dwarf_Off cie_offset, fde_offset; + Dwarf_Unsigned cie_length, fde_instlen; + Dwarf_Unsigned cie_caf, cie_daf, cie_instlen, func_len, fde_length; + Dwarf_Signed cie_count, fde_count, cie_index; + Dwarf_Addr low_pc; + Dwarf_Half cie_ra; + Dwarf_Small cie_version; + Dwarf_Ptr fde_addr, fde_inst, cie_inst; + char *cie_aug, c; + int i, eh_frame; + Dwarf_Error de; + + printf("\nThe section %s contains:\n\n", s->name); + + if (!strcmp(s->name, ".debug_frame")) { + eh_frame = 0; + if (dwarf_get_fde_list(re->dbg, &cie_list, &cie_count, + &fde_list, &fde_count, &de) != DW_DLV_OK) { + warnx("dwarf_get_fde_list failed: %s", + dwarf_errmsg(de)); + return; + } + } else if (!strcmp(s->name, ".eh_frame")) { + eh_frame = 1; + if (dwarf_get_fde_list_eh(re->dbg, &cie_list, &cie_count, + &fde_list, &fde_count, &de) != DW_DLV_OK) { + warnx("dwarf_get_fde_list_eh failed: %s", + dwarf_errmsg(de)); + return; + } + } else + return; + + pre_cie = NULL; + for (i = 0; i < fde_count; i++) { + if (dwarf_get_fde_n(fde_list, i, &fde, &de) != DW_DLV_OK) { + warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_get_cie_of_fde(fde, &cie, &de) != DW_DLV_OK) { + warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de)); + continue; + } + if (dwarf_get_fde_range(fde, &low_pc, &func_len, &fde_addr, + &fde_length, &cie_offset, &cie_index, &fde_offset, + &de) != DW_DLV_OK) { + warnx("dwarf_get_fde_range failed: %s", + dwarf_errmsg(de)); + continue; + } + if (dwarf_get_fde_instr_bytes(fde, &fde_inst, &fde_instlen, + &de) != DW_DLV_OK) { + warnx("dwarf_get_fde_instr_bytes failed: %s", + dwarf_errmsg(de)); + continue; + } + if (pre_cie == NULL || cie != pre_cie) { + pre_cie = cie; + if (dwarf_get_cie_info(cie, &cie_length, &cie_version, + &cie_aug, &cie_caf, &cie_daf, &cie_ra, + &cie_inst, &cie_instlen, &de) != DW_DLV_OK) { + warnx("dwarf_get_cie_info failed: %s", + dwarf_errmsg(de)); + continue; + } + printf("%08jx %08jx %8.8jx CIE", + (uintmax_t) cie_offset, + (uintmax_t) cie_length, + (uintmax_t) (eh_frame ? 0 : ~0U)); + if (!alt) { + putchar('\n'); + printf(" Version:\t\t\t%u\n", cie_version); + printf(" Augmentation:\t\t\t\""); + while ((c = *cie_aug++) != '\0') + putchar(c); + printf("\"\n"); + printf(" Code alignment factor:\t%ju\n", + (uintmax_t) cie_caf); + printf(" Data alignment factor:\t%jd\n", + (intmax_t) cie_daf); + printf(" Return address column:\t%ju\n", + (uintmax_t) cie_ra); + putchar('\n'); + dump_dwarf_frame_inst(cie, cie_inst, + cie_instlen, cie_caf, cie_daf, 0, + re->dbg); + putchar('\n'); + } else { + printf(" \""); + while ((c = *cie_aug++) != '\0') + putchar(c); + putchar('"'); + printf(" cf=%ju df=%jd ra=%ju\n", + (uintmax_t) cie_caf, + (uintmax_t) cie_daf, + (uintmax_t) cie_ra); + dump_dwarf_frame_regtable(fde, low_pc, 1, + cie_ra); + putchar('\n'); + } + } + printf("%08jx %08jx %08jx FDE cie=%08jx pc=%08jx..%08jx\n", + (uintmax_t) fde_offset, (uintmax_t) fde_length, + (uintmax_t) cie_offset, + (uintmax_t) (eh_frame ? fde_offset + 4 - cie_offset : + cie_offset), + (uintmax_t) low_pc, (uintmax_t) (low_pc + func_len)); + if (!alt) + dump_dwarf_frame_inst(cie, fde_inst, fde_instlen, + cie_caf, cie_daf, low_pc, re->dbg); + else + dump_dwarf_frame_regtable(fde, low_pc, func_len, + cie_ra); + putchar('\n'); + } +} + +static void +dump_dwarf_frame(struct readelf *re, int alt) +{ + struct section *s; + int i; + + (void) dwarf_set_frame_cfa_value(re->dbg, DW_FRAME_CFA_COL); + + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->name != NULL && (!strcmp(s->name, ".debug_frame") || + !strcmp(s->name, ".eh_frame"))) + dump_dwarf_frame_section(re, s, alt); + } +} + +static void +dump_dwarf_str(struct readelf *re) +{ + struct section *s; + Elf_Data *d; + unsigned char *p; + int elferr, end, i, j; + + printf("\nContents of section .debug_str:\n"); + + s = NULL; + for (i = 0; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (s->name != NULL && !strcmp(s->name, ".debug_str")) + break; + } + if ((size_t) i >= re->shnum) + return; + + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(-1)); + return; + } + if (d->d_size <= 0) + return; + + for (i = 0, p = d->d_buf; (size_t) i < d->d_size; i += 16) { + printf(" 0x%08x", (unsigned int) i); + if ((size_t) i + 16 > d->d_size) + end = d->d_size; + else + end = i + 16; + for (j = i; j < i + 16; j++) { + if ((j - i) % 4 == 0) + putchar(' '); + if (j >= end) { + printf(" "); + continue; + } + printf("%02x", (uint8_t) p[j]); + } + putchar(' '); + for (j = i; j < end; j++) { + if (isprint(p[j])) + putchar(p[j]); + else if (p[j] == 0) + putchar('.'); + else + putchar(' '); + } + putchar('\n'); + } +} + +struct loc_at { + Dwarf_Attribute la_at; + Dwarf_Unsigned la_off; + Dwarf_Unsigned la_lowpc; + TAILQ_ENTRY(loc_at) la_next; +}; + +static TAILQ_HEAD(, loc_at) lalist = TAILQ_HEAD_INITIALIZER(lalist); + +static void +search_loclist_at(struct readelf *re, Dwarf_Die die, Dwarf_Unsigned lowpc) +{ + Dwarf_Attribute *attr_list; + Dwarf_Die ret_die; + Dwarf_Unsigned off; + Dwarf_Signed attr_count; + Dwarf_Half attr, form; + Dwarf_Error de; + struct loc_at *la, *nla; + int i, ret; + + if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) != + DW_DLV_OK) { + if (ret == DW_DLV_ERROR) + warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de)); + goto cont_search; + } + for (i = 0; i < attr_count; i++) { + if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) { + warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de)); + continue; + } + if (attr != DW_AT_location && + attr != DW_AT_string_length && + attr != DW_AT_return_addr && + attr != DW_AT_data_member_location && + attr != DW_AT_frame_base && + attr != DW_AT_segment && + attr != DW_AT_static_link && + attr != DW_AT_use_location && + attr != DW_AT_vtable_elem_location) + continue; + if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) { + warnx("dwarf_whatform failed: %s", dwarf_errmsg(de)); + continue; + } + if (form != DW_FORM_data4 && form != DW_FORM_data8) + continue; + if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) { + warnx("dwarf_formudata failed: %s", dwarf_errmsg(de)); + continue; + } + TAILQ_FOREACH(la, &lalist, la_next) { + if (off == la->la_off) + break; + if (off < la->la_off) { + if ((nla = malloc(sizeof(*nla))) == NULL) + err(EXIT_FAILURE, "malloc failed"); + nla->la_at = attr_list[i]; + nla->la_off = off; + nla->la_lowpc = lowpc; + TAILQ_INSERT_BEFORE(la, nla, la_next); + break; + } + } + if (la == NULL) { + if ((nla = malloc(sizeof(*nla))) == NULL) + err(EXIT_FAILURE, "malloc failed"); + nla->la_at = attr_list[i]; + nla->la_off = off; + nla->la_lowpc = lowpc; + TAILQ_INSERT_TAIL(&lalist, nla, la_next); + } + } + +cont_search: + /* Search children. */ + ret = dwarf_child(die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_child: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + search_loclist_at(re, ret_die, lowpc); + + /* Search sibling. */ + ret = dwarf_siblingof(re->dbg, die, &ret_die, &de); + if (ret == DW_DLV_ERROR) + warnx("dwarf_siblingof: %s", dwarf_errmsg(de)); + else if (ret == DW_DLV_OK) + search_loclist_at(re, ret_die, lowpc); +} + +static void +dump_dwarf_loclist(struct readelf *re) +{ + Dwarf_Die die; + Dwarf_Locdesc **llbuf; + Dwarf_Unsigned lowpc; + Dwarf_Signed lcnt; + Dwarf_Half tag; + Dwarf_Error de; + Dwarf_Loc *lr; + struct loc_at *la; + const char *op_str; + int i, j, ret; + + printf("\nContents of section .debug_loc:\n"); + + while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL, + NULL, &de)) == DW_DLV_OK) { + die = NULL; + if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK) + continue; + if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { + warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); + continue; + } + /* XXX: What about DW_TAG_partial_unit? */ + lowpc = 0; + if (tag == DW_TAG_compile_unit) { + if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lowpc, + &de) != DW_DLV_OK) + lowpc = 0; + } + + /* Search attributes for reference to .debug_loc section. */ + search_loclist_at(re, die, lowpc); + } + if (ret == DW_DLV_ERROR) + warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); + + if (TAILQ_EMPTY(&lalist)) + return; + + printf(" Offset Begin End Expression\n"); + + TAILQ_FOREACH(la, &lalist, la_next) { + if (dwarf_loclist_n(la->la_at, &llbuf, &lcnt, &de) != + DW_DLV_OK) { + warnx("dwarf_loclist_n failed: %s", dwarf_errmsg(de)); + continue; + } + for (i = 0; i < lcnt; i++) { + printf(" %8.8jx ", la->la_off); + if (llbuf[i]->ld_lopc == 0 && llbuf[i]->ld_hipc == 0) { + printf("\n"); + continue; + } + + /* TODO: handle base selection entry. */ + + printf("%8.8jx %8.8jx ", + (uintmax_t) (la->la_lowpc + llbuf[i]->ld_lopc), + (uintmax_t) (la->la_lowpc + llbuf[i]->ld_hipc)); + + putchar('('); + for (j = 0; (Dwarf_Half) j < llbuf[i]->ld_cents; j++) { + lr = &llbuf[i]->ld_s[j]; + if (dwarf_get_OP_name(lr->lr_atom, &op_str) != + DW_DLV_OK) { + warnx("dwarf_get_OP_name failed: %s", + dwarf_errmsg(de)); + continue; + } + + printf("%s", op_str); + + switch (lr->lr_atom) { + /* Operations with no operands. */ + case DW_OP_deref: + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + case DW_OP_dup: + case DW_OP_drop: + case DW_OP_over: + case DW_OP_swap: + case DW_OP_rot: + case DW_OP_xderef: + case DW_OP_abs: + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_or: + case DW_OP_plus: + case DW_OP_shl: + case DW_OP_shr: + case DW_OP_shra: + case DW_OP_xor: + case DW_OP_eq: + case DW_OP_ge: + case DW_OP_gt: + case DW_OP_le: + case DW_OP_lt: + case DW_OP_ne: + case DW_OP_nop: + break; + + case DW_OP_const1u: + case DW_OP_const1s: + case DW_OP_pick: + case DW_OP_deref_size: + case DW_OP_xderef_size: + case DW_OP_const2u: + case DW_OP_const2s: + case DW_OP_bra: + case DW_OP_skip: + case DW_OP_const4u: + case DW_OP_const4s: + case DW_OP_const8u: + case DW_OP_const8s: + case DW_OP_constu: + case DW_OP_plus_uconst: + case DW_OP_regx: + case DW_OP_piece: + printf(": %ju", (uintmax_t) + lr->lr_number); + break; + + case DW_OP_consts: + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + case DW_OP_fbreg: + printf(": %jd", (intmax_t) + lr->lr_number); + break; + + case DW_OP_bregx: + printf(": %ju %jd", + (uintmax_t) lr->lr_number, + (intmax_t) lr->lr_number2); + break; + + case DW_OP_addr: + printf(": %#jx", (uintmax_t) + lr->lr_number); + break; + } + if (j < llbuf[i]->ld_cents - 1) + printf(", "); + } + putchar(')'); + + if (llbuf[i]->ld_lopc == llbuf[i]->ld_hipc) + printf(" (start == end)"); + putchar('\n'); + } + } +} + +/* + * Retrieve a string using string table section index and the string offset. + */ +static const char* +get_string(struct readelf *re, int strtab, size_t off) +{ + const char *name; + + if ((name = elf_strptr(re->elf, strtab, off)) == NULL) + return (""); + + return (name); +} + +/* + * Retrieve the name of a symbol using the section index of the symbol + * table and the index of the symbol within that table. + */ +static const char * +get_symbol_name(struct readelf *re, int symtab, int i) +{ + struct section *s; + const char *name; + GElf_Sym sym; + Elf_Data *data; + int elferr; + + s = &re->sl[symtab]; + if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) + return (""); + (void) elf_errno(); + if ((data = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(elferr)); + return (""); + } + if (gelf_getsym(data, i, &sym) != &sym) + return (""); + /* Return section name for STT_SECTION symbol. */ + if (GELF_ST_TYPE(sym.st_info) == STT_SECTION && + re->sl[sym.st_shndx].name != NULL) + return (re->sl[sym.st_shndx].name); + if ((name = elf_strptr(re->elf, s->link, sym.st_name)) == NULL) + return (""); + + return (name); +} + +static uint64_t +get_symbol_value(struct readelf *re, int symtab, int i) +{ + struct section *s; + GElf_Sym sym; + Elf_Data *data; + int elferr; + + s = &re->sl[symtab]; + if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) + return (0); + (void) elf_errno(); + if ((data = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", elf_errmsg(elferr)); + return (0); + } + if (gelf_getsym(data, i, &sym) != &sym) + return (0); + + return (sym.st_value); +} + +static void +hex_dump(struct readelf *re) +{ + struct section *s; + Elf_Data *d; + uint8_t *buf; + size_t sz, nbytes; + uint64_t addr; + int elferr, i, j; + + for (i = 1; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (find_dumpop(re, (size_t) i, s->name, HEX_DUMP, -1) == NULL) + continue; + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(elferr)); + continue; + } + if (d->d_size <= 0 || d->d_buf == NULL) { + printf("\nSection '%s' has no data to dump.\n", + s->name); + continue; + } + buf = d->d_buf; + sz = d->d_size; + addr = s->addr; + printf("\nHex dump of section '%s':\n", s->name); + while (sz > 0) { + printf(" 0x%8.8jx ", (uintmax_t)addr); + nbytes = sz > 16? 16 : sz; + for (j = 0; j < 16; j++) { + if ((size_t)j < nbytes) + printf("%2.2x", buf[j]); + else + printf(" "); + if ((j & 3) == 3) + printf(" "); + } + for (j = 0; (size_t)j < nbytes; j++) { + if (isprint(buf[j])) + printf("%c", buf[j]); + else + printf("."); + } + printf("\n"); + buf += nbytes; + addr += nbytes; + sz -= nbytes; + } + } +} + +static void +str_dump(struct readelf *re) +{ + struct section *s; + Elf_Data *d; + unsigned char *start, *end, *buf_end; + unsigned int len; + int i, j, elferr, found; + + for (i = 1; (size_t) i < re->shnum; i++) { + s = &re->sl[i]; + if (find_dumpop(re, (size_t) i, s->name, STR_DUMP, -1) == NULL) + continue; + (void) elf_errno(); + if ((d = elf_getdata(s->scn, NULL)) == NULL) { + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_getdata failed: %s", + elf_errmsg(elferr)); + continue; + } + if (d->d_size <= 0 || d->d_buf == NULL) { + printf("\nSection '%s' has no data to dump.\n", + s->name); + continue; + } + buf_end = (unsigned char *) d->d_buf + d->d_size; + start = (unsigned char *) d->d_buf; + found = 0; + printf("\nString dump of section '%s':\n", s->name); + for (;;) { + while (start < buf_end && !isprint(*start)) + start++; + if (start >= buf_end) + break; + end = start + 1; + while (end < buf_end && isprint(*end)) + end++; + printf(" [%6lx] ", + (long) (start - (unsigned char *) d->d_buf)); + len = end - start; + for (j = 0; (unsigned int) j < len; j++) + putchar(start[j]); + putchar('\n'); + found = 1; + if (end >= buf_end) + break; + start = end + 1; + } + if (!found) + printf(" No strings found in this section."); + putchar('\n'); + } +} + +static void +load_sections(struct readelf *re) +{ + struct section *s; + const char *name; + Elf_Scn *scn; + GElf_Shdr sh; + size_t shstrndx, ndx; + int elferr; + + /* Allocate storage for internal section list. */ + if (!elf_getshnum(re->elf, &re->shnum)) { + warnx("elf_getshnum failed: %s", elf_errmsg(-1)); + return; + } + if (re->sl != NULL) + free(re->sl); + if ((re->sl = calloc(re->shnum, sizeof(*re->sl))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + + /* Get the index of .shstrtab section. */ + if (!elf_getshstrndx(re->elf, &shstrndx)) { + warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); + return; + } + + if ((scn = elf_getscn(re->elf, 0)) == NULL) { + warnx("elf_getscn failed: %s", elf_errmsg(-1)); + return; + } + + (void) elf_errno(); + do { + if (gelf_getshdr(scn, &sh) == NULL) { + warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); + (void) elf_errno(); + continue; + } + if ((name = elf_strptr(re->elf, shstrndx, sh.sh_name)) == NULL) { + (void) elf_errno(); + name = "ERROR"; + } + if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) { + if ((elferr = elf_errno()) != 0) + warnx("elf_ndxscn failed: %s", + elf_errmsg(elferr)); + continue; + } + if (ndx >= re->shnum) { + warnx("section index of '%s' out of range", name); + continue; + } + s = &re->sl[ndx]; + s->name = name; + s->scn = scn; + s->off = sh.sh_offset; + s->sz = sh.sh_size; + s->entsize = sh.sh_entsize; + s->align = sh.sh_addralign; + s->type = sh.sh_type; + s->flags = sh.sh_flags; + s->addr = sh.sh_addr; + s->link = sh.sh_link; + s->info = sh.sh_info; + } while ((scn = elf_nextscn(re->elf, scn)) != NULL); + elferr = elf_errno(); + if (elferr != 0) + warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); +} + +static void +unload_sections(struct readelf *re) +{ + + if (re->sl != NULL) { + free(re->sl); + re->sl = NULL; + } + re->shnum = 0; + re->vd_s = NULL; + re->vn_s = NULL; + re->vs_s = NULL; + re->vs = NULL; + re->vs_sz = 0; + if (re->ver != NULL) { + free(re->ver); + re->ver = NULL; + re->ver_sz = 0; + } +} + +static void +dump_elf(struct readelf *re) +{ + + /* Fetch ELF header. No need to continue if it fails. */ + if (gelf_getehdr(re->elf, &re->ehdr) == NULL) { + warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); + return; + } + if ((re->ec = gelf_getclass(re->elf)) == ELFCLASSNONE) { + warnx("gelf_getclass failed: %s", elf_errmsg(-1)); + return; + } + if (re->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { + re->dw_read = _read_msb; + re->dw_decode = _decode_msb; + } else { + re->dw_read = _read_lsb; + re->dw_decode = _decode_lsb; + } + + if (re->options & ~RE_H) + load_sections(re); + if ((re->options & RE_VV) || (re->options & RE_S)) + search_ver(re); + if (re->options & RE_H) + dump_ehdr(re); + if (re->options & RE_L) + dump_phdr(re); + if (re->options & RE_SS) + dump_shdr(re); + if (re->options & RE_D) + dump_dynamic(re); + if (re->options & RE_R) + dump_reloc(re); + if (re->options & RE_S) + dump_symtabs(re); + if (re->options & RE_N) + dump_notes(re); + if (re->options & RE_II) + dump_hash(re); + if (re->options & RE_X) + hex_dump(re); + if (re->options & RE_P) + str_dump(re); + if (re->options & RE_VV) + dump_ver(re); + if (re->options & RE_AA) + dump_arch_specific_info(re); + if (re->options & RE_W) + dump_dwarf(re); + if (re->options & ~RE_H) + unload_sections(re); +} + +static void +dump_dwarf(struct readelf *re) +{ + int error; + Dwarf_Error de; + + if (dwarf_elf_init(re->elf, DW_DLC_READ, NULL, NULL, &re->dbg, &de)) { + if ((error = dwarf_errno(de)) != DW_DLE_DEBUG_INFO_NULL) + errx(EXIT_FAILURE, "dwarf_elf_init failed: %s", + dwarf_errmsg(de)); + return; + } + + if (re->dop & DW_A) + dump_dwarf_abbrev(re); + if (re->dop & DW_L) + dump_dwarf_line(re); + if (re->dop & DW_LL) + dump_dwarf_line_decoded(re); + if (re->dop & DW_I) + dump_dwarf_info(re); + if (re->dop & DW_P) + dump_dwarf_pubnames(re); + if (re->dop & DW_R) + dump_dwarf_aranges(re); + if (re->dop & DW_RR) + dump_dwarf_ranges(re); + if (re->dop & DW_M) + dump_dwarf_macinfo(re); + if (re->dop & DW_F) + dump_dwarf_frame(re, 0); + else if (re->dop & DW_FF) + dump_dwarf_frame(re, 1); + if (re->dop & DW_S) + dump_dwarf_str(re); + if (re->dop & DW_O) + dump_dwarf_loclist(re); + + dwarf_finish(re->dbg, &de); +} + +static void +dump_ar(struct readelf *re, int fd) +{ + Elf_Arsym *arsym; + Elf_Arhdr *arhdr; + Elf_Cmd cmd; + Elf *e; + size_t sz; + off_t off; + int i; + + re->ar = re->elf; + + if (re->options & RE_C) { + if ((arsym = elf_getarsym(re->ar, &sz)) == NULL) { + warnx("elf_getarsym() failed: %s", elf_errmsg(-1)); + goto process_members; + } + printf("Index of archive %s: (%ju entries)\n", re->filename, + (uintmax_t) sz - 1); + off = 0; + for (i = 0; (size_t) i < sz; i++) { + if (arsym[i].as_name == NULL) + break; + if (arsym[i].as_off != off) { + off = arsym[i].as_off; + if (elf_rand(re->ar, off) != off) { + warnx("elf_rand() failed: %s", + elf_errmsg(-1)); + continue; + } + if ((e = elf_begin(fd, ELF_C_READ, re->ar)) == + NULL) { + warnx("elf_begin() failed: %s", + elf_errmsg(-1)); + continue; + } + if ((arhdr = elf_getarhdr(e)) == NULL) { + warnx("elf_getarhdr() failed: %s", + elf_errmsg(-1)); + elf_end(e); + continue; + } + printf("Binary %s(%s) contains:\n", + re->filename, arhdr->ar_name); + } + printf("\t%s\n", arsym[i].as_name); + } + if (elf_rand(re->ar, SARMAG) != SARMAG) { + warnx("elf_rand() failed: %s", elf_errmsg(-1)); + return; + } + } + +process_members: + + if ((re->options & ~RE_C) == 0) + return; + + cmd = ELF_C_READ; + while ((re->elf = elf_begin(fd, cmd, re->ar)) != NULL) { + if ((arhdr = elf_getarhdr(re->elf)) == NULL) { + warnx("elf_getarhdr() failed: %s", elf_errmsg(-1)); + goto next_member; + } + if (strcmp(arhdr->ar_name, "/") == 0 || + strcmp(arhdr->ar_name, "//") == 0 || + strcmp(arhdr->ar_name, "__.SYMDEF") == 0) + goto next_member; + printf("\nFile: %s(%s)\n", re->filename, arhdr->ar_name); + dump_elf(re); + + next_member: + cmd = elf_next(re->elf); + elf_end(re->elf); + } + re->elf = re->ar; +} + +static void +dump_object(struct readelf *re) +{ + int fd; + + if ((fd = open(re->filename, O_RDONLY)) == -1) { + warn("open %s failed", re->filename); + return; + } + + if ((re->flags & DISPLAY_FILENAME) != 0) + printf("\nFile: %s\n", re->filename); + + if ((re->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { + warnx("elf_begin() failed: %s", elf_errmsg(-1)); + return; + } + + switch (elf_kind(re->elf)) { + case ELF_K_NONE: + warnx("Not an ELF file."); + return; + case ELF_K_ELF: + dump_elf(re); + break; + case ELF_K_AR: + dump_ar(re, fd); + break; + default: + warnx("Internal: libelf returned unknown elf kind."); + return; + } + + elf_end(re->elf); +} + +static void +add_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t) +{ + struct dumpop *d; + + if ((d = find_dumpop(re, si, sn, -1, t)) == NULL) { + if ((d = calloc(1, sizeof(*d))) == NULL) + err(EXIT_FAILURE, "calloc failed"); + if (t == DUMP_BY_INDEX) + d->u.si = si; + else + d->u.sn = sn; + d->type = t; + d->op = op; + STAILQ_INSERT_TAIL(&re->v_dumpop, d, dumpop_list); + } else + d->op |= op; +} + +static struct dumpop * +find_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t) +{ + struct dumpop *d; + + STAILQ_FOREACH(d, &re->v_dumpop, dumpop_list) { + if ((op == -1 || op & d->op) && + (t == -1 || (unsigned) t == d->type)) { + if ((d->type == DUMP_BY_INDEX && d->u.si == si) || + (d->type == DUMP_BY_NAME && !strcmp(d->u.sn, sn))) + return (d); + } + } + + return (NULL); +} + +static struct { + const char *ln; + char sn; + int value; +} dwarf_op[] = { + {"rawline", 'l', DW_L}, + {"decodedline", 'L', DW_LL}, + {"info", 'i', DW_I}, + {"abbrev", 'a', DW_A}, + {"pubnames", 'p', DW_P}, + {"aranges", 'r', DW_R}, + {"ranges", 'r', DW_R}, + {"Ranges", 'R', DW_RR}, + {"macro", 'm', DW_M}, + {"frames", 'f', DW_F}, + {"", 'F', DW_FF}, + {"str", 's', DW_S}, + {"loc", 'o', DW_O}, + {NULL, 0, 0} +}; + +static void +parse_dwarf_op_short(struct readelf *re, const char *op) +{ + int i; + + if (op == NULL) { + re->dop |= DW_DEFAULT_OPTIONS; + return; + } + + for (; *op != '\0'; op++) { + for (i = 0; dwarf_op[i].ln != NULL; i++) { + if (dwarf_op[i].sn == *op) { + re->dop |= dwarf_op[i].value; + break; + } + } + } +} + +static void +parse_dwarf_op_long(struct readelf *re, const char *op) +{ + char *p, *token, *bp; + int i; + + if (op == NULL) { + re->dop |= DW_DEFAULT_OPTIONS; + return; + } + + if ((p = strdup(op)) == NULL) + err(EXIT_FAILURE, "strdup failed"); + bp = p; + + while ((token = strsep(&p, ",")) != NULL) { + for (i = 0; dwarf_op[i].ln != NULL; i++) { + if (!strcmp(token, dwarf_op[i].ln)) { + re->dop |= dwarf_op[i].value; + break; + } + } + } + + free(bp); +} + +static uint64_t +_read_lsb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read) +{ + uint64_t ret; + uint8_t *src; + + src = (uint8_t *) d->d_buf + *offsetp; + + ret = 0; + switch (bytes_to_read) { + case 8: + ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; + ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; + case 4: + ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; + case 2: + ret |= ((uint64_t) src[1]) << 8; + case 1: + ret |= src[0]; + break; + default: + return (0); + } + + *offsetp += bytes_to_read; + + return (ret); +} + +static uint64_t +_read_msb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read) +{ + uint64_t ret; + uint8_t *src; + + src = (uint8_t *) d->d_buf + *offsetp; + + switch (bytes_to_read) { + case 1: + ret = src[0]; + break; + case 2: + ret = src[1] | ((uint64_t) src[0]) << 8; + break; + case 4: + ret = src[3] | ((uint64_t) src[2]) << 8; + ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24; + break; + case 8: + ret = src[7] | ((uint64_t) src[6]) << 8; + ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24; + ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40; + ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56; + break; + default: + return (0); + } + + *offsetp += bytes_to_read; + + return (ret); +} + +static uint64_t +_decode_lsb(uint8_t **data, int bytes_to_read) +{ + uint64_t ret; + uint8_t *src; + + src = *data; + + ret = 0; + switch (bytes_to_read) { + case 8: + ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; + ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; + case 4: + ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; + case 2: + ret |= ((uint64_t) src[1]) << 8; + case 1: + ret |= src[0]; + break; + default: + return (0); + } + + *data += bytes_to_read; + + return (ret); +} + +static uint64_t +_decode_msb(uint8_t **data, int bytes_to_read) +{ + uint64_t ret; + uint8_t *src; + + src = *data; + + ret = 0; + switch (bytes_to_read) { + case 1: + ret = src[0]; + break; + case 2: + ret = src[1] | ((uint64_t) src[0]) << 8; + break; + case 4: + ret = src[3] | ((uint64_t) src[2]) << 8; + ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24; + break; + case 8: + ret = src[7] | ((uint64_t) src[6]) << 8; + ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24; + ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40; + ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56; + break; + default: + return (0); + break; + } + + *data += bytes_to_read; + + return (ret); +} + +static int64_t +_decode_sleb128(uint8_t **dp) +{ + int64_t ret = 0; + uint8_t b; + int shift = 0; + + uint8_t *src = *dp; + + do { + b = *src++; + ret |= ((b & 0x7f) << shift); + shift += 7; + } while ((b & 0x80) != 0); + + if (shift < 32 && (b & 0x40) != 0) + ret |= (-1 << shift); + + *dp = src; + + return (ret); +} + +static uint64_t +_decode_uleb128(uint8_t **dp) +{ + uint64_t ret = 0; + uint8_t b; + int shift = 0; + + uint8_t *src = *dp; + + do { + b = *src++; + ret |= ((b & 0x7f) << shift); + shift += 7; + } while ((b & 0x80) != 0); + + *dp = src; + + return (ret); +} + +static void +readelf_version(void) +{ + (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), + elftc_version()); + exit(EXIT_SUCCESS); +} + +#define USAGE_MESSAGE "\ +Usage: %s [options] file...\n\ + Display information about ELF objects and ar(1) archives.\n\n\ + Options:\n\ + -a | --all Equivalent to specifying options '-dhIlrsASV'.\n\ + -c | --archive-index Print the archive symbol table for archives.\n\ + -d | --dynamic Print the contents of SHT_DYNAMIC sections.\n\ + -e | --headers Print all headers in the object.\n\ + -g | --section-groups (accepted, but ignored)\n\ + -h | --file-header Print the file header for the object.\n\ + -l | --program-headers Print the PHDR table for the object.\n\ + -n | --notes Print the contents of SHT_NOTE sections.\n\ + -p INDEX | --string-dump=INDEX\n\ + Print the contents of section at index INDEX.\n\ + -r | --relocs Print relocation information.\n\ + -s | --syms | --symbols Print symbol tables.\n\ + -t | --section-details Print additional information about sections.\n\ + -v | --version Print a version identifier and exit.\n\ + -x INDEX | --hex-dump=INDEX\n\ + Display contents of a section as hexadecimal.\n\ + -A | --arch-specific (accepted, but ignored)\n\ + -D | --use-dynamic Print the symbol table specified by the DT_SYMTAB\n\ + entry in the \".dynamic\" section.\n\ + -H | --help Print a help message.\n\ + -I | --histogram Print information on bucket list lengths for \n\ + hash sections.\n\ + -N | --full-section-name (accepted, but ignored)\n\ + -S | --sections | --section-headers\n\ + Print information about section headers.\n\ + -V | --version-info Print symbol versoning information.\n\ + -W | --wide Print information without wrapping long lines.\n" + + +static void +readelf_usage(void) +{ + fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); + exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) +{ + struct readelf *re, re_storage; + unsigned long si; + int opt, i; + char *ep; + + re = &re_storage; + memset(re, 0, sizeof(*re)); + STAILQ_INIT(&re->v_dumpop); + + while ((opt = getopt_long(argc, argv, "AacDdegHhIi:lNnp:rSstuVvWw::x:", + longopts, NULL)) != -1) { + switch(opt) { + case '?': + readelf_usage(); + break; + case 'A': + re->options |= RE_AA; + break; + case 'a': + re->options |= RE_AA | RE_D | RE_H | RE_II | RE_L | + RE_R | RE_SS | RE_S | RE_VV; + break; + case 'c': + re->options |= RE_C; + break; + case 'D': + re->options |= RE_DD; + break; + case 'd': + re->options |= RE_D; + break; + case 'e': + re->options |= RE_H | RE_L | RE_SS; + break; + case 'g': + re->options |= RE_G; + break; + case 'H': + readelf_usage(); + break; + case 'h': + re->options |= RE_H; + break; + case 'I': + re->options |= RE_II; + break; + case 'i': + /* Not implemented yet. */ + break; + case 'l': + re->options |= RE_L; + break; + case 'N': + re->options |= RE_NN; + break; + case 'n': + re->options |= RE_N; + break; + case 'p': + re->options |= RE_P; + si = strtoul(optarg, &ep, 10); + if (*ep == '\0') + add_dumpop(re, (size_t) si, NULL, STR_DUMP, + DUMP_BY_INDEX); + else + add_dumpop(re, 0, optarg, STR_DUMP, + DUMP_BY_NAME); + break; + case 'r': + re->options |= RE_R; + break; + case 'S': + re->options |= RE_SS; + break; + case 's': + re->options |= RE_S; + break; + case 't': + re->options |= RE_T; + break; + case 'u': + re->options |= RE_U; + break; + case 'V': + re->options |= RE_VV; + break; + case 'v': + readelf_version(); + break; + case 'W': + re->options |= RE_WW; + break; + case 'w': + re->options |= RE_W; + parse_dwarf_op_short(re, optarg); + break; + case 'x': + re->options |= RE_X; + si = strtoul(optarg, &ep, 10); + if (*ep == '\0') + add_dumpop(re, (size_t) si, NULL, HEX_DUMP, + DUMP_BY_INDEX); + else + add_dumpop(re, 0, optarg, HEX_DUMP, + DUMP_BY_NAME); + break; + case OPTION_DEBUG_DUMP: + re->options |= RE_W; + parse_dwarf_op_long(re, optarg); + } + } + + argv += optind; + argc -= optind; + + if (argc == 0 || re->options == 0) + readelf_usage(); + + if (argc > 1) + re->flags |= DISPLAY_FILENAME; + + if (elf_version(EV_CURRENT) == EV_NONE) + errx(EXIT_FAILURE, "ELF library initialization failed: %s", + elf_errmsg(-1)); + + for (i = 0; i < argc; i++) + if (argv[i] != NULL) { + re->filename = argv[i]; + dump_object(re); + } + + exit(EXIT_SUCCESS); +} diff --git a/contrib/llvm/patches/patch-r275759-clang-r221170-ppc-vaarg.diff b/contrib/llvm/patches/patch-r275759-clang-r221170-ppc-vaarg.diff new file mode 100644 index 000000000000..0562a68cb01f --- /dev/null +++ b/contrib/llvm/patches/patch-r275759-clang-r221170-ppc-vaarg.diff @@ -0,0 +1,298 @@ +Pull in r221170 from upstream clang trunk (by Roman Divacky): + + Implement vaarg lowering for ppc32. Lowering of scalars and + aggregates is supported. Complex numbers are not. + +Pull in r221174 from upstream clang trunk (by Roman Divacky): + + Require asserts to unbreak the buildbots. + +Pull in r221284 from upstream clang trunk (by Roman Divacky): + + Rewrite the test to not require asserts. + +Pull in r221285 from upstream clang trunk (by Roman Divacky): + + Since the file has both ppc and ppc64 tests in it rename it. + +This adds va_args support for PowerPC (32 bit) to clang. + +Introduced here: http://svnweb.freebsd.org/changeset/base/275759 + +Index: tools/clang/lib/CodeGen/TargetInfo.cpp +=================================================================== +--- tools/clang/lib/CodeGen/TargetInfo.cpp ++++ tools/clang/lib/CodeGen/TargetInfo.cpp +@@ -2733,12 +2733,20 @@ llvm::Value *NaClX86_64ABIInfo::EmitVAArg(llvm::Va + + + // PowerPC-32 +- + namespace { +-class PPC32TargetCodeGenInfo : public DefaultTargetCodeGenInfo { ++/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information. ++class PPC32_SVR4_ABIInfo : public DefaultABIInfo { + public: +- PPC32TargetCodeGenInfo(CodeGenTypes &CGT) : DefaultTargetCodeGenInfo(CGT) {} ++ PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} + ++ llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, ++ CodeGenFunction &CGF) const; ++}; ++ ++class PPC32TargetCodeGenInfo : public TargetCodeGenInfo { ++public: ++ PPC32TargetCodeGenInfo(CodeGenTypes &CGT) : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT)) {} ++ + int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + // This is recovered from gcc output. + return 1; // r1 is the dedicated stack pointer +@@ -2750,6 +2758,96 @@ namespace { + + } + ++llvm::Value *PPC32_SVR4_ABIInfo::EmitVAArg(llvm::Value *VAListAddr, ++ QualType Ty, ++ CodeGenFunction &CGF) const { ++ if (const ComplexType *CTy = Ty->getAs()) { ++ // TODO: Implement this. For now ignore. ++ (void)CTy; ++ return NULL; ++ } ++ ++ bool isI64 = Ty->isIntegerType() && getContext().getTypeSize(Ty) == 64; ++ bool isInt = Ty->isIntegerType() || Ty->isPointerType() || Ty->isAggregateType(); ++ llvm::Type *CharPtr = CGF.Int8PtrTy; ++ llvm::Type *CharPtrPtr = CGF.Int8PtrPtrTy; ++ ++ CGBuilderTy &Builder = CGF.Builder; ++ llvm::Value *GPRPtr = Builder.CreateBitCast(VAListAddr, CharPtr, "gprptr"); ++ llvm::Value *GPRPtrAsInt = Builder.CreatePtrToInt(GPRPtr, CGF.Int32Ty); ++ llvm::Value *FPRPtrAsInt = Builder.CreateAdd(GPRPtrAsInt, Builder.getInt32(1)); ++ llvm::Value *FPRPtr = Builder.CreateIntToPtr(FPRPtrAsInt, CharPtr); ++ llvm::Value *OverflowAreaPtrAsInt = Builder.CreateAdd(FPRPtrAsInt, Builder.getInt32(3)); ++ llvm::Value *OverflowAreaPtr = Builder.CreateIntToPtr(OverflowAreaPtrAsInt, CharPtrPtr); ++ llvm::Value *RegsaveAreaPtrAsInt = Builder.CreateAdd(OverflowAreaPtrAsInt, Builder.getInt32(4)); ++ llvm::Value *RegsaveAreaPtr = Builder.CreateIntToPtr(RegsaveAreaPtrAsInt, CharPtrPtr); ++ llvm::Value *GPR = Builder.CreateLoad(GPRPtr, false, "gpr"); ++ // Align GPR when TY is i64. ++ if (isI64) { ++ llvm::Value *GPRAnd = Builder.CreateAnd(GPR, Builder.getInt8(1)); ++ llvm::Value *CC64 = Builder.CreateICmpEQ(GPRAnd, Builder.getInt8(1)); ++ llvm::Value *GPRPlusOne = Builder.CreateAdd(GPR, Builder.getInt8(1)); ++ GPR = Builder.CreateSelect(CC64, GPRPlusOne, GPR); ++ } ++ llvm::Value *FPR = Builder.CreateLoad(FPRPtr, false, "fpr"); ++ llvm::Value *OverflowArea = Builder.CreateLoad(OverflowAreaPtr, false, "overflow_area"); ++ llvm::Value *OverflowAreaAsInt = Builder.CreatePtrToInt(OverflowArea, CGF.Int32Ty); ++ llvm::Value *RegsaveArea = Builder.CreateLoad(RegsaveAreaPtr, false, "regsave_area"); ++ llvm::Value *RegsaveAreaAsInt = Builder.CreatePtrToInt(RegsaveArea, CGF.Int32Ty); ++ ++ llvm::Value *CC = Builder.CreateICmpULT(isInt ? GPR : FPR, ++ Builder.getInt8(8), "cond"); ++ ++ llvm::Value *RegConstant = Builder.CreateMul(isInt ? GPR : FPR, ++ Builder.getInt8(isInt ? 4 : 8)); ++ ++ llvm::Value *OurReg = Builder.CreateAdd(RegsaveAreaAsInt, Builder.CreateSExt(RegConstant, CGF.Int32Ty)); ++ ++ if (Ty->isFloatingType()) ++ OurReg = Builder.CreateAdd(OurReg, Builder.getInt32(32)); ++ ++ llvm::BasicBlock *UsingRegs = CGF.createBasicBlock("using_regs"); ++ llvm::BasicBlock *UsingOverflow = CGF.createBasicBlock("using_overflow"); ++ llvm::BasicBlock *Cont = CGF.createBasicBlock("cont"); ++ ++ Builder.CreateCondBr(CC, UsingRegs, UsingOverflow); ++ ++ CGF.EmitBlock(UsingRegs); ++ ++ llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty)); ++ llvm::Value *Result1 = Builder.CreateIntToPtr(OurReg, PTy); ++ // Increase the GPR/FPR indexes. ++ if (isInt) { ++ GPR = Builder.CreateAdd(GPR, Builder.getInt8(isI64 ? 2 : 1)); ++ Builder.CreateStore(GPR, GPRPtr); ++ } else { ++ FPR = Builder.CreateAdd(FPR, Builder.getInt8(1)); ++ Builder.CreateStore(FPR, FPRPtr); ++ } ++ CGF.EmitBranch(Cont); ++ ++ CGF.EmitBlock(UsingOverflow); ++ ++ // Increase the overflow area. ++ llvm::Value *Result2 = Builder.CreateIntToPtr(OverflowAreaAsInt, PTy); ++ OverflowAreaAsInt = Builder.CreateAdd(OverflowAreaAsInt, Builder.getInt32(isInt ? 4 : 8)); ++ Builder.CreateStore(Builder.CreateIntToPtr(OverflowAreaAsInt, CharPtr), OverflowAreaPtr); ++ CGF.EmitBranch(Cont); ++ ++ CGF.EmitBlock(Cont); ++ ++ llvm::PHINode *Result = CGF.Builder.CreatePHI(PTy, 2, "vaarg.addr"); ++ Result->addIncoming(Result1, UsingRegs); ++ Result->addIncoming(Result2, UsingOverflow); ++ ++ if (Ty->isAggregateType()) { ++ llvm::Value *AGGPtr = Builder.CreateBitCast(Result, CharPtrPtr, "aggrptr") ; ++ return Builder.CreateLoad(AGGPtr, false, "aggr"); ++ } ++ ++ return Result; ++} ++ + bool + PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { +Index: tools/clang/test/CodeGen/ppc64-varargs-struct.c +=================================================================== +--- tools/clang/test/CodeGen/ppc64-varargs-struct.c ++++ tools/clang/test/CodeGen/ppc64-varargs-struct.c +@@ -1,30 +0,0 @@ +-// REQUIRES: ppc64-registered-target +-// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s +- +-#include +- +-struct x { +- long a; +- double b; +-}; +- +-void testva (int n, ...) +-{ +- va_list ap; +- +- struct x t = va_arg (ap, struct x); +-// CHECK: bitcast i8* %{{[a-z.0-9]*}} to %struct.x* +-// CHECK: bitcast %struct.x* %t to i8* +-// CHECK: bitcast %struct.x* %{{[0-9]+}} to i8* +-// CHECK: call void @llvm.memcpy +- +- int v = va_arg (ap, int); +-// CHECK: ptrtoint i8* %{{[a-z.0-9]*}} to i64 +-// CHECK: add i64 %{{[0-9]+}}, 4 +-// CHECK: inttoptr i64 %{{[0-9]+}} to i8* +-// CHECK: bitcast i8* %{{[0-9]+}} to i32* +- +- __int128_t u = va_arg (ap, __int128_t); +-// CHECK: bitcast i8* %{{[a-z.0-9]+}} to i128* +-// CHECK-NEXT: load i128* %{{[0-9]+}} +-} +Index: tools/clang/test/CodeGen/ppc-varargs-struct.c +=================================================================== +--- tools/clang/test/CodeGen/ppc-varargs-struct.c ++++ tools/clang/test/CodeGen/ppc-varargs-struct.c +@@ -0,0 +1,112 @@ ++// REQUIRES: ppc64-registered-target ++// REQUIRES: asserts ++// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s ++// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-PPC ++ ++#include ++ ++struct x { ++ long a; ++ double b; ++}; ++ ++void testva (int n, ...) ++{ ++ va_list ap; ++ ++ struct x t = va_arg (ap, struct x); ++// CHECK: bitcast i8* %{{[a-z.0-9]*}} to %struct.x* ++// CHECK: bitcast %struct.x* %t to i8* ++// CHECK: bitcast %struct.x* %{{[0-9]+}} to i8* ++// CHECK: call void @llvm.memcpy ++// CHECK-PPC: [[ARRAYDECAY:%[a-z0-9]+]] = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0 ++// CHECK-PPC-NEXT: [[GPRPTR:%[a-z0-9]+]] = bitcast %struct.__va_list_tag* [[ARRAYDECAY]] to i8* ++// CHECK-PPC-NEXT: [[ZERO:%[0-9]+]] = ptrtoint i8* [[GPRPTR]] to i32 ++// CHECK-PPC-NEXT: [[ONE:%[0-9]+]] = add i32 [[ZERO]], 1 ++// CHECK-PPC-NEXT: [[TWO:%[0-9]+]] = inttoptr i32 [[ONE]] to i8* ++// CHECK-PPC-NEXT: [[THREE:%[0-9]+]] = add i32 [[ONE]], 3 ++// CHECK-PPC-NEXT: [[FOUR:%[0-9]+]] = inttoptr i32 [[THREE]] to i8** ++// CHECK-PPC-NEXT: [[FIVE:%[0-9]+]] = add i32 [[THREE]], 4 ++// CHECK-PPC-NEXT: [[SIX:%[0-9]+]] = inttoptr i32 [[FIVE]] to i8** ++// CHECK-PPC-NEXT: [[GPR:%[a-z0-9]+]] = load i8* [[GPRPTR]] ++// CHECK-PPC-NEXT: [[FPR:%[a-z0-9]+]] = load i8* [[TWO]] ++// CHECK-PPC-NEXT: [[OVERFLOW_AREA:%[a-z_0-9]+]] = load i8** [[FOUR]] ++// CHECK-PPC-NEXT: [[SEVEN:%[0-9]+]] = ptrtoint i8* [[OVERFLOW_AREA]] to i32 ++// CHECK-PPC-NEXT: [[REGSAVE_AREA:%[a-z_0-9]+]] = load i8** [[SIX]] ++// CHECK-PPC-NEXT: [[EIGHT:%[0-9]+]] = ptrtoint i8* [[REGSAVE_AREA]] to i32 ++// CHECK-PPC-NEXT: [[COND:%[a-z0-9]+]] = icmp ult i8 [[GPR]], 8 ++// CHECK-PPC-NEXT: [[NINE:%[0-9]+]] = mul i8 [[GPR]], 4 ++// CHECK-PPC-NEXT: [[TEN:%[0-9]+]] = sext i8 [[NINE]] to i32 ++// CHECK-PPC-NEXT: [[ELEVEN:%[0-9]+]] = add i32 [[EIGHT]], [[TEN]] ++// CHECK-PPC-NEXT: br i1 [[COND]], label [[USING_REGS:%[a-z_0-9]+]], label [[USING_OVERFLOW:%[a-z_0-9]+]] ++// ++// CHECK-PPC1:[[USING_REGS]] ++// CHECK-PPC: [[TWELVE:%[0-9]+]] = inttoptr i32 [[ELEVEN]] to %struct.x* ++// CHECK-PPC-NEXT: [[THIRTEEN:%[0-9]+]] = add i8 [[GPR]], 1 ++// CHECK-PPC-NEXT: store i8 [[THIRTEEN]], i8* [[GPRPTR]] ++// CHECK-PPC-NEXT: br label [[CONT:%[a-z0-9]+]] ++// ++// CHECK-PPC1:[[USING_OVERFLOW]] ++// CHECK-PPC: [[FOURTEEN:%[0-9]+]] = inttoptr i32 [[SEVEN]] to %struct.x* ++// CHECK-PPC-NEXT: [[FIFTEEN:%[0-9]+]] = add i32 [[SEVEN]], 4 ++// CHECK-PPC-NEXT: [[SIXTEEN:%[0-9]+]] = inttoptr i32 [[FIFTEEN]] to i8* ++// CHECK-PPC-NEXT: store i8* [[SIXTEEN]], i8** [[FOUR]] ++// CHECK-PPC-NEXT: br label [[CONT]] ++// ++// CHECK-PPC1:[[CONT]] ++// CHECK-PPC: [[VAARG_ADDR:%[a-z.0-9]+]] = phi %struct.x* [ [[TWELVE]], [[USING_REGS]] ], [ [[FOURTEEN]], [[USING_OVERFLOW]] ] ++// CHECK-PPC-NEXT: [[AGGRPTR:%[a-z0-9]+]] = bitcast %struct.x* [[VAARG_ADDR]] to i8** ++// CHECK-PPC-NEXT: [[AGGR:%[a-z0-9]+]] = load i8** [[AGGRPTR]] ++// CHECK-PPC-NEXT: [[SEVENTEEN:%[0-9]+]] = bitcast %struct.x* %t to i8* ++// CHECK-PPC-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[SEVENTEEN]], i8* [[AGGR]], i32 16, i32 8, i1 false) ++ ++ int v = va_arg (ap, int); ++// CHECK: ptrtoint i8* %{{[a-z.0-9]*}} to i64 ++// CHECK: add i64 %{{[0-9]+}}, 4 ++// CHECK: inttoptr i64 %{{[0-9]+}} to i8* ++// CHECK: bitcast i8* %{{[0-9]+}} to i32* ++// CHECK-PPC: [[ARRAYDECAY1:%[a-z0-9]+]] = getelementptr inbounds [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0 ++// CHECK-PPC-NEXT: [[GPRPTR1:%[a-z0-9]+]] = bitcast %struct.__va_list_tag* [[ARRAYDECAY1]] to i8* ++// CHECK-PPC-NEXT: [[EIGHTEEN:%[0-9]+]] = ptrtoint i8* [[GPRPTR1]] to i32 ++// CHECK-PPC-NEXT: [[NINETEEN:%[0-9]+]] = add i32 [[EIGHTEEN]], 1 ++// CHECK-PPC-NEXT: [[TWENTY:%[0-9]+]] = inttoptr i32 [[NINETEEN]] to i8* ++// CHECK-PPC-NEXT: [[TWENTYONE:%[0-9]+]] = add i32 [[NINETEEN]], 3 ++// CHECK-PPC-NEXT: [[TWENTYTWO:%[0-9]+]] = inttoptr i32 [[TWENTYONE]] to i8** ++// CHECK-PPC-NEXT: [[TWENTYTHREE:%[0-9]+]] = add i32 [[TWENTYONE]], 4 ++// CHECK-PPC-NEXT: [[TWENTYFOUR:%[0-9]+]] = inttoptr i32 [[TWENTYTHREE]] to i8** ++// CHECK-PPC-NEXT: [[GPR1:%[a-z0-9]+]] = load i8* [[GPRPTR1]] ++// CHECK-PPC-NEXT: [[FPR1:%[a-z0-9]+]] = load i8* [[TWENTY]] ++// CHECK-PPC-NEXT: [[OVERFLOW_AREA1:%[a-z_0-9]+]] = load i8** [[TWENTYTWO]] ++// CHECK-PPC-NEXT: [[TWENTYFIVE:%[0-9]+]] = ptrtoint i8* [[OVERFLOW_AREA1]] to i32 ++// CHECK-PPC-NEXT: [[REGSAVE_AREA1:%[a-z_0-9]+]] = load i8** [[TWENTYFOUR]] ++// CHECK-PPC-NEXT: [[TWENTYSIX:%[0-9]+]] = ptrtoint i8* [[REGSAVE_AREA1]] to i32 ++// CHECK-PPC-NEXT: [[COND1:%[a-z0-9]+]] = icmp ult i8 [[GPR1]], 8 ++// CHECK-PPC-NEXT: [[TWENTYSEVEN:%[0-9]+]] = mul i8 [[GPR1]], 4 ++// CHECK-PPC-NEXT: [[TWENTYEIGHT:%[0-9]+]] = sext i8 [[TWENTYSEVEN]] to i32 ++// CHECK-PPC-NEXT: [[TWENTYNINE:%[0-9]+]] = add i32 [[TWENTYSIX]], [[TWENTYEIGHT]] ++// CHECK-PPC-NEXT: br i1 [[COND1]], label [[USING_REGS1:%[a-z_0-9]+]], label [[USING_OVERFLOW1:%[a-z_0-9]+]] ++// ++// CHECK-PPC1:[[USING_REGS1]]: ++// CHECK-PPC: [[THIRTY:%[0-9]+]] = inttoptr i32 [[TWENTYNINE]] to i32* ++// CHECK-PPC-NEXT: [[THIRTYONE:%[0-9]+]] = add i8 [[GPR1]], 1 ++// CHECK-PPC-NEXT: store i8 [[THIRTYONE]], i8* [[GPRPTR1]] ++// CHECK-PPC-NEXT: br label [[CONT1:%[a-z0-9]+]] ++// ++// CHECK-PPC1:[[USING_OVERFLOW1]]: ++// CHECK-PPC: [[THIRTYTWO:%[0-9]+]] = inttoptr i32 [[TWENTYFIVE]] to i32* ++// CHECK-PPC-NEXT: [[THIRTYTHREE:%[0-9]+]] = add i32 [[TWENTYFIVE]], 4 ++// CHECK-PPC-NEXT: [[THIRTYFOUR:%[0-9]+]] = inttoptr i32 [[THIRTYTHREE]] to i8* ++// CHECK-PPC-NEXT: store i8* [[THIRTYFOUR]], i8** [[TWENTYTWO]] ++// CHECK-PPC-NEXT: br label [[CONT1]] ++// ++// CHECK-PPC1:[[CONT1]]: ++// CHECK-PPC: [[VAARG_ADDR1:%[a-z.0-9]+]] = phi i32* [ [[THIRTY]], [[USING_REGS1]] ], [ [[THIRTYTWO]], [[USING_OVERFLOW1]] ] ++// CHECK-PPC-NEXT: [[THIRTYFIVE:%[0-9]+]] = load i32* [[VAARG_ADDR1]] ++// CHECK-PPC-NEXT: store i32 [[THIRTYFIVE]], i32* %v, align 4 ++ ++#ifdef __powerpc64__ ++ __int128_t u = va_arg (ap, __int128_t); ++#endif ++// CHECK: bitcast i8* %{{[a-z.0-9]+}} to i128* ++// CHECK-NEXT: load i128* %{{[0-9]+}} ++} diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c index 87fac81f38c6..dc93443e88f2 100644 --- a/contrib/unbound/iterator/iterator.c +++ b/contrib/unbound/iterator/iterator.c @@ -120,6 +120,7 @@ iter_new(struct module_qstate* qstate, int id) iq->query_restart_count = 0; iq->referral_count = 0; iq->sent_count = 0; + iq->target_count = NULL; iq->wait_priming_stub = 0; iq->refetch_glue = 0; iq->dnssec_expected = 0; @@ -445,6 +446,26 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq, return 1; } +/** create target count structure for this query */ +static void +target_count_create(struct iter_qstate* iq) +{ + if(!iq->target_count) { + iq->target_count = (int*)calloc(2, sizeof(int)); + /* if calloc fails we simply do not track this number */ + if(iq->target_count) + iq->target_count[0] = 1; + } +} + +static void +target_count_increase(struct iter_qstate* iq, int num) +{ + target_count_create(iq); + if(iq->target_count) + iq->target_count[1] += num; +} + /** * Generate a subrequest. * Generate a local request event. Local events are tied to this module, and @@ -516,6 +537,10 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, subiq = (struct iter_qstate*)subq->minfo[id]; memset(subiq, 0, sizeof(*subiq)); subiq->num_target_queries = 0; + target_count_create(iq); + subiq->target_count = iq->target_count; + if(iq->target_count) + iq->target_count[0] ++; /* extra reference */ subiq->num_current_queries = 0; subiq->depth = iq->depth+1; outbound_list_init(&subiq->outlist); @@ -1342,6 +1367,12 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq, if(iq->depth == ie->max_dependency_depth) return 0; + if(iq->depth > 0 && iq->target_count && + iq->target_count[1] > MAX_TARGET_COUNT) { + verbose(VERB_QUERY, "request has exceeded the maximum " + "number of glue fetches %d", iq->target_count[1]); + return 0; + } iter_mark_cycle_targets(qstate, iq->dp); missing = (int)delegpt_count_missing_targets(iq->dp); @@ -1524,6 +1555,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, return error_response(qstate, id, LDNS_RCODE_SERVFAIL); } iq->num_target_queries += qs; + target_count_increase(iq, qs); if(qs != 0) { qstate->ext_state[id] = module_wait_subquery; return 0; /* and wait for them */ @@ -1533,6 +1565,12 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, verbose(VERB_QUERY, "maxdepth and need more nameservers, fail"); return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); } + if(iq->depth > 0 && iq->target_count && + iq->target_count[1] > MAX_TARGET_COUNT) { + verbose(VERB_QUERY, "request has exceeded the maximum " + "number of glue fetches %d", iq->target_count[1]); + return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL); + } /* mark cycle targets for parent-side lookups */ iter_mark_pside_cycle_targets(qstate, iq->dp); /* see if we can issue queries to get nameserver addresses */ @@ -1562,6 +1600,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, if(query_count != 0) { /* suspend to await results */ verbose(VERB_ALGO, "try parent-side glue lookup"); iq->num_target_queries += query_count; + target_count_increase(iq, query_count); qstate->ext_state[id] = module_wait_subquery; return 0; } @@ -1717,6 +1756,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, return error_response(qstate, id, LDNS_RCODE_SERVFAIL); } iq->num_target_queries += extra; + target_count_increase(iq, extra); if(iq->num_target_queries > 0) { /* wait to get all targets, we want to try em */ verbose(VERB_ALGO, "wait for all targets for fallback"); @@ -1757,6 +1797,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* errors ignored, these targets are not strictly necessary for * this result, we do not have to reply with SERVFAIL */ iq->num_target_queries += extra; + target_count_increase(iq, extra); } /* Add the current set of unused targets to our queue. */ @@ -1802,6 +1843,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, return 1; } iq->num_target_queries += qs; + target_count_increase(iq, qs); } /* Since a target query might have been made, we * need to check again. */ @@ -2894,6 +2936,8 @@ iter_clear(struct module_qstate* qstate, int id) iq = (struct iter_qstate*)qstate->minfo[id]; if(iq) { outbound_list_clear(&iq->outlist); + if(iq->target_count && --iq->target_count[0] == 0) + free(iq->target_count); iq->num_current_queries = 0; } qstate->minfo[id] = NULL; diff --git a/contrib/unbound/iterator/iterator.h b/contrib/unbound/iterator/iterator.h index 1816d12cd031..f6aee34a65ab 100644 --- a/contrib/unbound/iterator/iterator.h +++ b/contrib/unbound/iterator/iterator.h @@ -52,6 +52,8 @@ struct iter_donotq; struct iter_prep_list; struct iter_priv; +/** max number of targets spawned for a query and its subqueries */ +#define MAX_TARGET_COUNT 32 /** max number of query restarts. Determines max number of CNAME chain. */ #define MAX_RESTART_COUNT 8 /** max number of referrals. Makes sure resolver does not run away */ @@ -254,6 +256,10 @@ struct iter_qstate { /** number of queries fired off */ int sent_count; + + /** number of target queries spawned in [1], for this query and its + * subqueries, the malloced-array is shared, [0] refcount. */ + int* target_count; /** * The query must store NS records from referrals as parentside RRs diff --git a/etc/Makefile b/etc/Makefile index ff70cc12ad0b..76db02a0cb26 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -333,7 +333,7 @@ MTREES+= mtree/BSD.debug.dist /usr/lib MTREES+= mtree/BSD.groff.dist /usr .endif .if ${MK_TESTS} != "no" -MTREES+= mtree/BSD.tests.dist /usr +MTREES+= mtree/BSD.tests.dist ${TESTSBASE} .endif .if ${MK_SENDMAIL} != "no" MTREES+= mtree/BSD.sendmail.dist / @@ -349,6 +349,7 @@ distrib-dirs: ${MTREES:N/*} shift; \ d=${DESTDIR}$$1; \ shift; \ + test -d $$d || mkdir -p $$d; \ ${ECHO} ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} \ -f $$m -p $$d; \ ${MTREE_CMD} -deU ${MTREE_FOLLOWS_SYMLINKS} -f $$m -p $$d; \ @@ -362,6 +363,7 @@ distrib-dirs: ${MTREES:N/*} test "$$d" == "/" && d=""; \ d=${DISTBASE}$$d; \ shift; \ + test -d $$d || mkdir -p $$d; \ ${ECHO} "${MTREE_CMD:N-W} -C -f $$m -K uname,gname | " \ "sed s#^\.#.$$d# | ${METALOG.add}" ; \ ${MTREE_CMD:N-W} -C -f $$m -K uname,gname | sed s#^\.#.$$d# | \ diff --git a/etc/devd/usb.conf b/etc/devd/usb.conf index 7828a8561cfe..9baa070cf840 100644 --- a/etc/devd/usb.conf +++ b/etc/devd/usb.conf @@ -1017,7 +1017,23 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x056e"; - match "product" "(0x200c|0x4002|0x4005|0x400b|0x4010)"; + match "product" "(0x200c|0x4002|0x4005)"; + action "kldload -n if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "0x4008"; + action "kldload -n if_urtwn"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "(0x400b|0x4010)"; action "kldload -n if_aue"; }; @@ -1177,7 +1193,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x05c6"; - match "product" "(0x1000|0x6000|0x6613|0x9000|0x9204|0x9205)"; + match "product" "(0x1000|0x6000|0x6500|0x6613|0x9000|0x9204|0x9205)"; action "kldload -n u3g"; }; @@ -2545,7 +2561,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0bda"; - match "product" "(0x8176|0x8176|0x8177|0x8178|0x8179|0x817a|0x817b|0x817c|0x817d|0x817e)"; + match "product" "(0x8176|0x8176|0x8177|0x8178|0x8179|0x817a|0x817b|0x817c|0x817d|0x817e|0x817f)"; action "kldload -n if_urtwn"; }; @@ -3617,7 +3633,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x12d1"; - match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1464|0x1465|0x14ac|0x14c9|0x14d1|0x14fe|0x1505|0x1506|0x1520|0x1521)"; + match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1464|0x1465|0x14ac|0x14c9|0x14cf|0x14d1|0x14fe|0x1505|0x1506|0x1520|0x1521|0x1526)"; action "kldload -n u3g"; }; @@ -4489,7 +4505,15 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x19d2"; - match "product" "(0x0001|0x0002|0x0003|0x0004|0x0005|0x0006|0x0007|0x0008|0x0009|0x000a|0x000b|0x000c|0x000d|0x000e|0x000f|0x0010|0x0011|0x0012|0x0013|0x0014|0x0015|0x0016|0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0030|0x0031|0x0032|0x0033|0x0037|0x0039|0x0042|0x0043|0x0048|0x0049|0x0051|0x0052|0x0053|0x0054|0x0055|0x0057|0x0058|0x0059|0x0060|0x0061|0x0062|0x0063|0x0064|0x0066|0x0069|0x0070|0x0073|0x0076|0x0078|0x0082|0x0086|0x0117|0x1179|0x2000|0x2002|0x2003|0xfff1|0xfff5|0xfffe)"; + match "product" "(0x0001|0x0002|0x0003|0x0004|0x0005|0x0006|0x0007|0x0008|0x0009|0x000a|0x000b|0x000c|0x000d|0x000e|0x000f|0x0010|0x0011|0x0012|0x0013|0x0014|0x0015|0x0016|0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0030|0x0031|0x0032|0x0033|0x0037|0x0039|0x0042|0x0043|0x0048|0x0049|0x0051|0x0052|0x0053|0x0054|0x0055|0x0057|0x0058|0x0059|0x0060|0x0061|0x0062|0x0063|0x0064|0x0066|0x0069|0x0070|0x0073|0x0076|0x0078|0x0082|0x0086|0x0117|0x1179|0x1181|0x1514|0x1516|0x2000|0x2002|0x2003|0xffdd|0xffde|0xfff1|0xfff5|0xfffe)"; + action "kldload -n u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x19f5"; + match "product" "0x9909"; action "kldload -n u3g"; }; @@ -4609,7 +4633,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x1cf1"; - match "product" "(0x0001|0x0004|0x0022)"; + match "product" "(0x0001|0x0004|0x001c|0x0022)"; action "kldload -n uftdi"; }; @@ -4697,7 +4721,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x2001"; - match "product" "(0x3307|0x3308|0x3309|0x330a|0x330d|0x330f)"; + match "product" "(0x3307|0x3308|0x3309|0x330a|0x330d|0x330f|0x3310)"; action "kldload -n if_urtwn"; }; @@ -4897,7 +4921,23 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x20f4"; - match "product" "(0x624d|0x648b)"; + match "product" "0x624d"; + action "kldload -n if_urtwn"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x20f4"; + match "product" "0x646b"; + action "kldload -n if_rsu"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x20f4"; + match "product" "0x648b"; action "kldload -n if_urtwn"; }; @@ -5291,6 +5331,16 @@ nomatch 32 { action "kldload -n if_ipheth"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0830"; + match "intclass" "0x02"; + match "intsubclass" "0x02"; + match "intprotocol" "0xff"; + action "kldload -n if_urndis"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -5301,6 +5351,16 @@ nomatch 32 { action "kldload -n ng_ubt"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "intclass" "0x02"; + match "intsubclass" "0x02"; + match "intprotocol" "0xff"; + action "kldload -n umodem"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -5349,15 +5409,6 @@ nomatch 32 { action "kldload -n umodem"; }; -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x02"; - match "intsubclass" "0x02"; - match "intprotocol" "0xff"; - action "kldload -n umodem"; -}; - nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -5501,5 +5552,5 @@ nomatch 32 { action "kldload -n umass"; }; -# 2643 USB entries processed +# 2658 USB entries processed diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 0a4eada108d7..6cadb8fd70d3 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -9,6 +9,10 @@ .. arpa .. + atf-c + .. + atf-c++ + .. bsm .. bsnmp diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 5285fe3c3f2b..2708568bc785 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -5,410 +5,392 @@ /set type=dir uname=root gname=wheel mode=0755 . - include - atf-c + bin + chown .. - atf-c++ + date + .. + mv + .. + pax + .. + pkill + .. + sh + builtins + .. + errors + .. + execution + .. + expansion + .. + parameters + .. + parser + .. + set-e + .. + .. + sleep + .. + test + .. + .. + cddl + lib + .. + sbin + .. + usr.bin + .. + usr.sbin + .. + .. + etc + .. + games + .. + gnu + lib + .. + usr.bin + diff + .. + .. + .. + lib + atf + libatf-c + detail + .. + .. + libatf-c++ + detail + .. + .. + test-programs + .. + .. + libc + c063 + .. + db + .. + gen + execve + .. + posix_spawn + .. + .. + hash + data + .. + .. + inet + .. + locale + .. + net + getaddrinfo + data + .. + .. + .. + regex + data + .. + .. + ssp + .. + stdio + .. + stdlib + .. + string + .. + sys + .. + time + .. + tls + dso + .. + .. + termios + .. + ttyio + .. + .. + libcrypt + .. + libmp + .. + libnv + .. + libpam + .. + libproc + .. + librt + .. + libthr + dlopen + .. + .. + libutil + .. + msun + .. + .. + libexec + atf + atf-check + .. + atf-sh + .. + .. + rtld-elf + .. + .. + sbin + dhclient + .. + devd + .. + growfs + .. + mdconfig + .. + .. + secure + lib + .. + libexec + .. + usr.bin + .. + usr.sbin .. .. share - atf - .. - doc - atf - .. - pjdfstest + examples + tests + atf + .. + plain + .. .. .. .. - tests - bin + sys + kern + .. + netinet + .. + opencrypto + .. + pjdfstest + chflags + .. + chmod + .. chown .. - date + ftruncate .. - mv + granular .. - pax + link .. - pkill + mkdir .. - sh - builtins - .. - errors - .. - execution - .. - expansion - .. - parameters - .. - parser - .. - set-e - .. + mkfifo .. - sleep + mknod .. - test + open .. - .. - cddl - lib + rename .. - sbin + rmdir .. - usr.bin - .. - usr.sbin - .. - .. - etc - .. - games - .. - gnu - lib - .. - usr.bin - diff - .. - .. - .. - lib - atf - libatf-c - detail - .. - .. - libatf-c++ - detail - .. - .. - test-programs - .. - .. - libc - c063 - .. - db - .. - gen - execve - .. - posix_spawn - .. - .. - hash - data - .. - .. - inet - .. - locale - .. - net - getaddrinfo - data - .. - .. - .. - regex - data - .. - .. - ssp - .. - stdio - .. - stdlib - .. - string - .. - sys - .. - time - .. - tls - dso - .. - .. - termios - .. - ttyio - .. - .. - libcrypt - .. - libmp - .. - libnv - .. - libpam - .. - libproc - .. - librt - .. - libthr - dlopen - .. - .. - libutil - .. - msun - .. - .. - libexec - atf - atf-check - .. - atf-sh - .. - .. - rtld-elf - .. - .. - sbin - dhclient - .. - devd - .. - growfs - .. - mdconfig - .. - .. - secure - lib - .. - libexec - .. - usr.bin - .. - usr.sbin - .. - .. - share - examples - tests - atf - .. - plain - .. - .. - .. - .. - sys - kern - .. - netinet - .. - opencrypto - .. - pjdfstest - chflags - .. - chmod - .. - chown - .. - ftruncate - .. - granular - .. - link - .. - mkdir - .. - mkfifo - .. - mknod - .. - open - .. - rename - .. - rmdir - .. - symlink - .. - truncate - .. - unlink - .. - .. - .. - usr.bin - apply - .. - basename - .. - bmake - archives - fmt_44bsd - .. - fmt_44bsd_mod - .. - fmt_oldbsd - .. - .. - basic - t0 - .. - t1 - .. - t2 - .. - t3 - .. - .. - execution - ellipsis - .. - empty - .. - joberr - .. - plus - .. - .. - shell - builtin - .. - meta - .. - path - .. - path_select - .. - replace - .. - select - .. - .. - suffixes - basic - .. - src_wild1 - .. - src_wild2 - .. - .. - syntax - directive-t0 - .. - enl - .. - funny-targets - .. - semi - .. - .. - sysmk - t0 - 2 - 1 - .. - .. - mk - .. - .. - t1 - 2 - 1 - .. - .. - mk - .. - .. - t2 - 2 - 1 - .. - .. - mk - .. - .. - .. - variables - modifier_M - .. - modifier_t - .. - opt_V - .. - t0 - .. - .. - .. - calendar - .. - cmp - .. - comm - .. - cut - .. - dirname - .. - file2c - .. - grep - .. - gzip - .. - join - .. - jot - .. - lastcomm - .. - m4 - .. - mkimg - .. - ncal - .. - printf - .. - sed - regress.multitest.out - .. - .. - timeout - .. - tr + symlink .. truncate .. - units + unlink .. - uudecode + .. + .. + usr.bin + apply + .. + basename + .. + bmake + archives + fmt_44bsd + .. + fmt_44bsd_mod + .. + fmt_oldbsd + .. .. - uuencode + basic + t0 + .. + t1 + .. + t2 + .. + t3 + .. .. - xargs + execution + ellipsis + .. + empty + .. + joberr + .. + plus + .. .. - yacc - yacc + shell + builtin + .. + meta + .. + path + .. + path_select + .. + replace + .. + select + .. + .. + suffixes + basic + .. + src_wild1 + .. + src_wild2 + .. + .. + syntax + directive-t0 + .. + enl + .. + funny-targets + .. + semi + .. + .. + sysmk + t0 + 2 + 1 + .. + .. + mk + .. + .. + t1 + 2 + 1 + .. + .. + mk + .. + .. + t2 + 2 + 1 + .. + .. + mk + .. + .. + .. + variables + modifier_M + .. + modifier_t + .. + opt_V + .. + t0 .. .. .. - usr.sbin - etcupdate + calendar + .. + cmp + .. + comm + .. + cut + .. + dirname + .. + file2c + .. + grep + .. + gzip + .. + join + .. + jot + .. + lastcomm + .. + m4 + .. + mkimg + .. + ncal + .. + printf + .. + sed + regress.multitest.out .. - newsyslog - .. - nmtree - .. - pw - .. - sa + .. + timeout + .. + tr + .. + truncate + .. + units + .. + uudecode + .. + uuencode + .. + xargs + .. + yacc + yacc .. .. .. + usr.sbin + etcupdate + .. + newsyslog + .. + nmtree + .. + pw + .. + sa + .. + .. .. # vim: set expandtab ts=4 sw=4: diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index 977cf754d451..c24d5c4e606b 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -126,6 +126,8 @@ sbin .. share + atf + .. bsdconfig media .. @@ -169,6 +171,8 @@ doc IPv6 .. + atf + .. atm .. legal @@ -189,6 +193,8 @@ .. papers .. + pjdfstest + .. psd 01.cacm .. diff --git a/gnu/usr.bin/cc/cc1plus/Makefile b/gnu/usr.bin/cc/cc1plus/Makefile index 64a07255e011..5d5a64d2e298 100644 --- a/gnu/usr.bin/cc/cc1plus/Makefile +++ b/gnu/usr.bin/cc/cc1plus/Makefile @@ -30,7 +30,7 @@ LDADD= ${LIBBACKEND} ${LIBCPP} ${LIBDECNUMBER} ${LIBIBERTY} # C++ parser cfns.h: cfns.gperf gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' -L ANSI-C \ - ${.ALLSRC} > ${.TARGET} + ${.ALLSRC} > ${.TARGET} || (rm -f ${.TARGET}; false) CLEANFILES= cfns.h DOBJS+= ${SRCS:N*.h:R:S/$/.o/g} diff --git a/gnu/usr.bin/groff/Makefile b/gnu/usr.bin/groff/Makefile index 7c61f71be945..2db554f6d408 100644 --- a/gnu/usr.bin/groff/Makefile +++ b/gnu/usr.bin/groff/Makefile @@ -2,4 +2,8 @@ SUBDIR= contrib doc font man src tmac +.for subdir in ${SUBDIR:Nsrc} +SUBDIR_DEPEND_${subdir}= src +.endfor + .include diff --git a/gnu/usr.bin/groff/src/Makefile b/gnu/usr.bin/groff/src/Makefile index 7d2ca90a2252..291b27c9d56a 100644 --- a/gnu/usr.bin/groff/src/Makefile +++ b/gnu/usr.bin/groff/src/Makefile @@ -2,4 +2,10 @@ SUBDIR= libs devices preproc roff utils +SUBDIR_PARALLEL= + +.for subdir in ${SUBDIR:Nlibs} +SUBDIR_DEPEND_${subdir}= libs +.endfor + .include diff --git a/gnu/usr.bin/groff/src/devices/Makefile b/gnu/usr.bin/groff/src/devices/Makefile index 8af4ff85b996..53dc4ed1581a 100644 --- a/gnu/usr.bin/groff/src/devices/Makefile +++ b/gnu/usr.bin/groff/src/devices/Makefile @@ -2,4 +2,6 @@ SUBDIR= grodvi grohtml grolbp grolj4 grops grotty +SUBDIR_PARALLEL= + .include diff --git a/gnu/usr.bin/groff/src/libs/Makefile b/gnu/usr.bin/groff/src/libs/Makefile index 1461cda28bac..373831492640 100644 --- a/gnu/usr.bin/groff/src/libs/Makefile +++ b/gnu/usr.bin/groff/src/libs/Makefile @@ -2,4 +2,6 @@ SUBDIR= libgroff libdriver libbib +SUBDIR_PARALLEL= + .include diff --git a/gnu/usr.bin/groff/src/preproc/Makefile b/gnu/usr.bin/groff/src/preproc/Makefile index 70af839313d6..f208bf2389be 100644 --- a/gnu/usr.bin/groff/src/preproc/Makefile +++ b/gnu/usr.bin/groff/src/preproc/Makefile @@ -2,4 +2,6 @@ SUBDIR= eqn grn html pic refer soelim tbl +SUBDIR_PARALLEL= + .include diff --git a/gnu/usr.bin/groff/src/roff/Makefile b/gnu/usr.bin/groff/src/roff/Makefile index 543a990c680f..6f23c42c95a8 100644 --- a/gnu/usr.bin/groff/src/roff/Makefile +++ b/gnu/usr.bin/groff/src/roff/Makefile @@ -2,4 +2,6 @@ SUBDIR= groff grog nroff psroff troff +SUBDIR_PARALLEL= + .include diff --git a/gnu/usr.bin/groff/src/utils/Makefile b/gnu/usr.bin/groff/src/utils/Makefile index 14953b925312..045030cb4417 100644 --- a/gnu/usr.bin/groff/src/utils/Makefile +++ b/gnu/usr.bin/groff/src/utils/Makefile @@ -2,4 +2,6 @@ SUBDIR= addftinfo afmtodit hpftodit indxbib lkbib lookbib pfbtops tfmtodit +SUBDIR_PARALLEL= + .include diff --git a/lib/libc/iconv/iconv.3 b/lib/libc/iconv/iconv.3 index 6692c47d4f7d..c4c250d89edd 100644 --- a/lib/libc/iconv/iconv.3 +++ b/lib/libc/iconv/iconv.3 @@ -48,7 +48,7 @@ .Ft size_t .Fn iconv "iconv_t cd" "char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft" .Ft size_t -.Fn __iconv "iconv_t cd" "const char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft" "uint32_t flags" "size_t invalids" +.Fn __iconv "iconv_t cd" "const char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft" "uint32_t flags" "size_t * invalids" .Sh DESCRIPTION The .Fn iconv_open diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c index ea66df9d886c..6971c606dbcd 100644 --- a/lib/libc/net/sctp_sys_calls.c +++ b/lib/libc/net/sctp_sys_calls.c @@ -597,6 +597,7 @@ sctp_sendmsg(int s, msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)); + msg.msg_flags = 0; cmsg = (struct cmsghdr *)cmsgbuf; cmsg->cmsg_level = IPPROTO_SCTP; cmsg->cmsg_type = SCTP_SNDRCV; @@ -663,6 +664,7 @@ sctp_send(int sd, const void *data, size_t len, msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)); + msg.msg_flags = 0; cmsg = (struct cmsghdr *)cmsgbuf; cmsg->cmsg_level = IPPROTO_SCTP; cmsg->cmsg_type = SCTP_SNDRCV; @@ -820,7 +822,6 @@ sctp_recvmsg(int s, errno = EINVAL; return (-1); } - msg.msg_flags = 0; iov.iov_base = dbuf; iov.iov_len = len; msg.msg_name = (caddr_t)from; @@ -832,6 +833,7 @@ sctp_recvmsg(int s, msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); + msg.msg_flags = 0; sz = recvmsg(s, &msg, *msg_flags); *msg_flags = msg.msg_flags; if (sz <= 0) { @@ -905,6 +907,7 @@ sctp_recvv(int sd, msg.msg_iovlen = iovlen; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); + msg.msg_flags = 0; ret = recvmsg(sd, &msg, *flags); *flags = msg.msg_flags; if ((ret > 0) && diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2 index 9a7cc235e0c0..93223f1fea6e 100644 --- a/lib/libc/sys/kqueue.2 +++ b/lib/libc/sys/kqueue.2 @@ -162,56 +162,56 @@ struct kevent { The fields of .Fa struct kevent are: -.Bl -tag -width XXXfilter -.It ident +.Bl -tag -width "Fa filter" +.It Fa ident Value used to identify this event. The exact interpretation is determined by the attached filter, but often is a file descriptor. -.It filter +.It Fa filter Identifies the kernel filter used to process this event. The pre-defined system filters are described below. -.It flags +.It Fa flags Actions to perform on the event. -.It fflags +.It Fa fflags Filter-specific flags. -.It data +.It Fa data Filter-specific data value. -.It udata +.It Fa udata Opaque user-defined value passed through the kernel unchanged. .El .Pp The .Va flags field can contain the following values: -.Bl -tag -width XXXEV_ONESHOT -.It EV_ADD +.Bl -tag -width EV_DISPATCH +.It Dv EV_ADD Adds the event to the kqueue. Re-adding an existing event will modify the parameters of the original event, and not result in a duplicate entry. Adding an event automatically enables it, unless overridden by the EV_DISABLE flag. -.It EV_ENABLE +.It Dv EV_ENABLE Permit .Fn kevent to return the event if it is triggered. -.It EV_DISABLE +.It Dv EV_DISABLE Disable the event so .Fn kevent will not return it. The filter itself is not disabled. -.It EV_DISPATCH +.It Dv EV_DISPATCH Disable the event source immediately after delivery of an event. See .Dv EV_DISABLE above. -.It EV_DELETE +.It Dv EV_DELETE Removes the event from the kqueue. Events which are attached to file descriptors are automatically deleted on the last close of the descriptor. -.It EV_RECEIPT +.It Dv EV_RECEIPT This flag is useful for making bulk changes to a kqueue without draining any pending events. When passed as input, it forces @@ -220,20 +220,20 @@ to always be returned. When a filter is successfully added the .Va data field will be zero. -.It EV_ONESHOT +.It Dv EV_ONESHOT Causes the event to return only the first occurrence of the filter being triggered. After the user retrieves the event from the kqueue, it is deleted. -.It EV_CLEAR +.It Dv EV_CLEAR After the event is retrieved by the user, its state is reset. This is useful for filters which report state transitions instead of the current state. Note that some filters may automatically set this flag internally. -.It EV_EOF +.It Dv EV_EOF Filters may set this flag to indicate filter-specific EOF condition. -.It EV_ERROR +.It Dv EV_ERROR See .Sx RETURN VALUES below. @@ -245,8 +245,8 @@ Arguments may be passed to and from the filter via the and .Va data fields in the kevent structure. -.Bl -tag -width EVFILT_PROCDESC -.It EVFILT_READ +.Bl -tag -width "Dv EVFILT_PROCDESC" +.It Dv EVFILT_READ Takes a descriptor as the identifier, and returns whenever there is data available to read. The behavior of the filter is slightly different depending @@ -265,7 +265,7 @@ subject to the value of the socket buffer. This may be overridden with a per-filter low water mark at the time the filter is added by setting the -NOTE_LOWAT +.Dv NOTE_LOWAT flag in .Va fflags , and specifying the new low water mark in @@ -275,7 +275,9 @@ On return, contains the number of bytes of protocol data available to read. .Pp If the read direction of the socket has shutdown, then the filter -also sets EV_EOF in +also sets +.Dv EV_EOF +in .Va flags , and returns the socket error (if any) in .Va fflags . @@ -291,9 +293,13 @@ Returns when the there is data to read; .Va data contains the number of bytes available. .Pp -When the last writer disconnects, the filter will set EV_EOF in +When the last writer disconnects, the filter will set +.Dv EV_EOF +in .Va flags . -This may be cleared by passing in EV_CLEAR, at which point the +This may be cleared by passing in +.Dv EV_CLEAR , +at which point the filter will resume waiting for data to become available before returning. .It "BPF devices" @@ -304,7 +310,7 @@ enabled and there is any data to read; .Va data contains the number of bytes available. .El -.It EVFILT_WRITE +.It Dv EVFILT_WRITE Takes a descriptor as the identifier, and returns whenever it is possible to write to the descriptor. For sockets, pipes @@ -312,23 +318,30 @@ and fifos, .Va data will contain the amount of space remaining in the write buffer. The filter will set EV_EOF when the reader disconnects, and for -the fifo case, this may be cleared by use of EV_CLEAR. +the fifo case, this may be cleared by use of +.Dv EV_CLEAR . Note that this filter is not supported for vnodes or BPF devices. .Pp For sockets, the low water mark and socket error handling is -identical to the EVFILT_READ case. -.It EVFILT_AIO +identical to the +.Dv EVFILT_READ +case. +.It Dv EVFILT_AIO The sigevent portion of the AIO request is filled in, with .Va sigev_notify_kqueue containing the descriptor of the kqueue that the event should be attached to, .Va sigev_notify_kevent_flags -containing the kevent flags which should be EV_ONESHOT, EV_CLEAR or -EV_DISPATCH, +containing the kevent flags which should be +.Dv EV_ONESHOT , +.Dv EV_CLEAR +or +.Dv EV_DISPATCH , .Va sigev_value containing the udata value, and .Va sigev_notify -set to SIGEV_KEVENT. +set to +.Dv SIGEV_KEVENT . When the .Fn aio_* system call is made, the event will be registered @@ -339,29 +352,30 @@ argument set to the returned by the .Fn aio_* system call. -The filter returns under the same conditions as aio_error. -.It EVFILT_VNODE +The filter returns under the same conditions as +.Fn aio_error . +.It Dv EVFILT_VNODE Takes a file descriptor as the identifier and the events to watch for in .Va fflags , and returns when one or more of the requested events occurs on the descriptor. The events to monitor are: -.Bl -tag -width XXNOTE_RENAME -.It NOTE_DELETE +.Bl -tag -width "Dv NOTE_RENAME" +.It Dv NOTE_DELETE The .Fn unlink system call was called on the file referenced by the descriptor. -.It NOTE_WRITE +.It Dv NOTE_WRITE A write occurred on the file referenced by the descriptor. -.It NOTE_EXTEND +.It Dv NOTE_EXTEND The file referenced by the descriptor was extended. -.It NOTE_ATTRIB +.It Dv NOTE_ATTRIB The file referenced by the descriptor had its attributes changed. -.It NOTE_LINK +.It Dv NOTE_LINK The link count on the file changed. -.It NOTE_RENAME +.It Dv NOTE_RENAME The file referenced by the descriptor was renamed. -.It NOTE_REVOKE +.It Dv NOTE_REVOKE Access to the file was revoked via .Xr revoke 2 or the underlying file system was unmounted. @@ -370,26 +384,26 @@ or the underlying file system was unmounted. On return, .Va fflags contains the events which triggered the filter. -.It EVFILT_PROC +.It Dv EVFILT_PROC Takes the process ID to monitor as the identifier and the events to watch for in .Va fflags , and returns when the process performs one or more of the requested events. If a process can normally see another process, it can attach an event to it. The events to monitor are: -.Bl -tag -width XXNOTE_TRACKERR -.It NOTE_EXIT +.Bl -tag -width "Dv NOTE_TRACKERR" +.It Dv NOTE_EXIT The process has exited. The exit status will be stored in .Va data . -.It NOTE_FORK +.It Dv NOTE_FORK The process has called .Fn fork . -.It NOTE_EXEC +.It Dv NOTE_EXEC The process has executed a new process via .Xr execve 2 or a similar call. -.It NOTE_TRACK +.It Dv NOTE_TRACK Follow a process across .Fn fork calls. @@ -397,22 +411,28 @@ The parent process registers a new kevent to monitor the child process using the same .Va fflags as the original event. -The child process will signal an event with NOTE_CHILD set in +The child process will signal an event with +.Dv NOTE_CHILD +set in .Va fflags and the parent PID in .Va data . .Pp If the parent process fails to register a new kevent .Pq usually due to resource limitations , -it will signal an event with NOTE_TRACKERR set in +it will signal an event with +.Dv NOTE_TRACKERR +set in .Va fflags , -and the child process will not signal a NOTE_CHILD event. +and the child process will not signal a +.Dv NOTE_CHILD +event. .El .Pp On return, .Va fflags contains the events which triggered the filter. -.It EVFILT_PROCDESC +.It Dv EVFILT_PROCDESC Takes the process descriptor created by .Xr pdfork 2 to monitor as the identifier and the events to watch for in @@ -420,8 +440,8 @@ to monitor as the identifier and the events to watch for in and returns when the associated process performs one or more of the requested events. The events to monitor are: -.Bl -tag -width XXNOTE_EXIT -.It NOTE_EXIT +.Bl -tag -width "Dv NOTE_EXIT" +.It Dv NOTE_EXIT The process has exited. The exit status will be stored in .Va data . @@ -430,7 +450,7 @@ The exit status will be stored in On return, .Va fflags contains the events which triggered the filter. -.It EVFILT_SIGNAL +.It Dv EVFILT_SIGNAL Takes the signal number to monitor as the identifier and returns when the given signal is delivered to the process. This coexists with the @@ -440,7 +460,9 @@ and facilities, and has a lower precedence. The filter will record all attempts to deliver a signal to a process, even if the signal has -been marked as SIG_IGN, except for the +been marked as +.Dv SIG_IGN , +except for the .Dv SIGCHLD signal, which, if ignored, won't be recorded by the filter. Event notification happens after normal @@ -448,14 +470,18 @@ signal delivery processing. .Va data returns the number of times the signal has occurred since the last call to .Fn kevent . -This filter automatically sets the EV_CLEAR flag internally. -.It EVFILT_TIMER +This filter automatically sets the +.Dv EV_CLEAR +flag internally. +.It Dv EVFILT_TIMER Establishes an arbitrary timer identified by .Va ident . When adding a timer, .Va data specifies the timeout period. -The timer will be periodic unless EV_ONESHOT is specified. +The timer will be periodic unless +.Dv EV_ONESHOT +is specified. On return, .Va data contains the number of times the timeout has expired since the last call to @@ -465,7 +491,7 @@ There is a system wide limit on the number of timers which is controlled by the .Va kern.kq_calloutmax sysctl. -.Bl -tag -width XXNOTE_USECONDS +.Bl -tag -width "Dv NOTE_USECONDS" .It Dv NOTE_SECONDS .Va data is in seconds. @@ -493,7 +519,7 @@ user level code. The lower 24 bits of the .Va fflags may be used for user defined flags and manipulated using the following: -.Bl -tag -width XXNOTE_FFLAGSMASK +.Bl -tag -width "Dv NOTE_FFLAGSMASK" .It Dv NOTE_FFNOP Ignore the input .Va fflags . @@ -515,7 +541,7 @@ User defined flag mask for .El .Pp A user event is triggered for output with the following: -.Bl -tag -width XXNOTE_FFLAGSMASK +.Bl -tag -width "Dv NOTE_FFLAGSMASK" .It Dv NOTE_TRIGGER Cause the event to be triggered. .El diff --git a/lib/libc/sys/procctl.2 b/lib/libc/sys/procctl.2 index 6ad0590804ad..70ee276922fa 100644 --- a/lib/libc/sys/procctl.2 +++ b/lib/libc/sys/procctl.2 @@ -2,6 +2,10 @@ .\" Written by: John H. Baldwin .\" All rights reserved. .\" +.\" Copyright (c) 2014 The FreeBSD Foundation +.\" Portions of this documentation were written by Konstantin Belousov +.\" under sponsorship from the FreeBSD Foundation. +.\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: @@ -25,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 19, 2013 +.Dd December 16, 2014 .Dt PROCCTL 2 .Os .Sh NAME @@ -67,7 +71,7 @@ The control request to perform is specified by the .Fa cmd argument. The following commands are supported: -.Bl -tag -width "Dv PROC_SPROTECT" +.Bl -tag -width "Dv PROC_REAP_GETPIDS" .It Dv PROC_SPROTECT Set process protection state. This is used to mark a process as protected from being killed if the system @@ -95,6 +99,182 @@ When used with mark all future child processes of each selected process as protected. Future child processes will also mark all of their future child processes. .El +.It Dv PROC_REAP_ACQUIRE +Acquires the reaper status for the current process. +The status means that children orphaned by the reaper's descendants +that were forked after the acquisition of the status are reparented to the +reaper. +After the system initialization, +.Xr init 8 +is the default reaper. +.Pp +.It Dv PROC_REAP_RELEASE +Releases the reaper state for the current process. +The reaper of the current process becomes the new reaper of the +current process's descendants. +.It Dv PROC_REAP_STATUS +Provides the information about the reaper of the specified process, +or the process itself when it is a reaper. +The +.Fa data +argument must point to a +.Vt procctl_reaper_status +structure which is filled in by the syscall on successful return. +.Bd -literal +struct procctl_reaper_status { + u_int rs_flags; + u_int rs_children; + u_int rs_descendants; + pid_t rs_reaper; + pid_t rs_pid; +}; +.Ed +The +.Fa rs_flags +may have the following flags returned: +.Bl -tag -width "Dv REAPER_STATUS_REALINIT" +.It Dv REAPER_STATUS_OWNED +The specified process has acquired the reaper status and has not +released it. +When the flag is returned, the specified process +.Fa id , +pid, identifies the reaper, otherwise the +.Fa rs_reaper +field of the structure is set to the pid of the reaper +for the specified process id. +.It Dv REAPER_STATUS_REALINIT +The specified process is the root of the reaper tree, i.e. +.Xr init 8 . +.El +The +.Fa rs_children +field returns the number of children of the reaper. +The +.Fa rs_descendants +field returns the total number of descendants of the reaper(s), +not counting descendants of the reaper in the subtree. +The +.Fa rs_reaper +field returns the reaper pid. +The +.Fa rs_pid +returns the pid of one reaper child if there are any descendants. +.It Dv PROC_REAP_GETPIDS +Queries the list of descendants of the reaper of the specified process. +The request takes a pointer to a +.Vt procctl_reaper_pids +structure in the +.Fa data +parameter. +.Bd -literal +struct procctl_reaper_pids { + u_int rp_count; + struct procctl_reaper_pidinfo *rp_pids; +}; +.Ed +When called, the +.Fa rp_pids +field must point to an array of +.Vt procctl_reaper_pidinfo +structures, to be filled in on return, +and the +.Fa rp_count +field must specify the size of the array, +into which no more than +.Fa rp_count +elements will be filled in by the kernel. +.Pp +The +.Vt "struct procctl_reaper_pidinfo" +structure provides some information about one of the reaper's descendants. +Note that for a descendant that is not a child, it may be incorrectly +identified because of a race in which the original child process exited +and the exited process's pid was reused for an unrelated process. +.Bd -literal +struct procctl_reaper_pidinfo { + pid_t pi_pid; + pid_t pi_subtree; + u_int pi_flags; +}; +.Ed +The +.Fa pi_pid +field is the process id of the descendant. +The +.Fa pi_subtree +field provides the pid of the child of the reaper, which is the (grand-)parent +of the process. +The +.Fa pi_flags +field returns the following flags, further describing the descendant: +.Bl -tag -width "Dv REAPER_PIDINFO_VALID" +.It Dv REAPER_PIDINFO_VALID +Set to indicate that the +.Vt procctl_reaper_pidinfo +structure was filled in by the kernel. +Zero-filling the +.Fa rp_pids +array and testing the +.Dv REAPER_PIDINFO_VALID +flag allows the caller to detect the end +of the returned array. +.It Dv REAPER_PIDINFO_CHILD +The +.Fa pi_pid +field identifies the direct child of the reaper. +.El +.It Dv PROC_REAP_KILL +Request to deliver a signal to some subset of the descendants of the reaper. +The +.Fa data +parameter must point to a +.Vt procctl_reaper_kill +structure, which is used both for parameters and status return. +.Bd -literal +struct procctl_reaper_kill { + int rk_sig; + u_int rk_flags; + pid_t rk_subtree; + u_int rk_killed; + pid_t rk_fpid; +}; +.Ed +The +.Fa rk_sig +field specifies the signal to be delivered. +Zero is not a valid signal number, unlike +.Xr kill 2 . +The +.Fa rk_flags +field further directs the operation. +It is or-ed from the following flags: +.Bl -tag -width "Dv REAPER_KILL_CHILDREN" +.It Dv REAPER_KILL_CHILDREN +Deliver the specified signal only to direct children of the reaper. +.It Dv REAPER_KILL_SUBTREE +Deliver the specified signal only to descendants that were forked by +the direct child with pid specified in the +.Fa rk_subtree +field. +.El +If neither the +.Dv REAPER_KILL_CHILDREN +nor the +.Dv REAPER_KILL_SUBTREE +flags are specified, all current descendants of the reaper are signalled. +.Pp +If a signal was delivered to any process, the return value from the request +is zero. +In this case, the +.Fa rk_killed +field identifies the number of processes signalled. +The +.Fa rk_fpid +field is set to the pid of the first process for which signal +delivery failed, e.g. due to the permission problems. +If no such process exist, the +.Fa rk_fpid +field is set to -1. .El .Sh RETURN VALUES If an error occurs, a value of -1 is returned and @@ -109,7 +289,7 @@ will fail if: .It Bq Er EFAULT The .Fa arg -points outside the process's allocated address space. +parameter points outside the process's allocated address space. .It Bq Er EINVAL The .Fa cmd @@ -132,11 +312,48 @@ An invalid operation or flag was passed in for a .Dv PROC_SPROTECT command. +.It Bq Er EPERM +The +.Fa idtype +argument is not equal to +.Dv P_PID , +or +.Fa id +is not equal to the pid of the calling process, for +.Dv PROC_REAP_ACQUIRE +or +.Dv PROC_REAP_RELEASE +requests. +.It Bq Er EINVAL +Invalid or undefined flags were passed to a +.Dv PROC_REAP_KILL +request. +.It Bq Er EINVAL +An invalid or zero signal number was requested for a +.Dv PROC_REAP_KILL +request. +.It Bq Er EINVAL +The +.Dv PROC_REAP_RELEASE +request was issued by the +.Xr init 8 +process. +.It Bq Er EBUSY +The +.Dv PROC_REAP_ACQUIRE +request was issued by a process that had already acquired reaper status +and has not yet released it. .El .Sh SEE ALSO -.Xr ptrace 2 +.Xr kill 2 , +.Xr ptrace 2 , +.Xr wait 2 , +.Xr init 8 .Sh HISTORY The .Fn procctl function appeared in .Fx 10.0 . +The reaper facility is based on a similar feature of Linux and +DragonflyBSD, and first appeared in +.Fx 10.2 . diff --git a/lib/msun/ld128/k_expl.h b/lib/msun/ld128/k_expl.h index a5668fd47c58..e0a48fc2093f 100644 --- a/lib/msun/ld128/k_expl.h +++ b/lib/msun/ld128/k_expl.h @@ -322,7 +322,7 @@ __ldexp_cexpl(long double complex z, int expt) scale2 = 1; SET_LDBL_EXPSIGN(scale1, BIAS + expt - half_expt); - return (cpackl(cos(y) * exp_x * scale1 * scale2, + return (CMPLXL(cos(y) * exp_x * scale1 * scale2, sinl(y) * exp_x * scale1 * scale2)); } #endif /* _COMPLEX_H */ diff --git a/lib/msun/ld80/k_expl.h b/lib/msun/ld80/k_expl.h index ebfb9a8749d4..9b081faf0331 100644 --- a/lib/msun/ld80/k_expl.h +++ b/lib/msun/ld80/k_expl.h @@ -299,7 +299,7 @@ __ldexp_cexpl(long double complex z, int expt) scale2 = 1; SET_LDBL_EXPSIGN(scale1, BIAS + expt - half_expt); - return (cpackl(cos(y) * exp_x * scale1 * scale2, + return (CMPLXL(cos(y) * exp_x * scale1 * scale2, sinl(y) * exp_x * scale1 * scale2)); } #endif /* _COMPLEX_H */ diff --git a/lib/msun/src/catrig.c b/lib/msun/src/catrig.c index 200977c0af48..c0f5f55079f5 100644 --- a/lib/msun/src/catrig.c +++ b/lib/msun/src/catrig.c @@ -286,19 +286,19 @@ casinh(double complex z) if (isnan(x) || isnan(y)) { /* casinh(+-Inf + I*NaN) = +-Inf + I*NaN */ if (isinf(x)) - return (cpack(x, y + y)); + return (CMPLX(x, y + y)); /* casinh(NaN + I*+-Inf) = opt(+-)Inf + I*NaN */ if (isinf(y)) - return (cpack(y, x + x)); + return (CMPLX(y, x + x)); /* casinh(NaN + I*0) = NaN + I*0 */ if (y == 0) - return (cpack(x + x, y)); + return (CMPLX(x + x, y)); /* * All other cases involving NaN return NaN + I*NaN. * C99 leaves it optional whether to raise invalid if one of * the arguments is not NaN, so we opt not to raise it. */ - return (cpack(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); + return (CMPLX(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { @@ -307,7 +307,7 @@ casinh(double complex z) w = clog_for_large_values(z) + m_ln2; else w = clog_for_large_values(-z) + m_ln2; - return (cpack(copysign(creal(w), x), copysign(cimag(w), y))); + return (CMPLX(copysign(creal(w), x), copysign(cimag(w), y))); } /* Avoid spuriously raising inexact for z = 0. */ @@ -325,7 +325,7 @@ casinh(double complex z) ry = asin(B); else ry = atan2(new_y, sqrt_A2my2); - return (cpack(copysign(rx, x), copysign(ry, y))); + return (CMPLX(copysign(rx, x), copysign(ry, y))); } /* @@ -335,9 +335,9 @@ casinh(double complex z) double complex casin(double complex z) { - double complex w = casinh(cpack(cimag(z), creal(z))); + double complex w = casinh(CMPLX(cimag(z), creal(z))); - return (cpack(cimag(w), creal(w))); + return (CMPLX(cimag(w), creal(w))); } /* @@ -370,19 +370,19 @@ cacos(double complex z) if (isnan(x) || isnan(y)) { /* cacos(+-Inf + I*NaN) = NaN + I*opt(-)Inf */ if (isinf(x)) - return (cpack(y + y, -INFINITY)); + return (CMPLX(y + y, -INFINITY)); /* cacos(NaN + I*+-Inf) = NaN + I*-+Inf */ if (isinf(y)) - return (cpack(x + x, -y)); + return (CMPLX(x + x, -y)); /* cacos(0 + I*NaN) = PI/2 + I*NaN with inexact */ if (x == 0) - return (cpack(pio2_hi + pio2_lo, y + y)); + return (CMPLX(pio2_hi + pio2_lo, y + y)); /* * All other cases involving NaN return NaN + I*NaN. * C99 leaves it optional whether to raise invalid if one of * the arguments is not NaN, so we opt not to raise it. */ - return (cpack(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); + return (CMPLX(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { @@ -392,18 +392,18 @@ cacos(double complex z) ry = creal(w) + m_ln2; if (sy == 0) ry = -ry; - return (cpack(rx, ry)); + return (CMPLX(rx, ry)); } /* Avoid spuriously raising inexact for z = 1. */ if (x == 1 && y == 0) - return (cpack(0, -y)); + return (CMPLX(0, -y)); /* All remaining cases are inexact. */ raise_inexact(); if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) - return (cpack(pio2_hi - (x - pio2_lo), -y)); + return (CMPLX(pio2_hi - (x - pio2_lo), -y)); do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x); if (B_is_usable) { @@ -419,7 +419,7 @@ cacos(double complex z) } if (sy == 0) ry = -ry; - return (cpack(rx, ry)); + return (CMPLX(rx, ry)); } /* @@ -437,15 +437,15 @@ cacosh(double complex z) ry = cimag(w); /* cacosh(NaN + I*NaN) = NaN + I*NaN */ if (isnan(rx) && isnan(ry)) - return (cpack(ry, rx)); + return (CMPLX(ry, rx)); /* cacosh(NaN + I*+-Inf) = +Inf + I*NaN */ /* cacosh(+-Inf + I*NaN) = +Inf + I*NaN */ if (isnan(rx)) - return (cpack(fabs(ry), rx)); + return (CMPLX(fabs(ry), rx)); /* cacosh(0 + I*NaN) = NaN + I*NaN */ if (isnan(ry)) - return (cpack(ry, ry)); - return (cpack(fabs(ry), copysign(rx, cimag(z)))); + return (CMPLX(ry, ry)); + return (CMPLX(fabs(ry), copysign(rx, cimag(z)))); } /* @@ -475,16 +475,16 @@ clog_for_large_values(double complex z) * this method is still poor since it is uneccessarily slow. */ if (ax > DBL_MAX / 2) - return (cpack(log(hypot(x / m_e, y / m_e)) + 1, atan2(y, x))); + return (CMPLX(log(hypot(x / m_e, y / m_e)) + 1, atan2(y, x))); /* * Avoid overflow when x or y is large. Avoid underflow when x or * y is small. */ if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN) - return (cpack(log(hypot(x, y)), atan2(y, x))); + return (CMPLX(log(hypot(x, y)), atan2(y, x))); - return (cpack(log(ax * ax + ay * ay) / 2, atan2(y, x))); + return (CMPLX(log(ax * ax + ay * ay) / 2, atan2(y, x))); } /* @@ -575,30 +575,30 @@ catanh(double complex z) /* This helps handle many cases. */ if (y == 0 && ax <= 1) - return (cpack(atanh(x), y)); + return (CMPLX(atanh(x), y)); /* To ensure the same accuracy as atan(), and to filter out z = 0. */ if (x == 0) - return (cpack(x, atan(y))); + return (CMPLX(x, atan(y))); if (isnan(x) || isnan(y)) { /* catanh(+-Inf + I*NaN) = +-0 + I*NaN */ if (isinf(x)) - return (cpack(copysign(0, x), y + y)); + return (CMPLX(copysign(0, x), y + y)); /* catanh(NaN + I*+-Inf) = sign(NaN)0 + I*+-PI/2 */ if (isinf(y)) - return (cpack(copysign(0, x), + return (CMPLX(copysign(0, x), copysign(pio2_hi + pio2_lo, y))); /* * All other cases involving NaN return NaN + I*NaN. * C99 leaves it optional whether to raise invalid if one of * the arguments is not NaN, so we opt not to raise it. */ - return (cpack(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); + return (CMPLX(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) - return (cpack(real_part_reciprocal(x, y), + return (CMPLX(real_part_reciprocal(x, y), copysign(pio2_hi + pio2_lo, y))); if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) { @@ -623,7 +623,7 @@ catanh(double complex z) else ry = atan2(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2; - return (cpack(copysign(rx, x), copysign(ry, y))); + return (CMPLX(copysign(rx, x), copysign(ry, y))); } /* @@ -633,7 +633,7 @@ catanh(double complex z) double complex catan(double complex z) { - double complex w = catanh(cpack(cimag(z), creal(z))); + double complex w = catanh(CMPLX(cimag(z), creal(z))); - return (cpack(cimag(w), creal(w))); + return (CMPLX(cimag(w), creal(w))); } diff --git a/lib/msun/src/catrigf.c b/lib/msun/src/catrigf.c index 08ebef783666..ca84ce2a99a8 100644 --- a/lib/msun/src/catrigf.c +++ b/lib/msun/src/catrigf.c @@ -156,12 +156,12 @@ casinhf(float complex z) if (isnan(x) || isnan(y)) { if (isinf(x)) - return (cpackf(x, y + y)); + return (CMPLXF(x, y + y)); if (isinf(y)) - return (cpackf(y, x + x)); + return (CMPLXF(y, x + x)); if (y == 0) - return (cpackf(x + x, y)); - return (cpackf(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); + return (CMPLXF(x + x, y)); + return (CMPLXF(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { @@ -169,7 +169,7 @@ casinhf(float complex z) w = clog_for_large_values(z) + m_ln2; else w = clog_for_large_values(-z) + m_ln2; - return (cpackf(copysignf(crealf(w), x), + return (CMPLXF(copysignf(crealf(w), x), copysignf(cimagf(w), y))); } @@ -186,15 +186,15 @@ casinhf(float complex z) ry = asinf(B); else ry = atan2f(new_y, sqrt_A2my2); - return (cpackf(copysignf(rx, x), copysignf(ry, y))); + return (CMPLXF(copysignf(rx, x), copysignf(ry, y))); } float complex casinf(float complex z) { - float complex w = casinhf(cpackf(cimagf(z), crealf(z))); + float complex w = casinhf(CMPLXF(cimagf(z), crealf(z))); - return (cpackf(cimagf(w), crealf(w))); + return (CMPLXF(cimagf(w), crealf(w))); } float complex @@ -214,12 +214,12 @@ cacosf(float complex z) if (isnan(x) || isnan(y)) { if (isinf(x)) - return (cpackf(y + y, -INFINITY)); + return (CMPLXF(y + y, -INFINITY)); if (isinf(y)) - return (cpackf(x + x, -y)); + return (CMPLXF(x + x, -y)); if (x == 0) - return (cpackf(pio2_hi + pio2_lo, y + y)); - return (cpackf(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); + return (CMPLXF(pio2_hi + pio2_lo, y + y)); + return (CMPLXF(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) { @@ -228,16 +228,16 @@ cacosf(float complex z) ry = crealf(w) + m_ln2; if (sy == 0) ry = -ry; - return (cpackf(rx, ry)); + return (CMPLXF(rx, ry)); } if (x == 1 && y == 0) - return (cpackf(0, -y)); + return (CMPLXF(0, -y)); raise_inexact(); if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4) - return (cpackf(pio2_hi - (x - pio2_lo), -y)); + return (CMPLXF(pio2_hi - (x - pio2_lo), -y)); do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x); if (B_is_usable) { @@ -253,7 +253,7 @@ cacosf(float complex z) } if (sy == 0) ry = -ry; - return (cpackf(rx, ry)); + return (CMPLXF(rx, ry)); } float complex @@ -266,12 +266,12 @@ cacoshf(float complex z) rx = crealf(w); ry = cimagf(w); if (isnan(rx) && isnan(ry)) - return (cpackf(ry, rx)); + return (CMPLXF(ry, rx)); if (isnan(rx)) - return (cpackf(fabsf(ry), rx)); + return (CMPLXF(fabsf(ry), rx)); if (isnan(ry)) - return (cpackf(ry, ry)); - return (cpackf(fabsf(ry), copysignf(rx, cimagf(z)))); + return (CMPLXF(ry, ry)); + return (CMPLXF(fabsf(ry), copysignf(rx, cimagf(z)))); } static float complex @@ -291,13 +291,13 @@ clog_for_large_values(float complex z) } if (ax > FLT_MAX / 2) - return (cpackf(logf(hypotf(x / m_e, y / m_e)) + 1, + return (CMPLXF(logf(hypotf(x / m_e, y / m_e)) + 1, atan2f(y, x))); if (ax > QUARTER_SQRT_MAX || ay < SQRT_MIN) - return (cpackf(logf(hypotf(x, y)), atan2f(y, x))); + return (CMPLXF(logf(hypotf(x, y)), atan2f(y, x))); - return (cpackf(logf(ax * ax + ay * ay) / 2, atan2f(y, x))); + return (CMPLXF(logf(ax * ax + ay * ay) / 2, atan2f(y, x))); } static inline float @@ -346,22 +346,22 @@ catanhf(float complex z) ay = fabsf(y); if (y == 0 && ax <= 1) - return (cpackf(atanhf(x), y)); + return (CMPLXF(atanhf(x), y)); if (x == 0) - return (cpackf(x, atanf(y))); + return (CMPLXF(x, atanf(y))); if (isnan(x) || isnan(y)) { if (isinf(x)) - return (cpackf(copysignf(0, x), y + y)); + return (CMPLXF(copysignf(0, x), y + y)); if (isinf(y)) - return (cpackf(copysignf(0, x), + return (CMPLXF(copysignf(0, x), copysignf(pio2_hi + pio2_lo, y))); - return (cpackf(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); + return (CMPLXF(x + 0.0L + (y + 0), x + 0.0L + (y + 0))); } if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) - return (cpackf(real_part_reciprocal(x, y), + return (CMPLXF(real_part_reciprocal(x, y), copysignf(pio2_hi + pio2_lo, y))); if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) { @@ -381,13 +381,13 @@ catanhf(float complex z) else ry = atan2f(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2; - return (cpackf(copysignf(rx, x), copysignf(ry, y))); + return (CMPLXF(copysignf(rx, x), copysignf(ry, y))); } float complex catanf(float complex z) { - float complex w = catanhf(cpackf(cimagf(z), crealf(z))); + float complex w = catanhf(CMPLXF(cimagf(z), crealf(z))); - return (cpackf(cimagf(w), crealf(w))); + return (CMPLXF(cimagf(w), crealf(w))); } diff --git a/lib/msun/src/k_exp.c b/lib/msun/src/k_exp.c index f592f69aa009..ecef54c0f3c1 100644 --- a/lib/msun/src/k_exp.c +++ b/lib/msun/src/k_exp.c @@ -103,6 +103,6 @@ __ldexp_cexp(double complex z, int expt) half_expt = expt - half_expt; INSERT_WORDS(scale2, (0x3ff + half_expt) << 20, 0); - return (cpack(cos(y) * exp_x * scale1 * scale2, + return (CMPLX(cos(y) * exp_x * scale1 * scale2, sin(y) * exp_x * scale1 * scale2)); } diff --git a/lib/msun/src/k_expf.c b/lib/msun/src/k_expf.c index 548a008f86be..f8c254d1d5bb 100644 --- a/lib/msun/src/k_expf.c +++ b/lib/msun/src/k_expf.c @@ -82,6 +82,6 @@ __ldexp_cexpf(float complex z, int expt) half_expt = expt - half_expt; SET_FLOAT_WORD(scale2, (0x7f + half_expt) << 23); - return (cpackf(cosf(y) * exp_x * scale1 * scale2, + return (CMPLXF(cosf(y) * exp_x * scale1 * scale2, sinf(y) * exp_x * scale1 * scale2)); } diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h index 8af2c650e77e..083197e1b941 100644 --- a/lib/msun/src/math_private.h +++ b/lib/msun/src/math_private.h @@ -454,9 +454,16 @@ typedef union { * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product. * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted * to -0.0+I*0.0. + * + * The C11 standard introduced the macros CMPLX(), CMPLXF() and CMPLXL() + * to construct complex values. The functions below are modelled after + * these macros, with the exception that they cannot be used to + * construct compile-time complex values. */ + +#ifndef CMPLXF static __inline float complex -cpackf(float x, float y) +CMPLXF(float x, float y) { float_complex z; @@ -464,9 +471,11 @@ cpackf(float x, float y) IMAGPART(z) = y; return (z.f); } +#endif +#ifndef CMPLX static __inline double complex -cpack(double x, double y) +CMPLX(double x, double y) { double_complex z; @@ -474,9 +483,11 @@ cpack(double x, double y) IMAGPART(z) = y; return (z.f); } +#endif +#ifndef CMPLXL static __inline long double complex -cpackl(long double x, long double y) +CMPLXL(long double x, long double y) { long_double_complex z; @@ -484,6 +495,8 @@ cpackl(long double x, long double y) IMAGPART(z) = y; return (z.f); } +#endif + #endif /* _COMPLEX_H */ #ifdef __GNUCLIKE_ASM diff --git a/lib/msun/src/s_ccosh.c b/lib/msun/src/s_ccosh.c index 9ea962b4818f..fbe15fc9c873 100644 --- a/lib/msun/src/s_ccosh.c +++ b/lib/msun/src/s_ccosh.c @@ -62,23 +62,23 @@ ccosh(double complex z) /* Handle the nearly-non-exceptional cases where x and y are finite. */ if (ix < 0x7ff00000 && iy < 0x7ff00000) { if ((iy | ly) == 0) - return (cpack(cosh(x), x * y)); + return (CMPLX(cosh(x), x * y)); if (ix < 0x40360000) /* small x: normal case */ - return (cpack(cosh(x) * cos(y), sinh(x) * sin(y))); + return (CMPLX(cosh(x) * cos(y), sinh(x) * sin(y))); /* |x| >= 22, so cosh(x) ~= exp(|x|) */ if (ix < 0x40862e42) { /* x < 710: exp(|x|) won't overflow */ h = exp(fabs(x)) * 0.5; - return (cpack(h * cos(y), copysign(h, x) * sin(y))); + return (CMPLX(h * cos(y), copysign(h, x) * sin(y))); } else if (ix < 0x4096bbaa) { /* x < 1455: scale to avoid overflow */ - z = __ldexp_cexp(cpack(fabs(x), y), -1); - return (cpack(creal(z), cimag(z) * copysign(1, x))); + z = __ldexp_cexp(CMPLX(fabs(x), y), -1); + return (CMPLX(creal(z), cimag(z) * copysign(1, x))); } else { /* x >= 1455: the result always overflows */ h = huge * x; - return (cpack(h * h * cos(y), h * sin(y))); + return (CMPLX(h * h * cos(y), h * sin(y))); } } @@ -92,7 +92,7 @@ ccosh(double complex z) * the same as d(NaN). */ if ((ix | lx) == 0 && iy >= 0x7ff00000) - return (cpack(y - y, copysign(0, x * (y - y)))); + return (CMPLX(y - y, copysign(0, x * (y - y)))); /* * cosh(+-Inf +- I 0) = +Inf + I (+-)(+-)0. @@ -102,8 +102,8 @@ ccosh(double complex z) */ if ((iy | ly) == 0 && ix >= 0x7ff00000) { if (((hx & 0xfffff) | lx) == 0) - return (cpack(x * x, copysign(0, x) * y)); - return (cpack(x * x, copysign(0, (x + x) * y))); + return (CMPLX(x * x, copysign(0, x) * y)); + return (CMPLX(x * x, copysign(0, (x + x) * y))); } /* @@ -115,7 +115,7 @@ ccosh(double complex z) * nonzero x. Choice = don't raise (except for signaling NaNs). */ if (ix < 0x7ff00000 && iy >= 0x7ff00000) - return (cpack(y - y, x * (y - y))); + return (CMPLX(y - y, x * (y - y))); /* * cosh(+-Inf + I NaN) = +Inf + I d(NaN). @@ -128,8 +128,8 @@ ccosh(double complex z) */ if (ix >= 0x7ff00000 && ((hx & 0xfffff) | lx) == 0) { if (iy >= 0x7ff00000) - return (cpack(x * x, x * (y - y))); - return (cpack((x * x) * cos(y), x * sin(y))); + return (CMPLX(x * x, x * (y - y))); + return (CMPLX((x * x) * cos(y), x * sin(y))); } /* @@ -143,7 +143,7 @@ ccosh(double complex z) * Optionally raises the invalid floating-point exception for finite * nonzero y. Choice = don't raise (except for signaling NaNs). */ - return (cpack((x * x) * (y - y), (x + x) * (y - y))); + return (CMPLX((x * x) * (y - y), (x + x) * (y - y))); } double complex @@ -151,5 +151,5 @@ ccos(double complex z) { /* ccos(z) = ccosh(I * z) */ - return (ccosh(cpack(-cimag(z), creal(z)))); + return (ccosh(CMPLX(-cimag(z), creal(z)))); } diff --git a/lib/msun/src/s_ccoshf.c b/lib/msun/src/s_ccoshf.c index 1de9ad443772..fe8cf89c4159 100644 --- a/lib/msun/src/s_ccoshf.c +++ b/lib/msun/src/s_ccoshf.c @@ -55,50 +55,50 @@ ccoshf(float complex z) if (ix < 0x7f800000 && iy < 0x7f800000) { if (iy == 0) - return (cpackf(coshf(x), x * y)); + return (CMPLXF(coshf(x), x * y)); if (ix < 0x41100000) /* small x: normal case */ - return (cpackf(coshf(x) * cosf(y), sinhf(x) * sinf(y))); + return (CMPLXF(coshf(x) * cosf(y), sinhf(x) * sinf(y))); /* |x| >= 9, so cosh(x) ~= exp(|x|) */ if (ix < 0x42b17218) { /* x < 88.7: expf(|x|) won't overflow */ h = expf(fabsf(x)) * 0.5f; - return (cpackf(h * cosf(y), copysignf(h, x) * sinf(y))); + return (CMPLXF(h * cosf(y), copysignf(h, x) * sinf(y))); } else if (ix < 0x4340b1e7) { /* x < 192.7: scale to avoid overflow */ - z = __ldexp_cexpf(cpackf(fabsf(x), y), -1); - return (cpackf(crealf(z), cimagf(z) * copysignf(1, x))); + z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1); + return (CMPLXF(crealf(z), cimagf(z) * copysignf(1, x))); } else { /* x >= 192.7: the result always overflows */ h = huge * x; - return (cpackf(h * h * cosf(y), h * sinf(y))); + return (CMPLXF(h * h * cosf(y), h * sinf(y))); } } if (ix == 0 && iy >= 0x7f800000) - return (cpackf(y - y, copysignf(0, x * (y - y)))); + return (CMPLXF(y - y, copysignf(0, x * (y - y)))); if (iy == 0 && ix >= 0x7f800000) { if ((hx & 0x7fffff) == 0) - return (cpackf(x * x, copysignf(0, x) * y)); - return (cpackf(x * x, copysignf(0, (x + x) * y))); + return (CMPLXF(x * x, copysignf(0, x) * y)); + return (CMPLXF(x * x, copysignf(0, (x + x) * y))); } if (ix < 0x7f800000 && iy >= 0x7f800000) - return (cpackf(y - y, x * (y - y))); + return (CMPLXF(y - y, x * (y - y))); if (ix >= 0x7f800000 && (hx & 0x7fffff) == 0) { if (iy >= 0x7f800000) - return (cpackf(x * x, x * (y - y))); - return (cpackf((x * x) * cosf(y), x * sinf(y))); + return (CMPLXF(x * x, x * (y - y))); + return (CMPLXF((x * x) * cosf(y), x * sinf(y))); } - return (cpackf((x * x) * (y - y), (x + x) * (y - y))); + return (CMPLXF((x * x) * (y - y), (x + x) * (y - y))); } float complex ccosf(float complex z) { - return (ccoshf(cpackf(-cimagf(z), crealf(z)))); + return (ccoshf(CMPLXF(-cimagf(z), crealf(z)))); } diff --git a/lib/msun/src/s_cexp.c b/lib/msun/src/s_cexp.c index abe178f3169f..9e11d515a68f 100644 --- a/lib/msun/src/s_cexp.c +++ b/lib/msun/src/s_cexp.c @@ -50,22 +50,22 @@ cexp(double complex z) /* cexp(x + I 0) = exp(x) + I 0 */ if ((hy | ly) == 0) - return (cpack(exp(x), y)); + return (CMPLX(exp(x), y)); EXTRACT_WORDS(hx, lx, x); /* cexp(0 + I y) = cos(y) + I sin(y) */ if (((hx & 0x7fffffff) | lx) == 0) - return (cpack(cos(y), sin(y))); + return (CMPLX(cos(y), sin(y))); if (hy >= 0x7ff00000) { if (lx != 0 || (hx & 0x7fffffff) != 0x7ff00000) { /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ - return (cpack(y - y, y - y)); + return (CMPLX(y - y, y - y)); } else if (hx & 0x80000000) { /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ - return (cpack(0.0, 0.0)); + return (CMPLX(0.0, 0.0)); } else { /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ - return (cpack(x, y - y)); + return (CMPLX(x, y - y)); } } @@ -84,6 +84,6 @@ cexp(double complex z) * - x = NaN (spurious inexact exception from y) */ exp_x = exp(x); - return (cpack(exp_x * cos(y), exp_x * sin(y))); + return (CMPLX(exp_x * cos(y), exp_x * sin(y))); } } diff --git a/lib/msun/src/s_cexpf.c b/lib/msun/src/s_cexpf.c index 0e30d08c80db..0138cd1e83fb 100644 --- a/lib/msun/src/s_cexpf.c +++ b/lib/msun/src/s_cexpf.c @@ -50,22 +50,22 @@ cexpf(float complex z) /* cexp(x + I 0) = exp(x) + I 0 */ if (hy == 0) - return (cpackf(expf(x), y)); + return (CMPLXF(expf(x), y)); GET_FLOAT_WORD(hx, x); /* cexp(0 + I y) = cos(y) + I sin(y) */ if ((hx & 0x7fffffff) == 0) - return (cpackf(cosf(y), sinf(y))); + return (CMPLXF(cosf(y), sinf(y))); if (hy >= 0x7f800000) { if ((hx & 0x7fffffff) != 0x7f800000) { /* cexp(finite|NaN +- I Inf|NaN) = NaN + I NaN */ - return (cpackf(y - y, y - y)); + return (CMPLXF(y - y, y - y)); } else if (hx & 0x80000000) { /* cexp(-Inf +- I Inf|NaN) = 0 + I 0 */ - return (cpackf(0.0, 0.0)); + return (CMPLXF(0.0, 0.0)); } else { /* cexp(+Inf +- I Inf|NaN) = Inf + I NaN */ - return (cpackf(x, y - y)); + return (CMPLXF(x, y - y)); } } @@ -84,6 +84,6 @@ cexpf(float complex z) * - x = NaN (spurious inexact exception from y) */ exp_x = expf(x); - return (cpackf(exp_x * cosf(y), exp_x * sinf(y))); + return (CMPLXF(exp_x * cosf(y), exp_x * sinf(y))); } } diff --git a/lib/msun/src/s_conj.c b/lib/msun/src/s_conj.c index 5770c29462ef..d0dd05133f29 100644 --- a/lib/msun/src/s_conj.c +++ b/lib/msun/src/s_conj.c @@ -34,5 +34,5 @@ double complex conj(double complex z) { - return (cpack(creal(z), -cimag(z))); + return (CMPLX(creal(z), -cimag(z))); } diff --git a/lib/msun/src/s_conjf.c b/lib/msun/src/s_conjf.c index b09076039cc6..c4cf127f8c22 100644 --- a/lib/msun/src/s_conjf.c +++ b/lib/msun/src/s_conjf.c @@ -34,5 +34,5 @@ float complex conjf(float complex z) { - return (cpackf(crealf(z), -cimagf(z))); + return (CMPLXF(crealf(z), -cimagf(z))); } diff --git a/lib/msun/src/s_conjl.c b/lib/msun/src/s_conjl.c index 0e431efa01a0..a4604b6fd166 100644 --- a/lib/msun/src/s_conjl.c +++ b/lib/msun/src/s_conjl.c @@ -34,5 +34,5 @@ long double complex conjl(long double complex z) { - return (cpackl(creall(z), -cimagl(z))); + return (CMPLXL(creall(z), -cimagl(z))); } diff --git a/lib/msun/src/s_cproj.c b/lib/msun/src/s_cproj.c index 8e9404c297dd..2f0db6e6151e 100644 --- a/lib/msun/src/s_cproj.c +++ b/lib/msun/src/s_cproj.c @@ -39,7 +39,7 @@ cproj(double complex z) if (!isinf(creal(z)) && !isinf(cimag(z))) return (z); else - return (cpack(INFINITY, copysign(0.0, cimag(z)))); + return (CMPLX(INFINITY, copysign(0.0, cimag(z)))); } #if LDBL_MANT_DIG == 53 diff --git a/lib/msun/src/s_cprojf.c b/lib/msun/src/s_cprojf.c index 68ea77b80d8e..bd27bdcb0b51 100644 --- a/lib/msun/src/s_cprojf.c +++ b/lib/msun/src/s_cprojf.c @@ -39,5 +39,5 @@ cprojf(float complex z) if (!isinf(crealf(z)) && !isinf(cimagf(z))) return (z); else - return (cpackf(INFINITY, copysignf(0.0, cimagf(z)))); + return (CMPLXF(INFINITY, copysignf(0.0, cimagf(z)))); } diff --git a/lib/msun/src/s_cprojl.c b/lib/msun/src/s_cprojl.c index 07385bcc6261..5cccc9170811 100644 --- a/lib/msun/src/s_cprojl.c +++ b/lib/msun/src/s_cprojl.c @@ -39,5 +39,5 @@ cprojl(long double complex z) if (!isinf(creall(z)) && !isinf(cimagl(z))) return (z); else - return (cpackl(INFINITY, copysignl(0.0, cimagl(z)))); + return (CMPLXL(INFINITY, copysignl(0.0, cimagl(z)))); } diff --git a/lib/msun/src/s_csinh.c b/lib/msun/src/s_csinh.c index c192f30308e0..37f46da226dd 100644 --- a/lib/msun/src/s_csinh.c +++ b/lib/msun/src/s_csinh.c @@ -62,23 +62,23 @@ csinh(double complex z) /* Handle the nearly-non-exceptional cases where x and y are finite. */ if (ix < 0x7ff00000 && iy < 0x7ff00000) { if ((iy | ly) == 0) - return (cpack(sinh(x), y)); + return (CMPLX(sinh(x), y)); if (ix < 0x40360000) /* small x: normal case */ - return (cpack(sinh(x) * cos(y), cosh(x) * sin(y))); + return (CMPLX(sinh(x) * cos(y), cosh(x) * sin(y))); /* |x| >= 22, so cosh(x) ~= exp(|x|) */ if (ix < 0x40862e42) { /* x < 710: exp(|x|) won't overflow */ h = exp(fabs(x)) * 0.5; - return (cpack(copysign(h, x) * cos(y), h * sin(y))); + return (CMPLX(copysign(h, x) * cos(y), h * sin(y))); } else if (ix < 0x4096bbaa) { /* x < 1455: scale to avoid overflow */ - z = __ldexp_cexp(cpack(fabs(x), y), -1); - return (cpack(creal(z) * copysign(1, x), cimag(z))); + z = __ldexp_cexp(CMPLX(fabs(x), y), -1); + return (CMPLX(creal(z) * copysign(1, x), cimag(z))); } else { /* x >= 1455: the result always overflows */ h = huge * x; - return (cpack(h * cos(y), h * h * sin(y))); + return (CMPLX(h * cos(y), h * h * sin(y))); } } @@ -92,7 +92,7 @@ csinh(double complex z) * the same as d(NaN). */ if ((ix | lx) == 0 && iy >= 0x7ff00000) - return (cpack(copysign(0, x * (y - y)), y - y)); + return (CMPLX(copysign(0, x * (y - y)), y - y)); /* * sinh(+-Inf +- I 0) = +-Inf + I +-0. @@ -101,8 +101,8 @@ csinh(double complex z) */ if ((iy | ly) == 0 && ix >= 0x7ff00000) { if (((hx & 0xfffff) | lx) == 0) - return (cpack(x, y)); - return (cpack(x, copysign(0, y))); + return (CMPLX(x, y)); + return (CMPLX(x, copysign(0, y))); } /* @@ -114,7 +114,7 @@ csinh(double complex z) * nonzero x. Choice = don't raise (except for signaling NaNs). */ if (ix < 0x7ff00000 && iy >= 0x7ff00000) - return (cpack(y - y, x * (y - y))); + return (CMPLX(y - y, x * (y - y))); /* * sinh(+-Inf + I NaN) = +-Inf + I d(NaN). @@ -129,8 +129,8 @@ csinh(double complex z) */ if (ix >= 0x7ff00000 && ((hx & 0xfffff) | lx) == 0) { if (iy >= 0x7ff00000) - return (cpack(x * x, x * (y - y))); - return (cpack(x * cos(y), INFINITY * sin(y))); + return (CMPLX(x * x, x * (y - y))); + return (CMPLX(x * cos(y), INFINITY * sin(y))); } /* @@ -144,7 +144,7 @@ csinh(double complex z) * Optionally raises the invalid floating-point exception for finite * nonzero y. Choice = don't raise (except for signaling NaNs). */ - return (cpack((x * x) * (y - y), (x + x) * (y - y))); + return (CMPLX((x * x) * (y - y), (x + x) * (y - y))); } double complex @@ -152,6 +152,6 @@ csin(double complex z) { /* csin(z) = -I * csinh(I * z) */ - z = csinh(cpack(-cimag(z), creal(z))); - return (cpack(cimag(z), -creal(z))); + z = csinh(CMPLX(-cimag(z), creal(z))); + return (CMPLX(cimag(z), -creal(z))); } diff --git a/lib/msun/src/s_csinhf.c b/lib/msun/src/s_csinhf.c index c5231251fade..63482723ad9e 100644 --- a/lib/msun/src/s_csinhf.c +++ b/lib/msun/src/s_csinhf.c @@ -55,51 +55,51 @@ csinhf(float complex z) if (ix < 0x7f800000 && iy < 0x7f800000) { if (iy == 0) - return (cpackf(sinhf(x), y)); + return (CMPLXF(sinhf(x), y)); if (ix < 0x41100000) /* small x: normal case */ - return (cpackf(sinhf(x) * cosf(y), coshf(x) * sinf(y))); + return (CMPLXF(sinhf(x) * cosf(y), coshf(x) * sinf(y))); /* |x| >= 9, so cosh(x) ~= exp(|x|) */ if (ix < 0x42b17218) { /* x < 88.7: expf(|x|) won't overflow */ h = expf(fabsf(x)) * 0.5f; - return (cpackf(copysignf(h, x) * cosf(y), h * sinf(y))); + return (CMPLXF(copysignf(h, x) * cosf(y), h * sinf(y))); } else if (ix < 0x4340b1e7) { /* x < 192.7: scale to avoid overflow */ - z = __ldexp_cexpf(cpackf(fabsf(x), y), -1); - return (cpackf(crealf(z) * copysignf(1, x), cimagf(z))); + z = __ldexp_cexpf(CMPLXF(fabsf(x), y), -1); + return (CMPLXF(crealf(z) * copysignf(1, x), cimagf(z))); } else { /* x >= 192.7: the result always overflows */ h = huge * x; - return (cpackf(h * cosf(y), h * h * sinf(y))); + return (CMPLXF(h * cosf(y), h * h * sinf(y))); } } if (ix == 0 && iy >= 0x7f800000) - return (cpackf(copysignf(0, x * (y - y)), y - y)); + return (CMPLXF(copysignf(0, x * (y - y)), y - y)); if (iy == 0 && ix >= 0x7f800000) { if ((hx & 0x7fffff) == 0) - return (cpackf(x, y)); - return (cpackf(x, copysignf(0, y))); + return (CMPLXF(x, y)); + return (CMPLXF(x, copysignf(0, y))); } if (ix < 0x7f800000 && iy >= 0x7f800000) - return (cpackf(y - y, x * (y - y))); + return (CMPLXF(y - y, x * (y - y))); if (ix >= 0x7f800000 && (hx & 0x7fffff) == 0) { if (iy >= 0x7f800000) - return (cpackf(x * x, x * (y - y))); - return (cpackf(x * cosf(y), INFINITY * sinf(y))); + return (CMPLXF(x * x, x * (y - y))); + return (CMPLXF(x * cosf(y), INFINITY * sinf(y))); } - return (cpackf((x * x) * (y - y), (x + x) * (y - y))); + return (CMPLXF((x * x) * (y - y), (x + x) * (y - y))); } float complex csinf(float complex z) { - z = csinhf(cpackf(-cimagf(z), crealf(z))); - return (cpackf(cimagf(z), -crealf(z))); + z = csinhf(CMPLXF(-cimagf(z), crealf(z))); + return (CMPLXF(cimagf(z), -crealf(z))); } diff --git a/lib/msun/src/s_csqrt.c b/lib/msun/src/s_csqrt.c index 18a7ae3e7146..75e12d8a4940 100644 --- a/lib/msun/src/s_csqrt.c +++ b/lib/msun/src/s_csqrt.c @@ -58,12 +58,12 @@ csqrt(double complex z) /* Handle special cases. */ if (z == 0) - return (cpack(0, b)); + return (CMPLX(0, b)); if (isinf(b)) - return (cpack(INFINITY, b)); + return (CMPLX(INFINITY, b)); if (isnan(a)) { t = (b - b) / (b - b); /* raise invalid if b is not a NaN */ - return (cpack(a, t)); /* return NaN + NaN i */ + return (CMPLX(a, t)); /* return NaN + NaN i */ } if (isinf(a)) { /* @@ -73,9 +73,9 @@ csqrt(double complex z) * csqrt(-inf + y i) = 0 + inf i */ if (signbit(a)) - return (cpack(fabs(b - b), copysign(a, b))); + return (CMPLX(fabs(b - b), copysign(a, b))); else - return (cpack(a, copysign(b - b, b))); + return (CMPLX(a, copysign(b - b, b))); } /* * The remaining special case (b is NaN) is handled just fine by @@ -94,10 +94,10 @@ csqrt(double complex z) /* Algorithm 312, CACM vol 10, Oct 1967. */ if (a >= 0) { t = sqrt((a + hypot(a, b)) * 0.5); - result = cpack(t, b / (2 * t)); + result = CMPLX(t, b / (2 * t)); } else { t = sqrt((-a + hypot(a, b)) * 0.5); - result = cpack(fabs(b) / (2 * t), copysign(t, b)); + result = CMPLX(fabs(b) / (2 * t), copysign(t, b)); } /* Rescale. */ diff --git a/lib/msun/src/s_csqrtf.c b/lib/msun/src/s_csqrtf.c index da7fe1847094..7ee513f2d760 100644 --- a/lib/msun/src/s_csqrtf.c +++ b/lib/msun/src/s_csqrtf.c @@ -49,12 +49,12 @@ csqrtf(float complex z) /* Handle special cases. */ if (z == 0) - return (cpackf(0, b)); + return (CMPLXF(0, b)); if (isinf(b)) - return (cpackf(INFINITY, b)); + return (CMPLXF(INFINITY, b)); if (isnan(a)) { t = (b - b) / (b - b); /* raise invalid if b is not a NaN */ - return (cpackf(a, t)); /* return NaN + NaN i */ + return (CMPLXF(a, t)); /* return NaN + NaN i */ } if (isinf(a)) { /* @@ -64,9 +64,9 @@ csqrtf(float complex z) * csqrtf(-inf + y i) = 0 + inf i */ if (signbit(a)) - return (cpackf(fabsf(b - b), copysignf(a, b))); + return (CMPLXF(fabsf(b - b), copysignf(a, b))); else - return (cpackf(a, copysignf(b - b, b))); + return (CMPLXF(a, copysignf(b - b, b))); } /* * The remaining special case (b is NaN) is handled just fine by @@ -80,9 +80,9 @@ csqrtf(float complex z) */ if (a >= 0) { t = sqrt((a + hypot(a, b)) * 0.5); - return (cpackf(t, b / (2.0 * t))); + return (CMPLXF(t, b / (2.0 * t))); } else { t = sqrt((-a + hypot(a, b)) * 0.5); - return (cpackf(fabsf(b) / (2.0 * t), copysignf(t, b))); + return (CMPLXF(fabsf(b) / (2.0 * t), copysignf(t, b))); } } diff --git a/lib/msun/src/s_csqrtl.c b/lib/msun/src/s_csqrtl.c index dd18e1ef38e8..ea2ef27b5088 100644 --- a/lib/msun/src/s_csqrtl.c +++ b/lib/msun/src/s_csqrtl.c @@ -58,12 +58,12 @@ csqrtl(long double complex z) /* Handle special cases. */ if (z == 0) - return (cpackl(0, b)); + return (CMPLXL(0, b)); if (isinf(b)) - return (cpackl(INFINITY, b)); + return (CMPLXL(INFINITY, b)); if (isnan(a)) { t = (b - b) / (b - b); /* raise invalid if b is not a NaN */ - return (cpackl(a, t)); /* return NaN + NaN i */ + return (CMPLXL(a, t)); /* return NaN + NaN i */ } if (isinf(a)) { /* @@ -73,9 +73,9 @@ csqrtl(long double complex z) * csqrt(-inf + y i) = 0 + inf i */ if (signbit(a)) - return (cpackl(fabsl(b - b), copysignl(a, b))); + return (CMPLXL(fabsl(b - b), copysignl(a, b))); else - return (cpackl(a, copysignl(b - b, b))); + return (CMPLXL(a, copysignl(b - b, b))); } /* * The remaining special case (b is NaN) is handled just fine by @@ -94,10 +94,10 @@ csqrtl(long double complex z) /* Algorithm 312, CACM vol 10, Oct 1967. */ if (a >= 0) { t = sqrtl((a + hypotl(a, b)) * 0.5); - result = cpackl(t, b / (2 * t)); + result = CMPLXL(t, b / (2 * t)); } else { t = sqrtl((-a + hypotl(a, b)) * 0.5); - result = cpackl(fabsl(b) / (2 * t), copysignl(t, b)); + result = CMPLXL(fabsl(b) / (2 * t), copysignl(t, b)); } /* Rescale. */ diff --git a/lib/msun/src/s_ctanh.c b/lib/msun/src/s_ctanh.c index d427e28d7281..b15c81469544 100644 --- a/lib/msun/src/s_ctanh.c +++ b/lib/msun/src/s_ctanh.c @@ -102,9 +102,9 @@ ctanh(double complex z) */ if (ix >= 0x7ff00000) { if ((ix & 0xfffff) | lx) /* x is NaN */ - return (cpack(x, (y == 0 ? y : x * y))); + return (CMPLX(x, (y == 0 ? y : x * y))); SET_HIGH_WORD(x, hx - 0x40000000); /* x = copysign(1, x) */ - return (cpack(x, copysign(0, isinf(y) ? y : sin(y) * cos(y)))); + return (CMPLX(x, copysign(0, isinf(y) ? y : sin(y) * cos(y)))); } /* @@ -112,7 +112,7 @@ ctanh(double complex z) * ctanh(x +- i Inf) = NaN + i NaN */ if (!isfinite(y)) - return (cpack(y - y, y - y)); + return (CMPLX(y - y, y - y)); /* * ctanh(+-huge + i +-y) ~= +-1 +- i 2sin(2y)/exp(2x), using the @@ -121,7 +121,7 @@ ctanh(double complex z) */ if (ix >= 0x40360000) { /* x >= 22 */ double exp_mx = exp(-fabs(x)); - return (cpack(copysign(1, x), + return (CMPLX(copysign(1, x), 4 * sin(y) * cos(y) * exp_mx * exp_mx)); } @@ -131,7 +131,7 @@ ctanh(double complex z) s = sinh(x); rho = sqrt(1 + s * s); /* = cosh(x) */ denom = 1 + beta * s * s; - return (cpack((beta * rho * s) / denom, t / denom)); + return (CMPLX((beta * rho * s) / denom, t / denom)); } double complex @@ -139,6 +139,6 @@ ctan(double complex z) { /* ctan(z) = -I * ctanh(I * z) */ - z = ctanh(cpack(-cimag(z), creal(z))); - return (cpack(cimag(z), -creal(z))); + z = ctanh(CMPLX(-cimag(z), creal(z))); + return (CMPLX(cimag(z), -creal(z))); } diff --git a/lib/msun/src/s_ctanhf.c b/lib/msun/src/s_ctanhf.c index 4be28d8526d1..9b0cda1600fa 100644 --- a/lib/msun/src/s_ctanhf.c +++ b/lib/msun/src/s_ctanhf.c @@ -51,18 +51,18 @@ ctanhf(float complex z) if (ix >= 0x7f800000) { if (ix & 0x7fffff) - return (cpackf(x, (y == 0 ? y : x * y))); + return (CMPLXF(x, (y == 0 ? y : x * y))); SET_FLOAT_WORD(x, hx - 0x40000000); - return (cpackf(x, + return (CMPLXF(x, copysignf(0, isinf(y) ? y : sinf(y) * cosf(y)))); } if (!isfinite(y)) - return (cpackf(y - y, y - y)); + return (CMPLXF(y - y, y - y)); if (ix >= 0x41300000) { /* x >= 11 */ float exp_mx = expf(-fabsf(x)); - return (cpackf(copysignf(1, x), + return (CMPLXF(copysignf(1, x), 4 * sinf(y) * cosf(y) * exp_mx * exp_mx)); } @@ -71,14 +71,14 @@ ctanhf(float complex z) s = sinhf(x); rho = sqrtf(1 + s * s); denom = 1 + beta * s * s; - return (cpackf((beta * rho * s) / denom, t / denom)); + return (CMPLXF((beta * rho * s) / denom, t / denom)); } float complex ctanf(float complex z) { - z = ctanhf(cpackf(-cimagf(z), crealf(z))); - return (cpackf(cimagf(z), -crealf(z))); + z = ctanhf(CMPLXF(-cimagf(z), crealf(z))); + return (CMPLXF(cimagf(z), -crealf(z))); } diff --git a/sbin/ffsinfo/ffsinfo.c b/sbin/ffsinfo/ffsinfo.c index 881fc1e1e1d3..c1e7c87c1b47 100644 --- a/sbin/ffsinfo/ffsinfo.c +++ b/sbin/ffsinfo/ffsinfo.c @@ -67,6 +67,7 @@ static const char rcsid[] = #include #include #include +#include #include #include #include @@ -361,7 +362,7 @@ dump_whole_ufs1_inode(ino_t inode, int level) /* * Dump the main inode structure. */ - snprintf(comment, sizeof(comment), "Inode 0x%08x", inode); + snprintf(comment, sizeof(comment), "Inode 0x%08jx", (uintmax_t)inode); if (level & 0x100) { DBG_DUMP_INO(&sblock, comment, @@ -385,8 +386,8 @@ dump_whole_ufs1_inode(ino_t inode, int level) (size_t)sblock.fs_bsize) == -1) { err(1, "bread: %s", disk.d_error); } - snprintf(comment, sizeof(comment), "Inode 0x%08x: indirect 0", - inode); + snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 0", + (uintmax_t)inode); DBG_DUMP_IBLK(&sblock, comment, i1blk, @@ -401,8 +402,8 @@ dump_whole_ufs1_inode(ino_t inode, int level) (size_t)sblock.fs_bsize) == -1) { err(1, "bread: %s", disk.d_error); } - snprintf(comment, sizeof(comment), "Inode 0x%08x: indirect 1", - inode); + snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 1", + (uintmax_t)inode); DBG_DUMP_IBLK(&sblock, comment, i2blk, @@ -416,7 +417,8 @@ dump_whole_ufs1_inode(ino_t inode, int level) err(1, "bread: %s", disk.d_error); } snprintf(comment, sizeof(comment), - "Inode 0x%08x: indirect 1->%d", inode, ind2ctr); + "Inode 0x%08jx: indirect 1->%d", (uintmax_t)inode, + ind2ctr); DBG_DUMP_IBLK(&sblock, comment, i1blk, @@ -432,8 +434,8 @@ dump_whole_ufs1_inode(ino_t inode, int level) (size_t)sblock.fs_bsize) == -1) { err(1, "bread: %s", disk.d_error); } - snprintf(comment, sizeof(comment), "Inode 0x%08x: indirect 2", - inode); + snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2", + (uintmax_t)inode); #define SQUARE(a) ((a)*(a)) DBG_DUMP_IBLK(&sblock, comment, @@ -450,7 +452,8 @@ dump_whole_ufs1_inode(ino_t inode, int level) err(1, "bread: %s", disk.d_error); } snprintf(comment, sizeof(comment), - "Inode 0x%08x: indirect 2->%d", inode, ind3ctr); + "Inode 0x%08jx: indirect 2->%d", (uintmax_t)inode, + ind3ctr); DBG_DUMP_IBLK(&sblock, comment, i2blk, @@ -466,8 +469,8 @@ dump_whole_ufs1_inode(ino_t inode, int level) err(1, "bread: %s", disk.d_error); } snprintf(comment, sizeof(comment), - "Inode 0x%08x: indirect 2->%d->%d", inode, - ind3ctr, ind3ctr); + "Inode 0x%08jx: indirect 2->%d->%d", + (uintmax_t)inode, ind3ctr, ind3ctr); DBG_DUMP_IBLK(&sblock, comment, i1blk, @@ -513,7 +516,7 @@ dump_whole_ufs2_inode(ino_t inode, int level) /* * Dump the main inode structure. */ - snprintf(comment, sizeof(comment), "Inode 0x%08x", inode); + snprintf(comment, sizeof(comment), "Inode 0x%08jx", (uintmax_t)inode); if (level & 0x100) { DBG_DUMP_INO(&sblock, comment, ino); } @@ -535,7 +538,8 @@ dump_whole_ufs2_inode(ino_t inode, int level) (size_t)sblock.fs_bsize) == -1) { err(1, "bread: %s", disk.d_error); } - snprintf(comment, sizeof(comment), "Inode 0x%08x: indirect 0", inode); + snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 0", + (uintmax_t)inode); DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); rb -= howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t)); } @@ -547,7 +551,8 @@ dump_whole_ufs2_inode(ino_t inode, int level) (size_t)sblock.fs_bsize) == -1) { err(1, "bread: %s", disk.d_error); } - snprintf(comment, sizeof(comment), "Inode 0x%08x: indirect 1", inode); + snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 1", + (uintmax_t)inode); DBG_DUMP_IBLK(&sblock, comment, i2blk, @@ -561,7 +566,8 @@ dump_whole_ufs2_inode(ino_t inode, int level) err(1, "bread: %s", disk.d_error); } snprintf(comment, sizeof(comment), - "Inode 0x%08x: indirect 1->%d", inode, ind2ctr); + "Inode 0x%08jx: indirect 1->%d", + (uintmax_t)inode, ind2ctr); DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); rb -= howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t)); } @@ -574,7 +580,8 @@ dump_whole_ufs2_inode(ino_t inode, int level) (size_t)sblock.fs_bsize) == -1) { err(1, "bread: %s", disk.d_error); } - snprintf(comment, sizeof(comment), "Inode 0x%08x: indirect 2", inode); + snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2", + (uintmax_t)inode); #define SQUARE(a) ((a)*(a)) DBG_DUMP_IBLK(&sblock, comment, @@ -591,7 +598,8 @@ dump_whole_ufs2_inode(ino_t inode, int level) err(1, "bread: %s", disk.d_error); } snprintf(comment, sizeof(comment), - "Inode 0x%08x: indirect 2->%d", inode, ind3ctr); + "Inode 0x%08jx: indirect 2->%d", + (uintmax_t)inode, ind3ctr); DBG_DUMP_IBLK(&sblock, comment, i2blk, @@ -605,8 +613,8 @@ dump_whole_ufs2_inode(ino_t inode, int level) err(1, "bread: %s", disk.d_error); } snprintf(comment, sizeof(comment), - "Inode 0x%08x: indirect 2->%d->%d", inode, - ind3ctr, ind3ctr); + "Inode 0x%08jx: indirect 2->%d->%d", + (uintmax_t)inode, ind3ctr, ind3ctr); DBG_DUMP_IBLK(&sblock, comment, i1blk, (size_t)rb); rb -= howmany(sblock.fs_bsize, sizeof(ufs2_daddr_t)); } diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile index 572c0613904c..885f8a9922bd 100644 --- a/sbin/ifconfig/Makefile +++ b/sbin/ifconfig/Makefile @@ -30,7 +30,7 @@ SRCS+= ifmac.c # MAC support SRCS+= ifmedia.c # SIOC[GS]IFMEDIA support SRCS+= iffib.c # non-default FIB support SRCS+= ifvlan.c # SIOC[GS]ETVLAN support -#SRCS+= ifvxlan.c # VXLAN support +SRCS+= ifvxlan.c # VXLAN support SRCS+= ifgre.c # GRE keys etc SRCS+= ifgif.c # GIF reversed header workaround diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 064a62d27b8d..90c8d7a8c1d0 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -28,7 +28,7 @@ .\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 .\" $FreeBSD$ .\" -.Dd October 20, 2014 +.Dd December 16, 2014 .Dt IFCONFIG 8 .Os .Sh NAME @@ -2544,33 +2544,33 @@ The following parameters are used to configure .Xr vxlan 4 interfaces. .Bl -tag -width indent -.It Cm vni Ar identifier +.It Cm vxlanid Ar identifier This value is a 24-bit VXLAN Network Identifier (VNI) that identifies the virtual network segment membership of the interface. -.It Cm local Ar address +.It Cm vxlanlocal Ar address The source address used in the encapsulating IPv4/IPv6 header. The address should already be assigned to an existing interface. When the interface is configured in unicast mode, the listening socket is bound to this address. -.It Cm remote Ar address +.It Cm vxlanremote Ar address The interface can be configured in a unicast, or point-to-point, mode to create a tunnel between two hosts. This is the IP address of the remote end of the tunnel. -.It Cm group Ar address +.It Cm vxlangroup Ar address The interface can be configured in a multicast mode to create a virtual network of hosts. This is the IP multicast group address the interface will join. -.It Cm localport Ar port +.It Cm vxlanlocalport Ar port The port number the interface will listen on. The default port number is 4789. -.It Cm remoteport Ar port +.It Cm vxlanremoteport Ar port The destination port number used in the encapsulating IPv4/IPv6 header. The remote host should be listening on this port. The default port number is 4789. Note some other implementations, such as Linux, do not default to the IANA assigned port, but instead listen on port 8472. -.It Cm portrange Ar low high +.It Cm vxlanportrange Ar low high The range of source ports used in the encapsulating IPv4/IPv6 header. The port selected within the range is based on a hash of the inner frame. A range is useful to provide entropy within the outer IP header @@ -2581,32 +2581,32 @@ variables .Va net.inet.ip.portrange.first and .Va net.inet.ip.portrange.last -.It Cm timeout Ar timeout +.It Cm vxlantimeout Ar timeout The maximum time, in seconds, before an entry in the forwarding table is pruned. The default is 1200 seconds (20 minutes). -.It Cm maxaddr Ar max +.It Cm vxlanmaxaddr Ar max The maximum number of entries in the forwarding table. The default is 2000. .It Cm vxlandev Ar dev When the interface is configured in multicast mode, the .Cm dev interface is used to transmit IP multicast packets. -.It Cm ttl Ar ttl +.It Cm vxlanttl Ar ttl The TTL used in the encapsulating IPv4/IPv6 header. The default is 64. -.It Cm learn +.It Cm vxlanlearn The source IP address and inner source Ethernet MAC address of received packets are used to dynamically populate the forwarding table. When in multicast mode, an entry in the forwarding table allows the interface to send the frame directly to the remote host instead of broadcasting the frame to the multicast group. This is the default. -.It Fl learn +.It Fl vxlanlearn The forwarding table is not populated by recevied packets. -.It Cm flush +.It Cm vxlanflush Delete all dynamically-learned addresses from the forwarding table. -.It Cm flushall +.It Cm vxlanflushall Delete all addresses, including static addresses, from the forwarding table. .El .Pp diff --git a/sbin/ifconfig/ifvxlan.c b/sbin/ifconfig/ifvxlan.c index 72346675faae..9aa84a29ff2b 100644 --- a/sbin/ifconfig/ifvxlan.c +++ b/sbin/ifconfig/ifvxlan.c @@ -595,36 +595,36 @@ setvxlan_flush(const char *val, int d, int s, const struct afswtch *afp) static struct cmd vxlan_cmds[] = { - DEF_CLONE_CMD_ARG("vni", setvxlan_vni), - DEF_CLONE_CMD_ARG("local", setvxlan_local), - DEF_CLONE_CMD_ARG("remote", setvxlan_remote), - DEF_CLONE_CMD_ARG("group", setvxlan_group), - DEF_CLONE_CMD_ARG("localport", setvxlan_local_port), - DEF_CLONE_CMD_ARG("remoteport", setvxlan_remote_port), - DEF_CLONE_CMD_ARG2("portrange", setvxlan_port_range), - DEF_CLONE_CMD_ARG("timeout", setvxlan_timeout), - DEF_CLONE_CMD_ARG("maxaddr", setvxlan_maxaddr), + DEF_CLONE_CMD_ARG("vxlanid", setvxlan_vni), + DEF_CLONE_CMD_ARG("vxlanlocal", setvxlan_local), + DEF_CLONE_CMD_ARG("vxlanremote", setvxlan_remote), + DEF_CLONE_CMD_ARG("vxlangroup", setvxlan_group), + DEF_CLONE_CMD_ARG("vxlanlocalport", setvxlan_local_port), + DEF_CLONE_CMD_ARG("vxlanremoteport", setvxlan_remote_port), + DEF_CLONE_CMD_ARG2("vxlanportrange", setvxlan_port_range), + DEF_CLONE_CMD_ARG("vxlantimeout", setvxlan_timeout), + DEF_CLONE_CMD_ARG("vxlanmaxaddr", setvxlan_maxaddr), DEF_CLONE_CMD_ARG("vxlandev", setvxlan_dev), - DEF_CLONE_CMD_ARG("ttl", setvxlan_ttl), - DEF_CLONE_CMD("learn", 1, setvxlan_learn), - DEF_CLONE_CMD("-learn", 0, setvxlan_learn), + DEF_CLONE_CMD_ARG("vxlanttl", setvxlan_ttl), + DEF_CLONE_CMD("vxlanlearn", 1, setvxlan_learn), + DEF_CLONE_CMD("-vxlanlearn", 0, setvxlan_learn), - DEF_CMD_ARG("vni", setvxlan_vni), - DEF_CMD_ARG("local", setvxlan_local), - DEF_CMD_ARG("remote", setvxlan_remote), - DEF_CMD_ARG("group", setvxlan_group), - DEF_CMD_ARG("localport", setvxlan_local_port), - DEF_CMD_ARG("remoteport", setvxlan_remote_port), - DEF_CMD_ARG2("portrange", setvxlan_port_range), - DEF_CMD_ARG("timeout", setvxlan_timeout), - DEF_CMD_ARG("maxaddr", setvxlan_maxaddr), + DEF_CMD_ARG("vxlanvni", setvxlan_vni), + DEF_CMD_ARG("vxlanlocal", setvxlan_local), + DEF_CMD_ARG("vxlanremote", setvxlan_remote), + DEF_CMD_ARG("vxlangroup", setvxlan_group), + DEF_CMD_ARG("vxlanlocalport", setvxlan_local_port), + DEF_CMD_ARG("vxlanremoteport", setvxlan_remote_port), + DEF_CMD_ARG2("vxlanportrange", setvxlan_port_range), + DEF_CMD_ARG("vxlantimeout", setvxlan_timeout), + DEF_CMD_ARG("vxlanmaxaddr", setvxlan_maxaddr), DEF_CMD_ARG("vxlandev", setvxlan_dev), - DEF_CMD_ARG("ttl", setvxlan_ttl), - DEF_CMD("learn", 1, setvxlan_learn), - DEF_CMD("-learn", 0, setvxlan_learn), + DEF_CMD_ARG("vxlanttl", setvxlan_ttl), + DEF_CMD("vxlanlearn", 1, setvxlan_learn), + DEF_CMD("-vxlanlearn", 0, setvxlan_learn), - DEF_CMD("flush", 0, setvxlan_flush), - DEF_CMD("flushall", 1, setvxlan_flush), + DEF_CMD("vxlanflush", 0, setvxlan_flush), + DEF_CMD("vxlanflushall", 1, setvxlan_flush), }; static struct afswtch af_vxlan = { diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c index fa314f6cb5c1..d71c021ad458 100644 --- a/sbin/ping6/ping6.c +++ b/sbin/ping6/ping6.c @@ -648,11 +648,20 @@ main(int argc, char *argv[]) err(1, "socket"); /* set the source address if specified. */ - if ((options & F_SRCADDR) && - bind(s, (struct sockaddr *)&src, srclen) != 0) { - err(1, "bind"); + if ((options & F_SRCADDR) != 0) { + /* properly fill sin6_scope_id */ + if (IN6_IS_ADDR_LINKLOCAL(&src.sin6_addr) && ( + IN6_IS_ADDR_LINKLOCAL(&dst.sin6_addr) || + IN6_IS_ADDR_MC_LINKLOCAL(&dst.sin6_addr) || + IN6_IS_ADDR_MC_NODELOCAL(&dst.sin6_addr))) { + if (src.sin6_scope_id == 0) + src.sin6_scope_id = dst.sin6_scope_id; + if (dst.sin6_scope_id == 0) + dst.sin6_scope_id = src.sin6_scope_id; + } + if (bind(s, (struct sockaddr *)&src, srclen) != 0) + err(1, "bind"); } - /* set the gateway (next hop) if specified */ if (gateway) { memset(&hints, 0, sizeof(hints)); diff --git a/sbin/shutdown/shutdown.8 b/sbin/shutdown/shutdown.8 index 871efbed8b06..4145ba5b64df 100644 --- a/sbin/shutdown/shutdown.8 +++ b/sbin/shutdown/shutdown.8 @@ -28,7 +28,7 @@ .\" @(#)shutdown.8 8.2 (Berkeley) 4/27/95 .\" $FreeBSD$ .\" -.Dd March 19, 2013 +.Dd December 15, 2014 .Dt SHUTDOWN 8 .Os .Sh NAME @@ -118,6 +118,15 @@ to the current system values. The first form brings the system down in .Ar number minutes and the second at the absolute time specified. +.Ar +number +may be specified in units other than minutes by appending the corresponding +suffix: +.Dq Li s , +.Dq Li sec , +.Dq Li m , +.Dq Li min . +.Dq Li h , +.Dq Li hour . .It Ar warning-message Any other arguments comprise the warning message that is broadcast to users currently logged into the system. diff --git a/sbin/shutdown/shutdown.c b/sbin/shutdown/shutdown.c index f53b3d8c98f9..b04e0bd87de6 100644 --- a/sbin/shutdown/shutdown.c +++ b/sbin/shutdown/shutdown.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -322,7 +323,8 @@ timewarn(int timeleft) (void)fprintf(pf, "System going down in %d minute%s\n\n", timeleft / 60, (timeleft > 60) ? "s" : ""); else if (timeleft) - (void)fprintf(pf, "System going down in 30 seconds\n\n"); + (void)fprintf(pf, "System going down in %s30 seconds\n\n", + (offset > 0 && offset < 30 ? "less than " : "")); else (void)fprintf(pf, "System going down IMMEDIATELY\n\n"); @@ -415,6 +417,7 @@ getoffset(char *timearg) char *p; time_t now; int this_year; + char *timeunit; (void)time(&now); @@ -427,8 +430,25 @@ getoffset(char *timearg) if (*timearg == '+') { /* +minutes */ if (!isdigit(*++timearg)) badtime(); - if ((offset = atoi(timearg) * 60) < 0) + errno = 0; + offset = strtol(timearg, &timeunit, 10); + if (offset < 0 || offset == LONG_MAX || errno != 0) badtime(); + if (timeunit[0] == '\0' || strcasecmp(timeunit, "m") == 0 || + strcasecmp(timeunit, "min") == 0 || + strcasecmp(timeunit, "mins") == 0) { + offset *= 60; + } else if (strcasecmp(timeunit, "h") == 0 || + strcasecmp(timeunit, "hour") == 0 || + strcasecmp(timeunit, "hours") == 0) { + offset *= 60 * 60; + } else if (strcasecmp(timeunit, "s") == 0 || + strcasecmp(timeunit, "sec") == 0 || + strcasecmp(timeunit, "secs") == 0) { + offset *= 1; + } else { + badtime(); + } shuttime = now + offset; return; } diff --git a/share/man/man4/vxlan.4 b/share/man/man4/vxlan.4 index 1e68c0845db6..ec95db1d9cfa 100644 --- a/share/man/man4/vxlan.4 +++ b/share/man/man4/vxlan.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 20, 2014 +.Dd December 16, 2014 .Dt VXLAN 4 .Os .Sh NAME @@ -140,7 +140,7 @@ or VNI. .Pp When configured with the .Xr ifconfig 8 -.Cm learn +.Cm vxlanlearn parameter, the interface dynamically creates forwarding table entries from received packets. An entry in the forwarding table maps the inner source MAC address @@ -153,16 +153,16 @@ Otherwise, when configured in multicast mode, the interface must flood the frame to all hosts in the group. The maximum number of entries in the table is configurable with the .Xr ifconfig 8 -.Cm maxaddr +.Cm vxlanmaxaddr command. Stale entries in the table periodically pruned. The timeout is configurable with the .Xr ifconfig 8 -.Cm timeout +.Cm vxlantimeout command. The table may be viewed with the .Xr sysctl 8 -.Cm net.link.vlxan.N.ftable.dump +.Cm net.link.vxlan.N.ftable.dump command. .Sh MTU Since the @@ -187,13 +187,13 @@ Create a .Nm interface in unicast mode with the -.Cm local +.Cm vxlanlocal tunnel address of 192.168.100.1, and the -.Cm remote +.Cm vxlanremote tunnel address of 192.168.100.2. .Bd -literal -offset indent -ifconfig vxlan create vni 108 local 192.168.100.1 remote 192.168.100.2 +ifconfig vxlan create vxlanid 108 vxlanlocal 192.168.100.1 vxlanremote 192.168.100.2 .Ed .Pp Create a @@ -207,7 +207,7 @@ and the address of 224.0.2.6. The em0 interface will be used to transmit multicast packets. .Bd -literal -offset indent -ifconfig vxlan create vni 42 local 192.168.10.95 group 224.0.2.6 vxlandev em0 +ifconfig vxlan create vxlanid 42 vxlanlocal 192.168.10.95 vxlangroup 224.0.2.6 vxlandev em0 .Ed .Pp Once created, the diff --git a/share/man/man7/build.7 b/share/man/man7/build.7 index a2172ed3316e..f634b59bb7fb 100644 --- a/share/man/man7/build.7 +++ b/share/man/man7/build.7 @@ -445,6 +445,21 @@ process. .Bd -literal -offset indent make PORTS_MODULES=emulators/kqemu-kmod kernel .Ed +.It Va STRIP_CMD +Command to use at install time when stripping binaries. +Be sure to add any additional tools required to run +.Va STRIP_CMD +to the +.Va LOCAL_ITOOLS +.Xr make 1 +variable before running the +.Cm distributeworld +or +.Cm installworld +targets. +See +.Xr install 1 +for more details. .It Va SUBDIR_OVERRIDE Override the default list of sub-directories and only build the sub-directory named in this variable. diff --git a/share/man/man9/rmlock.9 b/share/man/man9/rmlock.9 index da8234b0cdd4..ee033a6bc6b0 100644 --- a/share/man/man9/rmlock.9 +++ b/share/man/man9/rmlock.9 @@ -289,8 +289,8 @@ Assert that the current thread does not hold a recursive lock of .Xr mutex 9 , .Xr panic 9 , .Xr rwlock 9 , -.Xr sleep 9 , .Xr sema 9 , +.Xr sleep 9 , .Xr sx 9 .Sh HISTORY These diff --git a/share/man/man9/sx.9 b/share/man/man9/sx.9 index 01fffaae7e1e..49a064e39898 100644 --- a/share/man/man9/sx.9 +++ b/share/man/man9/sx.9 @@ -315,8 +315,8 @@ lock while another thread blocked on the same lock after acquiring a mutex, then the second thread would effectively end up sleeping while holding a mutex, which is not allowed. .Sh SEE ALSO -.Xr locking 9 , .Xr lock 9 , +.Xr locking 9 , .Xr mutex 9 , .Xr panic 9 , .Xr rwlock 9 , diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index 2a908a980f8d..71f16746e649 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -153,9 +153,13 @@ IDTVEC(xmm) IDTVEC(tss) TRAP_ERR(T_TSSFLT) IDTVEC(missing) - TRAP_ERR(T_SEGNPFLT) + subq $TF_ERR,%rsp + movl $T_SEGNPFLT,TF_TRAPNO(%rsp) + jmp prot_addrf IDTVEC(stk) - TRAP_ERR(T_STKFLT) + subq $TF_ERR,%rsp + movl $T_STKFLT,TF_TRAPNO(%rsp) + jmp prot_addrf IDTVEC(align) TRAP_ERR(T_ALIGNFLT) @@ -318,6 +322,7 @@ IDTVEC(page) IDTVEC(prot) subq $TF_ERR,%rsp movl $T_PROTFLT,TF_TRAPNO(%rsp) +prot_addrf: movq $0,TF_ADDR(%rsp) movq %rdi,TF_RDI(%rsp) /* free up a GP register */ leaq doreti_iret(%rip),%rdi diff --git a/sys/amd64/vmm/io/vatpic.c b/sys/amd64/vmm/io/vatpic.c index 54d8155611cc..c6d4590e893e 100644 --- a/sys/amd64/vmm/io/vatpic.c +++ b/sys/amd64/vmm/io/vatpic.c @@ -75,7 +75,7 @@ struct atpic { uint8_t mask; /* Interrupt Mask Register (IMR) */ int acnt[8]; /* sum of pin asserts and deasserts */ - int priority; /* current pin priority */ + int lowprio; /* lowest priority irq */ bool intr_raised; }; @@ -102,6 +102,14 @@ struct vatpic { #define VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4) \ VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4) +/* + * Loop over all the pins in priority order from highest to lowest. + */ +#define ATPIC_PIN_FOREACH(pinvar, atpic, tmpvar) \ + for (tmpvar = 0, pinvar = (atpic->lowprio + 1) & 0x7; \ + tmpvar < 8; \ + tmpvar++, pinvar = (pinvar + 1) & 0x7) + static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate); static __inline int @@ -110,8 +118,7 @@ vatpic_get_highest_isrpin(struct atpic *atpic) int bit, pin; int i; - for (i = 0; i <= 7; i++) { - pin = ((i + 7 - atpic->priority) & 0x7); + ATPIC_PIN_FOREACH(pin, atpic, i) { bit = (1 << pin); if (atpic->service & bit) @@ -125,8 +132,7 @@ static __inline int vatpic_get_highest_irrpin(struct atpic *atpic) { int serviced; - int bit, pin; - int i, j; + int bit, pin, tmp; /* * In 'Special Fully-Nested Mode' when an interrupt request from @@ -137,17 +143,21 @@ vatpic_get_highest_irrpin(struct atpic *atpic) if (atpic->sfn) serviced &= ~(1 << 2); - for (i = 0; i <= 7; i++) { - pin = ((i + 7 - atpic->priority) & 0x7); - bit = (1 << pin); - if (serviced & bit) - break; - } + ATPIC_PIN_FOREACH(pin, atpic, tmp) { + bit = 1 << pin; - for (j = 0; j < i; j++) { - pin = ((j + 7 - atpic->priority) & 0x7); - bit = (1 << pin); - if (atpic->request & bit && (~atpic->mask & bit)) + /* + * If there is already an interrupt in service at the same + * or higher priority then bail. + */ + if ((serviced & bit) != 0) + break; + + /* + * If an interrupt is asserted and not masked then return + * the corresponding 'pin' to the caller. + */ + if ((atpic->request & bit) != 0 && (atpic->mask & bit) == 0) return (pin); } @@ -238,7 +248,7 @@ vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) atpic->icw_num = 1; atpic->mask = 0; - atpic->priority = 0; + atpic->lowprio = 7; atpic->rd_cmd_reg = 0; if ((val & ICW1_SNGL) != 0) { @@ -329,11 +339,11 @@ vatpic_ocw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) atpic->service &= ~(1 << isr_bit); if (atpic->rotate) - atpic->priority = isr_bit; + atpic->lowprio = isr_bit; } } else if ((val & OCW2_SL) != 0 && atpic->rotate == true) { /* specific priority */ - atpic->priority = val & 0x7; + atpic->lowprio = val & 0x7; } return (0); @@ -388,6 +398,8 @@ vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate) } else if (oldcnt == 1 && newcnt == 0) { /* falling edge */ VATPIC_CTR1(vatpic, "atpic pin%d: deasserted", pin); + if (level) + atpic->request &= ~(1 << (pin & 0x7)); } else { VATPIC_CTR3(vatpic, "atpic pin%d: %s, ignored, acnt %d", pin, newstate ? "asserted" : "deasserted", newcnt); @@ -528,7 +540,7 @@ vatpic_pin_accepted(struct atpic *atpic, int pin) if (atpic->aeoi == true) { if (atpic->rotate == true) - atpic->priority = pin; + atpic->lowprio = pin; } else { atpic->service |= (1 << pin); } diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c index d62efc4ca2fb..d92f88d10a4f 100644 --- a/sys/arm/mv/mv_common.c +++ b/sys/arm/mv/mv_common.c @@ -1939,8 +1939,7 @@ fdt_get_ranges(const char *nodename, void *buf, int size, int *tuples, if (tuples_count <= 0) return (ERANGE); - if (fdt_ranges_verify(buf, tuples_count, par_addr_cells, - addr_cells, size_cells) != 0) + if (par_addr_cells > 2 || addr_cells > 2 || size_cells > 2) return (ERANGE); *tuples = tuples_count; diff --git a/sys/arm/mv/mv_pci.c b/sys/arm/mv/mv_pci.c index 8ac6c76bc0e1..42f9218ee81d 100644 --- a/sys/arm/mv/mv_pci.c +++ b/sys/arm/mv/mv_pci.c @@ -180,8 +180,7 @@ mv_pci_ranges_decode(phandle_t node, struct mv_pci_range *io_space, rangesptr += offset_cells; } - if (fdt_data_verify((void *)rangesptr, par_addr_cells - - offset_cells)) { + if ((par_addr_cells - offset_cells) > 2) { rv = ERANGE; goto out; } @@ -189,7 +188,7 @@ mv_pci_ranges_decode(phandle_t node, struct mv_pci_range *io_space, par_addr_cells - offset_cells); rangesptr += par_addr_cells - offset_cells; - if (fdt_data_verify((void *)rangesptr, size_cells)) { + if (size_cells > 2) { rv = ERANGE; goto out; } diff --git a/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts b/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts index 0ed81fcec268..c7dcde38263a 100644 --- a/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts +++ b/sys/boot/fdt/dts/arm/socfpga-sockit-beri.dts @@ -106,20 +106,36 @@ status = "okay"; }; + pio2: pio@c0022000 { + compatible = "altr,pio"; + reg = <0xc0022000 0x1000>; /* recv */ + interrupts = < 77 >; + interrupt-parent = <&GIC>; + status = "okay"; + }; + + pio3: pio@c0023000 { + compatible = "altr,pio"; + reg = <0xc0023000 0x1000>; /* send */ + interrupts = < 83 >; /* not in use on arm side */ + interrupt-parent = <&GIC>; + status = "okay"; + }; + beri_vtblk: vtblk@00001000 { compatible = "sri-cambridge,beri-vtblk"; reg = <0x00001000 0x1000>; pio-recv = <&pio0>; pio-send = <&pio1>; beri-mem = <&beri_mem0>; - status = "disabled"; + status = "okay"; }; beri_vtnet: vtnet@00002000 { compatible = "sri-cambridge,beri-vtnet"; reg = <0x00002000 0x1000>; - pio-recv = <&pio0>; - pio-send = <&pio1>; + pio-recv = <&pio2>; + pio-send = <&pio3>; beri-mem = <&beri_mem0>; status = "okay"; }; diff --git a/sys/boot/fdt/dts/mips/beri-netfpga.dts b/sys/boot/fdt/dts/mips/beri-netfpga.dts index 605392192d19..f272f9cfa5d6 100644 --- a/sys/boot/fdt/dts/mips/beri-netfpga.dts +++ b/sys/boot/fdt/dts/mips/beri-netfpga.dts @@ -82,6 +82,11 @@ */ }; + memory { + device_type = "memory"; + reg = <0x0 0x0FFFFFFF>; // ~256M at 0x0 + }; + soc { #address-cells = <1>; #size-cells = <1>; @@ -94,11 +99,6 @@ compatible = "simple-bus", "mips,mips4k"; ranges = <>; - memory { - device_type = "memory"; - reg = <0x0 0x0FFFFFFF>; // ~256M at 0x0 - }; - beripic: beripic@7f804000 { compatible = "sri-cambridge,beri-pic"; interrupt-controller; diff --git a/sys/boot/fdt/dts/mips/beri-sim.dts b/sys/boot/fdt/dts/mips/beri-sim.dts index 0704db867206..715445601d90 100644 --- a/sys/boot/fdt/dts/mips/beri-sim.dts +++ b/sys/boot/fdt/dts/mips/beri-sim.dts @@ -80,6 +80,11 @@ */ }; + memory { + device_type = "memory"; + reg = <0x0 0x4000000>; // 64M at 0x0 + }; + soc { #address-cells = <1>; #size-cells = <1>; @@ -92,11 +97,6 @@ compatible = "simple-bus", "mips,mips4k"; ranges = <>; - memory { - device_type = "memory"; - reg = <0x0 0x4000000>; // 64M at 0x0 - }; - beripic0: beripic@7f804000 { compatible = "sri-cambridge,beri-pic"; interrupt-controller; diff --git a/sys/boot/fdt/dts/mips/beripad-de4.dts b/sys/boot/fdt/dts/mips/beripad-de4.dts index 05ce0c2c8bca..287c2306d145 100644 --- a/sys/boot/fdt/dts/mips/beripad-de4.dts +++ b/sys/boot/fdt/dts/mips/beripad-de4.dts @@ -80,6 +80,11 @@ */ }; + memory { + device_type = "memory"; + reg = <0x0 0x40000000>; // 1G at 0x0 + }; + soc { #address-cells = <1>; #size-cells = <1>; @@ -92,11 +97,6 @@ compatible = "simple-bus", "mips,mips4k"; ranges = <>; - memory { - device_type = "memory"; - reg = <0x0 0x40000000>; // 1G at 0x0 - }; - beripic0: beripic@7f804000 { compatible = "sri-cambridge,beri-pic"; interrupt-controller; diff --git a/sys/boot/fdt/dts/mips/beripad-sockit.dts b/sys/boot/fdt/dts/mips/beripad-sockit.dts new file mode 100644 index 000000000000..ad9e4acfbea2 --- /dev/null +++ b/sys/boot/fdt/dts/mips/beripad-sockit.dts @@ -0,0 +1,219 @@ +/*- + * Copyright (c) 2012-2013 Robert N. M. Watson + * Copyright (c) 2013-2014 SRI International + * Copyright (c) 2014 Ruslan Bukin + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/dts-v1/; + +/* + * Device names here have been largely made up on the spot, especially for the + * "compatible" strings, and might want to be revised. + */ + +/ { + model = "SRI/Cambridge BeriPad (SoCKit)"; + compatible = "sri-cambridge,beripad-sockit"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <1>; + + /* + * Secondary CPUs all start disabled and use the + * spin-table enable method. cpu-release-addr must be + * specified for each cpu other than cpu@0. Values of + * cpu-release-addr grow down from 0x100000 (kernel). + */ + status = "disabled"; + enable-method = "spin-table"; + + cpu@0 { + device-type = "cpu"; + compatible = "sri-cambridge,beri"; + + reg = <0 1>; + status = "okay"; + }; + +/* + cpu@1 { + device-type = "cpu"; + compatible = "sri-cambridge,beri"; + + reg = <1 1>; + // XXX: should we need cached prefix? + cpu-release-addr = <0xffffffff 0x800fffe0>; + }; +*/ + }; + + memory { + device_type = "memory"; + reg = <0x0 0x10000000>; /* 256MB at 0x0 */ + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + #interrupt-cells = <1>; + + /* + * Declare mips,mips4k since BERI doesn't (yet) have a PIC, so + * we use mips4k coprocessor 0 interrupt management directly. + */ + compatible = "simple-bus", "mips,mips4k"; + /* ranges = <>; */ + + beripic0: beripic@7f804000 { + compatible = "sri-cambridge,beri-pic"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0x0 0x7f804000 0x0 0x400 + 0x0 0x7f806000 0x0 0x10 + 0x0 0x7f806080 0x0 0x10 + 0x0 0x7f806100 0x0 0x10>; + interrupts = <0 1 2 3 4>; + hard-interrupt-sources = <64>; + soft-interrupt-sources = <64>; + }; + + pio0: pio@7f020000 { + compatible = "altr,pio"; + reg = <0x0 0x7f020000 0x0 0x1000>; /* send */ + interrupts = <4>; /* not used */ + interrupt-parent = <&beripic0>; + }; + + pio1: pio@7f021000 { + compatible = "altr,pio"; + reg = <0x0 0x7f021000 0x0 0x1000>; /* recv */ + interrupts = <10>; + interrupt-parent = <&beripic0>; + }; + + pio2: pio@7f022000 { + compatible = "altr,pio"; + reg = <0x0 0x7f022000 0x0 0x1000>; /* send */ + interrupts = <5>; /* not used */ + interrupt-parent = <&beripic0>; + }; + + pio3: pio@7f023000 { + compatible = "altr,pio"; + reg = <0x0 0x7f023000 0x0 0x1000>; /* recv */ + interrupts = <11>; + interrupt-parent = <&beripic0>; + }; + + virtio_mmio_platform0: virtio_mmio_platform@0 { + compatible = "beri,virtio_mmio_platform"; + pio-send = <&pio0>; + pio-recv = <&pio1>; + }; + + virtio_mmio_platform1: virtio_mmio_platform@1 { + compatible = "beri,virtio_mmio_platform"; + pio-send = <&pio2>; + pio-recv = <&pio3>; + }; + + virtio_block@200001000 { + compatible = "virtio,mmio"; + reg = <0x2 0x1000 0x0 0x1000>; + platform = <&virtio_mmio_platform0>; + status = "okay"; + }; + + virtio_net@200002000 { + compatible = "virtio,mmio"; + reg = <0x2 0x2000 0x0 0x1000>; + platform = <&virtio_mmio_platform1>; + status = "okay"; + }; + + serial@7f000000 { + compatible = "altera,jtag_uart-11_0"; + reg = <0x0 0x7f000000 0x0 0x40>; + interrupts = <0>; + interrupt-parent = <&beripic0>; + }; + +/* + serial@7f001000 { + compatible = "altera,jtag_uart-11_0"; + reg = <0x7f001000 0x40>; + }; + + serial@7f002000 { + compatible = "altera,jtag_uart-11_0"; + reg = <0x7f002000 0x40>; + }; +*/ + +/* + led@7f006000 { + compatible = "sri-cambridge,de4led"; + reg = <0x7f006000 0x1>; + }; +*/ + +/* + avgen@0x7f009000 { + compatible = "sri-cambridge,avgen"; + reg = <0x7f009000 0x2>; + sri-cambridge,width = <1>; + sri-cambridge,fileio = "r"; + sri-cambridge,devname = "de4bsw"; + }; +*/ + +/* + berirom@0x7f00a000 { + compatible = "sri-cambridge,berirom"; + reg = <0x7f00a000 0x1000>; + }; +*/ + +/* + avgen@0x7f00c000 { + compatible = "sri-cambridge,avgen"; + reg = <0x7f00c000 0x8>; + sri-cambridge,width = <4>; + sri-cambridge,fileio = "rw"; + sri-cambridge,devname = "de4tempfan"; + }; +*/ + }; +}; diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 2a8aba908a2e..8fccd02f47bf 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -3900,7 +3900,7 @@ ctl_copy_io(union ctl_io *src, union ctl_io *dest) dest->io_hdr.flags |= CTL_FLAG_INT_COPY; } -static int +int ctl_expand_number(const char *buf, uint64_t *num) { char *endptr; @@ -10146,10 +10146,10 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len) if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) { scsi_ulto4b(0xffffffff, bl_ptr->max_unmap_lba_cnt); scsi_ulto4b(0xffffffff, bl_ptr->max_unmap_blk_cnt); - if (lun->be_lun->pblockexp != 0) { - scsi_ulto4b((1 << lun->be_lun->pblockexp), + if (lun->be_lun->ublockexp != 0) { + scsi_ulto4b((1 << lun->be_lun->ublockexp), bl_ptr->opt_unmap_grain); - scsi_ulto4b(0x80000000 | lun->be_lun->pblockoff, + scsi_ulto4b(0x80000000 | lun->be_lun->ublockoff, bl_ptr->unmap_grain_align); } } diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h index 1ec0586da4ec..ae6c5835f873 100644 --- a/sys/cam/ctl/ctl.h +++ b/sys/cam/ctl/ctl.h @@ -206,6 +206,7 @@ struct ctl_be_arg; void ctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args); void ctl_free_opts(ctl_options_t *opts); char * ctl_get_opt(ctl_options_t *opts, const char *name); +int ctl_expand_number(const char *buf, uint64_t *num); #endif /* _KERNEL */ diff --git a/sys/cam/ctl/ctl_backend.h b/sys/cam/ctl/ctl_backend.h index 77975f9ffea0..5e0af5cc302e 100644 --- a/sys/cam/ctl/ctl_backend.h +++ b/sys/cam/ctl/ctl_backend.h @@ -194,6 +194,8 @@ struct ctl_be_lun { uint32_t blocksize; /* passed to CTL */ uint16_t pblockexp; /* passed to CTL */ uint16_t pblockoff; /* passed to CTL */ + uint16_t ublockexp; /* passed to CTL */ + uint16_t ublockoff; /* passed to CTL */ uint32_t atomicblock; /* passed to CTL */ uint32_t req_lun_id; /* passed to CTL */ uint32_t lun_id; /* returned from CTL */ diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index 1eb5ed2e40ba..9c3e8fd686dc 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -173,6 +173,8 @@ struct ctl_be_block_lun { int blocksize_shift; uint16_t pblockexp; uint16_t pblockoff; + uint16_t ublockexp; + uint16_t ublockoff; struct ctl_be_block_softc *softc; struct devstat *disk_stats; ctl_be_block_lun_flags flags; @@ -1739,8 +1741,9 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) { struct ctl_be_block_filedata *file_data; struct ctl_lun_create_params *params; + char *value; struct vattr vattr; - off_t pss; + off_t ps, pss, po, pos, us, uss, uo, uos; int error; error = 0; @@ -1800,11 +1803,36 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) be_lun->blocksize = params->blocksize_bytes; else be_lun->blocksize = 512; - pss = vattr.va_blocksize / be_lun->blocksize; - if ((pss > 0) && (pss * be_lun->blocksize == vattr.va_blocksize) && - ((pss & (pss - 1)) == 0)) { + + us = ps = vattr.va_blocksize; + uo = po = 0; + + value = ctl_get_opt(&be_lun->ctl_be_lun.options, "pblocksize"); + if (value != NULL) + ctl_expand_number(value, &ps); + value = ctl_get_opt(&be_lun->ctl_be_lun.options, "pblockoffset"); + if (value != NULL) + ctl_expand_number(value, &po); + pss = ps / be_lun->blocksize; + pos = po / be_lun->blocksize; + if ((pss > 0) && (pss * be_lun->blocksize == ps) && (pss >= pos) && + ((pss & (pss - 1)) == 0) && (pos * be_lun->blocksize == po)) { be_lun->pblockexp = fls(pss) - 1; - be_lun->pblockoff = 0; + be_lun->pblockoff = (pss - pos) % pss; + } + + value = ctl_get_opt(&be_lun->ctl_be_lun.options, "ublocksize"); + if (value != NULL) + ctl_expand_number(value, &us); + value = ctl_get_opt(&be_lun->ctl_be_lun.options, "ublockoffset"); + if (value != NULL) + ctl_expand_number(value, &uo); + uss = us / be_lun->blocksize; + uos = uo / be_lun->blocksize; + if ((uss > 0) && (uss * be_lun->blocksize == us) && (uss >= uos) && + ((uss & (uss - 1)) == 0) && (uos * be_lun->blocksize == uo)) { + be_lun->ublockexp = fls(uss) - 1; + be_lun->ublockoff = (uss - uos) % uss; } /* @@ -1827,8 +1855,9 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) struct vattr vattr; struct cdev *dev; struct cdevsw *devsw; + char *value; int error; - off_t ps, pss, po, pos; + off_t ps, pss, po, pos, us, uss, uo, uos; params = &be_lun->params; @@ -1942,6 +1971,15 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) if (error) po = 0; } + us = ps; + uo = po; + + value = ctl_get_opt(&be_lun->ctl_be_lun.options, "pblocksize"); + if (value != NULL) + ctl_expand_number(value, &ps); + value = ctl_get_opt(&be_lun->ctl_be_lun.options, "pblockoffset"); + if (value != NULL) + ctl_expand_number(value, &po); pss = ps / be_lun->blocksize; pos = po / be_lun->blocksize; if ((pss > 0) && (pss * be_lun->blocksize == ps) && (pss >= pos) && @@ -1950,6 +1988,20 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req) be_lun->pblockoff = (pss - pos) % pss; } + value = ctl_get_opt(&be_lun->ctl_be_lun.options, "ublocksize"); + if (value != NULL) + ctl_expand_number(value, &us); + value = ctl_get_opt(&be_lun->ctl_be_lun.options, "ublockoffset"); + if (value != NULL) + ctl_expand_number(value, &uo); + uss = us / be_lun->blocksize; + uos = uo / be_lun->blocksize; + if ((uss > 0) && (uss * be_lun->blocksize == us) && (uss >= uos) && + ((uss & (uss - 1)) == 0) && (uos * be_lun->blocksize == uo)) { + be_lun->ublockexp = fls(uss) - 1; + be_lun->ublockoff = (uss - uos) % uss; + } + return (0); } @@ -2162,6 +2214,8 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) be_lun->blocksize = 0; be_lun->pblockexp = 0; be_lun->pblockoff = 0; + be_lun->ublockexp = 0; + be_lun->ublockoff = 0; be_lun->size_blocks = 0; be_lun->size_bytes = 0; be_lun->ctl_be_lun.maxlba = 0; @@ -2212,6 +2266,8 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) be_lun->ctl_be_lun.blocksize = be_lun->blocksize; be_lun->ctl_be_lun.pblockexp = be_lun->pblockexp; be_lun->ctl_be_lun.pblockoff = be_lun->pblockoff; + be_lun->ctl_be_lun.ublockexp = be_lun->ublockexp; + be_lun->ctl_be_lun.ublockoff = be_lun->ublockoff; if (be_lun->dispatch == ctl_be_block_dispatch_zvol && be_lun->blocksize != 0) be_lun->ctl_be_lun.atomicblock = CTLBLK_MAX_IO_SIZE / @@ -2591,6 +2647,8 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req) be_lun->ctl_be_lun.blocksize = be_lun->blocksize; be_lun->ctl_be_lun.pblockexp = be_lun->pblockexp; be_lun->ctl_be_lun.pblockoff = be_lun->pblockoff; + be_lun->ctl_be_lun.ublockexp = be_lun->ublockexp; + be_lun->ctl_be_lun.ublockoff = be_lun->ublockoff; if (be_lun->dispatch == ctl_be_block_dispatch_zvol && be_lun->blocksize != 0) be_lun->ctl_be_lun.atomicblock = CTLBLK_MAX_IO_SIZE / diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c index 24c0091d614f..b07ea9355708 100644 --- a/sys/cam/ctl/ctl_cmd_table.c +++ b/sys/cam/ctl/ctl_cmd_table.c @@ -513,7 +513,7 @@ const struct ctl_cmd_entry ctl_cmd_table_a3[32] = CTL_FLAG_DATA_IN | CTL_CMD_FLAG_ALLOW_ON_PR_RESV, CTL_LUN_PAT_NONE, - 12, {0x0c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, + 12, {0x0c, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}}, /* 0D REPORT SUPPORTED_TASK MANAGEMENT FUNCTIONS */ {ctl_report_supported_tmf, CTL_SERIDX_INQ, CTL_CMD_FLAG_OK_ON_BOTH | diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c index 8ec582586b77..0114b57b8247 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.c +++ b/sys/cam/ctl/ctl_frontend_iscsi.c @@ -233,19 +233,34 @@ cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request) } #endif - /* - * The target MUST silently ignore any non-immediate command outside - * of this range. - */ - if (cmdsn < cs->cs_cmdsn || cmdsn > cs->cs_cmdsn + maxcmdsn_delta) { - CFISCSI_SESSION_UNLOCK(cs); - CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %d, " - "while expected CmdSN was %d", cmdsn, cs->cs_cmdsn); - return (true); - } + if ((request->ip_bhs->bhs_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) { + /* + * The target MUST silently ignore any non-immediate command + * outside of this range. + */ + if (ISCSI_SNLT(cmdsn, cs->cs_cmdsn) || + ISCSI_SNGT(cmdsn, cs->cs_cmdsn + maxcmdsn_delta)) { + CFISCSI_SESSION_UNLOCK(cs); + CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %u, " + "while expected %u", cmdsn, cs->cs_cmdsn); + return (true); + } - if ((request->ip_bhs->bhs_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) + /* + * We don't support multiple connections now, so any + * discontinuity in CmdSN means lost PDUs. Since we don't + * support PDU retransmission -- terminate the connection. + */ + if (cmdsn != cs->cs_cmdsn) { + CFISCSI_SESSION_UNLOCK(cs); + CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %u, " + "while expected %u; dropping connection", + cmdsn, cs->cs_cmdsn); + cfiscsi_session_terminate(cs); + return (true); + } cs->cs_cmdsn++; + } CFISCSI_SESSION_UNLOCK(cs); @@ -892,6 +907,16 @@ cfiscsi_pdu_handle_data_out(struct icl_pdu *request) return; } + if (cdw->cdw_datasn != ntohl(bhsdo->bhsdo_datasn)) { + CFISCSI_SESSION_WARN(cs, "received Data-Out PDU with " + "DataSN %u, while expected %u; dropping connection", + ntohl(bhsdo->bhsdo_datasn), cdw->cdw_datasn); + icl_pdu_free(request); + cfiscsi_session_terminate(cs); + return; + } + cdw->cdw_datasn++; + io = cdw->cdw_ctl_io; KASSERT((io->io_hdr.flags & CTL_FLAG_DATA_MASK) != CTL_FLAG_DATA_IN, ("CTL_FLAG_DATA_IN")); @@ -2650,6 +2675,7 @@ cfiscsi_datamove_out(union ctl_io *io) cdw->cdw_target_transfer_tag = target_transfer_tag; cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag; cdw->cdw_r2t_end = io->scsiio.kern_data_len; + cdw->cdw_datasn = 0; /* Set initial data pointer for the CDW respecting ext_data_filled. */ if (io->scsiio.kern_sg_entries > 0) { diff --git a/sys/cam/ctl/ctl_frontend_iscsi.h b/sys/cam/ctl/ctl_frontend_iscsi.h index 336b69da3234..5000f4c9c067 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.h +++ b/sys/cam/ctl/ctl_frontend_iscsi.h @@ -58,6 +58,7 @@ struct cfiscsi_data_wait { char *cdw_sg_addr; size_t cdw_sg_len; uint32_t cdw_r2t_end; + uint32_t cdw_datasn; }; #define CFISCSI_SESSION_STATE_INVALID 0 diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c index 2635e4be6cc4..975ab7a7b381 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -197,6 +197,7 @@ static boolean_t arc_warm; uint64_t zfs_arc_max; uint64_t zfs_arc_min; uint64_t zfs_arc_meta_limit = 0; +uint64_t zfs_arc_meta_min = 0; int zfs_arc_grow_retry = 0; int zfs_arc_shrink_shift = 0; int zfs_arc_p_min_shift = 0; @@ -218,6 +219,7 @@ SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY, arc_free_target_init, NULL); TUNABLE_QUAD("vfs.zfs.arc_meta_limit", &zfs_arc_meta_limit); +TUNABLE_QUAD("vfs.zfs.arc_meta_min", &zfs_arc_meta_min); TUNABLE_INT("vfs.zfs.arc_shrink_shift", &zfs_arc_shrink_shift); SYSCTL_DECL(_vfs_zfs); SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, arc_max, CTLFLAG_RDTUN, &zfs_arc_max, 0, @@ -426,6 +428,7 @@ typedef struct arc_stats { kstat_named_t arcstat_meta_used; kstat_named_t arcstat_meta_limit; kstat_named_t arcstat_meta_max; + kstat_named_t arcstat_meta_min; } arc_stats_t; static arc_stats_t arc_stats = { @@ -506,7 +509,8 @@ static arc_stats_t arc_stats = { { "duplicate_reads", KSTAT_DATA_UINT64 }, { "arc_meta_used", KSTAT_DATA_UINT64 }, { "arc_meta_limit", KSTAT_DATA_UINT64 }, - { "arc_meta_max", KSTAT_DATA_UINT64 } + { "arc_meta_max", KSTAT_DATA_UINT64 }, + { "arc_meta_min", KSTAT_DATA_UINT64 } }; #define ARCSTAT(stat) (arc_stats.stat.value.ui64) @@ -569,6 +573,7 @@ static arc_state_t *arc_l2c_only; #define arc_c_min ARCSTAT(arcstat_c_min) /* min target cache size */ #define arc_c_max ARCSTAT(arcstat_c_max) /* max target cache size */ #define arc_meta_limit ARCSTAT(arcstat_meta_limit) /* max size for metadata */ +#define arc_meta_min ARCSTAT(arcstat_meta_min) /* min size for metadata */ #define arc_meta_used ARCSTAT(arcstat_meta_used) /* size of metadata */ #define arc_meta_max ARCSTAT(arcstat_meta_max) /* max size of metadata */ @@ -613,7 +618,7 @@ struct arc_buf_hdr { arc_buf_hdr_t *b_hash_next; arc_buf_t *b_buf; - uint32_t b_flags; + arc_flags_t b_flags; uint32_t b_datacnt; arc_callback_t *b_acb; @@ -661,52 +666,26 @@ sysctl_vfs_zfs_arc_meta_limit(SYSCTL_HANDLER_ARGS) static arc_buf_t *arc_eviction_list; static kmutex_t arc_eviction_mtx; static arc_buf_hdr_t arc_eviction_hdr; -static void arc_get_data_buf(arc_buf_t *buf); -static void arc_access(arc_buf_hdr_t *buf, kmutex_t *hash_lock); -static int arc_evict_needed(arc_buf_contents_t type); -static void arc_evict_ghost(arc_state_t *state, uint64_t spa, int64_t bytes); -#ifdef illumos -static void arc_buf_watch(arc_buf_t *buf); -#endif /* illumos */ - -static boolean_t l2arc_write_eligible(uint64_t spa_guid, arc_buf_hdr_t *ab); #define GHOST_STATE(state) \ ((state) == arc_mru_ghost || (state) == arc_mfu_ghost || \ (state) == arc_l2c_only) -/* - * Private ARC flags. These flags are private ARC only flags that will show up - * in b_flags in the arc_hdr_buf_t. Some flags are publicly declared, and can - * be passed in as arc_flags in things like arc_read. However, these flags - * should never be passed and should only be set by ARC code. When adding new - * public flags, make sure not to smash the private ones. - */ - -#define ARC_IN_HASH_TABLE (1 << 9) /* this buffer is hashed */ -#define ARC_IO_IN_PROGRESS (1 << 10) /* I/O in progress for buf */ -#define ARC_IO_ERROR (1 << 11) /* I/O failed for buf */ -#define ARC_FREED_IN_READ (1 << 12) /* buf freed while in read */ -#define ARC_BUF_AVAILABLE (1 << 13) /* block not in active use */ -#define ARC_INDIRECT (1 << 14) /* this is an indirect block */ -#define ARC_FREE_IN_PROGRESS (1 << 15) /* hdr about to be freed */ -#define ARC_L2_WRITING (1 << 16) /* L2ARC write in progress */ -#define ARC_L2_EVICTED (1 << 17) /* evicted during I/O */ -#define ARC_L2_WRITE_HEAD (1 << 18) /* head of write list */ - -#define HDR_IN_HASH_TABLE(hdr) ((hdr)->b_flags & ARC_IN_HASH_TABLE) -#define HDR_IO_IN_PROGRESS(hdr) ((hdr)->b_flags & ARC_IO_IN_PROGRESS) -#define HDR_IO_ERROR(hdr) ((hdr)->b_flags & ARC_IO_ERROR) -#define HDR_PREFETCH(hdr) ((hdr)->b_flags & ARC_PREFETCH) -#define HDR_FREED_IN_READ(hdr) ((hdr)->b_flags & ARC_FREED_IN_READ) -#define HDR_BUF_AVAILABLE(hdr) ((hdr)->b_flags & ARC_BUF_AVAILABLE) -#define HDR_FREE_IN_PROGRESS(hdr) ((hdr)->b_flags & ARC_FREE_IN_PROGRESS) -#define HDR_L2CACHE(hdr) ((hdr)->b_flags & ARC_L2CACHE) -#define HDR_L2_READING(hdr) ((hdr)->b_flags & ARC_IO_IN_PROGRESS && \ - (hdr)->b_l2hdr != NULL) -#define HDR_L2_WRITING(hdr) ((hdr)->b_flags & ARC_L2_WRITING) -#define HDR_L2_EVICTED(hdr) ((hdr)->b_flags & ARC_L2_EVICTED) -#define HDR_L2_WRITE_HEAD(hdr) ((hdr)->b_flags & ARC_L2_WRITE_HEAD) +#define HDR_IN_HASH_TABLE(hdr) ((hdr)->b_flags & ARC_FLAG_IN_HASH_TABLE) +#define HDR_IO_IN_PROGRESS(hdr) ((hdr)->b_flags & ARC_FLAG_IO_IN_PROGRESS) +#define HDR_IO_ERROR(hdr) ((hdr)->b_flags & ARC_FLAG_IO_ERROR) +#define HDR_PREFETCH(hdr) ((hdr)->b_flags & ARC_FLAG_PREFETCH) +#define HDR_FREED_IN_READ(hdr) ((hdr)->b_flags & ARC_FLAG_FREED_IN_READ) +#define HDR_BUF_AVAILABLE(hdr) ((hdr)->b_flags & ARC_FLAG_BUF_AVAILABLE) +#define HDR_FREE_IN_PROGRESS(hdr) \ + ((hdr)->b_flags & ARC_FLAG_FREE_IN_PROGRESS) +#define HDR_L2CACHE(hdr) ((hdr)->b_flags & ARC_FLAG_L2CACHE) +#define HDR_L2_READING(hdr) \ + ((hdr)->b_flags & ARC_FLAG_IO_IN_PROGRESS && \ + (hdr)->b_l2hdr != NULL) +#define HDR_L2_WRITING(hdr) ((hdr)->b_flags & ARC_FLAG_L2_WRITING) +#define HDR_L2_EVICTED(hdr) ((hdr)->b_flags & ARC_FLAG_L2_EVICTED) +#define HDR_L2_WRITE_HEAD(hdr) ((hdr)->b_flags & ARC_FLAG_L2_WRITE_HEAD) /* * Other sizes @@ -898,14 +877,20 @@ static kmutex_t l2arc_feed_thr_lock; static kcondvar_t l2arc_feed_thr_cv; static uint8_t l2arc_thread_exit; -static void l2arc_read_done(zio_t *zio); +static void arc_get_data_buf(arc_buf_t *); +static void arc_access(arc_buf_hdr_t *, kmutex_t *); +static int arc_evict_needed(arc_buf_contents_t); +static void arc_evict_ghost(arc_state_t *, uint64_t, int64_t); +static void arc_buf_watch(arc_buf_t *); + +static boolean_t l2arc_write_eligible(uint64_t, arc_buf_hdr_t *); +static void l2arc_read_done(zio_t *); static void l2arc_hdr_stat_add(void); static void l2arc_hdr_stat_remove(void); -static boolean_t l2arc_compress_buf(l2arc_buf_hdr_t *l2hdr); -static void l2arc_decompress_zio(zio_t *zio, arc_buf_hdr_t *hdr, - enum zio_compress c); -static void l2arc_release_cdata_buf(arc_buf_hdr_t *ab); +static boolean_t l2arc_compress_buf(l2arc_buf_hdr_t *); +static void l2arc_decompress_zio(zio_t *, arc_buf_hdr_t *, enum zio_compress); +static void l2arc_release_cdata_buf(arc_buf_hdr_t *); static uint64_t buf_hash(uint64_t spa, const dva_t *dva, uint64_t birth) @@ -950,14 +935,14 @@ buf_hash_find(uint64_t spa, const blkptr_t *bp, kmutex_t **lockp) uint64_t birth = BP_PHYSICAL_BIRTH(bp); uint64_t idx = BUF_HASH_INDEX(spa, dva, birth); kmutex_t *hash_lock = BUF_HASH_LOCK(idx); - arc_buf_hdr_t *buf; + arc_buf_hdr_t *hdr; mutex_enter(hash_lock); - for (buf = buf_hash_table.ht_table[idx]; buf != NULL; - buf = buf->b_hash_next) { - if (BUF_EQUAL(spa, dva, birth, buf)) { + for (hdr = buf_hash_table.ht_table[idx]; hdr != NULL; + hdr = hdr->b_hash_next) { + if (BUF_EQUAL(spa, dva, birth, hdr)) { *lockp = hash_lock; - return (buf); + return (hdr); } } mutex_exit(hash_lock); @@ -972,27 +957,27 @@ buf_hash_find(uint64_t spa, const blkptr_t *bp, kmutex_t **lockp) * Otherwise returns NULL. */ static arc_buf_hdr_t * -buf_hash_insert(arc_buf_hdr_t *buf, kmutex_t **lockp) +buf_hash_insert(arc_buf_hdr_t *hdr, kmutex_t **lockp) { - uint64_t idx = BUF_HASH_INDEX(buf->b_spa, &buf->b_dva, buf->b_birth); + uint64_t idx = BUF_HASH_INDEX(hdr->b_spa, &hdr->b_dva, hdr->b_birth); kmutex_t *hash_lock = BUF_HASH_LOCK(idx); - arc_buf_hdr_t *fbuf; + arc_buf_hdr_t *fhdr; uint32_t i; - ASSERT(!DVA_IS_EMPTY(&buf->b_dva)); - ASSERT(buf->b_birth != 0); - ASSERT(!HDR_IN_HASH_TABLE(buf)); + ASSERT(!DVA_IS_EMPTY(&hdr->b_dva)); + ASSERT(hdr->b_birth != 0); + ASSERT(!HDR_IN_HASH_TABLE(hdr)); *lockp = hash_lock; mutex_enter(hash_lock); - for (fbuf = buf_hash_table.ht_table[idx], i = 0; fbuf != NULL; - fbuf = fbuf->b_hash_next, i++) { - if (BUF_EQUAL(buf->b_spa, &buf->b_dva, buf->b_birth, fbuf)) - return (fbuf); + for (fhdr = buf_hash_table.ht_table[idx], i = 0; fhdr != NULL; + fhdr = fhdr->b_hash_next, i++) { + if (BUF_EQUAL(hdr->b_spa, &hdr->b_dva, hdr->b_birth, fhdr)) + return (fhdr); } - buf->b_hash_next = buf_hash_table.ht_table[idx]; - buf_hash_table.ht_table[idx] = buf; - buf->b_flags |= ARC_IN_HASH_TABLE; + hdr->b_hash_next = buf_hash_table.ht_table[idx]; + buf_hash_table.ht_table[idx] = hdr; + hdr->b_flags |= ARC_FLAG_IN_HASH_TABLE; /* collect some hash table performance data */ if (i > 0) { @@ -1010,22 +995,22 @@ buf_hash_insert(arc_buf_hdr_t *buf, kmutex_t **lockp) } static void -buf_hash_remove(arc_buf_hdr_t *buf) +buf_hash_remove(arc_buf_hdr_t *hdr) { - arc_buf_hdr_t *fbuf, **bufp; - uint64_t idx = BUF_HASH_INDEX(buf->b_spa, &buf->b_dva, buf->b_birth); + arc_buf_hdr_t *fhdr, **hdrp; + uint64_t idx = BUF_HASH_INDEX(hdr->b_spa, &hdr->b_dva, hdr->b_birth); ASSERT(MUTEX_HELD(BUF_HASH_LOCK(idx))); - ASSERT(HDR_IN_HASH_TABLE(buf)); + ASSERT(HDR_IN_HASH_TABLE(hdr)); - bufp = &buf_hash_table.ht_table[idx]; - while ((fbuf = *bufp) != buf) { - ASSERT(fbuf != NULL); - bufp = &fbuf->b_hash_next; + hdrp = &buf_hash_table.ht_table[idx]; + while ((fhdr = *hdrp) != hdr) { + ASSERT(fhdr != NULL); + hdrp = &fhdr->b_hash_next; } - *bufp = buf->b_hash_next; - buf->b_hash_next = NULL; - buf->b_flags &= ~ARC_IN_HASH_TABLE; + *hdrp = hdr->b_hash_next; + hdr->b_hash_next = NULL; + hdr->b_flags &= ~ARC_FLAG_IN_HASH_TABLE; /* collect some hash table performance data */ ARCSTAT_BUMPDOWN(arcstat_hash_elements); @@ -1062,12 +1047,12 @@ buf_fini(void) static int hdr_cons(void *vbuf, void *unused, int kmflag) { - arc_buf_hdr_t *buf = vbuf; + arc_buf_hdr_t *hdr = vbuf; - bzero(buf, sizeof (arc_buf_hdr_t)); - refcount_create(&buf->b_refcnt); - cv_init(&buf->b_cv, NULL, CV_DEFAULT, NULL); - mutex_init(&buf->b_freeze_lock, NULL, MUTEX_DEFAULT, NULL); + bzero(hdr, sizeof (arc_buf_hdr_t)); + refcount_create(&hdr->b_refcnt); + cv_init(&hdr->b_cv, NULL, CV_DEFAULT, NULL); + mutex_init(&hdr->b_freeze_lock, NULL, MUTEX_DEFAULT, NULL); arc_space_consume(sizeof (arc_buf_hdr_t), ARC_SPACE_HDRS); return (0); @@ -1094,12 +1079,12 @@ buf_cons(void *vbuf, void *unused, int kmflag) static void hdr_dest(void *vbuf, void *unused) { - arc_buf_hdr_t *buf = vbuf; + arc_buf_hdr_t *hdr = vbuf; - ASSERT(BUF_EMPTY(buf)); - refcount_destroy(&buf->b_refcnt); - cv_destroy(&buf->b_cv); - mutex_destroy(&buf->b_freeze_lock); + ASSERT(BUF_EMPTY(hdr)); + refcount_destroy(&hdr->b_refcnt); + cv_destroy(&hdr->b_cv); + mutex_destroy(&hdr->b_freeze_lock); arc_space_return(sizeof (arc_buf_hdr_t), ARC_SPACE_HDRS); } @@ -1181,7 +1166,7 @@ arc_cksum_verify(arc_buf_t *buf) mutex_enter(&buf->b_hdr->b_freeze_lock); if (buf->b_hdr->b_freeze_cksum == NULL || - (buf->b_hdr->b_flags & ARC_IO_ERROR)) { + (buf->b_hdr->b_flags & ARC_FLAG_IO_ERROR)) { mutex_exit(&buf->b_hdr->b_freeze_lock); return; } @@ -1276,7 +1261,7 @@ arc_buf_thaw(arc_buf_t *buf) if (zfs_flags & ZFS_DEBUG_MODIFY) { if (buf->b_hdr->b_state != arc_anon) panic("modifying non-anon buffer!"); - if (buf->b_hdr->b_flags & ARC_IO_IN_PROGRESS) + if (buf->b_hdr->b_flags & ARC_FLAG_IO_IN_PROGRESS) panic("modifying buffer while i/o in progress!"); arc_cksum_verify(buf); } @@ -1319,11 +1304,11 @@ arc_buf_freeze(arc_buf_t *buf) } static void -get_buf_info(arc_buf_hdr_t *ab, arc_state_t *state, list_t **list, kmutex_t **lock) +get_buf_info(arc_buf_hdr_t *hdr, arc_state_t *state, list_t **list, kmutex_t **lock) { - uint64_t buf_hashid = buf_hash(ab->b_spa, &ab->b_dva, ab->b_birth); + uint64_t buf_hashid = buf_hash(hdr->b_spa, &hdr->b_dva, hdr->b_birth); - if (ab->b_type == ARC_BUFC_METADATA) + if (hdr->b_type == ARC_BUFC_METADATA) buf_hashid &= (ARC_BUFC_NUMMETADATALISTS - 1); else { buf_hashid &= (ARC_BUFC_NUMDATALISTS - 1); @@ -1336,59 +1321,59 @@ get_buf_info(arc_buf_hdr_t *ab, arc_state_t *state, list_t **list, kmutex_t **lo static void -add_reference(arc_buf_hdr_t *ab, kmutex_t *hash_lock, void *tag) +add_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, void *tag) { ASSERT(MUTEX_HELD(hash_lock)); - if ((refcount_add(&ab->b_refcnt, tag) == 1) && - (ab->b_state != arc_anon)) { - uint64_t delta = ab->b_size * ab->b_datacnt; - uint64_t *size = &ab->b_state->arcs_lsize[ab->b_type]; + if ((refcount_add(&hdr->b_refcnt, tag) == 1) && + (hdr->b_state != arc_anon)) { + uint64_t delta = hdr->b_size * hdr->b_datacnt; + uint64_t *size = &hdr->b_state->arcs_lsize[hdr->b_type]; list_t *list; kmutex_t *lock; - get_buf_info(ab, ab->b_state, &list, &lock); + get_buf_info(hdr, hdr->b_state, &list, &lock); ASSERT(!MUTEX_HELD(lock)); mutex_enter(lock); - ASSERT(list_link_active(&ab->b_arc_node)); - list_remove(list, ab); - if (GHOST_STATE(ab->b_state)) { - ASSERT0(ab->b_datacnt); - ASSERT3P(ab->b_buf, ==, NULL); - delta = ab->b_size; + ASSERT(list_link_active(&hdr->b_arc_node)); + list_remove(list, hdr); + if (GHOST_STATE(hdr->b_state)) { + ASSERT0(hdr->b_datacnt); + ASSERT3P(hdr->b_buf, ==, NULL); + delta = hdr->b_size; } ASSERT(delta > 0); ASSERT3U(*size, >=, delta); atomic_add_64(size, -delta); mutex_exit(lock); /* remove the prefetch flag if we get a reference */ - if (ab->b_flags & ARC_PREFETCH) - ab->b_flags &= ~ARC_PREFETCH; + if (hdr->b_flags & ARC_FLAG_PREFETCH) + hdr->b_flags &= ~ARC_FLAG_PREFETCH; } } static int -remove_reference(arc_buf_hdr_t *ab, kmutex_t *hash_lock, void *tag) +remove_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lock, void *tag) { int cnt; - arc_state_t *state = ab->b_state; + arc_state_t *state = hdr->b_state; ASSERT(state == arc_anon || MUTEX_HELD(hash_lock)); ASSERT(!GHOST_STATE(state)); - if (((cnt = refcount_remove(&ab->b_refcnt, tag)) == 0) && + if (((cnt = refcount_remove(&hdr->b_refcnt, tag)) == 0) && (state != arc_anon)) { - uint64_t *size = &state->arcs_lsize[ab->b_type]; + uint64_t *size = &state->arcs_lsize[hdr->b_type]; list_t *list; kmutex_t *lock; - get_buf_info(ab, state, &list, &lock); + get_buf_info(hdr, state, &list, &lock); ASSERT(!MUTEX_HELD(lock)); mutex_enter(lock); - ASSERT(!list_link_active(&ab->b_arc_node)); - list_insert_head(list, ab); - ASSERT(ab->b_datacnt > 0); - atomic_add_64(size, ab->b_size * ab->b_datacnt); + ASSERT(!list_link_active(&hdr->b_arc_node)); + list_insert_head(list, hdr); + ASSERT(hdr->b_datacnt > 0); + atomic_add_64(size, hdr->b_size * hdr->b_datacnt); mutex_exit(lock); } return (cnt); @@ -1399,21 +1384,22 @@ remove_reference(arc_buf_hdr_t *ab, kmutex_t *hash_lock, void *tag) * for the buffer must be held by the caller. */ static void -arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *ab, kmutex_t *hash_lock) +arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *hdr, + kmutex_t *hash_lock) { - arc_state_t *old_state = ab->b_state; - int64_t refcnt = refcount_count(&ab->b_refcnt); + arc_state_t *old_state = hdr->b_state; + int64_t refcnt = refcount_count(&hdr->b_refcnt); uint64_t from_delta, to_delta; list_t *list; kmutex_t *lock; ASSERT(MUTEX_HELD(hash_lock)); ASSERT3P(new_state, !=, old_state); - ASSERT(refcnt == 0 || ab->b_datacnt > 0); - ASSERT(ab->b_datacnt == 0 || !GHOST_STATE(new_state)); - ASSERT(ab->b_datacnt <= 1 || old_state != arc_anon); + ASSERT(refcnt == 0 || hdr->b_datacnt > 0); + ASSERT(hdr->b_datacnt == 0 || !GHOST_STATE(new_state)); + ASSERT(hdr->b_datacnt <= 1 || old_state != arc_anon); - from_delta = to_delta = ab->b_datacnt * ab->b_size; + from_delta = to_delta = hdr->b_datacnt * hdr->b_size; /* * If this buffer is evictable, transfer it from the @@ -1422,24 +1408,24 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *ab, kmutex_t *hash_lock) if (refcnt == 0) { if (old_state != arc_anon) { int use_mutex; - uint64_t *size = &old_state->arcs_lsize[ab->b_type]; + uint64_t *size = &old_state->arcs_lsize[hdr->b_type]; - get_buf_info(ab, old_state, &list, &lock); + get_buf_info(hdr, old_state, &list, &lock); use_mutex = !MUTEX_HELD(lock); if (use_mutex) mutex_enter(lock); - ASSERT(list_link_active(&ab->b_arc_node)); - list_remove(list, ab); + ASSERT(list_link_active(&hdr->b_arc_node)); + list_remove(list, hdr); /* * If prefetching out of the ghost cache, * we will have a non-zero datacnt. */ - if (GHOST_STATE(old_state) && ab->b_datacnt == 0) { + if (GHOST_STATE(old_state) && hdr->b_datacnt == 0) { /* ghost elements have a ghost size */ - ASSERT(ab->b_buf == NULL); - from_delta = ab->b_size; + ASSERT(hdr->b_buf == NULL); + from_delta = hdr->b_size; } ASSERT3U(*size, >=, from_delta); atomic_add_64(size, -from_delta); @@ -1449,20 +1435,20 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *ab, kmutex_t *hash_lock) } if (new_state != arc_anon) { int use_mutex; - uint64_t *size = &new_state->arcs_lsize[ab->b_type]; + uint64_t *size = &new_state->arcs_lsize[hdr->b_type]; - get_buf_info(ab, new_state, &list, &lock); + get_buf_info(hdr, new_state, &list, &lock); use_mutex = !MUTEX_HELD(lock); if (use_mutex) mutex_enter(lock); - list_insert_head(list, ab); + list_insert_head(list, hdr); /* ghost elements have a ghost size */ if (GHOST_STATE(new_state)) { - ASSERT(ab->b_datacnt == 0); - ASSERT(ab->b_buf == NULL); - to_delta = ab->b_size; + ASSERT(hdr->b_datacnt == 0); + ASSERT(hdr->b_buf == NULL); + to_delta = hdr->b_size; } atomic_add_64(size, to_delta); @@ -1471,9 +1457,9 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *ab, kmutex_t *hash_lock) } } - ASSERT(!BUF_EMPTY(ab)); - if (new_state == arc_anon && HDR_IN_HASH_TABLE(ab)) - buf_hash_remove(ab); + ASSERT(!BUF_EMPTY(hdr)); + if (new_state == arc_anon && HDR_IN_HASH_TABLE(hdr)) + buf_hash_remove(hdr); /* adjust state sizes */ if (to_delta) @@ -1482,7 +1468,7 @@ arc_change_state(arc_state_t *new_state, arc_buf_hdr_t *ab, kmutex_t *hash_lock) ASSERT3U(old_state->arcs_size, >=, from_delta); atomic_add_64(&old_state->arcs_size, -from_delta); } - ab->b_state = new_state; + hdr->b_state = new_state; /* adjust l2arc hdr stats */ if (new_state == arc_l2c_only) @@ -1684,7 +1670,7 @@ arc_buf_add_ref(arc_buf_t *buf, void* tag) arc_access(hdr, hash_lock); mutex_exit(hash_lock); ARCSTAT_BUMP(arcstat_hits); - ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_PREFETCH), + ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH), demand, prefetch, hdr->b_type != ARC_BUFC_METADATA, data, metadata, hits); } @@ -1915,7 +1901,7 @@ arc_buf_free(arc_buf_t *buf, void *tag) } else { ASSERT(buf == hdr->b_buf); ASSERT(buf->b_efunc == NULL); - hdr->b_flags |= ARC_BUF_AVAILABLE; + hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE; } mutex_exit(hash_lock); } else if (HDR_IO_IN_PROGRESS(hdr)) { @@ -1966,7 +1952,7 @@ arc_buf_remove_ref(arc_buf_t *buf, void* tag) } else if (no_callback) { ASSERT(hdr->b_buf == buf && buf->b_next == NULL); ASSERT(buf->b_efunc == NULL); - hdr->b_flags |= ARC_BUF_AVAILABLE; + hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE; } ASSERT(no_callback || hdr->b_datacnt > 1 || refcount_is_zero(&hdr->b_refcnt)); @@ -2042,7 +2028,7 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle, arc_state_t *evicted_state; uint64_t bytes_evicted = 0, skipped = 0, missed = 0; int64_t bytes_remaining; - arc_buf_hdr_t *ab, *ab_prev = NULL; + arc_buf_hdr_t *hdr, *hdr_prev = NULL; list_t *evicted_list, *list, *evicted_list_start, *list_start; kmutex_t *lock, *evicted_lock; kmutex_t *hash_lock; @@ -2057,6 +2043,49 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle, evicted_state = (state == arc_mru) ? arc_mru_ghost : arc_mfu_ghost; + /* + * Decide which "type" (data vs metadata) to recycle from. + * + * If we are over the metadata limit, recycle from metadata. + * If we are under the metadata minimum, recycle from data. + * Otherwise, recycle from whichever type has the oldest (least + * recently accessed) header. This is not yet implemented. + */ + if (recycle) { + arc_buf_contents_t realtype; + if (state->arcs_lsize[ARC_BUFC_DATA] == 0) { + realtype = ARC_BUFC_METADATA; + } else if (state->arcs_lsize[ARC_BUFC_METADATA] == 0) { + realtype = ARC_BUFC_DATA; + } else if (arc_meta_used >= arc_meta_limit) { + realtype = ARC_BUFC_METADATA; + } else if (arc_meta_used <= arc_meta_min) { + realtype = ARC_BUFC_DATA; + } else { +#ifdef illumos + if (data_hdr->b_arc_access < + metadata_hdr->b_arc_access) { + realtype = ARC_BUFC_DATA; + } else { + realtype = ARC_BUFC_METADATA; + } +#else + /* TODO */ + realtype = type; +#endif + } + if (realtype != type) { + /* + * If we want to evict from a different list, + * we can not recycle, because DATA vs METADATA + * buffers are segregated into different kmem + * caches (and vmem arenas). + */ + type = realtype; + recycle = B_FALSE; + } + } + if (type == ARC_BUFC_METADATA) { offset = 0; list_count = ARC_BUFC_NUMMETADATALISTS; @@ -2082,25 +2111,25 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle, mutex_enter(lock); mutex_enter(evicted_lock); - for (ab = list_tail(list); ab; ab = ab_prev) { - ab_prev = list_prev(list, ab); - bytes_remaining -= (ab->b_size * ab->b_datacnt); + for (hdr = list_tail(list); hdr; hdr = hdr_prev) { + hdr_prev = list_prev(list, hdr); + bytes_remaining -= (hdr->b_size * hdr->b_datacnt); /* prefetch buffers have a minimum lifespan */ - if (HDR_IO_IN_PROGRESS(ab) || - (spa && ab->b_spa != spa) || - (ab->b_flags & (ARC_PREFETCH|ARC_INDIRECT) && - ddi_get_lbolt() - ab->b_arc_access < + if (HDR_IO_IN_PROGRESS(hdr) || + (spa && hdr->b_spa != spa) || + (hdr->b_flags & (ARC_FLAG_PREFETCH | ARC_FLAG_INDIRECT) && + ddi_get_lbolt() - hdr->b_arc_access < arc_min_prefetch_lifespan)) { skipped++; continue; } /* "lookahead" for better eviction candidate */ - if (recycle && ab->b_size != bytes && - ab_prev && ab_prev->b_size == bytes) + if (recycle && hdr->b_size != bytes && + hdr_prev && hdr_prev->b_size == bytes) continue; /* ignore markers */ - if (ab->b_spa == 0) + if (hdr->b_spa == 0) continue; /* @@ -2113,34 +2142,34 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle, * the hot code path, so don't sleep. */ if (!recycle && count++ > arc_evict_iterations) { - list_insert_after(list, ab, &marker); + list_insert_after(list, hdr, &marker); mutex_exit(evicted_lock); mutex_exit(lock); kpreempt(KPREEMPT_SYNC); mutex_enter(lock); mutex_enter(evicted_lock); - ab_prev = list_prev(list, &marker); + hdr_prev = list_prev(list, &marker); list_remove(list, &marker); count = 0; continue; } - hash_lock = HDR_LOCK(ab); + hash_lock = HDR_LOCK(hdr); have_lock = MUTEX_HELD(hash_lock); if (have_lock || mutex_tryenter(hash_lock)) { - ASSERT0(refcount_count(&ab->b_refcnt)); - ASSERT(ab->b_datacnt > 0); - while (ab->b_buf) { - arc_buf_t *buf = ab->b_buf; + ASSERT0(refcount_count(&hdr->b_refcnt)); + ASSERT(hdr->b_datacnt > 0); + while (hdr->b_buf) { + arc_buf_t *buf = hdr->b_buf; if (!mutex_tryenter(&buf->b_evict_lock)) { missed += 1; break; } if (buf->b_data) { - bytes_evicted += ab->b_size; - if (recycle && ab->b_type == type && - ab->b_size == bytes && - !HDR_L2_WRITING(ab)) { + bytes_evicted += hdr->b_size; + if (recycle && hdr->b_type == type && + hdr->b_size == bytes && + !HDR_L2_WRITING(hdr)) { stolen = buf->b_data; recycle = FALSE; } @@ -2149,7 +2178,7 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle, mutex_enter(&arc_eviction_mtx); arc_buf_destroy(buf, buf->b_data == stolen, FALSE); - ab->b_buf = buf->b_next; + hdr->b_buf = buf->b_next; buf->b_hdr = &arc_eviction_hdr; buf->b_next = arc_eviction_list; arc_eviction_list = buf; @@ -2162,26 +2191,26 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle, } } - if (ab->b_l2hdr) { + if (hdr->b_l2hdr) { ARCSTAT_INCR(arcstat_evict_l2_cached, - ab->b_size); + hdr->b_size); } else { - if (l2arc_write_eligible(ab->b_spa, ab)) { + if (l2arc_write_eligible(hdr->b_spa, hdr)) { ARCSTAT_INCR(arcstat_evict_l2_eligible, - ab->b_size); + hdr->b_size); } else { ARCSTAT_INCR( arcstat_evict_l2_ineligible, - ab->b_size); + hdr->b_size); } } - if (ab->b_datacnt == 0) { - arc_change_state(evicted_state, ab, hash_lock); - ASSERT(HDR_IN_HASH_TABLE(ab)); - ab->b_flags |= ARC_IN_HASH_TABLE; - ab->b_flags &= ~ARC_BUF_AVAILABLE; - DTRACE_PROBE1(arc__evict, arc_buf_hdr_t *, ab); + if (hdr->b_datacnt == 0) { + arc_change_state(evicted_state, hdr, hash_lock); + ASSERT(HDR_IN_HASH_TABLE(hdr)); + hdr->b_flags |= ARC_FLAG_IN_HASH_TABLE; + hdr->b_flags &= ~ARC_FLAG_BUF_AVAILABLE; + DTRACE_PROBE1(arc__evict, arc_buf_hdr_t *, hdr); } if (!have_lock) mutex_exit(hash_lock); @@ -2242,7 +2271,7 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle, static void arc_evict_ghost(arc_state_t *state, uint64_t spa, int64_t bytes) { - arc_buf_hdr_t *ab, *ab_prev; + arc_buf_hdr_t *hdr, *hdr_prev; arc_buf_hdr_t marker = { 0 }; list_t *list, *list_start; kmutex_t *hash_lock, *lock; @@ -2267,18 +2296,18 @@ arc_evict_ghost(arc_state_t *state, uint64_t spa, int64_t bytes) lock = ARCS_LOCK(state, idx + offset); mutex_enter(lock); - for (ab = list_tail(list); ab; ab = ab_prev) { - ab_prev = list_prev(list, ab); - if (ab->b_type > ARC_BUFC_NUMTYPES) - panic("invalid ab=%p", (void *)ab); - if (spa && ab->b_spa != spa) + for (hdr = list_tail(list); hdr; hdr = hdr_prev) { + hdr_prev = list_prev(list, hdr); + if (hdr->b_type > ARC_BUFC_NUMTYPES) + panic("invalid hdr=%p", (void *)hdr); + if (spa && hdr->b_spa != spa) continue; /* ignore markers */ - if (ab->b_spa == 0) + if (hdr->b_spa == 0) continue; - hash_lock = HDR_LOCK(ab); + hash_lock = HDR_LOCK(hdr); /* caller may be trying to modify this buffer, skip it */ if (MUTEX_HELD(hash_lock)) continue; @@ -2290,35 +2319,35 @@ arc_evict_ghost(arc_state_t *state, uint64_t spa, int64_t bytes) * before reacquiring the lock. */ if (count++ > arc_evict_iterations) { - list_insert_after(list, ab, &marker); + list_insert_after(list, hdr, &marker); mutex_exit(lock); kpreempt(KPREEMPT_SYNC); mutex_enter(lock); - ab_prev = list_prev(list, &marker); + hdr_prev = list_prev(list, &marker); list_remove(list, &marker); count = 0; continue; } if (mutex_tryenter(hash_lock)) { - ASSERT(!HDR_IO_IN_PROGRESS(ab)); - ASSERT(ab->b_buf == NULL); + ASSERT(!HDR_IO_IN_PROGRESS(hdr)); + ASSERT(hdr->b_buf == NULL); ARCSTAT_BUMP(arcstat_deleted); - bytes_deleted += ab->b_size; + bytes_deleted += hdr->b_size; - if (ab->b_l2hdr != NULL) { + if (hdr->b_l2hdr != NULL) { /* * This buffer is cached on the 2nd Level ARC; * don't destroy the header. */ - arc_change_state(arc_l2c_only, ab, hash_lock); + arc_change_state(arc_l2c_only, hdr, hash_lock); mutex_exit(hash_lock); } else { - arc_change_state(arc_anon, ab, hash_lock); + arc_change_state(arc_anon, hdr, hash_lock); mutex_exit(hash_lock); - arc_hdr_destroy(ab); + arc_hdr_destroy(hdr); } - DTRACE_PROBE1(arc__delete, arc_buf_hdr_t *, ab); + DTRACE_PROBE1(arc__delete, arc_buf_hdr_t *, hdr); if (bytes >= 0 && bytes_deleted >= bytes) break; } else if (bytes < 0) { @@ -2327,12 +2356,12 @@ arc_evict_ghost(arc_state_t *state, uint64_t spa, int64_t bytes) * hash lock to become available. Once its * available, restart from where we left off. */ - list_insert_after(list, ab, &marker); + list_insert_after(list, hdr, &marker); mutex_exit(lock); mutex_enter(hash_lock); mutex_exit(hash_lock); mutex_enter(lock); - ab_prev = list_prev(list, &marker); + hdr_prev = list_prev(list, &marker); list_remove(list, &marker); } else { bufs_skipped += 1; @@ -2917,7 +2946,8 @@ arc_get_data_buf(arc_buf_t *buf) * will end up on the mru list; so steal space from there. */ if (state == arc_mfu_ghost) - state = buf->b_hdr->b_flags & ARC_PREFETCH ? arc_mru : arc_mfu; + state = buf->b_hdr->b_flags & ARC_FLAG_PREFETCH ? + arc_mru : arc_mfu; else if (state == arc_mru_ghost) state = arc_mru; @@ -2973,25 +3003,25 @@ arc_get_data_buf(arc_buf_t *buf) * NOTE: the hash lock is dropped in this function. */ static void -arc_access(arc_buf_hdr_t *buf, kmutex_t *hash_lock) +arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock) { clock_t now; ASSERT(MUTEX_HELD(hash_lock)); - if (buf->b_state == arc_anon) { + if (hdr->b_state == arc_anon) { /* * This buffer is not in the cache, and does not * appear in our "ghost" list. Add the new buffer * to the MRU state. */ - ASSERT(buf->b_arc_access == 0); - buf->b_arc_access = ddi_get_lbolt(); - DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, buf); - arc_change_state(arc_mru, buf, hash_lock); + ASSERT(hdr->b_arc_access == 0); + hdr->b_arc_access = ddi_get_lbolt(); + DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr); + arc_change_state(arc_mru, hdr, hash_lock); - } else if (buf->b_state == arc_mru) { + } else if (hdr->b_state == arc_mru) { now = ddi_get_lbolt(); /* @@ -3002,14 +3032,14 @@ arc_access(arc_buf_hdr_t *buf, kmutex_t *hash_lock) * - move the buffer to the head of the list if this is * another prefetch (to make it less likely to be evicted). */ - if ((buf->b_flags & ARC_PREFETCH) != 0) { - if (refcount_count(&buf->b_refcnt) == 0) { - ASSERT(list_link_active(&buf->b_arc_node)); + if ((hdr->b_flags & ARC_FLAG_PREFETCH) != 0) { + if (refcount_count(&hdr->b_refcnt) == 0) { + ASSERT(list_link_active(&hdr->b_arc_node)); } else { - buf->b_flags &= ~ARC_PREFETCH; + hdr->b_flags &= ~ARC_FLAG_PREFETCH; ARCSTAT_BUMP(arcstat_mru_hits); } - buf->b_arc_access = now; + hdr->b_arc_access = now; return; } @@ -3018,18 +3048,18 @@ arc_access(arc_buf_hdr_t *buf, kmutex_t *hash_lock) * but it is still in the cache. Move it to the MFU * state. */ - if (now > buf->b_arc_access + ARC_MINTIME) { + if (now > hdr->b_arc_access + ARC_MINTIME) { /* * More than 125ms have passed since we * instantiated this buffer. Move it to the * most frequently used state. */ - buf->b_arc_access = now; - DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, buf); - arc_change_state(arc_mfu, buf, hash_lock); + hdr->b_arc_access = now; + DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr); + arc_change_state(arc_mfu, hdr, hash_lock); } ARCSTAT_BUMP(arcstat_mru_hits); - } else if (buf->b_state == arc_mru_ghost) { + } else if (hdr->b_state == arc_mru_ghost) { arc_state_t *new_state; /* * This buffer has been "accessed" recently, but @@ -3037,21 +3067,21 @@ arc_access(arc_buf_hdr_t *buf, kmutex_t *hash_lock) * MFU state. */ - if (buf->b_flags & ARC_PREFETCH) { + if (hdr->b_flags & ARC_FLAG_PREFETCH) { new_state = arc_mru; - if (refcount_count(&buf->b_refcnt) > 0) - buf->b_flags &= ~ARC_PREFETCH; - DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, buf); + if (refcount_count(&hdr->b_refcnt) > 0) + hdr->b_flags &= ~ARC_FLAG_PREFETCH; + DTRACE_PROBE1(new_state__mru, arc_buf_hdr_t *, hdr); } else { new_state = arc_mfu; - DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, buf); + DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr); } - buf->b_arc_access = ddi_get_lbolt(); - arc_change_state(new_state, buf, hash_lock); + hdr->b_arc_access = ddi_get_lbolt(); + arc_change_state(new_state, hdr, hash_lock); ARCSTAT_BUMP(arcstat_mru_ghost_hits); - } else if (buf->b_state == arc_mfu) { + } else if (hdr->b_state == arc_mfu) { /* * This buffer has been accessed more than once and is * still in the cache. Keep it in the MFU state. @@ -3061,13 +3091,13 @@ arc_access(arc_buf_hdr_t *buf, kmutex_t *hash_lock) * If it was a prefetch, we will explicitly move it to * the head of the list now. */ - if ((buf->b_flags & ARC_PREFETCH) != 0) { - ASSERT(refcount_count(&buf->b_refcnt) == 0); - ASSERT(list_link_active(&buf->b_arc_node)); + if ((hdr->b_flags & ARC_FLAG_PREFETCH) != 0) { + ASSERT(refcount_count(&hdr->b_refcnt) == 0); + ASSERT(list_link_active(&hdr->b_arc_node)); } ARCSTAT_BUMP(arcstat_mfu_hits); - buf->b_arc_access = ddi_get_lbolt(); - } else if (buf->b_state == arc_mfu_ghost) { + hdr->b_arc_access = ddi_get_lbolt(); + } else if (hdr->b_state == arc_mfu_ghost) { arc_state_t *new_state = arc_mfu; /* * This buffer has been accessed more than once but has @@ -3075,28 +3105,28 @@ arc_access(arc_buf_hdr_t *buf, kmutex_t *hash_lock) * MFU state. */ - if (buf->b_flags & ARC_PREFETCH) { + if (hdr->b_flags & ARC_FLAG_PREFETCH) { /* * This is a prefetch access... * move this block back to the MRU state. */ - ASSERT0(refcount_count(&buf->b_refcnt)); + ASSERT0(refcount_count(&hdr->b_refcnt)); new_state = arc_mru; } - buf->b_arc_access = ddi_get_lbolt(); - DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, buf); - arc_change_state(new_state, buf, hash_lock); + hdr->b_arc_access = ddi_get_lbolt(); + DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr); + arc_change_state(new_state, hdr, hash_lock); ARCSTAT_BUMP(arcstat_mfu_ghost_hits); - } else if (buf->b_state == arc_l2c_only) { + } else if (hdr->b_state == arc_l2c_only) { /* * This buffer is on the 2nd Level ARC. */ - buf->b_arc_access = ddi_get_lbolt(); - DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, buf); - arc_change_state(arc_mfu, buf, hash_lock); + hdr->b_arc_access = ddi_get_lbolt(); + DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr); + arc_change_state(arc_mfu, hdr, hash_lock); } else { ASSERT(!"invalid arc state"); } @@ -3164,9 +3194,9 @@ arc_read_done(zio_t *zio) (found == hdr && HDR_L2_READING(hdr))); } - hdr->b_flags &= ~ARC_L2_EVICTED; - if (l2arc_noprefetch && (hdr->b_flags & ARC_PREFETCH)) - hdr->b_flags &= ~ARC_L2CACHE; + hdr->b_flags &= ~ARC_FLAG_L2_EVICTED; + if (l2arc_noprefetch && (hdr->b_flags & ARC_FLAG_PREFETCH)) + hdr->b_flags &= ~ARC_FLAG_L2CACHE; /* byteswap if necessary */ callback_list = hdr->b_acb; @@ -3208,18 +3238,18 @@ arc_read_done(zio_t *zio) } } hdr->b_acb = NULL; - hdr->b_flags &= ~ARC_IO_IN_PROGRESS; + hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS; ASSERT(!HDR_BUF_AVAILABLE(hdr)); if (abuf == buf) { ASSERT(buf->b_efunc == NULL); ASSERT(hdr->b_datacnt == 1); - hdr->b_flags |= ARC_BUF_AVAILABLE; + hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE; } ASSERT(refcount_is_zero(&hdr->b_refcnt) || callback_list != NULL); if (zio->io_error != 0) { - hdr->b_flags |= ARC_IO_ERROR; + hdr->b_flags |= ARC_FLAG_IO_ERROR; if (hdr->b_state != arc_anon) arc_change_state(arc_anon, hdr, hash_lock); if (HDR_IN_HASH_TABLE(hdr)) @@ -3285,8 +3315,8 @@ arc_read_done(zio_t *zio) */ int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, - void *private, zio_priority_t priority, int zio_flags, uint32_t *arc_flags, - const zbookmark_phys_t *zb) + void *private, zio_priority_t priority, int zio_flags, + arc_flags_t *arc_flags, const zbookmark_phys_t *zb) { arc_buf_hdr_t *hdr = NULL; arc_buf_t *buf = NULL; @@ -3308,16 +3338,16 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, if (hdr != NULL && hdr->b_datacnt > 0) { - *arc_flags |= ARC_CACHED; + *arc_flags |= ARC_FLAG_CACHED; if (HDR_IO_IN_PROGRESS(hdr)) { - if (*arc_flags & ARC_WAIT) { + if (*arc_flags & ARC_FLAG_WAIT) { cv_wait(&hdr->b_cv, hash_lock); mutex_exit(hash_lock); goto top; } - ASSERT(*arc_flags & ARC_NOWAIT); + ASSERT(*arc_flags & ARC_FLAG_NOWAIT); if (done) { arc_callback_t *acb = NULL; @@ -3355,24 +3385,24 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, ASSERT(buf->b_data); if (HDR_BUF_AVAILABLE(hdr)) { ASSERT(buf->b_efunc == NULL); - hdr->b_flags &= ~ARC_BUF_AVAILABLE; + hdr->b_flags &= ~ARC_FLAG_BUF_AVAILABLE; } else { buf = arc_buf_clone(buf); } - } else if (*arc_flags & ARC_PREFETCH && + } else if (*arc_flags & ARC_FLAG_PREFETCH && refcount_count(&hdr->b_refcnt) == 0) { - hdr->b_flags |= ARC_PREFETCH; + hdr->b_flags |= ARC_FLAG_PREFETCH; } DTRACE_PROBE1(arc__hit, arc_buf_hdr_t *, hdr); arc_access(hdr, hash_lock); - if (*arc_flags & ARC_L2CACHE) - hdr->b_flags |= ARC_L2CACHE; - if (*arc_flags & ARC_L2COMPRESS) - hdr->b_flags |= ARC_L2COMPRESS; + if (*arc_flags & ARC_FLAG_L2CACHE) + hdr->b_flags |= ARC_FLAG_L2CACHE; + if (*arc_flags & ARC_FLAG_L2COMPRESS) + hdr->b_flags |= ARC_FLAG_L2COMPRESS; mutex_exit(hash_lock); ARCSTAT_BUMP(arcstat_hits); - ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_PREFETCH), + ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH), demand, prefetch, hdr->b_type != ARC_BUFC_METADATA, data, metadata, hits); @@ -3406,18 +3436,19 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, (void) arc_buf_remove_ref(buf, private); goto top; /* restart the IO request */ } + /* if this is a prefetch, we don't have a reference */ - if (*arc_flags & ARC_PREFETCH) { + if (*arc_flags & ARC_FLAG_PREFETCH) { (void) remove_reference(hdr, hash_lock, private); - hdr->b_flags |= ARC_PREFETCH; + hdr->b_flags |= ARC_FLAG_PREFETCH; } - if (*arc_flags & ARC_L2CACHE) - hdr->b_flags |= ARC_L2CACHE; - if (*arc_flags & ARC_L2COMPRESS) - hdr->b_flags |= ARC_L2COMPRESS; + if (*arc_flags & ARC_FLAG_L2CACHE) + hdr->b_flags |= ARC_FLAG_L2CACHE; + if (*arc_flags & ARC_FLAG_L2COMPRESS) + hdr->b_flags |= ARC_FLAG_L2COMPRESS; if (BP_GET_LEVEL(bp) > 0) - hdr->b_flags |= ARC_INDIRECT; + hdr->b_flags |= ARC_FLAG_INDIRECT; } else { /* this block is in the ghost cache */ ASSERT(GHOST_STATE(hdr->b_state)); @@ -3426,14 +3457,14 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, ASSERT(hdr->b_buf == NULL); /* if this is a prefetch, we don't have a reference */ - if (*arc_flags & ARC_PREFETCH) - hdr->b_flags |= ARC_PREFETCH; + if (*arc_flags & ARC_FLAG_PREFETCH) + hdr->b_flags |= ARC_FLAG_PREFETCH; else add_reference(hdr, hash_lock, private); - if (*arc_flags & ARC_L2CACHE) - hdr->b_flags |= ARC_L2CACHE; - if (*arc_flags & ARC_L2COMPRESS) - hdr->b_flags |= ARC_L2COMPRESS; + if (*arc_flags & ARC_FLAG_L2CACHE) + hdr->b_flags |= ARC_FLAG_L2CACHE; + if (*arc_flags & ARC_FLAG_L2COMPRESS) + hdr->b_flags |= ARC_FLAG_L2COMPRESS; buf = kmem_cache_alloc(buf_cache, KM_PUSHPAGE); buf->b_hdr = hdr; buf->b_data = NULL; @@ -3455,7 +3486,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, ASSERT(hdr->b_acb == NULL); hdr->b_acb = acb; - hdr->b_flags |= ARC_IO_IN_PROGRESS; + hdr->b_flags |= ARC_FLAG_IO_IN_PROGRESS; if (hdr->b_l2hdr != NULL && (vd = hdr->b_l2hdr->b_dev->l2ad_vdev) != NULL) { @@ -3482,7 +3513,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, DTRACE_PROBE4(arc__miss, arc_buf_hdr_t *, hdr, blkptr_t *, bp, uint64_t, size, zbookmark_phys_t *, zb); ARCSTAT_BUMP(arcstat_misses); - ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_PREFETCH), + ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_FLAG_PREFETCH), demand, prefetch, hdr->b_type != ARC_BUFC_METADATA, data, metadata, misses); #ifdef _KERNEL @@ -3547,12 +3578,12 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, zio_t *, rzio); ARCSTAT_INCR(arcstat_l2_read_bytes, b_asize); - if (*arc_flags & ARC_NOWAIT) { + if (*arc_flags & ARC_FLAG_NOWAIT) { zio_nowait(rzio); return (0); } - ASSERT(*arc_flags & ARC_WAIT); + ASSERT(*arc_flags & ARC_FLAG_WAIT); if (zio_wait(rzio) == 0) return (0); @@ -3578,10 +3609,10 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, rzio = zio_read(pio, spa, bp, buf->b_data, size, arc_read_done, buf, priority, zio_flags, zb); - if (*arc_flags & ARC_WAIT) + if (*arc_flags & ARC_FLAG_WAIT) return (zio_wait(rzio)); - ASSERT(*arc_flags & ARC_NOWAIT); + ASSERT(*arc_flags & ARC_FLAG_NOWAIT); zio_nowait(rzio); } return (0); @@ -3618,7 +3649,7 @@ arc_freed(spa_t *spa, const blkptr_t *bp) if (HDR_BUF_AVAILABLE(hdr)) { arc_buf_t *buf = hdr->b_buf; add_reference(hdr, hash_lock, FTAG); - hdr->b_flags &= ~ARC_BUF_AVAILABLE; + hdr->b_flags &= ~ARC_FLAG_BUF_AVAILABLE; mutex_exit(hash_lock); arc_release(buf, FTAG); @@ -3687,7 +3718,7 @@ arc_clear_callback(arc_buf_t *buf) arc_buf_destroy(buf, FALSE, TRUE); } else { ASSERT(buf == hdr->b_buf); - hdr->b_flags |= ARC_BUF_AVAILABLE; + hdr->b_flags |= ARC_FLAG_BUF_AVAILABLE; mutex_exit(&buf->b_evict_lock); } @@ -3796,7 +3827,7 @@ arc_release(arc_buf_t *buf, void *tag) nhdr->b_buf = buf; nhdr->b_state = arc_anon; nhdr->b_arc_access = 0; - nhdr->b_flags = flags & ARC_L2_WRITING; + nhdr->b_flags = flags & ARC_FLAG_L2_WRITING; nhdr->b_l2hdr = NULL; nhdr->b_datacnt = 1; nhdr->b_freeze_cksum = NULL; @@ -3882,7 +3913,7 @@ arc_write_ready(zio_t *zio) mutex_exit(&hdr->b_freeze_lock); } arc_cksum_compute(buf, B_FALSE); - hdr->b_flags |= ARC_IO_IN_PROGRESS; + hdr->b_flags |= ARC_FLAG_IO_IN_PROGRESS; } /* @@ -3963,13 +3994,13 @@ arc_write_done(zio_t *zio) ASSERT(BP_GET_LEVEL(zio->io_bp) == 0); } } - hdr->b_flags &= ~ARC_IO_IN_PROGRESS; + hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS; /* if it's not anon, we are doing a scrub */ if (!exists && hdr->b_state == arc_anon) arc_access(hdr, hash_lock); mutex_exit(hash_lock); } else { - hdr->b_flags &= ~ARC_IO_IN_PROGRESS; + hdr->b_flags &= ~ARC_FLAG_IO_IN_PROGRESS; } ASSERT(!refcount_is_zero(&hdr->b_refcnt)); @@ -3992,12 +4023,12 @@ arc_write(zio_t *pio, spa_t *spa, uint64_t txg, ASSERT(ready != NULL); ASSERT(done != NULL); ASSERT(!HDR_IO_ERROR(hdr)); - ASSERT((hdr->b_flags & ARC_IO_IN_PROGRESS) == 0); + ASSERT((hdr->b_flags & ARC_FLAG_IO_IN_PROGRESS) == 0); ASSERT(hdr->b_acb == NULL); if (l2arc) - hdr->b_flags |= ARC_L2CACHE; + hdr->b_flags |= ARC_FLAG_L2CACHE; if (l2arc_compress) - hdr->b_flags |= ARC_L2COMPRESS; + hdr->b_flags |= ARC_FLAG_L2COMPRESS; callback = kmem_zalloc(sizeof (arc_write_callback_t), KM_SLEEP); callback->awcb_ready = ready; callback->awcb_physdone = physdone; @@ -4198,6 +4229,12 @@ arc_init(void) if (arc_c_min < arc_meta_limit / 2 && zfs_arc_min == 0) arc_c_min = arc_meta_limit / 2; + if (zfs_arc_meta_min > 0) { + arc_meta_min = zfs_arc_meta_min; + } else { + arc_meta_min = arc_c_min / 2; + } + if (zfs_arc_grow_retry > 0) arc_grow_retry = zfs_arc_grow_retry; @@ -4527,7 +4564,7 @@ arc_fini(void) */ static boolean_t -l2arc_write_eligible(uint64_t spa_guid, arc_buf_hdr_t *ab) +l2arc_write_eligible(uint64_t spa_guid, arc_buf_hdr_t *hdr) { /* * A buffer is *not* eligible for the L2ARC if it: @@ -4536,19 +4573,19 @@ l2arc_write_eligible(uint64_t spa_guid, arc_buf_hdr_t *ab) * 3. has an I/O in progress (it may be an incomplete read). * 4. is flagged not eligible (zfs property). */ - if (ab->b_spa != spa_guid) { + if (hdr->b_spa != spa_guid) { ARCSTAT_BUMP(arcstat_l2_write_spa_mismatch); return (B_FALSE); } - if (ab->b_l2hdr != NULL) { + if (hdr->b_l2hdr != NULL) { ARCSTAT_BUMP(arcstat_l2_write_in_l2); return (B_FALSE); } - if (HDR_IO_IN_PROGRESS(ab)) { + if (HDR_IO_IN_PROGRESS(hdr)) { ARCSTAT_BUMP(arcstat_l2_write_hdr_io_in_progress); return (B_FALSE); } - if (!HDR_L2CACHE(ab)) { + if (!HDR_L2CACHE(hdr)) { ARCSTAT_BUMP(arcstat_l2_write_not_cacheable); return (B_FALSE); } @@ -4711,7 +4748,7 @@ l2arc_write_done(zio_t *zio) l2arc_write_callback_t *cb; l2arc_dev_t *dev; list_t *buflist; - arc_buf_hdr_t *head, *ab, *ab_prev; + arc_buf_hdr_t *head, *hdr, *hdr_prev; l2arc_buf_hdr_t *abl2; kmutex_t *hash_lock; int64_t bytes_dropped = 0; @@ -4735,17 +4772,17 @@ l2arc_write_done(zio_t *zio) /* * All writes completed, or an error was hit. */ - for (ab = list_prev(buflist, head); ab; ab = ab_prev) { - ab_prev = list_prev(buflist, ab); - abl2 = ab->b_l2hdr; + for (hdr = list_prev(buflist, head); hdr; hdr = hdr_prev) { + hdr_prev = list_prev(buflist, hdr); + abl2 = hdr->b_l2hdr; /* * Release the temporary compressed buffer as soon as possible. */ if (abl2->b_compress != ZIO_COMPRESS_OFF) - l2arc_release_cdata_buf(ab); + l2arc_release_cdata_buf(hdr); - hash_lock = HDR_LOCK(ab); + hash_lock = HDR_LOCK(hdr); if (!mutex_tryenter(hash_lock)) { /* * This buffer misses out. It may be in a stage @@ -4760,20 +4797,20 @@ l2arc_write_done(zio_t *zio) /* * Error - drop L2ARC entry. */ - list_remove(buflist, ab); + list_remove(buflist, hdr); ARCSTAT_INCR(arcstat_l2_asize, -abl2->b_asize); bytes_dropped += abl2->b_asize; - ab->b_l2hdr = NULL; + hdr->b_l2hdr = NULL; trim_map_free(abl2->b_dev->l2ad_vdev, abl2->b_daddr, - ab->b_size, 0); + hdr->b_size, 0); kmem_free(abl2, sizeof (l2arc_buf_hdr_t)); - ARCSTAT_INCR(arcstat_l2_size, -ab->b_size); + ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); } /* * Allow ARC to begin reads to this L2ARC entry. */ - ab->b_flags &= ~ARC_L2_WRITING; + hdr->b_flags &= ~ARC_FLAG_L2_WRITING; mutex_exit(hash_lock); } @@ -4921,7 +4958,7 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all) { list_t *buflist; l2arc_buf_hdr_t *abl2; - arc_buf_hdr_t *ab, *ab_prev; + arc_buf_hdr_t *hdr, *hdr_prev; kmutex_t *hash_lock; uint64_t taddr; int64_t bytes_evicted = 0; @@ -4953,10 +4990,10 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all) top: mutex_enter(&l2arc_buflist_mtx); - for (ab = list_tail(buflist); ab; ab = ab_prev) { - ab_prev = list_prev(buflist, ab); + for (hdr = list_tail(buflist); hdr; hdr = hdr_prev) { + hdr_prev = list_prev(buflist, hdr); - hash_lock = HDR_LOCK(ab); + hash_lock = HDR_LOCK(hdr); if (!mutex_tryenter(hash_lock)) { /* * Missed the hash lock. Retry. @@ -4968,19 +5005,19 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all) goto top; } - if (HDR_L2_WRITE_HEAD(ab)) { + if (HDR_L2_WRITE_HEAD(hdr)) { /* * We hit a write head node. Leave it for * l2arc_write_done(). */ - list_remove(buflist, ab); + list_remove(buflist, hdr); mutex_exit(hash_lock); continue; } - if (!all && ab->b_l2hdr != NULL && - (ab->b_l2hdr->b_daddr > taddr || - ab->b_l2hdr->b_daddr < dev->l2ad_hand)) { + if (!all && hdr->b_l2hdr != NULL && + (hdr->b_l2hdr->b_daddr > taddr || + hdr->b_l2hdr->b_daddr < dev->l2ad_hand)) { /* * We've evicted to the target address, * or the end of the device. @@ -4989,7 +5026,7 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all) break; } - if (HDR_FREE_IN_PROGRESS(ab)) { + if (HDR_FREE_IN_PROGRESS(hdr)) { /* * Already on the path to destruction. */ @@ -4997,49 +5034,49 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all) continue; } - if (ab->b_state == arc_l2c_only) { - ASSERT(!HDR_L2_READING(ab)); + if (hdr->b_state == arc_l2c_only) { + ASSERT(!HDR_L2_READING(hdr)); /* * This doesn't exist in the ARC. Destroy. * arc_hdr_destroy() will call list_remove() * and decrement arcstat_l2_size. */ - arc_change_state(arc_anon, ab, hash_lock); - arc_hdr_destroy(ab); + arc_change_state(arc_anon, hdr, hash_lock); + arc_hdr_destroy(hdr); } else { /* * Invalidate issued or about to be issued * reads, since we may be about to write * over this location. */ - if (HDR_L2_READING(ab)) { + if (HDR_L2_READING(hdr)) { ARCSTAT_BUMP(arcstat_l2_evict_reading); - ab->b_flags |= ARC_L2_EVICTED; + hdr->b_flags |= ARC_FLAG_L2_EVICTED; } /* * Tell ARC this no longer exists in L2ARC. */ - if (ab->b_l2hdr != NULL) { - abl2 = ab->b_l2hdr; + if (hdr->b_l2hdr != NULL) { + abl2 = hdr->b_l2hdr; ARCSTAT_INCR(arcstat_l2_asize, -abl2->b_asize); bytes_evicted += abl2->b_asize; - ab->b_l2hdr = NULL; + hdr->b_l2hdr = NULL; /* * We are destroying l2hdr, so ensure that * its compressed buffer, if any, is not leaked. */ ASSERT(abl2->b_tmp_cdata == NULL); kmem_free(abl2, sizeof (l2arc_buf_hdr_t)); - ARCSTAT_INCR(arcstat_l2_size, -ab->b_size); + ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size); } - list_remove(buflist, ab); + list_remove(buflist, hdr); /* * This may have been leftover after a * failed write. */ - ab->b_flags &= ~ARC_L2_WRITING; + hdr->b_flags &= ~ARC_FLAG_L2_WRITING; } mutex_exit(hash_lock); } @@ -5052,7 +5089,7 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all) /* * Find and write ARC buffers to the L2ARC device. * - * An ARC_L2_WRITING flag is set so that the L2ARC buffers are not valid + * An ARC_FLAG_L2_WRITING flag is set so that the L2ARC buffers are not valid * for reading until they have completed writing. * The headroom_boost is an in-out parameter used to maintain headroom boost * state between calls to this function. @@ -5064,7 +5101,7 @@ static uint64_t l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz, boolean_t *headroom_boost) { - arc_buf_hdr_t *ab, *ab_prev, *head; + arc_buf_hdr_t *hdr, *hdr_prev, *head; list_t *list; uint64_t write_asize, write_psize, write_sz, headroom, buf_compress_minsz; @@ -5086,7 +5123,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz, write_sz = write_asize = write_psize = 0; full = B_FALSE; head = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE); - head->b_flags |= ARC_L2_WRITE_HEAD; + head->b_flags |= ARC_FLAG_L2_WRITE_HEAD; ARCSTAT_BUMP(arcstat_l2_write_buffer_iter); /* @@ -5112,28 +5149,28 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz, * head of the ARC lists rather than the tail. */ if (arc_warm == B_FALSE) - ab = list_head(list); + hdr = list_head(list); else - ab = list_tail(list); - if (ab == NULL) + hdr = list_tail(list); + if (hdr == NULL) ARCSTAT_BUMP(arcstat_l2_write_buffer_list_null_iter); headroom = target_sz * l2arc_headroom * 2 / ARC_BUFC_NUMLISTS; if (do_headroom_boost) headroom = (headroom * l2arc_headroom_boost) / 100; - for (; ab; ab = ab_prev) { + for (; hdr; hdr = hdr_prev) { l2arc_buf_hdr_t *l2hdr; kmutex_t *hash_lock; uint64_t buf_sz; if (arc_warm == B_FALSE) - ab_prev = list_next(list, ab); + hdr_prev = list_next(list, hdr); else - ab_prev = list_prev(list, ab); - ARCSTAT_INCR(arcstat_l2_write_buffer_bytes_scanned, ab->b_size); + hdr_prev = list_prev(list, hdr); + ARCSTAT_INCR(arcstat_l2_write_buffer_bytes_scanned, hdr->b_size); - hash_lock = HDR_LOCK(ab); + hash_lock = HDR_LOCK(hdr); if (!mutex_tryenter(hash_lock)) { ARCSTAT_BUMP(arcstat_l2_write_trylock_fail); /* @@ -5142,7 +5179,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz, continue; } - passed_sz += ab->b_size; + passed_sz += hdr->b_size; if (passed_sz > headroom) { /* * Searched too far. @@ -5152,12 +5189,12 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz, break; } - if (!l2arc_write_eligible(guid, ab)) { + if (!l2arc_write_eligible(guid, hdr)) { mutex_exit(hash_lock); continue; } - if ((write_sz + ab->b_size) > target_sz) { + if ((write_sz + hdr->b_size) > target_sz) { full = B_TRUE; mutex_exit(hash_lock); ARCSTAT_BUMP(arcstat_l2_write_full); @@ -5186,31 +5223,31 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz, */ l2hdr = kmem_zalloc(sizeof (l2arc_buf_hdr_t), KM_SLEEP); l2hdr->b_dev = dev; - ab->b_flags |= ARC_L2_WRITING; + hdr->b_flags |= ARC_FLAG_L2_WRITING; /* * Temporarily stash the data buffer in b_tmp_cdata. * The subsequent write step will pick it up from - * there. This is because can't access ab->b_buf + * there. This is because can't access hdr->b_buf * without holding the hash_lock, which we in turn * can't access without holding the ARC list locks * (which we want to avoid during compression/writing). */ l2hdr->b_compress = ZIO_COMPRESS_OFF; - l2hdr->b_asize = ab->b_size; - l2hdr->b_tmp_cdata = ab->b_buf->b_data; + l2hdr->b_asize = hdr->b_size; + l2hdr->b_tmp_cdata = hdr->b_buf->b_data; - buf_sz = ab->b_size; - ab->b_l2hdr = l2hdr; + buf_sz = hdr->b_size; + hdr->b_l2hdr = l2hdr; - list_insert_head(dev->l2ad_buflist, ab); + list_insert_head(dev->l2ad_buflist, hdr); /* * Compute and store the buffer cksum before * writing. On debug the cksum is verified first. */ - arc_cksum_verify(ab->b_buf); - arc_cksum_compute(ab->b_buf, B_TRUE); + arc_cksum_verify(hdr->b_buf); + arc_cksum_compute(hdr->b_buf, B_TRUE); mutex_exit(hash_lock); @@ -5236,21 +5273,22 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz, * and work backwards, retracing the course of the buffer selector * loop above. */ - for (ab = list_prev(dev->l2ad_buflist, head); ab; - ab = list_prev(dev->l2ad_buflist, ab)) { + for (hdr = list_prev(dev->l2ad_buflist, head); hdr; + hdr = list_prev(dev->l2ad_buflist, hdr)) { l2arc_buf_hdr_t *l2hdr; uint64_t buf_sz; /* * We shouldn't need to lock the buffer here, since we flagged - * it as ARC_L2_WRITING in the previous step, but we must take - * care to only access its L2 cache parameters. In particular, - * ab->b_buf may be invalid by now due to ARC eviction. + * it as ARC_FLAG_L2_WRITING in the previous step, but we must + * take care to only access its L2 cache parameters. In + * particular, hdr->b_buf may be invalid by now due to + * ARC eviction. */ - l2hdr = ab->b_l2hdr; + l2hdr = hdr->b_l2hdr; l2hdr->b_daddr = dev->l2ad_hand; - if ((ab->b_flags & ARC_L2COMPRESS) && + if ((hdr->b_flags & ARC_FLAG_L2COMPRESS) && l2hdr->b_asize >= buf_compress_minsz) { if (l2arc_compress_buf(l2hdr)) { /* @@ -5464,9 +5502,9 @@ l2arc_decompress_zio(zio_t *zio, arc_buf_hdr_t *hdr, enum zio_compress c) * done, we can dispose of it. */ static void -l2arc_release_cdata_buf(arc_buf_hdr_t *ab) +l2arc_release_cdata_buf(arc_buf_hdr_t *hdr) { - l2arc_buf_hdr_t *l2hdr = ab->b_l2hdr; + l2arc_buf_hdr_t *l2hdr = hdr->b_l2hdr; ASSERT(L2ARC_IS_VALID_COMPRESS(l2hdr->b_compress)); if (l2hdr->b_compress != ZIO_COMPRESS_EMPTY) { @@ -5475,7 +5513,7 @@ l2arc_release_cdata_buf(arc_buf_hdr_t *ab) * temporary buffer for it, so now we need to release it. */ ASSERT(l2hdr->b_tmp_cdata != NULL); - zio_data_buf_free(l2hdr->b_tmp_cdata, ab->b_size); + zio_data_buf_free(l2hdr->b_tmp_cdata, hdr->b_size); l2hdr->b_tmp_cdata = NULL; } else { ASSERT(l2hdr->b_tmp_cdata == NULL); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c index 0b9a0b92434a..ea3c688c1344 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c @@ -223,11 +223,8 @@ dbuf_evict_user(dmu_buf_impl_t *db) if (db->db_level != 0 || db->db_evict_func == NULL) return; - if (db->db_user_data_ptr_ptr) - *db->db_user_data_ptr_ptr = db->db.db_data; db->db_evict_func(&db->db, db->db_user_ptr); db->db_user_ptr = NULL; - db->db_user_data_ptr_ptr = NULL; db->db_evict_func = NULL; } @@ -417,16 +414,6 @@ dbuf_verify(dmu_buf_impl_t *db) } #endif -static void -dbuf_update_data(dmu_buf_impl_t *db) -{ - ASSERT(MUTEX_HELD(&db->db_mtx)); - if (db->db_level == 0 && db->db_user_data_ptr_ptr) { - ASSERT(!refcount_is_zero(&db->db_holds)); - *db->db_user_data_ptr_ptr = db->db.db_data; - } -} - static void dbuf_set_data(dmu_buf_impl_t *db, arc_buf_t *buf) { @@ -437,7 +424,6 @@ dbuf_set_data(dmu_buf_impl_t *db, arc_buf_t *buf) db->db.db_data = buf->b_data; if (!arc_released(buf)) arc_set_callback(buf, dbuf_do_evict, db); - dbuf_update_data(db); } else { dbuf_evict_user(db); db->db.db_data = NULL; @@ -521,7 +507,7 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) { dnode_t *dn; zbookmark_phys_t zb; - uint32_t aflags = ARC_NOWAIT; + arc_flags_t aflags = ARC_FLAG_NOWAIT; DB_DNODE_ENTER(db); dn = DB_DNODE(db); @@ -543,7 +529,6 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) if (bonuslen) bcopy(DN_BONUS(dn->dn_phys), db->db.db_data, bonuslen); DB_DNODE_EXIT(db); - dbuf_update_data(db); db->db_state = DB_CACHED; mutex_exit(&db->db_mtx); return; @@ -575,9 +560,9 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) mutex_exit(&db->db_mtx); if (DBUF_IS_L2CACHEABLE(db)) - aflags |= ARC_L2CACHE; + aflags |= ARC_FLAG_L2CACHE; if (DBUF_IS_L2COMPRESSIBLE(db)) - aflags |= ARC_L2COMPRESS; + aflags |= ARC_FLAG_L2COMPRESS; SET_BOOKMARK(&zb, db->db_objset->os_dsl_dataset ? db->db_objset->os_dsl_dataset->ds_object : DMU_META_OBJSET, @@ -589,7 +574,7 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) dbuf_read_done, db, ZIO_PRIORITY_SYNC_READ, (*flags & DB_RF_CANFAIL) ? ZIO_FLAG_CANFAIL : ZIO_FLAG_MUSTSUCCEED, &aflags, &zb); - if (aflags & ARC_CACHED) + if (aflags & ARC_FLAG_CACHED) *flags |= DB_RF_CACHED; } @@ -1726,7 +1711,6 @@ dbuf_create(dnode_t *dn, uint8_t level, uint64_t blkid, db->db_blkptr = blkptr; db->db_user_ptr = NULL; - db->db_user_data_ptr_ptr = NULL; db->db_evict_func = NULL; db->db_immediate_evict = 0; db->db_freed_in_flight = 0; @@ -1879,7 +1863,8 @@ dbuf_prefetch(dnode_t *dn, uint64_t blkid, zio_priority_t prio) if (dbuf_findbp(dn, 0, blkid, TRUE, &db, &bp) == 0) { if (bp && !BP_IS_HOLE(bp) && !BP_IS_EMBEDDED(bp)) { dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset; - uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH; + arc_flags_t aflags = + ARC_FLAG_NOWAIT | ARC_FLAG_PREFETCH; zbookmark_phys_t zb; SET_BOOKMARK(&zb, ds ? ds->ds_object : DMU_META_OBJSET, @@ -1971,7 +1956,6 @@ dbuf_hold_impl(dnode_t *dn, uint8_t level, uint64_t blkid, int fail_sparse, } (void) refcount_add(&db->db_holds, tag); - dbuf_update_data(db); DBUF_VERIFY(db); mutex_exit(&db->db_mtx); @@ -2182,27 +2166,25 @@ dbuf_refcount(dmu_buf_impl_t *db) } void * -dmu_buf_set_user(dmu_buf_t *db_fake, void *user_ptr, void *user_data_ptr_ptr, +dmu_buf_set_user(dmu_buf_t *db_fake, void *user_ptr, dmu_buf_evict_func_t *evict_func) { - return (dmu_buf_update_user(db_fake, NULL, user_ptr, - user_data_ptr_ptr, evict_func)); + return (dmu_buf_update_user(db_fake, NULL, user_ptr, evict_func)); } void * -dmu_buf_set_user_ie(dmu_buf_t *db_fake, void *user_ptr, void *user_data_ptr_ptr, +dmu_buf_set_user_ie(dmu_buf_t *db_fake, void *user_ptr, dmu_buf_evict_func_t *evict_func) { dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake; db->db_immediate_evict = TRUE; - return (dmu_buf_update_user(db_fake, NULL, user_ptr, - user_data_ptr_ptr, evict_func)); + return (dmu_buf_update_user(db_fake, NULL, user_ptr, evict_func)); } void * dmu_buf_update_user(dmu_buf_t *db_fake, void *old_user_ptr, void *user_ptr, - void *user_data_ptr_ptr, dmu_buf_evict_func_t *evict_func) + dmu_buf_evict_func_t *evict_func) { dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake; ASSERT(db->db_level == 0); @@ -2213,10 +2195,7 @@ dmu_buf_update_user(dmu_buf_t *db_fake, void *old_user_ptr, void *user_ptr, if (db->db_user_ptr == old_user_ptr) { db->db_user_ptr = user_ptr; - db->db_user_data_ptr_ptr = user_data_ptr_ptr; db->db_evict_func = evict_func; - - dbuf_update_data(db); } else { old_user_ptr = db->db_user_ptr; } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c index 39faeb5dae94..bd9e89440817 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c @@ -152,7 +152,7 @@ diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, } else if (zb->zb_level == 0) { dnode_phys_t *blk; arc_buf_t *abuf; - uint32_t aflags = ARC_WAIT; + arc_flags_t aflags = ARC_FLAG_WAIT; int blksz = BP_GET_LSIZE(bp); int i; @@ -221,7 +221,7 @@ dmu_diff(const char *tosnap_name, const char *fromsnap_name, return (SET_ERROR(EXDEV)); } - fromtxg = fromsnap->ds_phys->ds_creation_txg; + fromtxg = dsl_dataset_phys(fromsnap)->ds_creation_txg; dsl_dataset_rele(fromsnap, FTAG); dsl_dataset_long_hold(tosnap, FTAG); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c index e7aeed17fb9d..36ac27a5e0de 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c @@ -293,15 +293,15 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp, os->os_spa = spa; os->os_rootbp = bp; if (!BP_IS_HOLE(os->os_rootbp)) { - uint32_t aflags = ARC_WAIT; + arc_flags_t aflags = ARC_FLAG_WAIT; zbookmark_phys_t zb; SET_BOOKMARK(&zb, ds ? ds->ds_object : DMU_META_OBJSET, ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID); if (DMU_OS_IS_L2CACHEABLE(os)) - aflags |= ARC_L2CACHE; + aflags |= ARC_FLAG_L2CACHE; if (DMU_OS_IS_L2COMPRESSIBLE(os)) - aflags |= ARC_L2COMPRESS; + aflags |= ARC_FLAG_L2COMPRESS; dprintf_bp(os->os_rootbp, "reading %s", ""); err = arc_read(NULL, spa, os->os_rootbp, @@ -1479,12 +1479,12 @@ dmu_snapshot_realname(objset_t *os, char *name, char *real, int maxlen, dsl_dataset_t *ds = os->os_dsl_dataset; uint64_t ignored; - if (ds->ds_phys->ds_snapnames_zapobj == 0) + if (dsl_dataset_phys(ds)->ds_snapnames_zapobj == 0) return (SET_ERROR(ENOENT)); return (zap_lookup_norm(ds->ds_dir->dd_pool->dp_meta_objset, - ds->ds_phys->ds_snapnames_zapobj, name, 8, 1, &ignored, MT_FIRST, - real, maxlen, conflict)); + dsl_dataset_phys(ds)->ds_snapnames_zapobj, name, 8, 1, &ignored, + MT_FIRST, real, maxlen, conflict)); } int @@ -1497,12 +1497,12 @@ dmu_snapshot_list_next(objset_t *os, int namelen, char *name, ASSERT(dsl_pool_config_held(dmu_objset_pool(os))); - if (ds->ds_phys->ds_snapnames_zapobj == 0) + if (dsl_dataset_phys(ds)->ds_snapnames_zapobj == 0) return (SET_ERROR(ENOENT)); zap_cursor_init_serialized(&cursor, ds->ds_dir->dd_pool->dp_meta_objset, - ds->ds_phys->ds_snapnames_zapobj, *offp); + dsl_dataset_phys(ds)->ds_snapnames_zapobj, *offp); if (zap_cursor_retrieve(&cursor, &attr) != 0) { zap_cursor_fini(&cursor); @@ -1536,12 +1536,12 @@ dmu_dir_list_next(objset_t *os, int namelen, char *name, /* there is no next dir on a snapshot! */ if (os->os_dsl_dataset->ds_object != - dd->dd_phys->dd_head_dataset_obj) + dsl_dir_phys(dd)->dd_head_dataset_obj) return (SET_ERROR(ENOENT)); zap_cursor_init_serialized(&cursor, dd->dd_pool->dp_meta_objset, - dd->dd_phys->dd_child_dir_zapobj, *offp); + dsl_dir_phys(dd)->dd_child_dir_zapobj, *offp); if (zap_cursor_retrieve(&cursor, &attr) != 0) { zap_cursor_fini(&cursor); @@ -1589,7 +1589,7 @@ dmu_objset_find_dp(dsl_pool_t *dp, uint64_t ddobj, return (0); } - thisobj = dd->dd_phys->dd_head_dataset_obj; + thisobj = dsl_dir_phys(dd)->dd_head_dataset_obj; attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); /* @@ -1597,7 +1597,7 @@ dmu_objset_find_dp(dsl_pool_t *dp, uint64_t ddobj, */ if (flags & DS_FIND_CHILDREN) { for (zap_cursor_init(&zc, dp->dp_meta_objset, - dd->dd_phys->dd_child_dir_zapobj); + dsl_dir_phys(dd)->dd_child_dir_zapobj); zap_cursor_retrieve(&zc, attr) == 0; (void) zap_cursor_advance(&zc)) { ASSERT3U(attr->za_integer_length, ==, @@ -1626,7 +1626,9 @@ dmu_objset_find_dp(dsl_pool_t *dp, uint64_t ddobj, err = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds); if (err == 0) { - uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj; + uint64_t snapobj; + + snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj; dsl_dataset_rele(ds, FTAG); for (zap_cursor_init(&zc, dp->dp_meta_objset, snapobj); @@ -1701,7 +1703,7 @@ dmu_objset_find_impl(spa_t *spa, const char *name, return (0); } - thisobj = dd->dd_phys->dd_head_dataset_obj; + thisobj = dsl_dir_phys(dd)->dd_head_dataset_obj; attr = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); /* @@ -1709,7 +1711,7 @@ dmu_objset_find_impl(spa_t *spa, const char *name, */ if (flags & DS_FIND_CHILDREN) { for (zap_cursor_init(&zc, dp->dp_meta_objset, - dd->dd_phys->dd_child_dir_zapobj); + dsl_dir_phys(dd)->dd_child_dir_zapobj); zap_cursor_retrieve(&zc, attr) == 0; (void) zap_cursor_advance(&zc)) { ASSERT3U(attr->za_integer_length, ==, @@ -1742,7 +1744,9 @@ dmu_objset_find_impl(spa_t *spa, const char *name, err = dsl_dataset_hold_obj(dp, thisobj, FTAG, &ds); if (err == 0) { - uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj; + uint64_t snapobj; + + snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj; dsl_dataset_rele(ds, FTAG); for (zap_cursor_init(&zc, dp->dp_meta_objset, snapobj); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c index 00d4f3e73e2a..d74c2cf88203 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c @@ -479,7 +479,7 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, dnode_phys_t *blk; int i; int blksz = BP_GET_LSIZE(bp); - uint32_t aflags = ARC_WAIT; + arc_flags_t aflags = ARC_FLAG_WAIT; arc_buf_t *abuf; if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf, @@ -497,7 +497,7 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, } (void) arc_buf_remove_ref(abuf, &abuf); } else if (type == DMU_OT_SA) { - uint32_t aflags = ARC_WAIT; + arc_flags_t aflags = ARC_FLAG_WAIT; arc_buf_t *abuf; int blksz = BP_GET_LSIZE(bp); @@ -514,7 +514,7 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, err = dump_write_embedded(dsp, zb->zb_object, zb->zb_blkid * blksz, blksz, bp); } else { /* it's a level-0 block of a regular object */ - uint32_t aflags = ARC_WAIT; + arc_flags_t aflags = ARC_FLAG_WAIT; arc_buf_t *abuf; int blksz = BP_GET_LSIZE(bp); uint64_t offset; @@ -623,12 +623,12 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds, featureflags); drr->drr_u.drr_begin.drr_creation_time = - ds->ds_phys->ds_creation_time; + dsl_dataset_phys(ds)->ds_creation_time; drr->drr_u.drr_begin.drr_type = dmu_objset_type(os); if (is_clone) drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE; - drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid; - if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET) + drr->drr_u.drr_begin.drr_toguid = dsl_dataset_phys(ds)->ds_guid; + if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET) drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CI_DATA; if (fromzb != NULL) { @@ -650,7 +650,7 @@ dmu_send_impl(void *tag, dsl_pool_t *dp, dsl_dataset_t *ds, dsp->dsa_fp = fp; dsp->dsa_os = os; dsp->dsa_off = off; - dsp->dsa_toguid = ds->ds_phys->ds_guid; + dsp->dsa_toguid = dsl_dataset_phys(ds)->ds_guid; ZIO_SET_CHECKSUM(&dsp->dsa_zc, 0, 0, 0, 0); dsp->dsa_pending_op = PENDING_NONE; dsp->dsa_incremental = (fromzb != NULL); @@ -740,9 +740,10 @@ dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap, } if (!dsl_dataset_is_before(ds, fromds, 0)) err = SET_ERROR(EXDEV); - zb.zbm_creation_time = fromds->ds_phys->ds_creation_time; - zb.zbm_creation_txg = fromds->ds_phys->ds_creation_txg; - zb.zbm_guid = fromds->ds_phys->ds_guid; + zb.zbm_creation_time = + dsl_dataset_phys(fromds)->ds_creation_time; + zb.zbm_creation_txg = dsl_dataset_phys(fromds)->ds_creation_txg; + zb.zbm_guid = dsl_dataset_phys(fromds)->ds_guid; is_clone = (fromds->ds_dir != ds->ds_dir); dsl_dataset_rele(fromds, FTAG); err = dmu_send_impl(FTAG, dp, ds, &zb, is_clone, @@ -813,10 +814,10 @@ dmu_send(const char *tosnap, const char *fromsnap, if (!dsl_dataset_is_before(ds, fromds, 0)) err = SET_ERROR(EXDEV); zb.zbm_creation_time = - fromds->ds_phys->ds_creation_time; + dsl_dataset_phys(fromds)->ds_creation_time; zb.zbm_creation_txg = - fromds->ds_phys->ds_creation_txg; - zb.zbm_guid = fromds->ds_phys->ds_guid; + dsl_dataset_phys(fromds)->ds_creation_txg; + zb.zbm_guid = dsl_dataset_phys(fromds)->ds_guid; is_clone = (ds->ds_dir != fromds->ds_dir); dsl_dataset_rele(fromds, FTAG); } @@ -863,7 +864,7 @@ dmu_send_estimate(dsl_dataset_t *ds, dsl_dataset_t *fromds, uint64_t *sizep) /* Get uncompressed size estimate of changed data. */ if (fromds == NULL) { - size = ds->ds_phys->ds_uncompressed_bytes; + size = dsl_dataset_phys(ds)->ds_uncompressed_bytes; } else { uint64_t used, comp; err = dsl_dataset_space_written(fromds, ds, @@ -918,15 +919,15 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds, /* temporary clone name must not exist */ error = zap_lookup(dp->dp_meta_objset, - ds->ds_dir->dd_phys->dd_child_dir_zapobj, recv_clone_name, + dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, recv_clone_name, 8, 1, &val); if (error != ENOENT) return (error == 0 ? EBUSY : error); /* new snapshot name must not exist */ error = zap_lookup(dp->dp_meta_objset, - ds->ds_phys->ds_snapnames_zapobj, drba->drba_cookie->drc_tosnap, - 8, 1, &val); + dsl_dataset_phys(ds)->ds_snapnames_zapobj, + drba->drba_cookie->drc_tosnap, 8, 1, &val); if (error != ENOENT) return (error == 0 ? EEXIST : error); @@ -946,7 +947,7 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds, if (fromguid != 0) { dsl_dataset_t *snap; - uint64_t obj = ds->ds_phys->ds_prev_snap_obj; + uint64_t obj = dsl_dataset_phys(ds)->ds_prev_snap_obj; /* Find snapshot in this dir that matches fromguid. */ while (obj != 0) { @@ -958,9 +959,9 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds, dsl_dataset_rele(snap, FTAG); return (SET_ERROR(ENODEV)); } - if (snap->ds_phys->ds_guid == fromguid) + if (dsl_dataset_phys(snap)->ds_guid == fromguid) break; - obj = snap->ds_phys->ds_prev_snap_obj; + obj = dsl_dataset_phys(snap)->ds_prev_snap_obj; dsl_dataset_rele(snap, FTAG); } if (obj == 0) @@ -983,9 +984,9 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds, dsl_dataset_rele(snap, FTAG); } else { /* if full, most recent snapshot must be $ORIGIN */ - if (ds->ds_phys->ds_prev_snap_txg >= TXG_INITIAL) + if (dsl_dataset_phys(ds)->ds_prev_snap_txg >= TXG_INITIAL) return (SET_ERROR(ENODEV)); - drba->drba_snapobj = ds->ds_phys->ds_prev_snap_obj; + drba->drba_snapobj = dsl_dataset_phys(ds)->ds_prev_snap_obj; } return (0); @@ -1103,7 +1104,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) dsl_dataset_rele(ds, FTAG); return (SET_ERROR(EINVAL)); } - if (origin->ds_phys->ds_guid != fromguid) { + if (dsl_dataset_phys(origin)->ds_guid != fromguid) { dsl_dataset_rele(origin, FTAG); dsl_dataset_rele(ds, FTAG); return (SET_ERROR(ENODEV)); @@ -1174,7 +1175,7 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx) } dmu_buf_will_dirty(newds->ds_dbuf, tx); - newds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT; + dsl_dataset_phys(newds)->ds_flags |= DS_FLAG_INCONSISTENT; /* * If we actually created a non-clone, we need to create the @@ -1837,7 +1838,7 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, struct file *fp, offset_t *voffp, */ VERIFY0(dmu_objset_from_ds(drc->drc_ds, &os)); - ASSERT(drc->drc_ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT); + ASSERT(dsl_dataset_phys(drc->drc_ds)->ds_flags & DS_FLAG_INCONSISTENT); featureflags = DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo); @@ -2000,8 +2001,11 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx) * the snap before drc_ds, because drc_ds can not * have any snaps of its own). */ - uint64_t obj = origin_head->ds_phys->ds_prev_snap_obj; - while (obj != drc->drc_ds->ds_phys->ds_prev_snap_obj) { + uint64_t obj; + + obj = dsl_dataset_phys(origin_head)->ds_prev_snap_obj; + while (obj != + dsl_dataset_phys(drc->drc_ds)->ds_prev_snap_obj) { dsl_dataset_t *snap; error = dsl_dataset_hold_obj(dp, obj, FTAG, &snap); @@ -2013,7 +2017,7 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx) error = dsl_destroy_snapshot_check_impl( snap, B_FALSE); } - obj = snap->ds_phys->ds_prev_snap_obj; + obj = dsl_dataset_phys(snap)->ds_prev_snap_obj; dsl_dataset_rele(snap, FTAG); if (error != 0) return (error); @@ -2059,13 +2063,16 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx) * Destroy any snapshots of drc_tofs (origin_head) * after the origin (the snap before drc_ds). */ - uint64_t obj = origin_head->ds_phys->ds_prev_snap_obj; - while (obj != drc->drc_ds->ds_phys->ds_prev_snap_obj) { + uint64_t obj; + + obj = dsl_dataset_phys(origin_head)->ds_prev_snap_obj; + while (obj != + dsl_dataset_phys(drc->drc_ds)->ds_prev_snap_obj) { dsl_dataset_t *snap; VERIFY0(dsl_dataset_hold_obj(dp, obj, FTAG, &snap)); ASSERT3P(snap->ds_dir, ==, origin_head->ds_dir); - obj = snap->ds_phys->ds_prev_snap_obj; + obj = dsl_dataset_phys(snap)->ds_prev_snap_obj; dsl_destroy_snapshot_sync_impl(snap, B_FALSE, tx); dsl_dataset_rele(snap, FTAG); @@ -2081,15 +2088,16 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx) /* set snapshot's creation time and guid */ dmu_buf_will_dirty(origin_head->ds_prev->ds_dbuf, tx); - origin_head->ds_prev->ds_phys->ds_creation_time = + dsl_dataset_phys(origin_head->ds_prev)->ds_creation_time = drc->drc_drrb->drr_creation_time; - origin_head->ds_prev->ds_phys->ds_guid = + dsl_dataset_phys(origin_head->ds_prev)->ds_guid = drc->drc_drrb->drr_toguid; - origin_head->ds_prev->ds_phys->ds_flags &= + dsl_dataset_phys(origin_head->ds_prev)->ds_flags &= ~DS_FLAG_INCONSISTENT; dmu_buf_will_dirty(origin_head->ds_dbuf, tx); - origin_head->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT; + dsl_dataset_phys(origin_head)->ds_flags &= + ~DS_FLAG_INCONSISTENT; dsl_dataset_rele(origin_head, FTAG); dsl_destroy_head_sync_impl(drc->drc_ds, tx); @@ -2103,15 +2111,17 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx) /* set snapshot's creation time and guid */ dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx); - ds->ds_prev->ds_phys->ds_creation_time = + dsl_dataset_phys(ds->ds_prev)->ds_creation_time = drc->drc_drrb->drr_creation_time; - ds->ds_prev->ds_phys->ds_guid = drc->drc_drrb->drr_toguid; - ds->ds_prev->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT; + dsl_dataset_phys(ds->ds_prev)->ds_guid = + drc->drc_drrb->drr_toguid; + dsl_dataset_phys(ds->ds_prev)->ds_flags &= + ~DS_FLAG_INCONSISTENT; dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT; + dsl_dataset_phys(ds)->ds_flags &= ~DS_FLAG_INCONSISTENT; } - drc->drc_newsnapobj = drc->drc_ds->ds_phys->ds_prev_snap_obj; + drc->drc_newsnapobj = dsl_dataset_phys(drc->drc_ds)->ds_prev_snap_obj; /* * Release the hold from dmu_recv_begin. This must be done before * we return to open context, so that when we free the dataset's dnode, @@ -2137,7 +2147,7 @@ add_ds_to_guidmap(const char *name, avl_tree_t *guid_map, uint64_t snapobj) gmep = kmem_alloc(sizeof (*gmep), KM_SLEEP); err = dsl_dataset_hold_obj(dp, snapobj, gmep, &snapds); if (err == 0) { - gmep->guid = snapds->ds_phys->ds_guid; + gmep->guid = dsl_dataset_phys(snapds)->ds_guid; gmep->gme_ds = snapds; avl_add(guid_map, gmep); dsl_dataset_long_hold(snapds, gmep); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c index 5523f6206fbc..7b1d6befa6ae 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c @@ -178,7 +178,7 @@ static void traverse_prefetch_metadata(traverse_data_t *td, const blkptr_t *bp, const zbookmark_phys_t *zb) { - uint32_t flags = ARC_NOWAIT | ARC_PREFETCH; + arc_flags_t flags = ARC_FLAG_NOWAIT | ARC_FLAG_PREFETCH; if (!(td->td_flags & TRAVERSE_PREFETCH_METADATA)) return; @@ -275,7 +275,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, } if (BP_GET_LEVEL(bp) > 0) { - uint32_t flags = ARC_WAIT; + arc_flags_t flags = ARC_FLAG_WAIT; int i; blkptr_t *cbp; int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT; @@ -303,7 +303,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, break; } } else if (BP_GET_TYPE(bp) == DMU_OT_DNODE) { - uint32_t flags = ARC_WAIT; + arc_flags_t flags = ARC_FLAG_WAIT; int i; int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT; @@ -326,7 +326,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp, break; } } else if (BP_GET_TYPE(bp) == DMU_OT_OBJSET) { - uint32_t flags = ARC_WAIT; + arc_flags_t flags = ARC_FLAG_WAIT; objset_phys_t *osp; dnode_phys_t *dnp; @@ -442,7 +442,7 @@ traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg) { prefetch_data_t *pfd = arg; - uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH; + arc_flags_t aflags = ARC_FLAG_NOWAIT | ARC_FLAG_PREFETCH; ASSERT(pfd->pd_blks_fetched >= 0); if (pfd->pd_cancel) @@ -533,7 +533,7 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp, /* See comment on ZIL traversal in dsl_scan_visitds. */ if (ds != NULL && !dsl_dataset_is_snapshot(ds) && !BP_IS_HOLE(rootbp)) { - uint32_t flags = ARC_WAIT; + arc_flags_t flags = ARC_FLAG_WAIT; objset_phys_t *osp; arc_buf_t *buf; @@ -579,7 +579,7 @@ traverse_dataset(dsl_dataset_t *ds, uint64_t txg_start, int flags, blkptr_cb_t func, void *arg) { return (traverse_impl(ds->ds_dir->dd_pool->dp_spa, ds, ds->ds_object, - &ds->ds_phys->ds_bp, txg_start, NULL, flags, func, arg)); + &dsl_dataset_phys(ds)->ds_bp, txg_start, NULL, flags, func, arg)); } int @@ -634,8 +634,8 @@ traverse_pool(spa_t *spa, uint64_t txg_start, int flags, continue; break; } - if (ds->ds_phys->ds_prev_snap_txg > txg) - txg = ds->ds_phys->ds_prev_snap_txg; + if (dsl_dataset_phys(ds)->ds_prev_snap_txg > txg) + txg = dsl_dataset_phys(ds)->ds_prev_snap_txg; err = traverse_dataset(ds, txg, flags, func, arg); dsl_dataset_rele(ds, FTAG); if (err != 0) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c index b97040ae870a..1f4270462668 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c @@ -714,6 +714,7 @@ dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, const char *name) { dmu_tx_hold_t *txh; dnode_t *dn; + dsl_dataset_phys_t *ds_phys; uint64_t nblocks; int epbs, err; @@ -788,8 +789,9 @@ dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, const char *name) * we'll have to modify an indirect twig for each. */ epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT; + ds_phys = dsl_dataset_phys(dn->dn_objset->os_dsl_dataset); for (nblocks = dn->dn_maxblkid >> epbs; nblocks != 0; nblocks >>= epbs) - if (dn->dn_objset->os_dsl_dataset->ds_phys->ds_prev_snap_obj) + if (ds_phys->ds_prev_snap_obj) txh->txh_space_towrite += 3 << dn->dn_indblkshift; else txh->txh_space_tooverwrite += 3 << dn->dn_indblkshift; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c index b39f6b11d26f..66552c33252e 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c @@ -1121,7 +1121,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, zrl_init(&dnh[i].dnh_zrlock); dnh[i].dnh_dnode = NULL; } - if (winner = dmu_buf_set_user(&db->db, children_dnodes, NULL, + if (winner = dmu_buf_set_user(&db->db, children_dnodes, dnode_buf_pageout)) { for (i = 0; i < epb; i++) { diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c index 21784630da6b..5fb7f96600dc 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c @@ -65,7 +65,7 @@ dsl_dataset_bmark_lookup(dsl_dataset_t *ds, const char *shortname, if (bmark_zapobj == 0) return (SET_ERROR(ESRCH)); - if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET) + if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET) mt = MT_FIRST; else mt = MT_EXACT; @@ -208,10 +208,11 @@ dsl_bookmark_create_sync(void *arg, dmu_tx_t *tx) &bmark_fs->ds_bookmarks, tx)); } - bmark_phys.zbm_guid = snapds->ds_phys->ds_guid; - bmark_phys.zbm_creation_txg = snapds->ds_phys->ds_creation_txg; + bmark_phys.zbm_guid = dsl_dataset_phys(snapds)->ds_guid; + bmark_phys.zbm_creation_txg = + dsl_dataset_phys(snapds)->ds_creation_txg; bmark_phys.zbm_creation_time = - snapds->ds_phys->ds_creation_time; + dsl_dataset_phys(snapds)->ds_creation_time; VERIFY0(zap_add(mos, bmark_fs->ds_bookmarks, shortname, sizeof (uint64_t), @@ -340,7 +341,7 @@ dsl_dataset_bookmark_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx) uint64_t bmark_zapobj = ds->ds_bookmarks; matchtype_t mt; - if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET) + if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET) mt = MT_FIRST; else mt = MT_EXACT; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c index 0db2db7d0489..34bef4ee5698 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c @@ -76,6 +76,9 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, max_recordsize, CTLFLAG_RWTUN, #define DS_REF_MAX (1ULL << 62) +extern inline dsl_dataset_phys_t *dsl_dataset_phys(dsl_dataset_t *ds); +extern inline boolean_t dsl_dataset_is_snapshot(dsl_dataset_t *ds); + /* * Figure out how much of this delta should be propogated to the dsl_dir * layer. If there's a refreservation, that space has already been @@ -84,13 +87,15 @@ SYSCTL_INT(_vfs_zfs, OID_AUTO, max_recordsize, CTLFLAG_RWTUN, static int64_t parent_delta(dsl_dataset_t *ds, int64_t delta) { + dsl_dataset_phys_t *ds_phys; uint64_t old_bytes, new_bytes; if (ds->ds_reserved == 0) return (delta); - old_bytes = MAX(ds->ds_phys->ds_unique_bytes, ds->ds_reserved); - new_bytes = MAX(ds->ds_phys->ds_unique_bytes + delta, ds->ds_reserved); + ds_phys = dsl_dataset_phys(ds); + old_bytes = MAX(ds_phys->ds_unique_bytes, ds->ds_reserved); + new_bytes = MAX(ds_phys->ds_unique_bytes + delta, ds->ds_reserved); ASSERT3U(ABS((int64_t)(new_bytes - old_bytes)), <=, ABS(delta)); return (new_bytes - old_bytes); @@ -121,10 +126,10 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx) dmu_buf_will_dirty(ds->ds_dbuf, tx); mutex_enter(&ds->ds_lock); delta = parent_delta(ds, used); - ds->ds_phys->ds_referenced_bytes += used; - ds->ds_phys->ds_compressed_bytes += compressed; - ds->ds_phys->ds_uncompressed_bytes += uncompressed; - ds->ds_phys->ds_unique_bytes += used; + dsl_dataset_phys(ds)->ds_referenced_bytes += used; + dsl_dataset_phys(ds)->ds_compressed_bytes += compressed; + dsl_dataset_phys(ds)->ds_uncompressed_bytes += uncompressed; + dsl_dataset_phys(ds)->ds_unique_bytes += used; if (BP_GET_LSIZE(bp) > SPA_OLD_MAXBLOCKSIZE) ds->ds_need_large_blocks = B_TRUE; mutex_exit(&ds->ds_lock); @@ -159,17 +164,17 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx, ASSERT(!dsl_dataset_is_snapshot(ds)); dmu_buf_will_dirty(ds->ds_dbuf, tx); - if (bp->blk_birth > ds->ds_phys->ds_prev_snap_txg) { + if (bp->blk_birth > dsl_dataset_phys(ds)->ds_prev_snap_txg) { int64_t delta; dprintf_bp(bp, "freeing ds=%llu", ds->ds_object); dsl_free(tx->tx_pool, tx->tx_txg, bp); mutex_enter(&ds->ds_lock); - ASSERT(ds->ds_phys->ds_unique_bytes >= used || + ASSERT(dsl_dataset_phys(ds)->ds_unique_bytes >= used || !DS_UNIQUE_IS_ACCURATE(ds)); delta = parent_delta(ds, -used); - ds->ds_phys->ds_unique_bytes -= used; + dsl_dataset_phys(ds)->ds_unique_bytes -= used; mutex_exit(&ds->ds_lock); dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, delta, -compressed, -uncompressed, tx); @@ -190,15 +195,15 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx, dsl_deadlist_insert(&ds->ds_deadlist, bp, tx); } ASSERT3U(ds->ds_prev->ds_object, ==, - ds->ds_phys->ds_prev_snap_obj); - ASSERT(ds->ds_prev->ds_phys->ds_num_children > 0); + dsl_dataset_phys(ds)->ds_prev_snap_obj); + ASSERT(dsl_dataset_phys(ds->ds_prev)->ds_num_children > 0); /* if (bp->blk_birth > prev prev snap txg) prev unique += bs */ - if (ds->ds_prev->ds_phys->ds_next_snap_obj == + if (dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj == ds->ds_object && bp->blk_birth > - ds->ds_prev->ds_phys->ds_prev_snap_txg) { + dsl_dataset_phys(ds->ds_prev)->ds_prev_snap_txg) { dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx); mutex_enter(&ds->ds_prev->ds_lock); - ds->ds_prev->ds_phys->ds_unique_bytes += used; + dsl_dataset_phys(ds->ds_prev)->ds_unique_bytes += used; mutex_exit(&ds->ds_prev->ds_lock); } if (bp->blk_birth > ds->ds_dir->dd_origin_txg) { @@ -207,12 +212,12 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx, } } mutex_enter(&ds->ds_lock); - ASSERT3U(ds->ds_phys->ds_referenced_bytes, >=, used); - ds->ds_phys->ds_referenced_bytes -= used; - ASSERT3U(ds->ds_phys->ds_compressed_bytes, >=, compressed); - ds->ds_phys->ds_compressed_bytes -= compressed; - ASSERT3U(ds->ds_phys->ds_uncompressed_bytes, >=, uncompressed); - ds->ds_phys->ds_uncompressed_bytes -= uncompressed; + ASSERT3U(dsl_dataset_phys(ds)->ds_referenced_bytes, >=, used); + dsl_dataset_phys(ds)->ds_referenced_bytes -= used; + ASSERT3U(dsl_dataset_phys(ds)->ds_compressed_bytes, >=, compressed); + dsl_dataset_phys(ds)->ds_compressed_bytes -= compressed; + ASSERT3U(dsl_dataset_phys(ds)->ds_uncompressed_bytes, >=, uncompressed); + dsl_dataset_phys(ds)->ds_uncompressed_bytes -= uncompressed; mutex_exit(&ds->ds_lock); return (used); @@ -238,7 +243,7 @@ dsl_dataset_prev_snap_txg(dsl_dataset_t *ds) if (ds->ds_trysnap_txg > spa_last_synced_txg(ds->ds_dir->dd_pool->dp_spa)) trysnap = ds->ds_trysnap_txg; - return (MAX(ds->ds_phys->ds_prev_snap_txg, trysnap)); + return (MAX(dsl_dataset_phys(ds)->ds_prev_snap_txg, trysnap)); } boolean_t @@ -273,7 +278,7 @@ dsl_dataset_evict(dmu_buf_t *db, void *dsv) } bplist_destroy(&ds->ds_pending_deadlist); - if (ds->ds_phys->ds_deadlist_obj != 0) + if (dsl_dataset_phys(ds)->ds_deadlist_obj != 0) dsl_deadlist_close(&ds->ds_deadlist); if (ds->ds_dir) dsl_dir_rele(ds->ds_dir, ds); @@ -303,10 +308,10 @@ dsl_dataset_get_snapname(dsl_dataset_t *ds) if (ds->ds_snapname[0]) return (0); - if (ds->ds_phys->ds_next_snap_obj == 0) + if (dsl_dataset_phys(ds)->ds_next_snap_obj == 0) return (0); - err = dmu_bonus_hold(mos, ds->ds_dir->dd_phys->dd_head_dataset_obj, + err = dmu_bonus_hold(mos, dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj, FTAG, &headdbuf); if (err != 0) return (err); @@ -321,11 +326,11 @@ int dsl_dataset_snap_lookup(dsl_dataset_t *ds, const char *name, uint64_t *value) { objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset; - uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj; + uint64_t snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj; matchtype_t mt; int err; - if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET) + if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET) mt = MT_FIRST; else mt = MT_EXACT; @@ -342,13 +347,13 @@ dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx, boolean_t adj_cnt) { objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset; - uint64_t snapobj = ds->ds_phys->ds_snapnames_zapobj; + uint64_t snapobj = dsl_dataset_phys(ds)->ds_snapnames_zapobj; matchtype_t mt; int err; dsl_dir_snap_cmtime_update(ds->ds_dir); - if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET) + if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET) mt = MT_FIRST; else mt = MT_EXACT; @@ -394,7 +399,6 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag, ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP); ds->ds_dbuf = dbuf; ds->ds_object = dsobj; - ds->ds_phys = dbuf->db_data; mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL); @@ -403,7 +407,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag, bplist_create(&ds->ds_pending_deadlist); dsl_deadlist_open(&ds->ds_deadlist, - mos, ds->ds_phys->ds_deadlist_obj); + mos, dsl_dataset_phys(ds)->ds_deadlist_obj); list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t), offsetof(dmu_sendarg_t, dsa_link)); @@ -418,7 +422,8 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag, if (err == 0) { err = dsl_dir_hold_obj(dp, - ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir); + dsl_dataset_phys(ds)->ds_dir_obj, NULL, ds, + &ds->ds_dir); } if (err != 0) { mutex_destroy(&ds->ds_lock); @@ -434,9 +439,9 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag, if (!dsl_dataset_is_snapshot(ds)) { ds->ds_snapname[0] = '\0'; - if (ds->ds_phys->ds_prev_snap_obj != 0) { + if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) { err = dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_prev_snap_obj, + dsl_dataset_phys(ds)->ds_prev_snap_obj, ds, &ds->ds_prev); } if (doi.doi_type == DMU_OTN_ZAP_METADATA) { @@ -450,10 +455,11 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag, } else { if (zfs_flags & ZFS_DEBUG_SNAPNAMES) err = dsl_dataset_get_snapname(ds); - if (err == 0 && ds->ds_phys->ds_userrefs_obj != 0) { + if (err == 0 && + dsl_dataset_phys(ds)->ds_userrefs_obj != 0) { err = zap_count( ds->ds_dir->dd_pool->dp_meta_objset, - ds->ds_phys->ds_userrefs_obj, + dsl_dataset_phys(ds)->ds_userrefs_obj, &ds->ds_userrefs); } } @@ -472,7 +478,7 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag, } if (err != 0 || (winner = dmu_buf_set_user_ie(dbuf, ds, - &ds->ds_phys, dsl_dataset_evict)) != NULL) { + dsl_dataset_evict)) != NULL) { bplist_destroy(&ds->ds_pending_deadlist); dsl_deadlist_close(&ds->ds_deadlist); if (ds->ds_prev) @@ -490,12 +496,12 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag, ds = winner; } else { ds->ds_fsid_guid = - unique_insert(ds->ds_phys->ds_fsid_guid); + unique_insert(dsl_dataset_phys(ds)->ds_fsid_guid); } } ASSERT3P(ds->ds_dbuf, ==, dbuf); - ASSERT3P(ds->ds_phys, ==, dbuf->db_data); - ASSERT(ds->ds_phys->ds_prev_snap_obj != 0 || + ASSERT3P(dsl_dataset_phys(ds), ==, dbuf->db_data); + ASSERT(dsl_dataset_phys(ds)->ds_prev_snap_obj != 0 || spa_version(dp->dp_spa) < SPA_VERSION_ORIGIN || dp->dp_origin_snap == NULL || ds == dp->dp_origin_snap); *dsp = ds; @@ -516,7 +522,7 @@ dsl_dataset_hold(dsl_pool_t *dp, const char *name, return (err); ASSERT(dsl_pool_config_held(dp)); - obj = dd->dd_phys->dd_head_dataset_obj; + obj = dsl_dir_phys(dd)->dd_head_dataset_obj; if (obj != 0) err = dsl_dataset_hold_obj(dp, obj, tag, dsp); else @@ -683,9 +689,9 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin, origin = dp->dp_origin_snap; ASSERT(origin == NULL || origin->ds_dir->dd_pool == dp); - ASSERT(origin == NULL || origin->ds_phys->ds_num_children > 0); + ASSERT(origin == NULL || dsl_dataset_phys(origin)->ds_num_children > 0); ASSERT(dmu_tx_is_syncing(tx)); - ASSERT(dd->dd_phys->dd_head_dataset_obj == 0); + ASSERT(dsl_dir_phys(dd)->dd_head_dataset_obj == 0); dsobj = dmu_object_alloc(mos, DMU_OT_DSL_DATASET, 0, DMU_OT_DSL_DATASET, sizeof (dsl_dataset_phys_t), tx); @@ -713,55 +719,58 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin, dsphys->ds_prev_snap_obj = origin->ds_object; dsphys->ds_prev_snap_txg = - origin->ds_phys->ds_creation_txg; + dsl_dataset_phys(origin)->ds_creation_txg; dsphys->ds_referenced_bytes = - origin->ds_phys->ds_referenced_bytes; + dsl_dataset_phys(origin)->ds_referenced_bytes; dsphys->ds_compressed_bytes = - origin->ds_phys->ds_compressed_bytes; + dsl_dataset_phys(origin)->ds_compressed_bytes; dsphys->ds_uncompressed_bytes = - origin->ds_phys->ds_uncompressed_bytes; - dsphys->ds_bp = origin->ds_phys->ds_bp; + dsl_dataset_phys(origin)->ds_uncompressed_bytes; + dsphys->ds_bp = dsl_dataset_phys(origin)->ds_bp; /* * Inherit flags that describe the dataset's contents * (INCONSISTENT) or properties (Case Insensitive). */ - dsphys->ds_flags |= origin->ds_phys->ds_flags & + dsphys->ds_flags |= dsl_dataset_phys(origin)->ds_flags & (DS_FLAG_INCONSISTENT | DS_FLAG_CI_DATASET); if (origin->ds_large_blocks) dsl_dataset_activate_large_blocks_sync_impl(dsobj, tx); dmu_buf_will_dirty(origin->ds_dbuf, tx); - origin->ds_phys->ds_num_children++; + dsl_dataset_phys(origin)->ds_num_children++; VERIFY0(dsl_dataset_hold_obj(dp, - origin->ds_dir->dd_phys->dd_head_dataset_obj, FTAG, &ohds)); + dsl_dir_phys(origin->ds_dir)->dd_head_dataset_obj, + FTAG, &ohds)); dsphys->ds_deadlist_obj = dsl_deadlist_clone(&ohds->ds_deadlist, dsphys->ds_prev_snap_txg, dsphys->ds_prev_snap_obj, tx); dsl_dataset_rele(ohds, FTAG); if (spa_version(dp->dp_spa) >= SPA_VERSION_NEXT_CLONES) { - if (origin->ds_phys->ds_next_clones_obj == 0) { - origin->ds_phys->ds_next_clones_obj = + if (dsl_dataset_phys(origin)->ds_next_clones_obj == 0) { + dsl_dataset_phys(origin)->ds_next_clones_obj = zap_create(mos, DMU_OT_NEXT_CLONES, DMU_OT_NONE, 0, tx); } VERIFY0(zap_add_int(mos, - origin->ds_phys->ds_next_clones_obj, dsobj, tx)); + dsl_dataset_phys(origin)->ds_next_clones_obj, + dsobj, tx)); } dmu_buf_will_dirty(dd->dd_dbuf, tx); - dd->dd_phys->dd_origin_obj = origin->ds_object; + dsl_dir_phys(dd)->dd_origin_obj = origin->ds_object; if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) { - if (origin->ds_dir->dd_phys->dd_clones == 0) { + if (dsl_dir_phys(origin->ds_dir)->dd_clones == 0) { dmu_buf_will_dirty(origin->ds_dir->dd_dbuf, tx); - origin->ds_dir->dd_phys->dd_clones = + dsl_dir_phys(origin->ds_dir)->dd_clones = zap_create(mos, DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx); } VERIFY0(zap_add_int(mos, - origin->ds_dir->dd_phys->dd_clones, dsobj, tx)); + dsl_dir_phys(origin->ds_dir)->dd_clones, + dsobj, tx)); } } @@ -771,7 +780,7 @@ dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin, dmu_buf_rele(dbuf, FTAG); dmu_buf_will_dirty(dd->dd_dbuf, tx); - dd->dd_phys->dd_head_dataset_obj = dsobj; + dsl_dir_phys(dd)->dd_head_dataset_obj = dsobj; return (dsobj); } @@ -893,20 +902,20 @@ dsl_dataset_recalc_head_uniq(dsl_dataset_t *ds) ASSERT(!dsl_dataset_is_snapshot(ds)); - if (ds->ds_phys->ds_prev_snap_obj != 0) - mrs_used = ds->ds_prev->ds_phys->ds_referenced_bytes; + if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) + mrs_used = dsl_dataset_phys(ds->ds_prev)->ds_referenced_bytes; else mrs_used = 0; dsl_deadlist_space(&ds->ds_deadlist, &dlused, &dlcomp, &dluncomp); ASSERT3U(dlused, <=, mrs_used); - ds->ds_phys->ds_unique_bytes = - ds->ds_phys->ds_referenced_bytes - (mrs_used - dlused); + dsl_dataset_phys(ds)->ds_unique_bytes = + dsl_dataset_phys(ds)->ds_referenced_bytes - (mrs_used - dlused); if (spa_version(ds->ds_dir->dd_pool->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE) - ds->ds_phys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE; + dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_UNIQUE_ACCURATE; } void @@ -917,8 +926,9 @@ dsl_dataset_remove_from_next_clones(dsl_dataset_t *ds, uint64_t obj, uint64_t count; int err; - ASSERT(ds->ds_phys->ds_num_children >= 2); - err = zap_remove_int(mos, ds->ds_phys->ds_next_clones_obj, obj, tx); + ASSERT(dsl_dataset_phys(ds)->ds_num_children >= 2); + err = zap_remove_int(mos, dsl_dataset_phys(ds)->ds_next_clones_obj, + obj, tx); /* * The err should not be ENOENT, but a bug in a previous version * of the code could cause upgrade_clones_cb() to not set @@ -931,16 +941,16 @@ dsl_dataset_remove_from_next_clones(dsl_dataset_t *ds, uint64_t obj, */ if (err != ENOENT) VERIFY0(err); - ASSERT0(zap_count(mos, ds->ds_phys->ds_next_clones_obj, + ASSERT0(zap_count(mos, dsl_dataset_phys(ds)->ds_next_clones_obj, &count)); - ASSERT3U(count, <=, ds->ds_phys->ds_num_children - 2); + ASSERT3U(count, <=, dsl_dataset_phys(ds)->ds_num_children - 2); } blkptr_t * dsl_dataset_get_blkptr(dsl_dataset_t *ds) { - return (&ds->ds_phys->ds_bp); + return (&dsl_dataset_phys(ds)->ds_bp); } void @@ -952,7 +962,7 @@ dsl_dataset_set_blkptr(dsl_dataset_t *ds, blkptr_t *bp, dmu_tx_t *tx) tx->tx_pool->dp_meta_rootbp = *bp; } else { dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_bp = *bp; + dsl_dataset_phys(ds)->ds_bp = *bp; } } @@ -972,7 +982,7 @@ dsl_dataset_dirty(dsl_dataset_t *ds, dmu_tx_t *tx) ASSERT(ds->ds_objset != NULL); - if (ds->ds_phys->ds_next_snap_obj != 0) + if (dsl_dataset_phys(ds)->ds_next_snap_obj != 0) panic("dirtying snapshot!"); dp = ds->ds_dir->dd_pool; @@ -1008,7 +1018,7 @@ dsl_dataset_snapshot_reserve_space(dsl_dataset_t *ds, dmu_tx_t *tx) * outside of the reservation. */ ASSERT(ds->ds_reserved == 0 || DS_UNIQUE_IS_ACCURATE(ds)); - asize = MIN(ds->ds_phys->ds_unique_bytes, ds->ds_reserved); + asize = MIN(dsl_dataset_phys(ds)->ds_unique_bytes, ds->ds_reserved); if (asize > dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE)) return (SET_ERROR(ENOSPC)); @@ -1045,7 +1055,7 @@ dsl_dataset_snapshot_check_impl(dsl_dataset_t *ds, const char *snapname, * We don't allow multiple snapshots of the same txg. If there * is already one, try again. */ - if (ds->ds_phys->ds_prev_snap_txg >= tx->tx_txg) + if (dsl_dataset_phys(ds)->ds_prev_snap_txg >= tx->tx_txg) return (SET_ERROR(EAGAIN)); /* @@ -1273,35 +1283,38 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname, (void) random_get_pseudo_bytes((void*)&dsphys->ds_guid, sizeof (dsphys->ds_guid)); } while (dsphys->ds_guid == 0); - dsphys->ds_prev_snap_obj = ds->ds_phys->ds_prev_snap_obj; - dsphys->ds_prev_snap_txg = ds->ds_phys->ds_prev_snap_txg; + dsphys->ds_prev_snap_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj; + dsphys->ds_prev_snap_txg = dsl_dataset_phys(ds)->ds_prev_snap_txg; dsphys->ds_next_snap_obj = ds->ds_object; dsphys->ds_num_children = 1; dsphys->ds_creation_time = gethrestime_sec(); dsphys->ds_creation_txg = crtxg; - dsphys->ds_deadlist_obj = ds->ds_phys->ds_deadlist_obj; - dsphys->ds_referenced_bytes = ds->ds_phys->ds_referenced_bytes; - dsphys->ds_compressed_bytes = ds->ds_phys->ds_compressed_bytes; - dsphys->ds_uncompressed_bytes = ds->ds_phys->ds_uncompressed_bytes; - dsphys->ds_flags = ds->ds_phys->ds_flags; - dsphys->ds_bp = ds->ds_phys->ds_bp; + dsphys->ds_deadlist_obj = dsl_dataset_phys(ds)->ds_deadlist_obj; + dsphys->ds_referenced_bytes = dsl_dataset_phys(ds)->ds_referenced_bytes; + dsphys->ds_compressed_bytes = dsl_dataset_phys(ds)->ds_compressed_bytes; + dsphys->ds_uncompressed_bytes = + dsl_dataset_phys(ds)->ds_uncompressed_bytes; + dsphys->ds_flags = dsl_dataset_phys(ds)->ds_flags; + dsphys->ds_bp = dsl_dataset_phys(ds)->ds_bp; dmu_buf_rele(dbuf, FTAG); if (ds->ds_large_blocks) dsl_dataset_activate_large_blocks_sync_impl(dsobj, tx); - ASSERT3U(ds->ds_prev != 0, ==, ds->ds_phys->ds_prev_snap_obj != 0); + ASSERT3U(ds->ds_prev != 0, ==, + dsl_dataset_phys(ds)->ds_prev_snap_obj != 0); if (ds->ds_prev) { uint64_t next_clones_obj = - ds->ds_prev->ds_phys->ds_next_clones_obj; - ASSERT(ds->ds_prev->ds_phys->ds_next_snap_obj == + dsl_dataset_phys(ds->ds_prev)->ds_next_clones_obj; + ASSERT(dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj == ds->ds_object || - ds->ds_prev->ds_phys->ds_num_children > 1); - if (ds->ds_prev->ds_phys->ds_next_snap_obj == ds->ds_object) { + dsl_dataset_phys(ds->ds_prev)->ds_num_children > 1); + if (dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj == + ds->ds_object) { dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx); - ASSERT3U(ds->ds_phys->ds_prev_snap_txg, ==, - ds->ds_prev->ds_phys->ds_creation_txg); - ds->ds_prev->ds_phys->ds_next_snap_obj = dsobj; + ASSERT3U(dsl_dataset_phys(ds)->ds_prev_snap_txg, ==, + dsl_dataset_phys(ds->ds_prev)->ds_creation_txg); + dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj = dsobj; } else if (next_clones_obj != 0) { dsl_dataset_remove_from_next_clones(ds->ds_prev, dsphys->ds_next_snap_obj, tx); @@ -1318,33 +1331,36 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname, if (ds->ds_reserved) { int64_t delta; ASSERT(DS_UNIQUE_IS_ACCURATE(ds)); - delta = MIN(ds->ds_phys->ds_unique_bytes, ds->ds_reserved); + delta = MIN(dsl_dataset_phys(ds)->ds_unique_bytes, + ds->ds_reserved); dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx); } dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_deadlist_obj = dsl_deadlist_clone(&ds->ds_deadlist, - UINT64_MAX, ds->ds_phys->ds_prev_snap_obj, tx); + dsl_dataset_phys(ds)->ds_deadlist_obj = + dsl_deadlist_clone(&ds->ds_deadlist, UINT64_MAX, + dsl_dataset_phys(ds)->ds_prev_snap_obj, tx); dsl_deadlist_close(&ds->ds_deadlist); - dsl_deadlist_open(&ds->ds_deadlist, mos, ds->ds_phys->ds_deadlist_obj); + dsl_deadlist_open(&ds->ds_deadlist, mos, + dsl_dataset_phys(ds)->ds_deadlist_obj); dsl_deadlist_add_key(&ds->ds_deadlist, - ds->ds_phys->ds_prev_snap_txg, tx); + dsl_dataset_phys(ds)->ds_prev_snap_txg, tx); - ASSERT3U(ds->ds_phys->ds_prev_snap_txg, <, tx->tx_txg); - ds->ds_phys->ds_prev_snap_obj = dsobj; - ds->ds_phys->ds_prev_snap_txg = crtxg; - ds->ds_phys->ds_unique_bytes = 0; + ASSERT3U(dsl_dataset_phys(ds)->ds_prev_snap_txg, <, tx->tx_txg); + dsl_dataset_phys(ds)->ds_prev_snap_obj = dsobj; + dsl_dataset_phys(ds)->ds_prev_snap_txg = crtxg; + dsl_dataset_phys(ds)->ds_unique_bytes = 0; if (spa_version(dp->dp_spa) >= SPA_VERSION_UNIQUE_ACCURATE) - ds->ds_phys->ds_flags |= DS_FLAG_UNIQUE_ACCURATE; + dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_UNIQUE_ACCURATE; - VERIFY0(zap_add(mos, ds->ds_phys->ds_snapnames_zapobj, + VERIFY0(zap_add(mos, dsl_dataset_phys(ds)->ds_snapnames_zapobj, snapname, 8, 1, &dsobj, tx)); if (ds->ds_prev) dsl_dataset_rele(ds->ds_prev, ds); VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_prev_snap_obj, ds, &ds->ds_prev)); + dsl_dataset_phys(ds)->ds_prev_snap_obj, ds, &ds->ds_prev)); dsl_scan_ds_snapshotted(ds, tx); @@ -1564,14 +1580,14 @@ dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx) { ASSERT(dmu_tx_is_syncing(tx)); ASSERT(ds->ds_objset != NULL); - ASSERT(ds->ds_phys->ds_next_snap_obj == 0); + ASSERT(dsl_dataset_phys(ds)->ds_next_snap_obj == 0); /* * in case we had to change ds_fsid_guid when we opened it, * sync it out now. */ dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_fsid_guid = ds->ds_fsid_guid; + dsl_dataset_phys(ds)->ds_fsid_guid = ds->ds_fsid_guid; dmu_objset_sync(ds->ds_objset, zio, tx); @@ -1598,13 +1614,14 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv) * due to a bug in a previous version of the code. * Only trust it if it has the right number of entries. */ - if (ds->ds_phys->ds_next_clones_obj != 0) { - VERIFY0(zap_count(mos, ds->ds_phys->ds_next_clones_obj, + if (dsl_dataset_phys(ds)->ds_next_clones_obj != 0) { + VERIFY0(zap_count(mos, dsl_dataset_phys(ds)->ds_next_clones_obj, &count)); } - if (count != ds->ds_phys->ds_num_children - 1) + if (count != dsl_dataset_phys(ds)->ds_num_children - 1) goto fail; - for (zap_cursor_init(&zc, mos, ds->ds_phys->ds_next_clones_obj); + for (zap_cursor_init(&zc, mos, + dsl_dataset_phys(ds)->ds_next_clones_obj); zap_cursor_retrieve(&zc, &za) == 0; zap_cursor_advance(&zc)) { dsl_dataset_t *clone; @@ -1631,18 +1648,18 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv) ASSERT(dsl_pool_config_held(dp)); - ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 : - (ds->ds_phys->ds_uncompressed_bytes * 100 / - ds->ds_phys->ds_compressed_bytes); + ratio = dsl_dataset_phys(ds)->ds_compressed_bytes == 0 ? 100 : + (dsl_dataset_phys(ds)->ds_uncompressed_bytes * 100 / + dsl_dataset_phys(ds)->ds_compressed_bytes); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALREFERENCED, - ds->ds_phys->ds_uncompressed_bytes); + dsl_dataset_phys(ds)->ds_uncompressed_bytes); if (dsl_dataset_is_snapshot(ds)) { dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED, - ds->ds_phys->ds_unique_bytes); + dsl_dataset_phys(ds)->ds_unique_bytes); get_clones_stat(ds, nv); } else { if (ds->ds_prev != NULL && ds->ds_prev != dp->dp_origin_snap) { @@ -1659,17 +1676,17 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv) dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFERENCED, refd); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATION, - ds->ds_phys->ds_creation_time); + dsl_dataset_phys(ds)->ds_creation_time); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_CREATETXG, - ds->ds_phys->ds_creation_txg); + dsl_dataset_phys(ds)->ds_creation_txg); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFQUOTA, ds->ds_quota); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRESERVATION, ds->ds_reserved); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_GUID, - ds->ds_phys->ds_guid); + dsl_dataset_phys(ds)->ds_guid); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_UNIQUE, - ds->ds_phys->ds_unique_bytes); + dsl_dataset_phys(ds)->ds_unique_bytes); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_OBJSETID, ds->ds_object); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USERREFS, @@ -1677,13 +1694,13 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv) dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY, DS_IS_DEFER_DESTROY(ds) ? 1 : 0); - if (ds->ds_phys->ds_prev_snap_obj != 0) { + if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) { uint64_t written, comp, uncomp; dsl_pool_t *dp = ds->ds_dir->dd_pool; dsl_dataset_t *prev; int err = dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_prev_snap_obj, FTAG, &prev); + dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &prev); if (err == 0) { err = dsl_dataset_space_written(prev, ds, &written, &comp, &uncomp); @@ -1702,13 +1719,15 @@ dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat) dsl_pool_t *dp = ds->ds_dir->dd_pool; ASSERT(dsl_pool_config_held(dp)); - stat->dds_creation_txg = ds->ds_phys->ds_creation_txg; - stat->dds_inconsistent = ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT; - stat->dds_guid = ds->ds_phys->ds_guid; + stat->dds_creation_txg = dsl_dataset_phys(ds)->ds_creation_txg; + stat->dds_inconsistent = + dsl_dataset_phys(ds)->ds_flags & DS_FLAG_INCONSISTENT; + stat->dds_guid = dsl_dataset_phys(ds)->ds_guid; stat->dds_origin[0] = '\0'; if (dsl_dataset_is_snapshot(ds)) { stat->dds_is_snapshot = B_TRUE; - stat->dds_num_clones = ds->ds_phys->ds_num_children - 1; + stat->dds_num_clones = + dsl_dataset_phys(ds)->ds_num_children - 1; } else { stat->dds_is_snapshot = B_FALSE; stat->dds_num_clones = 0; @@ -1717,7 +1736,8 @@ dsl_dataset_fast_stat(dsl_dataset_t *ds, dmu_objset_stats_t *stat) dsl_dataset_t *ods; VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods)); + dsl_dir_phys(ds->ds_dir)->dd_origin_obj, + FTAG, &ods)); dsl_dataset_name(ods, stat->dds_origin); dsl_dataset_rele(ods, FTAG); } @@ -1735,10 +1755,11 @@ dsl_dataset_space(dsl_dataset_t *ds, uint64_t *refdbytesp, uint64_t *availbytesp, uint64_t *usedobjsp, uint64_t *availobjsp) { - *refdbytesp = ds->ds_phys->ds_referenced_bytes; + *refdbytesp = dsl_dataset_phys(ds)->ds_referenced_bytes; *availbytesp = dsl_dir_space_available(ds->ds_dir, NULL, 0, TRUE); - if (ds->ds_reserved > ds->ds_phys->ds_unique_bytes) - *availbytesp += ds->ds_reserved - ds->ds_phys->ds_unique_bytes; + if (ds->ds_reserved > dsl_dataset_phys(ds)->ds_unique_bytes) + *availbytesp += + ds->ds_reserved - dsl_dataset_phys(ds)->ds_unique_bytes; if (ds->ds_quota != 0) { /* * Adjust available bytes according to refquota @@ -1749,7 +1770,7 @@ dsl_dataset_space(dsl_dataset_t *ds, else *availbytesp = 0; } - *usedobjsp = BP_GET_FILL(&ds->ds_phys->ds_bp); + *usedobjsp = BP_GET_FILL(&dsl_dataset_phys(ds)->ds_bp); *availobjsp = DN_MAX_OBJECT - *usedobjsp; } @@ -1761,8 +1782,8 @@ dsl_dataset_modified_since_snap(dsl_dataset_t *ds, dsl_dataset_t *snap) ASSERT(dsl_pool_config_held(dp)); if (snap == NULL) return (B_FALSE); - if (ds->ds_phys->ds_bp.blk_birth > - snap->ds_phys->ds_creation_txg) { + if (dsl_dataset_phys(ds)->ds_bp.blk_birth > + dsl_dataset_phys(snap)->ds_creation_txg) { objset_t *os, *os_snap; /* * It may be that only the ZIL differs, because it was @@ -1874,7 +1895,8 @@ dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp, mutex_enter(&ds->ds_lock); (void) strcpy(ds->ds_snapname, ddrsa->ddrsa_newsnapname); mutex_exit(&ds->ds_lock); - VERIFY0(zap_add(dp->dp_meta_objset, hds->ds_phys->ds_snapnames_zapobj, + VERIFY0(zap_add(dp->dp_meta_objset, + dsl_dataset_phys(hds)->ds_snapnames_zapobj, ds->ds_snapname, 8, 1, &ds->ds_object, tx)); #ifdef __FreeBSD__ @@ -1988,7 +2010,7 @@ dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx) } /* must have a most recent snapshot */ - if (ds->ds_phys->ds_prev_snap_txg < TXG_INITIAL) { + if (dsl_dataset_phys(ds)->ds_prev_snap_txg < TXG_INITIAL) { dsl_dataset_rele(ds, FTAG); return (SET_ERROR(EINVAL)); } @@ -2007,7 +2029,7 @@ dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx) fnvlist_lookup_nvlist(fnvpair_value_nvlist(pair), zfs_prop_to_name(ZFS_PROP_CREATETXG)); uint64_t createtxg = fnvlist_lookup_uint64(valuenv, "value"); - if (createtxg > ds->ds_phys->ds_prev_snap_txg) { + if (createtxg > dsl_dataset_phys(ds)->ds_prev_snap_txg) { fnvlist_free(bookmarks); dsl_dataset_rele(ds, FTAG); return (SET_ERROR(EEXIST)); @@ -2026,7 +2048,7 @@ dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx) * the refquota. */ if (ds->ds_quota != 0 && - ds->ds_prev->ds_phys->ds_referenced_bytes > ds->ds_quota) { + dsl_dataset_phys(ds->ds_prev)->ds_referenced_bytes > ds->ds_quota) { dsl_dataset_rele(ds, FTAG); return (SET_ERROR(EDQUOT)); } @@ -2039,7 +2061,7 @@ dsl_dataset_rollback_check(void *arg, dmu_tx_t *tx) * this space, but the freeing happens over many txg's. */ unused_refres_delta = (int64_t)MIN(ds->ds_reserved, - ds->ds_phys->ds_unique_bytes); + dsl_dataset_phys(ds)->ds_unique_bytes); if (unused_refres_delta > 0 && unused_refres_delta > @@ -2145,7 +2167,7 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) hds = ddpa->ddpa_clone; - if (hds->ds_phys->ds_flags & DS_FLAG_NOPROMOTE) { + if (dsl_dataset_phys(hds)->ds_flags & DS_FLAG_NOPROMOTE) { promote_rele(ddpa, FTAG); return (SET_ERROR(EXDEV)); } @@ -2164,9 +2186,10 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) /* compute origin's new unique space */ snap = list_tail(&ddpa->clone_snaps); - ASSERT3U(snap->ds->ds_phys->ds_prev_snap_obj, ==, origin_ds->ds_object); + ASSERT3U(dsl_dataset_phys(snap->ds)->ds_prev_snap_obj, ==, + origin_ds->ds_object); dsl_deadlist_space_range(&snap->ds->ds_deadlist, - origin_ds->ds_phys->ds_prev_snap_txg, UINT64_MAX, + dsl_dataset_phys(origin_ds)->ds_prev_snap_txg, UINT64_MAX, &ddpa->unique, &unused, &unused); /* @@ -2185,9 +2208,9 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) * uN + kN + kN-1 + ... + kM - uM-1 */ ss_mv_cnt = 0; - ddpa->used = origin_ds->ds_phys->ds_referenced_bytes; - ddpa->comp = origin_ds->ds_phys->ds_compressed_bytes; - ddpa->uncomp = origin_ds->ds_phys->ds_uncompressed_bytes; + ddpa->used = dsl_dataset_phys(origin_ds)->ds_referenced_bytes; + ddpa->comp = dsl_dataset_phys(origin_ds)->ds_compressed_bytes; + ddpa->uncomp = dsl_dataset_phys(origin_ds)->ds_uncompressed_bytes; for (snap = list_head(&ddpa->shared_snaps); snap; snap = list_next(&ddpa->shared_snaps, snap)) { uint64_t val, dlused, dlcomp, dluncomp; @@ -2216,7 +2239,7 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) goto out; /* The very first snapshot does not have a deadlist */ - if (ds->ds_phys->ds_prev_snap_obj == 0) + if (dsl_dataset_phys(ds)->ds_prev_snap_obj == 0) continue; dsl_deadlist_space(&ds->ds_deadlist, @@ -2231,10 +2254,13 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) * so we need to subtract out the clone origin's used space. */ if (ddpa->origin_origin) { - ddpa->used -= ddpa->origin_origin->ds_phys->ds_referenced_bytes; - ddpa->comp -= ddpa->origin_origin->ds_phys->ds_compressed_bytes; + ddpa->used -= + dsl_dataset_phys(ddpa->origin_origin)->ds_referenced_bytes; + ddpa->comp -= + dsl_dataset_phys(ddpa->origin_origin)->ds_compressed_bytes; ddpa->uncomp -= - ddpa->origin_origin->ds_phys->ds_uncompressed_bytes; + dsl_dataset_phys(ddpa->origin_origin)-> + ds_uncompressed_bytes; } /* Check that there is enough space and limit headroom here */ @@ -2249,7 +2275,7 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) * it is the amount of space that will be on all of their * deadlists (that was not born before their new origin). */ - if (hds->ds_dir->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) { + if (dsl_dir_phys(hds->ds_dir)->dd_flags & DD_FLAG_USED_BREAKDOWN) { uint64_t space; /* @@ -2271,9 +2297,11 @@ dsl_dataset_promote_check(void *arg, dmu_tx_t *tx) goto out; ddpa->cloneusedsnap += space; } - if (origin_ds->ds_dir->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) { + if (dsl_dir_phys(origin_ds->ds_dir)->dd_flags & + DD_FLAG_USED_BREAKDOWN) { err = snaplist_space(&ddpa->origin_snaps, - origin_ds->ds_phys->ds_creation_txg, &ddpa->originusedsnap); + dsl_dataset_phys(origin_ds)->ds_creation_txg, + &ddpa->originusedsnap); if (err != 0) goto out; } @@ -2303,7 +2331,7 @@ dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx) VERIFY0(promote_hold(ddpa, dp, FTAG)); hds = ddpa->ddpa_clone; - ASSERT0(hds->ds_phys->ds_flags & DS_FLAG_NOPROMOTE); + ASSERT0(dsl_dataset_phys(hds)->ds_flags & DS_FLAG_NOPROMOTE); snap = list_head(&ddpa->shared_snaps); origin_ds = snap->ds; @@ -2321,47 +2349,49 @@ dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx) /* change origin's next snap */ dmu_buf_will_dirty(origin_ds->ds_dbuf, tx); - oldnext_obj = origin_ds->ds_phys->ds_next_snap_obj; + oldnext_obj = dsl_dataset_phys(origin_ds)->ds_next_snap_obj; snap = list_tail(&ddpa->clone_snaps); - ASSERT3U(snap->ds->ds_phys->ds_prev_snap_obj, ==, origin_ds->ds_object); - origin_ds->ds_phys->ds_next_snap_obj = snap->ds->ds_object; + ASSERT3U(dsl_dataset_phys(snap->ds)->ds_prev_snap_obj, ==, + origin_ds->ds_object); + dsl_dataset_phys(origin_ds)->ds_next_snap_obj = snap->ds->ds_object; /* change the origin's next clone */ - if (origin_ds->ds_phys->ds_next_clones_obj) { + if (dsl_dataset_phys(origin_ds)->ds_next_clones_obj) { dsl_dataset_remove_from_next_clones(origin_ds, snap->ds->ds_object, tx); VERIFY0(zap_add_int(dp->dp_meta_objset, - origin_ds->ds_phys->ds_next_clones_obj, + dsl_dataset_phys(origin_ds)->ds_next_clones_obj, oldnext_obj, tx)); } /* change origin */ dmu_buf_will_dirty(dd->dd_dbuf, tx); - ASSERT3U(dd->dd_phys->dd_origin_obj, ==, origin_ds->ds_object); - dd->dd_phys->dd_origin_obj = odd->dd_phys->dd_origin_obj; + ASSERT3U(dsl_dir_phys(dd)->dd_origin_obj, ==, origin_ds->ds_object); + dsl_dir_phys(dd)->dd_origin_obj = dsl_dir_phys(odd)->dd_origin_obj; dd->dd_origin_txg = origin_head->ds_dir->dd_origin_txg; dmu_buf_will_dirty(odd->dd_dbuf, tx); - odd->dd_phys->dd_origin_obj = origin_ds->ds_object; + dsl_dir_phys(odd)->dd_origin_obj = origin_ds->ds_object; origin_head->ds_dir->dd_origin_txg = - origin_ds->ds_phys->ds_creation_txg; + dsl_dataset_phys(origin_ds)->ds_creation_txg; /* change dd_clone entries */ if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) { VERIFY0(zap_remove_int(dp->dp_meta_objset, - odd->dd_phys->dd_clones, hds->ds_object, tx)); + dsl_dir_phys(odd)->dd_clones, hds->ds_object, tx)); VERIFY0(zap_add_int(dp->dp_meta_objset, - ddpa->origin_origin->ds_dir->dd_phys->dd_clones, + dsl_dir_phys(ddpa->origin_origin->ds_dir)->dd_clones, hds->ds_object, tx)); VERIFY0(zap_remove_int(dp->dp_meta_objset, - ddpa->origin_origin->ds_dir->dd_phys->dd_clones, + dsl_dir_phys(ddpa->origin_origin->ds_dir)->dd_clones, origin_head->ds_object, tx)); - if (dd->dd_phys->dd_clones == 0) { - dd->dd_phys->dd_clones = zap_create(dp->dp_meta_objset, - DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx); + if (dsl_dir_phys(dd)->dd_clones == 0) { + dsl_dir_phys(dd)->dd_clones = + zap_create(dp->dp_meta_objset, DMU_OT_DSL_CLONES, + DMU_OT_NONE, 0, tx); } VERIFY0(zap_add_int(dp->dp_meta_objset, - dd->dd_phys->dd_clones, origin_head->ds_object, tx)); + dsl_dir_phys(dd)->dd_clones, origin_head->ds_object, tx)); } #if defined(__FreeBSD__) && defined(_KERNEL) @@ -2392,15 +2422,15 @@ dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx) VERIFY0(dsl_dataset_snap_remove(origin_head, ds->ds_snapname, tx, B_TRUE)); VERIFY0(zap_add(dp->dp_meta_objset, - hds->ds_phys->ds_snapnames_zapobj, ds->ds_snapname, + dsl_dataset_phys(hds)->ds_snapnames_zapobj, ds->ds_snapname, 8, 1, &ds->ds_object, tx)); dsl_fs_ss_count_adjust(hds->ds_dir, 1, DD_FIELD_SNAPSHOT_COUNT, tx); /* change containing dsl_dir */ dmu_buf_will_dirty(ds->ds_dbuf, tx); - ASSERT3U(ds->ds_phys->ds_dir_obj, ==, odd->dd_object); - ds->ds_phys->ds_dir_obj = dd->dd_object; + ASSERT3U(dsl_dataset_phys(ds)->ds_dir_obj, ==, odd->dd_object); + dsl_dataset_phys(ds)->ds_dir_obj = dd->dd_object; ASSERT3P(ds->ds_dir, ==, odd); dsl_dir_rele(ds->ds_dir, ds); VERIFY0(dsl_dir_hold_obj(dp, dd->dd_object, @@ -2413,13 +2443,13 @@ dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx) #endif /* move any clone references */ - if (ds->ds_phys->ds_next_clones_obj && + if (dsl_dataset_phys(ds)->ds_next_clones_obj && spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) { zap_cursor_t zc; zap_attribute_t za; for (zap_cursor_init(&zc, dp->dp_meta_objset, - ds->ds_phys->ds_next_clones_obj); + dsl_dataset_phys(ds)->ds_next_clones_obj); zap_cursor_retrieve(&zc, &za) == 0; zap_cursor_advance(&zc)) { dsl_dataset_t *cnds; @@ -2435,12 +2465,13 @@ dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx) VERIFY0(dsl_dataset_hold_obj(dp, za.za_first_integer, FTAG, &cnds)); - o = cnds->ds_dir->dd_phys->dd_head_dataset_obj; + o = dsl_dir_phys(cnds->ds_dir)-> + dd_head_dataset_obj; VERIFY0(zap_remove_int(dp->dp_meta_objset, - odd->dd_phys->dd_clones, o, tx)); + dsl_dir_phys(odd)->dd_clones, o, tx)); VERIFY0(zap_add_int(dp->dp_meta_objset, - dd->dd_phys->dd_clones, o, tx)); + dsl_dir_phys(dd)->dd_clones, o, tx)); dsl_dataset_rele(cnds, FTAG); } zap_cursor_fini(&zc); @@ -2463,7 +2494,7 @@ dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx) */ delta = ddpa->cloneusedsnap - - dd->dd_phys->dd_used_breakdown[DD_USED_SNAP]; + dsl_dir_phys(dd)->dd_used_breakdown[DD_USED_SNAP]; ASSERT3S(delta, >=, 0); ASSERT3U(ddpa->used, >=, delta); dsl_dir_diduse_space(dd, DD_USED_SNAP, delta, 0, 0, tx); @@ -2471,14 +2502,14 @@ dsl_dataset_promote_sync(void *arg, dmu_tx_t *tx) ddpa->used - delta, ddpa->comp, ddpa->uncomp, tx); delta = ddpa->originusedsnap - - odd->dd_phys->dd_used_breakdown[DD_USED_SNAP]; + dsl_dir_phys(odd)->dd_used_breakdown[DD_USED_SNAP]; ASSERT3S(delta, <=, 0); ASSERT3U(ddpa->used, >=, -delta); dsl_dir_diduse_space(odd, DD_USED_SNAP, delta, 0, 0, tx); dsl_dir_diduse_space(odd, DD_USED_HEAD, -ddpa->used - delta, -ddpa->comp, -ddpa->uncomp, tx); - origin_ds->ds_phys->ds_unique_bytes = ddpa->unique; + dsl_dataset_phys(origin_ds)->ds_unique_bytes = ddpa->unique; /* log history record */ spa_history_log_internal_ds(hds, "promote", tx, ""); @@ -2513,12 +2544,12 @@ snaplist_make(dsl_pool_t *dp, return (err); if (first_obj == 0) - first_obj = ds->ds_dir->dd_phys->dd_origin_obj; + first_obj = dsl_dir_phys(ds->ds_dir)->dd_origin_obj; snap = kmem_alloc(sizeof (*snap), KM_SLEEP); snap->ds = ds; list_insert_tail(l, snap); - obj = ds->ds_phys->ds_prev_snap_obj; + obj = dsl_dataset_phys(ds)->ds_prev_snap_obj; } return (0); @@ -2574,7 +2605,7 @@ promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp, void *tag) return (SET_ERROR(EINVAL)); } - error = snaplist_make(dp, 0, dd->dd_phys->dd_origin_obj, + error = snaplist_make(dp, 0, dsl_dir_phys(dd)->dd_origin_obj, &ddpa->shared_snaps, tag); if (error != 0) goto out; @@ -2585,16 +2616,16 @@ promote_hold(dsl_dataset_promote_arg_t *ddpa, dsl_pool_t *dp, void *tag) goto out; snap = list_head(&ddpa->shared_snaps); - ASSERT3U(snap->ds->ds_object, ==, dd->dd_phys->dd_origin_obj); - error = snaplist_make(dp, dd->dd_phys->dd_origin_obj, - snap->ds->ds_dir->dd_phys->dd_head_dataset_obj, + ASSERT3U(snap->ds->ds_object, ==, dsl_dir_phys(dd)->dd_origin_obj); + error = snaplist_make(dp, dsl_dir_phys(dd)->dd_origin_obj, + dsl_dir_phys(snap->ds->ds_dir)->dd_head_dataset_obj, &ddpa->origin_snaps, tag); if (error != 0) goto out; - if (snap->ds->ds_dir->dd_phys->dd_origin_obj != 0) { + if (dsl_dir_phys(snap->ds->ds_dir)->dd_origin_obj != 0) { error = dsl_dataset_hold_obj(dp, - snap->ds->ds_dir->dd_phys->dd_origin_obj, + dsl_dir_phys(snap->ds->ds_dir)->dd_origin_obj, tag, &ddpa->origin_origin); if (error != 0) goto out; @@ -2638,7 +2669,8 @@ dsl_dataset_promote(const char *name, char *conflsnap) if (error != 0) return (error); error = zap_count(dmu_objset_pool(os)->dp_meta_objset, - dmu_objset_ds(os)->ds_phys->ds_snapnames_zapobj, &numsnaps); + dsl_dataset_phys(dmu_objset_ds(os))->ds_snapnames_zapobj, + &numsnaps); dmu_objset_rele(os, FTAG); if (error != 0) return (error); @@ -2689,9 +2721,9 @@ dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone, /* check amount of any unconsumed refreservation */ unused_refres_delta = (int64_t)MIN(origin_head->ds_reserved, - origin_head->ds_phys->ds_unique_bytes) - + dsl_dataset_phys(origin_head)->ds_unique_bytes) - (int64_t)MIN(origin_head->ds_reserved, - clone->ds_phys->ds_unique_bytes); + dsl_dataset_phys(clone)->ds_unique_bytes); if (unused_refres_delta > 0 && unused_refres_delta > @@ -2700,7 +2732,8 @@ dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone, /* clone can't be over the head's refquota */ if (origin_head->ds_quota != 0 && - clone->ds_phys->ds_referenced_bytes > origin_head->ds_quota) + dsl_dataset_phys(clone)->ds_referenced_bytes > + origin_head->ds_quota) return (SET_ERROR(EDQUOT)); return (0); @@ -2715,7 +2748,7 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone, ASSERT(clone->ds_reserved == 0); ASSERT(origin_head->ds_quota == 0 || - clone->ds_phys->ds_unique_bytes <= origin_head->ds_quota); + dsl_dataset_phys(clone)->ds_unique_bytes <= origin_head->ds_quota); ASSERT3P(clone->ds_prev, ==, origin_head->ds_prev); dmu_buf_will_dirty(clone->ds_dbuf, tx); @@ -2733,9 +2766,9 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone, unused_refres_delta = (int64_t)MIN(origin_head->ds_reserved, - origin_head->ds_phys->ds_unique_bytes) - + dsl_dataset_phys(origin_head)->ds_unique_bytes) - (int64_t)MIN(origin_head->ds_reserved, - clone->ds_phys->ds_unique_bytes); + dsl_dataset_phys(clone)->ds_unique_bytes); /* * Reset origin's unique bytes, if it exists. @@ -2746,16 +2779,17 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone, dmu_buf_will_dirty(origin->ds_dbuf, tx); dsl_deadlist_space_range(&clone->ds_deadlist, - origin->ds_phys->ds_prev_snap_txg, UINT64_MAX, - &origin->ds_phys->ds_unique_bytes, &comp, &uncomp); + dsl_dataset_phys(origin)->ds_prev_snap_txg, UINT64_MAX, + &dsl_dataset_phys(origin)->ds_unique_bytes, &comp, &uncomp); } /* swap blkptrs */ { blkptr_t tmp; - tmp = origin_head->ds_phys->ds_bp; - origin_head->ds_phys->ds_bp = clone->ds_phys->ds_bp; - clone->ds_phys->ds_bp = tmp; + tmp = dsl_dataset_phys(origin_head)->ds_bp; + dsl_dataset_phys(origin_head)->ds_bp = + dsl_dataset_phys(clone)->ds_bp; + dsl_dataset_phys(clone)->ds_bp = tmp; } /* set dd_*_bytes */ @@ -2764,7 +2798,7 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone, uint64_t cdl_used, cdl_comp, cdl_uncomp; uint64_t odl_used, odl_comp, odl_uncomp; - ASSERT3U(clone->ds_dir->dd_phys-> + ASSERT3U(dsl_dir_phys(clone->ds_dir)-> dd_used_breakdown[DD_USED_SNAP], ==, 0); dsl_deadlist_space(&clone->ds_deadlist, @@ -2772,13 +2806,18 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone, dsl_deadlist_space(&origin_head->ds_deadlist, &odl_used, &odl_comp, &odl_uncomp); - dused = clone->ds_phys->ds_referenced_bytes + cdl_used - - (origin_head->ds_phys->ds_referenced_bytes + odl_used); - dcomp = clone->ds_phys->ds_compressed_bytes + cdl_comp - - (origin_head->ds_phys->ds_compressed_bytes + odl_comp); - duncomp = clone->ds_phys->ds_uncompressed_bytes + + dused = dsl_dataset_phys(clone)->ds_referenced_bytes + + cdl_used - + (dsl_dataset_phys(origin_head)->ds_referenced_bytes + + odl_used); + dcomp = dsl_dataset_phys(clone)->ds_compressed_bytes + + cdl_comp - + (dsl_dataset_phys(origin_head)->ds_compressed_bytes + + odl_comp); + duncomp = dsl_dataset_phys(clone)->ds_uncompressed_bytes + cdl_uncomp - - (origin_head->ds_phys->ds_uncompressed_bytes + odl_uncomp); + (dsl_dataset_phys(origin_head)->ds_uncompressed_bytes + + odl_uncomp); dsl_dir_diduse_space(origin_head->ds_dir, DD_USED_HEAD, dused, dcomp, duncomp, tx); @@ -2802,14 +2841,14 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone, } /* swap ds_*_bytes */ - SWITCH64(origin_head->ds_phys->ds_referenced_bytes, - clone->ds_phys->ds_referenced_bytes); - SWITCH64(origin_head->ds_phys->ds_compressed_bytes, - clone->ds_phys->ds_compressed_bytes); - SWITCH64(origin_head->ds_phys->ds_uncompressed_bytes, - clone->ds_phys->ds_uncompressed_bytes); - SWITCH64(origin_head->ds_phys->ds_unique_bytes, - clone->ds_phys->ds_unique_bytes); + SWITCH64(dsl_dataset_phys(origin_head)->ds_referenced_bytes, + dsl_dataset_phys(clone)->ds_referenced_bytes); + SWITCH64(dsl_dataset_phys(origin_head)->ds_compressed_bytes, + dsl_dataset_phys(clone)->ds_compressed_bytes); + SWITCH64(dsl_dataset_phys(origin_head)->ds_uncompressed_bytes, + dsl_dataset_phys(clone)->ds_uncompressed_bytes); + SWITCH64(dsl_dataset_phys(origin_head)->ds_unique_bytes, + dsl_dataset_phys(clone)->ds_unique_bytes); /* apply any parent delta for change in unconsumed refreservation */ dsl_dir_diduse_space(origin_head->ds_dir, DD_USED_REFRSRV, @@ -2820,12 +2859,12 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone, */ dsl_deadlist_close(&clone->ds_deadlist); dsl_deadlist_close(&origin_head->ds_deadlist); - SWITCH64(origin_head->ds_phys->ds_deadlist_obj, - clone->ds_phys->ds_deadlist_obj); + SWITCH64(dsl_dataset_phys(origin_head)->ds_deadlist_obj, + dsl_dataset_phys(clone)->ds_deadlist_obj); dsl_deadlist_open(&clone->ds_deadlist, dp->dp_meta_objset, - clone->ds_phys->ds_deadlist_obj); + dsl_dataset_phys(clone)->ds_deadlist_obj); dsl_deadlist_open(&origin_head->ds_deadlist, dp->dp_meta_objset, - origin_head->ds_phys->ds_deadlist_obj); + dsl_dataset_phys(origin_head)->ds_deadlist_obj); dsl_scan_ds_clone_swapped(origin_head, clone, tx); @@ -2876,10 +2915,11 @@ dsl_dataset_check_quota(dsl_dataset_t *ds, boolean_t check_quota, /* * Make a space adjustment for reserved bytes. */ - if (ds->ds_reserved > ds->ds_phys->ds_unique_bytes) { + if (ds->ds_reserved > dsl_dataset_phys(ds)->ds_unique_bytes) { ASSERT3U(*used, >=, - ds->ds_reserved - ds->ds_phys->ds_unique_bytes); - *used -= (ds->ds_reserved - ds->ds_phys->ds_unique_bytes); + ds->ds_reserved - dsl_dataset_phys(ds)->ds_unique_bytes); + *used -= + (ds->ds_reserved - dsl_dataset_phys(ds)->ds_unique_bytes); *ref_rsrv = asize - MIN(asize, parent_delta(ds, asize + inflight)); } @@ -2894,9 +2934,10 @@ dsl_dataset_check_quota(dsl_dataset_t *ds, boolean_t check_quota, * on-disk is over quota and there are no pending changes (which * may free up space for us). */ - if (ds->ds_phys->ds_referenced_bytes + inflight >= ds->ds_quota) { + if (dsl_dataset_phys(ds)->ds_referenced_bytes + inflight >= + ds->ds_quota) { if (inflight > 0 || - ds->ds_phys->ds_referenced_bytes < ds->ds_quota) + dsl_dataset_phys(ds)->ds_referenced_bytes < ds->ds_quota) error = SET_ERROR(ERESTART); else error = SET_ERROR(EDQUOT); @@ -2948,7 +2989,7 @@ dsl_dataset_set_refquota_check(void *arg, dmu_tx_t *tx) return (0); } - if (newval < ds->ds_phys->ds_referenced_bytes || + if (newval < dsl_dataset_phys(ds)->ds_referenced_bytes || newval < ds->ds_reserved) { dsl_dataset_rele(ds, FTAG); return (SET_ERROR(ENOSPC)); @@ -3038,7 +3079,7 @@ dsl_dataset_set_refreservation_check(void *arg, dmu_tx_t *tx) mutex_enter(&ds->ds_lock); if (!DS_UNIQUE_IS_ACCURATE(ds)) dsl_dataset_recalc_head_uniq(ds); - unique = ds->ds_phys->ds_unique_bytes; + unique = dsl_dataset_phys(ds)->ds_unique_bytes; mutex_exit(&ds->ds_lock); if (MAX(unique, newval) > MAX(unique, ds->ds_reserved)) { @@ -3075,7 +3116,7 @@ dsl_dataset_set_refreservation_sync_impl(dsl_dataset_t *ds, mutex_enter(&ds->ds_dir->dd_lock); mutex_enter(&ds->ds_lock); ASSERT(DS_UNIQUE_IS_ACCURATE(ds)); - unique = ds->ds_phys->ds_unique_bytes; + unique = dsl_dataset_phys(ds)->ds_unique_bytes; delta = MAX(0, (int64_t)(newval - unique)) - MAX(0, (int64_t)(ds->ds_reserved - unique)); ds->ds_reserved = newval; @@ -3141,16 +3182,16 @@ dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new, ASSERT(dsl_pool_config_held(dp)); *usedp = 0; - *usedp += new->ds_phys->ds_referenced_bytes; - *usedp -= oldsnap->ds_phys->ds_referenced_bytes; + *usedp += dsl_dataset_phys(new)->ds_referenced_bytes; + *usedp -= dsl_dataset_phys(oldsnap)->ds_referenced_bytes; *compp = 0; - *compp += new->ds_phys->ds_compressed_bytes; - *compp -= oldsnap->ds_phys->ds_compressed_bytes; + *compp += dsl_dataset_phys(new)->ds_compressed_bytes; + *compp -= dsl_dataset_phys(oldsnap)->ds_compressed_bytes; *uncompp = 0; - *uncompp += new->ds_phys->ds_uncompressed_bytes; - *uncompp -= oldsnap->ds_phys->ds_uncompressed_bytes; + *uncompp += dsl_dataset_phys(new)->ds_uncompressed_bytes; + *uncompp -= dsl_dataset_phys(oldsnap)->ds_uncompressed_bytes; snapobj = new->ds_object; while (snapobj != oldsnap->ds_object) { @@ -3165,8 +3206,8 @@ dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new, break; } - if (snap->ds_phys->ds_prev_snap_txg == - oldsnap->ds_phys->ds_creation_txg) { + if (dsl_dataset_phys(snap)->ds_prev_snap_txg == + dsl_dataset_phys(oldsnap)->ds_creation_txg) { /* * The blocks in the deadlist can not be born after * ds_prev_snap_txg, so get the whole deadlist space, @@ -3179,7 +3220,7 @@ dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new, &used, &comp, &uncomp); } else { dsl_deadlist_space_range(&snap->ds_deadlist, - 0, oldsnap->ds_phys->ds_creation_txg, + 0, dsl_dataset_phys(oldsnap)->ds_creation_txg, &used, &comp, &uncomp); } *usedp += used; @@ -3191,7 +3232,7 @@ dsl_dataset_space_written(dsl_dataset_t *oldsnap, dsl_dataset_t *new, * (ds_prev_snap_obj == 0) before oldsnap, then oldsnap * was not a snapshot of/before new. */ - snapobj = snap->ds_phys->ds_prev_snap_obj; + snapobj = dsl_dataset_phys(snap)->ds_prev_snap_obj; if (snap != new) dsl_dataset_rele(snap, FTAG); if (snapobj == 0) { @@ -3235,13 +3276,13 @@ dsl_dataset_space_wouldfree(dsl_dataset_t *firstsnap, * is before lastsnap. */ if (firstsnap->ds_dir != lastsnap->ds_dir || - firstsnap->ds_phys->ds_creation_txg > - lastsnap->ds_phys->ds_creation_txg) + dsl_dataset_phys(firstsnap)->ds_creation_txg > + dsl_dataset_phys(lastsnap)->ds_creation_txg) return (SET_ERROR(EINVAL)); *usedp = *compp = *uncompp = 0; - snapobj = lastsnap->ds_phys->ds_next_snap_obj; + snapobj = dsl_dataset_phys(lastsnap)->ds_next_snap_obj; while (snapobj != firstsnap->ds_object) { dsl_dataset_t *ds; uint64_t used, comp, uncomp; @@ -3251,13 +3292,13 @@ dsl_dataset_space_wouldfree(dsl_dataset_t *firstsnap, break; dsl_deadlist_space_range(&ds->ds_deadlist, - firstsnap->ds_phys->ds_prev_snap_txg, UINT64_MAX, + dsl_dataset_phys(firstsnap)->ds_prev_snap_txg, UINT64_MAX, &used, &comp, &uncomp); *usedp += used; *compp += comp; *uncompp += uncomp; - snapobj = ds->ds_phys->ds_prev_snap_obj; + snapobj = dsl_dataset_phys(ds)->ds_prev_snap_obj; ASSERT3U(snapobj, !=, 0); dsl_dataset_rele(ds, FTAG); } @@ -3356,10 +3397,10 @@ dsl_dataset_is_before(dsl_dataset_t *later, dsl_dataset_t *earlier, ASSERT(dsl_dataset_is_snapshot(earlier) || earlier_txg != 0); if (earlier_txg == 0) - earlier_txg = earlier->ds_phys->ds_creation_txg; + earlier_txg = dsl_dataset_phys(earlier)->ds_creation_txg; if (dsl_dataset_is_snapshot(later) && - earlier_txg >= later->ds_phys->ds_creation_txg) + earlier_txg >= dsl_dataset_phys(later)->ds_creation_txg) return (B_FALSE); if (later->ds_dir == earlier->ds_dir) @@ -3367,11 +3408,11 @@ dsl_dataset_is_before(dsl_dataset_t *later, dsl_dataset_t *earlier, if (!dsl_dir_is_clone(later->ds_dir)) return (B_FALSE); - if (later->ds_dir->dd_phys->dd_origin_obj == earlier->ds_object) + if (dsl_dir_phys(later->ds_dir)->dd_origin_obj == earlier->ds_object) return (B_TRUE); dsl_dataset_t *origin; error = dsl_dataset_hold_obj(dp, - later->ds_dir->dd_phys->dd_origin_obj, FTAG, &origin); + dsl_dir_phys(later->ds_dir)->dd_origin_obj, FTAG, &origin); if (error != 0) return (B_FALSE); ret = dsl_dataset_is_before(origin, earlier, earlier_txg); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c index 8c8e3746eecb..4ac562bfdba3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c @@ -308,8 +308,9 @@ dsl_deadlist_regenerate(objset_t *os, uint64_t dlobj, while (mrs_obj != 0) { dsl_dataset_t *ds; VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, mrs_obj, FTAG, &ds)); - dsl_deadlist_add_key(&dl, ds->ds_phys->ds_prev_snap_txg, tx); - mrs_obj = ds->ds_phys->ds_prev_snap_obj; + dsl_deadlist_add_key(&dl, + dsl_dataset_phys(ds)->ds_prev_snap_txg, tx); + mrs_obj = dsl_dataset_phys(ds)->ds_prev_snap_obj; dsl_dataset_rele(ds, FTAG); } dsl_deadlist_close(&dl); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c index bdedccf4d872..2912e333f8f4 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c @@ -164,10 +164,10 @@ dsl_deleg_set_sync(void *arg, dmu_tx_t *tx) VERIFY0(dsl_dir_hold(dp, dda->dda_name, FTAG, &dd, NULL)); - zapobj = dd->dd_phys->dd_deleg_zapobj; + zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj; if (zapobj == 0) { dmu_buf_will_dirty(dd->dd_dbuf, tx); - zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos, + zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); } @@ -208,7 +208,7 @@ dsl_deleg_unset_sync(void *arg, dmu_tx_t *tx) uint64_t zapobj; VERIFY0(dsl_dir_hold(dp, dda->dda_name, FTAG, &dd, NULL)); - zapobj = dd->dd_phys->dd_deleg_zapobj; + zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj; if (zapobj == 0) { dsl_dir_rele(dd, FTAG); return; @@ -332,14 +332,14 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp) uint64_t n; char source[MAXNAMELEN]; - if (dd->dd_phys->dd_deleg_zapobj == 0 || - zap_count(mos, dd->dd_phys->dd_deleg_zapobj, &n) != 0 || - n == 0) + if (dsl_dir_phys(dd)->dd_deleg_zapobj == 0 || + zap_count(mos, + dsl_dir_phys(dd)->dd_deleg_zapobj, &n) != 0 || n == 0) continue; sp_nvp = fnvlist_alloc(); for (zap_cursor_init(&basezc, mos, - dd->dd_phys->dd_deleg_zapobj); + dsl_dir_phys(dd)->dd_deleg_zapobj); zap_cursor_retrieve(&basezc, &baseza) == 0; zap_cursor_advance(&basezc)) { zap_cursor_t zc; @@ -594,7 +594,7 @@ dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr) if (!zoned) break; } - zapobj = dd->dd_phys->dd_deleg_zapobj; + zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj; if (zapobj == 0) continue; @@ -673,7 +673,7 @@ copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj, { objset_t *mos = dd->dd_pool->dp_meta_objset; uint64_t jumpobj, pjumpobj; - uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj; + uint64_t zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj; zap_cursor_t zc; zap_attribute_t za; char whokey[ZFS_MAX_DELEG_NAME]; @@ -686,7 +686,7 @@ copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj, if (zapobj == 0) { dmu_buf_will_dirty(dd->dd_dbuf, tx); - zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos, + zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); } @@ -724,7 +724,7 @@ dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr) return; for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) { - uint64_t pzapobj = dd->dd_phys->dd_deleg_zapobj; + uint64_t pzapobj = dsl_dir_phys(dd)->dd_deleg_zapobj; if (pzapobj == 0) continue; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c index 1237641583a1..a776e144f1d2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c @@ -78,7 +78,7 @@ dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer) /* * Can't delete a branch point. */ - if (ds->ds_phys->ds_num_children > 1) + if (dsl_dataset_phys(ds)->ds_num_children > 1) return (SET_ERROR(EEXIST)); return (0); @@ -147,12 +147,12 @@ process_old_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx) ASSERT(!BP_IS_HOLE(bp)); - if (bp->blk_birth <= poa->ds->ds_phys->ds_prev_snap_txg) { + if (bp->blk_birth <= dsl_dataset_phys(poa->ds)->ds_prev_snap_txg) { dsl_deadlist_insert(&poa->ds->ds_deadlist, bp, tx); if (poa->ds_prev && !poa->after_branch_point && bp->blk_birth > - poa->ds_prev->ds_phys->ds_prev_snap_txg) { - poa->ds_prev->ds_phys->ds_unique_bytes += + dsl_dataset_phys(poa->ds_prev)->ds_prev_snap_txg) { + dsl_dataset_phys(poa->ds_prev)->ds_unique_bytes += bp_get_dsize_sync(dp->dp_spa, bp); } } else { @@ -183,7 +183,7 @@ process_old_deadlist(dsl_dataset_t *ds, dsl_dataset_t *ds_prev, VERIFY0(bpobj_iterate(&ds_next->ds_deadlist.dl_bpobj, process_old_cb, &poa, tx)); VERIFY0(zio_wait(poa.pio)); - ASSERT3U(poa.used, ==, ds->ds_phys->ds_unique_bytes); + ASSERT3U(poa.used, ==, dsl_dataset_phys(ds)->ds_unique_bytes); /* change snapused */ dsl_dir_diduse_space(ds->ds_dir, DD_USED_SNAP, @@ -192,12 +192,14 @@ process_old_deadlist(dsl_dataset_t *ds, dsl_dataset_t *ds_prev, /* swap next's deadlist to our deadlist */ dsl_deadlist_close(&ds->ds_deadlist); dsl_deadlist_close(&ds_next->ds_deadlist); - deadlist_obj = ds->ds_phys->ds_deadlist_obj; - ds->ds_phys->ds_deadlist_obj = ds_next->ds_phys->ds_deadlist_obj; - ds_next->ds_phys->ds_deadlist_obj = deadlist_obj; - dsl_deadlist_open(&ds->ds_deadlist, mos, ds->ds_phys->ds_deadlist_obj); + deadlist_obj = dsl_dataset_phys(ds)->ds_deadlist_obj; + dsl_dataset_phys(ds)->ds_deadlist_obj = + dsl_dataset_phys(ds_next)->ds_deadlist_obj; + dsl_dataset_phys(ds_next)->ds_deadlist_obj = deadlist_obj; + dsl_deadlist_open(&ds->ds_deadlist, mos, + dsl_dataset_phys(ds)->ds_deadlist_obj); dsl_deadlist_open(&ds_next->ds_deadlist, mos, - ds_next->ds_phys->ds_deadlist_obj); + dsl_dataset_phys(ds_next)->ds_deadlist_obj); } static void @@ -212,10 +214,10 @@ dsl_dataset_remove_clones_key(dsl_dataset_t *ds, uint64_t mintxg, dmu_tx_t *tx) * find the clones, but dsl_deadlist_remove_key() is a no-op so it * doesn't matter. */ - if (ds->ds_dir->dd_phys->dd_clones == 0) + if (dsl_dir_phys(ds->ds_dir)->dd_clones == 0) return; - for (zap_cursor_init(&zc, mos, ds->ds_dir->dd_phys->dd_clones); + for (zap_cursor_init(&zc, mos, dsl_dir_phys(ds->ds_dir)->dd_clones); zap_cursor_retrieve(&zc, &za) == 0; zap_cursor_advance(&zc)) { dsl_dataset_t *clone; @@ -243,19 +245,20 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) uint64_t obj; ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock)); - ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg); + ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg); ASSERT(refcount_is_zero(&ds->ds_longholds)); if (defer && - (ds->ds_userrefs > 0 || ds->ds_phys->ds_num_children > 1)) { + (ds->ds_userrefs > 0 || + dsl_dataset_phys(ds)->ds_num_children > 1)) { ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS); dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_flags |= DS_FLAG_DEFER_DESTROY; + dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_DEFER_DESTROY; spa_history_log_internal_ds(ds, "defer_destroy", tx, ""); return; } - ASSERT3U(ds->ds_phys->ds_num_children, <=, 1); + ASSERT3U(dsl_dataset_phys(ds)->ds_num_children, <=, 1); /* We need to log before removing it from the namespace. */ spa_history_log_internal_ds(ds, "destroy", tx, ""); @@ -268,26 +271,28 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) ASSERT0(zap_contains(mos, obj, DS_FIELD_LARGE_BLOCKS)); spa_feature_decr(dp->dp_spa, SPA_FEATURE_LARGE_BLOCKS, tx); } - if (ds->ds_phys->ds_prev_snap_obj != 0) { + if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) { ASSERT3P(ds->ds_prev, ==, NULL); VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_prev_snap_obj, FTAG, &ds_prev)); + dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &ds_prev)); after_branch_point = - (ds_prev->ds_phys->ds_next_snap_obj != obj); + (dsl_dataset_phys(ds_prev)->ds_next_snap_obj != obj); dmu_buf_will_dirty(ds_prev->ds_dbuf, tx); if (after_branch_point && - ds_prev->ds_phys->ds_next_clones_obj != 0) { + dsl_dataset_phys(ds_prev)->ds_next_clones_obj != 0) { dsl_dataset_remove_from_next_clones(ds_prev, obj, tx); - if (ds->ds_phys->ds_next_snap_obj != 0) { + if (dsl_dataset_phys(ds)->ds_next_snap_obj != 0) { VERIFY0(zap_add_int(mos, - ds_prev->ds_phys->ds_next_clones_obj, - ds->ds_phys->ds_next_snap_obj, tx)); + dsl_dataset_phys(ds_prev)-> + ds_next_clones_obj, + dsl_dataset_phys(ds)->ds_next_snap_obj, + tx)); } } if (!after_branch_point) { - ds_prev->ds_phys->ds_next_snap_obj = - ds->ds_phys->ds_next_snap_obj; + dsl_dataset_phys(ds_prev)->ds_next_snap_obj = + dsl_dataset_phys(ds)->ds_next_snap_obj; } } @@ -296,18 +301,18 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) uint64_t used = 0, comp = 0, uncomp = 0; VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_next_snap_obj, FTAG, &ds_next)); - ASSERT3U(ds_next->ds_phys->ds_prev_snap_obj, ==, obj); + dsl_dataset_phys(ds)->ds_next_snap_obj, FTAG, &ds_next)); + ASSERT3U(dsl_dataset_phys(ds_next)->ds_prev_snap_obj, ==, obj); - old_unique = ds_next->ds_phys->ds_unique_bytes; + old_unique = dsl_dataset_phys(ds_next)->ds_unique_bytes; dmu_buf_will_dirty(ds_next->ds_dbuf, tx); - ds_next->ds_phys->ds_prev_snap_obj = - ds->ds_phys->ds_prev_snap_obj; - ds_next->ds_phys->ds_prev_snap_txg = - ds->ds_phys->ds_prev_snap_txg; - ASSERT3U(ds->ds_phys->ds_prev_snap_txg, ==, - ds_prev ? ds_prev->ds_phys->ds_creation_txg : 0); + dsl_dataset_phys(ds_next)->ds_prev_snap_obj = + dsl_dataset_phys(ds)->ds_prev_snap_obj; + dsl_dataset_phys(ds_next)->ds_prev_snap_txg = + dsl_dataset_phys(ds)->ds_prev_snap_txg; + ASSERT3U(dsl_dataset_phys(ds)->ds_prev_snap_txg, ==, + ds_prev ? dsl_dataset_phys(ds_prev)->ds_creation_txg : 0); if (ds_next->ds_deadlist.dl_oldfmt) { process_old_deadlist(ds, ds_prev, ds_next, @@ -316,38 +321,38 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) /* Adjust prev's unique space. */ if (ds_prev && !after_branch_point) { dsl_deadlist_space_range(&ds_next->ds_deadlist, - ds_prev->ds_phys->ds_prev_snap_txg, - ds->ds_phys->ds_prev_snap_txg, + dsl_dataset_phys(ds_prev)->ds_prev_snap_txg, + dsl_dataset_phys(ds)->ds_prev_snap_txg, &used, &comp, &uncomp); - ds_prev->ds_phys->ds_unique_bytes += used; + dsl_dataset_phys(ds_prev)->ds_unique_bytes += used; } /* Adjust snapused. */ dsl_deadlist_space_range(&ds_next->ds_deadlist, - ds->ds_phys->ds_prev_snap_txg, UINT64_MAX, + dsl_dataset_phys(ds)->ds_prev_snap_txg, UINT64_MAX, &used, &comp, &uncomp); dsl_dir_diduse_space(ds->ds_dir, DD_USED_SNAP, -used, -comp, -uncomp, tx); /* Move blocks to be freed to pool's free list. */ dsl_deadlist_move_bpobj(&ds_next->ds_deadlist, - &dp->dp_free_bpobj, ds->ds_phys->ds_prev_snap_txg, + &dp->dp_free_bpobj, dsl_dataset_phys(ds)->ds_prev_snap_txg, tx); dsl_dir_diduse_space(tx->tx_pool->dp_free_dir, DD_USED_HEAD, used, comp, uncomp, tx); /* Merge our deadlist into next's and free it. */ dsl_deadlist_merge(&ds_next->ds_deadlist, - ds->ds_phys->ds_deadlist_obj, tx); + dsl_dataset_phys(ds)->ds_deadlist_obj, tx); } dsl_deadlist_close(&ds->ds_deadlist); - dsl_deadlist_free(mos, ds->ds_phys->ds_deadlist_obj, tx); + dsl_deadlist_free(mos, dsl_dataset_phys(ds)->ds_deadlist_obj, tx); dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_deadlist_obj = 0; + dsl_dataset_phys(ds)->ds_deadlist_obj = 0; /* Collapse range in clone heads */ dsl_dataset_remove_clones_key(ds, - ds->ds_phys->ds_creation_txg, tx); + dsl_dataset_phys(ds)->ds_creation_txg, tx); if (dsl_dataset_is_snapshot(ds_next)) { dsl_dataset_t *ds_nextnext; @@ -362,21 +367,22 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) * deadlist). */ VERIFY0(dsl_dataset_hold_obj(dp, - ds_next->ds_phys->ds_next_snap_obj, FTAG, &ds_nextnext)); + dsl_dataset_phys(ds_next)->ds_next_snap_obj, + FTAG, &ds_nextnext)); dsl_deadlist_space_range(&ds_nextnext->ds_deadlist, - ds->ds_phys->ds_prev_snap_txg, - ds->ds_phys->ds_creation_txg, + dsl_dataset_phys(ds)->ds_prev_snap_txg, + dsl_dataset_phys(ds)->ds_creation_txg, &used, &comp, &uncomp); - ds_next->ds_phys->ds_unique_bytes += used; + dsl_dataset_phys(ds_next)->ds_unique_bytes += used; dsl_dataset_rele(ds_nextnext, FTAG); ASSERT3P(ds_next->ds_prev, ==, NULL); /* Collapse range in this head. */ dsl_dataset_t *hds; VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_dir->dd_phys->dd_head_dataset_obj, FTAG, &hds)); + dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj, FTAG, &hds)); dsl_deadlist_remove_key(&hds->ds_deadlist, - ds->ds_phys->ds_creation_txg, tx); + dsl_dataset_phys(ds)->ds_creation_txg, tx); dsl_dataset_rele(hds, FTAG); } else { @@ -385,7 +391,7 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) ds_next->ds_prev = NULL; if (ds_prev) { VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_prev_snap_obj, + dsl_dataset_phys(ds)->ds_prev_snap_obj, ds_next, &ds_next->ds_prev)); } @@ -399,7 +405,7 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) if (old_unique < ds_next->ds_reserved) { int64_t mrsdelta; uint64_t new_unique = - ds_next->ds_phys->ds_unique_bytes; + dsl_dataset_phys(ds_next)->ds_unique_bytes; ASSERT(old_unique <= new_unique); mrsdelta = MIN(new_unique - old_unique, @@ -421,9 +427,9 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) /* remove from snapshot namespace */ dsl_dataset_t *ds_head; - ASSERT(ds->ds_phys->ds_snapnames_zapobj == 0); + ASSERT(dsl_dataset_phys(ds)->ds_snapnames_zapobj == 0); VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_dir->dd_phys->dd_head_dataset_obj, FTAG, &ds_head)); + dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj, FTAG, &ds_head)); VERIFY0(dsl_dataset_get_snapname(ds)); #ifdef ZFS_DEBUG { @@ -443,17 +449,20 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx) spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx); - if (ds->ds_phys->ds_next_clones_obj != 0) { + if (dsl_dataset_phys(ds)->ds_next_clones_obj != 0) { uint64_t count; ASSERT0(zap_count(mos, - ds->ds_phys->ds_next_clones_obj, &count) && count == 0); + dsl_dataset_phys(ds)->ds_next_clones_obj, &count) && + count == 0); VERIFY0(dmu_object_free(mos, - ds->ds_phys->ds_next_clones_obj, tx)); + dsl_dataset_phys(ds)->ds_next_clones_obj, tx)); } - if (ds->ds_phys->ds_props_obj != 0) - VERIFY0(zap_destroy(mos, ds->ds_phys->ds_props_obj, tx)); - if (ds->ds_phys->ds_userrefs_obj != 0) - VERIFY0(zap_destroy(mos, ds->ds_phys->ds_userrefs_obj, tx)); + if (dsl_dataset_phys(ds)->ds_props_obj != 0) + VERIFY0(zap_destroy(mos, dsl_dataset_phys(ds)->ds_props_obj, + tx)); + if (dsl_dataset_phys(ds)->ds_userrefs_obj != 0) + VERIFY0(zap_destroy(mos, dsl_dataset_phys(ds)->ds_userrefs_obj, + tx)); dsl_dir_rele(ds->ds_dir, ds); ds->ds_dir = NULL; dmu_object_free_zapified(mos, obj, tx); @@ -555,7 +564,8 @@ kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, dsl_free(ka->tx->tx_pool, ka->tx->tx_txg, bp); } else { ASSERT(zilog == NULL); - ASSERT3U(bp->blk_birth, >, ka->ds->ds_phys->ds_prev_snap_txg); + ASSERT3U(bp->blk_birth, >, + dsl_dataset_phys(ka->ds)->ds_prev_snap_txg); (void) dsl_dataset_block_kill(ka->ds, bp, tx, B_FALSE); } @@ -577,9 +587,10 @@ old_synchronous_dataset_destroy(dsl_dataset_t *ds, dmu_tx_t *tx) ka.ds = ds; ka.tx = tx; VERIFY0(traverse_dataset(ds, - ds->ds_phys->ds_prev_snap_txg, TRAVERSE_POST, + dsl_dataset_phys(ds)->ds_prev_snap_txg, TRAVERSE_POST, kill_blkptr, &ka)); - ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) || ds->ds_phys->ds_unique_bytes == 0); + ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) || + dsl_dataset_phys(ds)->ds_unique_bytes == 0); } typedef struct dsl_destroy_head_arg { @@ -608,21 +619,21 @@ dsl_destroy_head_check_impl(dsl_dataset_t *ds, int expected_holds) * from.) */ if (ds->ds_prev != NULL && - ds->ds_prev->ds_phys->ds_next_snap_obj == ds->ds_object) + dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj == ds->ds_object) return (SET_ERROR(EBUSY)); /* * Can't delete if there are children of this fs. */ error = zap_count(mos, - ds->ds_dir->dd_phys->dd_child_dir_zapobj, &count); + dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, &count); if (error != 0) return (error); if (count != 0) return (SET_ERROR(EEXIST)); if (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev) && - ds->ds_prev->ds_phys->ds_num_children == 2 && + dsl_dataset_phys(ds->ds_prev)->ds_num_children == 2 && ds->ds_prev->ds_userrefs == 0) { /* We need to remove the origin snapshot as well. */ if (!refcount_is_zero(&ds->ds_prev->ds_longholds)) @@ -660,7 +671,7 @@ dsl_dir_destroy_sync(uint64_t ddobj, dmu_tx_t *tx) VERIFY0(dsl_dir_hold_obj(dp, ddobj, NULL, FTAG, &dd)); - ASSERT0(dd->dd_phys->dd_head_dataset_obj); + ASSERT0(dsl_dir_phys(dd)->dd_head_dataset_obj); /* * Decrement the filesystem count for all parent filesystems. @@ -679,16 +690,17 @@ dsl_dir_destroy_sync(uint64_t ddobj, dmu_tx_t *tx) */ dsl_dir_set_reservation_sync_impl(dd, 0, tx); - ASSERT0(dd->dd_phys->dd_used_bytes); - ASSERT0(dd->dd_phys->dd_reserved); + ASSERT0(dsl_dir_phys(dd)->dd_used_bytes); + ASSERT0(dsl_dir_phys(dd)->dd_reserved); for (t = 0; t < DD_USED_NUM; t++) - ASSERT0(dd->dd_phys->dd_used_breakdown[t]); + ASSERT0(dsl_dir_phys(dd)->dd_used_breakdown[t]); - VERIFY0(zap_destroy(mos, dd->dd_phys->dd_child_dir_zapobj, tx)); - VERIFY0(zap_destroy(mos, dd->dd_phys->dd_props_zapobj, tx)); - VERIFY0(dsl_deleg_destroy(mos, dd->dd_phys->dd_deleg_zapobj, tx)); + VERIFY0(zap_destroy(mos, dsl_dir_phys(dd)->dd_child_dir_zapobj, tx)); + VERIFY0(zap_destroy(mos, dsl_dir_phys(dd)->dd_props_zapobj, tx)); + VERIFY0(dsl_deleg_destroy(mos, dsl_dir_phys(dd)->dd_deleg_zapobj, tx)); VERIFY0(zap_remove(mos, - dd->dd_parent->dd_phys->dd_child_dir_zapobj, dd->dd_myname, tx)); + dsl_dir_phys(dd->dd_parent)->dd_child_dir_zapobj, + dd->dd_myname, tx)); dsl_dir_rele(dd, FTAG); dmu_object_free_zapified(mos, ddobj, tx); @@ -702,10 +714,10 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx) uint64_t obj, ddobj, prevobj = 0; boolean_t rmorigin; - ASSERT3U(ds->ds_phys->ds_num_children, <=, 1); + ASSERT3U(dsl_dataset_phys(ds)->ds_num_children, <=, 1); ASSERT(ds->ds_prev == NULL || - ds->ds_prev->ds_phys->ds_next_snap_obj != ds->ds_object); - ASSERT3U(ds->ds_phys->ds_bp.blk_birth, <=, tx->tx_txg); + dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj != ds->ds_object); + ASSERT3U(dsl_dataset_phys(ds)->ds_bp.blk_birth, <=, tx->tx_txg); ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock)); /* We need to log before removing it from the namespace. */ @@ -713,7 +725,7 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx) rmorigin = (dsl_dir_is_clone(ds->ds_dir) && DS_IS_DEFER_DESTROY(ds->ds_prev) && - ds->ds_prev->ds_phys->ds_num_children == 2 && + dsl_dataset_phys(ds->ds_prev)->ds_num_children == 2 && ds->ds_prev->ds_userrefs == 0); /* Remove our reservation. */ @@ -731,20 +743,21 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx) obj = ds->ds_object; - if (ds->ds_phys->ds_prev_snap_obj != 0) { + if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) { /* This is a clone */ ASSERT(ds->ds_prev != NULL); - ASSERT3U(ds->ds_prev->ds_phys->ds_next_snap_obj, !=, obj); - ASSERT0(ds->ds_phys->ds_next_snap_obj); + ASSERT3U(dsl_dataset_phys(ds->ds_prev)->ds_next_snap_obj, !=, + obj); + ASSERT0(dsl_dataset_phys(ds)->ds_next_snap_obj); dmu_buf_will_dirty(ds->ds_prev->ds_dbuf, tx); - if (ds->ds_prev->ds_phys->ds_next_clones_obj != 0) { + if (dsl_dataset_phys(ds->ds_prev)->ds_next_clones_obj != 0) { dsl_dataset_remove_from_next_clones(ds->ds_prev, obj, tx); } - ASSERT3U(ds->ds_prev->ds_phys->ds_num_children, >, 1); - ds->ds_prev->ds_phys->ds_num_children--; + ASSERT3U(dsl_dataset_phys(ds->ds_prev)->ds_num_children, >, 1); + dsl_dataset_phys(ds->ds_prev)->ds_num_children--; } /* @@ -753,9 +766,9 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx) * safe to ignore the deadlist contents.) */ dsl_deadlist_close(&ds->ds_deadlist); - dsl_deadlist_free(mos, ds->ds_phys->ds_deadlist_obj, tx); + dsl_deadlist_free(mos, dsl_dataset_phys(ds)->ds_deadlist_obj, tx); dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_deadlist_obj = 0; + dsl_dataset_phys(ds)->ds_deadlist_obj = 0; objset_t *os; VERIFY0(dmu_objset_from_ds(ds, &os)); @@ -785,15 +798,16 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx) scn->scn_async_destroying = B_TRUE; } - used = ds->ds_dir->dd_phys->dd_used_bytes; - comp = ds->ds_dir->dd_phys->dd_compressed_bytes; - uncomp = ds->ds_dir->dd_phys->dd_uncompressed_bytes; + used = dsl_dir_phys(ds->ds_dir)->dd_used_bytes; + comp = dsl_dir_phys(ds->ds_dir)->dd_compressed_bytes; + uncomp = dsl_dir_phys(ds->ds_dir)->dd_uncompressed_bytes; ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) || - ds->ds_phys->ds_unique_bytes == used); + dsl_dataset_phys(ds)->ds_unique_bytes == used); bptree_add(mos, dp->dp_bptree_obj, - &ds->ds_phys->ds_bp, ds->ds_phys->ds_prev_snap_txg, + &dsl_dataset_phys(ds)->ds_bp, + dsl_dataset_phys(ds)->ds_prev_snap_txg, used, comp, uncomp, tx); dsl_dir_diduse_space(ds->ds_dir, DD_USED_HEAD, -used, -comp, -uncomp, tx); @@ -804,7 +818,7 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx) if (ds->ds_prev != NULL) { if (spa_version(dp->dp_spa) >= SPA_VERSION_DIR_CLONES) { VERIFY0(zap_remove_int(mos, - ds->ds_prev->ds_dir->dd_phys->dd_clones, + dsl_dir_phys(ds->ds_prev->ds_dir)->dd_clones, ds->ds_object, tx)); } prevobj = ds->ds_prev->ds_object; @@ -823,22 +837,22 @@ dsl_destroy_head_sync_impl(dsl_dataset_t *ds, dmu_tx_t *tx) /* Erase the link in the dir */ dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx); - ds->ds_dir->dd_phys->dd_head_dataset_obj = 0; + dsl_dir_phys(ds->ds_dir)->dd_head_dataset_obj = 0; ddobj = ds->ds_dir->dd_object; - ASSERT(ds->ds_phys->ds_snapnames_zapobj != 0); - VERIFY0(zap_destroy(mos, ds->ds_phys->ds_snapnames_zapobj, tx)); + ASSERT(dsl_dataset_phys(ds)->ds_snapnames_zapobj != 0); + VERIFY0(zap_destroy(mos, + dsl_dataset_phys(ds)->ds_snapnames_zapobj, tx)); if (ds->ds_bookmarks != 0) { - VERIFY0(zap_destroy(mos, - ds->ds_bookmarks, tx)); + VERIFY0(zap_destroy(mos, ds->ds_bookmarks, tx)); spa_feature_decr(dp->dp_spa, SPA_FEATURE_BOOKMARKS, tx); } spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx); - ASSERT0(ds->ds_phys->ds_next_clones_obj); - ASSERT0(ds->ds_phys->ds_props_obj); - ASSERT0(ds->ds_phys->ds_userrefs_obj); + ASSERT0(dsl_dataset_phys(ds)->ds_next_clones_obj); + ASSERT0(dsl_dataset_phys(ds)->ds_props_obj); + ASSERT0(dsl_dataset_phys(ds)->ds_userrefs_obj); dsl_dir_rele(ds->ds_dir, ds); ds->ds_dir = NULL; dmu_object_free_zapified(mos, obj, tx); @@ -876,7 +890,7 @@ dsl_destroy_head_begin_sync(void *arg, dmu_tx_t *tx) /* Mark it as inconsistent on-disk, in case we crash */ dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT; + dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_INCONSISTENT; spa_history_log_internal_ds(ds, "destroy begin", tx, ""); dsl_dataset_rele(ds, FTAG); @@ -919,7 +933,8 @@ dsl_destroy_head(const char *name) error = dmu_objset_own(name, DMU_OST_ANY, B_FALSE, FTAG, &os); if (error == 0) { uint64_t prev_snap_txg = - dmu_objset_ds(os)->ds_phys->ds_prev_snap_txg; + dsl_dataset_phys(dmu_objset_ds(os))-> + ds_prev_snap_txg; for (uint64_t obj = 0; error == 0; error = dmu_object_next(os, &obj, FALSE, prev_snap_txg)) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c index 74daa537fd17..5a891d1ba3d6 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c @@ -126,6 +126,8 @@ * such as those created by zfs diff. */ +extern inline dsl_dir_phys_t *dsl_dir_phys(dsl_dir_t *dd); + static uint64_t dsl_dir_space_towrite(dsl_dir_t *dd); /* ARGSUSED */ @@ -185,7 +187,6 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj, dd->dd_object = ddobj; dd->dd_dbuf = dbuf; dd->dd_pool = dp; - dd->dd_phys = dbuf->db_data; mutex_init(&dd->dd_lock, NULL, MUTEX_DEFAULT, NULL); list_create(&dd->dd_prop_cbs, sizeof (dsl_prop_cb_record_t), @@ -193,9 +194,10 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj, dsl_dir_snap_cmtime_update(dd); - if (dd->dd_phys->dd_parent_obj) { - err = dsl_dir_hold_obj(dp, dd->dd_phys->dd_parent_obj, - NULL, dd, &dd->dd_parent); + if (dsl_dir_phys(dd)->dd_parent_obj) { + err = dsl_dir_hold_obj(dp, + dsl_dir_phys(dd)->dd_parent_obj, NULL, dd, + &dd->dd_parent); if (err != 0) goto errout; if (tail) { @@ -203,14 +205,16 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj, uint64_t foundobj; err = zap_lookup(dp->dp_meta_objset, - dd->dd_parent->dd_phys->dd_child_dir_zapobj, - tail, sizeof (foundobj), 1, &foundobj); + dsl_dir_phys(dd->dd_parent)-> + dd_child_dir_zapobj, tail, + sizeof (foundobj), 1, &foundobj); ASSERT(err || foundobj == ddobj); #endif (void) strcpy(dd->dd_myname, tail); } else { err = zap_value_search(dp->dp_meta_objset, - dd->dd_parent->dd_phys->dd_child_dir_zapobj, + dsl_dir_phys(dd->dd_parent)-> + dd_child_dir_zapobj, ddobj, 0, dd->dd_myname); } if (err != 0) @@ -229,7 +233,8 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj, * Just look at its phys directly instead. */ err = dmu_bonus_hold(dp->dp_meta_objset, - dd->dd_phys->dd_origin_obj, FTAG, &origin_bonus); + dsl_dir_phys(dd)->dd_origin_obj, FTAG, + &origin_bonus); if (err != 0) goto errout; origin_phys = origin_bonus->db_data; @@ -238,8 +243,7 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj, dmu_buf_rele(origin_bonus, FTAG); } - winner = dmu_buf_set_user_ie(dbuf, dd, &dd->dd_phys, - dsl_dir_evict); + winner = dmu_buf_set_user_ie(dbuf, dd, dsl_dir_evict); if (winner) { if (dd->dd_parent) dsl_dir_rele(dd->dd_parent, dd); @@ -422,10 +426,10 @@ dsl_dir_hold(dsl_pool_t *dp, const char *name, void *tag, if (next[0] == '@') break; dprintf("looking up %s in obj%lld\n", - buf, dd->dd_phys->dd_child_dir_zapobj); + buf, dsl_dir_phys(dd)->dd_child_dir_zapobj); err = zap_lookup(dp->dp_meta_objset, - dd->dd_phys->dd_child_dir_zapobj, + dsl_dir_phys(dd)->dd_child_dir_zapobj, buf, sizeof (ddobj), 1, &ddobj); if (err != 0) { if (err == ENOENT) @@ -506,7 +510,7 @@ dsl_dir_init_fs_ss_count(dsl_dir_t *dd, dmu_tx_t *tx) za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); /* Iterate my child dirs */ - for (zap_cursor_init(zc, os, dd->dd_phys->dd_child_dir_zapobj); + for (zap_cursor_init(zc, os, dsl_dir_phys(dd)->dd_child_dir_zapobj); zap_cursor_retrieve(zc, za) == 0; zap_cursor_advance(zc)) { dsl_dir_t *chld_dd; uint64_t count; @@ -540,9 +544,9 @@ dsl_dir_init_fs_ss_count(dsl_dir_t *dd, dmu_tx_t *tx) zap_cursor_fini(zc); /* Count my snapshots (we counted children's snapshots above) */ VERIFY0(dsl_dataset_hold_obj(dd->dd_pool, - dd->dd_phys->dd_head_dataset_obj, FTAG, &ds)); + dsl_dir_phys(dd)->dd_head_dataset_obj, FTAG, &ds)); - for (zap_cursor_init(zc, os, ds->ds_phys->ds_snapnames_zapobj); + for (zap_cursor_init(zc, os, dsl_dataset_phys(ds)->ds_snapnames_zapobj); zap_cursor_retrieve(zc, za) == 0; zap_cursor_advance(zc)) { /* Don't count temporary snapshots */ @@ -695,7 +699,7 @@ dsl_enforce_ds_ss_limits(dsl_dir_t *dd, zfs_prop_t prop, cred_t *cr) return (ENFORCE_NEVER); #endif - if ((obj = dd->dd_phys->dd_head_dataset_obj) == 0) + if ((obj = dsl_dir_phys(dd)->dd_head_dataset_obj) == 0) return (ENFORCE_ALWAYS); ASSERT(dsl_pool_config_held(dd->dd_pool)); @@ -873,7 +877,7 @@ dsl_dir_create_sync(dsl_pool_t *dp, dsl_dir_t *pds, const char *name, ddobj = dmu_object_alloc(mos, DMU_OT_DSL_DIR, 0, DMU_OT_DSL_DIR, sizeof (dsl_dir_phys_t), tx); if (pds) { - VERIFY(0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, + VERIFY(0 == zap_add(mos, dsl_dir_phys(pds)->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)); } else { /* it's the root dir */ @@ -905,9 +909,9 @@ dsl_dir_create_sync(dsl_pool_t *dp, dsl_dir_t *pds, const char *name, boolean_t dsl_dir_is_clone(dsl_dir_t *dd) { - return (dd->dd_phys->dd_origin_obj && + return (dsl_dir_phys(dd)->dd_origin_obj && (dd->dd_pool->dp_origin_snap == NULL || - dd->dd_phys->dd_origin_obj != + dsl_dir_phys(dd)->dd_origin_obj != dd->dd_pool->dp_origin_snap->ds_object)); } @@ -916,26 +920,27 @@ dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv) { mutex_enter(&dd->dd_lock); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED, - dd->dd_phys->dd_used_bytes); - dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_QUOTA, dd->dd_phys->dd_quota); + dsl_dir_phys(dd)->dd_used_bytes); + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_QUOTA, + dsl_dir_phys(dd)->dd_quota); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_RESERVATION, - dd->dd_phys->dd_reserved); + dsl_dir_phys(dd)->dd_reserved); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, - dd->dd_phys->dd_compressed_bytes == 0 ? 100 : - (dd->dd_phys->dd_uncompressed_bytes * 100 / - dd->dd_phys->dd_compressed_bytes)); + dsl_dir_phys(dd)->dd_compressed_bytes == 0 ? 100 : + (dsl_dir_phys(dd)->dd_uncompressed_bytes * 100 / + dsl_dir_phys(dd)->dd_compressed_bytes)); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALUSED, - dd->dd_phys->dd_uncompressed_bytes); - if (dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) { + dsl_dir_phys(dd)->dd_uncompressed_bytes); + if (dsl_dir_phys(dd)->dd_flags & DD_FLAG_USED_BREAKDOWN) { dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDSNAP, - dd->dd_phys->dd_used_breakdown[DD_USED_SNAP]); + dsl_dir_phys(dd)->dd_used_breakdown[DD_USED_SNAP]); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDDS, - dd->dd_phys->dd_used_breakdown[DD_USED_HEAD]); + dsl_dir_phys(dd)->dd_used_breakdown[DD_USED_HEAD]); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDREFRESERV, - dd->dd_phys->dd_used_breakdown[DD_USED_REFRSRV]); + dsl_dir_phys(dd)->dd_used_breakdown[DD_USED_REFRSRV]); dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDCHILD, - dd->dd_phys->dd_used_breakdown[DD_USED_CHILD] + - dd->dd_phys->dd_used_breakdown[DD_USED_CHILD_RSRV]); + dsl_dir_phys(dd)->dd_used_breakdown[DD_USED_CHILD] + + dsl_dir_phys(dd)->dd_used_breakdown[DD_USED_CHILD_RSRV]); } mutex_exit(&dd->dd_lock); @@ -960,7 +965,7 @@ dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv) char buf[MAXNAMELEN]; VERIFY0(dsl_dataset_hold_obj(dd->dd_pool, - dd->dd_phys->dd_origin_obj, FTAG, &ds)); + dsl_dir_phys(dd)->dd_origin_obj, FTAG, &ds)); dsl_dataset_name(ds, buf); dsl_dataset_rele(ds, FTAG); dsl_prop_nvlist_add_string(nv, ZFS_PROP_ORIGIN, buf); @@ -972,7 +977,7 @@ dsl_dir_dirty(dsl_dir_t *dd, dmu_tx_t *tx) { dsl_pool_t *dp = dd->dd_pool; - ASSERT(dd->dd_phys); + ASSERT(dsl_dir_phys(dd)); if (txg_list_add(&dp->dp_dirty_dirs, dd, tx->tx_txg)) { /* up the hold count until we can be written out */ @@ -983,8 +988,9 @@ dsl_dir_dirty(dsl_dir_t *dd, dmu_tx_t *tx) static int64_t parent_delta(dsl_dir_t *dd, uint64_t used, int64_t delta) { - uint64_t old_accounted = MAX(used, dd->dd_phys->dd_reserved); - uint64_t new_accounted = MAX(used + delta, dd->dd_phys->dd_reserved); + uint64_t old_accounted = MAX(used, dsl_dir_phys(dd)->dd_reserved); + uint64_t new_accounted = + MAX(used + delta, dsl_dir_phys(dd)->dd_reserved); return (new_accounted - old_accounted); } @@ -1043,9 +1049,9 @@ dsl_dir_space_available(dsl_dir_t *dd, } mutex_enter(&dd->dd_lock); - if (dd->dd_phys->dd_quota != 0) - quota = dd->dd_phys->dd_quota; - used = dd->dd_phys->dd_used_bytes; + if (dsl_dir_phys(dd)->dd_quota != 0) + quota = dsl_dir_phys(dd)->dd_quota; + used = dsl_dir_phys(dd)->dd_used_bytes; if (!ondiskonly) used += dsl_dir_space_towrite(dd); @@ -1054,12 +1060,12 @@ dsl_dir_space_available(dsl_dir_t *dd, quota = MIN(quota, poolsize); } - if (dd->dd_phys->dd_reserved > used && parentspace != UINT64_MAX) { + if (dsl_dir_phys(dd)->dd_reserved > used && parentspace != UINT64_MAX) { /* * We have some space reserved, in addition to what our * parent gave us. */ - parentspace += dd->dd_phys->dd_reserved - used; + parentspace += dsl_dir_phys(dd)->dd_reserved - used; } if (dd == ancestor) { @@ -1118,7 +1124,7 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, est_inflight = dsl_dir_space_towrite(dd); for (i = 0; i < TXG_SIZE; i++) est_inflight += dd->dd_tempreserved[i]; - used_on_disk = dd->dd_phys->dd_used_bytes; + used_on_disk = dsl_dir_phys(dd)->dd_used_bytes; /* * On the first iteration, fetch the dataset's used-on-disk and @@ -1141,10 +1147,10 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, * If this transaction will result in a net free of space, * we want to let it through. */ - if (ignorequota || netfree || dd->dd_phys->dd_quota == 0) + if (ignorequota || netfree || dsl_dir_phys(dd)->dd_quota == 0) quota = UINT64_MAX; else - quota = dd->dd_phys->dd_quota; + quota = dsl_dir_phys(dd)->dd_quota; /* * Adjust the quota against the actual pool size at the root @@ -1198,7 +1204,7 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, /* see if it's OK with our parent */ if (dd->dd_parent && parent_rsrv) { - boolean_t ismos = (dd->dd_phys->dd_head_dataset_obj == 0); + boolean_t ismos = (dsl_dir_phys(dd)->dd_head_dataset_obj == 0); return (dsl_dir_tempreserve_impl(dd->dd_parent, parent_rsrv, netfree, ismos, TRUE, tr_list, tx, FALSE)); @@ -1317,7 +1323,7 @@ dsl_dir_willuse_space(dsl_dir_t *dd, int64_t space, dmu_tx_t *tx) if (space > 0) dd->dd_space_towrite[tx->tx_txg & TXG_MASK] += space; - est_used = dsl_dir_space_towrite(dd) + dd->dd_phys->dd_used_bytes; + est_used = dsl_dir_space_towrite(dd) + dsl_dir_phys(dd)->dd_used_bytes; parent_space = parent_delta(dd, est_used, space); mutex_exit(&dd->dd_lock); @@ -1352,26 +1358,27 @@ dsl_dir_diduse_space(dsl_dir_t *dd, dd_used_t type, if (needlock) mutex_enter(&dd->dd_lock); - accounted_delta = parent_delta(dd, dd->dd_phys->dd_used_bytes, used); - ASSERT(used >= 0 || dd->dd_phys->dd_used_bytes >= -used); + accounted_delta = + parent_delta(dd, dsl_dir_phys(dd)->dd_used_bytes, used); + ASSERT(used >= 0 || dsl_dir_phys(dd)->dd_used_bytes >= -used); ASSERT(compressed >= 0 || - dd->dd_phys->dd_compressed_bytes >= -compressed); + dsl_dir_phys(dd)->dd_compressed_bytes >= -compressed); ASSERT(uncompressed >= 0 || - dd->dd_phys->dd_uncompressed_bytes >= -uncompressed); - dd->dd_phys->dd_used_bytes += used; - dd->dd_phys->dd_uncompressed_bytes += uncompressed; - dd->dd_phys->dd_compressed_bytes += compressed; + dsl_dir_phys(dd)->dd_uncompressed_bytes >= -uncompressed); + dsl_dir_phys(dd)->dd_used_bytes += used; + dsl_dir_phys(dd)->dd_uncompressed_bytes += uncompressed; + dsl_dir_phys(dd)->dd_compressed_bytes += compressed; - if (dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) { + if (dsl_dir_phys(dd)->dd_flags & DD_FLAG_USED_BREAKDOWN) { ASSERT(used > 0 || - dd->dd_phys->dd_used_breakdown[type] >= -used); - dd->dd_phys->dd_used_breakdown[type] += used; + dsl_dir_phys(dd)->dd_used_breakdown[type] >= -used); + dsl_dir_phys(dd)->dd_used_breakdown[type] += used; #ifdef DEBUG dd_used_t t; uint64_t u = 0; for (t = 0; t < DD_USED_NUM; t++) - u += dd->dd_phys->dd_used_breakdown[t]; - ASSERT3U(u, ==, dd->dd_phys->dd_used_bytes); + u += dsl_dir_phys(dd)->dd_used_breakdown[t]; + ASSERT3U(u, ==, dsl_dir_phys(dd)->dd_used_bytes); #endif } if (needlock) @@ -1394,17 +1401,18 @@ dsl_dir_transfer_space(dsl_dir_t *dd, int64_t delta, ASSERT(oldtype < DD_USED_NUM); ASSERT(newtype < DD_USED_NUM); - if (delta == 0 || !(dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN)) + if (delta == 0 || + !(dsl_dir_phys(dd)->dd_flags & DD_FLAG_USED_BREAKDOWN)) return; dmu_buf_will_dirty(dd->dd_dbuf, tx); mutex_enter(&dd->dd_lock); ASSERT(delta > 0 ? - dd->dd_phys->dd_used_breakdown[oldtype] >= delta : - dd->dd_phys->dd_used_breakdown[newtype] >= -delta); - ASSERT(dd->dd_phys->dd_used_bytes >= ABS(delta)); - dd->dd_phys->dd_used_breakdown[oldtype] -= delta; - dd->dd_phys->dd_used_breakdown[newtype] += delta; + dsl_dir_phys(dd)->dd_used_breakdown[oldtype] >= delta : + dsl_dir_phys(dd)->dd_used_breakdown[newtype] >= -delta); + ASSERT(dsl_dir_phys(dd)->dd_used_bytes >= ABS(delta)); + dsl_dir_phys(dd)->dd_used_breakdown[oldtype] -= delta; + dsl_dir_phys(dd)->dd_used_breakdown[newtype] += delta; mutex_exit(&dd->dd_lock); } @@ -1448,8 +1456,8 @@ dsl_dir_set_quota_check(void *arg, dmu_tx_t *tx) */ towrite = dsl_dir_space_towrite(ds->ds_dir); if ((dmu_tx_is_syncing(tx) || towrite == 0) && - (newval < ds->ds_dir->dd_phys->dd_reserved || - newval < ds->ds_dir->dd_phys->dd_used_bytes + towrite)) { + (newval < dsl_dir_phys(ds->ds_dir)->dd_reserved || + newval < dsl_dir_phys(ds->ds_dir)->dd_used_bytes + towrite)) { error = SET_ERROR(ENOSPC); } mutex_exit(&ds->ds_dir->dd_lock); @@ -1482,7 +1490,7 @@ dsl_dir_set_quota_sync(void *arg, dmu_tx_t *tx) dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx); mutex_enter(&ds->ds_dir->dd_lock); - ds->ds_dir->dd_phys->dd_quota = newval; + dsl_dir_phys(ds->ds_dir)->dd_quota = newval; mutex_exit(&ds->ds_dir->dd_lock); dsl_dataset_rele(ds, FTAG); } @@ -1533,7 +1541,7 @@ dsl_dir_set_reservation_check(void *arg, dmu_tx_t *tx) } mutex_enter(&dd->dd_lock); - used = dd->dd_phys->dd_used_bytes; + used = dsl_dir_phys(dd)->dd_used_bytes; mutex_exit(&dd->dd_lock); if (dd->dd_parent) { @@ -1543,13 +1551,13 @@ dsl_dir_set_reservation_check(void *arg, dmu_tx_t *tx) avail = dsl_pool_adjustedsize(dd->dd_pool, B_FALSE) - used; } - if (MAX(used, newval) > MAX(used, dd->dd_phys->dd_reserved)) { + if (MAX(used, newval) > MAX(used, dsl_dir_phys(dd)->dd_reserved)) { uint64_t delta = MAX(used, newval) - - MAX(used, dd->dd_phys->dd_reserved); + MAX(used, dsl_dir_phys(dd)->dd_reserved); if (delta > avail || - (dd->dd_phys->dd_quota > 0 && - newval > dd->dd_phys->dd_quota)) + (dsl_dir_phys(dd)->dd_quota > 0 && + newval > dsl_dir_phys(dd)->dd_quota)) error = SET_ERROR(ENOSPC); } @@ -1566,9 +1574,9 @@ dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value, dmu_tx_t *tx) dmu_buf_will_dirty(dd->dd_dbuf, tx); mutex_enter(&dd->dd_lock); - used = dd->dd_phys->dd_used_bytes; - delta = MAX(used, value) - MAX(used, dd->dd_phys->dd_reserved); - dd->dd_phys->dd_reserved = value; + used = dsl_dir_phys(dd)->dd_used_bytes; + delta = MAX(used, value) - MAX(used, dsl_dir_phys(dd)->dd_reserved); + dsl_dir_phys(dd)->dd_reserved = value; if (dd->dd_parent != NULL) { /* Roll up this additional usage into our ancestors */ @@ -1645,7 +1653,7 @@ would_change(dsl_dir_t *dd, int64_t delta, dsl_dir_t *ancestor) return (delta); mutex_enter(&dd->dd_lock); - delta = parent_delta(dd, dd->dd_phys->dd_used_bytes, delta); + delta = parent_delta(dd, dsl_dir_phys(dd)->dd_used_bytes, delta); mutex_exit(&dd->dd_lock); return (would_change(dd->dd_parent, delta, ancestor)); } @@ -1736,7 +1744,8 @@ dsl_dir_rename_check(void *arg, dmu_tx_t *tx) if (newparent != dd->dd_parent) { /* is there enough space? */ uint64_t myspace = - MAX(dd->dd_phys->dd_used_bytes, dd->dd_phys->dd_reserved); + MAX(dsl_dir_phys(dd)->dd_used_bytes, + dsl_dir_phys(dd)->dd_reserved); objset_t *os = dd->dd_pool->dp_meta_objset; uint64_t fs_cnt = 0; uint64_t ss_cnt = 0; @@ -1841,17 +1850,18 @@ dsl_dir_rename_sync(void *arg, dmu_tx_t *tx) DD_FIELD_SNAPSHOT_COUNT, tx); dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD, - -dd->dd_phys->dd_used_bytes, - -dd->dd_phys->dd_compressed_bytes, - -dd->dd_phys->dd_uncompressed_bytes, tx); + -dsl_dir_phys(dd)->dd_used_bytes, + -dsl_dir_phys(dd)->dd_compressed_bytes, + -dsl_dir_phys(dd)->dd_uncompressed_bytes, tx); dsl_dir_diduse_space(newparent, DD_USED_CHILD, - dd->dd_phys->dd_used_bytes, - dd->dd_phys->dd_compressed_bytes, - dd->dd_phys->dd_uncompressed_bytes, tx); + dsl_dir_phys(dd)->dd_used_bytes, + dsl_dir_phys(dd)->dd_compressed_bytes, + dsl_dir_phys(dd)->dd_uncompressed_bytes, tx); - if (dd->dd_phys->dd_reserved > dd->dd_phys->dd_used_bytes) { - uint64_t unused_rsrv = dd->dd_phys->dd_reserved - - dd->dd_phys->dd_used_bytes; + if (dsl_dir_phys(dd)->dd_reserved > + dsl_dir_phys(dd)->dd_used_bytes) { + uint64_t unused_rsrv = dsl_dir_phys(dd)->dd_reserved - + dsl_dir_phys(dd)->dd_used_bytes; dsl_dir_diduse_space(dd->dd_parent, DD_USED_CHILD_RSRV, -unused_rsrv, 0, 0, tx); @@ -1863,18 +1873,19 @@ dsl_dir_rename_sync(void *arg, dmu_tx_t *tx) dmu_buf_will_dirty(dd->dd_dbuf, tx); /* remove from old parent zapobj */ - error = zap_remove(mos, dd->dd_parent->dd_phys->dd_child_dir_zapobj, + error = zap_remove(mos, + dsl_dir_phys(dd->dd_parent)->dd_child_dir_zapobj, dd->dd_myname, tx); ASSERT0(error); (void) strcpy(dd->dd_myname, mynewname); dsl_dir_rele(dd->dd_parent, dd); - dd->dd_phys->dd_parent_obj = newparent->dd_object; + dsl_dir_phys(dd)->dd_parent_obj = newparent->dd_object; VERIFY0(dsl_dir_hold_obj(dp, newparent->dd_object, NULL, dd, &dd->dd_parent)); /* add to new parent zapobj */ - VERIFY0(zap_add(mos, newparent->dd_phys->dd_child_dir_zapobj, + VERIFY0(zap_add(mos, dsl_dir_phys(newparent)->dd_child_dir_zapobj, dd->dd_myname, 8, 1, &dd->dd_object, tx)); #ifdef __FreeBSD__ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c index 08e79ca5b8af..672368e8a468 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c @@ -235,7 +235,7 @@ dsl_pool_open_special_dir(dsl_pool_t *dp, const char *name, dsl_dir_t **ddp) int err; err = zap_lookup(dp->dp_meta_objset, - dp->dp_root_dir->dd_phys->dd_child_dir_zapobj, + dsl_dir_phys(dp->dp_root_dir)->dd_child_dir_zapobj, name, sizeof (obj), 1, &obj); if (err) return (err); @@ -317,11 +317,11 @@ dsl_pool_open(dsl_pool_t *dp) err = dsl_pool_open_special_dir(dp, ORIGIN_DIR_NAME, &dd); if (err) goto out; - err = dsl_dataset_hold_obj(dp, dd->dd_phys->dd_head_dataset_obj, - FTAG, &ds); + err = dsl_dataset_hold_obj(dp, + dsl_dir_phys(dd)->dd_head_dataset_obj, FTAG, &ds); if (err == 0) { err = dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_prev_snap_obj, dp, + dsl_dataset_phys(ds)->ds_prev_snap_obj, dp, &dp->dp_origin_snap); dsl_dataset_rele(ds, FTAG); } @@ -774,15 +774,15 @@ upgrade_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) if (err) return (err); - while (ds->ds_phys->ds_prev_snap_obj != 0) { - err = dsl_dataset_hold_obj(dp, ds->ds_phys->ds_prev_snap_obj, - FTAG, &prev); + while (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) { + err = dsl_dataset_hold_obj(dp, + dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &prev); if (err) { dsl_dataset_rele(ds, FTAG); return (err); } - if (prev->ds_phys->ds_next_snap_obj != ds->ds_object) + if (dsl_dataset_phys(prev)->ds_next_snap_obj != ds->ds_object) break; dsl_dataset_rele(ds, FTAG); ds = prev; @@ -796,7 +796,7 @@ upgrade_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) * The $ORIGIN can't have any data, or the accounting * will be wrong. */ - ASSERT0(prev->ds_phys->ds_bp.blk_birth); + ASSERT0(dsl_dataset_phys(prev)->ds_bp.blk_birth); /* The origin doesn't get attached to itself */ if (ds->ds_object == prev->ds_object) { @@ -805,33 +805,35 @@ upgrade_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) } dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_prev_snap_obj = prev->ds_object; - ds->ds_phys->ds_prev_snap_txg = prev->ds_phys->ds_creation_txg; + dsl_dataset_phys(ds)->ds_prev_snap_obj = prev->ds_object; + dsl_dataset_phys(ds)->ds_prev_snap_txg = + dsl_dataset_phys(prev)->ds_creation_txg; dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx); - ds->ds_dir->dd_phys->dd_origin_obj = prev->ds_object; + dsl_dir_phys(ds->ds_dir)->dd_origin_obj = prev->ds_object; dmu_buf_will_dirty(prev->ds_dbuf, tx); - prev->ds_phys->ds_num_children++; + dsl_dataset_phys(prev)->ds_num_children++; - if (ds->ds_phys->ds_next_snap_obj == 0) { + if (dsl_dataset_phys(ds)->ds_next_snap_obj == 0) { ASSERT(ds->ds_prev == NULL); VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_prev_snap_obj, ds, &ds->ds_prev)); + dsl_dataset_phys(ds)->ds_prev_snap_obj, + ds, &ds->ds_prev)); } } - ASSERT3U(ds->ds_dir->dd_phys->dd_origin_obj, ==, prev->ds_object); - ASSERT3U(ds->ds_phys->ds_prev_snap_obj, ==, prev->ds_object); + ASSERT3U(dsl_dir_phys(ds->ds_dir)->dd_origin_obj, ==, prev->ds_object); + ASSERT3U(dsl_dataset_phys(ds)->ds_prev_snap_obj, ==, prev->ds_object); - if (prev->ds_phys->ds_next_clones_obj == 0) { + if (dsl_dataset_phys(prev)->ds_next_clones_obj == 0) { dmu_buf_will_dirty(prev->ds_dbuf, tx); - prev->ds_phys->ds_next_clones_obj = + dsl_dataset_phys(prev)->ds_next_clones_obj = zap_create(dp->dp_meta_objset, DMU_OT_NEXT_CLONES, DMU_OT_NONE, 0, tx); } VERIFY0(zap_add_int(dp->dp_meta_objset, - prev->ds_phys->ds_next_clones_obj, ds->ds_object, tx)); + dsl_dataset_phys(prev)->ds_next_clones_obj, ds->ds_object, tx)); dsl_dataset_rele(ds, FTAG); if (prev != dp->dp_origin_snap) @@ -856,20 +858,22 @@ upgrade_dir_clones_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg) dmu_tx_t *tx = arg; objset_t *mos = dp->dp_meta_objset; - if (ds->ds_dir->dd_phys->dd_origin_obj != 0) { + if (dsl_dir_phys(ds->ds_dir)->dd_origin_obj != 0) { dsl_dataset_t *origin; VERIFY0(dsl_dataset_hold_obj(dp, - ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &origin)); + dsl_dir_phys(ds->ds_dir)->dd_origin_obj, FTAG, &origin)); - if (origin->ds_dir->dd_phys->dd_clones == 0) { + if (dsl_dir_phys(origin->ds_dir)->dd_clones == 0) { dmu_buf_will_dirty(origin->ds_dir->dd_dbuf, tx); - origin->ds_dir->dd_phys->dd_clones = zap_create(mos, - DMU_OT_DSL_CLONES, DMU_OT_NONE, 0, tx); + dsl_dir_phys(origin->ds_dir)->dd_clones = + zap_create(mos, DMU_OT_DSL_CLONES, DMU_OT_NONE, + 0, tx); } VERIFY0(zap_add_int(dp->dp_meta_objset, - origin->ds_dir->dd_phys->dd_clones, ds->ds_object, tx)); + dsl_dir_phys(origin->ds_dir)->dd_clones, + ds->ds_object, tx)); dsl_dataset_rele(origin, FTAG); } @@ -916,7 +920,7 @@ dsl_pool_create_origin(dsl_pool_t *dp, dmu_tx_t *tx) NULL, 0, kcred, tx); VERIFY0(dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds)); dsl_dataset_snapshot_sync_impl(ds, ORIGIN_DIR_NAME, tx); - VERIFY0(dsl_dataset_hold_obj(dp, ds->ds_phys->ds_prev_snap_obj, + VERIFY0(dsl_dataset_hold_obj(dp, dsl_dataset_phys(ds)->ds_prev_snap_obj, dp, &dp->dp_origin_snap)); dsl_dataset_rele(ds, FTAG); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c index fa2f84cc7b09..398c5710820e 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c @@ -104,8 +104,8 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, } /* Check for a local value. */ - err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, propname, - intsz, numints, buf); + err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj, + propname, intsz, numints, buf); if (err != ENOENT) { if (setpoint != NULL && err == 0) dsl_dir_name(dd, setpoint); @@ -116,14 +116,14 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, * Skip the check for a received value if there is an explicit * inheritance entry. */ - err = zap_contains(mos, dd->dd_phys->dd_props_zapobj, + err = zap_contains(mos, dsl_dir_phys(dd)->dd_props_zapobj, inheritstr); if (err != 0 && err != ENOENT) break; if (err == ENOENT) { /* Check for a received value. */ - err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, + err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj, recvdstr, intsz, numints, buf); if (err != ENOENT) { if (setpoint != NULL && err == 0) { @@ -168,7 +168,7 @@ dsl_prop_get_ds(dsl_dataset_t *ds, const char *propname, ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool)); inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop)); snapshot = dsl_dataset_is_snapshot(ds); - zapobj = ds->ds_phys->ds_props_obj; + zapobj = dsl_dataset_phys(ds)->ds_props_obj; if (zapobj != 0) { objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset; @@ -326,7 +326,7 @@ dsl_prop_predict(dsl_dir_t *dd, const char *propname, } mos = dd->dd_pool->dp_meta_objset; - zapobj = dd->dd_phys->dd_props_zapobj; + zapobj = dsl_dir_phys(dd)->dd_props_zapobj; recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); version = spa_version(dd->dd_pool->dp_spa); @@ -485,7 +485,8 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, * If the prop is set here, then this change is not * being inherited here or below; stop the recursion. */ - err = zap_contains(mos, dd->dd_phys->dd_props_zapobj, propname); + err = zap_contains(mos, dsl_dir_phys(dd)->dd_props_zapobj, + propname); if (err == 0) { dsl_dir_rele(dd, FTAG); return; @@ -496,7 +497,7 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, mutex_enter(&dd->dd_lock); for (cbr = list_head(&dd->dd_prop_cbs); cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { - uint64_t propobj = cbr->cbr_ds->ds_phys->ds_props_obj; + uint64_t propobj = dsl_dataset_phys(cbr->cbr_ds)->ds_props_obj; if (strcmp(cbr->cbr_propname, propname) != 0) continue; @@ -514,7 +515,7 @@ dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); for (zap_cursor_init(&zc, mos, - dd->dd_phys->dd_child_dir_zapobj); + dsl_dir_phys(dd)->dd_child_dir_zapobj); zap_cursor_retrieve(&zc, za) == 0; zap_cursor_advance(&zc)) { dsl_prop_changed_notify(dp, za->za_first_integer, @@ -545,15 +546,15 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname, if (dsl_dataset_is_snapshot(ds)) { ASSERT(version >= SPA_VERSION_SNAP_PROPS); - if (ds->ds_phys->ds_props_obj == 0) { + if (dsl_dataset_phys(ds)->ds_props_obj == 0) { dmu_buf_will_dirty(ds->ds_dbuf, tx); - ds->ds_phys->ds_props_obj = + dsl_dataset_phys(ds)->ds_props_obj = zap_create(mos, DMU_OT_DSL_PROPS, DMU_OT_NONE, 0, tx); } - zapobj = ds->ds_phys->ds_props_obj; + zapobj = dsl_dataset_phys(ds)->ds_props_obj; } else { - zapobj = ds->ds_dir->dd_phys->dd_props_zapobj; + zapobj = dsl_dir_phys(ds->ds_dir)->dd_props_zapobj; } if (version < SPA_VERSION_RECVD_PROPS) { @@ -986,11 +987,11 @@ dsl_prop_get_all_ds(dsl_dataset_t *ds, nvlist_t **nvp, ASSERT(dsl_pool_config_held(dp)); - if (ds->ds_phys->ds_props_obj != 0) { + if (dsl_dataset_phys(ds)->ds_props_obj != 0) { ASSERT(flags & DSL_PROP_GET_SNAPSHOT); dsl_dataset_name(ds, setpoint); - err = dsl_prop_get_all_impl(mos, ds->ds_phys->ds_props_obj, - setpoint, flags, *nvp); + err = dsl_prop_get_all_impl(mos, + dsl_dataset_phys(ds)->ds_props_obj, setpoint, flags, *nvp); if (err) goto out; } @@ -1003,8 +1004,8 @@ dsl_prop_get_all_ds(dsl_dataset_t *ds, nvlist_t **nvp, flags |= DSL_PROP_GET_INHERITING; } dsl_dir_name(dd, setpoint); - err = dsl_prop_get_all_impl(mos, dd->dd_phys->dd_props_zapobj, - setpoint, flags, *nvp); + err = dsl_prop_get_all_impl(mos, + dsl_dir_phys(dd)->dd_props_zapobj, setpoint, flags, *nvp); if (err) break; } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c index 8923151e605b..3b1d732ebf54 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c @@ -401,7 +401,7 @@ dsl_scan_ds_maxtxg(dsl_dataset_t *ds) { uint64_t smt = ds->ds_dir->dd_pool->dp_scan->scn_phys.scn_max_txg; if (dsl_dataset_is_snapshot(ds)) - return (MIN(smt, ds->ds_phys->ds_creation_txg)); + return (MIN(smt, dsl_dataset_phys(ds)->ds_creation_txg)); return (smt); } @@ -571,7 +571,7 @@ dsl_scan_prefetch(dsl_scan_t *scn, arc_buf_t *buf, blkptr_t *bp, uint64_t objset, uint64_t object, uint64_t blkid) { zbookmark_phys_t czb; - uint32_t flags = ARC_NOWAIT | ARC_PREFETCH; + arc_flags_t flags = ARC_FLAG_NOWAIT | ARC_FLAG_PREFETCH; if (zfs_no_scrub_prefetch) return; @@ -636,7 +636,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype, int err; if (BP_GET_LEVEL(bp) > 0) { - uint32_t flags = ARC_WAIT; + arc_flags_t flags = ARC_FLAG_WAIT; int i; blkptr_t *cbp; int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT; @@ -663,7 +663,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype, } (void) arc_buf_remove_ref(buf, &buf); } else if (BP_GET_TYPE(bp) == DMU_OT_DNODE) { - uint32_t flags = ARC_WAIT; + arc_flags_t flags = ARC_FLAG_WAIT; dnode_phys_t *cdnp; int i, j; int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT; @@ -689,7 +689,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype, (void) arc_buf_remove_ref(buf, &buf); } else if (BP_GET_TYPE(bp) == DMU_OT_OBJSET) { - uint32_t flags = ARC_WAIT; + arc_flags_t flags = ARC_FLAG_WAIT; objset_phys_t *osp; arc_buf_t *buf; @@ -839,11 +839,12 @@ dsl_scan_ds_destroyed(dsl_dataset_t *ds, dmu_tx_t *tx) if (dsl_dataset_is_snapshot(ds)) { /* Note, scn_cur_{min,max}_txg stays the same. */ scn->scn_phys.scn_bookmark.zb_objset = - ds->ds_phys->ds_next_snap_obj; + dsl_dataset_phys(ds)->ds_next_snap_obj; zfs_dbgmsg("destroying ds %llu; currently traversing; " "reset zb_objset to %llu", (u_longlong_t)ds->ds_object, - (u_longlong_t)ds->ds_phys->ds_next_snap_obj); + (u_longlong_t)dsl_dataset_phys(ds)-> + ds_next_snap_obj); scn->scn_phys.scn_flags |= DSF_VISIT_DS_AGAIN; } else { SET_BOOKMARK(&scn->scn_phys.scn_bookmark, @@ -854,7 +855,7 @@ dsl_scan_ds_destroyed(dsl_dataset_t *ds, dmu_tx_t *tx) } } else if (zap_lookup_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, ds->ds_object, &mintxg) == 0) { - ASSERT3U(ds->ds_phys->ds_num_children, <=, 1); + ASSERT3U(dsl_dataset_phys(ds)->ds_num_children, <=, 1); VERIFY3U(0, ==, zap_remove_int(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, ds->ds_object, tx)); if (dsl_dataset_is_snapshot(ds)) { @@ -865,11 +866,13 @@ dsl_scan_ds_destroyed(dsl_dataset_t *ds, dmu_tx_t *tx) */ VERIFY(zap_add_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, - ds->ds_phys->ds_next_snap_obj, mintxg, tx) == 0); + dsl_dataset_phys(ds)->ds_next_snap_obj, + mintxg, tx) == 0); zfs_dbgmsg("destroying ds %llu; in queue; " "replacing with %llu", (u_longlong_t)ds->ds_object, - (u_longlong_t)ds->ds_phys->ds_next_snap_obj); + (u_longlong_t)dsl_dataset_phys(ds)-> + ds_next_snap_obj); } else { zfs_dbgmsg("destroying ds %llu; in queue; removing", (u_longlong_t)ds->ds_object); @@ -896,26 +899,26 @@ dsl_scan_ds_snapshotted(dsl_dataset_t *ds, dmu_tx_t *tx) if (scn->scn_phys.scn_state != DSS_SCANNING) return; - ASSERT(ds->ds_phys->ds_prev_snap_obj != 0); + ASSERT(dsl_dataset_phys(ds)->ds_prev_snap_obj != 0); if (scn->scn_phys.scn_bookmark.zb_objset == ds->ds_object) { scn->scn_phys.scn_bookmark.zb_objset = - ds->ds_phys->ds_prev_snap_obj; + dsl_dataset_phys(ds)->ds_prev_snap_obj; zfs_dbgmsg("snapshotting ds %llu; currently traversing; " "reset zb_objset to %llu", (u_longlong_t)ds->ds_object, - (u_longlong_t)ds->ds_phys->ds_prev_snap_obj); + (u_longlong_t)dsl_dataset_phys(ds)->ds_prev_snap_obj); } else if (zap_lookup_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, ds->ds_object, &mintxg) == 0) { VERIFY3U(0, ==, zap_remove_int(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, ds->ds_object, tx)); VERIFY(zap_add_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, - ds->ds_phys->ds_prev_snap_obj, mintxg, tx) == 0); + dsl_dataset_phys(ds)->ds_prev_snap_obj, mintxg, tx) == 0); zfs_dbgmsg("snapshotting ds %llu; in queue; " "replacing with %llu", (u_longlong_t)ds->ds_object, - (u_longlong_t)ds->ds_phys->ds_prev_snap_obj); + (u_longlong_t)dsl_dataset_phys(ds)->ds_prev_snap_obj); } dsl_scan_sync_state(scn, tx); } @@ -948,8 +951,8 @@ dsl_scan_ds_clone_swapped(dsl_dataset_t *ds1, dsl_dataset_t *ds2, dmu_tx_t *tx) ds1->ds_object, &mintxg) == 0) { int err; - ASSERT3U(mintxg, ==, ds1->ds_phys->ds_prev_snap_txg); - ASSERT3U(mintxg, ==, ds2->ds_phys->ds_prev_snap_txg); + ASSERT3U(mintxg, ==, dsl_dataset_phys(ds1)->ds_prev_snap_txg); + ASSERT3U(mintxg, ==, dsl_dataset_phys(ds2)->ds_prev_snap_txg); VERIFY3U(0, ==, zap_remove_int(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, ds1->ds_object, tx)); err = zap_add_int_key(dp->dp_meta_objset, @@ -967,8 +970,8 @@ dsl_scan_ds_clone_swapped(dsl_dataset_t *ds1, dsl_dataset_t *ds2, dmu_tx_t *tx) (u_longlong_t)ds2->ds_object); } else if (zap_lookup_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, ds2->ds_object, &mintxg) == 0) { - ASSERT3U(mintxg, ==, ds1->ds_phys->ds_prev_snap_txg); - ASSERT3U(mintxg, ==, ds2->ds_phys->ds_prev_snap_txg); + ASSERT3U(mintxg, ==, dsl_dataset_phys(ds1)->ds_prev_snap_txg); + ASSERT3U(mintxg, ==, dsl_dataset_phys(ds2)->ds_prev_snap_txg); VERIFY3U(0, ==, zap_remove_int(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, ds2->ds_object, tx)); VERIFY(0 == zap_add_int_key(dp->dp_meta_objset, @@ -996,17 +999,17 @@ enqueue_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) int err; dsl_scan_t *scn = dp->dp_scan; - if (hds->ds_dir->dd_phys->dd_origin_obj != eca->originobj) + if (dsl_dir_phys(hds->ds_dir)->dd_origin_obj != eca->originobj) return (0); err = dsl_dataset_hold_obj(dp, hds->ds_object, FTAG, &ds); if (err) return (err); - while (ds->ds_phys->ds_prev_snap_obj != eca->originobj) { + while (dsl_dataset_phys(ds)->ds_prev_snap_obj != eca->originobj) { dsl_dataset_t *prev; err = dsl_dataset_hold_obj(dp, - ds->ds_phys->ds_prev_snap_obj, FTAG, &prev); + dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &prev); dsl_dataset_rele(ds, FTAG); if (err) @@ -1015,7 +1018,7 @@ enqueue_clones_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) } VERIFY(zap_add_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, ds->ds_object, - ds->ds_phys->ds_prev_snap_txg, eca->tx) == 0); + dsl_dataset_phys(ds)->ds_prev_snap_txg, eca->tx) == 0); dsl_dataset_rele(ds, FTAG); return (0); } @@ -1046,7 +1049,7 @@ dsl_scan_visitds(dsl_scan_t *scn, uint64_t dsobj, dmu_tx_t *tx) * Iterate over the bps in this ds. */ dmu_buf_will_dirty(ds->ds_dbuf, tx); - dsl_scan_visit_rootbp(scn, ds, &ds->ds_phys->ds_bp, tx); + dsl_scan_visit_rootbp(scn, ds, &dsl_dataset_phys(ds)->ds_bp, tx); char *dsname = kmem_alloc(ZFS_MAXNAMELEN, KM_SLEEP); dsl_dataset_name(ds, dsname); @@ -1080,14 +1083,15 @@ dsl_scan_visitds(dsl_scan_t *scn, uint64_t dsobj, dmu_tx_t *tx) /* * Add descendent datasets to work queue. */ - if (ds->ds_phys->ds_next_snap_obj != 0) { + if (dsl_dataset_phys(ds)->ds_next_snap_obj != 0) { VERIFY(zap_add_int_key(dp->dp_meta_objset, - scn->scn_phys.scn_queue_obj, ds->ds_phys->ds_next_snap_obj, - ds->ds_phys->ds_creation_txg, tx) == 0); + scn->scn_phys.scn_queue_obj, + dsl_dataset_phys(ds)->ds_next_snap_obj, + dsl_dataset_phys(ds)->ds_creation_txg, tx) == 0); } - if (ds->ds_phys->ds_num_children > 1) { + if (dsl_dataset_phys(ds)->ds_num_children > 1) { boolean_t usenext = B_FALSE; - if (ds->ds_phys->ds_next_clones_obj != 0) { + if (dsl_dataset_phys(ds)->ds_next_clones_obj != 0) { uint64_t count; /* * A bug in a previous version of the code could @@ -1097,17 +1101,17 @@ dsl_scan_visitds(dsl_scan_t *scn, uint64_t dsobj, dmu_tx_t *tx) * next_clones_obj when its count is correct. */ int err = zap_count(dp->dp_meta_objset, - ds->ds_phys->ds_next_clones_obj, &count); + dsl_dataset_phys(ds)->ds_next_clones_obj, &count); if (err == 0 && - count == ds->ds_phys->ds_num_children - 1) + count == dsl_dataset_phys(ds)->ds_num_children - 1) usenext = B_TRUE; } if (usenext) { VERIFY0(zap_join_key(dp->dp_meta_objset, - ds->ds_phys->ds_next_clones_obj, + dsl_dataset_phys(ds)->ds_next_clones_obj, scn->scn_phys.scn_queue_obj, - ds->ds_phys->ds_creation_txg, tx)); + dsl_dataset_phys(ds)->ds_creation_txg, tx)); } else { struct enqueue_clones_arg eca; eca.tx = tx; @@ -1135,10 +1139,10 @@ enqueue_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) if (err) return (err); - while (ds->ds_phys->ds_prev_snap_obj != 0) { + while (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) { dsl_dataset_t *prev; - err = dsl_dataset_hold_obj(dp, ds->ds_phys->ds_prev_snap_obj, - FTAG, &prev); + err = dsl_dataset_hold_obj(dp, + dsl_dataset_phys(ds)->ds_prev_snap_obj, FTAG, &prev); if (err) { dsl_dataset_rele(ds, FTAG); return (err); @@ -1147,7 +1151,7 @@ enqueue_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) /* * If this is a clone, we don't need to worry about it for now. */ - if (prev->ds_phys->ds_next_snap_obj != ds->ds_object) { + if (dsl_dataset_phys(prev)->ds_next_snap_obj != ds->ds_object) { dsl_dataset_rele(ds, FTAG); dsl_dataset_rele(prev, FTAG); return (0); @@ -1157,7 +1161,7 @@ enqueue_cb(dsl_pool_t *dp, dsl_dataset_t *hds, void *arg) } VERIFY(zap_add_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj, - ds->ds_object, ds->ds_phys->ds_prev_snap_txg, tx) == 0); + ds->ds_object, dsl_dataset_phys(ds)->ds_prev_snap_txg, tx) == 0); dsl_dataset_rele(ds, FTAG); return (0); } @@ -1332,7 +1336,7 @@ dsl_scan_visit(dsl_scan_t *scn, dmu_tx_t *tx) } else { scn->scn_phys.scn_cur_min_txg = MAX(scn->scn_phys.scn_min_txg, - ds->ds_phys->ds_prev_snap_txg); + dsl_dataset_phys(ds)->ds_prev_snap_txg); } scn->scn_phys.scn_cur_max_txg = dsl_scan_ds_maxtxg(ds); dsl_dataset_rele(ds, FTAG); @@ -1486,11 +1490,15 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx) dp->dp_bptree_obj, tx)); dp->dp_bptree_obj = 0; scn->scn_async_destroying = B_FALSE; + scn->scn_async_stalled = B_FALSE; } else { /* - * If we didn't make progress, mark the async destroy as - * stalled, so that we will not initiate a spa_sync() on - * its behalf. + * If we didn't make progress, mark the async + * destroy as stalled, so that we will not initiate + * a spa_sync() on its behalf. Note that we only + * check this if we are not finished, because if the + * bptree had no blocks for us to visit, we can + * finish without "making progress". */ scn->scn_async_stalled = (scn->scn_visited_this_txg == 0); @@ -1515,9 +1523,9 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx) if (err != 0) return; if (!scn->scn_async_destroying && zfs_free_leak_on_eio && - (dp->dp_free_dir->dd_phys->dd_used_bytes != 0 || - dp->dp_free_dir->dd_phys->dd_compressed_bytes != 0 || - dp->dp_free_dir->dd_phys->dd_uncompressed_bytes != 0)) { + (dsl_dir_phys(dp->dp_free_dir)->dd_used_bytes != 0 || + dsl_dir_phys(dp->dp_free_dir)->dd_compressed_bytes != 0 || + dsl_dir_phys(dp->dp_free_dir)->dd_uncompressed_bytes != 0)) { /* * We have finished background destroying, but there is still * some space left in the dp_free_dir. Transfer this leaked @@ -1532,19 +1540,19 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx) rrw_exit(&dp->dp_config_rwlock, FTAG); } dsl_dir_diduse_space(dp->dp_leak_dir, DD_USED_HEAD, - dp->dp_free_dir->dd_phys->dd_used_bytes, - dp->dp_free_dir->dd_phys->dd_compressed_bytes, - dp->dp_free_dir->dd_phys->dd_uncompressed_bytes, tx); + dsl_dir_phys(dp->dp_free_dir)->dd_used_bytes, + dsl_dir_phys(dp->dp_free_dir)->dd_compressed_bytes, + dsl_dir_phys(dp->dp_free_dir)->dd_uncompressed_bytes, tx); dsl_dir_diduse_space(dp->dp_free_dir, DD_USED_HEAD, - -dp->dp_free_dir->dd_phys->dd_used_bytes, - -dp->dp_free_dir->dd_phys->dd_compressed_bytes, - -dp->dp_free_dir->dd_phys->dd_uncompressed_bytes, tx); + -dsl_dir_phys(dp->dp_free_dir)->dd_used_bytes, + -dsl_dir_phys(dp->dp_free_dir)->dd_compressed_bytes, + -dsl_dir_phys(dp->dp_free_dir)->dd_uncompressed_bytes, tx); } if (!scn->scn_async_destroying) { /* finished; verify that space accounting went to zero */ - ASSERT0(dp->dp_free_dir->dd_phys->dd_used_bytes); - ASSERT0(dp->dp_free_dir->dd_phys->dd_compressed_bytes); - ASSERT0(dp->dp_free_dir->dd_phys->dd_uncompressed_bytes); + ASSERT0(dsl_dir_phys(dp->dp_free_dir)->dd_used_bytes); + ASSERT0(dsl_dir_phys(dp->dp_free_dir)->dd_compressed_bytes); + ASSERT0(dsl_dir_phys(dp->dp_free_dir)->dd_uncompressed_bytes); } if (scn->scn_phys.scn_state != DSS_SCANNING) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c index 8e09347678dd..e66e931726f0 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c @@ -163,7 +163,7 @@ dsl_sync_task_sync(dsl_sync_task_t *dst, dmu_tx_t *tx) uint64_t quota = dsl_pool_adjustedsize(dp, dst->dst_space_check == ZFS_SPACE_CHECK_RESERVED) - metaslab_class_get_deferred(spa_normal_class(dp->dp_spa)); - uint64_t used = dp->dp_root_dir->dd_phys->dd_used_bytes; + uint64_t used = dsl_dir_phys(dp->dp_root_dir)->dd_used_bytes; /* MOS space is triple-dittoed, so we multiply by 3. */ if (dst->dst_space > 0 && used + dst->dst_space * 3 > quota) { dst->dst_error = SET_ERROR(ENOSPC); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c index b6878d7ecc44..0985ec91fd50 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c @@ -64,10 +64,10 @@ dsl_dataset_user_hold_check_one(dsl_dataset_t *ds, const char *htag, return (SET_ERROR(E2BIG)); /* tags must be unique (if ds already exists) */ - if (ds != NULL && ds->ds_phys->ds_userrefs_obj != 0) { + if (ds != NULL && dsl_dataset_phys(ds)->ds_userrefs_obj != 0) { uint64_t value; - error = zap_lookup(mos, ds->ds_phys->ds_userrefs_obj, + error = zap_lookup(mos, dsl_dataset_phys(ds)->ds_userrefs_obj, htag, 8, 1, &value); if (error == 0) error = SET_ERROR(EEXIST); @@ -140,16 +140,16 @@ dsl_dataset_user_hold_sync_one_impl(nvlist_t *tmpholds, dsl_dataset_t *ds, ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock)); - if (ds->ds_phys->ds_userrefs_obj == 0) { + if (dsl_dataset_phys(ds)->ds_userrefs_obj == 0) { /* * This is the first user hold for this dataset. Create * the userrefs zap object. */ dmu_buf_will_dirty(ds->ds_dbuf, tx); - zapobj = ds->ds_phys->ds_userrefs_obj = + zapobj = dsl_dataset_phys(ds)->ds_userrefs_obj = zap_create(mos, DMU_OT_USERREFS, DMU_OT_NONE, 0, tx); } else { - zapobj = ds->ds_phys->ds_userrefs_obj; + zapobj = dsl_dataset_phys(ds)->ds_userrefs_obj; } ds->ds_userrefs++; @@ -360,7 +360,7 @@ dsl_dataset_user_release_check_one(dsl_dataset_user_release_arg_t *ddura, numholds = 0; mos = ds->ds_dir->dd_pool->dp_meta_objset; - zapobj = ds->ds_phys->ds_userrefs_obj; + zapobj = dsl_dataset_phys(ds)->ds_userrefs_obj; holds_found = fnvlist_alloc(); for (nvpair_t *pair = nvlist_next_nvpair(holds, NULL); pair != NULL; @@ -398,7 +398,8 @@ dsl_dataset_user_release_check_one(dsl_dataset_user_release_arg_t *ddura, numholds++; } - if (DS_IS_DEFER_DESTROY(ds) && ds->ds_phys->ds_num_children == 1 && + if (DS_IS_DEFER_DESTROY(ds) && + dsl_dataset_phys(ds)->ds_num_children == 1 && ds->ds_userrefs == numholds) { /* we need to destroy the snapshot as well */ if (dsl_dataset_long_held(ds)) { @@ -484,8 +485,8 @@ dsl_dataset_user_release_sync_one(dsl_dataset_t *ds, nvlist_t *holds, error = dsl_pool_user_release(dp, ds->ds_object, holdname, tx); VERIFY(error == 0 || error == ENOENT); - VERIFY0(zap_remove(mos, ds->ds_phys->ds_userrefs_obj, holdname, - tx)); + VERIFY0(zap_remove(mos, dsl_dataset_phys(ds)->ds_userrefs_obj, + holdname, tx)); ds->ds_userrefs--; spa_history_log_internal_ds(ds, "release", tx, @@ -514,7 +515,7 @@ dsl_dataset_user_release_sync(void *arg, dmu_tx_t *tx) fnvpair_value_nvlist(pair), tx); if (nvlist_exists(ddura->ddura_todelete, name)) { ASSERT(ds->ds_userrefs == 0 && - ds->ds_phys->ds_num_children == 1 && + dsl_dataset_phys(ds)->ds_num_children == 1 && DS_IS_DEFER_DESTROY(ds)); dsl_destroy_snapshot_sync_impl(ds, B_FALSE, tx); } @@ -644,13 +645,13 @@ dsl_dataset_get_holds(const char *dsname, nvlist_t *nvl) return (err); } - if (ds->ds_phys->ds_userrefs_obj != 0) { + if (dsl_dataset_phys(ds)->ds_userrefs_obj != 0) { zap_attribute_t *za; zap_cursor_t zc; za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); for (zap_cursor_init(&zc, ds->ds_dir->dd_pool->dp_meta_objset, - ds->ds_phys->ds_userrefs_obj); + dsl_dataset_phys(ds)->ds_userrefs_obj); zap_cursor_retrieve(&zc, za) == 0; zap_cursor_advance(&zc)) { fnvlist_add_uint64(nvl, za->za_name, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c index 84b39dd02929..e40361e1a3f6 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c @@ -1348,7 +1348,7 @@ sa_handle_destroy(sa_handle_t *hdl) { mutex_enter(&hdl->sa_lock); (void) dmu_buf_update_user((dmu_buf_t *)hdl->sa_bonus, hdl, - NULL, NULL, NULL); + NULL, NULL); if (hdl->sa_bonus_tab) { sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab); @@ -1395,8 +1395,7 @@ sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp, error = sa_build_index(handle, SA_BONUS); newhandle = (hdl_type == SA_HDL_SHARED) ? - dmu_buf_set_user_ie(db, handle, - NULL, sa_evict) : NULL; + dmu_buf_set_user_ie(db, handle, sa_evict) : NULL; if (newhandle != NULL) { kmem_cache_free(sa_cache, handle); @@ -1921,7 +1920,7 @@ void sa_update_user(sa_handle_t *newhdl, sa_handle_t *oldhdl) { (void) dmu_buf_update_user((dmu_buf_t *)newhdl->sa_bonus, - oldhdl, newhdl, NULL, sa_evict); + oldhdl, newhdl, sa_evict); oldhdl->sa_bonus = NULL; } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c index 9c62669e9b0a..7886fd9302d5 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -261,7 +261,8 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp) */ if (pool->dp_free_dir != NULL) { spa_prop_add_list(*nvp, ZPOOL_PROP_FREEING, NULL, - pool->dp_free_dir->dd_phys->dd_used_bytes, src); + dsl_dir_phys(pool->dp_free_dir)->dd_used_bytes, + src); } else { spa_prop_add_list(*nvp, ZPOOL_PROP_FREEING, NULL, 0, src); @@ -269,7 +270,8 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp) if (pool->dp_leak_dir != NULL) { spa_prop_add_list(*nvp, ZPOOL_PROP_LEAKED, NULL, - pool->dp_leak_dir->dd_phys->dd_used_bytes, src); + dsl_dir_phys(pool->dp_leak_dir)->dd_used_bytes, + src); } else { spa_prop_add_list(*nvp, ZPOOL_PROP_LEAKED, NULL, 0, src); @@ -6604,21 +6606,6 @@ spa_sync(spa_t *spa, uint64_t txg) } } - /* - * If anything has changed in this txg, or if someone is waiting - * for this txg to sync (eg, spa_vdev_remove()), push the - * deferred frees from the previous txg. If not, leave them - * alone so that we don't generate work on an otherwise idle - * system. - */ - if (!txg_list_empty(&dp->dp_dirty_datasets, txg) || - !txg_list_empty(&dp->dp_dirty_dirs, txg) || - !txg_list_empty(&dp->dp_sync_tasks, txg) || - ((dsl_scan_active(dp->dp_scan) || - txg_sync_waiting(dp)) && !spa_shutting_down(spa))) { - spa_sync_deferred_frees(spa, tx); - } - /* * Iterate to convergence. */ @@ -6636,6 +6623,11 @@ spa_sync(spa_t *spa, uint64_t txg) if (pass < zfs_sync_pass_deferred_free) { spa_sync_frees(spa, free_bpl, tx); } else { + /* + * We can not defer frees in pass 1, because + * we sync the deferred frees later in pass 1. + */ + ASSERT3U(pass, >, 1); bplist_iterate(free_bpl, bpobj_enqueue_cb, &spa->spa_deferred_bpobj, tx); } @@ -6646,8 +6638,37 @@ spa_sync(spa_t *spa, uint64_t txg) while (vd = txg_list_remove(&spa->spa_vdev_txg_list, txg)) vdev_sync(vd, txg); - if (pass == 1) + if (pass == 1) { spa_sync_upgrades(spa, tx); + ASSERT3U(txg, >=, + spa->spa_uberblock.ub_rootbp.blk_birth); + /* + * Note: We need to check if the MOS is dirty + * because we could have marked the MOS dirty + * without updating the uberblock (e.g. if we + * have sync tasks but no dirty user data). We + * need to check the uberblock's rootbp because + * it is updated if we have synced out dirty + * data (though in this case the MOS will most + * likely also be dirty due to second order + * effects, we don't want to rely on that here). + */ + if (spa->spa_uberblock.ub_rootbp.blk_birth < txg && + !dmu_objset_is_dirty(mos, txg)) { + /* + * Nothing changed on the first pass, + * therefore this TXG is a no-op. Avoid + * syncing deferred frees, so that we + * can keep this TXG as a no-op. + */ + ASSERT(txg_list_empty(&dp->dp_dirty_datasets, + txg)); + ASSERT(txg_list_empty(&dp->dp_dirty_dirs, txg)); + ASSERT(txg_list_empty(&dp->dp_sync_tasks, txg)); + break; + } + spa_sync_deferred_frees(spa, tx); + } } while (dmu_objset_is_dirty(mos, txg)); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c index 9fc7a463c653..ecd5435b5480 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c @@ -527,7 +527,7 @@ spa_history_log_internal_dd(dsl_dir_t *dd, const char *operation, dsl_dir_name(dd, namebuf); fnvlist_add_string(nvl, ZPOOL_HIST_DSNAME, namebuf); fnvlist_add_uint64(nvl, ZPOOL_HIST_DSID, - dd->dd_phys->dd_head_dataset_obj); + dsl_dir_phys(dd)->dd_head_dataset_obj); va_start(adx, fmt); log_internal(nvl, operation, dd->dd_pool->dp_spa, tx, fmt, adx); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h index 9065a22afd4e..eb2186755fb9 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h @@ -46,6 +46,36 @@ typedef int arc_evict_func_t(void *priv); arc_done_func_t arc_bcopy_func; arc_done_func_t arc_getbuf_func; +typedef enum arc_flags +{ + /* + * Public flags that can be passed into the ARC by external consumers. + */ + ARC_FLAG_NONE = 1 << 0, /* No flags set */ + ARC_FLAG_WAIT = 1 << 1, /* perform sync I/O */ + ARC_FLAG_NOWAIT = 1 << 2, /* perform async I/O */ + ARC_FLAG_PREFETCH = 1 << 3, /* I/O is a prefetch */ + ARC_FLAG_CACHED = 1 << 4, /* I/O was in cache */ + ARC_FLAG_L2CACHE = 1 << 5, /* cache in L2ARC */ + ARC_FLAG_L2COMPRESS = 1 << 6, /* compress in L2ARC */ + + /* + * Private ARC flags. These flags are private ARC only flags that + * will show up in b_flags in the arc_hdr_buf_t. These flags should + * only be set by ARC code. + */ + ARC_FLAG_IN_HASH_TABLE = 1 << 7, /* buffer is hashed */ + ARC_FLAG_IO_IN_PROGRESS = 1 << 8, /* I/O in progress */ + ARC_FLAG_IO_ERROR = 1 << 9, /* I/O failed for buf */ + ARC_FLAG_FREED_IN_READ = 1 << 10, /* freed during read */ + ARC_FLAG_BUF_AVAILABLE = 1 << 11, /* block not in use */ + ARC_FLAG_INDIRECT = 1 << 12, /* indirect block */ + ARC_FLAG_FREE_IN_PROGRESS = 1 << 13, /* about to be freed */ + ARC_FLAG_L2_WRITING = 1 << 14, /* write in progress */ + ARC_FLAG_L2_EVICTED = 1 << 15, /* evicted during I/O */ + ARC_FLAG_L2_WRITE_HEAD = 1 << 16, /* head of write list */ +} arc_flags_t; + struct arc_buf { arc_buf_hdr_t *b_hdr; arc_buf_t *b_next; @@ -60,15 +90,6 @@ typedef enum arc_buf_contents { ARC_BUFC_METADATA, /* buffer contains metadata */ ARC_BUFC_NUMTYPES } arc_buf_contents_t; -/* - * These are the flags we pass into calls to the arc - */ -#define ARC_WAIT (1 << 1) /* perform I/O synchronously */ -#define ARC_NOWAIT (1 << 2) /* perform I/O asynchronously */ -#define ARC_PREFETCH (1 << 3) /* I/O is a prefetch */ -#define ARC_CACHED (1 << 4) /* I/O was already in cache */ -#define ARC_L2CACHE (1 << 5) /* cache in L2ARC */ -#define ARC_L2COMPRESS (1 << 6) /* compress in L2ARC */ /* * The following breakdows of arc_size exist for kstat only. @@ -102,7 +123,7 @@ int arc_referenced(arc_buf_t *buf); int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done, void *priv, zio_priority_t priority, int flags, - uint32_t *arc_flags, const zbookmark_phys_t *zb); + arc_flags_t *arc_flags, const zbookmark_phys_t *zb); zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc, boolean_t l2arc_compress, const zio_prop_t *zp, arc_done_func_t *ready, arc_done_func_t *physdone, diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h index 8ca8753e5e6d..8be8ed6bc85b 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h @@ -228,7 +228,6 @@ typedef struct dmu_buf_impl { /* stuff we store for the user (see dmu_buf_set_user) */ void *db_user_ptr; - void **db_user_data_ptr_ptr; dmu_buf_evict_func_t *db_evict_func; uint8_t db_immediate_evict; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h index d85d872f89da..3881d247b6d9 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h @@ -486,12 +486,6 @@ void dmu_buf_rele_array(dmu_buf_t **, int numbufs, void *tag); * * user_ptr is for use by the user and can be obtained via dmu_buf_get_user(). * - * user_data_ptr_ptr should be NULL, or a pointer to a pointer which - * will be set to db->db_data when you are allowed to access it. Note - * that db->db_data (the pointer) can change when you do dmu_buf_read(), - * dmu_buf_tryupgrade(), dmu_buf_will_dirty(), or dmu_buf_will_fill(). - * *user_data_ptr_ptr will be set to the new value when it changes. - * * If non-NULL, pageout func will be called when this buffer is being * excised from the cache, so that you can clean up the data structure * pointed to by user_ptr. @@ -499,17 +493,16 @@ void dmu_buf_rele_array(dmu_buf_t **, int numbufs, void *tag); * dmu_evict_user() will call the pageout func for all buffers in a * objset with a given pageout func. */ -void *dmu_buf_set_user(dmu_buf_t *db, void *user_ptr, void *user_data_ptr_ptr, +void *dmu_buf_set_user(dmu_buf_t *db, void *user_ptr, dmu_buf_evict_func_t *pageout_func); /* * set_user_ie is the same as set_user, but request immediate eviction * when hold count goes to zero. */ void *dmu_buf_set_user_ie(dmu_buf_t *db, void *user_ptr, - void *user_data_ptr_ptr, dmu_buf_evict_func_t *pageout_func); -void *dmu_buf_update_user(dmu_buf_t *db_fake, void *old_user_ptr, - void *user_ptr, void *user_data_ptr_ptr, dmu_buf_evict_func_t *pageout_func); +void *dmu_buf_update_user(dmu_buf_t *db_fake, void *old_user_ptr, + void *user_ptr, dmu_buf_evict_func_t *pageout_func); void dmu_evict_user(objset_t *os, dmu_buf_evict_func_t *func); /* diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h index ff90f8b439cc..3160a05a8c59 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h @@ -48,7 +48,7 @@ struct dsl_pool; #define DS_FLAG_INCONSISTENT (1ULL<<0) #define DS_IS_INCONSISTENT(ds) \ - ((ds)->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) + (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_INCONSISTENT) /* * Do not allow this dataset to be promoted. @@ -68,7 +68,7 @@ struct dsl_pool; */ #define DS_FLAG_DEFER_DESTROY (1ULL<<3) #define DS_IS_DEFER_DESTROY(ds) \ - ((ds)->ds_phys->ds_flags & DS_FLAG_DEFER_DESTROY) + (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_DEFER_DESTROY) /* * DS_FIELD_* are strings that are used in the "extensified" dataset zap object. @@ -134,7 +134,6 @@ typedef struct dsl_dataset_phys { typedef struct dsl_dataset { /* Immutable: */ struct dsl_dir *ds_dir; - dsl_dataset_phys_t *ds_phys; dmu_buf_t *ds_dbuf; uint64_t ds_object; uint64_t ds_fsid_guid; @@ -186,17 +185,26 @@ typedef struct dsl_dataset { char ds_snapname[MAXNAMELEN]; } dsl_dataset_t; +inline dsl_dataset_phys_t * +dsl_dataset_phys(dsl_dataset_t *ds) +{ + return (ds->ds_dbuf->db_data); +} + /* * The max length of a temporary tag prefix is the number of hex digits * required to express UINT64_MAX plus one for the hyphen. */ #define MAX_TAG_PREFIX_LEN 17 -#define dsl_dataset_is_snapshot(ds) \ - ((ds)->ds_phys->ds_num_children != 0) +inline boolean_t +dsl_dataset_is_snapshot(dsl_dataset_t *ds) +{ + return (dsl_dataset_phys(ds)->ds_num_children != 0); +} #define DS_UNIQUE_IS_ACCURATE(ds) \ - (((ds)->ds_phys->ds_flags & DS_FLAG_UNIQUE_ACCURATE) != 0) + ((dsl_dataset_phys(ds)->ds_flags & DS_FLAG_UNIQUE_ACCURATE) != 0) int dsl_dataset_hold(struct dsl_pool *dp, const char *name, void *tag, dsl_dataset_t **dsp); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h index a9c4f67515a9..772bfbe6db12 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dir.h @@ -86,10 +86,11 @@ typedef struct dsl_dir_phys { struct dsl_dir { /* These are immutable; no lock needed: */ uint64_t dd_object; - dsl_dir_phys_t *dd_phys; - dmu_buf_t *dd_dbuf; dsl_pool_t *dd_pool; + /* Stable until user eviction; no lock needed: */ + dmu_buf_t *dd_dbuf; + /* protected by lock on pool's dp_dirty_dirs list */ txg_node_t dd_dirty_link; @@ -111,6 +112,12 @@ struct dsl_dir { char dd_myname[MAXNAMELEN]; }; +inline dsl_dir_phys_t * +dsl_dir_phys(dsl_dir_t *dd) +{ + return (dd->dd_dbuf->db_data); +} + void dsl_dir_rele(dsl_dir_t *dd, void *tag); int dsl_dir_hold(dsl_pool_t *dp, const char *name, void *tag, dsl_dir_t **, const char **tail); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/uberblock.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/uberblock.h index b5bb91573145..21e7ae0de7a7 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/uberblock.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/uberblock.h @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2014 by Delphix. All rights reserved. + */ #ifndef _SYS_UBERBLOCK_H #define _SYS_UBERBLOCK_H @@ -36,8 +39,8 @@ extern "C" { typedef struct uberblock uberblock_t; -extern int uberblock_verify(uberblock_t *ub); -extern int uberblock_update(uberblock_t *ub, vdev_t *rvd, uint64_t txg); +extern int uberblock_verify(uberblock_t *); +extern boolean_t uberblock_update(uberblock_t *, vdev_t *, uint64_t); #ifdef __cplusplus } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_impl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_impl.h index 29ebae53849d..d95cd5d16fb9 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_impl.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_impl.h @@ -69,7 +69,7 @@ typedef struct mzap_ent { } mzap_ent_t; #define MZE_PHYS(zap, mze) \ - (&(zap)->zap_m.zap_phys->mz_chunk[(mze)->mze_chunkid]) + (&zap_m_phys(zap)->mz_chunk[(mze)->mze_chunkid]) /* * The (fat) zap is stored in one object. It is an array of @@ -103,7 +103,7 @@ struct zap_leaf; * word number (1<zap_f.zap_phys) \ + ((uint64_t *)zap_f_phys(zap)) \ [(idx) + (1<zap_dbuf->db_data); +} + +inline mzap_phys_t * +zap_m_phys(zap_t *zap) +{ + return (zap->zap_dbuf->db_data); +} + typedef struct zap_name { zap_t *zn_zap; int zn_key_intlen; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_leaf.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_leaf.h index f6947a72d70e..cd8b74a77a8c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_leaf.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_leaf.h @@ -83,7 +83,7 @@ struct zap_stats; */ #define ZAP_LEAF_CHUNK(l, idx) \ ((zap_leaf_chunk_t *) \ - ((l)->l_phys->l_hash + ZAP_LEAF_HASH_NUMENTRIES(l)))[idx] + (zap_leaf_phys(l)->l_hash + ZAP_LEAF_HASH_NUMENTRIES(l)))[idx] #define ZAP_LEAF_ENTRY(l, idx) (&ZAP_LEAF_CHUNK(l, idx).l_entry) typedef enum zap_chunk_type { @@ -156,9 +156,13 @@ typedef struct zap_leaf { uint64_t l_blkid; /* 1<l_dbuf->db_data); +} typedef struct zap_entry_handle { /* Set by zap_leaf and public to ZAP */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c index a07dc00ae19a..f8bdecdf5749 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2013, 2014 by Delphix. All rights reserved. */ #include @@ -40,10 +40,10 @@ uberblock_verify(uberblock_t *ub) } /* - * Update the uberblock and return a boolean value indicating whether - * anything changed in this transaction group. + * Update the uberblock and return TRUE if anything changed in this + * transaction group. */ -int +boolean_t uberblock_update(uberblock_t *ub, vdev_t *rvd, uint64_t txg) { ASSERT(ub->ub_txg < txg); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c index 18d722276b2f..397acb9fc247 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c @@ -50,10 +50,11 @@ int fzap_default_block_shift = 14; /* 16k blocksize */ +extern inline zap_phys_t *zap_f_phys(zap_t *zap); + static void zap_leaf_pageout(dmu_buf_t *db, void *vl); static uint64_t zap_allocate_blocks(zap_t *zap, int nblocks); - void fzap_byteswap(void *vbuf, size_t size) { @@ -80,13 +81,12 @@ fzap_upgrade(zap_t *zap, dmu_tx_t *tx, zap_flags_t flags) ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); zap->zap_ismicro = FALSE; - (void) dmu_buf_update_user(zap->zap_dbuf, zap, zap, - &zap->zap_f.zap_phys, zap_evict); + (void) dmu_buf_update_user(zap->zap_dbuf, zap, zap, zap_evict); mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0); zap->zap_f.zap_block_shift = highbit64(zap->zap_dbuf->db_size) - 1; - zp = zap->zap_f.zap_phys; + zp = zap_f_phys(zap); /* * explicitly zero it since it might be coming from an * initialized microzap @@ -117,7 +117,6 @@ fzap_upgrade(zap_t *zap, dmu_tx_t *tx, zap_flags_t flags) l = kmem_zalloc(sizeof (zap_leaf_t), KM_SLEEP); l->l_dbuf = db; - l->l_phys = db->db_data; zap_leaf_init(l, zp->zap_normflags != 0); @@ -325,10 +324,10 @@ zap_grow_ptrtbl(zap_t *zap, dmu_tx_t *tx) * If we are within 2 bits of running out, stop growing, since * this is already an aberrant condition. */ - if (zap->zap_f.zap_phys->zap_ptrtbl.zt_shift >= zap_hashbits(zap) - 2) + if (zap_f_phys(zap)->zap_ptrtbl.zt_shift >= zap_hashbits(zap) - 2) return (SET_ERROR(ENOSPC)); - if (zap->zap_f.zap_phys->zap_ptrtbl.zt_numblks == 0) { + if (zap_f_phys(zap)->zap_ptrtbl.zt_numblks == 0) { /* * We are outgrowing the "embedded" ptrtbl (the one * stored in the header block). Give it its own entire @@ -338,9 +337,9 @@ zap_grow_ptrtbl(zap_t *zap, dmu_tx_t *tx) dmu_buf_t *db_new; int err; - ASSERT3U(zap->zap_f.zap_phys->zap_ptrtbl.zt_shift, ==, + ASSERT3U(zap_f_phys(zap)->zap_ptrtbl.zt_shift, ==, ZAP_EMBEDDED_PTRTBL_SHIFT(zap)); - ASSERT0(zap->zap_f.zap_phys->zap_ptrtbl.zt_blk); + ASSERT0(zap_f_phys(zap)->zap_ptrtbl.zt_blk); newblk = zap_allocate_blocks(zap, 1); err = dmu_buf_hold(zap->zap_objset, zap->zap_object, @@ -353,17 +352,17 @@ zap_grow_ptrtbl(zap_t *zap, dmu_tx_t *tx) db_new->db_data, 1 << ZAP_EMBEDDED_PTRTBL_SHIFT(zap)); dmu_buf_rele(db_new, FTAG); - zap->zap_f.zap_phys->zap_ptrtbl.zt_blk = newblk; - zap->zap_f.zap_phys->zap_ptrtbl.zt_numblks = 1; - zap->zap_f.zap_phys->zap_ptrtbl.zt_shift++; + zap_f_phys(zap)->zap_ptrtbl.zt_blk = newblk; + zap_f_phys(zap)->zap_ptrtbl.zt_numblks = 1; + zap_f_phys(zap)->zap_ptrtbl.zt_shift++; - ASSERT3U(1ULL << zap->zap_f.zap_phys->zap_ptrtbl.zt_shift, ==, - zap->zap_f.zap_phys->zap_ptrtbl.zt_numblks << + ASSERT3U(1ULL << zap_f_phys(zap)->zap_ptrtbl.zt_shift, ==, + zap_f_phys(zap)->zap_ptrtbl.zt_numblks << (FZAP_BLOCK_SHIFT(zap)-3)); return (0); } else { - return (zap_table_grow(zap, &zap->zap_f.zap_phys->zap_ptrtbl, + return (zap_table_grow(zap, &zap_f_phys(zap)->zap_ptrtbl, zap_ptrtbl_transfer, tx)); } } @@ -373,8 +372,8 @@ zap_increment_num_entries(zap_t *zap, int delta, dmu_tx_t *tx) { dmu_buf_will_dirty(zap->zap_dbuf, tx); mutex_enter(&zap->zap_f.zap_num_entries_mtx); - ASSERT(delta > 0 || zap->zap_f.zap_phys->zap_num_entries >= -delta); - zap->zap_f.zap_phys->zap_num_entries += delta; + ASSERT(delta > 0 || zap_f_phys(zap)->zap_num_entries >= -delta); + zap_f_phys(zap)->zap_num_entries += delta; mutex_exit(&zap->zap_f.zap_num_entries_mtx); } @@ -383,8 +382,8 @@ zap_allocate_blocks(zap_t *zap, int nblocks) { uint64_t newblk; ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); - newblk = zap->zap_f.zap_phys->zap_freeblk; - zap->zap_f.zap_phys->zap_freeblk += nblocks; + newblk = zap_f_phys(zap)->zap_freeblk; + zap_f_phys(zap)->zap_freeblk += nblocks; return (newblk); } @@ -400,18 +399,17 @@ zap_create_leaf(zap_t *zap, dmu_tx_t *tx) rw_enter(&l->l_rwlock, RW_WRITER); l->l_blkid = zap_allocate_blocks(zap, 1); l->l_dbuf = NULL; - l->l_phys = NULL; VERIFY(0 == dmu_buf_hold(zap->zap_objset, zap->zap_object, l->l_blkid << FZAP_BLOCK_SHIFT(zap), NULL, &l->l_dbuf, DMU_READ_NO_PREFETCH)); - winner = dmu_buf_set_user(l->l_dbuf, l, &l->l_phys, zap_leaf_pageout); + winner = dmu_buf_set_user(l->l_dbuf, l, zap_leaf_pageout); ASSERT(winner == NULL); dmu_buf_will_dirty(l->l_dbuf, tx); zap_leaf_init(l, zap->zap_normflags != 0); - zap->zap_f.zap_phys->zap_num_leafs++; + zap_f_phys(zap)->zap_num_leafs++; return (l); } @@ -421,7 +419,7 @@ fzap_count(zap_t *zap, uint64_t *count) { ASSERT(!zap->zap_ismicro); mutex_enter(&zap->zap_f.zap_num_entries_mtx); /* unnecessary */ - *count = zap->zap_f.zap_phys->zap_num_entries; + *count = zap_f_phys(zap)->zap_num_entries; mutex_exit(&zap->zap_f.zap_num_entries_mtx); return (0); } @@ -460,9 +458,8 @@ zap_open_leaf(uint64_t blkid, dmu_buf_t *db) l->l_blkid = blkid; l->l_bs = highbit64(db->db_size) - 1; l->l_dbuf = db; - l->l_phys = NULL; - winner = dmu_buf_set_user(db, l, &l->l_phys, zap_leaf_pageout); + winner = dmu_buf_set_user(db, l, zap_leaf_pageout); rw_exit(&l->l_rwlock); if (winner != NULL) { @@ -476,7 +473,7 @@ zap_open_leaf(uint64_t blkid, dmu_buf_t *db) * chain. There should be no chained leafs (as we have removed * support for them). */ - ASSERT0(l->l_phys->l_hdr.lh_pad1); + ASSERT0(zap_leaf_phys(l)->l_hdr.lh_pad1); /* * There should be more hash entries than there can be @@ -486,11 +483,11 @@ zap_open_leaf(uint64_t blkid, dmu_buf_t *db) /* The chunks should begin at the end of the hash table */ ASSERT3P(&ZAP_LEAF_CHUNK(l, 0), ==, - &l->l_phys->l_hash[ZAP_LEAF_HASH_NUMENTRIES(l)]); + &zap_leaf_phys(l)->l_hash[ZAP_LEAF_HASH_NUMENTRIES(l)]); /* The chunks should end at the end of the block */ ASSERT3U((uintptr_t)&ZAP_LEAF_CHUNK(l, ZAP_LEAF_NUMCHUNKS(l)) - - (uintptr_t)l->l_phys, ==, l->l_dbuf->db_size); + (uintptr_t)zap_leaf_phys(l), ==, l->l_dbuf->db_size); return (l); } @@ -523,16 +520,15 @@ zap_get_leaf_byblk(zap_t *zap, uint64_t blkid, dmu_tx_t *tx, krw_t lt, rw_enter(&l->l_rwlock, lt); /* - * Must lock before dirtying, otherwise l->l_phys could change, + * Must lock before dirtying, otherwise zap_leaf_phys(l) could change, * causing ASSERT below to fail. */ if (lt == RW_WRITER) dmu_buf_will_dirty(db, tx); ASSERT3U(l->l_blkid, ==, blkid); ASSERT3P(l->l_dbuf, ==, db); - ASSERT3P(l->l_phys, ==, l->l_dbuf->db_data); - ASSERT3U(l->l_phys->l_hdr.lh_block_type, ==, ZBT_LEAF); - ASSERT3U(l->l_phys->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC); + ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_block_type, ==, ZBT_LEAF); + ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC); *lp = l; return (0); @@ -543,13 +539,13 @@ zap_idx_to_blk(zap_t *zap, uint64_t idx, uint64_t *valp) { ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); - if (zap->zap_f.zap_phys->zap_ptrtbl.zt_numblks == 0) { + if (zap_f_phys(zap)->zap_ptrtbl.zt_numblks == 0) { ASSERT3U(idx, <, - (1ULL << zap->zap_f.zap_phys->zap_ptrtbl.zt_shift)); + (1ULL << zap_f_phys(zap)->zap_ptrtbl.zt_shift)); *valp = ZAP_EMBEDDED_PTRTBL_ENT(zap, idx); return (0); } else { - return (zap_table_load(zap, &zap->zap_f.zap_phys->zap_ptrtbl, + return (zap_table_load(zap, &zap_f_phys(zap)->zap_ptrtbl, idx, valp)); } } @@ -560,11 +556,11 @@ zap_set_idx_to_blk(zap_t *zap, uint64_t idx, uint64_t blk, dmu_tx_t *tx) ASSERT(tx != NULL); ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); - if (zap->zap_f.zap_phys->zap_ptrtbl.zt_blk == 0) { + if (zap_f_phys(zap)->zap_ptrtbl.zt_blk == 0) { ZAP_EMBEDDED_PTRTBL_ENT(zap, idx) = blk; return (0); } else { - return (zap_table_store(zap, &zap->zap_f.zap_phys->zap_ptrtbl, + return (zap_table_store(zap, &zap_f_phys(zap)->zap_ptrtbl, idx, blk, tx)); } } @@ -576,16 +572,17 @@ zap_deref_leaf(zap_t *zap, uint64_t h, dmu_tx_t *tx, krw_t lt, zap_leaf_t **lp) int err; ASSERT(zap->zap_dbuf == NULL || - zap->zap_f.zap_phys == zap->zap_dbuf->db_data); - ASSERT3U(zap->zap_f.zap_phys->zap_magic, ==, ZAP_MAGIC); - idx = ZAP_HASH_IDX(h, zap->zap_f.zap_phys->zap_ptrtbl.zt_shift); + zap_f_phys(zap) == zap->zap_dbuf->db_data); + ASSERT3U(zap_f_phys(zap)->zap_magic, ==, ZAP_MAGIC); + idx = ZAP_HASH_IDX(h, zap_f_phys(zap)->zap_ptrtbl.zt_shift); err = zap_idx_to_blk(zap, idx, &blk); if (err != 0) return (err); err = zap_get_leaf_byblk(zap, blk, tx, lt, lp); - ASSERT(err || ZAP_HASH_IDX(h, (*lp)->l_phys->l_hdr.lh_prefix_len) == - (*lp)->l_phys->l_hdr.lh_prefix); + ASSERT(err || + ZAP_HASH_IDX(h, zap_leaf_phys(*lp)->l_hdr.lh_prefix_len) == + zap_leaf_phys(*lp)->l_hdr.lh_prefix); return (err); } @@ -597,16 +594,16 @@ zap_expand_leaf(zap_name_t *zn, zap_leaf_t *l, dmu_tx_t *tx, zap_leaf_t **lp) zap_leaf_t *nl; int prefix_diff, i, err; uint64_t sibling; - int old_prefix_len = l->l_phys->l_hdr.lh_prefix_len; + int old_prefix_len = zap_leaf_phys(l)->l_hdr.lh_prefix_len; - ASSERT3U(old_prefix_len, <=, zap->zap_f.zap_phys->zap_ptrtbl.zt_shift); + ASSERT3U(old_prefix_len, <=, zap_f_phys(zap)->zap_ptrtbl.zt_shift); ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); ASSERT3U(ZAP_HASH_IDX(hash, old_prefix_len), ==, - l->l_phys->l_hdr.lh_prefix); + zap_leaf_phys(l)->l_hdr.lh_prefix); if (zap_tryupgradedir(zap, tx) == 0 || - old_prefix_len == zap->zap_f.zap_phys->zap_ptrtbl.zt_shift) { + old_prefix_len == zap_f_phys(zap)->zap_ptrtbl.zt_shift) { /* We failed to upgrade, or need to grow the pointer table */ objset_t *os = zap->zap_objset; uint64_t object = zap->zap_object; @@ -621,7 +618,7 @@ zap_expand_leaf(zap_name_t *zn, zap_leaf_t *l, dmu_tx_t *tx, zap_leaf_t **lp) ASSERT(!zap->zap_ismicro); while (old_prefix_len == - zap->zap_f.zap_phys->zap_ptrtbl.zt_shift) { + zap_f_phys(zap)->zap_ptrtbl.zt_shift) { err = zap_grow_ptrtbl(zap, tx); if (err) return (err); @@ -631,18 +628,18 @@ zap_expand_leaf(zap_name_t *zn, zap_leaf_t *l, dmu_tx_t *tx, zap_leaf_t **lp) if (err) return (err); - if (l->l_phys->l_hdr.lh_prefix_len != old_prefix_len) { + if (zap_leaf_phys(l)->l_hdr.lh_prefix_len != old_prefix_len) { /* it split while our locks were down */ *lp = l; return (0); } } ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); - ASSERT3U(old_prefix_len, <, zap->zap_f.zap_phys->zap_ptrtbl.zt_shift); + ASSERT3U(old_prefix_len, <, zap_f_phys(zap)->zap_ptrtbl.zt_shift); ASSERT3U(ZAP_HASH_IDX(hash, old_prefix_len), ==, - l->l_phys->l_hdr.lh_prefix); + zap_leaf_phys(l)->l_hdr.lh_prefix); - prefix_diff = zap->zap_f.zap_phys->zap_ptrtbl.zt_shift - + prefix_diff = zap_f_phys(zap)->zap_ptrtbl.zt_shift - (old_prefix_len + 1); sibling = (ZAP_HASH_IDX(hash, old_prefix_len + 1) | 1) << prefix_diff; @@ -664,7 +661,7 @@ zap_expand_leaf(zap_name_t *zn, zap_leaf_t *l, dmu_tx_t *tx, zap_leaf_t **lp) ASSERT0(err); /* we checked for i/o errors above */ } - if (hash & (1ULL << (64 - l->l_phys->l_hdr.lh_prefix_len))) { + if (hash & (1ULL << (64 - zap_leaf_phys(l)->l_hdr.lh_prefix_len))) { /* we want the sibling */ zap_put_leaf(l); *lp = nl; @@ -680,13 +677,13 @@ static void zap_put_leaf_maybe_grow_ptrtbl(zap_name_t *zn, zap_leaf_t *l, dmu_tx_t *tx) { zap_t *zap = zn->zn_zap; - int shift = zap->zap_f.zap_phys->zap_ptrtbl.zt_shift; - int leaffull = (l->l_phys->l_hdr.lh_prefix_len == shift && - l->l_phys->l_hdr.lh_nfree < ZAP_LEAF_LOW_WATER); + int shift = zap_f_phys(zap)->zap_ptrtbl.zt_shift; + int leaffull = (zap_leaf_phys(l)->l_hdr.lh_prefix_len == shift && + zap_leaf_phys(l)->l_hdr.lh_nfree < ZAP_LEAF_LOW_WATER); zap_put_leaf(l); - if (leaffull || zap->zap_f.zap_phys->zap_ptrtbl.zt_nextblk) { + if (leaffull || zap_f_phys(zap)->zap_ptrtbl.zt_nextblk) { int err; /* @@ -706,7 +703,7 @@ zap_put_leaf_maybe_grow_ptrtbl(zap_name_t *zn, zap_leaf_t *l, dmu_tx_t *tx) } /* could have finished growing while our locks were down */ - if (zap->zap_f.zap_phys->zap_ptrtbl.zt_shift == shift) + if (zap_f_phys(zap)->zap_ptrtbl.zt_shift == shift) (void) zap_grow_ptrtbl(zap, tx); } } @@ -937,7 +934,7 @@ fzap_prefetch(zap_name_t *zn) int bs; idx = ZAP_HASH_IDX(zn->zn_hash, - zap->zap_f.zap_phys->zap_ptrtbl.zt_shift); + zap_f_phys(zap)->zap_ptrtbl.zt_shift); if (zap_idx_to_blk(zap, idx, &blk) != 0) return; bs = FZAP_BLOCK_SHIFT(zap); @@ -1169,8 +1166,8 @@ fzap_cursor_retrieve(zap_t *zap, zap_cursor_t *zc, zap_attribute_t *za) if (zc->zc_leaf && (ZAP_HASH_IDX(zc->zc_hash, - zc->zc_leaf->l_phys->l_hdr.lh_prefix_len) != - zc->zc_leaf->l_phys->l_hdr.lh_prefix)) { + zap_leaf_phys(zc->zc_leaf)->l_hdr.lh_prefix_len) != + zap_leaf_phys(zc->zc_leaf)->l_hdr.lh_prefix)) { rw_enter(&zc->zc_leaf->l_rwlock, RW_READER); zap_put_leaf(zc->zc_leaf); zc->zc_leaf = NULL; @@ -1191,10 +1188,11 @@ fzap_cursor_retrieve(zap_t *zap, zap_cursor_t *zc, zap_attribute_t *za) if (err == ENOENT) { uint64_t nocare = - (1ULL << (64 - l->l_phys->l_hdr.lh_prefix_len)) - 1; + (1ULL << (64 - zap_leaf_phys(l)->l_hdr.lh_prefix_len)) - 1; zc->zc_hash = (zc->zc_hash & ~nocare) + nocare + 1; zc->zc_cd = 0; - if (l->l_phys->l_hdr.lh_prefix_len == 0 || zc->zc_hash == 0) { + if (zap_leaf_phys(l)->l_hdr.lh_prefix_len == 0 || + zc->zc_hash == 0) { zc->zc_hash = -1ULL; } else { zap_put_leaf(zc->zc_leaf); @@ -1286,25 +1284,25 @@ fzap_get_stats(zap_t *zap, zap_stats_t *zs) /* * Set zap_phys_t fields */ - zs->zs_num_leafs = zap->zap_f.zap_phys->zap_num_leafs; - zs->zs_num_entries = zap->zap_f.zap_phys->zap_num_entries; - zs->zs_num_blocks = zap->zap_f.zap_phys->zap_freeblk; - zs->zs_block_type = zap->zap_f.zap_phys->zap_block_type; - zs->zs_magic = zap->zap_f.zap_phys->zap_magic; - zs->zs_salt = zap->zap_f.zap_phys->zap_salt; + zs->zs_num_leafs = zap_f_phys(zap)->zap_num_leafs; + zs->zs_num_entries = zap_f_phys(zap)->zap_num_entries; + zs->zs_num_blocks = zap_f_phys(zap)->zap_freeblk; + zs->zs_block_type = zap_f_phys(zap)->zap_block_type; + zs->zs_magic = zap_f_phys(zap)->zap_magic; + zs->zs_salt = zap_f_phys(zap)->zap_salt; /* * Set zap_ptrtbl fields */ - zs->zs_ptrtbl_len = 1ULL << zap->zap_f.zap_phys->zap_ptrtbl.zt_shift; - zs->zs_ptrtbl_nextblk = zap->zap_f.zap_phys->zap_ptrtbl.zt_nextblk; + zs->zs_ptrtbl_len = 1ULL << zap_f_phys(zap)->zap_ptrtbl.zt_shift; + zs->zs_ptrtbl_nextblk = zap_f_phys(zap)->zap_ptrtbl.zt_nextblk; zs->zs_ptrtbl_blks_copied = - zap->zap_f.zap_phys->zap_ptrtbl.zt_blks_copied; - zs->zs_ptrtbl_zt_blk = zap->zap_f.zap_phys->zap_ptrtbl.zt_blk; - zs->zs_ptrtbl_zt_numblks = zap->zap_f.zap_phys->zap_ptrtbl.zt_numblks; - zs->zs_ptrtbl_zt_shift = zap->zap_f.zap_phys->zap_ptrtbl.zt_shift; + zap_f_phys(zap)->zap_ptrtbl.zt_blks_copied; + zs->zs_ptrtbl_zt_blk = zap_f_phys(zap)->zap_ptrtbl.zt_blk; + zs->zs_ptrtbl_zt_numblks = zap_f_phys(zap)->zap_ptrtbl.zt_numblks; + zs->zs_ptrtbl_zt_shift = zap_f_phys(zap)->zap_ptrtbl.zt_shift; - if (zap->zap_f.zap_phys->zap_ptrtbl.zt_numblks == 0) { + if (zap_f_phys(zap)->zap_ptrtbl.zt_numblks == 0) { /* the ptrtbl is entirely in the header block. */ zap_stats_ptrtbl(zap, &ZAP_EMBEDDED_PTRTBL_ENT(zap, 0), 1 << ZAP_EMBEDDED_PTRTBL_SHIFT(zap), zs); @@ -1312,16 +1310,16 @@ fzap_get_stats(zap_t *zap, zap_stats_t *zs) int b; dmu_prefetch(zap->zap_objset, zap->zap_object, - zap->zap_f.zap_phys->zap_ptrtbl.zt_blk << bs, - zap->zap_f.zap_phys->zap_ptrtbl.zt_numblks << bs); + zap_f_phys(zap)->zap_ptrtbl.zt_blk << bs, + zap_f_phys(zap)->zap_ptrtbl.zt_numblks << bs); - for (b = 0; b < zap->zap_f.zap_phys->zap_ptrtbl.zt_numblks; + for (b = 0; b < zap_f_phys(zap)->zap_ptrtbl.zt_numblks; b++) { dmu_buf_t *db; int err; err = dmu_buf_hold(zap->zap_objset, zap->zap_object, - (zap->zap_f.zap_phys->zap_ptrtbl.zt_blk + b) << bs, + (zap_f_phys(zap)->zap_ptrtbl.zt_blk + b) << bs, FTAG, &db, DMU_READ_NO_PREFETCH); if (err == 0) { zap_stats_ptrtbl(zap, db->db_data, @@ -1358,7 +1356,7 @@ fzap_count_write(zap_name_t *zn, int add, uint64_t *towrite, * could extend the table. */ if (add) { - if (zap->zap_f.zap_phys->zap_ptrtbl.zt_blk == 0) + if (zap_f_phys(zap)->zap_ptrtbl.zt_blk == 0) *towrite += zap->zap_dbuf->db_size; else *towrite += (zap->zap_dbuf->db_size * 3); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c index 78f05d7a7e37..96358f7bd80f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c @@ -48,10 +48,12 @@ static uint16_t *zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry); #define LEAF_HASH(l, h) \ ((ZAP_LEAF_HASH_NUMENTRIES(l)-1) & \ - ((h) >> (64 - ZAP_LEAF_HASH_SHIFT(l)-(l)->l_phys->l_hdr.lh_prefix_len))) + ((h) >> \ + (64 - ZAP_LEAF_HASH_SHIFT(l) - zap_leaf_phys(l)->l_hdr.lh_prefix_len))) -#define LEAF_HASH_ENTPTR(l, h) (&(l)->l_phys->l_hash[LEAF_HASH(l, h)]) +#define LEAF_HASH_ENTPTR(l, h) (&zap_leaf_phys(l)->l_hash[LEAF_HASH(l, h)]) +extern inline zap_leaf_phys_t *zap_leaf_phys(zap_leaf_t *l); static void zap_memset(void *a, int c, size_t n) @@ -105,8 +107,11 @@ zap_leaf_byteswap(zap_leaf_phys_t *buf, int size) { int i; zap_leaf_t l; + dmu_buf_t l_dbuf; + + l_dbuf.db_data = buf; l.l_bs = highbit64(size) - 1; - l.l_phys = buf; + l.l_dbuf = &l_dbuf; buf->l_hdr.lh_block_type = BSWAP_64(buf->l_hdr.lh_block_type); buf->l_hdr.lh_prefix = BSWAP_64(buf->l_hdr.lh_prefix); @@ -158,18 +163,20 @@ zap_leaf_init(zap_leaf_t *l, boolean_t sort) int i; l->l_bs = highbit64(l->l_dbuf->db_size) - 1; - zap_memset(&l->l_phys->l_hdr, 0, sizeof (struct zap_leaf_header)); - zap_memset(l->l_phys->l_hash, CHAIN_END, 2*ZAP_LEAF_HASH_NUMENTRIES(l)); + zap_memset(&zap_leaf_phys(l)->l_hdr, 0, + sizeof (struct zap_leaf_header)); + zap_memset(zap_leaf_phys(l)->l_hash, CHAIN_END, + 2*ZAP_LEAF_HASH_NUMENTRIES(l)); for (i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) { ZAP_LEAF_CHUNK(l, i).l_free.lf_type = ZAP_CHUNK_FREE; ZAP_LEAF_CHUNK(l, i).l_free.lf_next = i+1; } ZAP_LEAF_CHUNK(l, ZAP_LEAF_NUMCHUNKS(l)-1).l_free.lf_next = CHAIN_END; - l->l_phys->l_hdr.lh_block_type = ZBT_LEAF; - l->l_phys->l_hdr.lh_magic = ZAP_LEAF_MAGIC; - l->l_phys->l_hdr.lh_nfree = ZAP_LEAF_NUMCHUNKS(l); + zap_leaf_phys(l)->l_hdr.lh_block_type = ZBT_LEAF; + zap_leaf_phys(l)->l_hdr.lh_magic = ZAP_LEAF_MAGIC; + zap_leaf_phys(l)->l_hdr.lh_nfree = ZAP_LEAF_NUMCHUNKS(l); if (sort) - l->l_phys->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED; + zap_leaf_phys(l)->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED; } /* @@ -181,15 +188,16 @@ zap_leaf_chunk_alloc(zap_leaf_t *l) { int chunk; - ASSERT(l->l_phys->l_hdr.lh_nfree > 0); + ASSERT(zap_leaf_phys(l)->l_hdr.lh_nfree > 0); - chunk = l->l_phys->l_hdr.lh_freelist; + chunk = zap_leaf_phys(l)->l_hdr.lh_freelist; ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_free.lf_type, ==, ZAP_CHUNK_FREE); - l->l_phys->l_hdr.lh_freelist = ZAP_LEAF_CHUNK(l, chunk).l_free.lf_next; + zap_leaf_phys(l)->l_hdr.lh_freelist = + ZAP_LEAF_CHUNK(l, chunk).l_free.lf_next; - l->l_phys->l_hdr.lh_nfree--; + zap_leaf_phys(l)->l_hdr.lh_nfree--; return (chunk); } @@ -198,16 +206,16 @@ static void zap_leaf_chunk_free(zap_leaf_t *l, uint16_t chunk) { struct zap_leaf_free *zlf = &ZAP_LEAF_CHUNK(l, chunk).l_free; - ASSERT3U(l->l_phys->l_hdr.lh_nfree, <, ZAP_LEAF_NUMCHUNKS(l)); + ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_nfree, <, ZAP_LEAF_NUMCHUNKS(l)); ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); ASSERT(zlf->lf_type != ZAP_CHUNK_FREE); zlf->lf_type = ZAP_CHUNK_FREE; - zlf->lf_next = l->l_phys->l_hdr.lh_freelist; + zlf->lf_next = zap_leaf_phys(l)->l_hdr.lh_freelist; bzero(zlf->lf_pad, sizeof (zlf->lf_pad)); /* help it to compress */ - l->l_phys->l_hdr.lh_freelist = chunk; + zap_leaf_phys(l)->l_hdr.lh_freelist = chunk; - l->l_phys->l_hdr.lh_nfree++; + zap_leaf_phys(l)->l_hdr.lh_nfree++; } /* @@ -393,7 +401,7 @@ zap_leaf_lookup(zap_leaf_t *l, zap_name_t *zn, zap_entry_handle_t *zeh) uint16_t *chunkp; struct zap_leaf_entry *le; - ASSERT3U(l->l_phys->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC); + ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC); again: for (chunkp = LEAF_HASH_ENTPTR(l, zn->zn_hash); @@ -413,7 +421,7 @@ zap_leaf_lookup(zap_leaf_t *l, zap_name_t *zn, zap_entry_handle_t *zeh) * lowest-cd match for MT_FIRST. */ ASSERT(zn->zn_matchtype == MT_EXACT || - (l->l_phys->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED)); + (zap_leaf_phys(l)->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED)); if (zap_leaf_array_match(l, zn, le->le_name_chunk, le->le_name_numints)) { zeh->zeh_num_integers = le->le_value_numints; @@ -453,10 +461,10 @@ zap_leaf_lookup_closest(zap_leaf_t *l, uint16_t lh; struct zap_leaf_entry *le; - ASSERT3U(l->l_phys->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC); + ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC); for (lh = LEAF_HASH(l, h); lh <= bestlh; lh++) { - for (chunk = l->l_phys->l_hash[lh]; + for (chunk = zap_leaf_phys(l)->l_hash[lh]; chunk != CHAIN_END; chunk = le->le_next) { le = ZAP_LEAF_ENTRY(l, chunk); @@ -536,7 +544,7 @@ zap_entry_update(zap_entry_handle_t *zeh, delta_chunks = ZAP_LEAF_ARRAY_NCHUNKS(num_integers * integer_size) - ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_numints * le->le_value_intlen); - if ((int)l->l_phys->l_hdr.lh_nfree < delta_chunks) + if ((int)zap_leaf_phys(l)->l_hdr.lh_nfree < delta_chunks) return (SET_ERROR(EAGAIN)); zap_leaf_array_free(l, &le->le_value_chunk); @@ -566,7 +574,7 @@ zap_entry_remove(zap_entry_handle_t *zeh) *zeh->zeh_chunkp = le->le_next; zap_leaf_chunk_free(l, entry_chunk); - l->l_phys->l_hdr.lh_nentries--; + zap_leaf_phys(l)->l_hdr.lh_nentries--; } int @@ -590,7 +598,7 @@ zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd, if (cd == ZAP_NEED_CD) { /* find the lowest unused cd */ - if (l->l_phys->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED) { + if (zap_leaf_phys(l)->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED) { cd = 0; for (chunk = *LEAF_HASH_ENTPTR(l, h); @@ -626,7 +634,7 @@ zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd, ASSERT3U(cd, <, zap_maxcd(zn->zn_zap)); } - if (l->l_phys->l_hdr.lh_nfree < numchunks) + if (zap_leaf_phys(l)->l_hdr.lh_nfree < numchunks) return (SET_ERROR(EAGAIN)); /* make the entry */ @@ -647,7 +655,7 @@ zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd, /* XXX if we did the search above, we could just use that */ chunkp = zap_leaf_rehash_entry(l, chunk); - l->l_phys->l_hdr.lh_nentries++; + zap_leaf_phys(l)->l_hdr.lh_nentries++; zeh->zeh_leaf = l; zeh->zeh_num_integers = num_integers; @@ -781,8 +789,8 @@ zap_leaf_transfer_entry(zap_leaf_t *l, int entry, zap_leaf_t *nl) zap_leaf_chunk_free(l, entry); - l->l_phys->l_hdr.lh_nentries--; - nl->l_phys->l_hdr.lh_nentries++; + zap_leaf_phys(l)->l_hdr.lh_nentries--; + zap_leaf_phys(nl)->l_hdr.lh_nentries++; } /* @@ -792,19 +800,22 @@ void zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort) { int i; - int bit = 64 - 1 - l->l_phys->l_hdr.lh_prefix_len; + int bit = 64 - 1 - zap_leaf_phys(l)->l_hdr.lh_prefix_len; /* set new prefix and prefix_len */ - l->l_phys->l_hdr.lh_prefix <<= 1; - l->l_phys->l_hdr.lh_prefix_len++; - nl->l_phys->l_hdr.lh_prefix = l->l_phys->l_hdr.lh_prefix | 1; - nl->l_phys->l_hdr.lh_prefix_len = l->l_phys->l_hdr.lh_prefix_len; + zap_leaf_phys(l)->l_hdr.lh_prefix <<= 1; + zap_leaf_phys(l)->l_hdr.lh_prefix_len++; + zap_leaf_phys(nl)->l_hdr.lh_prefix = + zap_leaf_phys(l)->l_hdr.lh_prefix | 1; + zap_leaf_phys(nl)->l_hdr.lh_prefix_len = + zap_leaf_phys(l)->l_hdr.lh_prefix_len; /* break existing hash chains */ - zap_memset(l->l_phys->l_hash, CHAIN_END, 2*ZAP_LEAF_HASH_NUMENTRIES(l)); + zap_memset(zap_leaf_phys(l)->l_hash, CHAIN_END, + 2*ZAP_LEAF_HASH_NUMENTRIES(l)); if (sort) - l->l_phys->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED; + zap_leaf_phys(l)->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED; /* * Transfer entries whose hash bit 'bit' is set to nl; rehash @@ -832,25 +843,25 @@ zap_leaf_stats(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs) { int i, n; - n = zap->zap_f.zap_phys->zap_ptrtbl.zt_shift - - l->l_phys->l_hdr.lh_prefix_len; + n = zap_f_phys(zap)->zap_ptrtbl.zt_shift - + zap_leaf_phys(l)->l_hdr.lh_prefix_len; n = MIN(n, ZAP_HISTOGRAM_SIZE-1); zs->zs_leafs_with_2n_pointers[n]++; - n = l->l_phys->l_hdr.lh_nentries/5; + n = zap_leaf_phys(l)->l_hdr.lh_nentries/5; n = MIN(n, ZAP_HISTOGRAM_SIZE-1); zs->zs_blocks_with_n5_entries[n]++; n = ((1<l_phys->l_hdr.lh_nfree * (ZAP_LEAF_ARRAY_BYTES+1))*10 / + zap_leaf_phys(l)->l_hdr.lh_nfree * (ZAP_LEAF_ARRAY_BYTES+1))*10 / (1<zs_blocks_n_tenths_full[n]++; for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(l); i++) { int nentries = 0; - int chunk = l->l_phys->l_hash[i]; + int chunk = zap_leaf_phys(l)->l_hash[i]; while (chunk != CHAIN_END) { struct zap_leaf_entry *le = diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c index 4ed8aac29851..26377b6c3fca 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c @@ -39,6 +39,8 @@ #include #endif +extern inline mzap_phys_t *zap_m_phys(zap_t *zap); + static int mzap_upgrade(zap_t **zapp, dmu_tx_t *tx, zap_flags_t flags); uint64_t @@ -46,7 +48,7 @@ zap_getflags(zap_t *zap) { if (zap->zap_ismicro) return (0); - return (zap->zap_u.zap_fat.zap_phys->zap_flags); + return (zap_f_phys(zap)->zap_flags); } int @@ -391,7 +393,7 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) * it, because zap_lockdir() checks zap_ismicro without the lock * held. */ - winner = dmu_buf_set_user(db, zap, &zap->zap_m.zap_phys, zap_evict); + winner = dmu_buf_set_user(db, zap, zap_evict); if (winner != NULL) { rw_exit(&zap->zap_rwlock); @@ -403,15 +405,15 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) } if (zap->zap_ismicro) { - zap->zap_salt = zap->zap_m.zap_phys->mz_salt; - zap->zap_normflags = zap->zap_m.zap_phys->mz_normflags; + zap->zap_salt = zap_m_phys(zap)->mz_salt; + zap->zap_normflags = zap_m_phys(zap)->mz_normflags; zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1; avl_create(&zap->zap_m.zap_avl, mze_compare, sizeof (mzap_ent_t), offsetof(mzap_ent_t, mze_node)); for (i = 0; i < zap->zap_m.zap_num_chunks; i++) { mzap_ent_phys_t *mze = - &zap->zap_m.zap_phys->mz_chunk[i]; + &zap_m_phys(zap)->mz_chunk[i]; if (mze->mze_name[0]) { zap_name_t *zn; @@ -428,8 +430,8 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) } } } else { - zap->zap_salt = zap->zap_f.zap_phys->zap_salt; - zap->zap_normflags = zap->zap_f.zap_phys->zap_normflags; + zap->zap_salt = zap_f_phys(zap)->zap_salt; + zap->zap_normflags = zap_f_phys(zap)->zap_normflags; ASSERT3U(sizeof (struct zap_leaf_header), ==, 2*ZAP_LEAF_CHUNKSIZE); @@ -439,7 +441,7 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) * other members. */ ASSERT3P(&ZAP_EMBEDDED_PTRTBL_ENT(zap, 0), >, - &zap->zap_f.zap_phys->zap_salt); + &zap_f_phys(zap)->zap_salt); /* * The embedded pointer table should end at the end of @@ -447,7 +449,7 @@ mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) */ ASSERT3U((uintptr_t)&ZAP_EMBEDDED_PTRTBL_ENT(zap, 1<zap_f.zap_phys, ==, + (uintptr_t)zap_f_phys(zap), ==, zap->zap_dbuf->db_size); } rw_exit(&zap->zap_rwlock); @@ -950,7 +952,7 @@ mzap_addent(zap_name_t *zn, uint64_t value) #ifdef ZFS_DEBUG for (i = 0; i < zap->zap_m.zap_num_chunks; i++) { - mzap_ent_phys_t *mze = &zap->zap_m.zap_phys->mz_chunk[i]; + mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i]; ASSERT(strcmp(zn->zn_key_orig, mze->mze_name) != 0); } #endif @@ -961,7 +963,7 @@ mzap_addent(zap_name_t *zn, uint64_t value) again: for (i = start; i < zap->zap_m.zap_num_chunks; i++) { - mzap_ent_phys_t *mze = &zap->zap_m.zap_phys->mz_chunk[i]; + mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i]; if (mze->mze_name[0] == 0) { mze->mze_value = value; mze->mze_cd = cd; @@ -1162,7 +1164,7 @@ zap_remove_norm(objset_t *os, uint64_t zapobj, const char *name, err = SET_ERROR(ENOENT); } else { zap->zap_m.zap_num_entries--; - bzero(&zap->zap_m.zap_phys->mz_chunk[mze->mze_chunkid], + bzero(&zap_m_phys(zap)->mz_chunk[mze->mze_chunkid], sizeof (mzap_ent_phys_t)); mze_remove(zap, mze); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 5595348e9e10..d7300836e018 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -953,7 +953,7 @@ zfs_secpolicy_promote(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr) dd = clone->ds_dir; error = dsl_dataset_hold_obj(dd->dd_pool, - dd->dd_phys->dd_origin_obj, FTAG, &origin); + dsl_dir_phys(dd)->dd_origin_obj, FTAG, &origin); if (error != 0) { dsl_dataset_rele(clone, FTAG); dsl_pool_rele(dp, FTAG); @@ -4408,7 +4408,8 @@ zfs_ioc_send(zfs_cmd_t *zc) } if (dsl_dir_is_clone(tosnap->ds_dir)) - zc->zc_fromobj = tosnap->ds_dir->dd_phys->dd_origin_obj; + zc->zc_fromobj = + dsl_dir_phys(tosnap->ds_dir)->dd_origin_obj; dsl_dataset_rele(tosnap, FTAG); dsl_pool_rele(dp, FTAG); } @@ -4988,7 +4989,7 @@ zfs_ioc_next_obj(zfs_cmd_t *zc) return (error); error = dmu_object_next(os, &zc->zc_obj, B_FALSE, - os->os_dsl_dataset->ds_phys->ds_prev_snap_txg); + dsl_dataset_phys(os->os_dsl_dataset)->ds_prev_snap_txg); dmu_objset_rele(os, FTAG); return (error); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 7763d44acaa8..5d7fa70544ef 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -1548,7 +1548,7 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct componentname *cnp, /* * Insert name into cache (as non-existent) if appropriate. */ - if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) + if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) != 0) cache_enter(dvp, *vpp, cnp); /* * Insert name into cache if appropriate. diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c index 2084d88ff685..2dcfe06dbff8 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c @@ -190,7 +190,7 @@ zil_read_log_block(zilog_t *zilog, const blkptr_t *bp, blkptr_t *nbp, void *dst, char **end) { enum zio_flag zio_flags = ZIO_FLAG_CANFAIL; - uint32_t aflags = ARC_WAIT; + arc_flags_t aflags = ARC_FLAG_WAIT; arc_buf_t *abuf = NULL; zbookmark_phys_t zb; int error; @@ -266,7 +266,7 @@ zil_read_log_data(zilog_t *zilog, const lr_write_t *lr, void *wbuf) { enum zio_flag zio_flags = ZIO_FLAG_CANFAIL; const blkptr_t *bp = &lr->lr_blkptr; - uint32_t aflags = ARC_WAIT; + arc_flags_t aflags = ARC_FLAG_WAIT; arc_buf_t *abuf = NULL; zbookmark_phys_t zb; int error; diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c index 8408afbbfe49..3925e90c0e84 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c @@ -2250,7 +2250,7 @@ zio_ddt_collision(zio_t *zio, ddt_t *ddt, ddt_entry_t *dde) if (ddp->ddp_phys_birth != 0) { arc_buf_t *abuf = NULL; - uint32_t aflags = ARC_WAIT; + arc_flags_t aflags = ARC_FLAG_WAIT; blkptr_t blk = *zio->io_bp; int error; diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h index af10055d0936..ed3df7ac0ee5 100644 --- a/sys/compat/freebsd32/freebsd32.h +++ b/sys/compat/freebsd32/freebsd32.h @@ -390,4 +390,10 @@ struct kld32_file_stat { char pathname[MAXPATHLEN]; }; +struct procctl_reaper_pids32 { + u_int rp_count; + u_int rp_pad0[15]; + uint32_t rp_pids; +}; + #endif /* !_COMPAT_FREEBSD32_FREEBSD32_H_ */ diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 24c573813535..1457f57b78f7 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -2957,20 +2957,63 @@ int freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap) { void *data; - int error, flags; + union { + struct procctl_reaper_status rs; + struct procctl_reaper_pids rp; + struct procctl_reaper_kill rk; + } x; + union { + struct procctl_reaper_pids32 rp; + } x32; + int error, error1, flags; switch (uap->com) { case PROC_SPROTECT: error = copyin(PTRIN(uap->data), &flags, sizeof(flags)); - if (error) + if (error != 0) return (error); data = &flags; break; + case PROC_REAP_ACQUIRE: + case PROC_REAP_RELEASE: + if (uap->data != NULL) + return (EINVAL); + data = NULL; + break; + case PROC_REAP_STATUS: + data = &x.rs; + break; + case PROC_REAP_GETPIDS: + error = copyin(uap->data, &x32.rp, sizeof(x32.rp)); + if (error != 0) + return (error); + CP(x32.rp, x.rp, rp_count); + PTRIN_CP(x32.rp, x.rp, rp_pids); + data = &x.rp; + break; + case PROC_REAP_KILL: + error = copyin(uap->data, &x.rk, sizeof(x.rk)); + if (error != 0) + return (error); + data = &x.rk; + break; default: return (EINVAL); } - return (kern_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id), - uap->com, data)); + error = kern_procctl(td, uap->idtype, PAIR32TO64(id_t, uap->id), + uap->com, data); + switch (uap->com) { + case PROC_REAP_STATUS: + if (error == 0) + error = copyout(&x.rs, uap->data, sizeof(x.rs)); + break; + case PROC_REAP_KILL: + error1 = copyout(&x.rk, uap->data, sizeof(x.rk)); + if (error == 0) + error = error1; + break; + } + return (error); } int diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 92ecb2f308a0..8607646ded1f 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -674,7 +674,7 @@ linprocfs_doprocstat(PFS_FILL_ARGS) PS_ADD("pgrp", "%d", p->p_pgid); PS_ADD("session", "%d", p->p_session->s_sid); PROC_UNLOCK(p); - PS_ADD("tty", "%d", kp.ki_tdev); + PS_ADD("tty", "%ju", (uintmax_t)kp.ki_tdev); PS_ADD("tpgid", "%d", kp.ki_tpgid); PS_ADD("flags", "%u", 0); /* XXX */ PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt); diff --git a/sys/compat/svr4/svr4_socket.c b/sys/compat/svr4/svr4_socket.c index 038267ca221d..f59241ce15f1 100644 --- a/sys/compat/svr4/svr4_socket.c +++ b/sys/compat/svr4/svr4_socket.c @@ -93,7 +93,8 @@ svr4_find_socket(td, fp, dev, ino, saun) struct svr4_sockcache_entry *e; void *cookie = ((struct socket *)fp->f_data)->so_emuldata; - DPRINTF(("svr4_find_socket: [%p,%d,%d]: ", td, dev, ino)); + DPRINTF(("svr4_find_socket: [%p,%ju,%ju]: ", td, (uintmax_t)dev, + (uintmax_t)ino)); mtx_lock(&svr4_sockcache_lock); TAILQ_FOREACH(e, &svr4_head, entries) if (e->p == td->td_proc && e->dev == dev && e->ino == ino) { @@ -142,8 +143,8 @@ svr4_add_socket(td, path, st) mtx_lock(&svr4_sockcache_lock); TAILQ_INSERT_HEAD(&svr4_head, e, entries); mtx_unlock(&svr4_sockcache_lock); - DPRINTF(("svr4_add_socket: %s [%p,%d,%d]\n", e->sock.sun_path, - td->td_proc, e->dev, e->ino)); + DPRINTF(("svr4_add_socket: %s [%p,%ju,%ju]\n", e->sock.sun_path, + td->td_proc, (uintmax_t)e->dev, (uintmax_t)e->ino)); return 0; } @@ -160,8 +161,9 @@ svr4_delete_socket(p, fp) if (e->p == p && e->cookie == cookie) { TAILQ_REMOVE(&svr4_head, e, entries); mtx_unlock(&svr4_sockcache_lock); - DPRINTF(("svr4_delete_socket: %s [%p,%d,%d]\n", - e->sock.sun_path, p, (int)e->dev, e->ino)); + DPRINTF(("svr4_delete_socket: %s [%p,%ju,%ju]\n", + e->sock.sun_path, p, (uintmax_t)e->dev, + (uintmax_t)e->ino)); free(e, M_TEMP); return; } @@ -179,8 +181,9 @@ svr4_purge_sockcache(arg, p) TAILQ_FOREACH_SAFE(e, &svr4_head, entries, ne) { if (e->p == p) { TAILQ_REMOVE(&svr4_head, e, entries); - DPRINTF(("svr4_purge_sockcache: %s [%p,%d,%d]\n", - e->sock.sun_path, p, (int)e->dev, e->ino)); + DPRINTF(("svr4_purge_sockcache: %s [%p,%ju,%ju]\n", + e->sock.sun_path, p, (uintmax_t)e->dev, + (uintmax_t)e->ino)); free(e, M_TEMP); } } diff --git a/sys/conf/files b/sys/conf/files index 018d77bfa84d..939b63517d38 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2987,6 +2987,7 @@ kern/kern_pmc.c standard kern/kern_poll.c optional device_polling kern/kern_priv.c standard kern/kern_proc.c standard +kern/kern_procctl.c standard kern/kern_prot.c standard kern/kern_racct.c standard kern/kern_rangelock.c standard diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 62f645e0bc63..5bac8476524c 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -44,6 +44,7 @@ dev/nand/nfc_fsl.c optional nand mpc85xx dev/ofw/openfirm.c optional aim dev/ofw/openfirmio.c optional aim dev/ofw/ofw_bus_if.m optional aim +dev/ofw/ofw_cpu.c optional aim dev/ofw/ofw_if.m optional aim dev/ofw/ofw_bus_subr.c optional aim dev/ofw/ofw_console.c optional aim @@ -135,7 +136,6 @@ powerpc/mpc85xx/lbc.c optional mpc85xx powerpc/mpc85xx/mpc85xx.c optional mpc85xx powerpc/mpc85xx/platform_mpc85xx.c optional mpc85xx powerpc/mpc85xx/pci_mpc85xx.c optional pci mpc85xx -powerpc/ofw/ofw_cpu.c optional aim powerpc/ofw/ofw_machdep.c standard powerpc/ofw/ofw_pci.c optional pci powerpc/ofw/ofw_pcibus.c optional pci diff --git a/sys/dev/cxgbe/tom/t4_ddp.c b/sys/dev/cxgbe/tom/t4_ddp.c index 17eb071b3cb7..08c3224e2135 100644 --- a/sys/dev/cxgbe/tom/t4_ddp.c +++ b/sys/dev/cxgbe/tom/t4_ddp.c @@ -1173,7 +1173,7 @@ t4_soreceive_ddp(struct socket *so, struct sockaddr **psa, struct uio *uio, /* Socket buffer got some data that we shall deliver now. */ if (sbused(sb) && !(flags & MSG_WAITALL) && - ((sb->sb_flags & SS_NBIO) || + ((so->so_state & SS_NBIO) || (flags & (MSG_DONTWAIT|MSG_NBIO)) || sbused(sb) >= sb->sb_lowat || sbused(sb) >= uio->uio_resid || diff --git a/sys/dev/drm/drm_sysctl.c b/sys/dev/drm/drm_sysctl.c index 9e2c49a8e872..2a138e88a73b 100644 --- a/sys/dev/drm/drm_sysctl.c +++ b/sys/dev/drm/drm_sysctl.c @@ -137,8 +137,9 @@ static int drm_name_info DRM_SYSCTL_HANDLER_ARGS int retcode; int hasunique = 0; - DRM_SYSCTL_PRINT("%s 0x%x", dev->driver->name, dev2udev(dev->devnode)); - + DRM_SYSCTL_PRINT("%s 0x%jx", dev->driver->name, + (uintmax_t)dev2udev(dev->devnode)); + DRM_LOCK(); if (dev->unique) { snprintf(buf, sizeof(buf), " %s", dev->unique); diff --git a/sys/dev/drm2/drm_sysctl.c b/sys/dev/drm2/drm_sysctl.c index aac21e6a486e..9564e68df854 100644 --- a/sys/dev/drm2/drm_sysctl.c +++ b/sys/dev/drm2/drm_sysctl.c @@ -155,7 +155,8 @@ static int drm_name_info DRM_SYSCTL_HANDLER_ARGS int retcode; int hasunique = 0; - DRM_SYSCTL_PRINT("%s 0x%x", dev->driver->name, dev2udev(dev->devnode)); + DRM_SYSCTL_PRINT("%s 0x%jx", dev->driver->name, + (uintmax_t)dev2udev(dev->devnode)); DRM_LOCK(dev); if (dev->unique) { diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c index 117e7de7adcc..d99fdf26dcdf 100644 --- a/sys/dev/fdt/fdt_common.c +++ b/sys/dev/fdt/fdt_common.c @@ -102,10 +102,9 @@ fdt_get_range_by_busaddr(phandle_t node, u_long addr, u_long *base, tuple_size = addr_cells + par_addr_cells + size_cells; tuples = len / (tuple_size * sizeof(cell_t)); - if (fdt_ranges_verify(ranges, tuples, par_addr_cells, - addr_cells, size_cells)) { + if (par_addr_cells > 2 || addr_cells > 2 || size_cells > 2) return (ERANGE); - } + *base = 0; *size = 0; @@ -173,10 +172,9 @@ fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size) size_cells); tuples = len / tuple_size; - if (fdt_ranges_verify(ranges, tuples, par_addr_cells, - addr_cells, size_cells)) { + if (par_addr_cells > 2 || addr_cells > 2 || size_cells > 2) return (ERANGE); - } + *base = 0; *size = 0; rangesptr = &ranges[range_id]; @@ -380,20 +378,6 @@ fdt_parent_addr_cells(phandle_t node) return ((int)fdt32_to_cpu(addr_cells)); } -int -fdt_data_verify(void *data, int cells) -{ - uint64_t d64; - - if (cells > 1) { - d64 = fdt64_to_cpu(*((uint64_t *)data)); - if (((d64 >> 32) & 0xffffffffull) != 0 || cells > 2) - return (ERANGE); - } - - return (0); -} - int fdt_pm_is_enabled(phandle_t node) { @@ -440,62 +424,20 @@ fdt_addrsize_cells(phandle_t node, int *addr_cells, int *size_cells) return (0); } -int -fdt_ranges_verify(pcell_t *ranges, int tuples, int par_addr_cells, - int this_addr_cells, int this_size_cells) -{ - int i, rv, ulsz; - - if (par_addr_cells > 2 || this_addr_cells > 2 || this_size_cells > 2) - return (ERANGE); - - /* - * This is the max size the resource manager can handle for addresses - * and sizes. - */ - ulsz = sizeof(u_long); - if (par_addr_cells <= ulsz && this_addr_cells <= ulsz && - this_size_cells <= ulsz) - /* We can handle everything */ - return (0); - - rv = 0; - for (i = 0; i < tuples; i++) { - - if (fdt_data_verify((void *)ranges, par_addr_cells)) - goto err; - ranges += par_addr_cells; - - if (fdt_data_verify((void *)ranges, this_addr_cells)) - goto err; - ranges += this_addr_cells; - - if (fdt_data_verify((void *)ranges, this_size_cells)) - goto err; - ranges += this_size_cells; - } - - return (0); - -err: - debugf("using address range >%d-bit not supported\n", ulsz * 8); - return (ERANGE); -} - int fdt_data_to_res(pcell_t *data, int addr_cells, int size_cells, u_long *start, u_long *count) { /* Address portion. */ - if (fdt_data_verify((void *)data, addr_cells)) + if (addr_cells > 2) return (ERANGE); *start = fdt_data_get((void *)data, addr_cells); data += addr_cells; /* Size portion. */ - if (fdt_data_verify((void *)data, size_cells)) + if (size_cells > 2) return (ERANGE); *count = fdt_data_get((void *)data, size_cells); diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h index 0a79ce03baf8..3d05341dad1d 100644 --- a/sys/dev/fdt/fdt_common.h +++ b/sys/dev/fdt/fdt_common.h @@ -79,7 +79,6 @@ extern u_char fdt_static_dtb; int fdt_addrsize_cells(phandle_t, int *, int *); u_long fdt_data_get(void *, int); int fdt_data_to_res(pcell_t *, int, int, u_long *, u_long *); -int fdt_data_verify(void *, int); phandle_t fdt_find_compatible(phandle_t, const char *, int); phandle_t fdt_depth_search_compatible(phandle_t, const char *, int); int fdt_get_mem_regions(struct mem_region *, int *, uint32_t *); @@ -94,7 +93,6 @@ int fdt_is_enabled(phandle_t); int fdt_pm_is_enabled(phandle_t); int fdt_is_type(phandle_t, const char *); int fdt_parent_addr_cells(phandle_t); -int fdt_ranges_verify(pcell_t *, int, int, int, int); int fdt_reg_to_rl(phandle_t, struct resource_list *); int fdt_pm(phandle_t); int fdt_get_unit(device_t); diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c index af7184684d35..f9edc8246c31 100644 --- a/sys/dev/iscsi/iscsi.c +++ b/sys/dev/iscsi/iscsi.c @@ -192,7 +192,7 @@ iscsi_pdu_prepare(struct icl_pdu *request) * Data-Out PDU does not contain CmdSN. */ if (bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_OUT) { - if (is->is_cmdsn > is->is_maxcmdsn && + if (ISCSI_SNGT(is->is_cmdsn, is->is_maxcmdsn) && (bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) { /* * Current MaxCmdSN prevents us from sending any more @@ -201,8 +201,10 @@ iscsi_pdu_prepare(struct icl_pdu *request) * or by maintenance thread. */ #if 0 - ISCSI_SESSION_DEBUG(is, "postponing send, CmdSN %d, ExpCmdSN %d, MaxCmdSN %d, opcode 0x%x", - is->is_cmdsn, is->is_expcmdsn, is->is_maxcmdsn, bhssc->bhssc_opcode); + ISCSI_SESSION_DEBUG(is, "postponing send, CmdSN %u, " + "ExpCmdSN %u, MaxCmdSN %u, opcode 0x%x", + is->is_cmdsn, is->is_expcmdsn, is->is_maxcmdsn, + bhssc->bhssc_opcode); #endif return (true); } @@ -611,7 +613,7 @@ iscsi_pdu_update_statsn(const struct icl_pdu *response) { const struct iscsi_bhs_data_in *bhsdi; struct iscsi_session *is; - uint32_t expcmdsn, maxcmdsn; + uint32_t expcmdsn, maxcmdsn, statsn; is = PDU_SESSION(response); @@ -630,26 +632,27 @@ iscsi_pdu_update_statsn(const struct icl_pdu *response) */ if (bhsdi->bhsdi_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN || (bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0) { - if (ntohl(bhsdi->bhsdi_statsn) < is->is_statsn) { - ISCSI_SESSION_WARN(is, - "PDU StatSN %d >= session StatSN %d, opcode 0x%x", - is->is_statsn, ntohl(bhsdi->bhsdi_statsn), - bhsdi->bhsdi_opcode); + statsn = ntohl(bhsdi->bhsdi_statsn); + if (statsn != is->is_statsn && statsn != (is->is_statsn + 1)) { + /* XXX: This is normal situation for MCS */ + ISCSI_SESSION_WARN(is, "PDU 0x%x StatSN %u != " + "session ExpStatSN %u (or + 1); reconnecting", + bhsdi->bhsdi_opcode, statsn, is->is_statsn); + iscsi_session_reconnect(is); } - is->is_statsn = ntohl(bhsdi->bhsdi_statsn); + if (ISCSI_SNGT(statsn, is->is_statsn)) + is->is_statsn = statsn; } expcmdsn = ntohl(bhsdi->bhsdi_expcmdsn); maxcmdsn = ntohl(bhsdi->bhsdi_maxcmdsn); - /* - * XXX: Compare using Serial Arithmetic Sense. - */ - if (maxcmdsn + 1 < expcmdsn) { - ISCSI_SESSION_DEBUG(is, "PDU MaxCmdSN %d + 1 < PDU ExpCmdSN %d; ignoring", + if (ISCSI_SNLT(maxcmdsn + 1, expcmdsn)) { + ISCSI_SESSION_DEBUG(is, + "PDU MaxCmdSN %u + 1 < PDU ExpCmdSN %u; ignoring", maxcmdsn, expcmdsn); } else { - if (maxcmdsn > is->is_maxcmdsn) { + if (ISCSI_SNGT(maxcmdsn, is->is_maxcmdsn)) { is->is_maxcmdsn = maxcmdsn; /* @@ -658,15 +661,19 @@ iscsi_pdu_update_statsn(const struct icl_pdu *response) */ if (!STAILQ_EMPTY(&is->is_postponed)) cv_signal(&is->is_maintenance_cv); - } else if (maxcmdsn < is->is_maxcmdsn) { - ISCSI_SESSION_DEBUG(is, "PDU MaxCmdSN %d < session MaxCmdSN %d; ignoring", + } else if (ISCSI_SNLT(maxcmdsn, is->is_maxcmdsn)) { + /* XXX: This is normal situation for MCS */ + ISCSI_SESSION_DEBUG(is, + "PDU MaxCmdSN %u < session MaxCmdSN %u; ignoring", maxcmdsn, is->is_maxcmdsn); } - if (expcmdsn > is->is_expcmdsn) { + if (ISCSI_SNGT(expcmdsn, is->is_expcmdsn)) { is->is_expcmdsn = expcmdsn; - } else if (expcmdsn < is->is_expcmdsn) { - ISCSI_SESSION_DEBUG(is, "PDU ExpCmdSN %d < session ExpCmdSN %d; ignoring", + } else if (ISCSI_SNLT(expcmdsn, is->is_expcmdsn)) { + /* XXX: This is normal situation for MCS */ + ISCSI_SESSION_DEBUG(is, + "PDU ExpCmdSN %u < session ExpCmdSN %u; ignoring", expcmdsn, is->is_expcmdsn); } } diff --git a/sys/dev/iscsi/iscsi_proto.h b/sys/dev/iscsi/iscsi_proto.h index 97d73a7a074e..46572ce62d46 100644 --- a/sys/dev/iscsi/iscsi_proto.h +++ b/sys/dev/iscsi/iscsi_proto.h @@ -38,6 +38,9 @@ #define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1] #endif +#define ISCSI_SNGT(x, y) ((int32_t)(x) - (int32_t)(y) > 0) +#define ISCSI_SNLT(x, y) ((int32_t)(x) - (int32_t)(y) < 0) + #define ISCSI_BHS_SIZE 48 #define ISCSI_HEADER_DIGEST_SIZE 4 #define ISCSI_DATA_DIGEST_SIZE 4 diff --git a/sys/dev/malo/if_malo_pci.c b/sys/dev/malo/if_malo_pci.c index c9e6b2070380..26324c09f091 100644 --- a/sys/dev/malo/if_malo_pci.c +++ b/sys/dev/malo/if_malo_pci.c @@ -225,9 +225,9 @@ malo_pci_attach(device_t dev) BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXADDR, /* maxsize */ + BUS_SPACE_MAXSIZE, /* maxsize */ 0, /* nsegments */ - BUS_SPACE_MAXADDR, /* maxsegsize */ + BUS_SPACE_MAXSIZE, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c index a7762badec4d..a3b9744b99b1 100644 --- a/sys/dev/mmc/mmc.c +++ b/sys/dev/mmc/mmc.c @@ -1357,7 +1357,6 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->erase_sector = 16 << ivar->sd_status.au_size; } - mmc_select_card(sc, 0); /* Find max supported bus width. */ if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) && (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) @@ -1385,6 +1384,7 @@ mmc_discover_cards(struct mmc_softc *sc) child = device_add_child(sc->dev, NULL, -1); device_set_ivars(child, ivar); } + mmc_select_card(sc, 0); return; } mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid); @@ -1443,7 +1443,6 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->hs_tran_speed = ivar->tran_speed; /* Find max supported bus width. */ ivar->bus_width = mmc_test_bus_width(sc); - mmc_select_card(sc, 0); /* Handle HC erase sector size. */ if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) { ivar->erase_sector = 1024 * @@ -1451,6 +1450,7 @@ mmc_discover_cards(struct mmc_softc *sc) mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_ERASE_GRP_DEF, 1); } + mmc_select_card(sc, 0); } else { ivar->bus_width = bus_width_1; ivar->timing = bus_timing_normal; diff --git a/sys/dev/mwl/if_mwl_pci.c b/sys/dev/mwl/if_mwl_pci.c index 8527cd67e380..ef7009c785d1 100644 --- a/sys/dev/mwl/if_mwl_pci.c +++ b/sys/dev/mwl/if_mwl_pci.c @@ -178,9 +178,9 @@ mwl_pci_attach(device_t dev) BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXADDR, /* maxsize */ + BUS_SPACE_MAXSIZE, /* maxsize */ MWL_TXDESC, /* nsegments */ - BUS_SPACE_MAXADDR, /* maxsegsize */ + BUS_SPACE_MAXSIZE, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ diff --git a/sys/powerpc/ofw/ofw_cpu.c b/sys/dev/ofw/ofw_cpu.c similarity index 87% rename from sys/powerpc/ofw/ofw_cpu.c rename to sys/dev/ofw/ofw_cpu.c index e830e3e9b3ab..226514059d56 100644 --- a/sys/powerpc/ofw/ofw_cpu.c +++ b/sys/dev/ofw/ofw_cpu.c @@ -11,16 +11,17 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include diff --git a/sys/dev/sis/if_sis.c b/sys/dev/sis/if_sis.c index f7e6f3ba4442..520642f13ba2 100644 --- a/sys/dev/sis/if_sis.c +++ b/sys/dev/sis/if_sis.c @@ -780,7 +780,7 @@ sis_rxfilter_sis(struct sis_softc *sc) filter = CSR_READ_4(sc, SIS_RXFILT_CTL); if (filter & SIS_RXFILTCTL_ENABLE) { - CSR_WRITE_4(sc, SIS_RXFILT_CTL, filter & ~SIS_RXFILT_CTL); + CSR_WRITE_4(sc, SIS_RXFILT_CTL, filter & ~SIS_RXFILTCTL_ENABLE); CSR_READ_4(sc, SIS_RXFILT_CTL); } filter &= ~(SIS_RXFILTCTL_ALLPHYS | SIS_RXFILTCTL_BROAD | diff --git a/sys/dev/usb/net/if_urndis.c b/sys/dev/usb/net/if_urndis.c index 5d45395d46c6..aa88a56148b7 100644 --- a/sys/dev/usb/net/if_urndis.c +++ b/sys/dev/usb/net/if_urndis.c @@ -170,15 +170,15 @@ static const struct usb_ether_methods urndis_ue_methods = { }; static const STRUCT_USB_HOST_ID urndis_host_devs[] = { -#if 0 - /* XXX this entry has a conflict an entry the umodem driver XXX */ - {USB_IFACE_CLASS(UICLASS_CDC), USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL), - USB_IFACE_PROTOCOL(0xff)}, -#endif + /* Generic RNDIS class match */ {USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF), - USB_IFACE_PROTOCOL(UIPROTO_RNDIS)}, + USB_IFACE_PROTOCOL(UIPROTO_RNDIS)}, {USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC), - USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)}, + USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)}, + /* HP-WebOS */ + {USB_VENDOR(USB_VENDOR_PALM), USB_IFACE_CLASS(UICLASS_CDC), + USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL), + USB_IFACE_PROTOCOL(0xff)}, }; static int diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c index 982104d21755..68b5ff4f4a61 100644 --- a/sys/dev/usb/serial/umodem.c +++ b/sys/dev/usb/serial/umodem.c @@ -125,7 +125,7 @@ static const STRUCT_USB_HOST_ID umodem_devs[] = { USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL), USB_IFACE_PROTOCOL(UIPROTO_CDC_NONE)}, /* Huawei Modem class match */ - {USB_IFACE_CLASS(UICLASS_CDC), + {USB_VENDOR(USB_VENDOR_HUAWEI),USB_IFACE_CLASS(UICLASS_CDC), USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL), USB_IFACE_PROTOCOL(0xFF)}, /* Kyocera AH-K3001V */ diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c index 106a124a1dd5..e2bb138793b5 100644 --- a/sys/fs/ext2fs/ext2_alloc.c +++ b/sys/fs/ext2fs/ext2_alloc.c @@ -264,8 +264,8 @@ ext2_reallocblks(struct vop_reallocblks_args *ap) * with the file. */ #ifdef DEBUG - printf("realloc: ino %d, lbns %jd-%jd\n\told:", ip->i_number, - (intmax_t)start_lbn, (intmax_t)end_lbn); + printf("realloc: ino %ju, lbns %jd-%jd\n\told:", + (uintmax_t)ip->i_number, (intmax_t)start_lbn, (intmax_t)end_lbn); #endif /* DEBUG */ blkno = newblk; for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->e2fs_fpb) { @@ -968,8 +968,8 @@ ext2_blkfree(struct inode *ip, e4fs_daddr_t bno, long size) ump = ip->i_ump; cg = dtog(fs, bno); if ((u_int)bno >= fs->e2fs->e2fs_bcount) { - printf("bad block %lld, ino %llu\n", (long long)bno, - (unsigned long long)ip->i_number); + printf("bad block %lld, ino %ju\n", (long long)bno, + (uintmax_t)ip->i_number); ext2_fserr(fs, ip->i_uid, "bad block"); return; } diff --git a/sys/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c index ad1f41a57777..e59b60614c4a 100644 --- a/sys/fs/ext2fs/ext2_lookup.c +++ b/sys/fs/ext2fs/ext2_lookup.c @@ -514,7 +514,7 @@ ext2_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp /* * Insert name into cache (as non-existent) if appropriate. */ - if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) + if ((cnp->cn_flags & MAKEENTRY) != 0) cache_enter(vdp, NULL, cnp); return (ENOENT); @@ -801,11 +801,13 @@ ext2_dirbad(struct inode *ip, doff_t offset, char *how) mp = ITOV(ip)->v_mount; if ((mp->mnt_flag & MNT_RDONLY) == 0) - panic("ext2_dirbad: %s: bad dir ino %lu at offset %ld: %s\n", - mp->mnt_stat.f_mntonname, (u_long)ip->i_number,(long)offset, how); + panic("ext2_dirbad: %s: bad dir ino %ju at offset %ld: %s\n", + mp->mnt_stat.f_mntonname, (uintmax_t)ip->i_number, + (long)offset, how); else - (void)printf("%s: bad dir ino %lu at offset %ld: %s\n", - mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how); + (void)printf("%s: bad dir ino %ju at offset %ld: %s\n", + mp->mnt_stat.f_mntonname, (uintmax_t)ip->i_number, + (long)offset, how); } diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index 06173b1060e5..899ae7970d68 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -1366,7 +1366,7 @@ ext2_print(struct vop_print_args *ap) struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); - vn_printf(ip->i_devvp, "\tino %lu", (u_long)ip->i_number); + vn_printf(ip->i_devvp, "\tino %ju", (uintmax_t)ip->i_number); if (vp->v_type == VFIFO) fifo_printinfo(vp); printf("\n"); diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index 54f659fe70c8..085edbaf1417 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -795,7 +795,7 @@ fuse_vnop_lookup(struct vop_lookup_args *ap) * caching...) */ #if 0 - if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) { + if ((cnp->cn_flags & MAKEENTRY) != 0) { FS_DEBUG("inserting NULL into cache\n"); cache_enter(dvp, NULL, cnp); } diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c index 3704915b7144..b5b8e316933c 100644 --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -416,7 +416,7 @@ msdosfs_lookup_(struct vnode *vdp, struct vnode **vpp, * and 8.3 filenames. Hence, it may not invalidate all negative * entries if a file with this name is later created. */ - if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) + if ((cnp->cn_flags & MAKEENTRY) != 0) cache_enter(vdp, *vpp, cnp); #endif return (ENOENT); diff --git a/sys/fs/nandfs/nandfs_vnops.c b/sys/fs/nandfs/nandfs_vnops.c index 2c92f8b02dc7..65dcf6416e0f 100644 --- a/sys/fs/nandfs/nandfs_vnops.c +++ b/sys/fs/nandfs/nandfs_vnops.c @@ -478,7 +478,7 @@ nandfs_lookup(struct vop_cachedlookup_args *ap) * the file might not be found and thus putting it into the namecache * might be seen as negative caching. */ - if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) + if ((cnp->cn_flags & MAKEENTRY) != 0) cache_enter(dvp, *vpp, cnp); return (error); diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 9570b70092ac..818551fa3b69 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1184,8 +1184,7 @@ nfs_lookup(struct vop_lookup_args *ap) return (EJUSTRETURN); } - if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE && - dattrflag) { + if ((cnp->cn_flags & MAKEENTRY) != 0 && dattrflag) { /* * Cache the modification time of the parent * directory from the post-op attributes in diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index 9bf43c37b10a..e6e02d7ea9da 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -994,7 +994,7 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram, goto out; } NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, - LOCKPARENT | LOCKLEAF | SAVESTART); + LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE); nfsvno_setpathbuf(&named, &bufp, &hashp); error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); if (error) @@ -1205,7 +1205,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram, goto out; } } - NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags); + NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags | NOCACHE); nfsvno_setpathbuf(&named, &bufp, &hashp); error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); if (error) @@ -1658,7 +1658,7 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram, } } NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, - LOCKPARENT | SAVENAME); + LOCKPARENT | SAVENAME | NOCACHE); if (!nd->nd_repstat) { nfsvno_setpathbuf(&named, &bufp, &hashp); error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); @@ -1735,7 +1735,7 @@ nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram, *vpp = NULL; NFSVNO_ATTRINIT(&nva); NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, - LOCKPARENT | SAVESTART); + LOCKPARENT | SAVESTART | NOCACHE); nfsvno_setpathbuf(&named, &bufp, &hashp); error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); if (!error && !nd->nd_repstat) @@ -1853,7 +1853,7 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram, goto out; } NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, - LOCKPARENT | SAVENAME); + LOCKPARENT | SAVENAME | NOCACHE); nfsvno_setpathbuf(&named, &bufp, &hashp); error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen); if (error) @@ -2782,7 +2782,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram, } if (create == NFSV4OPEN_CREATE) NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, - LOCKPARENT | LOCKLEAF | SAVESTART); + LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE); else NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP, LOCKLEAF | SAVESTART); diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 5ffab5013e5a..29ee38915ab5 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -195,7 +195,7 @@ tmpfs_lookup(struct vop_cachedlookup_args *v) /* Store the result of this lookup in the cache. Avoid this if the * request was for creation, as it does not improve timings on * emprical tests. */ - if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE) + if ((cnp->cn_flags & MAKEENTRY) != 0) cache_enter(dvp, *vpp, cnp); out: diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index e3391a7f7696..74192dcfbb32 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -536,6 +536,8 @@ unionfs_relookup(struct vnode *dvp, struct vnode **vpp, cn->cn_flags |= (cnp->cn_flags & (DOWHITEOUT | SAVESTART)); else if (RENAME == nameiop) cn->cn_flags |= (cnp->cn_flags & SAVESTART); + else if (nameiop == CREATE) + cn->cn_flags |= NOCACHE; vref(dvp); VOP_UNLOCK(dvp, LK_RELEASE); diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 5076f161e24c..6b60dbd47fb5 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -160,8 +160,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap) LK_RETRY); vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); - } else if (error == ENOENT && (cnflags & MAKEENTRY) && - nameiop != CREATE) + } else if (error == ENOENT && (cnflags & MAKEENTRY) != 0) cache_enter(dvp, NULLVP, cnp); UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error); @@ -337,7 +336,7 @@ unionfs_lookup(struct vop_cachedlookup_args *ap) if (lvp != NULLVP) vrele(lvp); - if (error == ENOENT && (cnflags & MAKEENTRY) && nameiop != CREATE) + if (error == ENOENT && (cnflags & MAKEENTRY) != 0) cache_enter(dvp, NULLVP, cnp); UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error); diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index e903f4cc89f5..beb49bc56962 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -496,7 +496,8 @@ proc0_init(void *dummy __unused) prison0.pr_cpuset = cpuset_ref(td->td_cpuset); p->p_peers = 0; p->p_leader = p; - + p->p_reaper = p; + LIST_INIT(&p->p_reaplist); strncpy(p->p_comm, "kernel", sizeof (p->p_comm)); strncpy(td->td_name, "swapper", sizeof (td->td_name)); @@ -821,8 +822,11 @@ create_init(const void *udata __unused) KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1")); /* divorce init's credentials from the kernel's */ newcred = crget(); + sx_xlock(&proctree_lock); PROC_LOCK(initproc); initproc->p_flag |= P_SYSTEM | P_INMEM; + initproc->p_treeflag |= P_TREE_REAPER; + LIST_INSERT_HEAD(&initproc->p_reaplist, &proc0, p_reapsibling); oldcred = initproc->p_ucred; crcopy(newcred, oldcred); #ifdef MAC @@ -833,6 +837,7 @@ create_init(const void *udata __unused) #endif initproc->p_ucred = newcred; PROC_UNLOCK(initproc); + sx_xunlock(&proctree_lock); crfree(oldcred); cred_update_thread(FIRST_THREAD_IN_PROC(initproc)); cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL); diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index b1ae7a16ceab..d15e5dabe6b9 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -1292,7 +1292,8 @@ clone_cleanup(struct clonedevs **cdp) if (!(cp->cdp_flags & CDP_SCHED_DTR)) { cp->cdp_flags |= CDP_SCHED_DTR; KASSERT(dev->si_flags & SI_NAMED, - ("Driver has goofed in cloning underways udev %x unit %x", dev2udev(dev), dev2unit(dev))); + ("Driver has goofed in cloning underways udev %jx unit %x", + (uintmax_t)dev2udev(dev), dev2unit(dev))); destroy_devl(dev); } } diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index a4313091e44d..ce1f8f9e6e32 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -123,6 +123,31 @@ proc_realparent(struct proc *child) return (parent); } +void +reaper_abandon_children(struct proc *p, bool exiting) +{ + struct proc *p1, *p2, *ptmp; + + sx_assert(&proctree_lock, SX_LOCKED); + KASSERT(p != initproc, ("reaper_abandon_children for initproc")); + if ((p->p_treeflag & P_TREE_REAPER) == 0) + return; + p1 = p->p_reaper; + LIST_FOREACH_SAFE(p2, &p->p_reaplist, p_reapsibling, ptmp) { + LIST_REMOVE(p2, p_reapsibling); + p2->p_reaper = p1; + p2->p_reapsubtree = p->p_reapsubtree; + LIST_INSERT_HEAD(&p1->p_reaplist, p2, p_reapsibling); + if (exiting && p2->p_pptr == p) { + PROC_LOCK(p2); + proc_reparent(p2, p1); + PROC_UNLOCK(p2); + } + } + KASSERT(LIST_EMPTY(&p->p_reaplist), ("p_reaplist not empty")); + p->p_treeflag &= ~P_TREE_REAPER; +} + static void clear_orphan(struct proc *p) { @@ -458,14 +483,14 @@ exit1(struct thread *td, int rv) sx_xlock(&proctree_lock); q = LIST_FIRST(&p->p_children); if (q != NULL) /* only need this if any child is S_ZOMB */ - wakeup(initproc); + wakeup(q->p_reaper); for (; q != NULL; q = nq) { nq = LIST_NEXT(q, p_sibling); PROC_LOCK(q); q->p_sigparent = SIGCHLD; if (!(q->p_flag & P_TRACED)) { - proc_reparent(q, initproc); + proc_reparent(q, q->p_reaper); } else { /* * Traced processes are killed since their existence @@ -473,7 +498,7 @@ exit1(struct thread *td, int rv) */ t = proc_realparent(q); if (t == p) { - proc_reparent(q, initproc); + proc_reparent(q, q->p_reaper); } else { PROC_LOCK(t); proc_reparent(q, t); @@ -562,7 +587,7 @@ exit1(struct thread *td, int rv) mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx); pp = p->p_pptr; PROC_UNLOCK(pp); - proc_reparent(p, initproc); + proc_reparent(p, p->p_reaper); p->p_sigparent = SIGCHLD; PROC_LOCK(p->p_pptr); @@ -575,8 +600,8 @@ exit1(struct thread *td, int rv) } else mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx); - if (p->p_pptr == initproc) - kern_psignal(p->p_pptr, SIGCHLD); + if (p->p_pptr == p->p_reaper || p->p_pptr == initproc) + childproc_exited(p); else if (p->p_sigparent != 0) { if (p->p_sigparent == SIGCHLD) childproc_exited(p); @@ -849,6 +874,8 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options) LIST_REMOVE(p, p_list); /* off zombproc */ sx_xunlock(&allproc_lock); LIST_REMOVE(p, p_sibling); + reaper_abandon_children(p, true); + LIST_REMOVE(p, p_reapsibling); PROC_LOCK(p); clear_orphan(p); PROC_UNLOCK(p); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index c5298388c888..f469db634bca 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -261,11 +261,21 @@ fork_findpid(int flags) * Scan the active and zombie procs to check whether this pid * is in use. Remember the lowest pid that's greater * than trypid, so we can avoid checking for a while. + * + * Avoid reuse of the process group id, session id or + * the reaper subtree id. Note that for process group + * and sessions, the amount of reserved pids is + * limited by process limit. For the subtree ids, the + * id is kept reserved only while there is a + * non-reaped process in the subtree, so amount of + * reserved pids is limited by process limit times + * two. */ p = LIST_FIRST(&allproc); again: for (; p != NULL; p = LIST_NEXT(p, p_list)) { while (p->p_pid == trypid || + p->p_reapsubtree == trypid || (p->p_pgrp != NULL && (p->p_pgrp->pg_id == trypid || (p->p_session != NULL && @@ -611,12 +621,20 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * of init. This effectively disassociates the child from the * parent. */ - if (flags & RFNOWAIT) - pptr = initproc; - else + if ((flags & RFNOWAIT) != 0) { + pptr = p1->p_reaper; + p2->p_reaper = pptr; + } else { + p2->p_reaper = (p1->p_treeflag & P_TREE_REAPER) != 0 ? + p1 : p1->p_reaper; pptr = p1; + } p2->p_pptr = pptr; LIST_INSERT_HEAD(&pptr->p_children, p2, p_sibling); + LIST_INIT(&p2->p_reaplist); + LIST_INSERT_HEAD(&p2->p_reaper->p_reaplist, p2, p_reapsibling); + if (p2->p_reaper == p1) + p2->p_reapsubtree = p2->p_pid; sx_xunlock(&proctree_lock); /* Inform accounting that we have forked. */ diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c new file mode 100644 index 000000000000..9b0d14aea354 --- /dev/null +++ b/sys/kern/kern_procctl.c @@ -0,0 +1,461 @@ +/*- + * Copyright (c) 2014 John Baldwin + * Copyright (c) 2014 The FreeBSD Foundation + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +protect_setchild(struct thread *td, struct proc *p, int flags) +{ + + PROC_LOCK_ASSERT(p, MA_OWNED); + if (p->p_flag & P_SYSTEM || p_cansched(td, p) != 0) + return (0); + if (flags & PPROT_SET) { + p->p_flag |= P_PROTECTED; + if (flags & PPROT_INHERIT) + p->p_flag2 |= P2_INHERIT_PROTECTED; + } else { + p->p_flag &= ~P_PROTECTED; + p->p_flag2 &= ~P2_INHERIT_PROTECTED; + } + return (1); +} + +static int +protect_setchildren(struct thread *td, struct proc *top, int flags) +{ + struct proc *p; + int ret; + + p = top; + ret = 0; + sx_assert(&proctree_lock, SX_LOCKED); + for (;;) { + ret |= protect_setchild(td, p, flags); + PROC_UNLOCK(p); + /* + * If this process has children, descend to them next, + * otherwise do any siblings, and if done with this level, + * follow back up the tree (but not past top). + */ + if (!LIST_EMPTY(&p->p_children)) + p = LIST_FIRST(&p->p_children); + else for (;;) { + if (p == top) { + PROC_LOCK(p); + return (ret); + } + if (LIST_NEXT(p, p_sibling)) { + p = LIST_NEXT(p, p_sibling); + break; + } + p = p->p_pptr; + } + PROC_LOCK(p); + } +} + +static int +protect_set(struct thread *td, struct proc *p, int flags) +{ + int error, ret; + + switch (PPROT_OP(flags)) { + case PPROT_SET: + case PPROT_CLEAR: + break; + default: + return (EINVAL); + } + + if ((PPROT_FLAGS(flags) & ~(PPROT_DESCEND | PPROT_INHERIT)) != 0) + return (EINVAL); + + error = priv_check(td, PRIV_VM_MADV_PROTECT); + if (error) + return (error); + + if (flags & PPROT_DESCEND) + ret = protect_setchildren(td, p, flags); + else + ret = protect_setchild(td, p, flags); + if (ret == 0) + return (EPERM); + return (0); +} + +static int +reap_acquire(struct thread *td, struct proc *p) +{ + + sx_assert(&proctree_lock, SX_XLOCKED); + if (p != curproc) + return (EPERM); + if ((p->p_treeflag & P_TREE_REAPER) != 0) + return (EBUSY); + p->p_treeflag |= P_TREE_REAPER; + /* + * We do not reattach existing children and the whole tree + * under them to us, since p->p_reaper already seen them. + */ + return (0); +} + +static int +reap_release(struct thread *td, struct proc *p) +{ + + sx_assert(&proctree_lock, SX_XLOCKED); + if (p != curproc) + return (EPERM); + if (p == initproc) + return (EINVAL); + if ((p->p_treeflag & P_TREE_REAPER) == 0) + return (EINVAL); + reaper_abandon_children(p, false); + return (0); +} + +static int +reap_status(struct thread *td, struct proc *p, + struct procctl_reaper_status *rs) +{ + struct proc *reap, *p2; + + sx_assert(&proctree_lock, SX_LOCKED); + bzero(rs, sizeof(*rs)); + if ((p->p_treeflag & P_TREE_REAPER) == 0) { + reap = p->p_reaper; + } else { + reap = p; + rs->rs_flags |= REAPER_STATUS_OWNED; + } + if (reap == initproc) + rs->rs_flags |= REAPER_STATUS_REALINIT; + rs->rs_reaper = reap->p_pid; + rs->rs_descendants = 0; + rs->rs_children = 0; + if (!LIST_EMPTY(&reap->p_reaplist)) { + KASSERT(!LIST_EMPTY(&reap->p_children), ("no children")); + rs->rs_pid = LIST_FIRST(&reap->p_children)->p_pid; + LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) { + if (proc_realparent(p2) == reap) + rs->rs_children++; + rs->rs_descendants++; + } + } else { + rs->rs_pid = -1; + KASSERT(LIST_EMPTY(&reap->p_reaplist), ("reap children list")); + KASSERT(LIST_EMPTY(&reap->p_children), ("children list")); + } + return (0); +} + +static int +reap_getpids(struct thread *td, struct proc *p, struct procctl_reaper_pids *rp) +{ + struct proc *reap, *p2; + struct procctl_reaper_pidinfo *pi, *pip; + u_int i, n; + int error; + + sx_assert(&proctree_lock, SX_LOCKED); + PROC_UNLOCK(p); + reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p; + n = i = 0; + error = 0; + LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) + n++; + sx_unlock(&proctree_lock); + if (rp->rp_count < n) + n = rp->rp_count; + pi = malloc(n * sizeof(*pi), M_TEMP, M_WAITOK); + sx_slock(&proctree_lock); + LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) { + if (i == n) + break; + pip = &pi[i]; + bzero(pip, sizeof(*pip)); + pip->pi_pid = p2->p_pid; + pip->pi_subtree = p2->p_reapsubtree; + pip->pi_flags = REAPER_PIDINFO_VALID; + if (proc_realparent(p2) == reap) + pip->pi_flags |= REAPER_PIDINFO_CHILD; + i++; + } + sx_sunlock(&proctree_lock); + error = copyout(pi, rp->rp_pids, i * sizeof(*pi)); + free(pi, M_TEMP); + sx_slock(&proctree_lock); + PROC_LOCK(p); + return (error); +} + +static int +reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk) +{ + struct proc *reap, *p2; + ksiginfo_t ksi; + int error, error1; + + sx_assert(&proctree_lock, SX_LOCKED); + PROC_UNLOCK(p); + if (IN_CAPABILITY_MODE(td)) + return (ECAPMODE); + if (rk->rk_sig <= 0 || rk->rk_sig > _SIG_MAXSIG) + return (EINVAL); + if ((rk->rk_flags & ~REAPER_KILL_CHILDREN) != 0) + return (EINVAL); + reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p; + ksiginfo_init(&ksi); + ksi.ksi_signo = rk->rk_sig; + ksi.ksi_code = SI_USER; + ksi.ksi_pid = td->td_proc->p_pid; + ksi.ksi_uid = td->td_ucred->cr_ruid; + error = ESRCH; + rk->rk_killed = 0; + rk->rk_fpid = -1; + for (p2 = (rk->rk_flags & REAPER_KILL_CHILDREN) != 0 ? + LIST_FIRST(&reap->p_children) : LIST_FIRST(&reap->p_reaplist); + p2 != NULL; + p2 = (rk->rk_flags & REAPER_KILL_CHILDREN) != 0 ? + LIST_NEXT(p2, p_sibling) : LIST_NEXT(p2, p_reapsibling)) { + if ((rk->rk_flags & REAPER_KILL_SUBTREE) != 0 && + p2->p_reapsubtree != rk->rk_subtree) + continue; + PROC_LOCK(p2); + error1 = p_cansignal(td, p2, rk->rk_sig); + if (error1 == 0) { + pksignal(p2, rk->rk_sig, &ksi); + rk->rk_killed++; + error = error1; + } else if (error == ESRCH) { + error = error1; + rk->rk_fpid = p2->p_pid; + } + PROC_UNLOCK(p2); + /* Do not end the loop on error, signal everything we can. */ + } + PROC_LOCK(p); + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ +struct procctl_args { + idtype_t idtype; + id_t id; + int com; + void *data; +}; +#endif +/* ARGSUSED */ +int +sys_procctl(struct thread *td, struct procctl_args *uap) +{ + void *data; + union { + struct procctl_reaper_status rs; + struct procctl_reaper_pids rp; + struct procctl_reaper_kill rk; + } x; + int error, error1, flags; + + switch (uap->com) { + case PROC_SPROTECT: + error = copyin(uap->data, &flags, sizeof(flags)); + if (error != 0) + return (error); + data = &flags; + break; + case PROC_REAP_ACQUIRE: + case PROC_REAP_RELEASE: + if (uap->data != NULL) + return (EINVAL); + data = NULL; + break; + case PROC_REAP_STATUS: + data = &x.rs; + break; + case PROC_REAP_GETPIDS: + error = copyin(uap->data, &x.rp, sizeof(x.rp)); + if (error != 0) + return (error); + data = &x.rp; + break; + case PROC_REAP_KILL: + error = copyin(uap->data, &x.rk, sizeof(x.rk)); + if (error != 0) + return (error); + data = &x.rk; + break; + default: + return (EINVAL); + } + error = kern_procctl(td, uap->idtype, uap->id, uap->com, data); + switch (uap->com) { + case PROC_REAP_STATUS: + if (error == 0) + error = copyout(&x.rs, uap->data, sizeof(x.rs)); + break; + case PROC_REAP_KILL: + error1 = copyout(&x.rk, uap->data, sizeof(x.rk)); + if (error == 0) + error = error1; + break; + } + return (error); +} + +static int +kern_procctl_single(struct thread *td, struct proc *p, int com, void *data) +{ + + PROC_LOCK_ASSERT(p, MA_OWNED); + switch (com) { + case PROC_SPROTECT: + return (protect_set(td, p, *(int *)data)); + case PROC_REAP_ACQUIRE: + return (reap_acquire(td, p)); + case PROC_REAP_RELEASE: + return (reap_release(td, p)); + case PROC_REAP_STATUS: + return (reap_status(td, p, data)); + case PROC_REAP_GETPIDS: + return (reap_getpids(td, p, data)); + case PROC_REAP_KILL: + return (reap_kill(td, p, data)); + default: + return (EINVAL); + } +} + +int +kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) +{ + struct pgrp *pg; + struct proc *p; + int error, first_error, ok; + + switch (com) { + case PROC_REAP_ACQUIRE: + case PROC_REAP_RELEASE: + case PROC_REAP_STATUS: + case PROC_REAP_GETPIDS: + case PROC_REAP_KILL: + if (idtype != P_PID) + return (EINVAL); + } + + switch (com) { + case PROC_SPROTECT: + case PROC_REAP_STATUS: + case PROC_REAP_GETPIDS: + case PROC_REAP_KILL: + sx_slock(&proctree_lock); + break; + case PROC_REAP_ACQUIRE: + case PROC_REAP_RELEASE: + sx_xlock(&proctree_lock); + break; + default: + return (EINVAL); + } + + switch (idtype) { + case P_PID: + p = pfind(id); + if (p == NULL) { + error = ESRCH; + break; + } + error = p_cansee(td, p); + if (error == 0) + error = kern_procctl_single(td, p, com, data); + PROC_UNLOCK(p); + break; + case P_PGID: + /* + * Attempt to apply the operation to all members of the + * group. Ignore processes in the group that can't be + * seen. Ignore errors so long as at least one process is + * able to complete the request successfully. + */ + pg = pgfind(id); + if (pg == NULL) { + error = ESRCH; + break; + } + PGRP_UNLOCK(pg); + ok = 0; + first_error = 0; + LIST_FOREACH(p, &pg->pg_members, p_pglist) { + PROC_LOCK(p); + if (p->p_state == PRS_NEW || p_cansee(td, p) != 0) { + PROC_UNLOCK(p); + continue; + } + error = kern_procctl_single(td, p, com, data); + PROC_UNLOCK(p); + if (error == 0) + ok = 1; + else if (first_error == 0) + first_error = error; + } + if (ok) + error = 0; + else if (first_error != 0) + error = first_error; + else + /* + * Was not able to see any processes in the + * process group. + */ + error = ESRCH; + break; + default: + error = EINVAL; + break; + } + sx_unlock(&proctree_lock); + return (error); +} diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 0ede6551fda2..2d0b0d278a56 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -618,6 +618,7 @@ weed_inhib(int mode, struct thread *td2, struct proc *p) wakeup_swapper |= thread_unsuspend_one(td2, p); if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) wakeup_swapper |= sleepq_abort(td2, ERESTART); + break; case SINGLE_ALLPROC: /* * ALLPROC suspend tries to avoid spurious EINTR for diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 3105d94d2998..7dd3d1754361 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -1234,193 +1233,3 @@ stopevent(struct proc *p, unsigned int event, unsigned int val) msleep(&p->p_step, &p->p_mtx, PWAIT, "stopevent", 0); } while (p->p_step); } - -static int -protect_setchild(struct thread *td, struct proc *p, int flags) -{ - - PROC_LOCK_ASSERT(p, MA_OWNED); - if (p->p_flag & P_SYSTEM || p_cansched(td, p) != 0) - return (0); - if (flags & PPROT_SET) { - p->p_flag |= P_PROTECTED; - if (flags & PPROT_INHERIT) - p->p_flag2 |= P2_INHERIT_PROTECTED; - } else { - p->p_flag &= ~P_PROTECTED; - p->p_flag2 &= ~P2_INHERIT_PROTECTED; - } - return (1); -} - -static int -protect_setchildren(struct thread *td, struct proc *top, int flags) -{ - struct proc *p; - int ret; - - p = top; - ret = 0; - sx_assert(&proctree_lock, SX_LOCKED); - for (;;) { - ret |= protect_setchild(td, p, flags); - PROC_UNLOCK(p); - /* - * If this process has children, descend to them next, - * otherwise do any siblings, and if done with this level, - * follow back up the tree (but not past top). - */ - if (!LIST_EMPTY(&p->p_children)) - p = LIST_FIRST(&p->p_children); - else for (;;) { - if (p == top) { - PROC_LOCK(p); - return (ret); - } - if (LIST_NEXT(p, p_sibling)) { - p = LIST_NEXT(p, p_sibling); - break; - } - p = p->p_pptr; - } - PROC_LOCK(p); - } -} - -static int -protect_set(struct thread *td, struct proc *p, int flags) -{ - int error, ret; - - switch (PPROT_OP(flags)) { - case PPROT_SET: - case PPROT_CLEAR: - break; - default: - return (EINVAL); - } - - if ((PPROT_FLAGS(flags) & ~(PPROT_DESCEND | PPROT_INHERIT)) != 0) - return (EINVAL); - - error = priv_check(td, PRIV_VM_MADV_PROTECT); - if (error) - return (error); - - if (flags & PPROT_DESCEND) - ret = protect_setchildren(td, p, flags); - else - ret = protect_setchild(td, p, flags); - if (ret == 0) - return (EPERM); - return (0); -} - -#ifndef _SYS_SYSPROTO_H_ -struct procctl_args { - idtype_t idtype; - id_t id; - int com; - void *data; -}; -#endif -/* ARGSUSED */ -int -sys_procctl(struct thread *td, struct procctl_args *uap) -{ - int error, flags; - void *data; - - switch (uap->com) { - case PROC_SPROTECT: - error = copyin(uap->data, &flags, sizeof(flags)); - if (error) - return (error); - data = &flags; - break; - default: - return (EINVAL); - } - - return (kern_procctl(td, uap->idtype, uap->id, uap->com, data)); -} - -static int -kern_procctl_single(struct thread *td, struct proc *p, int com, void *data) -{ - - PROC_LOCK_ASSERT(p, MA_OWNED); - switch (com) { - case PROC_SPROTECT: - return (protect_set(td, p, *(int *)data)); - default: - return (EINVAL); - } -} - -int -kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) -{ - struct pgrp *pg; - struct proc *p; - int error, first_error, ok; - - sx_slock(&proctree_lock); - switch (idtype) { - case P_PID: - p = pfind(id); - if (p == NULL) { - error = ESRCH; - break; - } - error = p_cansee(td, p); - if (error == 0) - error = kern_procctl_single(td, p, com, data); - PROC_UNLOCK(p); - break; - case P_PGID: - /* - * Attempt to apply the operation to all members of the - * group. Ignore processes in the group that can't be - * seen. Ignore errors so long as at least one process is - * able to complete the request successfully. - */ - pg = pgfind(id); - if (pg == NULL) { - error = ESRCH; - break; - } - PGRP_UNLOCK(pg); - ok = 0; - first_error = 0; - LIST_FOREACH(p, &pg->pg_members, p_pglist) { - PROC_LOCK(p); - if (p->p_state == PRS_NEW || p_cansee(td, p) != 0) { - PROC_UNLOCK(p); - continue; - } - error = kern_procctl_single(td, p, com, data); - PROC_UNLOCK(p); - if (error == 0) - ok = 1; - else if (first_error == 0) - first_error = error; - } - if (ok) - error = 0; - else if (first_error != 0) - error = first_error; - else - /* - * Was not able to see any processes in the - * process group. - */ - error = ESRCH; - break; - default: - error = EINVAL; - break; - } - sx_sunlock(&proctree_lock); - return (error); -} diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index b2091ea28417..f08036d63360 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -2002,7 +2002,7 @@ soreceive_stream(struct socket *so, struct sockaddr **psa, struct uio *uio, /* Socket buffer got some data that we shall deliver now. */ if (sbavail(sb) > 0 && !(flags & MSG_WAITALL) && - ((sb->sb_flags & SS_NBIO) || + ((so->so_state & SS_NBIO) || (flags & (MSG_DONTWAIT|MSG_NBIO)) || sbavail(sb) >= sb->sb_lowat || sbavail(sb) >= uio->uio_resid || diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index a540cc0dfa85..ef0b83c9b53c 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -505,7 +505,7 @@ uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) buf[namelen] = 0; restart: - NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, + NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME | NOCACHE, UIO_SYSSPACE, buf, fd, cap_rights_init(&rights, CAP_BINDAT), td); /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ error = namei(&nd); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 2bcf85d352c9..3105c2f4bcd5 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1269,8 +1269,9 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg, return (error); restart: bwillwrite(); - NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1, - pathseg, path, fd, cap_rights_init(&rights, CAP_MKNODAT), td); + NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 | + NOCACHE, pathseg, path, fd, cap_rights_init(&rights, CAP_MKNODAT), + td); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; @@ -1384,8 +1385,9 @@ kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg, AUDIT_ARG_MODE(mode); restart: bwillwrite(); - NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1, - pathseg, path, fd, cap_rights_init(&rights, CAP_MKFIFOAT), td); + NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 | + NOCACHE, pathseg, path, fd, cap_rights_init(&rights, CAP_MKFIFOAT), + td); if ((error = namei(&nd)) != 0) return (error); if (nd.ni_vp != NULL) { @@ -1530,8 +1532,9 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2, vrele(vp); return (EPERM); /* POSIX */ } - NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2, - segflg, path2, fd2, cap_rights_init(&rights, CAP_LINKAT), td); + NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2 | + NOCACHE, segflg, path2, fd2, cap_rights_init(&rights, CAP_LINKAT), + td); if ((error = namei(&nd)) == 0) { if (nd.ni_vp != NULL) { NDFREE(&nd, NDF_ONLY_PNBUF); @@ -1650,8 +1653,9 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2, AUDIT_ARG_TEXT(syspath); restart: bwillwrite(); - NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1, - segflg, path2, fd, cap_rights_init(&rights, CAP_SYMLINKAT), td); + NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 | + NOCACHE, segflg, path2, fd, cap_rights_init(&rights, CAP_SYMLINKAT), + td); if ((error = namei(&nd)) != 0) goto out; if (nd.ni_vp) { @@ -3581,8 +3585,9 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg, AUDIT_ARG_MODE(mode); restart: bwillwrite(); - NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1, - segflg, path, fd, cap_rights_init(&rights, CAP_MKDIRAT), td); + NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 | + NOCACHE, segflg, path, fd, cap_rights_init(&rights, CAP_MKDIRAT), + td); nd.ni_cnd.cn_flags |= WILLBEDIR; if ((error = namei(&nd)) != 0) return (error); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 687269dd35a6..40a69bbf27e0 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -189,7 +189,11 @@ vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, u_int vn_open_flags, fmode = *flagp; if (fmode & O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; - ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF; + /* + * Set NOCACHE to avoid flushing the cache when + * rolling in many files at once. + */ + ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF | NOCACHE; if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; if (!(vn_open_flags & VN_OPEN_NOAUDIT)) diff --git a/sys/mips/beri/beri_machdep.c b/sys/mips/beri/beri_machdep.c index deda11968f72..714ee3d583e4 100644 --- a/sys/mips/beri/beri_machdep.c +++ b/sys/mips/beri/beri_machdep.c @@ -88,6 +88,11 @@ static void mips_init(void) { int i; +#ifdef FDT + struct mem_region mr[FDT_MEM_REGIONS]; + int mr_cnt, val; + int j; +#endif for (i = 0; i < 10; i++) { phys_avail[i] = 0; @@ -102,6 +107,29 @@ mips_init(void) physmem = realmem; +#ifdef FDT + if (fdt_get_mem_regions(mr, &mr_cnt, &val) == 0) { + + physmem = btoc(val); + + KASSERT((phys_avail[0] >= mr[0].mr_start) && \ + (phys_avail[0] < (mr[0].mr_start + mr[0].mr_size)), + ("First region is not within FDT memory range")); + + /* Limit size of the first region */ + phys_avail[1] = MIN(mr[0].mr_size, ctob(realmem)); + dump_avail[1] = phys_avail[1]; + + /* Add the rest of regions */ + for (i = 1, j = 2; i < mr_cnt; i++, j+=2) { + phys_avail[j] = mr[i].mr_start; + phys_avail[j+1] = mr[i].mr_size; + dump_avail[j] = phys_avail[j]; + dump_avail[j+1] = phys_avail[j+1]; + } + } +#endif + init_param1(); init_param2(physmem); mips_cpu_init(); diff --git a/sys/mips/beri/files.beri b/sys/mips/beri/files.beri index 26c94ff651be..37e1839f4f13 100644 --- a/sys/mips/beri/files.beri +++ b/sys/mips/beri/files.beri @@ -6,6 +6,7 @@ dev/altera/jtag_uart/altera_jtag_uart_cons.c optional altera_jtag_uart dev/altera/jtag_uart/altera_jtag_uart_tty.c optional altera_jtag_uart dev/altera/jtag_uart/altera_jtag_uart_fdt.c optional altera_jtag_uart fdt dev/altera/jtag_uart/altera_jtag_uart_nexus.c optional altera_jtag_uart +dev/beri/virtio/virtio_mmio_platform.c optional virtio_mmio dev/netfpga10g/nf10bmac/if_nf10bmac_fdt.c optional netfpga10g_nf10bmac fdt dev/netfpga10g/nf10bmac/if_nf10bmac.c optional netfpga10g_nf10bmac dev/terasic/de4led/terasic_de4led.c optional terasic_de4led diff --git a/sys/mips/conf/BERI_SOCKIT b/sys/mips/conf/BERI_SOCKIT new file mode 100644 index 000000000000..ecc5bfe1edfd --- /dev/null +++ b/sys/mips/conf/BERI_SOCKIT @@ -0,0 +1,26 @@ +# +# BERI_SOCKIT -- Kernel for the SRI/Cambridge "BERI" (Bluespec Extensible +# RISC Implementation) FPGA soft core, as configured in its Terasic SoCKit +# reference configuration. This kernel configration must be further +# specialized to to include a root filesystem specification. +# +# $FreeBSD$ +# + +include "BERI_TEMPLATE" + +ident BERI_SOCKIT + +options ROOTDEVNAME=\"ufs:vtbd0\" + +device altera_pio +device altera_jtag_uart + +device virtio +device virtio_blk +device vtnet +device virtio_mmio + +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=beripad-sockit.dts diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index 6da06fd1c4d0..1e87e35245e2 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -600,10 +600,12 @@ makescanlist(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, * so if the desired mode is 11g, then use * the 11b channel list but upgrade the mode. */ - if (vap->iv_des_mode != IEEE80211_MODE_11G || - mode != IEEE80211_MODE_11B) - continue; - mode = IEEE80211_MODE_11G; /* upgrade */ + if (vap->iv_des_mode == IEEE80211_MODE_11G) { + if (mode == IEEE80211_MODE_11G) /* Skip the G check */ + continue; + else if (mode == IEEE80211_MODE_11B) + mode = IEEE80211_MODE_11G; /* upgrade */ + } } } else { /* diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index f986375e563e..fc39495f2f00 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -6462,6 +6462,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, switch (pr_supported->chunk_types[i]) { case SCTP_ASCONF: peer_supports_asconf = 1; + break; case SCTP_ASCONF_ACK: peer_supports_asconf_ack = 1; break; diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index 93253f2a3f25..08b1bb708ccf 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -1125,8 +1125,11 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr) SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT); return (ENOENT); } - if ((error = sa6_recoverscope(sin6)) != 0) + if ((error = sa6_recoverscope(sin6)) != 0) { + SCTP_FREE_SONAME(sin6); + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, error); return (error); + } *addr = (struct sockaddr *)sin6; return (0); } diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index a841f65dc96c..2516d7db94c2 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -1184,8 +1184,7 @@ nfs_lookup(struct vop_lookup_args *ap) return (EJUSTRETURN); } - if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE && - dattrflag) { + if ((cnp->cn_flags & MAKEENTRY) != 0 && dattrflag) { /* * Cache the modification time of the parent * directory from the post-op attributes in diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c index 1010da66d10e..32fd3f590299 100644 --- a/sys/nfsserver/nfs_serv.c +++ b/sys/nfsserver/nfs_serv.c @@ -1217,7 +1217,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; - nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART; + nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE; /* * Call namei and do initial cleanup to get a few things @@ -1501,7 +1501,7 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; - nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART; + nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE; /* * Handle nfs_namei() call. If an error occurs, the nd structure @@ -2030,7 +2030,7 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, VOP_UNLOCK(vp, 0); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; - nd.ni_cnd.cn_flags = LOCKPARENT; + nd.ni_cnd.cn_flags = LOCKPARENT | NOCACHE; error = nfs_namei(&nd, nfsd, dfhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, FALSE); if (dirp && !v3) { @@ -2153,7 +2153,7 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; - nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART; + nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART | NOCACHE; error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, FALSE); if (error == 0) { @@ -2325,7 +2325,7 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; - nd.ni_cnd.cn_flags = LOCKPARENT; + nd.ni_cnd.cn_flags = LOCKPARENT | NOCACHE; error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, FALSE); diff --git a/sys/security/mac_lomac/mac_lomac.c b/sys/security/mac_lomac/mac_lomac.c index cf66423a91c6..32ae2239a2d3 100644 --- a/sys/security/mac_lomac/mac_lomac.c +++ b/sys/security/mac_lomac/mac_lomac.c @@ -559,11 +559,11 @@ maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel, pgid = p->p_pgrp->pg_id; /* XXX could be stale? */ if (vp != NULL && VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) { log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" - " level %s after %s a level-%s %s (inode=%ld, " + " level %s after %s a level-%s %s (inode=%ju, " "mountpount=%s)\n", subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, p->p_comm, subjtext, actionname, objlabeltext, objname, - va.va_fileid, vp->v_mount->mnt_stat.f_mntonname); + (uintmax_t)va.va_fileid, vp->v_mount->mnt_stat.f_mntonname); } else { log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" " level %s after %s a level-%s %s\n", diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 2a29dd42df03..805238463a1f 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -641,6 +641,18 @@ typedef struct { #define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ #define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */ +#define R_AARCH64_ABS64 257 /* Absolute offset */ +#define R_AARCH64_ABS32 258 /* Absolute, 32-bit overflow check */ +#define R_AARCH64_ABS16 259 /* Absolute, 16-bit overflow check */ +#define R_AARCH64_PREL64 260 /* PC relative */ +#define R_AARCH64_PREL32 261 /* PC relative, 32-bit overflow check */ +#define R_AARCH64_PREL16 262 /* PC relative, 16-bit overflow check */ +#define R_AARCH64_COPY 1024 /* Copy data from shared object */ +#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ +#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ +#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */ +#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */ + #define R_ARM_NONE 0 /* No relocation. */ #define R_ARM_PC24 1 #define R_ARM_ABS32 2 diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 6590394f234d..d7a45e972867 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -513,6 +513,11 @@ struct proc { struct proc *p_pptr; /* (c + e) Pointer to parent process. */ LIST_ENTRY(proc) p_sibling; /* (e) List of sibling processes. */ LIST_HEAD(, proc) p_children; /* (e) Pointer to list of children. */ + struct proc *p_reaper; /* (e) My reaper. */ + LIST_HEAD(, proc) p_reaplist; /* (e) List of my descendants + (if I am reaper). */ + LIST_ENTRY(proc) p_reapsibling; /* (e) List of siblings - descendants of + the same reaper. */ struct mtx p_mtx; /* (n) Lock for this struct. */ struct mtx p_statmtx; /* Lock for the stats */ struct mtx p_itimmtx; /* Lock for the virt/prof timers */ @@ -570,6 +575,9 @@ struct proc { rlim_t p_cpulimit; /* (c) Current CPU limit in seconds. */ signed char p_nice; /* (c) Process "nice" value. */ int p_fibnum; /* in this routing domain XXX MRT */ + pid_t p_reapsubtree; /* (e) Pid of the direct child of the + reaper which spawned + our subtree. */ /* End area that is copied on creation. */ #define p_endcopy p_xstat @@ -671,6 +679,7 @@ struct proc { #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ #define P_TREE_FIRST_ORPHAN 0x00000002 /* First element of orphan list */ +#define P_TREE_REAPER 0x00000004 /* Reaper of subtree */ /* * These were process status values (p_stat), now they are only used in @@ -920,6 +929,7 @@ void proc_reparent(struct proc *child, struct proc *newparent); struct pstats *pstats_alloc(void); void pstats_fork(struct pstats *src, struct pstats *dst); void pstats_free(struct pstats *ps); +void reaper_abandon_children(struct proc *p, bool exiting); int securelevel_ge(struct ucred *cr, int level); int securelevel_gt(struct ucred *cr, int level); void sess_hold(struct session *); diff --git a/sys/sys/procctl.h b/sys/sys/procctl.h index ff577c06be84..d11b2b29600a 100644 --- a/sys/sys/procctl.h +++ b/sys/sys/procctl.h @@ -30,7 +30,17 @@ #ifndef _SYS_PROCCTL_H_ #define _SYS_PROCCTL_H_ +#ifndef _KERNEL +#include +#include +#endif + #define PROC_SPROTECT 1 /* set protected state */ +#define PROC_REAP_ACQUIRE 2 /* reaping enable */ +#define PROC_REAP_RELEASE 3 /* reaping disable */ +#define PROC_REAP_STATUS 4 /* reaping status */ +#define PROC_REAP_GETPIDS 5 /* get descendants */ +#define PROC_REAP_KILL 6 /* kill descendants */ /* Operations for PROC_SPROTECT (passed in integer arg). */ #define PPROT_OP(x) ((x) & 0xf) @@ -42,10 +52,51 @@ #define PPROT_DESCEND 0x10 #define PPROT_INHERIT 0x20 -#ifndef _KERNEL -#include -#include +/* Result of PREAP_STATUS (returned by value). */ +struct procctl_reaper_status { + u_int rs_flags; + u_int rs_children; + u_int rs_descendants; + pid_t rs_reaper; + pid_t rs_pid; + u_int rs_pad0[15]; +}; +/* struct procctl_reaper_status rs_flags */ +#define REAPER_STATUS_OWNED 0x00000001 +#define REAPER_STATUS_REALINIT 0x00000002 + +struct procctl_reaper_pidinfo { + pid_t pi_pid; + pid_t pi_subtree; + u_int pi_flags; + u_int pi_pad0[15]; +}; + +#define REAPER_PIDINFO_VALID 0x00000001 +#define REAPER_PIDINFO_CHILD 0x00000002 + +struct procctl_reaper_pids { + u_int rp_count; + u_int rp_pad0[15]; + struct procctl_reaper_pidinfo *rp_pids; +}; + +struct procctl_reaper_kill { + int rk_sig; /* in - signal to send */ + u_int rk_flags; /* in - REAPER_KILL flags */ + pid_t rk_subtree; /* in - subtree, if REAPER_KILL_SUBTREE */ + u_int rk_killed; /* out - count of processes sucessfully + killed */ + pid_t rk_fpid; /* out - first failed pid for which error + is returned */ + u_int rk_pad0[15]; +}; + +#define REAPER_KILL_CHILDREN 0x00000001 +#define REAPER_KILL_SUBTREE 0x00000002 + +#ifndef _KERNEL __BEGIN_DECLS int procctl(idtype_t, id_t, int, void *); __END_DECLS diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 36db48f6352f..c918cd74f65a 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -845,7 +845,7 @@ ffs_reallocblks_ufs2(ap) */ #ifdef DEBUG if (prtrealloc) - printf("realloc: ino %d, lbns %jd-%jd\n\told:", ip->i_number, + printf("realloc: ino %ju, lbns %jd-%jd\n\told:", (uintmax_t)ip->i_number, (intmax_t)start_lbn, (intmax_t)end_lbn); #endif blkno = newblk; @@ -1029,8 +1029,8 @@ ffs_valloc(pvp, mode, cred, vpp) ip = VTOI(*vpp); if (ip->i_mode) { dup_alloc: - printf("mode = 0%o, inum = %lu, fs = %s\n", - ip->i_mode, (u_long)ip->i_number, fs->fs_fsmnt); + printf("mode = 0%o, inum = %ju, fs = %s\n", + ip->i_mode, (uintmax_t)ip->i_number, fs->fs_fsmnt); panic("ffs_valloc: dup alloc"); } if (DIP(ip, i_blocks) && (fs->fs_flags & FS_UNCLEAN) == 0) { /* XXX */ diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 3df89326118a..099faeb77f15 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -256,7 +256,8 @@ ffs_snapshot(mp, snapfile) * Create the snapshot file. */ restart: - NDINIT(&nd, CREATE, LOCKPARENT | LOCKLEAF, UIO_SYSSPACE, snapfile, td); + NDINIT(&nd, CREATE, LOCKPARENT | LOCKLEAF | NOCACHE, UIO_SYSSPACE, + snapfile, td); if ((error = namei(&nd)) != 0) return (error); if (nd.ni_vp != NULL) { diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index 87a030ea501e..408349e28e6c 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -550,7 +550,7 @@ ufs_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp, /* * Insert name into cache (as non-existent) if appropriate. */ - if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) + if ((cnp->cn_flags & MAKEENTRY) != 0) cache_enter(vdp, NULL, cnp); return (ENOENT); @@ -1475,7 +1475,8 @@ ufs_checkpath(ino_t source_ino, ino_t parent_ino, struct inode *target, struct u } } KASSERT(dd_ino == VTOI(vp1)->i_number, - ("directory %d reparented\n", VTOI(vp1)->i_number)); + ("directory %ju reparented\n", + (uintmax_t)VTOI(vp1)->i_number)); if (vp != tvp) vput(vp); vp = vp1; diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index a095dbc29a21..6ba177690a0c 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -4665,10 +4665,10 @@ OLD_FILES+=usr/share/man/man4/atf-test-case.4.gz OLD_FILES+=usr/share/mk/atf.test.mk # Test suite. -. if(exists(${DESTDIR}/usr/tests/)) -TESTS_DIRS!=find ${DESTDIR}/usr/tests -type d | sed -e 's,^${DESTDIR}/,,'; echo +. if exists(${DESTDIR}${TESTSBASE}) +TESTS_DIRS!=find ${DESTDIR}${TESTSBASE} -type d | sed -e 's,^${DESTDIR}/,,'; echo OLD_DIRS+=${TESTS_DIRS} -TESTS_FILES!=find ${DESTDIR}/usr/tests \! -type d | sed -e 's,^${DESTDIR}/,,'; echo +TESTS_FILES!=find ${DESTDIR}${TESTSBASE} \! -type d | sed -e 's,^${DESTDIR}/,,'; echo OLD_FILES+=${TESTS_FILES} . endif .endif # Test suite. diff --git a/tools/tools/nanobsd/defaults.sh b/tools/tools/nanobsd/defaults.sh new file mode 100755 index 000000000000..a556e1b9622a --- /dev/null +++ b/tools/tools/nanobsd/defaults.sh @@ -0,0 +1,983 @@ +#!/bin/sh +# +# Copyright (c) 2005 Poul-Henning Kamp. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +set -e + +####################################################################### +# +# Setup default values for all controlling variables. +# These values can be overridden from the config file(s) +# +####################################################################### + +# Name of this NanoBSD build. (Used to construct workdir names) +NANO_NAME=full + +# Source tree directory +NANO_SRC=/usr/src + +# Where nanobsd additional files live under the source tree +NANO_TOOLS=tools/tools/nanobsd + +# Where cust_pkg() finds packages to install +NANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg +NANO_PACKAGE_LIST="*" + +# where package metadata gets placed +NANO_PKG_META_BASE=/var/db + +# Object tree directory +# default is subdir of /usr/obj +#NANO_OBJ="" + +# The directory to put the final images +# default is ${NANO_OBJ} +#NANO_DISKIMGDIR="" + +# Make & parallel Make +NANO_MAKE="make" +NANO_PMAKE="make -j 3" + +# The default name for any image we create. +NANO_IMGNAME="_.disk.full" + +# Options to put in make.conf during buildworld only +CONF_BUILD=' ' + +# Options to put in make.conf during installworld only +CONF_INSTALL=' ' + +# Options to put in make.conf during both build- & installworld. +CONF_WORLD=' ' + +# Kernel config file to use +NANO_KERNEL=GENERIC + +# Kernel modules to install. If empty, no modules are installed. +# Use "default" to install all built modules. +NANO_MODULES= + +# Customize commands. +NANO_CUSTOMIZE="" + +# Late customize commands. +NANO_LATE_CUSTOMIZE="" + +# Newfs paramters to use +NANO_NEWFS="-b 4096 -f 512 -i 8192 -U" + +# The drive name of the media at runtime +NANO_DRIVE=ad0 + +# Target media size in 512 bytes sectors +NANO_MEDIASIZE=2000000 + +# Number of code images on media (1 or 2) +NANO_IMAGES=2 + +# 0 -> Leave second image all zeroes so it compresses better. +# 1 -> Initialize second image with a copy of the first +NANO_INIT_IMG2=1 + +# Size of code file system in 512 bytes sectors +# If zero, size will be as large as possible. +NANO_CODESIZE=0 + +# Size of configuration file system in 512 bytes sectors +# Cannot be zero. +NANO_CONFSIZE=2048 + +# Size of data file system in 512 bytes sectors +# If zero: no partition configured. +# If negative: max size possible +NANO_DATASIZE=0 + +# Size of the /etc ramdisk in 512 bytes sectors +NANO_RAM_ETCSIZE=10240 + +# Size of the /tmp+/var ramdisk in 512 bytes sectors +NANO_RAM_TMPVARSIZE=10240 + +# Media geometry, only relevant if bios doesn't understand LBA. +NANO_SECTS=63 +NANO_HEADS=16 + +# boot0 flags/options and configuration +NANO_BOOT0CFG="-o packet -s 1 -m 3" +NANO_BOOTLOADER="boot/boot0sio" + +# boot2 flags/options +# default force serial console +NANO_BOOT2CFG="-h" + +# Backing type of md(4) device +# Can be "file" or "swap" +NANO_MD_BACKING="file" + +# for swap type md(4) backing, write out the mbr only +NANO_IMAGE_MBRONLY=true + +# Progress Print level +PPLEVEL=3 + +# Set NANO_LABEL to non-blank to form the basis for using /dev/ufs/label +# in preference to /dev/${NANO_DRIVE} +# Root partition will be ${NANO_LABEL}s{1,2} +# /cfg partition will be ${NANO_LABEL}s3 +# /data partition will be ${NANO_LABEL}s4 +NANO_LABEL="" + +####################################################################### +# Architecture to build. Corresponds to TARGET_ARCH in a buildworld. +# Unfortunately, there's no way to set TARGET at this time, and it +# conflates the two, so architectures where TARGET != TARGET_ARCH do +# not work. This defaults to the arch of the current machine. + +NANO_ARCH=`uname -p` + +# Directory to populate /cfg from +NANO_CFGDIR="" + +# Directory to populate /data from +NANO_DATADIR="" + +# src.conf to use when building the image. Defaults to /dev/null for the sake +# of determinism. +SRCCONF=${SRCCONF:=/dev/null} + +####################################################################### +# +# The functions which do the real work. +# Can be overridden from the config file(s) +# +####################################################################### + +# rm doesn't know -x prior to FreeBSD 10, so cope with a variety of build +# hosts for now. +nano_rm ( ) { + case $(uname -r) in + 7*|8*|9*) rm $* ;; + *) rm -x $* ;; + esac +} + +# run in the world chroot, errors fatal +CR() +{ + chroot ${NANO_WORLDDIR} /bin/sh -exc "$*" +} + +# run in the world chroot, errors not fatal +CR0() +{ + chroot ${NANO_WORLDDIR} /bin/sh -c "$*" || true +} + +nano_cleanup ( ) ( + if [ $? -ne 0 ]; then + echo "Error encountered. Check for errors in last log file." 1>&2 + fi + exit $? +) + +clean_build ( ) ( + pprint 2 "Clean and create object directory (${MAKEOBJDIRPREFIX})" + + if ! nano_rm -rf ${MAKEOBJDIRPREFIX}/ > /dev/null 2>&1 ; then + chflags -R noschg ${MAKEOBJDIRPREFIX}/ + nano_rm -r ${MAKEOBJDIRPREFIX}/ + fi +) + +make_conf_build ( ) ( + pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)" + + mkdir -p ${MAKEOBJDIRPREFIX} + printenv > ${MAKEOBJDIRPREFIX}/_.env + + echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_BUILD} + echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF_BUILD} +) + +build_world ( ) ( + pprint 2 "run buildworld" + pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bw" + + cd ${NANO_SRC} + env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} \ + SRCCONF=${SRCCONF} \ + __MAKE_CONF=${NANO_MAKE_CONF_BUILD} buildworld \ + > ${MAKEOBJDIRPREFIX}/_.bw 2>&1 +) + +build_kernel ( ) ( + local extra + + pprint 2 "build kernel ($NANO_KERNEL)" + pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bk" + + ( + if [ -f ${NANO_KERNEL} ] ; then + kernconfdir_arg="KERNCONFDIR='$(realpath $(dirname ${NANO_KERNEL}))'" + kernconf=$(basename ${NANO_KERNEL}) + else + kernconf=${NANO_KERNEL} + fi + + cd ${NANO_SRC}; + # unset these just in case to avoid compiler complaints + # when cross-building + unset TARGET_CPUTYPE + # Note: We intentionally build all modules, not only the ones in + # NANO_MODULES so the built world can be reused by multiple images. + eval "TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} buildkernel \ + SRCCONF='${SRCCONF}' \ + __MAKE_CONF='${NANO_MAKE_CONF_BUILD}' \ + ${kernconfdir_arg} KERNCONF=${kernconf}" + ) > ${MAKEOBJDIRPREFIX}/_.bk 2>&1 +) + +clean_world ( ) ( + if [ "${NANO_OBJ}" != "${MAKEOBJDIRPREFIX}" ]; then + pprint 2 "Clean and create object directory (${NANO_OBJ})" + if ! nano_rm -rf ${NANO_OBJ}/ > /dev/null 2>&1 ; then + chflags -R noschg ${NANO_OBJ} + nano_rm -r ${NANO_OBJ}/ + fi + mkdir -p ${NANO_OBJ} ${NANO_WORLDDIR} + printenv > ${NANO_OBJ}/_.env + else + pprint 2 "Clean and create world directory (${NANO_WORLDDIR})" + if ! nano_rm -rf ${NANO_WORLDDIR}/ > /dev/null 2>&1 ; then + chflags -R noschg ${NANO_WORLDDIR} + nano_rm -rf ${NANO_WORLDDIR}/ + fi + mkdir -p ${NANO_WORLDDIR} + fi +) + +make_conf_install ( ) ( + pprint 2 "Construct install make.conf ($NANO_MAKE_CONF_INSTALL)" + + echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_INSTALL} + echo "${CONF_INSTALL}" >> ${NANO_MAKE_CONF_INSTALL} +) + +install_world ( ) ( + pprint 2 "installworld" + pprint 3 "log: ${NANO_OBJ}/_.iw" + + cd ${NANO_SRC} + env TARGET_ARCH=${NANO_ARCH} \ + ${NANO_MAKE} SRCCONF=${SRCCONF} \ + __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} installworld \ + DESTDIR=${NANO_WORLDDIR} \ + > ${NANO_OBJ}/_.iw 2>&1 + chflags -R noschg ${NANO_WORLDDIR} +) + +install_etc ( ) ( + + pprint 2 "install /etc" + pprint 3 "log: ${NANO_OBJ}/_.etc" + + cd ${NANO_SRC} + env TARGET_ARCH=${NANO_ARCH} \ + ${NANO_MAKE} SRCCONF=${SRCCONF} \ + __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} distribution \ + DESTDIR=${NANO_WORLDDIR} \ + > ${NANO_OBJ}/_.etc 2>&1 + # make.conf doesn't get created by default, but some ports need it + # so they can spam it. + cp /dev/null ${NANO_WORLDDIR}/etc/make.conf +) + +install_kernel ( ) ( + local extra + + pprint 2 "install kernel ($NANO_KERNEL)" + pprint 3 "log: ${NANO_OBJ}/_.ik" + + ( + if [ -f ${NANO_KERNEL} ] ; then + kernconfdir_arg="KERNCONFDIR='$(realpath $(dirname ${NANO_KERNEL}))'" + kernconf=$(basename ${NANO_KERNEL}) + else + kernconf=${NANO_KERNEL} + fi + + # Install all built modules if NANO_MODULES=default, + # else install only listed modules (none if NANO_MODULES is empty). + if [ "${NANO_MODULES}" != "default" ]; then + modules_override_arg="MODULES_OVERRIDE='${NANO_MODULES}'" + fi + + cd ${NANO_SRC} + eval "TARGET_ARCH=${NANO_ARCH} ${NANO_MAKE} installkernel \ + DESTDIR='${NANO_WORLDDIR}' \ + SRCCONF='${SRCCONF}' \ + __MAKE_CONF='${NANO_MAKE_CONF_INSTALL}' \ + ${kernconfdir_arg} KERNCONF=${kernconf} \ + ${modules_override_arg}" + ) > ${NANO_OBJ}/_.ik 2>&1 +) + +native_xtools ( ) ( + print 2 "Installing the optimized native build tools for cross env" + pprint 3 "log: ${NANO_OBJ}/_.native_xtools" + + cd ${NANO_SRC} + env TARGET_ARCH=${NANO_ARCH} \ + ${NANO_MAKE} SRCCONF=${SRCCONF} \ + __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} native-xtools \ + DESTDIR=${NANO_WORLDDIR} \ + > ${NANO_OBJ}/_.native_xtools 2>&1 +) + +run_customize() ( + + pprint 2 "run customize scripts" + for c in $NANO_CUSTOMIZE + do + pprint 2 "customize \"$c\"" + pprint 3 "log: ${NANO_OBJ}/_.cust.$c" + pprint 4 "`type $c`" + ( set -x ; $c ) > ${NANO_OBJ}/_.cust.$c 2>&1 + done +) + +run_late_customize() ( + + pprint 2 "run late customize scripts" + for c in $NANO_LATE_CUSTOMIZE + do + pprint 2 "late customize \"$c\"" + pprint 3 "log: ${NANO_OBJ}/_.late_cust.$c" + pprint 4 "`type $c`" + ( set -x ; $c ) > ${NANO_OBJ}/_.late_cust.$c 2>&1 + done +) + +setup_nanobsd ( ) ( + pprint 2 "configure nanobsd setup" + pprint 3 "log: ${NANO_OBJ}/_.dl" + + ( + cd ${NANO_WORLDDIR} + + # Move /usr/local/etc to /etc/local so that the /cfg stuff + # can stomp on it. Otherwise packages like ipsec-tools which + # have hardcoded paths under ${prefix}/etc are not tweakable. + if [ -d usr/local/etc ] ; then + ( + mkdir -p etc/local + cd usr/local/etc + find . -print | cpio -dumpl ../../../etc/local + cd .. + nano_rm -rf etc + ln -s ../../etc/local etc + ) + fi + + for d in var etc + do + # link /$d under /conf + # we use hard links so we have them both places. + # the files in /$d will be hidden by the mount. + # XXX: configure /$d ramdisk size + mkdir -p conf/base/$d conf/default/$d + find $d -print | cpio -dumpl conf/base/ + done + + echo "$NANO_RAM_ETCSIZE" > conf/base/etc/md_size + echo "$NANO_RAM_TMPVARSIZE" > conf/base/var/md_size + + # pick up config files from the special partition + echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount + + # Put /tmp on the /var ramdisk (could be symlink already) + nano_rm -rf tmp + ln -s var/tmp tmp + + ) > ${NANO_OBJ}/_.dl 2>&1 +) + +setup_nanobsd_etc ( ) ( + pprint 2 "configure nanobsd /etc" + + ( + cd ${NANO_WORLDDIR} + + # create diskless marker file + touch etc/diskless + + # Make root filesystem R/O by default + echo "root_rw_mount=NO" >> etc/defaults/rc.conf + + # save config file for scripts + echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf + + echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab + echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab + mkdir -p cfg + ) +) + +prune_usr() ( + + # Remove all empty directories in /usr + find ${NANO_WORLDDIR}/usr -type d -depth -print | + while read d + do + rmdir $d > /dev/null 2>&1 || true + done +) + +newfs_part ( ) ( + local dev mnt lbl + dev=$1 + mnt=$2 + lbl=$3 + echo newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} + newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} + mount -o async ${dev} ${mnt} +) + +# Convenient spot to work around any umount issues that your build environment +# hits by overriding this method. +nano_umount () ( + umount ${1} +) + +populate_slice ( ) ( + local dev dir mnt lbl + dev=$1 + dir=$2 + mnt=$3 + lbl=$4 + echo "Creating ${dev} (mounting on ${mnt})" + newfs_part ${dev} ${mnt} ${lbl} + if [ -n "${dir}" -a -d "${dir}" ]; then + echo "Populating ${lbl} from ${dir}" + cd ${dir} + find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -dumpv ${mnt} + fi + df -i ${mnt} + nano_umount ${mnt} +) + +populate_cfg_slice ( ) ( + populate_slice "$1" "$2" "$3" "$4" +) + +populate_data_slice ( ) ( + populate_slice "$1" "$2" "$3" "$4" +) + +create_diskimage ( ) ( + pprint 2 "build diskimage" + pprint 3 "log: ${NANO_OBJ}/_.di" + + ( + echo $NANO_MEDIASIZE $NANO_IMAGES \ + $NANO_SECTS $NANO_HEADS \ + $NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE | + awk ' + { + printf "# %s\n", $0 + + # size of cylinder in sectors + cs = $3 * $4 + + # number of full cylinders on media + cyl = int ($1 / cs) + + # output fdisk geometry spec, truncate cyls to 1023 + if (cyl <= 1023) + print "g c" cyl " h" $4 " s" $3 + else + print "g c" 1023 " h" $4 " s" $3 + + if ($7 > 0) { + # size of data partition in full cylinders + dsl = int (($7 + cs - 1) / cs) + } else { + dsl = 0; + } + + # size of config partition in full cylinders + csl = int (($6 + cs - 1) / cs) + + if ($5 == 0) { + # size of image partition(s) in full cylinders + isl = int ((cyl - dsl - csl) / $2) + } else { + isl = int (($5 + cs - 1) / cs) + } + + # First image partition start at second track + print "p 1 165 " $3, isl * cs - $3 + c = isl * cs; + + # Second image partition (if any) also starts offset one + # track to keep them identical. + if ($2 > 1) { + print "p 2 165 " $3 + c, isl * cs - $3 + c += isl * cs; + } + + # Config partition starts at cylinder boundary. + print "p 3 165 " c, csl * cs + c += csl * cs + + # Data partition (if any) starts at cylinder boundary. + if ($7 > 0) { + print "p 4 165 " c, dsl * cs + } else if ($7 < 0 && $1 > c) { + print "p 4 165 " c, $1 - c + } else if ($1 < c) { + print "Disk space overcommitted by", \ + c - $1, "sectors" > "/dev/stderr" + exit 2 + } + + # Force slice 1 to be marked active. This is necessary + # for booting the image from a USB device to work. + print "a 1" + } + ' > ${NANO_OBJ}/_.fdisk + + IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} + MNT=${NANO_OBJ}/_.mnt + mkdir -p ${MNT} + + if [ "${NANO_MD_BACKING}" = "swap" ] ; then + MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \ + -y ${NANO_HEADS}` + else + echo "Creating md backing file..." + nano_rm -f ${IMG} + dd if=/dev/zero of=${IMG} seek=${NANO_MEDIASIZE} count=0 + MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \ + -y ${NANO_HEADS}` + fi + + trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT + + fdisk -i -f ${NANO_OBJ}/_.fdisk ${MD} + fdisk ${MD} + # XXX: params + # XXX: pick up cached boot* files, they may not be in image anymore. + if [ -f ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ]; then + boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD} + fi + if [ -f ${NANO_WORLDDIR}/boot/boot ]; then + bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}s1 + else + bsdlabel -w ${MD}s1 + fi + bsdlabel ${MD}s1 + + # Create first image + populate_slice /dev/${MD}s1a ${NANO_WORLDDIR} ${MNT} "s1a" + mount /dev/${MD}s1a ${MNT} + echo "Generating mtree..." + ( cd ${MNT} && mtree -c ) > ${NANO_OBJ}/_.mtree + ( cd ${MNT} && du -k ) > ${NANO_OBJ}/_.du + nano_umount ${MNT} + + if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then + # Duplicate to second image (if present) + echo "Duplicating to second image..." + dd conv=sparse if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k + mount /dev/${MD}s2a ${MNT} + for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab + do + sed -i "" "s=${NANO_DRIVE}s1=${NANO_DRIVE}s2=g" $f + done + nano_umount ${MNT} + # Override the label from the first partition so we + # don't confuse glabel with duplicates. + if [ ! -z ${NANO_LABEL} ]; then + tunefs -L ${NANO_LABEL}"s2a" /dev/${MD}s2a + fi + fi + + # Create Config slice + populate_cfg_slice /dev/${MD}s3 "${NANO_CFGDIR}" ${MNT} "s3" + + # Create Data slice, if any. + if [ $NANO_DATASIZE -ne 0 ] ; then + populate_data_slice /dev/${MD}s4 "${NANO_DATADIR}" ${MNT} "s4" + fi + + if [ "${NANO_MD_BACKING}" = "swap" ] ; then + if [ ${NANO_IMAGE_MBRONLY} ]; then + echo "Writing out _.disk.mbr..." + dd if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.mbr bs=512 count=1 + else + echo "Writing out ${NANO_IMGNAME}..." + dd if=/dev/${MD} of=${IMG} bs=64k + fi + + echo "Writing out ${NANO_IMGNAME}..." + dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k + fi + + if ${do_copyout_partition} ; then + echo "Writing out _.disk.image..." + dd conv=sparse if=/dev/${MD}s1 of=${NANO_DISKIMGDIR}/_.disk.image bs=64k + fi + mdconfig -d -u $MD + + trap - 1 2 15 + trap nano_cleanup EXIT + + ) > ${NANO_OBJ}/_.di 2>&1 +) + +last_orders () ( + # Redefine this function with any last orders you may have + # after the build completed, for instance to copy the finished + # image to a more convenient place: + # cp ${NANO_DISKIMGDIR}/_.disk.image /home/ftp/pub/nanobsd.disk + true +) + +####################################################################### +# +# Optional convenience functions. +# +####################################################################### + +####################################################################### +# Common Flash device geometries +# + +FlashDevice () { + if [ -d ${NANO_TOOLS} ] ; then + . ${NANO_TOOLS}/FlashDevice.sub + else + . ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub + fi + sub_FlashDevice $1 $2 +} + +####################################################################### +# USB device geometries +# +# Usage: +# UsbDevice Generic 1000 # a generic flash key sold as having 1GB +# +# This function will set NANO_MEDIASIZE, NANO_HEADS and NANO_SECTS for you. +# +# Note that the capacity of a flash key is usually advertised in MB or +# GB, *not* MiB/GiB. As such, the precise number of cylinders available +# for C/H/S geometry may vary depending on the actual flash geometry. +# +# The following generic device layouts are understood: +# generic An alias for generic-hdd. +# generic-hdd 255H 63S/T xxxxC with no MBR restrictions. +# generic-fdd 64H 32S/T xxxxC with no MBR restrictions. +# +# The generic-hdd device is preferred for flash devices larger than 1GB. +# + +UsbDevice () { + a1=`echo $1 | tr '[:upper:]' '[:lower:]'` + case $a1 in + generic-fdd) + NANO_HEADS=64 + NANO_SECTS=32 + NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 )) + ;; + generic|generic-hdd) + NANO_HEADS=255 + NANO_SECTS=63 + NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 )) + ;; + *) + echo "Unknown USB flash device" + exit 2 + ;; + esac +} + +####################################################################### +# Setup serial console + +cust_comconsole () ( + # Enable getty on console + sed -i "" -e /tty[du]0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys + + # Disable getty on syscons devices + sed -i "" -e '/^ttyv[0-8]/s/ on/ off/' ${NANO_WORLDDIR}/etc/ttys + + # Tell loader to use serial console early. + echo "${NANO_BOOT2CFG}" > ${NANO_WORLDDIR}/boot.config +) + +####################################################################### +# Allow root login via ssh + +cust_allow_ssh_root () ( + sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \ + ${NANO_WORLDDIR}/etc/ssh/sshd_config +) + +####################################################################### +# Install the stuff under ./Files + +cust_install_files () ( + cd ${NANO_TOOLS}/Files + find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -Ldumpv ${NANO_WORLDDIR} +) + +####################################################################### +# Install packages from ${NANO_PACKAGE_DIR} + +cust_pkg () ( + + # If the package directory doesn't exist, we're done. + if [ ! -d ${NANO_PACKAGE_DIR} ]; then + echo "DONE 0 packages" + return 0 + fi + + # Copy packages into chroot + mkdir -p ${NANO_WORLDDIR}/Pkg ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg + ( + cd ${NANO_PACKAGE_DIR} + find ${NANO_PACKAGE_LIST} -print | + cpio -Ldumpv ${NANO_WORLDDIR}/Pkg + ) + + # Count & report how many we have to install + todo=`ls ${NANO_WORLDDIR}/Pkg | wc -l` + echo "=== TODO: $todo" + ls ${NANO_WORLDDIR}/Pkg + echo "===" + while true + do + # Record how many we have now + have=`ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg | wc -l` + + # Attempt to install more packages + # ...but no more than 200 at a time due to pkg_add's internal + # limitations. + CR0 'ls Pkg/*tbz | xargs -n 200 env PKG_DBDIR='${NANO_PKG_META_BASE}'/pkg pkg_add -v -F' + + # See what that got us + now=`ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg | wc -l` + echo "=== NOW $now" + ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg + echo "===" + + + if [ $now -eq $todo ] ; then + echo "DONE $now packages" + break + elif [ $now -eq $have ] ; then + echo "FAILED: Nothing happened on this pass" + exit 2 + fi + done + nano_rm -rf ${NANO_WORLDDIR}/Pkg +) + +cust_pkgng () ( + + # If the package directory doesn't exist, we're done. + if [ ! -d ${NANO_PACKAGE_DIR} ]; then + echo "DONE 0 packages" + return 0 + fi + + # Find a pkg-* package + for x in `find -s ${NANO_PACKAGE_DIR} -iname 'pkg-*'`; do + _NANO_PKG_PACKAGE=`basename "$x"` + done + if [ -z "${_NANO_PKG_PACKAGE}" -o ! -f "${NANO_PACKAGE_DIR}/${_NANO_PKG_PACKAGE}" ]; then + echo "FAILED: need a pkg/ package for bootstrapping" + exit 2 + fi + + # Copy packages into chroot + mkdir -p ${NANO_WORLDDIR}/Pkg + ( + cd ${NANO_PACKAGE_DIR} + find ${NANO_PACKAGE_LIST} -print | + cpio -Ldumpv ${NANO_WORLDDIR}/Pkg + ) + + #Bootstrap pkg + CR env ASSUME_ALWAYS_YES=YES SIGNATURE_TYPE=none /usr/sbin/pkg add /Pkg/${_NANO_PKG_PACKAGE} + CR pkg -N >/dev/null 2>&1 + if [ "$?" -ne "0" ]; then + echo "FAILED: pkg bootstrapping faied" + exit 2 + fi + nano_rm -f ${NANO_WORLDDIR}/Pkg/pkg-* + + # Count & report how many we have to install + todo=`ls ${NANO_WORLDDIR}/Pkg | /usr/bin/wc -l` + todo=$(expr $todo + 1) # add one for pkg since it is installed already + echo "=== TODO: $todo" + ls ${NANO_WORLDDIR}/Pkg + echo "===" + while true + do + # Record how many we have now + have=$(CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info | /usr/bin/wc -l) + + # Attempt to install more packages + CR0 'ls 'Pkg/*txz' | xargs env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg add' + + # See what that got us + now=$(CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info | /usr/bin/wc -l) + echo "=== NOW $now" + CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info + echo "===" + if [ $now -eq $todo ] ; then + echo "DONE $now packages" + break + elif [ $now -eq $have ] ; then + echo "FAILED: Nothing happened on this pass" + exit 2 + fi + done + nano_rm -rf ${NANO_WORLDDIR}/Pkg +) + +####################################################################### +# Convenience function: +# Register all args as customize function. + +customize_cmd () { + NANO_CUSTOMIZE="$NANO_CUSTOMIZE $*" +} + +####################################################################### +# Convenience function: +# Register all args as late customize function to run just before +# image creation. + +late_customize_cmd () { + NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $*" +} + +####################################################################### +# +# All set up to go... +# +####################################################################### + +# Progress Print +# Print $2 at level $1. +pprint() ( + if [ "$1" -le $PPLEVEL ]; then + runtime=$(( `date +%s` - $NANO_STARTTIME )) + printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3 + fi +) + +usage () { + ( + echo "Usage: $0 [-bfiKknqvw] [-c config_file]" + echo " -b suppress builds (both kernel and world)" + echo " -c specify config file" + echo " -f suppress code slice extraction" + echo " -i suppress disk image build" + echo " -K suppress installkernel" + echo " -k suppress buildkernel" + echo " -n add -DNO_CLEAN to buildworld, buildkernel, etc" + echo " -q make output more quiet" + echo " -v make output more verbose" + echo " -w suppress buildworld" + ) 1>&2 + exit 2 +} + +####################################################################### +# Setup and Export Internal variables +# + +export_var() { + var=$1 + # Lookup value of the variable. + eval val=\$$var + pprint 3 "Setting variable: $var=\"$val\"" + export $1 +} + +# Call this function to set defaults _after_ parsing options. +set_defaults_and_export() { + test -n "${NANO_OBJ}" || NANO_OBJ=/usr/obj/nanobsd.${NANO_NAME} + test -n "${MAKEOBJDIRPREFIX}" || MAKEOBJDIRPREFIX=${NANO_OBJ} + test -n "${NANO_DISKIMGDIR}" || NANO_DISKIMGDIR=${NANO_OBJ} + NANO_WORLDDIR=${NANO_OBJ}/_.w + NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build + NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install + + # Override user's NANO_DRIVE if they specified a NANO_LABEL + [ ! -z "${NANO_LABEL}" ] && NANO_DRIVE="ufs/${NANO_LABEL}" + + # Set a default NANO_TOOLS to NANO_SRC/NANO_TOOLS if it exists. + [ ! -d "${NANO_TOOLS}" ] && [ -d "${NANO_SRC}/${NANO_TOOLS}" ] && \ + NANO_TOOLS="${NANO_SRC}/${NANO_TOOLS}" + + NANO_STARTTIME=`date +%s` + pprint 3 "Exporting NanoBSD variables" + export_var MAKEOBJDIRPREFIX + export_var NANO_ARCH + export_var NANO_CODESIZE + export_var NANO_CONFSIZE + export_var NANO_CUSTOMIZE + export_var NANO_DATASIZE + export_var NANO_DRIVE + export_var NANO_HEADS + export_var NANO_IMAGES + export_var NANO_IMGNAME + export_var NANO_MAKE + export_var NANO_MAKE_CONF_BUILD + export_var NANO_MAKE_CONF_INSTALL + export_var NANO_MEDIASIZE + export_var NANO_NAME + export_var NANO_NEWFS + export_var NANO_OBJ + export_var NANO_PMAKE + export_var NANO_SECTS + export_var NANO_SRC + export_var NANO_TOOLS + export_var NANO_WORLDDIR + export_var NANO_BOOT0CFG + export_var NANO_BOOTLOADER + export_var NANO_LABEL + export_var NANO_MODULES +} diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh index 7789ef0999b8..a4464e0caf52 100644 --- a/tools/tools/nanobsd/nanobsd.sh +++ b/tools/tools/nanobsd/nanobsd.sh @@ -29,900 +29,9 @@ set -e -####################################################################### -# -# Setup default values for all controlling variables. -# These values can be overridden from the config file(s) -# -####################################################################### - -# Name of this NanoBSD build. (Used to construct workdir names) -NANO_NAME=full - -# Source tree directory -NANO_SRC=/usr/src - -# Where nanobsd additional files live under the source tree -NANO_TOOLS=tools/tools/nanobsd - -# Where cust_pkg() finds packages to install -NANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg -NANO_PACKAGE_LIST="*" - -# where package metadata gets placed -NANO_PKG_META_BASE=/var/db - -# Object tree directory -# default is subdir of /usr/obj -#NANO_OBJ="" - -# The directory to put the final images -# default is ${NANO_OBJ} -#NANO_DISKIMGDIR="" - -# Make & parallel Make -NANO_MAKE="make" -NANO_PMAKE="make -j 3" - -# The default name for any image we create. -NANO_IMGNAME="_.disk.full" - -# Options to put in make.conf during buildworld only -CONF_BUILD=' ' - -# Options to put in make.conf during installworld only -CONF_INSTALL=' ' - -# Options to put in make.conf during both build- & installworld. -CONF_WORLD=' ' - -# Kernel config file to use -NANO_KERNEL=GENERIC - -# Kernel modules to install. If empty, no modules are installed. -# Use "default" to install all built modules. -NANO_MODULES= - -# Customize commands. -NANO_CUSTOMIZE="" - -# Late customize commands. -NANO_LATE_CUSTOMIZE="" - -# Newfs paramters to use -NANO_NEWFS="-b 4096 -f 512 -i 8192 -U" - -# The drive name of the media at runtime -NANO_DRIVE=ad0 - -# Target media size in 512 bytes sectors -NANO_MEDIASIZE=2000000 - -# Number of code images on media (1 or 2) -NANO_IMAGES=2 - -# 0 -> Leave second image all zeroes so it compresses better. -# 1 -> Initialize second image with a copy of the first -NANO_INIT_IMG2=1 - -# Size of code file system in 512 bytes sectors -# If zero, size will be as large as possible. -NANO_CODESIZE=0 - -# Size of configuration file system in 512 bytes sectors -# Cannot be zero. -NANO_CONFSIZE=2048 - -# Size of data file system in 512 bytes sectors -# If zero: no partition configured. -# If negative: max size possible -NANO_DATASIZE=0 - -# Size of the /etc ramdisk in 512 bytes sectors -NANO_RAM_ETCSIZE=10240 - -# Size of the /tmp+/var ramdisk in 512 bytes sectors -NANO_RAM_TMPVARSIZE=10240 - -# Media geometry, only relevant if bios doesn't understand LBA. -NANO_SECTS=63 -NANO_HEADS=16 - -# boot0 flags/options and configuration -NANO_BOOT0CFG="-o packet -s 1 -m 3" -NANO_BOOTLOADER="boot/boot0sio" - -# boot2 flags/options -# default force serial console -NANO_BOOT2CFG="-h" - -# Backing type of md(4) device -# Can be "file" or "swap" -NANO_MD_BACKING="file" - -# for swap type md(4) backing, write out the mbr only -NANO_IMAGE_MBRONLY=true - -# Progress Print level -PPLEVEL=3 - -# Set NANO_LABEL to non-blank to form the basis for using /dev/ufs/label -# in preference to /dev/${NANO_DRIVE} -# Root partition will be ${NANO_LABEL}s{1,2} -# /cfg partition will be ${NANO_LABEL}s3 -# /data partition will be ${NANO_LABEL}s4 -NANO_LABEL="" - -####################################################################### -# Architecture to build. Corresponds to TARGET_ARCH in a buildworld. -# Unfortunately, there's no way to set TARGET at this time, and it -# conflates the two, so architectures where TARGET != TARGET_ARCH do -# not work. This defaults to the arch of the current machine. - -NANO_ARCH=`uname -p` - -# Directory to populate /cfg from -NANO_CFGDIR="" - -# Directory to populate /data from -NANO_DATADIR="" - -# src.conf to use when building the image. Defaults to /dev/null for the sake -# of determinism. -SRCCONF=${SRCCONF:=/dev/null} - -####################################################################### -# -# The functions which do the real work. -# Can be overridden from the config file(s) -# -####################################################################### - -# rm doesn't know -x prior to FreeBSD 10, so cope with a variety of build -# hosts for now. -nano_rm ( ) { - case $(uname -r) in - 7*|8*|9*) rm $* ;; - *) rm -x $* ;; - esac -} - -# run in the world chroot, errors fatal -CR() -{ - chroot ${NANO_WORLDDIR} /bin/sh -exc "$*" -} - -# run in the world chroot, errors not fatal -CR0() -{ - chroot ${NANO_WORLDDIR} /bin/sh -c "$*" || true -} - -nano_cleanup ( ) ( - if [ $? -ne 0 ]; then - echo "Error encountered. Check for errors in last log file." 1>&2 - fi - exit $? -) - -clean_build ( ) ( - pprint 2 "Clean and create object directory (${MAKEOBJDIRPREFIX})" - - if ! nano_rm -rf ${MAKEOBJDIRPREFIX}/ > /dev/null 2>&1 ; then - chflags -R noschg ${MAKEOBJDIRPREFIX}/ - nano_rm -r ${MAKEOBJDIRPREFIX}/ - fi -) - -make_conf_build ( ) ( - pprint 2 "Construct build make.conf ($NANO_MAKE_CONF_BUILD)" - - mkdir -p ${MAKEOBJDIRPREFIX} - printenv > ${MAKEOBJDIRPREFIX}/_.env - - echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_BUILD} - echo "${CONF_BUILD}" >> ${NANO_MAKE_CONF_BUILD} -) - -build_world ( ) ( - pprint 2 "run buildworld" - pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bw" - - cd ${NANO_SRC} - env TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} \ - SRCCONF=${SRCCONF} \ - __MAKE_CONF=${NANO_MAKE_CONF_BUILD} buildworld \ - > ${MAKEOBJDIRPREFIX}/_.bw 2>&1 -) - -build_kernel ( ) ( - local extra - - pprint 2 "build kernel ($NANO_KERNEL)" - pprint 3 "log: ${MAKEOBJDIRPREFIX}/_.bk" - - ( - if [ -f ${NANO_KERNEL} ] ; then - kernconfdir_arg="KERNCONFDIR='$(realpath $(dirname ${NANO_KERNEL}))'" - kernconf=$(basename ${NANO_KERNEL}) - else - kernconf=${NANO_KERNEL} - fi - - cd ${NANO_SRC}; - # unset these just in case to avoid compiler complaints - # when cross-building - unset TARGET_CPUTYPE - # Note: We intentionally build all modules, not only the ones in - # NANO_MODULES so the built world can be reused by multiple images. - eval "TARGET_ARCH=${NANO_ARCH} ${NANO_PMAKE} buildkernel \ - SRCCONF='${SRCCONF}' \ - __MAKE_CONF='${NANO_MAKE_CONF_BUILD}' \ - ${kernconfdir_arg} KERNCONF=${kernconf}" - ) > ${MAKEOBJDIRPREFIX}/_.bk 2>&1 -) - -clean_world ( ) ( - if [ "${NANO_OBJ}" != "${MAKEOBJDIRPREFIX}" ]; then - pprint 2 "Clean and create object directory (${NANO_OBJ})" - if ! nano_rm -rf ${NANO_OBJ}/ > /dev/null 2>&1 ; then - chflags -R noschg ${NANO_OBJ} - nano_rm -r ${NANO_OBJ}/ - fi - mkdir -p ${NANO_OBJ} ${NANO_WORLDDIR} - printenv > ${NANO_OBJ}/_.env - else - pprint 2 "Clean and create world directory (${NANO_WORLDDIR})" - if ! nano_rm -rf ${NANO_WORLDDIR}/ > /dev/null 2>&1 ; then - chflags -R noschg ${NANO_WORLDDIR} - nano_rm -rf ${NANO_WORLDDIR}/ - fi - mkdir -p ${NANO_WORLDDIR} - fi -) - -make_conf_install ( ) ( - pprint 2 "Construct install make.conf ($NANO_MAKE_CONF_INSTALL)" - - echo "${CONF_WORLD}" > ${NANO_MAKE_CONF_INSTALL} - echo "${CONF_INSTALL}" >> ${NANO_MAKE_CONF_INSTALL} -) - -install_world ( ) ( - pprint 2 "installworld" - pprint 3 "log: ${NANO_OBJ}/_.iw" - - cd ${NANO_SRC} - env TARGET_ARCH=${NANO_ARCH} \ - ${NANO_MAKE} SRCCONF=${SRCCONF} \ - __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} installworld \ - DESTDIR=${NANO_WORLDDIR} \ - > ${NANO_OBJ}/_.iw 2>&1 - chflags -R noschg ${NANO_WORLDDIR} -) - -install_etc ( ) ( - - pprint 2 "install /etc" - pprint 3 "log: ${NANO_OBJ}/_.etc" - - cd ${NANO_SRC} - env TARGET_ARCH=${NANO_ARCH} \ - ${NANO_MAKE} SRCCONF=${SRCCONF} \ - __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} distribution \ - DESTDIR=${NANO_WORLDDIR} \ - > ${NANO_OBJ}/_.etc 2>&1 - # make.conf doesn't get created by default, but some ports need it - # so they can spam it. - cp /dev/null ${NANO_WORLDDIR}/etc/make.conf -) - -install_kernel ( ) ( - local extra - - pprint 2 "install kernel ($NANO_KERNEL)" - pprint 3 "log: ${NANO_OBJ}/_.ik" - - ( - if [ -f ${NANO_KERNEL} ] ; then - kernconfdir_arg="KERNCONFDIR='$(realpath $(dirname ${NANO_KERNEL}))'" - kernconf=$(basename ${NANO_KERNEL}) - else - kernconf=${NANO_KERNEL} - fi - - # Install all built modules if NANO_MODULES=default, - # else install only listed modules (none if NANO_MODULES is empty). - if [ "${NANO_MODULES}" != "default" ]; then - modules_override_arg="MODULES_OVERRIDE='${NANO_MODULES}'" - fi - - cd ${NANO_SRC} - eval "TARGET_ARCH=${NANO_ARCH} ${NANO_MAKE} installkernel \ - DESTDIR='${NANO_WORLDDIR}' \ - SRCCONF='${SRCCONF}' \ - __MAKE_CONF='${NANO_MAKE_CONF_INSTALL}' \ - ${kernconfdir_arg} KERNCONF=${kernconf} \ - ${modules_override_arg}" - ) > ${NANO_OBJ}/_.ik 2>&1 -) - -native_xtools ( ) ( - print 2 "Installing the optimized native build tools for cross env" - pprint 3 "log: ${NANO_OBJ}/_.native_xtools" - - cd ${NANO_SRC} - env TARGET_ARCH=${NANO_ARCH} \ - ${NANO_MAKE} SRCCONF=${SRCCONF} \ - __MAKE_CONF=${NANO_MAKE_CONF_INSTALL} native-xtools \ - DESTDIR=${NANO_WORLDDIR} \ - > ${NANO_OBJ}/_.native_xtools 2>&1 -) - -run_customize() ( - - pprint 2 "run customize scripts" - for c in $NANO_CUSTOMIZE - do - pprint 2 "customize \"$c\"" - pprint 3 "log: ${NANO_OBJ}/_.cust.$c" - pprint 4 "`type $c`" - ( set -x ; $c ) > ${NANO_OBJ}/_.cust.$c 2>&1 - done -) - -run_late_customize() ( - - pprint 2 "run late customize scripts" - for c in $NANO_LATE_CUSTOMIZE - do - pprint 2 "late customize \"$c\"" - pprint 3 "log: ${NANO_OBJ}/_.late_cust.$c" - pprint 4 "`type $c`" - ( set -x ; $c ) > ${NANO_OBJ}/_.late_cust.$c 2>&1 - done -) - -setup_nanobsd ( ) ( - pprint 2 "configure nanobsd setup" - pprint 3 "log: ${NANO_OBJ}/_.dl" - - ( - cd ${NANO_WORLDDIR} - - # Move /usr/local/etc to /etc/local so that the /cfg stuff - # can stomp on it. Otherwise packages like ipsec-tools which - # have hardcoded paths under ${prefix}/etc are not tweakable. - if [ -d usr/local/etc ] ; then - ( - mkdir -p etc/local - cd usr/local/etc - find . -print | cpio -dumpl ../../../etc/local - cd .. - nano_rm -rf etc - ln -s ../../etc/local etc - ) - fi - - for d in var etc - do - # link /$d under /conf - # we use hard links so we have them both places. - # the files in /$d will be hidden by the mount. - # XXX: configure /$d ramdisk size - mkdir -p conf/base/$d conf/default/$d - find $d -print | cpio -dumpl conf/base/ - done - - echo "$NANO_RAM_ETCSIZE" > conf/base/etc/md_size - echo "$NANO_RAM_TMPVARSIZE" > conf/base/var/md_size - - # pick up config files from the special partition - echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount - - # Put /tmp on the /var ramdisk (could be symlink already) - nano_rm -rf tmp - ln -s var/tmp tmp - - ) > ${NANO_OBJ}/_.dl 2>&1 -) - -setup_nanobsd_etc ( ) ( - pprint 2 "configure nanobsd /etc" - - ( - cd ${NANO_WORLDDIR} - - # create diskless marker file - touch etc/diskless - - # Make root filesystem R/O by default - echo "root_rw_mount=NO" >> etc/defaults/rc.conf - - # save config file for scripts - echo "NANO_DRIVE=${NANO_DRIVE}" > etc/nanobsd.conf - - echo "/dev/${NANO_DRIVE}s1a / ufs ro 1 1" > etc/fstab - echo "/dev/${NANO_DRIVE}s3 /cfg ufs rw,noauto 2 2" >> etc/fstab - mkdir -p cfg - ) -) - -prune_usr() ( - - # Remove all empty directories in /usr - find ${NANO_WORLDDIR}/usr -type d -depth -print | - while read d - do - rmdir $d > /dev/null 2>&1 || true - done -) - -newfs_part ( ) ( - local dev mnt lbl - dev=$1 - mnt=$2 - lbl=$3 - echo newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} - newfs ${NANO_NEWFS} ${NANO_LABEL:+-L${NANO_LABEL}${lbl}} ${dev} - mount -o async ${dev} ${mnt} -) - -# Convenient spot to work around any umount issues that your build environment -# hits by overriding this method. -nano_umount () ( - umount ${1} -) - -populate_slice ( ) ( - local dev dir mnt lbl - dev=$1 - dir=$2 - mnt=$3 - lbl=$4 - echo "Creating ${dev} (mounting on ${mnt})" - newfs_part ${dev} ${mnt} ${lbl} - if [ -n "${dir}" -a -d "${dir}" ]; then - echo "Populating ${lbl} from ${dir}" - cd ${dir} - find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -dumpv ${mnt} - fi - df -i ${mnt} - nano_umount ${mnt} -) - -populate_cfg_slice ( ) ( - populate_slice "$1" "$2" "$3" "$4" -) - -populate_data_slice ( ) ( - populate_slice "$1" "$2" "$3" "$4" -) - -create_diskimage ( ) ( - pprint 2 "build diskimage" - pprint 3 "log: ${NANO_OBJ}/_.di" - - ( - echo $NANO_MEDIASIZE $NANO_IMAGES \ - $NANO_SECTS $NANO_HEADS \ - $NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE | - awk ' - { - printf "# %s\n", $0 - - # size of cylinder in sectors - cs = $3 * $4 - - # number of full cylinders on media - cyl = int ($1 / cs) - - # output fdisk geometry spec, truncate cyls to 1023 - if (cyl <= 1023) - print "g c" cyl " h" $4 " s" $3 - else - print "g c" 1023 " h" $4 " s" $3 - - if ($7 > 0) { - # size of data partition in full cylinders - dsl = int (($7 + cs - 1) / cs) - } else { - dsl = 0; - } - - # size of config partition in full cylinders - csl = int (($6 + cs - 1) / cs) - - if ($5 == 0) { - # size of image partition(s) in full cylinders - isl = int ((cyl - dsl - csl) / $2) - } else { - isl = int (($5 + cs - 1) / cs) - } - - # First image partition start at second track - print "p 1 165 " $3, isl * cs - $3 - c = isl * cs; - - # Second image partition (if any) also starts offset one - # track to keep them identical. - if ($2 > 1) { - print "p 2 165 " $3 + c, isl * cs - $3 - c += isl * cs; - } - - # Config partition starts at cylinder boundary. - print "p 3 165 " c, csl * cs - c += csl * cs - - # Data partition (if any) starts at cylinder boundary. - if ($7 > 0) { - print "p 4 165 " c, dsl * cs - } else if ($7 < 0 && $1 > c) { - print "p 4 165 " c, $1 - c - } else if ($1 < c) { - print "Disk space overcommitted by", \ - c - $1, "sectors" > "/dev/stderr" - exit 2 - } - - # Force slice 1 to be marked active. This is necessary - # for booting the image from a USB device to work. - print "a 1" - } - ' > ${NANO_OBJ}/_.fdisk - - IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} - MNT=${NANO_OBJ}/_.mnt - mkdir -p ${MNT} - - if [ "${NANO_MD_BACKING}" = "swap" ] ; then - MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \ - -y ${NANO_HEADS}` - else - echo "Creating md backing file..." - nano_rm -f ${IMG} - dd if=/dev/zero of=${IMG} seek=${NANO_MEDIASIZE} count=0 - MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \ - -y ${NANO_HEADS}` - fi - - trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT - - fdisk -i -f ${NANO_OBJ}/_.fdisk ${MD} - fdisk ${MD} - # XXX: params - # XXX: pick up cached boot* files, they may not be in image anymore. - if [ -f ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ]; then - boot0cfg -B -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOT0CFG} ${MD} - fi - if [ -f ${NANO_WORLDDIR}/boot/boot ]; then - bsdlabel -w -B -b ${NANO_WORLDDIR}/boot/boot ${MD}s1 - else - bsdlabel -w ${MD}s1 - fi - bsdlabel ${MD}s1 - - # Create first image - populate_slice /dev/${MD}s1a ${NANO_WORLDDIR} ${MNT} "s1a" - mount /dev/${MD}s1a ${MNT} - echo "Generating mtree..." - ( cd ${MNT} && mtree -c ) > ${NANO_OBJ}/_.mtree - ( cd ${MNT} && du -k ) > ${NANO_OBJ}/_.du - nano_umount ${MNT} - - if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then - # Duplicate to second image (if present) - echo "Duplicating to second image..." - dd conv=sparse if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k - mount /dev/${MD}s2a ${MNT} - for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab - do - sed -i "" "s=${NANO_DRIVE}s1=${NANO_DRIVE}s2=g" $f - done - nano_umount ${MNT} - # Override the label from the first partition so we - # don't confuse glabel with duplicates. - if [ ! -z ${NANO_LABEL} ]; then - tunefs -L ${NANO_LABEL}"s2a" /dev/${MD}s2a - fi - fi - - # Create Config slice - populate_cfg_slice /dev/${MD}s3 "${NANO_CFGDIR}" ${MNT} "s3" - - # Create Data slice, if any. - if [ $NANO_DATASIZE -ne 0 ] ; then - populate_data_slice /dev/${MD}s4 "${NANO_DATADIR}" ${MNT} "s4" - fi - - if [ "${NANO_MD_BACKING}" = "swap" ] ; then - if [ ${NANO_IMAGE_MBRONLY} ]; then - echo "Writing out _.disk.mbr..." - dd if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.mbr bs=512 count=1 - else - echo "Writing out ${NANO_IMGNAME}..." - dd if=/dev/${MD} of=${IMG} bs=64k - fi - - echo "Writing out ${NANO_IMGNAME}..." - dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k - fi - - if ${do_copyout_partition} ; then - echo "Writing out _.disk.image..." - dd conv=sparse if=/dev/${MD}s1 of=${NANO_DISKIMGDIR}/_.disk.image bs=64k - fi - mdconfig -d -u $MD - - trap - 1 2 15 - trap nano_cleanup EXIT - - ) > ${NANO_OBJ}/_.di 2>&1 -) - -last_orders () ( - # Redefine this function with any last orders you may have - # after the build completed, for instance to copy the finished - # image to a more convenient place: - # cp ${NANO_DISKIMGDIR}/_.disk.image /home/ftp/pub/nanobsd.disk - true -) - -####################################################################### -# -# Optional convenience functions. -# -####################################################################### - -####################################################################### -# Common Flash device geometries -# - -FlashDevice () { - if [ -d ${NANO_TOOLS} ] ; then - . ${NANO_TOOLS}/FlashDevice.sub - else - . ${NANO_SRC}/${NANO_TOOLS}/FlashDevice.sub - fi - sub_FlashDevice $1 $2 -} - -####################################################################### -# USB device geometries -# -# Usage: -# UsbDevice Generic 1000 # a generic flash key sold as having 1GB -# -# This function will set NANO_MEDIASIZE, NANO_HEADS and NANO_SECTS for you. -# -# Note that the capacity of a flash key is usually advertised in MB or -# GB, *not* MiB/GiB. As such, the precise number of cylinders available -# for C/H/S geometry may vary depending on the actual flash geometry. -# -# The following generic device layouts are understood: -# generic An alias for generic-hdd. -# generic-hdd 255H 63S/T xxxxC with no MBR restrictions. -# generic-fdd 64H 32S/T xxxxC with no MBR restrictions. -# -# The generic-hdd device is preferred for flash devices larger than 1GB. -# - -UsbDevice () { - a1=`echo $1 | tr '[:upper:]' '[:lower:]'` - case $a1 in - generic-fdd) - NANO_HEADS=64 - NANO_SECTS=32 - NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 )) - ;; - generic|generic-hdd) - NANO_HEADS=255 - NANO_SECTS=63 - NANO_MEDIASIZE=$(( $2 * 1000 * 1000 / 512 )) - ;; - *) - echo "Unknown USB flash device" - exit 2 - ;; - esac -} - -####################################################################### -# Setup serial console - -cust_comconsole () ( - # Enable getty on console - sed -i "" -e /tty[du]0/s/off/on/ ${NANO_WORLDDIR}/etc/ttys - - # Disable getty on syscons devices - sed -i "" -e '/^ttyv[0-8]/s/ on/ off/' ${NANO_WORLDDIR}/etc/ttys - - # Tell loader to use serial console early. - echo "${NANO_BOOT2CFG}" > ${NANO_WORLDDIR}/boot.config -) - -####################################################################### -# Allow root login via ssh - -cust_allow_ssh_root () ( - sed -i "" -e '/PermitRootLogin/s/.*/PermitRootLogin yes/' \ - ${NANO_WORLDDIR}/etc/ssh/sshd_config -) - -####################################################################### -# Install the stuff under ./Files - -cust_install_files () ( - cd ${NANO_TOOLS}/Files - find . -print | grep -Ev '/(CVS|\.svn|\.hg|\.git)' | cpio -Ldumpv ${NANO_WORLDDIR} -) - -####################################################################### -# Install packages from ${NANO_PACKAGE_DIR} - -cust_pkg () ( - - # If the package directory doesn't exist, we're done. - if [ ! -d ${NANO_PACKAGE_DIR} ]; then - echo "DONE 0 packages" - return 0 - fi - - # Copy packages into chroot - mkdir -p ${NANO_WORLDDIR}/Pkg ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg - ( - cd ${NANO_PACKAGE_DIR} - find ${NANO_PACKAGE_LIST} -print | - cpio -Ldumpv ${NANO_WORLDDIR}/Pkg - ) - - # Count & report how many we have to install - todo=`ls ${NANO_WORLDDIR}/Pkg | wc -l` - echo "=== TODO: $todo" - ls ${NANO_WORLDDIR}/Pkg - echo "===" - while true - do - # Record how many we have now - have=`ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg | wc -l` - - # Attempt to install more packages - # ...but no more than 200 at a time due to pkg_add's internal - # limitations. - CR0 'ls Pkg/*tbz | xargs -n 200 env PKG_DBDIR='${NANO_PKG_META_BASE}'/pkg pkg_add -v -F' - - # See what that got us - now=`ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg | wc -l` - echo "=== NOW $now" - ls ${NANO_WORLDDIR}/${NANO_PKG_META_BASE}/pkg - echo "===" - - - if [ $now -eq $todo ] ; then - echo "DONE $now packages" - break - elif [ $now -eq $have ] ; then - echo "FAILED: Nothing happened on this pass" - exit 2 - fi - done - nano_rm -rf ${NANO_WORLDDIR}/Pkg -) - -cust_pkgng () ( - - # If the package directory doesn't exist, we're done. - if [ ! -d ${NANO_PACKAGE_DIR} ]; then - echo "DONE 0 packages" - return 0 - fi - - # Find a pkg-* package - for x in `find -s ${NANO_PACKAGE_DIR} -iname 'pkg-*'`; do - _NANO_PKG_PACKAGE=`basename "$x"` - done - if [ -z "${_NANO_PKG_PACKAGE}" -o ! -f "${NANO_PACKAGE_DIR}/${_NANO_PKG_PACKAGE}" ]; then - echo "FAILED: need a pkg/ package for bootstrapping" - exit 2 - fi - - # Copy packages into chroot - mkdir -p ${NANO_WORLDDIR}/Pkg - ( - cd ${NANO_PACKAGE_DIR} - find ${NANO_PACKAGE_LIST} -print | - cpio -Ldumpv ${NANO_WORLDDIR}/Pkg - ) - - #Bootstrap pkg - CR env ASSUME_ALWAYS_YES=YES SIGNATURE_TYPE=none /usr/sbin/pkg add /Pkg/${_NANO_PKG_PACKAGE} - CR pkg -N >/dev/null 2>&1 - if [ "$?" -ne "0" ]; then - echo "FAILED: pkg bootstrapping faied" - exit 2 - fi - nano_rm -f ${NANO_WORLDDIR}/Pkg/pkg-* - - # Count & report how many we have to install - todo=`ls ${NANO_WORLDDIR}/Pkg | /usr/bin/wc -l` - todo=$(expr $todo + 1) # add one for pkg since it is installed already - echo "=== TODO: $todo" - ls ${NANO_WORLDDIR}/Pkg - echo "===" - while true - do - # Record how many we have now - have=$(CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info | /usr/bin/wc -l) - - # Attempt to install more packages - CR0 'ls 'Pkg/*txz' | xargs env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg add' - - # See what that got us - now=$(CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info | /usr/bin/wc -l) - echo "=== NOW $now" - CR env ASSUME_ALWAYS_YES=YES /usr/sbin/pkg info - echo "===" - if [ $now -eq $todo ] ; then - echo "DONE $now packages" - break - elif [ $now -eq $have ] ; then - echo "FAILED: Nothing happened on this pass" - exit 2 - fi - done - nano_rm -rf ${NANO_WORLDDIR}/Pkg -) - -####################################################################### -# Convenience function: -# Register all args as customize function. - -customize_cmd () { - NANO_CUSTOMIZE="$NANO_CUSTOMIZE $*" -} - -####################################################################### -# Convenience function: -# Register all args as late customize function to run just before -# image creation. - -late_customize_cmd () { - NANO_LATE_CUSTOMIZE="$NANO_LATE_CUSTOMIZE $*" -} - -####################################################################### -# -# All set up to go... -# -####################################################################### - -# Progress Print -# Print $2 at level $1. -pprint() ( - if [ "$1" -le $PPLEVEL ]; then - runtime=$(( `date +%s` - $NANO_STARTTIME )) - printf "%s %.${1}s %s\n" "`date -u -r $runtime +%H:%M:%S`" "#####" "$2" 1>&3 - fi -) - -usage () { - ( - echo "Usage: $0 [-bfiKknqvw] [-c config_file]" - echo " -b suppress builds (both kernel and world)" - echo " -c specify config file" - echo " -f suppress code slice extraction" - echo " -i suppress disk image build" - echo " -K suppress installkernel" - echo " -k suppress buildkernel" - echo " -n add -DNO_CLEAN to buildworld, buildkernel, etc" - echo " -q make output more quiet" - echo " -v make output more verbose" - echo " -w suppress buildworld" - ) 1>&2 - exit 2 -} +nanobsd_sh=`realpath $0` +topdir=`dirname ${nanobsd_sh}` +. "${topdir}/defaults.sh" ####################################################################### # Parse arguments @@ -1012,74 +121,22 @@ if [ $# -gt 0 ] ; then usage fi -trap nano_cleanup EXIT - -####################################################################### -# Setup and Export Internal variables -# -test -n "${NANO_OBJ}" || NANO_OBJ=/usr/obj/nanobsd.${NANO_NAME} -test -n "${MAKEOBJDIRPREFIX}" || MAKEOBJDIRPREFIX=${NANO_OBJ} -test -n "${NANO_DISKIMGDIR}" || NANO_DISKIMGDIR=${NANO_OBJ} - -NANO_WORLDDIR=${NANO_OBJ}/_.w -NANO_MAKE_CONF_BUILD=${MAKEOBJDIRPREFIX}/make.conf.build -NANO_MAKE_CONF_INSTALL=${NANO_OBJ}/make.conf.install - -if [ -d ${NANO_TOOLS} ] ; then - true -elif [ -d ${NANO_SRC}/${NANO_TOOLS} ] ; then - NANO_TOOLS=${NANO_SRC}/${NANO_TOOLS} -else +if [ ! -d "${NANO_TOOLS}" ]; then echo "NANO_TOOLS directory does not exist" 1>&2 exit 1 fi -if $do_clean ; then - true -else - NANO_MAKE="${NANO_MAKE} -DNO_CLEAN" +if ! $do_clean; then NANO_PMAKE="${NANO_PMAKE} -DNO_CLEAN" fi -# Override user's NANO_DRIVE if they specified a NANO_LABEL -if [ ! -z "${NANO_LABEL}" ]; then - NANO_DRIVE=ufs/${NANO_LABEL} -fi - -export MAKEOBJDIRPREFIX - -export NANO_ARCH -export NANO_CODESIZE -export NANO_CONFSIZE -export NANO_CUSTOMIZE -export NANO_DATASIZE -export NANO_DRIVE -export NANO_HEADS -export NANO_IMAGES -export NANO_IMGNAME -export NANO_MAKE -export NANO_MAKE_CONF_BUILD -export NANO_MAKE_CONF_INSTALL -export NANO_MEDIASIZE -export NANO_NAME -export NANO_NEWFS -export NANO_OBJ -export NANO_PMAKE -export NANO_SECTS -export NANO_SRC -export NANO_TOOLS -export NANO_WORLDDIR -export NANO_BOOT0CFG -export NANO_BOOTLOADER -export NANO_LABEL - ####################################################################### # And then it is as simple as that... # File descriptor 3 is used for logging output, see pprint exec 3>&1 +set_defaults_and_export -NANO_STARTTIME=`date +%s` pprint 1 "NanoBSD image ${NANO_NAME} build starting" if $do_world ; then diff --git a/usr.bin/id/id.c b/usr.bin/id/id.c index a49fd756a747..345e2a677f5b 100644 --- a/usr.bin/id/id.c +++ b/usr.bin/id/id.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -346,14 +347,14 @@ auditid(void) "mask.success=0x%08x\n" "mask.failure=0x%08x\n" "asid=%d\n" - "termid_addr.port=0x%08x\n" + "termid_addr.port=0x%08jx\n" "termid_addr.addr[0]=0x%08x\n" "termid_addr.addr[1]=0x%08x\n" "termid_addr.addr[2]=0x%08x\n" "termid_addr.addr[3]=0x%08x\n", ainfo_addr.ai_auid, ainfo_addr.ai_mask.am_success, ainfo_addr.ai_mask.am_failure, ainfo_addr.ai_asid, - ainfo_addr.ai_termid.at_port, + (uintmax_t)ainfo_addr.ai_termid.at_port, ainfo_addr.ai_termid.at_addr[0], ainfo_addr.ai_termid.at_addr[1], ainfo_addr.ai_termid.at_addr[2], @@ -363,11 +364,11 @@ auditid(void) "mask.success=0x%08x\n" "mask.failure=0x%08x\n" "asid=%d\n" - "termid.port=0x%08x\n" + "termid.port=0x%08jx\n" "termid.machine=0x%08x\n", auditinfo.ai_auid, auditinfo.ai_mask.am_success, auditinfo.ai_mask.am_failure, - auditinfo.ai_asid, auditinfo.ai_termid.port, + auditinfo.ai_asid, (uintmax_t)auditinfo.ai_termid.port, auditinfo.ai_termid.machine); } } diff --git a/usr.bin/killall/killall.c b/usr.bin/killall/killall.c index b171630d6b9b..cdb62da6e4b9 100644 --- a/usr.bin/killall/killall.c +++ b/usr.bin/killall/killall.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -262,7 +263,7 @@ main(int ac, char **av) errx(1, "%s: not a character device", buf); tdev = sb.st_rdev; if (dflag) - printf("ttydev:0x%x\n", tdev); + printf("ttydev:0x%jx\n", (uintmax_t)tdev); } if (user) { uid = strtol(user, &ep, 10); @@ -410,8 +411,9 @@ main(int ac, char **av) if (matched == 0) continue; if (dflag) - printf("sig:%d, cmd:%s, pid:%d, dev:0x%x uid:%d\n", sig, - thiscmd, thispid, thistdev, thisuid); + printf("sig:%d, cmd:%s, pid:%d, dev:0x%jx uid:%d\n", + sig, thiscmd, thispid, (uintmax_t)thistdev, + thisuid); if (vflag || sflag) printf("kill -%s %d\n", sys_signame[sig], thispid); diff --git a/usr.bin/sed/compile.c b/usr.bin/sed/compile.c index e14666883d06..c7fbe21f9d28 100644 --- a/usr.bin/sed/compile.c +++ b/usr.bin/sed/compile.c @@ -558,7 +558,7 @@ compile_flags(char *p, struct s_subst *s) { int gn; /* True if we have seen g or n */ unsigned long nval; - char wfile[_POSIX2_LINE_MAX + 1], *q; + char wfile[_POSIX2_LINE_MAX + 1], *q, *eq; s->n = 1; /* Default */ s->p = 0; @@ -611,9 +611,12 @@ compile_flags(char *p, struct s_subst *s) #endif EATSPACE(); q = wfile; + eq = wfile + sizeof(wfile) - 1; while (*p) { if (*p == '\n') break; + if (q >= eq) + err(1, "wfile too long"); *q++ = *p++; } *q = '\0'; diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 7c444816f42d..8c92af1e0ffc 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -94,6 +94,7 @@ SUBDIR= adduser \ trpt \ tzsetup \ ugidfw \ + vigr \ vipw \ wake \ watch \ diff --git a/usr.sbin/bsdinstall/distextract/Makefile b/usr.sbin/bsdinstall/distextract/Makefile index 464ef6bf3466..313ec00902f6 100644 --- a/usr.sbin/bsdinstall/distextract/Makefile +++ b/usr.sbin/bsdinstall/distextract/Makefile @@ -2,7 +2,7 @@ BINDIR= /usr/libexec/bsdinstall PROG= distextract -LIBADD= archive ncursesw dialog m +LIBADD= archive dpv figpar ncursesw dialog m WARNS?= 6 MAN= diff --git a/usr.sbin/bsdinstall/distextract/distextract.c b/usr.sbin/bsdinstall/distextract/distextract.c index 54e0171cfe90..94536bc80638 100644 --- a/usr.sbin/bsdinstall/distextract/distextract.c +++ b/usr.sbin/bsdinstall/distextract/distextract.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -42,17 +43,13 @@ __FBSDID("$FreeBSD$"); /* Data to process */ static char *distdir = NULL; -struct file_node { - char *path; - char *name; - int length; - struct file_node *next; -}; -static struct file_node *dists = NULL; +static struct archive *archive = NULL; +static struct dpv_file_node *dists = NULL; /* Function prototypes */ +static void sig_int(int sig); static int count_files(const char *file); -static int extract_files(int nfiles, struct file_node *files); +static int extract_files(struct dpv_file_node *file, int out); #if __FreeBSD_version <= 1000008 /* r232154: bump for libarchive update */ #define archive_read_support_filter_all(x) \ @@ -66,11 +63,17 @@ main(void) { char *chrootdir; char *distributions; - int ndists = 0; int retval; - size_t file_node_size = sizeof(struct file_node); + size_t config_size = sizeof(struct dpv_config); + size_t file_node_size = sizeof(struct dpv_file_node); size_t span; - struct file_node *dist = dists; + struct dpv_config *config; + struct dpv_file_node *dist = dists; + static char backtitle[] = "FreeBSD Installer"; + static char title[] = "Archive Extraction"; + static char aprompt[] = "\n Overall Progress:"; + static char pprompt[] = "Extracting distribution files...\n"; + struct sigaction act; char error[PATH_MAX + 512]; if ((distributions = getenv("DISTRIBUTIONS")) == NULL) @@ -80,14 +83,14 @@ main(void) /* Initialize dialog(3) */ init_dialog(stdin, stdout); - dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer"); + dialog_vars.backtitle = backtitle; dlg_put_backtitle(); dialog_msgbox("", "Checking distribution archives.\nPlease wait...", 4, 35, FALSE); /* - * Parse $DISTRIBUTIONS into linked-list + * Parse $DISTRIBUTIONS into dpv(3) linked-list */ while (*distributions != '\0') { span = strcspn(distributions, "\t\n\v\f\r "); @@ -95,7 +98,6 @@ main(void) distributions++; continue; } - ndists++; /* Allocate a new struct for the distribution */ if (dist == NULL) { @@ -141,10 +143,30 @@ main(void) return (EXIT_FAILURE); } - retval = extract_files(ndists, dists); + /* Set cleanup routine for Ctrl-C action */ + act.sa_handler = sig_int; + sigaction(SIGINT, &act, 0); + /* + * Hand off to dpv(3) + */ + if ((config = calloc(1, config_size)) == NULL) + _errx(EXIT_FAILURE, "Out of memory!"); + config->backtitle = backtitle; + config->title = title; + config->pprompt = pprompt; + config->aprompt = aprompt; + config->options |= DPV_WIDE_MODE; + config->label_size = -1; + config->action = extract_files; + config->status_solo = + "%10lli files read @ %'9.1f files/sec."; + config->status_many = + "%10lli files read @ %'9.1f files/sec. [%i/%i busy/wait]"; end_dialog(); + retval = dpv(config, dists); + dpv_free(); while ((dist = dists) != NULL) { dists = dist->next; if (dist->path != NULL) @@ -155,6 +177,12 @@ main(void) return (retval); } +static void +sig_int(int sig __unused) +{ + dpv_interrupt = TRUE; +} + /* * Returns number of files in archive file. Parses $BSDINSTALL_DISTDIR/MANIFEST * if it exists, otherwise uses archive(3) to read the archive file. @@ -167,7 +195,6 @@ count_files(const char *file) int file_count; int retval; size_t span; - struct archive *archive; struct archive_entry *entry; char line[512]; char path[PATH_MAX]; @@ -220,6 +247,7 @@ count_files(const char *file) "Error while extracting %s: %s\n", file, archive_error_string(archive)); dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE); + archive = NULL; return (-1); } @@ -227,49 +255,27 @@ count_files(const char *file) while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) file_count++; archive_read_free(archive); + archive = NULL; return (file_count); } static int -extract_files(int nfiles, struct file_node *files) +extract_files(struct dpv_file_node *file, int out __unused) { - int archive_file; - int archive_files[nfiles]; - int current_files = 0; - int i; - int last_progress; - int progress = 0; int retval; - int total_files = 0; - struct archive *archive; struct archive_entry *entry; - struct file_node *file; - char status[8]; - static char title[] = "Archive Extraction"; - static char pprompt[] = "Extracting distribution files...\n"; char path[PATH_MAX]; char errormsg[PATH_MAX + 512]; - const char *items[nfiles*2]; - /* Make the transfer list for dialog */ - i = 0; - for (file = files; file != NULL; file = file->next) { - items[i*2] = file->name; - items[i*2 + 1] = "Pending"; - archive_files[i] = file->length; - - total_files += file->length; - i++; - } - - i = 0; - for (file = files; file != NULL; file = file->next) { + /* Open the archive if necessary */ + if (archive == NULL) { if ((archive = archive_read_new()) == NULL) { snprintf(errormsg, sizeof(errormsg), "Error: %s\n", archive_error_string(NULL)); dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE); - return (EXIT_FAILURE); + dpv_abort = 1; + return (-1); } archive_read_support_format_all(archive); archive_read_support_filter_all(archive); @@ -280,59 +286,44 @@ extract_files(int nfiles, struct file_node *files) "Error opening %s: %s\n", file->name, archive_error_string(archive)); dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE); - return (EXIT_FAILURE); + file->status = DPV_STATUS_FAILED; + dpv_abort = 1; + return (-1); } - - items[i*2 + 1] = "In Progress"; - archive_file = 0; - - dialog_mixedgauge(title, pprompt, 0, 0, progress, nfiles, - __DECONST(char **, items)); - - while ((retval = archive_read_next_header(archive, &entry)) == - ARCHIVE_OK) { - last_progress = progress; - progress = (current_files*100)/total_files; - - snprintf(status, sizeof(status), "-%d", - (archive_file*100)/archive_files[i]); - items[i*2 + 1] = status; - - if (progress > last_progress) - dialog_mixedgauge(title, pprompt, 0, 0, - progress, nfiles, - __DECONST(char **, items)); - - retval = archive_read_extract(archive, entry, - ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_OWNER | - ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | - ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_FFLAGS); - - if (retval != ARCHIVE_OK) - break; - - archive_file++; - current_files++; - } - - items[i*2 + 1] = "Done"; - - if (retval != ARCHIVE_EOF) { - snprintf(errormsg, sizeof(errormsg), - "Error while extracting %s: %s\n", items[i*2], - archive_error_string(archive)); - items[i*2 + 1] = "Failed"; - dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE); - return (retval); - } - - progress = (current_files*100)/total_files; - dialog_mixedgauge(title, pprompt, 0, 0, progress, nfiles, - __DECONST(char **, items)); - - archive_read_free(archive); - i++; } - return (EXIT_SUCCESS); + /* Read the next archive header */ + retval = archive_read_next_header(archive, &entry); + + /* If that went well, perform the extraction */ + if (retval == ARCHIVE_OK) + retval = archive_read_extract(archive, entry, + ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_OWNER | + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | + ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_FFLAGS); + + /* Test for either EOF or error */ + if (retval == ARCHIVE_EOF) { + archive_read_free(archive); + archive = NULL; + file->status = DPV_STATUS_DONE; + return (100); + } else if (retval != ARCHIVE_OK) { + snprintf(errormsg, sizeof(errormsg), + "Error while extracting %s: %s\n", file->name, + archive_error_string(archive)); + dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE); + file->status = DPV_STATUS_FAILED; + dpv_abort = 1; + return (-1); + } + + dpv_overall_read++; + file->read++; + + /* Calculate [overall] percentage of completion (if possible) */ + if (file->length >= 0) + return (file->read * 100 / file->length); + else + return (-1); } diff --git a/usr.sbin/chkgrp/chkgrp.c b/usr.sbin/chkgrp/chkgrp.c index c9515b5c479d..d7c15067102e 100644 --- a/usr.sbin/chkgrp/chkgrp.c +++ b/usr.sbin/chkgrp/chkgrp.c @@ -40,154 +40,152 @@ __FBSDID("$FreeBSD$"); #include #include -static char empty[] = { 0 }; - static void __dead2 usage(void) { - fprintf(stderr, "usage: chkgrp [groupfile]\n"); - exit(EX_USAGE); + + fprintf(stderr, "usage: chkgrp [-q] [groupfile]\n"); + exit(EX_USAGE); } int main(int argc, char *argv[]) { - unsigned int i; - size_t len; - int quiet; - int ch; - int n = 0, k, e = 0; - char *line, *f[4], *p; - const char *cp, *gfn; - FILE *gf; + FILE *gf; + unsigned long gid; + unsigned int i; + size_t len; + int opt, quiet; + int n = 0, k, e = 0; + const char *cp, *f[4], *gfn, *p; + char *line; - quiet = 0; - while ((ch = getopt(argc, argv, "q")) != -1) { - switch (ch) { + quiet = 0; + while ((opt = getopt(argc, argv, "q")) != -1) { + switch (opt) { case 'q': quiet = 1; break; - case '?': default: usage(); - } - } - - if (optind == argc) - gfn = "/etc/group"; - else if (optind == argc - 1) - gfn = argv[optind]; - else - usage(); - - /* open group file */ - if ((gf = fopen(gfn, "r")) == NULL) - err(EX_NOINPUT, "%s", gfn); - - /* check line by line */ - while (++n) { - if ((line = fgetln(gf, &len)) == NULL) - break; - if (len > 0 && line[len - 1] != '\n') { - warnx("%s: line %d: no newline character", gfn, n); - e = 1; + } } - while (len && isspace(line[len-1])) - len--; - /* ignore blank lines and comments */ - for (p = line; p < (line + len); p++) - if (!isspace(*p)) break; - if (!len || (*p == '#')) { -#if 0 - /* entry is correct, so print it */ - printf("%*.*s\n", len, len, line); -#endif - continue; - } + argc -= optind; + argv += optind; + + if (argc == 0) + gfn = "/etc/group"; + else if (argc == 1) + gfn = argv[0]; + else + usage(); + + /* open group file */ + if ((gf = fopen(gfn, "r")) == NULL) + err(EX_NOINPUT, "%s", gfn); + + /* check line by line */ + while (++n) { + if ((line = fgetln(gf, &len)) == NULL) + break; + if (len > 0 && line[len - 1] != '\n') { + warnx("%s: line %d: no newline character", gfn, n); + e = 1; + } + while (len && isspace(line[len-1])) + len--; + + /* ignore blank lines and comments */ + for (p = line; p < line + len; p++) + if (!isspace(*p)) break; + if (!len || *p == '#') + continue; + + /* + * Hack: special case for + line + */ + if (strncmp(line, "+:::", len) == 0) + continue; + + /* + * A correct group entry has four colon-separated fields, + * the third of which must be entirely numeric and the + * fourth of which may be empty. + */ + for (i = k = 0; k < 4; k++) { + for (f[k] = line + i; i < len && line[i] != ':'; i++) + /* nothing */ ; + if (k < 3 && line[i] != ':') + break; + line[i++] = 0; + } + + if (k < 4) { + warnx("%s: line %d: missing field(s)", gfn, n); + while (k < 4) + f[k++] = ""; + e = 1; + } + + for (cp = f[0] ; *cp ; cp++) { + if (!isalnum(*cp) && *cp != '.' && *cp != '_' && + *cp != '-' && (cp > f[0] || *cp != '+')) { + warnx("%s: line %d: '%c' invalid character", + gfn, n, *cp); + e = 1; + } + } + + for (cp = f[3] ; *cp ; cp++) { + if (!isalnum(*cp) && *cp != '.' && *cp != '_' && + *cp != '-' && *cp != ',') { + warnx("%s: line %d: '%c' invalid character", + gfn, n, *cp); + e = 1; + } + } + + /* check if fourth field ended with a colon */ + if (i < len) { + warnx("%s: line %d: too many fields", gfn, n); + e = 1; + } - /* - * A correct group entry has four colon-separated fields, the third - * of which must be entirely numeric and the fourth of which may - * be empty. - */ - for (i = k = 0; k < 4; k++) { - for (f[k] = line+i; (i < len) && (line[i] != ':'); i++) - /* nothing */ ; - if ((k < 3) && (line[i] != ':')) - break; - line[i++] = 0; + /* check that none of the fields contain whitespace */ + for (k = 0; k < 4; k++) { + if (strcspn(f[k], " \t") != strlen(f[k])) { + warnx("%s: line %d: field %d contains whitespace", + gfn, n, k+1); + e = 1; + } + } + + /* check that the GID is numeric */ + if (strspn(f[2], "0123456789") != strlen(f[2])) { + warnx("%s: line %d: group id is not numeric", gfn, n); + e = 1; + } + + /* check the range of the group id */ + errno = 0; + gid = strtoul(f[2], NULL, 10); + if (errno != 0) { + warnx("%s: line %d: strtoul failed", gfn, n); + } else if (gid > GID_MAX) { + warnx("%s: line %d: group id is too large (%ju > %ju)", + gfn, n, (uintmax_t)gid, (uintmax_t)GID_MAX); + e = 1; + } } - if (k < 4) { - warnx("%s: line %d: missing field(s)", gfn, n); - for ( ; k < 4; k++) - f[k] = empty; - e = 1; - } + /* check what broke the loop */ + if (ferror(gf)) + err(EX_IOERR, "%s: line %d", gfn, n); - for (cp = f[0] ; *cp ; cp++) { - if (!isalnum(*cp) && *cp != '.' && *cp != '_' && *cp != '-' && - (cp > f[0] || *cp != '+')) { - warnx("%s: line %d: '%c' invalid character", gfn, n, *cp); - e = 1; - } - } - - for (cp = f[3] ; *cp ; cp++) { - if (!isalnum(*cp) && *cp != '.' && *cp != '_' && *cp != '-' && - *cp != ',') { - warnx("%s: line %d: '%c' invalid character", gfn, n, *cp); - e = 1; - } - } - - /* check if fourth field ended with a colon */ - if (i < len) { - warnx("%s: line %d: too many fields", gfn, n); - e = 1; - } - - /* check that none of the fields contain whitespace */ - for (k = 0; k < 4; k++) { - if (strcspn(f[k], " \t") != strlen(f[k])) { - warnx("%s: line %d: field %d contains whitespace", - gfn, n, k+1); - e = 1; - } - } - - /* check that the GID is numeric */ - if (strspn(f[2], "0123456789") != strlen(f[2])) { - warnx("%s: line %d: GID is not numeric", gfn, n); - e = 1; - } - - /* check the range of the group id */ - errno = 0; - unsigned long groupid = strtoul(f[2], NULL, 10); - if (errno != 0) { - warnx("%s: line %d: strtoul failed", gfn, n); - } - else if (groupid > GID_MAX) { - warnx("%s: line %d: group id is too large (> %ju)", - gfn, n, (uintmax_t)GID_MAX); - e = 1; - } - -#if 0 - /* entry is correct, so print it */ - printf("%s:%s:%s:%s\n", f[0], f[1], f[2], f[3]); -#endif - } - - /* check what broke the loop */ - if (ferror(gf)) - err(EX_IOERR, "%s: line %d", gfn, n); - - /* done */ - fclose(gf); - if (e == 0 && quiet == 0) - printf("%s is fine\n", gfn); - exit(e ? EX_DATAERR : EX_OK); + /* done */ + fclose(gf); + if (e == 0 && quiet == 0) + printf("%s is fine\n", gfn); + exit(e ? EX_DATAERR : EX_OK); } diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8 index 571a87a25b17..2a5123ab877e 100644 --- a/usr.sbin/ctladm/ctladm.8 +++ b/usr.sbin/ctladm/ctladm.8 @@ -34,7 +34,7 @@ .\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $ .\" $FreeBSD$ .\" -.Dd December 6, 2014 +.Dd December 17, 2014 .Dt CTLADM 8 .Os .Sh NAME @@ -1002,6 +1002,13 @@ Set to "off" to allow them be issued in parallel. Parallel issue of consecutive operations may confuse logic of the backing file system, hurting performance; but it may improve performance of backing stores without prefetch/write-back. +.It Va psectorsize +.It Va psectoroffset +Specify physical block size and offset of the device. +.It Va usectorsize +.It Va usectoroffset +Specify UNMAP block size and offset of the device. +.It Va rpm .It Va rpm Specifies medium rotation rate of the device: 0 -- not reported, 1 -- non-rotating (SSD), >1024 -- value in revolutions per minute. diff --git a/usr.sbin/ctld/discovery.c b/usr.sbin/ctld/discovery.c index 01c9913051ba..b370e0be5867 100644 --- a/usr.sbin/ctld/discovery.c +++ b/usr.sbin/ctld/discovery.c @@ -65,13 +65,13 @@ text_receive(struct connection *conn) */ if ((bhstr->bhstr_flags & BHSTR_FLAGS_CONTINUE) != 0) log_errx(1, "received Text PDU with unsupported \"C\" flag"); - if (ntohl(bhstr->bhstr_cmdsn) < conn->conn_cmdsn) { + if (ISCSI_SNLT(ntohl(bhstr->bhstr_cmdsn), conn->conn_cmdsn)) { log_errx(1, "received Text PDU with decreasing CmdSN: " - "was %d, is %d", conn->conn_cmdsn, ntohl(bhstr->bhstr_cmdsn)); + "was %u, is %u", conn->conn_cmdsn, ntohl(bhstr->bhstr_cmdsn)); } if (ntohl(bhstr->bhstr_expstatsn) != conn->conn_statsn) { log_errx(1, "received Text PDU with wrong StatSN: " - "is %d, should be %d", ntohl(bhstr->bhstr_expstatsn), + "is %u, should be %u", ntohl(bhstr->bhstr_expstatsn), conn->conn_statsn); } conn->conn_cmdsn = ntohl(bhstr->bhstr_cmdsn); @@ -120,14 +120,14 @@ logout_receive(struct connection *conn) if ((bhslr->bhslr_reason & 0x7f) != BHSLR_REASON_CLOSE_SESSION) log_debugx("received Logout PDU with invalid reason 0x%x; " "continuing anyway", bhslr->bhslr_reason & 0x7f); - if (ntohl(bhslr->bhslr_cmdsn) < conn->conn_cmdsn) { + if (ISCSI_SNLT(ntohl(bhslr->bhslr_cmdsn), conn->conn_cmdsn)) { log_errx(1, "received Logout PDU with decreasing CmdSN: " - "was %d, is %d", conn->conn_cmdsn, + "was %u, is %u", conn->conn_cmdsn, ntohl(bhslr->bhslr_cmdsn)); } if (ntohl(bhslr->bhslr_expstatsn) != conn->conn_statsn) { log_errx(1, "received Logout PDU with wrong StatSN: " - "is %d, should be %d", ntohl(bhslr->bhslr_expstatsn), + "is %u, should be %u", ntohl(bhslr->bhslr_expstatsn), conn->conn_statsn); } conn->conn_cmdsn = ntohl(bhslr->bhslr_cmdsn); diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c index fc41f5178d34..7add09b5d9bc 100644 --- a/usr.sbin/ctld/login.c +++ b/usr.sbin/ctld/login.c @@ -127,17 +127,17 @@ login_receive(struct connection *conn, bool initial) log_errx(1, "received Login PDU with unsupported " "Version-min 0x%x", bhslr->bhslr_version_min); } - if (ntohl(bhslr->bhslr_cmdsn) < conn->conn_cmdsn) { + if (ISCSI_SNLT(ntohl(bhslr->bhslr_cmdsn), conn->conn_cmdsn)) { login_send_error(request, 0x02, 0x05); log_errx(1, "received Login PDU with decreasing CmdSN: " - "was %d, is %d", conn->conn_cmdsn, + "was %u, is %u", conn->conn_cmdsn, ntohl(bhslr->bhslr_cmdsn)); } if (initial == false && ntohl(bhslr->bhslr_expstatsn) != conn->conn_statsn) { login_send_error(request, 0x02, 0x05); log_errx(1, "received Login PDU with wrong ExpStatSN: " - "is %d, should be %d", ntohl(bhslr->bhslr_expstatsn), + "is %u, should be %u", ntohl(bhslr->bhslr_expstatsn), conn->conn_statsn); } conn->conn_cmdsn = ntohl(bhslr->bhslr_cmdsn); diff --git a/usr.sbin/iscsid/discovery.c b/usr.sbin/iscsid/discovery.c index c87d9fff7356..a8975d73077a 100644 --- a/usr.sbin/iscsid/discovery.c +++ b/usr.sbin/iscsid/discovery.c @@ -66,7 +66,7 @@ text_receive(struct connection *conn) log_errx(1, "received Text PDU with unsupported \"C\" flag"); if (ntohl(bhstr->bhstr_statsn) != conn->conn_statsn + 1) { log_errx(1, "received Text PDU with wrong StatSN: " - "is %d, should be %d", ntohl(bhstr->bhstr_statsn), + "is %u, should be %u", ntohl(bhstr->bhstr_statsn), conn->conn_statsn + 1); } conn->conn_statsn = ntohl(bhstr->bhstr_statsn); @@ -112,7 +112,7 @@ logout_receive(struct connection *conn) ntohs(bhslr->bhslr_response)); if (ntohl(bhslr->bhslr_statsn) != conn->conn_statsn + 1) { log_errx(1, "received Logout PDU with wrong StatSN: " - "is %d, should be %d", ntohl(bhslr->bhslr_statsn), + "is %u, should be %u", ntohl(bhslr->bhslr_statsn), conn->conn_statsn + 1); } conn->conn_statsn = ntohl(bhslr->bhslr_statsn); diff --git a/usr.sbin/iscsid/login.c b/usr.sbin/iscsid/login.c index afe7ebbc6bfd..360b0ef186ab 100644 --- a/usr.sbin/iscsid/login.c +++ b/usr.sbin/iscsid/login.c @@ -257,7 +257,7 @@ login_receive(struct connection *conn) * to be bug in NetBSD iSCSI target. */ log_warnx("received Login PDU with wrong StatSN: " - "is %d, should be %d", ntohl(bhslr->bhslr_statsn), + "is %u, should be %u", ntohl(bhslr->bhslr_statsn), conn->conn_statsn + 1); } conn->conn_tsih = ntohs(bhslr->bhslr_tsih); diff --git a/usr.sbin/jail/command.c b/usr.sbin/jail/command.c index 6101e078bc2c..6fefe414be67 100644 --- a/usr.sbin/jail/command.c +++ b/usr.sbin/jail/command.c @@ -667,6 +667,11 @@ run_command(struct cfjail *j) if (term != NULL) setenv("TERM", term, 1); } + if (setgid(pwd->pw_gid) < 0) { + jail_warnx(j, "setgid %d: %s", pwd->pw_gid, + strerror(errno)); + exit(1); + } if (setusercontext(lcap, pwd, pwd->pw_uid, username ? LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN : LOGIN_SETPATH | LOGIN_SETENV) < 0) { diff --git a/usr.sbin/kldxref/Makefile b/usr.sbin/kldxref/Makefile index 767cc23cea2c..75e74efc65da 100644 --- a/usr.sbin/kldxref/Makefile +++ b/usr.sbin/kldxref/Makefile @@ -5,7 +5,6 @@ MAN= kldxref.8 SRCS= kldxref.c ef.c ef_obj.c WARNS?= 2 -CFLAGS+=-fno-strict-aliasing .if exists(ef_${MACHINE_CPUARCH}.c) && ${MACHINE_ARCH} != "powerpc64" SRCS+= ef_${MACHINE_CPUARCH}.c diff --git a/usr.sbin/lpr/lpr/lpr.c b/usr.sbin/lpr/lpr/lpr.c index 394ccb063242..9a4382f12c5f 100644 --- a/usr.sbin/lpr/lpr/lpr.c +++ b/usr.sbin/lpr/lpr/lpr.c @@ -387,8 +387,8 @@ main(int argc, char *argv[]) continue; /* file unreasonable */ if (sflag && (cp = linked(arg)) != NULL) { - (void)snprintf(buf, sizeof(buf), "%u %ju", - statb.st_dev, (uintmax_t)statb.st_ino); + (void)snprintf(buf, sizeof(buf), "%ju %ju", + (uintmax_t)statb.st_dev, (uintmax_t)statb.st_ino); card('S', buf); if (format == 'p') card('T', title ? title : arg); diff --git a/usr.sbin/pw/tests/pw_useradd.sh b/usr.sbin/pw/tests/pw_useradd.sh index fb2e33f954c7..2930c41b0647 100755 --- a/usr.sbin/pw/tests/pw_useradd.sh +++ b/usr.sbin/pw/tests/pw_useradd.sh @@ -13,7 +13,16 @@ user_add_body() { grep "^test:.*" $HOME/master.passwd } +# Test add user with option -N +atf_test_case user_add_noupdate +user_add_noupdate_body() { + populate_etc_skel + atf_check -s exit:0 -o match:"^test:.*" ${PW} useradd test -N + atf_check -s exit:1 -o empty grep "^test:.*" $HOME/master.passwd +} + +# Test add user with comments atf_test_case user_add_comments user_add_comments_body() { populate_etc_skel @@ -23,6 +32,17 @@ user_add_comments_body() { grep "^test:.*:Test User,work,123,456:" $HOME/master.passwd } +# Test add user with comments and option -N +atf_test_case user_add_comments_noupdate +user_add_comments_noupdate_body() { + populate_etc_skel + + atf_check -s exit:0 -o match:"^test:.*:Test User,work,123,456:" \ + ${PW} useradd test -c "Test User,work,123,456" -N + atf_check -s exit:1 -o empty grep "^test:.*" $HOME/master.passwd +} + +# Test add user with invalid comments atf_test_case user_add_comments_invalid user_add_comments_invalid_body() { populate_etc_skel @@ -33,8 +53,21 @@ user_add_comments_invalid_body() { grep "^test:.*:Test User,work,123:456,456:" $HOME/master.passwd } +# Test add user with invalid comments and option -N +atf_test_case user_add_comments_invalid_noupdate +user_add_comments_invalid_noupdate_body() { + populate_etc_skel + + atf_check -s exit:65 -e match:"invalid character" \ + ${PW} useradd test -c "Test User,work,123:456,456" -N + atf_check -s exit:1 -o empty grep "^test:.*" $HOME/master.passwd +} + atf_init_test_cases() { atf_add_test_case user_add + atf_add_test_case user_add_noupdate atf_add_test_case user_add_comments + atf_add_test_case user_add_comments_noupdate atf_add_test_case user_add_comments_invalid + atf_add_test_case user_add_comments_invalid_noupdate } diff --git a/usr.sbin/pw/tests/pw_usermod.sh b/usr.sbin/pw/tests/pw_usermod.sh index f5bac78aed3d..88bd3163a621 100755 --- a/usr.sbin/pw/tests/pw_usermod.sh +++ b/usr.sbin/pw/tests/pw_usermod.sh @@ -15,6 +15,18 @@ user_mod_body() { grep "^test:.*" $HOME/master.passwd } +# Test modifying a user with option -N +atf_test_case user_mod_noupdate +user_mod_noupdate_body() { + populate_etc_skel + + atf_check -s exit:67 -e match:"no such user" ${PW} usermod test -N + atf_check -s exit:0 ${PW} useradd test + atf_check -s exit:0 -o match:"^test:.*" ${PW} usermod test -N + atf_check -s exit:0 -o match:"^test:.*" \ + grep "^test:.*" $HOME/master.passwd +} + # Test modifying a user with comments atf_test_case user_mod_comments user_mod_comments_body() { @@ -26,6 +38,18 @@ user_mod_comments_body() { grep "^test:.*:Test User,work,123,456:" $HOME/master.passwd } +# Test modifying a user with comments with option -N +atf_test_case user_mod_comments_noupdate +user_mod_comments_noupdate_body() { + populate_etc_skel + + atf_check -s exit:0 ${PW} useradd test -c "Test User,home,123,456" + atf_check -s exit:0 -o match:"^test:.*:Test User,work,123,456:" \ + ${PW} usermod test -c "Test User,work,123,456" -N + atf_check -s exit:0 -o match:"^test:.*:Test User,home,123,456:" \ + grep "^test:.*:Test User,home,123,456:" $HOME/master.passwd +} + # Test modifying a user with invalid comments atf_test_case user_mod_comments_invalid user_mod_comments_invalid_body() { @@ -36,6 +60,22 @@ user_mod_comments_invalid_body() { ${PW} usermod test -c "Test User,work,123:456,456" atf_check -s exit:1 -o empty \ grep "^test:.*:Test User,work,123:456,456:" $HOME/master.passwd + atf_check -s exit:0 -o match:"^test:\*" \ + grep "^test:\*" $HOME/master.passwd +} + +# Test modifying a user with invalid comments with option -N +atf_test_case user_mod_comments_invalid_noupdate +user_mod_comments_invalid_noupdate_body() { + populate_etc_skel + + atf_check -s exit:0 ${PW} useradd test + atf_check -s exit:65 -e match:"invalid character" \ + ${PW} usermod test -c "Test User,work,123:456,456" -N + atf_check -s exit:1 -o empty \ + grep "^test:.*:Test User,work,123:456,456:" $HOME/master.passwd + atf_check -s exit:0 -o match:"^test:\*" \ + grep "^test:\*" $HOME/master.passwd } # Test modifying a user name with -l @@ -48,9 +88,25 @@ user_mod_name_body() { atf_check -s exit:0 -o match:"^bar:.*" \ grep "^bar:.*" $HOME/master.passwd } + +# Test modifying a user name with -l with option -N +atf_test_case user_mod_name_noupdate +user_mod_name_noupdate_body() { + populate_etc_skel + + atf_check -s exit:0 ${PW} useradd foo + atf_check -s exit:0 -o match:"^bar:.*" ${PW} usermod foo -l "bar" -N + atf_check -s exit:0 -o match:"^foo:.*" \ + grep "^foo:.*" $HOME/master.passwd +} + atf_init_test_cases() { atf_add_test_case user_mod + atf_add_test_case user_mod_noupdate atf_add_test_case user_mod_comments + atf_add_test_case user_mod_comments_noupdate atf_add_test_case user_mod_comments_invalid + atf_add_test_case user_mod_comments_invalid_noupdate atf_add_test_case user_mod_name + atf_add_test_case user_mod_name_noupdate } diff --git a/usr.sbin/vigr/Makefile b/usr.sbin/vigr/Makefile new file mode 100644 index 000000000000..d71998b47326 --- /dev/null +++ b/usr.sbin/vigr/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SCRIPTS= vigr +MAN= vigr.8 + +.include diff --git a/usr.sbin/vigr/vigr.8 b/usr.sbin/vigr/vigr.8 new file mode 100644 index 000000000000..3fd582b2cd98 --- /dev/null +++ b/usr.sbin/vigr/vigr.8 @@ -0,0 +1,71 @@ +.\"- +.\" Copyright (c) 2014 Dag-Erling Smørgrav +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 14, 2014 +.Dt VIGR 8 +.Os +.Sh NAME +.Nm vigr +.Nd edit the group file +.Sh SYNOPSIS +.Nm +.Op Fl d Ar directory +.Sh DESCRIPTION +The +.Nm +utility makes a temporary copy of the group file, allows the user to +edit it, then verifies that the edited file is valid before installing +it. +.Pp +The following options are available: +.Bl -tag -width Fl +.It Fl d Ar directory +Edit the group file in the specified directory instead of the default +.Pa /etc/group . +.El +.Sh ENVIRONMENT +.Bl -tag -width EDITOR +.It Ev EDITOR +The editor to use instead of +.Xr vi 1 . +.It Ev TMPDIR +The directory in which to store the temporary copy of the group file. +.El +.Sh SEE ALSO +.Xr group 5 , +.Xr chkgrp 8 , +.Xr vipw 8 +.Sh HISTORY +The +.Nm +utility appeared in +.Fx 11.0 . +.Sh AUTHORS +The +.Nm +utility and this manual page were written by +.An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org . diff --git a/usr.sbin/vigr/vigr.sh b/usr.sbin/vigr/vigr.sh new file mode 100644 index 000000000000..c5dc65d8be18 --- /dev/null +++ b/usr.sbin/vigr/vigr.sh @@ -0,0 +1,95 @@ +#!/bin/sh +#- +# Copyright (c) 2014 Dag-Erling Smørgrav +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +error() { + echo "$@" >&2 + exit 1 +} + +usage() { + error "usage: vigr [-d dir]" +} + +# Check arguments +while getopts d: opt ; do + case $opt in + d) + etcdir="${OPTARG}" + ;; + *) + usage + ;; + esac +done + +# Look for the current group file +grpfile="${etcdir:-/etc}/group" +if [ ! -f "${grpfile}" ] ; then + error "Missing group file" +fi + +# Create a secure temporary working directory +tmpdir=$(mktemp -d -t vigr) +if [ -z "${tmpdir}" -o ! -d "${tmpdir}" ] ; then + error "Unable to create the temporary directory" +fi +tmpfile="${tmpdir}/group" + +# Clean up on exit +trap "exit 1" INT +trap "rm -rf '${tmpdir}'" EXIT +set -e + +# Make a copy of the group file for the user to edit +cp "${grpfile}" "${tmpfile}" + +while :; do + # Let the user edit the file + ${EDITOR:-/usr/bin/vi} "${tmpfile}" + + # If the result is valid, install it and exit + if chkgrp -q "${tmpfile}" ; then + install -b -m 0644 -C -S "${tmpfile}" "${grpfile}" + exit 0 + fi + + # If it is not, offer to re-edit + while :; do + echo -n "Re-edit the group file? " + read ans + case $ans in + [Yy]|[Yy][Ee][Ss]) + break + ;; + [Nn]|[Nn][Oo]) + exit 1 + ;; + esac + done +done