summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Botelho <renato@netgate.com>2016-08-17 15:28:04 -0300
committerRenato Botelho <renato@netgate.com>2016-08-17 15:28:04 -0300
commit09d13eb42030a7cc873d4ddfeefec8729da43a33 (patch)
treea096d70cac1e6382d6d25dc5726ab2bace917fa9
parent9f8f029a1d248dbac66c141e28e7cc76522b4532 (diff)
parentfe7e5c7c52420f37d2b9ea80f9be220dc8e314b8 (diff)
downloadFreeBSD-src-09d13eb42030a7cc873d4ddfeefec8729da43a33.zip
FreeBSD-src-09d13eb42030a7cc873d4ddfeefec8729da43a33.tar.gz
Merge remote-tracking branch 'origin/stable/11' into devel-11
-rw-r--r--Makefile.inc12
-rw-r--r--bin/ps/ps.14
-rw-r--r--cddl/contrib/opensolaris/cmd/zdb/zdb.811
-rw-r--r--cddl/contrib/opensolaris/cmd/zdb/zdb.c28
-rw-r--r--contrib/blacklist/lib/bl.c21
-rw-r--r--contrib/tcsh/glob.c2
-rw-r--r--lib/clang/clang.build.mk2
-rw-r--r--lib/clang/freebsd_cc_version.h2
-rw-r--r--lib/libc/gen/fnmatch.c4
-rw-r--r--lib/libc/gen/glob.320
-rw-r--r--lib/libc/gen/glob.c512
-rw-r--r--lib/libc/locale/collate.h4
-rw-r--r--lib/libc/locale/collcmp.c13
-rw-r--r--lib/libc/regex/regcomp.c11
-rw-r--r--lib/libc/stdio/vfscanf.c6
-rw-r--r--lib/libc/sys/ptrace.2219
-rwxr-xr-xrelease/release.sh8
-rw-r--r--sbin/ipfw/ipfw2.c4
-rw-r--r--sbin/pfctl/parse.y6
-rw-r--r--sbin/route/route.c28
-rw-r--r--share/mk/bsd.README1
-rw-r--r--share/mk/bsd.progs.mk4
-rw-r--r--sys/amd64/amd64/initcpu.c14
-rw-r--r--sys/amd64/amd64/pmap.c6
-rw-r--r--sys/amd64/amd64/trap.c4
-rw-r--r--sys/arm/allwinner/a10_gpio.c2
-rw-r--r--sys/arm/allwinner/aw_nmi.c2
-rw-r--r--sys/arm/allwinner/axp209.c8
-rw-r--r--sys/arm64/arm64/vm_machdep.c2
-rw-r--r--sys/boot/fdt/dts/arm/pcduino3.dts (renamed from sys/boot/fdt/dts/arm/pcduino3b.dts)0
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c20
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c148
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c15
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c8
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c24
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c24
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h10
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h10
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c31
-rw-r--r--sys/dev/bxe/bxe.c3
-rw-r--r--sys/dev/mlx5/mlx5_en/en.h8
-rw-r--r--sys/dev/mlx5/mlx5_en/mlx5_en_main.c31
-rw-r--r--sys/dev/mlx5/mlx5_en/mlx5_en_rx.c19
-rw-r--r--sys/dev/mlx5/mlx5_en/tcp_tlro.c697
-rw-r--r--sys/dev/mlx5/mlx5_en/tcp_tlro.h83
-rw-r--r--sys/dev/usb/input/ukbd.c12
-rw-r--r--sys/dev/usb/usbdevs1
-rw-r--r--sys/dev/virtio/network/if_vtnet.c61
-rw-r--r--sys/dev/virtio/network/if_vtnetvar.h1
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c11
-rw-r--r--sys/i386/i386/trap.c4
-rw-r--r--sys/i386/linux/linux_ptrace.c4
-rw-r--r--sys/kern/kern_exec.c4
-rw-r--r--sys/kern/kern_exit.c9
-rw-r--r--sys/kern/kern_fork.c14
-rw-r--r--sys/kern/kern_kthread.c11
-rw-r--r--sys/kern/kern_sig.c49
-rw-r--r--sys/kern/kern_thr.c5
-rw-r--r--sys/kern/subr_syscall.c4
-rw-r--r--sys/kern/sys_process.c105
-rw-r--r--sys/modules/dtb/allwinner/Makefile2
-rw-r--r--sys/modules/mlx5en/Makefile9
-rw-r--r--sys/netinet/ip_fw.h1
-rw-r--r--sys/netinet/sctp_indata.c45
-rw-r--r--sys/netinet/tcp_fastopen.c1
-rw-r--r--sys/netinet6/in6.h5
-rw-r--r--sys/netinet6/ip6_input.c37
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c24
-rw-r--r--sys/netpfil/pf/pf_ioctl.c16
-rw-r--r--sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.c7
-rw-r--r--sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.h11
-rw-r--r--sys/sys/proc.h7
-rw-r--r--sys/sys/ptrace.h20
-rw-r--r--sys/vm/uma_core.c5
-rw-r--r--sys/vm/vm_page.c10
-rw-r--r--sys/vm/vm_pageout.c20
-rw-r--r--tests/sys/kern/ptrace_test.c198
-rw-r--r--usr.bin/Makefile5
-rw-r--r--usr.bin/getconf/getconf.14
-rw-r--r--usr.bin/getconf/progenv.gperf2
-rw-r--r--usr.bin/resizewin/resizewin.18
-rw-r--r--usr.bin/tr/tr.14
-rw-r--r--usr.bin/tr/tr.c7
-rw-r--r--usr.bin/truss/setup.c4
-rw-r--r--usr.bin/truss/syscalls.c2
88 files changed, 1496 insertions, 1340 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index f554d65..cfd9076 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -1011,7 +1011,7 @@ distributeworld installworld stageworld: _installcheck_world .PHONY
${IMAKEENV} rm -rf ${INSTALLTMP}
.if make(distributeworld)
.for dist in ${EXTRA_DISTRIBUTIONS}
- find ${DESTDIR}/${DISTDIR}/${dist} -mindepth 1 -empty -delete
+ find ${DESTDIR}/${DISTDIR}/${dist} -mindepth 1 -type d -empty -delete
.endfor
.if defined(NO_ROOT)
.for dist in base ${EXTRA_DISTRIBUTIONS}
diff --git a/bin/ps/ps.1 b/bin/ps/ps.1
index 3d7c738..2a52da7 100644
--- a/bin/ps/ps.1
+++ b/bin/ps/ps.1
@@ -29,7 +29,7 @@
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
-.Dd December 1, 2015
+.Dd August 12, 2016
.Dt PS 1
.Os
.Sh NAME
@@ -319,7 +319,6 @@ the include file
.It Dv "P_ADVLOCK" Ta No "0x00001" Ta "Process may hold a POSIX advisory lock"
.It Dv "P_CONTROLT" Ta No "0x00002" Ta "Has a controlling terminal"
.It Dv "P_KPROC" Ta No "0x00004" Ta "Kernel process"
-.It Dv "P_FOLLOWFORK" Ta No "0x00008" Ta "Attach debugger to new children"
.It Dv "P_PPWAIT" Ta No "0x00010" Ta "Parent is waiting for child to exec/exit"
.It Dv "P_PROFIL" Ta No "0x00020" Ta "Has started profiling"
.It Dv "P_STOPPROF" Ta No "0x00040" Ta "Has thread in requesting to stop prof"
@@ -360,6 +359,7 @@ the include file
.It Dv "P2_NOTRACE" Ta No "0x00000002" Ta "No ptrace(2) attach or coredumps"
.It Dv "P2_NOTRACE_EXEC" Ta No "0x00000004" Ta "Keep P2_NOPTRACE on exec(2)"
.It Dv "P2_AST_SU" Ta No "0x00000008" Ta "Handles SU ast for kthreads"
+.It Dv "P2_PTRACE_FSTP" Ta No "0x00000010" Ta "SIGSTOP from PT_ATTACH not yet handled"
.El
.It Cm label
The MAC label of the process.
diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.8 b/cddl/contrib/opensolaris/cmd/zdb/zdb.8
index 4ef437e..6ae25c3 100644
--- a/cddl/contrib/opensolaris/cmd/zdb/zdb.8
+++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.8
@@ -86,6 +86,17 @@ pool, and is inherently unstable.
The precise output of most invocations is not documented, a knowledge of ZFS
internals is assumed.
.Pp
+If the
+.Ar dataset
+argument does not contain any
+.Sy /
+or
+.Sy @
+characters, it is interpreted as a pool name.
+The root dataset can be specified as
+.Pa pool Ns Sy /
+(pool name followed by a slash).
+.Pp
When operating on an imported and active pool it is possible, though unlikely,
that zdb may interpret inconsistent pool data and behave erratically.
.Sh OPTIONS
diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
index 7157d58..893e6a2 100644
--- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c
+++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
@@ -3558,12 +3558,23 @@ main(int argc, char **argv)
nvlist_t *policy = NULL;
uint64_t max_txg = UINT64_MAX;
int rewind = ZPOOL_NEVER_REWIND;
+ char *spa_config_path_env;
+ boolean_t target_is_spa = B_TRUE;
(void) setrlimit(RLIMIT_NOFILE, &rl);
(void) enable_extended_FILE_stdio(-1, -1);
dprintf_setup(&argc, argv);
+ /*
+ * If there is an environment variable SPA_CONFIG_PATH it overrides
+ * default spa_config_path setting. If -U flag is specified it will
+ * override this environment variable settings once again.
+ */
+ spa_config_path_env = getenv("SPA_CONFIG_PATH");
+ if (spa_config_path_env != NULL)
+ spa_config_path = spa_config_path_env;
+
while ((c = getopt(argc, argv,
"bcdhilmMI:suCDRSAFLXx:evp:t:U:P")) != -1) {
switch (c) {
@@ -3728,8 +3739,23 @@ main(int argc, char **argv)
}
}
+ if (strpbrk(target, "/@") != NULL) {
+ size_t targetlen;
+
+ target_is_spa = B_FALSE;
+ /*
+ * Remove any trailing slash. Later code would get confused
+ * by it, but we want to allow it so that "pool/" can
+ * indicate that we want to dump the topmost filesystem,
+ * rather than the whole pool.
+ */
+ targetlen = strlen(target);
+ if (targetlen != 0 && target[targetlen - 1] == '/')
+ target[targetlen - 1] = '\0';
+ }
+
if (error == 0) {
- if (strpbrk(target, "/@") == NULL || dump_opt['R']) {
+ if (target_is_spa || dump_opt['R']) {
error = spa_open_rewind(target, &spa, FTAG, policy,
NULL);
if (error) {
diff --git a/contrib/blacklist/lib/bl.c b/contrib/blacklist/lib/bl.c
index bca52cf..3c3201d 100644
--- a/contrib/blacklist/lib/bl.c
+++ b/contrib/blacklist/lib/bl.c
@@ -152,8 +152,8 @@ bl_init(bl_t b, bool srv)
b->b_fd = socket(PF_LOCAL,
SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK|SOCK_NOSIGPIPE, 0);
if (b->b_fd == -1) {
- bl_log(b->b_fun, LOG_ERR, "%s: socket failed (%m)",
- __func__);
+ bl_log(b->b_fun, LOG_ERR, "%s: socket failed (%s)",
+ __func__, strerror(errno));
BL_UNLOCK(b);
return -1;
}
@@ -200,8 +200,8 @@ bl_init(bl_t b, bool srv)
*/
if (b->b_connected != 1) {
bl_log(b->b_fun, LOG_DEBUG,
- "%s: connect failed for `%s' (%m)",
- __func__, sun->sun_path);
+ "%s: connect failed for `%s' (%s)",
+ __func__, sun->sun_path, strerror(errno));
b->b_connected = 1;
}
BL_UNLOCK(b);
@@ -220,8 +220,8 @@ bl_init(bl_t b, bool srv)
errno = serrno;
if (rv == -1) {
bl_log(b->b_fun, LOG_ERR,
- "%s: bind failed for `%s' (%m)",
- __func__, sun->sun_path);
+ "%s: bind failed for `%s' (%s)",
+ __func__, sun->sun_path, strerror(errno));
goto out;
}
}
@@ -260,7 +260,8 @@ bl_init(bl_t b, bool srv)
if (setsockopt(b->b_fd, CRED_LEVEL, CRED_NAME,
&one, (socklen_t)sizeof(one)) == -1) {
bl_log(b->b_fun, LOG_ERR, "%s: setsockopt %s "
- "failed (%m)", __func__, __STRING(CRED_NAME));
+ "failed (%s)", __func__, __STRING(CRED_NAME),
+ strerror(errno));
goto out;
}
#endif
@@ -296,7 +297,8 @@ bl_create(bool srv, const char *path, void (*fun)(int, const char *, va_list))
return b;
out:
free(b);
- bl_log(fun, LOG_ERR, "%s: malloc failed (%m)", __func__);
+ bl_log(fun, LOG_ERR, "%s: malloc failed (%s)", __func__,
+ strerror(errno));
return NULL;
}
@@ -451,7 +453,8 @@ bl_recv(bl_t b)
rlen = recvmsg(b->b_fd, &msg, 0);
if (rlen == -1) {
- bl_log(b->b_fun, LOG_ERR, "%s: recvmsg failed (%m)", __func__);
+ bl_log(b->b_fun, LOG_ERR, "%s: recvmsg failed (%s)", __func__,
+ strerror(errno));
return NULL;
}
diff --git a/contrib/tcsh/glob.c b/contrib/tcsh/glob.c
index 3680403..48d3f90 100644
--- a/contrib/tcsh/glob.c
+++ b/contrib/tcsh/glob.c
@@ -142,12 +142,14 @@ globcharcoll(__Char c1, __Char c2, int cs)
c1 = towlower(c1);
c2 = towlower(c2);
} else {
+#ifndef __FreeBSD__
/* This should not be here, but I'll rather leave it in than engage in
a LC_COLLATE flamewar about a shell I don't use... */
if (iswlower(c1) && iswupper(c2))
return (1);
if (iswupper(c1) && iswlower(c2))
return (-1);
+#endif
}
s1[0] = c1;
s2[0] = c2;
diff --git a/lib/clang/clang.build.mk b/lib/clang/clang.build.mk
index a2ee0a5..ae068d2 100644
--- a/lib/clang/clang.build.mk
+++ b/lib/clang/clang.build.mk
@@ -8,7 +8,7 @@ CFLAGS+= -I${LLVM_SRCS}/include -I${CLANG_SRCS}/include \
-I${LLVM_SRCS}/${SRCDIR} ${INCDIR:C/^/-I${LLVM_SRCS}\//} -I. \
-I${LLVM_SRCS}/../../lib/clang/include \
-DLLVM_ON_UNIX -DLLVM_ON_FREEBSD \
- -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS #-DNDEBUG
+ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DNDEBUG
.if ${MK_CLANG_FULL} != "no"
CFLAGS+= -DCLANG_ENABLE_ARCMT \
diff --git a/lib/clang/freebsd_cc_version.h b/lib/clang/freebsd_cc_version.h
index 0f13792..74f8068 100644
--- a/lib/clang/freebsd_cc_version.h
+++ b/lib/clang/freebsd_cc_version.h
@@ -1,3 +1,3 @@
/* $FreeBSD$ */
-#define FREEBSD_CC_VERSION 1100004
+#define FREEBSD_CC_VERSION 1100500
diff --git a/lib/libc/gen/fnmatch.c b/lib/libc/gen/fnmatch.c
index 8cdcaf1..65efe20 100644
--- a/lib/libc/gen/fnmatch.c
+++ b/lib/libc/gen/fnmatch.c
@@ -296,8 +296,8 @@ rangematch(const char *pattern, wchar_t test, int flags, char **newp,
if (table->__collate_load_error ?
c <= test && test <= c2 :
- __wcollate_range_cmp(table, c, test) <= 0
- && __wcollate_range_cmp(table, test, c2) <= 0
+ __wcollate_range_cmp(c, test) <= 0
+ && __wcollate_range_cmp(test, c2) <= 0
)
ok = 1;
} else if (c == test)
diff --git a/lib/libc/gen/glob.3 b/lib/libc/gen/glob.3
index 468a73b..398c14b 100644
--- a/lib/libc/gen/glob.3
+++ b/lib/libc/gen/glob.3
@@ -275,24 +275,10 @@ is
.Pf non- Dv NULL ,
.Fn glob
calls
-.Fa \*(lp*errfunc\*(rp Ns ( Fa path , errno ) .
-This may be unintuitive: a pattern like
-.Ql */Makefile
-will try to
-.Xr stat 2
-.Ql foo/Makefile
-even if
-.Ql foo
-is not a directory, resulting in a
-call to
-.Fa errfunc .
-The error routine can suppress this action by testing for
-.Er ENOENT
-and
-.Er ENOTDIR ;
+.Fa \*(lp*errfunc\*(rp Ns ( Fa path , errno ) ,
however, the
.Dv GLOB_ERR
-flag will still cause an immediate
+flag will cause an immediate
return when this happens.
.Pp
If
@@ -377,7 +363,7 @@ file
.It Dv GLOB_NOSPACE
An attempt to allocate memory failed, or if
.Fa errno
-was 0
+was E2BIG,
.Dv GLOB_LIMIT
was specified in the flags and
.Fa pglob\->gl_matchc
diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c
index 62aa8ad..5df0b74 100644
--- a/lib/libc/gen/glob.c
+++ b/lib/libc/gen/glob.c
@@ -71,7 +71,7 @@ __FBSDID("$FreeBSD$");
* 1. Patterns with illegal byte sequences match nothing - even if
* GLOB_NOCHECK is specified.
* 2. Illegal byte sequences in filenames are handled by treating them as
- * single-byte characters with a value of the first byte of the sequence
+ * single-byte characters with a values of such bytes of the sequence
* cast to wchar_t.
* 3. State-dependent encodings are not currently supported.
*/
@@ -113,25 +113,20 @@ struct glob_limit {
size_t l_string_cnt;
};
-#define DOLLAR '$'
-#define DOT '.'
-#define EOS '\0'
-#define LBRACKET '['
-#define NOT '!'
-#define QUESTION '?'
-#define QUOTE '\\'
-#define RANGE '-'
-#define RBRACKET ']'
-#define SEP '/'
-#define STAR '*'
-#define TILDE '~'
-#define UNDERSCORE '_'
-#define LBRACE '{'
-#define RBRACE '}'
-#define SLASH '/'
-#define COMMA ','
-
-#ifndef DEBUG
+#define DOT L'.'
+#define EOS L'\0'
+#define LBRACKET L'['
+#define NOT L'!'
+#define QUESTION L'?'
+#define QUOTE L'\\'
+#define RANGE L'-'
+#define RBRACKET L']'
+#define SEP L'/'
+#define STAR L'*'
+#define TILDE L'~'
+#define LBRACE L'{'
+#define RBRACE L'}'
+#define COMMA L','
#define M_QUOTE 0x8000000000ULL
#define M_PROTECT 0x4000000000ULL
@@ -140,28 +135,19 @@ struct glob_limit {
typedef uint_fast64_t Char;
-#else
-
-#define M_QUOTE 0x80
-#define M_PROTECT 0x40
-#define M_MASK 0xff
-#define M_CHAR 0x7f
-
-typedef char Char;
-
-#endif
-
-
#define CHAR(c) ((Char)((c)&M_CHAR))
#define META(c) ((Char)((c)|M_QUOTE))
-#define M_ALL META('*')
-#define M_END META(']')
-#define M_NOT META('!')
-#define M_ONE META('?')
-#define M_RNG META('-')
-#define M_SET META('[')
+#define UNPROT(c) ((c) & ~M_PROTECT)
+#define M_ALL META(L'*')
+#define M_END META(L']')
+#define M_NOT META(L'!')
+#define M_ONE META(L'?')
+#define M_RNG META(L'-')
+#define M_SET META(L'[')
#define ismeta(c) (((c)&M_QUOTE) != 0)
-
+#ifdef DEBUG
+#define isprot(c) (((c)&M_PROTECT) != 0)
+#endif
static int compare(const void *, const void *);
static int g_Ctoc(const Char *, char *, size_t);
@@ -172,19 +158,27 @@ static const Char *g_strchr(const Char *, wchar_t);
static Char *g_strcat(Char *, const Char *);
#endif
static int g_stat(Char *, struct stat *, glob_t *);
-static int glob0(const Char *, glob_t *, struct glob_limit *);
+static int glob0(const Char *, glob_t *, struct glob_limit *,
+ const char *);
static int glob1(Char *, glob_t *, struct glob_limit *);
static int glob2(Char *, Char *, Char *, Char *, glob_t *,
struct glob_limit *);
static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *,
struct glob_limit *);
-static int globextend(const Char *, glob_t *, struct glob_limit *);
+static int globextend(const Char *, glob_t *, struct glob_limit *,
+ const char *);
static const Char *
globtilde(const Char *, Char *, size_t, glob_t *);
+static int globexp0(const Char *, glob_t *, struct glob_limit *,
+ const char *);
static int globexp1(const Char *, glob_t *, struct glob_limit *);
-static int globexp2(const Char *, const Char *, glob_t *, int *,
+static int globexp2(const Char *, const Char *, glob_t *,
struct glob_limit *);
+static int globfinal(glob_t *, struct glob_limit *, size_t,
+ const char *);
static int match(Char *, Char *, Char *);
+static int err_nomatch(glob_t *, struct glob_limit *, const char *);
+static int err_aborted(glob_t *, int, char *);
#ifdef DEBUG
static void qprintf(const char *, Char *);
#endif
@@ -199,6 +193,7 @@ glob(const char * __restrict pattern, int flags,
mbstate_t mbs;
wchar_t wc;
size_t clen;
+ int too_long;
patnext = pattern;
if (!(flags & GLOB_APPEND)) {
@@ -218,24 +213,27 @@ glob(const char * __restrict pattern, int flags,
bufnext = patbuf;
bufend = bufnext + MAXPATHLEN - 1;
+ too_long = 1;
if (flags & GLOB_NOESCAPE) {
memset(&mbs, 0, sizeof(mbs));
- while (bufend - bufnext >= MB_CUR_MAX) {
+ while (bufnext <= bufend) {
clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
if (clen == (size_t)-1 || clen == (size_t)-2)
- return (GLOB_NOMATCH);
- else if (clen == 0)
+ return (err_nomatch(pglob, &limit, pattern));
+ else if (clen == 0) {
+ too_long = 0;
break;
+ }
*bufnext++ = wc;
patnext += clen;
}
} else {
/* Protect the quoted characters. */
memset(&mbs, 0, sizeof(mbs));
- while (bufend - bufnext >= MB_CUR_MAX) {
- if (*patnext == QUOTE) {
- if (*++patnext == EOS) {
- *bufnext++ = QUOTE | M_PROTECT;
+ while (bufnext <= bufend) {
+ if (*patnext == '\\') {
+ if (*++patnext == '\0') {
+ *bufnext++ = QUOTE;
continue;
}
prot = M_PROTECT;
@@ -243,19 +241,47 @@ glob(const char * __restrict pattern, int flags,
prot = 0;
clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
if (clen == (size_t)-1 || clen == (size_t)-2)
- return (GLOB_NOMATCH);
- else if (clen == 0)
+ return (err_nomatch(pglob, &limit, pattern));
+ else if (clen == 0) {
+ too_long = 0;
break;
+ }
*bufnext++ = wc | prot;
patnext += clen;
}
}
+ if (too_long)
+ return (err_nomatch(pglob, &limit, pattern));
*bufnext = EOS;
if (flags & GLOB_BRACE)
- return (globexp1(patbuf, pglob, &limit));
+ return (globexp0(patbuf, pglob, &limit, pattern));
else
- return (glob0(patbuf, pglob, &limit));
+ return (glob0(patbuf, pglob, &limit, pattern));
+}
+
+static int
+globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat) {
+ int rv;
+ size_t oldpathc;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) {
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ return (glob0(pattern, pglob, limit, origpat));
+ }
+
+ oldpathc = pglob->gl_pathc;
+
+ if ((rv = globexp1(pattern, pglob, limit)) != 0)
+ return rv;
+
+ return (globfinal(pglob, limit, oldpathc, origpat));
}
/*
@@ -266,24 +292,18 @@ glob(const char * __restrict pattern, int flags,
static int
globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
{
- const Char* ptr = pattern;
- int rv;
+ const Char* ptr;
- if ((pglob->gl_flags & GLOB_LIMIT) &&
- limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
- errno = 0;
- return (GLOB_NOSPACE);
+ if ((ptr = g_strchr(pattern, LBRACE)) != NULL) {
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ return (globexp2(ptr, pattern, pglob, limit));
}
- /* Protect a single {}, for find(1), like csh */
- if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
- return glob0(pattern, pglob, limit);
-
- while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
- if (!globexp2(ptr, pattern, pglob, &rv, limit))
- return rv;
-
- return glob0(pattern, pglob, limit);
+ return (glob0(pattern, pglob, limit, NULL));
}
@@ -293,10 +313,10 @@ globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
* If it fails then it tries to glob the rest of the pattern and returns.
*/
static int
-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
struct glob_limit *limit)
{
- int i;
+ int i, rv;
Char *lm, *ls;
const Char *pe, *pm, *pm1, *pl;
Char patbuf[MAXPATHLEN];
@@ -308,7 +328,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
ls = lm;
/* Find the balanced brace */
- for (i = 0, pe = ++ptr; *pe; pe++)
+ for (i = 0, pe = ++ptr; *pe != EOS; pe++)
if (*pe == LBRACKET) {
/* Ignore everything between [] */
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
@@ -330,10 +350,8 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
}
/* Non matching braces; just glob the pattern */
- if (i != 0 || *pe == EOS) {
- *rv = glob0(patbuf, pglob, limit);
- return (0);
- }
+ if (i != 0 || *pe == EOS)
+ return (glob0(pattern, pglob, limit, NULL));
for (i = 0, pl = pm = ptr; pm <= pe; pm++)
switch (*pm) {
@@ -378,7 +396,9 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
#ifdef DEBUG
qprintf("globexp2:", patbuf);
#endif
- *rv = globexp1(patbuf, pglob, limit);
+ rv = globexp1(patbuf, pglob, limit);
+ if (rv)
+ return (rv);
/* move after the comma, to the next string */
pl = pm + 1;
@@ -388,7 +408,6 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
default:
break;
}
- *rv = 0;
return (0);
}
@@ -401,9 +420,15 @@ static const Char *
globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
{
struct passwd *pwd;
- char *h;
+ char *h, *sc;
const Char *p;
Char *b, *eb;
+ wchar_t wc;
+ wchar_t wbuf[MAXPATHLEN];
+ wchar_t *wbufend, *dc;
+ size_t clen;
+ mbstate_t mbs;
+ int too_long;
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
return (pattern);
@@ -412,13 +437,17 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
* Copy up to the end of the string or /
*/
eb = &patbuf[patbuf_len - 1];
- for (p = pattern + 1, h = (char *) patbuf;
- h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
+ for (p = pattern + 1, b = patbuf;
+ b < eb && *p != EOS && UNPROT(*p) != SEP; *b++ = *p++)
continue;
- *h = EOS;
+ if (*p != EOS && UNPROT(*p) != SEP)
+ return (NULL);
- if (((char *) patbuf)[0] == EOS) {
+ *b = EOS;
+ h = NULL;
+
+ if (patbuf[0] == EOS) {
/*
* handle a plain ~ or ~/ by expanding $HOME first (iff
* we're not running setuid or setgid) and then trying
@@ -438,20 +467,56 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
/*
* Expand a ~user
*/
- if ((pwd = getpwnam((char*) patbuf)) == NULL)
+ if (g_Ctoc(patbuf, (char *)wbuf, sizeof(wbuf)))
+ return (NULL);
+ if ((pwd = getpwnam((char *)wbuf)) == NULL)
return (pattern);
else
h = pwd->pw_dir;
}
/* Copy the home directory */
- for (b = patbuf; b < eb && *h; *b++ = *h++)
+ dc = wbuf;
+ sc = h;
+ wbufend = wbuf + MAXPATHLEN - 1;
+ too_long = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ while (dc <= wbufend) {
+ clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ /* XXX See initial comment #2. */
+ wc = (unsigned char)*sc;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if ((*dc++ = wc) == EOS) {
+ too_long = 0;
+ break;
+ }
+ sc += clen;
+ }
+ if (too_long)
+ return (NULL);
+
+ dc = wbuf;
+ for (b = patbuf; b < eb && *dc != EOS; *b++ = *dc++ | M_PROTECT)
continue;
+ if (*dc != EOS)
+ return (NULL);
/* Append the rest of the pattern */
- while (b < eb && (*b++ = *p++) != EOS)
- continue;
- *b = EOS;
+ if (*p != EOS) {
+ too_long = 1;
+ while (b <= eb) {
+ if ((*b++ = *p++) == EOS) {
+ too_long = 0;
+ break;
+ }
+ }
+ if (too_long)
+ return (NULL);
+ } else
+ *b = EOS;
return (patbuf);
}
@@ -464,14 +529,18 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
* if things went well, nonzero if errors occurred.
*/
static int
-glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
-{
+glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat) {
const Char *qpatnext;
int err;
size_t oldpathc;
Char *bufnext, c, patbuf[MAXPATHLEN];
qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
+ if (qpatnext == NULL) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
oldpathc = pglob->gl_pathc;
bufnext = patbuf;
@@ -530,30 +599,29 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
if ((err = glob1(patbuf, pglob, limit)) != 0)
return(err);
- /*
- * If there was no match we are going to append the pattern
- * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
- * and the pattern did not contain any magic characters
- * GLOB_NOMAGIC is there just for compatibility with csh.
- */
- if (pglob->gl_pathc == oldpathc) {
- if (((pglob->gl_flags & GLOB_NOCHECK) ||
- ((pglob->gl_flags & GLOB_NOMAGIC) &&
- !(pglob->gl_flags & GLOB_MAGCHAR))))
- return (globextend(pattern, pglob, limit));
- else
- return (GLOB_NOMATCH);
- }
+ if (origpat != NULL)
+ return (globfinal(pglob, limit, oldpathc, origpat));
+
+ return (0);
+}
+
+static int
+globfinal(glob_t *pglob, struct glob_limit *limit, size_t oldpathc,
+ const char *origpat) {
+ if (pglob->gl_pathc == oldpathc)
+ return (err_nomatch(pglob, limit, origpat));
+
if (!(pglob->gl_flags & GLOB_NOSORT))
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+
return (0);
}
static int
compare(const void *p, const void *q)
{
- return (strcmp(*(char **)p, *(char **)q));
+ return (strcoll(*(char **)p, *(char **)q));
}
static int
@@ -593,44 +661,47 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
if ((pglob->gl_flags & GLOB_LIMIT) &&
limit->l_stat_cnt++ >= GLOB_LIMIT_STAT) {
- errno = 0;
- if (pathend + 1 > pathend_last)
- return (GLOB_ABORTED);
- *pathend++ = SEP;
- *pathend = EOS;
+ errno = E2BIG;
return (GLOB_NOSPACE);
}
- if (((pglob->gl_flags & GLOB_MARK) &&
- pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
- || (S_ISLNK(sb.st_mode) &&
- (g_stat(pathbuf, &sb, pglob) == 0) &&
+ if ((pglob->gl_flags & GLOB_MARK) &&
+ UNPROT(pathend[-1]) != SEP &&
+ (S_ISDIR(sb.st_mode) ||
+ (S_ISLNK(sb.st_mode) &&
+ g_stat(pathbuf, &sb, pglob) == 0 &&
S_ISDIR(sb.st_mode)))) {
- if (pathend + 1 > pathend_last)
- return (GLOB_ABORTED);
+ if (pathend + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
*pathend++ = SEP;
*pathend = EOS;
}
++pglob->gl_matchc;
- return (globextend(pathbuf, pglob, limit));
+ return (globextend(pathbuf, pglob, limit, NULL));
}
/* Find end of next segment, copy tentatively to pathend. */
q = pathend;
p = pattern;
- while (*p != EOS && *p != SEP) {
+ while (*p != EOS && UNPROT(*p) != SEP) {
if (ismeta(*p))
anymeta = 1;
- if (q + 1 > pathend_last)
- return (GLOB_ABORTED);
+ if (q + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
*q++ = *p++;
}
if (!anymeta) { /* No expansion, do next segment. */
pathend = q;
pattern = p;
- while (*pattern == SEP) {
- if (pathend + 1 > pathend_last)
- return (GLOB_ABORTED);
+ while (UNPROT(*pattern) == SEP) {
+ if (pathend + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
*pathend++ = *pattern++;
}
} else /* Need expansion, recurse. */
@@ -647,26 +718,31 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
{
struct dirent *dp;
DIR *dirp;
- int err;
- char buf[MAXPATHLEN];
+ int err, too_long, saverrno, saverrno2;
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
struct dirent *(*readdirfunc)(DIR *);
- if (pathend > pathend_last)
- return (GLOB_ABORTED);
+ if (pathend > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
*pathend = EOS;
- errno = 0;
+ if (pglob->gl_errfunc != NULL &&
+ g_Ctoc(pathbuf, buf, sizeof(buf))) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ saverrno = errno;
+ errno = 0;
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
- /* TODO: don't call for ENOENT or ENOTDIR? */
- if (pglob->gl_errfunc) {
- if (g_Ctoc(pathbuf, buf, sizeof(buf)))
- return (GLOB_ABORTED);
- if (pglob->gl_errfunc(buf, errno) ||
- pglob->gl_flags & GLOB_ERR)
- return (GLOB_ABORTED);
- }
- return (0);
+ if (errno == ENOENT || errno == ENOTDIR)
+ return (0);
+ err = err_aborted(pglob, errno, buf);
+ if (errno == 0)
+ errno = saverrno;
+ return (err);
}
err = 0;
@@ -677,6 +753,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
else
readdirfunc = readdir;
+ errno = 0;
/* Search directory for matching names. */
while ((dp = (*readdirfunc)(dirp)) != NULL) {
char *sc;
@@ -687,49 +764,70 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
if ((pglob->gl_flags & GLOB_LIMIT) &&
limit->l_readdir_cnt++ >= GLOB_LIMIT_READDIR) {
- errno = 0;
- if (pathend + 1 > pathend_last)
- err = GLOB_ABORTED;
- else {
- *pathend++ = SEP;
- *pathend = EOS;
- err = GLOB_NOSPACE;
- }
+ errno = E2BIG;
+ err = GLOB_NOSPACE;
break;
}
/* Initial DOT must be matched literally. */
- if (dp->d_name[0] == DOT && *pattern != DOT)
+ if (dp->d_name[0] == '.' && UNPROT(*pattern) != DOT) {
+ errno = 0;
continue;
+ }
memset(&mbs, 0, sizeof(mbs));
dc = pathend;
sc = dp->d_name;
- while (dc < pathend_last) {
+ too_long = 1;
+ while (dc <= pathend_last) {
clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
if (clen == (size_t)-1 || clen == (size_t)-2) {
- wc = *sc;
+ /* XXX See initial comment #2. */
+ wc = (unsigned char)*sc;
clen = 1;
memset(&mbs, 0, sizeof(mbs));
}
- if ((*dc++ = wc) == EOS)
+ if ((*dc++ = wc) == EOS) {
+ too_long = 0;
break;
+ }
sc += clen;
}
- if (!match(pathend, pattern, restpattern)) {
+ if (too_long && (err = err_aborted(pglob, ENAMETOOLONG,
+ buf))) {
+ errno = ENAMETOOLONG;
+ break;
+ }
+ if (too_long || !match(pathend, pattern, restpattern)) {
*pathend = EOS;
+ errno = 0;
continue;
}
+ if (errno == 0)
+ errno = saverrno;
err = glob2(pathbuf, --dc, pathend_last, restpattern,
pglob, limit);
if (err)
break;
+ errno = 0;
}
+ saverrno2 = errno;
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
(*pglob->gl_closedir)(dirp);
else
closedir(dirp);
- return (err);
+ errno = saverrno2;
+
+ if (err)
+ return (err);
+
+ if (dp == NULL && errno != 0 &&
+ (err = err_aborted(pglob, errno, buf)))
+ return (err);
+
+ if (errno == 0)
+ errno = saverrno;
+ return (0);
}
@@ -748,7 +846,8 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
static int
-globextend(const Char *path, glob_t *pglob, struct glob_limit *limit)
+globextend(const Char *path, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat)
{
char **pathv;
size_t i, newsize, len;
@@ -757,7 +856,7 @@ globextend(const Char *path, glob_t *pglob, struct glob_limit *limit)
if ((pglob->gl_flags & GLOB_LIMIT) &&
pglob->gl_matchc > limit->l_path_lim) {
- errno = 0;
+ errno = E2BIG;
return (GLOB_NOSPACE);
}
@@ -775,18 +874,26 @@ globextend(const Char *path, glob_t *pglob, struct glob_limit *limit)
}
pglob->gl_pathv = pathv;
- for (p = path; *p++;)
- continue;
- len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */
- limit->l_string_cnt += len;
- if ((pglob->gl_flags & GLOB_LIMIT) &&
- limit->l_string_cnt >= GLOB_LIMIT_STRING) {
- errno = 0;
- return (GLOB_NOSPACE);
+ if (origpat != NULL)
+ copy = strdup(origpat);
+ else {
+ for (p = path; *p++ != EOS;)
+ continue;
+ len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */
+ if ((copy = malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len)) {
+ free(copy);
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ }
}
- if ((copy = malloc(len)) != NULL) {
- if (g_Ctoc(path, copy, len)) {
+ if (copy != NULL) {
+ limit->l_string_cnt += strlen(copy) + 1;
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_string_cnt >= GLOB_LIMIT_STRING) {
free(copy);
+ errno = E2BIG;
return (GLOB_NOSPACE);
}
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
@@ -826,15 +933,17 @@ match(Char *name, Char *pat, Char *patend)
ok = 0;
if ((k = *name++) == EOS)
return (0);
- if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != 0)
++pat;
while (((c = *pat++) & M_MASK) != M_END)
if ((*pat & M_MASK) == M_RNG) {
if (table->__collate_load_error ?
- CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
- __wcollate_range_cmp(table, CHAR(c), CHAR(k)) <= 0
- && __wcollate_range_cmp(table, CHAR(k), CHAR(pat[1])) <= 0
- )
+ CHAR(c) <= CHAR(k) &&
+ CHAR(k) <= CHAR(pat[1]) :
+ __wcollate_range_cmp(CHAR(c),
+ CHAR(k)) <= 0 &&
+ __wcollate_range_cmp(CHAR(k),
+ CHAR(pat[1])) <= 0)
ok = 1;
pat += 2;
} else if (c == k)
@@ -871,13 +980,15 @@ globfree(glob_t *pglob)
static DIR *
g_opendir(Char *str, glob_t *pglob)
{
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
- if (!*str)
+ if (*str == EOS)
strcpy(buf, ".");
else {
- if (g_Ctoc(str, buf, sizeof(buf)))
+ if (g_Ctoc(str, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
return (NULL);
+ }
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
@@ -889,7 +1000,7 @@ g_opendir(Char *str, glob_t *pglob)
static int
g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
{
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
if (g_Ctoc(fn, buf, sizeof(buf))) {
errno = ENAMETOOLONG;
@@ -903,7 +1014,7 @@ g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
static int
g_stat(Char *fn, struct stat *sb, glob_t *pglob)
{
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
if (g_Ctoc(fn, buf, sizeof(buf))) {
errno = ENAMETOOLONG;
@@ -933,10 +1044,14 @@ g_Ctoc(const Char *str, char *buf, size_t len)
memset(&mbs, 0, sizeof(mbs));
while (len >= MB_CUR_MAX) {
- clen = wcrtomb(buf, *str, &mbs);
- if (clen == (size_t)-1)
- return (1);
- if (*str == L'\0')
+ clen = wcrtomb(buf, CHAR(*str), &mbs);
+ if (clen == (size_t)-1) {
+ /* XXX See initial comment #2. */
+ *buf = (char)CHAR(*str);
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if (CHAR(*str) == EOS)
return (0);
str++;
buf += clen;
@@ -945,21 +1060,46 @@ g_Ctoc(const Char *str, char *buf, size_t len)
return (1);
}
+static int
+err_nomatch(glob_t *pglob, struct glob_limit *limit, const char *origpat) {
+ /*
+ * If there was no match we are going to append the origpat
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the origpat did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR)))
+ return (globextend(NULL, pglob, limit, origpat));
+ return (GLOB_NOMATCH);
+}
+
+static int
+err_aborted(glob_t *pglob, int err, char *buf) {
+ if ((pglob->gl_errfunc != NULL && pglob->gl_errfunc(buf, err)) ||
+ (pglob->gl_flags & GLOB_ERR))
+ return (GLOB_ABORTED);
+ return (0);
+}
+
#ifdef DEBUG
static void
qprintf(const char *str, Char *s)
{
Char *p;
- (void)printf("%s:\n", str);
- for (p = s; *p; p++)
- (void)printf("%c", CHAR(*p));
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", ismeta(*p) ? '_' : ' ');
- (void)printf("\n");
+ (void)printf("%s\n", str);
+ if (s != NULL) {
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (char)CHAR(*p));
+ (void)printf("\n");
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (isprot(*p) ? '\\' : ' '));
+ (void)printf("\n");
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (ismeta(*p) ? '_' : ' '));
+ (void)printf("\n");
+ }
}
#endif
diff --git a/lib/libc/locale/collate.h b/lib/libc/locale/collate.h
index 3253d9c..c8968c6 100644
--- a/lib/libc/locale/collate.h
+++ b/lib/libc/locale/collate.h
@@ -128,8 +128,8 @@ int __collate_load_tables(const char *);
int __collate_equiv_value(locale_t, const wchar_t *, size_t);
void _collate_lookup(struct xlocale_collate *,const wchar_t *, int *, int *,
int, const int **);
-int __collate_range_cmp(struct xlocale_collate *, char, char);
-int __wcollate_range_cmp(struct xlocale_collate *, wchar_t, wchar_t);
+int __collate_range_cmp(char, char);
+int __wcollate_range_cmp(wchar_t, wchar_t);
size_t _collate_wxfrm(struct xlocale_collate *, const wchar_t *, wchar_t *,
size_t);
size_t _collate_sxfrm(struct xlocale_collate *, const wchar_t *, char *,
diff --git a/lib/libc/locale/collcmp.c b/lib/libc/locale/collcmp.c
index b90c379..ce71a71 100644
--- a/lib/libc/locale/collcmp.c
+++ b/lib/libc/locale/collcmp.c
@@ -34,14 +34,13 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <wchar.h>
-#include <xlocale.h>
#include "collate.h"
/*
* Compare two characters using collate
*/
-int __collate_range_cmp(struct xlocale_collate *table, char c1, char c2)
+int __collate_range_cmp(char c1, char c2)
{
char s1[2], s2[2];
@@ -49,12 +48,10 @@ int __collate_range_cmp(struct xlocale_collate *table, char c1, char c2)
s1[1] = '\0';
s2[0] = c2;
s2[1] = '\0';
- struct _xlocale l = {{0}};
- l.components[XLC_COLLATE] = (struct xlocale_component *)table;
- return (strcoll_l(s1, s2, &l));
+ return (strcoll(s1, s2));
}
-int __wcollate_range_cmp(struct xlocale_collate *table, wchar_t c1, wchar_t c2)
+int __wcollate_range_cmp(wchar_t c1, wchar_t c2)
{
wchar_t s1[2], s2[2];
@@ -62,7 +59,5 @@ int __wcollate_range_cmp(struct xlocale_collate *table, wchar_t c1, wchar_t c2)
s1[1] = L'\0';
s2[0] = c2;
s2[1] = L'\0';
- struct _xlocale l = {{0}};
- l.components[XLC_COLLATE] = (struct xlocale_component *)table;
- return (wcscoll_l(s1, s2, &l));
+ return (wcscoll(s1, s2));
}
diff --git a/lib/libc/regex/regcomp.c b/lib/libc/regex/regcomp.c
index 5333233..b2b1255 100644
--- a/lib/libc/regex/regcomp.c
+++ b/lib/libc/regex/regcomp.c
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$");
#include <limits.h>
#include <stdlib.h>
#include <regex.h>
-#include <runetype.h>
#include <wchar.h>
#include <wctype.h>
@@ -817,14 +816,14 @@ p_b_term(struct parse *p, cset *cs)
if (start == finish)
CHadd(p, cs, start);
else {
- if (table->__collate_load_error) {
- (void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE);
+ if (table->__collate_load_error || MB_CUR_MAX > 1) {
+ (void)REQUIRE(start <= finish, REG_ERANGE);
CHaddrange(p, cs, start, finish);
} else {
- (void)REQUIRE(__wcollate_range_cmp(table, start, finish) <= 0, REG_ERANGE);
+ (void)REQUIRE(__wcollate_range_cmp(start, finish) <= 0, REG_ERANGE);
for (i = 0; i <= UCHAR_MAX; i++) {
- if ( __wcollate_range_cmp(table, start, i) <= 0
- && __wcollate_range_cmp(table, i, finish) <= 0
+ if ( __wcollate_range_cmp(start, i) <= 0
+ && __wcollate_range_cmp(i, finish) <= 0
)
CHadd(p, cs, i);
}
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index e09a5b2..e49a9e1 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -873,7 +873,7 @@ doswitch:
n = *fmt;
if (n == ']'
|| (table->__collate_load_error ? n < c :
- __wcollate_range_cmp(table, n, c) < 0
+ __collate_range_cmp(n, c) < 0
)
) {
c = '-';
@@ -887,8 +887,8 @@ doswitch:
} while (c < n);
} else {
for (i = 0; i < 256; i ++)
- if (__wcollate_range_cmp(table, c, i) < 0 &&
- __wcollate_range_cmp(table, i, n) <= 0
+ if (__collate_range_cmp(c, i) <= 0 &&
+ __collate_range_cmp(i, n) <= 0
)
tab[i] = v;
}
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
index 10ad660..14ce6dd 100644
--- a/lib/libc/sys/ptrace.2
+++ b/lib/libc/sys/ptrace.2
@@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
-.Dd December 29, 2015
+.Dd July 28, 2016
.Dt PTRACE 2
.Os
.Sh NAME
@@ -58,8 +58,9 @@ The signal may be a normal process signal, generated as a result of
traced process behavior, or use of the
.Xr kill 2
system call; alternatively, it may be generated by the tracing facility
-as a result of attaching, system calls, or stepping by the tracing
-process.
+as a result of attaching, stepping by the tracing
+process,
+or an event in the traced process.
The tracing process may choose to intercept the signal, using it to
observe process behavior (such as
.Dv SIGTRAP ) ,
@@ -69,6 +70,121 @@ The
system call
is the mechanism by which all this happens.
.Pp
+A traced process may report additional signal stops corresponding to
+events in the traced process.
+These additional signal stops are reported as
+.Dv SIGTRAP
+or
+.Dv SIGSTOP
+signals.
+The tracing process can use the
+.Dv PT_LWPINFO
+request to determine which events are associated with a
+.Dv SIGTRAP
+or
+.Dv SIGSTOP
+signal.
+Note that multiple events may be associated with a single signal.
+For example, events indicated by the
+.Dv PL_FLAG_BORN ,
+.Dv PL_FLAG_FORKED ,
+and
+.Dv PL_FLAG_EXEC
+flags are also reported as a system call exit event
+.Pq Dv PL_FLAG_SCX .
+The signal stop for a new child process enabled via
+.Dv PTRACE_FORK
+will report a
+.Dv SIGSTOP
+signal.
+All other additional signal stops use
+.Dv SIGTRAP .
+.Pp
+Each traced process has a tracing event mask.
+An event in the traced process only reports a
+signal stop if the corresponding flag is set in the tracing event mask.
+The current set of tracing event flags include:
+.Bl -tag -width ".Dv PTRACE_SYSCALL"
+.It Dv PTRACE_EXEC
+Report a stop for a successful invocation of
+.Xr execve 2 .
+This event is indicated by the
+.Dv PL_FLAG_EXEC
+flag in the
+.Va pl_flags
+member of
+.Vt "struct ptrace_lwpinfo" .
+.It Dv PTRACE_SCE
+Report a stop on each system call entry.
+This event is indicated by the
+.Dv PL_FLAG_SCE
+flag in the
+.Va pl_flags
+member of
+.Vt "struct ptrace_lwpinfo" .
+.It Dv PTRACE_SCX
+Report a stop on each system call exit.
+This event is indicated by the
+.Dv PL_FLAG_SCX
+flag in the
+.Va pl_flags
+member of
+.Vt "struct ptrace_lwpinfo" .
+.It Dv PTRACE_SYSCALL
+Report stops for both system call entry and exit.
+.It Dv PTRACE_FORK
+This event flag controls tracing for new child processes of a traced process.
+.Pp
+When this event flag is enabled,
+new child processes will enable tracing and stop before executing their
+first instruction.
+The new child process will include the
+.Dv PL_FLAG_CHILD
+flag in the
+.Va pl_flags
+member of
+.Vt "struct ptrace_lwpinfo" .
+The traced process will report a stop that includes the
+.Dv PL_FLAG_FORKED
+flag.
+The process ID of the new child process will also be present in the
+.Va pl_child_pid
+member of
+.Vt "struct ptrace_lwpinfo" .
+Note that new child processes will be attached with the default
+tracing event mask;
+they do not inherit the event mask of the traced process.
+.Pp
+When this event flag is not enabled,
+new child processes will execute without tracing enabled.
+.It Dv PTRACE_LWP
+This event flag controls tracing of LWP
+.Pq kernel thread
+creation and destruction.
+When this event is enabled,
+new LWPs will stop and report an event with
+.Dv PL_FLAG_BORN
+set before executing their first instruction,
+and exiting LWPs will stop and report an event with
+.Dv PL_FLAG_EXITED
+set before completing their termination.
+.Pp
+Note that new processes do not report an event for the creation of their
+initial thread,
+and exiting processes do not report an event for the termination of the
+last thread.
+.El
+.Pp
+The default tracing event mask when attaching to a process via
+.Dv PT_ATTACH ,
+.Dv PT_TRACE_ME ,
+or
+.Dv PTRACE_FORK
+includes only
+.Dv PTRACE_EXEC
+events.
+All other event flags are disabled.
+.Pp
The
.Fa request
argument specifies what operation is being performed; the meaning of
@@ -368,21 +484,20 @@ The process identifier of the new process is available in the
member of
.Vt "struct ptrace_lwpinfo" .
.It PL_FLAG_CHILD
-The flag is set for first event reported from a new child, which is
-automatically attached due to
-.Dv PT_FOLLOW_FORK
-enabled.
+The flag is set for first event reported from a new child which is
+automatically attached when
+.Dv PTRACE_FORK
+is enabled.
.It PL_FLAG_BORN
-This flag is set for the first event reported from a new LWP when LWP
-events are enabled via
-.Dv PT_LWP_EVENTS .
+This flag is set for the first event reported from a new LWP when
+.Dv PTRACE_LWP
+is enabled.
It is reported along with
-.Dv PL_FLAG_SCX
-and is always reported if LWP events are enabled.
+.Dv PL_FLAG_SCX .
.It PL_FLAG_EXITED
This flag is set for the last event reported by an exiting LWP when
-LWP events are enabled via
-.Dv PT_LWP_EVENTS .
+.Dv PTRACE_LWP
+is enabled.
Note that this event is not reported when the last LWP in a process exits.
The termination of the last thread is reported via a normal process exit
event.
@@ -456,50 +571,72 @@ This request will suspend the specified thread.
.It PT_RESUME
This request will resume the specified thread.
.It PT_TO_SCE
-This request will trace the specified process on each system call entry.
+This request will set the
+.Dv PTRACE_SCE
+event flag to trace all future system call entries and continue the process.
+The
+.Fa addr
+and
+.Fa data
+arguments are used the same as for
+.Dv PT_CONTINUE.
.It PT_TO_SCX
-This request will trace the specified process on each system call exit.
+This request will set the
+.Dv PTRACE_SCX
+event flag to trace all future system call exits and continue the process.
+The
+.Fa addr
+and
+.Fa data
+arguments are used the same as for
+.Dv PT_CONTINUE.
.It PT_SYSCALL
-This request will trace the specified process
-on each system call entry and exit.
+This request will set the
+.Dv PTRACE_SYSCALL
+event flag to trace all future system call entries and exits and continue
+the process.
+The
+.Fa addr
+and
+.Fa data
+arguments are used the same as for
+.Dv PT_CONTINUE.
.It PT_FOLLOW_FORK
This request controls tracing for new child processes of a traced process.
If
.Fa data
is non-zero,
-then new child processes will enable tracing and stop before executing their
-first instruction.
+.Dv PTRACE_FORK
+is set in the traced process's event tracing mask.
If
.Fa data
-is zero, then new child processes will execute without tracing enabled.
-By default, tracing is not enabled for new child processes.
-Child processes do not inherit this property.
-The traced process will set the
-.Dv PL_FLAG_FORKED
-flag upon exit from a system call that creates a new process.
+is zero,
+.Dv PTRACE_FORK
+is cleared from the traced process's event tracing mask.
.It PT_LWP_EVENTS
This request controls tracing of LWP creation and destruction.
If
.Fa data
is non-zero,
-then LWPs will stop to report creation and destruction events.
+.Dv PTRACE_LWP
+is set in the traced process's event tracing mask.
If
.Fa data
is zero,
-then LWP creation and destruction events will not be reported.
-By default, tracing is not enabled for LWP events.
-Child processes do not inherit this property.
-New LWPs will stop to report an event with
-.Dv PL_FLAG_BORN
-set before executing their first instruction.
-Exiting LWPs will stop to report an event with
-.Dv PL_FLAG_EXITED
-set before completing their termination.
-.Pp
-Note that new processes do not report an event for the creation of their
-initial thread,
-and exiting processes do not report an event for the termination of the
-last thread.
+.Dv PTRACE_LWP
+is cleared from the traced process's event tracing mask.
+.It PT_GET_EVENT_MASK
+This request reads the traced process's event tracing mask into the
+integer pointed to by
+.Fa addr .
+The size of the integer must be passed in
+.Fa data .
+.It PT_SET_EVENT_MASK
+This request sets the traced process's event tracing mask from the
+integer pointed to by
+.Fa addr .
+The size of the integer must be passed in
+.Fa data .
.It PT_VM_TIMESTAMP
This request returns the generation number or timestamp of the memory map of
the traced process as the return value from
diff --git a/release/release.sh b/release/release.sh
index 07485c9..8216239 100755
--- a/release/release.sh
+++ b/release/release.sh
@@ -287,9 +287,15 @@ extra_chroot_setup() {
fi
if [ ! -z "${EMBEDDEDPORTS}" ]; then
+ _OSVERSION=$(chroot ${CHROOTDIR} /usr/bin/uname -U)
+ REVISION=$(chroot ${CHROOTDIR} make -C /usr/src/release -V REVISION)
+ BRANCH=$(chroot ${CHROOTDIR} make -C /usr/src/release -V BRANCH)
+ PBUILD_FLAGS="OSVERSION=${_OSVERSION} BATCH=yes"
+ PBUILD_FLAGS="${PBUILD_FLAGS} UNAME_r=${UNAME_r}"
+ PBUILD_FLAGS="${PBUILD_FLAGS} OSREL=${REVISION}"
for _PORT in ${EMBEDDEDPORTS}; do
eval chroot ${CHROOTDIR} make -C /usr/ports/${_PORT} \
- BATCH=1 FORCE_PKG_REGISTER=1 install clean distclean
+ FORCE_PKG_REGISTER=1 ${PBUILD_FLAGS} install clean distclean
done
fi
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index f64c2be..42b020a 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -1575,7 +1575,7 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
break;
case O_NAT:
- if (cmd->arg1 != 0)
+ if (cmd->arg1 != IP_FW_NAT44_GLOBAL)
bprint_uint_arg(bp, "nat ", cmd->arg1);
else
bprintf(bp, "nat global");
@@ -3733,7 +3733,7 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
action->len = F_INSN_SIZE(ipfw_insn_nat);
CHECK_ACTLEN;
if (*av != NULL && _substrcmp(*av, "global") == 0) {
- action->arg1 = 0;
+ action->arg1 = IP_FW_NAT44_GLOBAL;
av++;
break;
} else
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 17c96db..dcfddfc 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -3674,8 +3674,8 @@ tos : STRING {
else if ($1[0] == '0' && $1[1] == 'x')
$$ = strtoul($1, NULL, 16);
else
- $$ = 0; /* flag bad argument */
- if (!$$ || $$ > 255) {
+ $$ = 256; /* flag bad argument */
+ if ($$ < 0 || $$ > 255) {
yyerror("illegal tos value %s", $1);
free($1);
YYERROR;
@@ -3684,7 +3684,7 @@ tos : STRING {
}
| NUMBER {
$$ = $1;
- if (!$$ || $$ > 255) {
+ if ($$ < 0 || $$ > 255) {
yyerror("illegal tos value %s", $1);
YYERROR;
}
diff --git a/sbin/route/route.c b/sbin/route/route.c
index a357a4d..ee312a4 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <paths.h>
+#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -144,6 +145,16 @@ static int fiboptlist_range(const char *, struct fibl_head_t *);
static void usage(const char *) __dead2;
+#define READ_TIMEOUT 10
+static volatile sig_atomic_t stop_read;
+
+static void
+stopit(int sig __unused)
+{
+
+ stop_read = 1;
+}
+
static void
usage(const char *cp)
{
@@ -776,6 +787,7 @@ set_metric(char *value, int key)
static void
newroute(int argc, char **argv)
{
+ struct sigaction sa;
struct hostent *hp;
struct fibl *fl;
char *cmd;
@@ -791,6 +803,12 @@ newroute(int argc, char **argv)
hp = NULL;
TAILQ_INIT(&fibl_head);
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = stopit;
+ if (sigaction(SIGALRM, &sa, 0) == -1)
+ warn("sigaction SIGALRM");
+
cmd = argv[0];
if (*cmd != 'g' && *cmd != 's')
shutdown(s, SHUT_RD); /* Don't want to read back our messages */
@@ -1541,9 +1559,17 @@ rtmsg(int cmd, int flags, int fib)
return (-1);
}
if (cmd == RTM_GET) {
+ stop_read = 0;
+ alarm(READ_TIMEOUT);
do {
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
- } while (l > 0 && (rtm.rtm_seq != rtm_seq || rtm.rtm_pid != pid));
+ } while (l > 0 && stop_read == 0 &&
+ (rtm.rtm_seq != rtm_seq || rtm.rtm_pid != pid));
+ if (stop_read != 0) {
+ warnx("read from routing socket timed out");
+ return (-1);
+ } else
+ alarm(0);
if (l < 0)
warn("read from routing socket");
else
diff --git a/share/mk/bsd.README b/share/mk/bsd.README
index fb5948e..210e600 100644
--- a/share/mk/bsd.README
+++ b/share/mk/bsd.README
@@ -331,6 +331,7 @@ PROGS_CXX PROG and PROGS_CXX in one Makefile. To define
- DEBUG_FLAGS
- DPADD
- DPSRCS
+ - INTERNALPROG (no installation)
- LDADD
- LDFLAGS
- LIBADD
diff --git a/share/mk/bsd.progs.mk b/share/mk/bsd.progs.mk
index d26ba76..3254bda 100644
--- a/share/mk/bsd.progs.mk
+++ b/share/mk/bsd.progs.mk
@@ -24,8 +24,8 @@ PROGS += ${PROGS_CXX}
# just one of many
PROG_OVERRIDE_VARS += BINDIR BINGRP BINOWN BINMODE DPSRCS MAN NO_WERROR \
PROGNAME SRCS STRIP WARNS
-PROG_VARS += CFLAGS CXXFLAGS DEBUG_FLAGS DPADD LDADD LIBADD LINKS \
- LDFLAGS MLINKS ${PROG_OVERRIDE_VARS}
+PROG_VARS += CFLAGS CXXFLAGS DEBUG_FLAGS DPADD INTERNALPROG LDADD LIBADD \
+ LINKS LDFLAGS MLINKS ${PROG_OVERRIDE_VARS}
.for v in ${PROG_VARS:O:u}
.if empty(${PROG_OVERRIDE_VARS:M$v})
.if defined(${v}.${PROG})
diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c
index d0811a2..305d0bf 100644
--- a/sys/amd64/amd64/initcpu.c
+++ b/sys/amd64/amd64/initcpu.c
@@ -94,6 +94,20 @@ init_amd(void)
wrmsr(MSR_NB_CFG1, msr);
}
}
+
+ /*
+ * BIOS may configure Family 10h processors to convert WC+ cache type
+ * to CD. That can hurt performance of guest VMs using nested paging.
+ * The relevant MSR bit is not documented in the BKDG,
+ * the fix is borrowed from Linux.
+ */
+ if (CPUID_TO_FAMILY(cpu_id) == 0x10) {
+ if ((cpu_feature2 & CPUID2_HV) == 0) {
+ msr = rdmsr(0xc001102a);
+ msr &= ~((uint64_t)1 << 24);
+ wrmsr(0xc001102a, msr);
+ }
+ }
}
/*
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index c418532..6062bfd 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -561,9 +561,9 @@ pmap_delayed_invl_wait(vm_page_t m)
* block to complete before proceeding.
*
* The function works by setting the DI generation number for m's PV
- * list to at least * the number for the current thread. This forces
- * a caller to pmap_delayed_invl_wait() to spin until current thread
- * calls pmap_delayed_invl_finished().
+ * list to at least the DI generation number of the current thread.
+ * This forces a caller of pmap_delayed_invl_wait() to block until
+ * current thread calls pmap_delayed_invl_finished().
*/
static void
pmap_delayed_invl_page(vm_page_t m)
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 1b85b32..04c5dcc 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -443,8 +443,8 @@ trap(struct trapframe *frame)
goto out;
case T_DNA:
- KASSERT(!PCB_USER_FPU(td->td_pcb),
- ("Unregistered use of FPU in kernel"));
+ if (PCB_USER_FPU(td->td_pcb))
+ panic("Unregistered use of FPU in kernel");
fpudna();
goto out;
diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c
index d088152..fe9a050 100644
--- a/sys/arm/allwinner/a10_gpio.c
+++ b/sys/arm/allwinner/a10_gpio.c
@@ -708,4 +708,4 @@ static driver_t a10_gpio_driver = {
};
EARLY_DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0,
- BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
diff --git a/sys/arm/allwinner/aw_nmi.c b/sys/arm/allwinner/aw_nmi.c
index a8b4598..a49b9c7 100644
--- a/sys/arm/allwinner/aw_nmi.c
+++ b/sys/arm/allwinner/aw_nmi.c
@@ -400,4 +400,4 @@ static driver_t aw_nmi_driver = {
static devclass_t aw_nmi_devclass;
EARLY_DRIVER_MODULE(aw_nmi, simplebus, aw_nmi_driver,
- aw_nmi_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);
+ aw_nmi_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
diff --git a/sys/arm/allwinner/axp209.c b/sys/arm/allwinner/axp209.c
index 7cb41e5..2283fe3 100644
--- a/sys/arm/allwinner/axp209.c
+++ b/sys/arm/allwinner/axp209.c
@@ -707,10 +707,10 @@ extern devclass_t ofwgpiobus_devclass, gpioc_devclass;
extern driver_t ofw_gpiobus_driver, gpioc_driver;
EARLY_DRIVER_MODULE(axp209, iicbus, axp209_driver, axp209_devclass,
- 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
+ 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
EARLY_DRIVER_MODULE(ofw_gpiobus, axp209_pmu, ofw_gpiobus_driver,
- ofwgpiobus_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
-EARLY_DRIVER_MODULE(gpioc, axp209_pmu, gpioc_driver, gpioc_devclass,
- 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
+ ofwgpiobus_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
+DRIVER_MODULE(gpioc, axp209_pmu, gpioc_driver, gpioc_devclass,
+ 0, 0);
MODULE_VERSION(axp209, 1);
MODULE_DEPEND(axp209, iicbus, 1, 1, 1);
diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c
index 1de9424..1f8466d 100644
--- a/sys/arm64/arm64/vm_machdep.c
+++ b/sys/arm64/arm64/vm_machdep.c
@@ -201,6 +201,8 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
pcb = td->td_pcb;
pcb->pcb_tpidr_el0 = (register_t)tls_base;
+ if (td == curthread)
+ WRITE_SPECIALREG(tpidr_el0, tls_base);
return (0);
}
diff --git a/sys/boot/fdt/dts/arm/pcduino3b.dts b/sys/boot/fdt/dts/arm/pcduino3.dts
index 9072baa..9072baa 100644
--- a/sys/boot/fdt/dts/arm/pcduino3b.dts
+++ b/sys/boot/fdt/dts/arm/pcduino3.dts
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 31a8c65..c889e92 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2014 by Saso Kiselkov. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
@@ -784,6 +784,7 @@ typedef struct arc_write_callback arc_write_callback_t;
struct arc_write_callback {
void *awcb_private;
arc_done_func_t *awcb_ready;
+ arc_done_func_t *awcb_children_ready;
arc_done_func_t *awcb_physdone;
arc_done_func_t *awcb_done;
arc_buf_t *awcb_buf;
@@ -5106,6 +5107,15 @@ arc_write_ready(zio_t *zio)
hdr->b_flags |= ARC_FLAG_IO_IN_PROGRESS;
}
+static void
+arc_write_children_ready(zio_t *zio)
+{
+ arc_write_callback_t *callback = zio->io_private;
+ arc_buf_t *buf = callback->awcb_buf;
+
+ callback->awcb_children_ready(zio, buf, callback->awcb_private);
+}
+
/*
* The SPA calls this callback for each physical write that happens on behalf
* of a logical write. See the comment in dbuf_write_physdone() for details.
@@ -5202,7 +5212,8 @@ arc_write_done(zio_t *zio)
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,
+ const zio_prop_t *zp, arc_done_func_t *ready,
+ arc_done_func_t *children_ready, arc_done_func_t *physdone,
arc_done_func_t *done, void *private, zio_priority_t priority,
int zio_flags, const zbookmark_phys_t *zb)
{
@@ -5222,13 +5233,16 @@ arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
hdr->b_flags |= ARC_FLAG_L2COMPRESS;
callback = kmem_zalloc(sizeof (arc_write_callback_t), KM_SLEEP);
callback->awcb_ready = ready;
+ callback->awcb_children_ready = children_ready;
callback->awcb_physdone = physdone;
callback->awcb_done = done;
callback->awcb_private = private;
callback->awcb_buf = buf;
zio = zio_write(pio, spa, txg, bp, buf->b_data, hdr->b_size, zp,
- arc_write_ready, arc_write_physdone, arc_write_done, callback,
+ arc_write_ready,
+ (children_ready != NULL) ? arc_write_children_ready : NULL,
+ arc_write_physdone, arc_write_done, callback,
priority, zio_flags, zb);
return (zio);
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 bf194a5..56c93d3 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
@@ -486,13 +486,49 @@ dbuf_verify(dmu_buf_impl_t *db)
* If the blkptr isn't set but they have nonzero data,
* it had better be dirty, otherwise we'll lose that
* data when we evict this buffer.
+ *
+ * There is an exception to this rule for indirect blocks; in
+ * this case, if the indirect block is a hole, we fill in a few
+ * fields on each of the child blocks (importantly, birth time)
+ * to prevent hole birth times from being lost when you
+ * partially fill in a hole.
*/
if (db->db_dirtycnt == 0) {
- uint64_t *buf = db->db.db_data;
- int i;
+ if (db->db_level == 0) {
+ uint64_t *buf = db->db.db_data;
+ int i;
- for (i = 0; i < db->db.db_size >> 3; i++) {
- ASSERT(buf[i] == 0);
+ for (i = 0; i < db->db.db_size >> 3; i++) {
+ ASSERT(buf[i] == 0);
+ }
+ } else {
+ blkptr_t *bps = db->db.db_data;
+ ASSERT3U(1 << DB_DNODE(db)->dn_indblkshift, ==,
+ db->db.db_size);
+ /*
+ * We want to verify that all the blkptrs in the
+ * indirect block are holes, but we may have
+ * automatically set up a few fields for them.
+ * We iterate through each blkptr and verify
+ * they only have those fields set.
+ */
+ for (int i = 0;
+ i < db->db.db_size / sizeof (blkptr_t);
+ i++) {
+ blkptr_t *bp = &bps[i];
+ ASSERT(ZIO_CHECKSUM_IS_ZERO(
+ &bp->blk_cksum));
+ ASSERT(
+ DVA_IS_EMPTY(&bp->blk_dva[0]) &&
+ DVA_IS_EMPTY(&bp->blk_dva[1]) &&
+ DVA_IS_EMPTY(&bp->blk_dva[2]));
+ ASSERT0(bp->blk_fill);
+ ASSERT0(bp->blk_pad[0]);
+ ASSERT0(bp->blk_pad[1]);
+ ASSERT(!BP_IS_EMBEDDED(bp));
+ ASSERT(BP_IS_HOLE(bp));
+ ASSERT0(bp->blk_phys_birth);
+ }
}
}
}
@@ -660,10 +696,31 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
BP_IS_HOLE(db->db_blkptr)))) {
arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db);
- DB_DNODE_EXIT(db);
dbuf_set_data(db, arc_buf_alloc(db->db_objset->os_spa,
db->db.db_size, db, type));
bzero(db->db.db_data, db->db.db_size);
+
+ if (db->db_blkptr != NULL && db->db_level > 0 &&
+ BP_IS_HOLE(db->db_blkptr) &&
+ db->db_blkptr->blk_birth != 0) {
+ blkptr_t *bps = db->db.db_data;
+ for (int i = 0; i < ((1 <<
+ DB_DNODE(db)->dn_indblkshift) / sizeof (blkptr_t));
+ i++) {
+ blkptr_t *bp = &bps[i];
+ ASSERT3U(BP_GET_LSIZE(db->db_blkptr), ==,
+ 1 << dn->dn_indblkshift);
+ BP_SET_LSIZE(bp,
+ BP_GET_LEVEL(db->db_blkptr) == 1 ?
+ dn->dn_datablksz :
+ BP_GET_LSIZE(db->db_blkptr));
+ BP_SET_TYPE(bp, BP_GET_TYPE(db->db_blkptr));
+ BP_SET_LEVEL(bp,
+ BP_GET_LEVEL(db->db_blkptr) - 1);
+ BP_SET_BIRTH(bp, db->db_blkptr->blk_birth, 0);
+ }
+ }
+ DB_DNODE_EXIT(db);
db->db_state = DB_CACHED;
mutex_exit(&db->db_mtx);
return;
@@ -2883,7 +2940,8 @@ dbuf_write_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
uint64_t fill = 0;
int i;
- ASSERT3P(db->db_blkptr, ==, bp);
+ ASSERT3P(db->db_blkptr, !=, NULL);
+ ASSERT3P(&db->db_data_pending->dr_bp_copy, ==, bp);
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
@@ -2905,7 +2963,7 @@ dbuf_write_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
#ifdef ZFS_DEBUG
if (db->db_blkid == DMU_SPILL_BLKID) {
ASSERT(dn->dn_phys->dn_flags & DNODE_FLAG_SPILL_BLKPTR);
- ASSERT(!(BP_IS_HOLE(db->db_blkptr)) &&
+ ASSERT(!(BP_IS_HOLE(bp)) &&
db->db_blkptr == &dn->dn_phys->dn_spill);
}
#endif
@@ -2946,6 +3004,49 @@ dbuf_write_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
bp->blk_fill = fill;
mutex_exit(&db->db_mtx);
+
+ rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
+ *db->db_blkptr = *bp;
+ rw_exit(&dn->dn_struct_rwlock);
+}
+
+/* ARGSUSED */
+/*
+ * This function gets called just prior to running through the compression
+ * stage of the zio pipeline. If we're an indirect block comprised of only
+ * holes, then we want this indirect to be compressed away to a hole. In
+ * order to do that we must zero out any information about the holes that
+ * this indirect points to prior to before we try to compress it.
+ */
+static void
+dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
+{
+ dmu_buf_impl_t *db = vdb;
+ dnode_t *dn;
+ blkptr_t *bp;
+ uint64_t i;
+ int epbs;
+
+ ASSERT3U(db->db_level, >, 0);
+ DB_DNODE_ENTER(db);
+ dn = DB_DNODE(db);
+ epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
+
+ /* Determine if all our children are holes */
+ for (i = 0, bp = db->db.db_data; i < 1 << epbs; i++, bp++) {
+ if (!BP_IS_HOLE(bp))
+ break;
+ }
+
+ /*
+ * If all the children are holes, then zero them all out so that
+ * we may get compressed away.
+ */
+ if (i == 1 << epbs) {
+ /* didn't find any non-holes */
+ bzero(db->db.db_data, db->db.db_size);
+ }
+ DB_DNODE_EXIT(db);
}
/*
@@ -3124,6 +3225,8 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
zio_t *zio;
int wp_flag = 0;
+ ASSERT(dmu_tx_is_syncing(tx));
+
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
os = dn->dn_objset;
@@ -3182,6 +3285,14 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
dmu_write_policy(os, dn, db->db_level, wp_flag, &zp);
DB_DNODE_EXIT(db);
+ /*
+ * We copy the blkptr now (rather than when we instantiate the dirty
+ * record), because its value can change between open context and
+ * syncing context. We do not need to hold dn_struct_rwlock to read
+ * db_blkptr because we are in syncing context.
+ */
+ dr->dr_bp_copy = *db->db_blkptr;
+
if (db->db_level == 0 &&
dr->dt.dl.dr_override_state == DR_OVERRIDDEN) {
/*
@@ -3191,8 +3302,9 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
void *contents = (data != NULL) ? data->b_data : NULL;
dr->dr_zio = zio_write(zio, os->os_spa, txg,
- db->db_blkptr, contents, db->db.db_size, &zp,
- dbuf_write_override_ready, NULL, dbuf_write_override_done,
+ &dr->dr_bp_copy, contents, db->db.db_size, &zp,
+ dbuf_write_override_ready, NULL, NULL,
+ dbuf_write_override_done,
dr, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
mutex_enter(&db->db_mtx);
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
@@ -3203,15 +3315,27 @@ dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
ASSERT(zp.zp_checksum == ZIO_CHECKSUM_OFF ||
zp.zp_checksum == ZIO_CHECKSUM_NOPARITY);
dr->dr_zio = zio_write(zio, os->os_spa, txg,
- db->db_blkptr, NULL, db->db.db_size, &zp,
- dbuf_write_nofill_ready, NULL, dbuf_write_nofill_done, db,
+ &dr->dr_bp_copy, NULL, db->db.db_size, &zp,
+ dbuf_write_nofill_ready, NULL, NULL,
+ dbuf_write_nofill_done, db,
ZIO_PRIORITY_ASYNC_WRITE,
ZIO_FLAG_MUSTSUCCEED | ZIO_FLAG_NODATA, &zb);
} else {
ASSERT(arc_released(data));
+
+ /*
+ * For indirect blocks, we want to setup the children
+ * ready callback so that we can properly handle an indirect
+ * block that only contains holes.
+ */
+ arc_done_func_t *children_ready_cb = NULL;
+ if (db->db_level != 0)
+ children_ready_cb = dbuf_write_children_ready;
+
dr->dr_zio = arc_write(zio, os->os_spa, txg,
- db->db_blkptr, data, DBUF_IS_L2CACHEABLE(db),
+ &dr->dr_bp_copy, data, DBUF_IS_L2CACHEABLE(db),
DBUF_IS_L2COMPRESSIBLE(db), &zp, dbuf_write_ready,
+ children_ready_cb,
dbuf_write_physdone, dbuf_write_done, db,
ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
index bb81879..e5dae5d 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
*/
/* Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */
/* Copyright (c) 2013, Joyent, Inc. All rights reserved. */
@@ -1607,10 +1607,11 @@ dmu_sync_late_arrival(zio_t *pio, objset_t *os, dmu_sync_cb_t *done, zgd_t *zgd,
dsa->dsa_zgd = zgd;
dsa->dsa_tx = tx;
- zio_nowait(zio_write(pio, os->os_spa, dmu_tx_get_txg(tx), zgd->zgd_bp,
- zgd->zgd_db->db_data, zgd->zgd_db->db_size, zp,
- dmu_sync_late_arrival_ready, NULL, dmu_sync_late_arrival_done, dsa,
- ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, zb));
+ zio_nowait(zio_write(pio, os->os_spa, dmu_tx_get_txg(tx),
+ zgd->zgd_bp, zgd->zgd_db->db_data, zgd->zgd_db->db_size,
+ zp, dmu_sync_late_arrival_ready, NULL,
+ NULL, dmu_sync_late_arrival_done, dsa, ZIO_PRIORITY_SYNC_WRITE,
+ ZIO_FLAG_CANFAIL, zb));
return (0);
}
@@ -1763,8 +1764,8 @@ dmu_sync(zio_t *pio, uint64_t txg, dmu_sync_cb_t *done, zgd_t *zgd)
zio_nowait(arc_write(pio, os->os_spa, txg,
bp, dr->dt.dl.dr_data, DBUF_IS_L2CACHEABLE(db),
DBUF_IS_L2COMPRESSIBLE(db), &zp, dmu_sync_ready,
- NULL, dmu_sync_done, dsa, ZIO_PRIORITY_SYNC_WRITE,
- ZIO_FLAG_CANFAIL, &zb));
+ NULL, NULL, dmu_sync_done, dsa,
+ ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, &zb));
return (0);
}
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 367dbcb..82c5854 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
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
@@ -1116,9 +1116,9 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
zio = arc_write(pio, os->os_spa, tx->tx_txg,
os->os_rootbp, os->os_phys_buf, DMU_OS_IS_L2CACHEABLE(os),
- DMU_OS_IS_L2COMPRESSIBLE(os), &zp, dmu_objset_write_ready,
- NULL, dmu_objset_write_done, os, ZIO_PRIORITY_ASYNC_WRITE,
- ZIO_FLAG_MUSTSUCCEED, &zb);
+ DMU_OS_IS_L2COMPRESSIBLE(os),
+ &zp, dmu_objset_write_ready, NULL, NULL, dmu_objset_write_done,
+ os, ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
/*
* Sync special dnodes - the parent IO for the sync is the root block
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
index 9aee513..7179c41 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
*/
@@ -60,20 +60,14 @@ dnode_increase_indirection(dnode_t *dn, dmu_tx_t *tx)
dprintf("os=%p obj=%llu, increase to %d\n", dn->dn_objset,
dn->dn_object, dn->dn_phys->dn_nlevels);
- /* check for existing blkptrs in the dnode */
- for (i = 0; i < nblkptr; i++)
- if (!BP_IS_HOLE(&dn->dn_phys->dn_blkptr[i]))
- break;
- if (i != nblkptr) {
- /* transfer dnode's block pointers to new indirect block */
- (void) dbuf_read(db, NULL, DB_RF_MUST_SUCCEED|DB_RF_HAVESTRUCT);
- ASSERT(db->db.db_data);
- ASSERT(arc_released(db->db_buf));
- ASSERT3U(sizeof (blkptr_t) * nblkptr, <=, db->db.db_size);
- bcopy(dn->dn_phys->dn_blkptr, db->db.db_data,
- sizeof (blkptr_t) * nblkptr);
- arc_buf_freeze(db->db_buf);
- }
+ /* transfer dnode's block pointers to new indirect block */
+ (void) dbuf_read(db, NULL, DB_RF_MUST_SUCCEED|DB_RF_HAVESTRUCT);
+ ASSERT(db->db.db_data);
+ ASSERT(arc_released(db->db_buf));
+ ASSERT3U(sizeof (blkptr_t) * nblkptr, <=, db->db.db_size);
+ bcopy(dn->dn_phys->dn_blkptr, db->db.db_data,
+ sizeof (blkptr_t) * nblkptr);
+ arc_buf_freeze(db->db_buf);
/* set dbuf's parent pointers to new indirect buf */
for (i = 0; i < nblkptr; i++) {
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 d56bd13..f6408c8 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
@@ -56,7 +56,8 @@ typedef int (scan_cb_t)(dsl_pool_t *, const blkptr_t *,
static scan_cb_t dsl_scan_scrub_cb;
static void dsl_scan_cancel_sync(void *, dmu_tx_t *);
-static void dsl_scan_sync_state(dsl_scan_t *, dmu_tx_t *tx);
+static void dsl_scan_sync_state(dsl_scan_t *, dmu_tx_t *);
+static boolean_t dsl_scan_restarting(dsl_scan_t *, dmu_tx_t *);
unsigned int zfs_top_maxinflight = 32; /* maximum I/Os per top-level */
unsigned int zfs_resilver_delay = 2; /* number of ticks to delay resilver */
@@ -320,8 +321,15 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
else
scn->scn_phys.scn_state = DSS_CANCELED;
- spa_history_log_internal(spa, "scan done", tx,
- "complete=%u", complete);
+ if (dsl_scan_restarting(scn, tx))
+ spa_history_log_internal(spa, "scan aborted, restarting", tx,
+ "errors=%llu", spa_get_errlog_size(spa));
+ else if (!complete)
+ spa_history_log_internal(spa, "scan cancelled", tx,
+ "errors=%llu", spa_get_errlog_size(spa));
+ else
+ spa_history_log_internal(spa, "scan done", tx,
+ "errors=%llu", spa_get_errlog_size(spa));
if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
mutex_enter(&spa->spa_scrub_lock);
@@ -1476,8 +1484,7 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
* that we can restart an old-style scan while the pool is being
* imported (see dsl_scan_init).
*/
- if (scn->scn_restart_txg != 0 &&
- scn->scn_restart_txg <= tx->tx_txg) {
+ if (dsl_scan_restarting(scn, tx)) {
pool_scan_func_t func = POOL_SCAN_SCRUB;
dsl_scan_done(scn, B_FALSE, tx);
if (vdev_resilver_needed(spa->spa_root_vdev, NULL, NULL))
@@ -1904,3 +1911,10 @@ dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
return (dsl_sync_task(spa_name(spa), dsl_scan_setup_check,
dsl_scan_setup_sync, &func, 0, ZFS_SPACE_CHECK_NONE));
}
+
+static boolean_t
+dsl_scan_restarting(dsl_scan_t *scn, dmu_tx_t *tx)
+{
+ return (scn->scn_restart_txg != 0 &&
+ scn->scn_restart_txg <= tx->tx_txg);
+}
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 04a80f7..714c528 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
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
@@ -141,9 +141,11 @@ int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
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,
- arc_done_func_t *done, void *priv, zio_priority_t priority,
- int zio_flags, const zbookmark_phys_t *zb);
+ const zio_prop_t *zp,
+ arc_done_func_t *ready, arc_done_func_t *child_ready,
+ arc_done_func_t *physdone, arc_done_func_t *done,
+ void *priv, zio_priority_t priority, int zio_flags,
+ const zbookmark_phys_t *zb);
void arc_freed(spa_t *spa, const blkptr_t *bp);
void arc_set_callback(arc_buf_t *buf, arc_evict_func_t *func, void *priv);
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 233d541..4964126 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
@@ -121,6 +121,9 @@ typedef struct dbuf_dirty_record {
/* How much space was changed to dsl_pool_dirty_space() for this? */
unsigned int dr_accounted;
+ /* A copy of the bp that points to us */
+ blkptr_t dr_bp_copy;
+
union dirty_types {
struct dirty_indirect {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
index bda9afa..7517e04 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
@@ -436,6 +436,7 @@ struct zio {
/* Callback info */
zio_done_func_t *io_ready;
+ zio_done_func_t *io_children_ready;
zio_done_func_t *io_physdone;
zio_done_func_t *io_done;
void *io_private;
@@ -503,9 +504,10 @@ extern zio_t *zio_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, void *data,
extern zio_t *zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
void *data, uint64_t size, const zio_prop_t *zp,
- zio_done_func_t *ready, zio_done_func_t *physdone, zio_done_func_t *done,
- void *priv,
- zio_priority_t priority, enum zio_flag flags, const zbookmark_phys_t *zb);
+ zio_done_func_t *ready, zio_done_func_t *children_ready,
+ zio_done_func_t *physdone, zio_done_func_t *done,
+ void *priv, zio_priority_t priority, enum zio_flag flags,
+ const zbookmark_phys_t *zb);
extern zio_t *zio_rewrite(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
void *data, uint64_t size, zio_done_func_t *done, void *priv,
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 5302a22..4693542 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
@@ -2244,6 +2244,7 @@ zfs_rmdir(vnode_t *dvp, vnode_t *vp, char *name, cred_t *cr)
dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
zfs_sa_upgrade_txholds(tx, zp);
zfs_sa_upgrade_txholds(tx, dzp);
+ dmu_tx_mark_netfree(tx);
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
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 9f1a98b..0b4f7d8 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
*/
@@ -766,9 +766,10 @@ zio_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
zio_t *
zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
void *data, uint64_t size, const zio_prop_t *zp,
- zio_done_func_t *ready, zio_done_func_t *physdone, zio_done_func_t *done,
- void *private,
- zio_priority_t priority, enum zio_flag flags, const zbookmark_phys_t *zb)
+ zio_done_func_t *ready, zio_done_func_t *children_ready,
+ zio_done_func_t *physdone, zio_done_func_t *done,
+ void *private, zio_priority_t priority, enum zio_flag flags,
+ const zbookmark_phys_t *zb)
{
zio_t *zio;
@@ -787,6 +788,7 @@ zio_write(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
ZIO_DDT_CHILD_WRITE_PIPELINE : ZIO_WRITE_PIPELINE);
zio->io_ready = ready;
+ zio->io_children_ready = children_ready;
zio->io_physdone = physdone;
zio->io_prop = *zp;
@@ -1184,6 +1186,16 @@ zio_write_bp_init(zio_t *zio)
if (!IO_IS_ALLOCATING(zio))
return (ZIO_PIPELINE_CONTINUE);
+ if (zio->io_children_ready != NULL) {
+ /*
+ * Now that all our children are ready, run the callback
+ * associated with this zio in case it wants to modify the
+ * data to be written.
+ */
+ ASSERT3U(zp->zp_level, >, 0);
+ zio->io_children_ready(zio);
+ }
+
ASSERT(zio->io_child_type != ZIO_CHILD_DDT);
if (zio->io_bp_override) {
@@ -2113,9 +2125,9 @@ zio_write_gang_block(zio_t *pio)
zio_nowait(zio_write(zio, spa, txg, &gbh->zg_blkptr[g],
(char *)pio->io_data + (pio->io_size - resid), lsize, &zp,
- zio_write_gang_member_ready, NULL, NULL, &gn->gn_child[g],
- pio->io_priority, ZIO_GANG_CHILD_FLAGS(pio),
- &pio->io_bookmark));
+ zio_write_gang_member_ready, NULL, NULL, NULL,
+ &gn->gn_child[g], pio->io_priority,
+ ZIO_GANG_CHILD_FLAGS(pio), &pio->io_bookmark));
}
/*
@@ -2504,7 +2516,7 @@ zio_ddt_write(zio_t *zio)
dio = zio_write(zio, spa, txg, bp, zio->io_orig_data,
zio->io_orig_size, &czp, NULL, NULL,
- zio_ddt_ditto_write_done, dde, zio->io_priority,
+ NULL, zio_ddt_ditto_write_done, dde, zio->io_priority,
ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark);
zio_push_transform(dio, zio->io_data, zio->io_size, 0, NULL);
@@ -2525,7 +2537,8 @@ zio_ddt_write(zio_t *zio)
ddt_phys_addref(ddp);
} else {
cio = zio_write(zio, spa, txg, bp, zio->io_orig_data,
- zio->io_orig_size, zp, zio_ddt_child_write_ready, NULL,
+ zio->io_orig_size, zp,
+ zio_ddt_child_write_ready, NULL, NULL,
zio_ddt_child_write_done, dde, zio->io_priority,
ZIO_DDT_CHILD_FLAGS(zio), &zio->io_bookmark);
diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c
index e832389..329801d 100644
--- a/sys/dev/bxe/bxe.c
+++ b/sys/dev/bxe/bxe.c
@@ -5624,7 +5624,8 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
if (!sc->link_vars.link_up ||
(if_getdrvflags(ifp) &
(IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) {
- rc = drbr_enqueue(ifp, tx_br, m);
+ if (m != NULL)
+ rc = drbr_enqueue(ifp, tx_br, m);
goto bxe_tx_mq_start_locked_exit;
}
diff --git a/sys/dev/mlx5/mlx5_en/en.h b/sys/dev/mlx5/mlx5_en/en.h
index e894a3f..0ed0a0e 100644
--- a/sys/dev/mlx5/mlx5_en/en.h
+++ b/sys/dev/mlx5/mlx5_en/en.h
@@ -59,10 +59,6 @@
#include <machine/bus.h>
-#ifdef HAVE_TURBO_LRO
-#include "tcp_tlro.h"
-#endif
-
#include <dev/mlx5/driver.h>
#include <dev/mlx5/qp.h>
#include <dev/mlx5/cq.h>
@@ -460,11 +456,7 @@ struct mlx5e_rq {
struct ifnet *ifp;
struct mlx5e_rq_stats stats;
struct mlx5e_cq cq;
-#ifdef HAVE_TURBO_LRO
- struct tlro_ctrl lro;
-#else
struct lro_ctrl lro;
-#endif
volatile int enabled;
int ix;
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
index 4a8029b..2136567 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c
@@ -666,10 +666,15 @@ mlx5e_create_rq(struct mlx5e_channel *c,
}
wq_sz = mlx5_wq_ll_get_size(&rq->wq);
+
+ err = -tcp_lro_init_args(&rq->lro, c->ifp, TCP_LRO_ENTRIES, wq_sz);
+ if (err)
+ goto err_rq_wq_destroy;
+
rq->mbuf = malloc(wq_sz * sizeof(rq->mbuf[0]), M_MLX5EN, M_WAITOK | M_ZERO);
if (rq->mbuf == NULL) {
err = -ENOMEM;
- goto err_rq_wq_destroy;
+ goto err_lro_init;
}
for (i = 0; i != wq_sz; i++) {
struct mlx5e_rx_wqe *wqe = mlx5_wq_ll_get_wqe(&rq->wq, i);
@@ -694,20 +699,12 @@ mlx5e_create_rq(struct mlx5e_channel *c,
mlx5e_create_stats(&rq->stats.ctx, SYSCTL_CHILDREN(priv->sysctl_ifnet),
buffer, mlx5e_rq_stats_desc, MLX5E_RQ_STATS_NUM,
rq->stats.arg);
-
-#ifdef HAVE_TURBO_LRO
- if (tcp_tlro_init(&rq->lro, c->ifp, MLX5E_BUDGET_MAX) != 0)
- rq->lro.mbuf = NULL;
-#else
- if (tcp_lro_init(&rq->lro))
- rq->lro.lro_cnt = 0;
- else
- rq->lro.ifp = c->ifp;
-#endif
return (0);
err_rq_mbuf_free:
free(rq->mbuf, M_MLX5EN);
+err_lro_init:
+ tcp_lro_free(&rq->lro);
err_rq_wq_destroy:
mlx5_wq_destroy(&rq->wq_ctrl);
err_free_dma_tag:
@@ -726,11 +723,8 @@ mlx5e_destroy_rq(struct mlx5e_rq *rq)
sysctl_ctx_free(&rq->stats.ctx);
/* free leftover LRO packets, if any */
-#ifdef HAVE_TURBO_LRO
- tcp_tlro_free(&rq->lro);
-#else
tcp_lro_free(&rq->lro);
-#endif
+
wq_sz = mlx5_wq_ll_get_size(&rq->wq);
for (i = 0; i != wq_sz; i++) {
if (rq->mbuf[i].mbuf != NULL) {
@@ -3114,6 +3108,13 @@ mlx5e_destroy_ifp(struct mlx5_core_dev *mdev, void *vpriv)
/* don't allow more IOCTLs */
priv->gone = 1;
+ /*
+ * Clear the device description to avoid use after free,
+ * because the bsddev is not destroyed when this module is
+ * unloaded:
+ */
+ device_set_desc(mdev->pdev->dev.bsddev, NULL);
+
/* XXX wait a bit to allow IOCTL handlers to complete */
pause("W", hz);
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
index 6bc2c17..5c79347 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
@@ -369,15 +369,9 @@ mlx5e_poll_rx_cq(struct mlx5e_rq *rq, int budget)
mlx5e_build_rx_mbuf(cqe, rq, mb, byte_cnt);
rq->stats.packets++;
-#ifdef HAVE_TURBO_LRO
- if (mb->m_pkthdr.csum_flags == 0 ||
- (rq->ifp->if_capenable & IFCAP_LRO) == 0 ||
- rq->lro.mbuf == NULL) {
- /* normal input */
- rq->ifp->if_input(rq->ifp, mb);
- } else {
- tcp_tlro_rx(&rq->lro, mb);
- }
+
+#if !defined(HAVE_TCP_LRO_RX)
+ tcp_lro_queue_mbuf(&rq->lro, mb);
#else
if (mb->m_pkthdr.csum_flags == 0 ||
(rq->ifp->if_capenable & IFCAP_LRO) == 0 ||
@@ -395,9 +389,6 @@ wq_ll_pop:
/* ensure cq space is freed before enabling more cqes */
wmb();
-#ifndef HAVE_TURBO_LRO
- tcp_lro_flush_all(&rq->lro);
-#endif
return (i);
}
@@ -437,8 +428,6 @@ mlx5e_rx_cq_comp(struct mlx5_core_cq *mcq)
}
mlx5e_post_rx_wqes(rq);
mlx5e_cq_arm(&rq->cq);
-#ifdef HAVE_TURBO_LRO
- tcp_tlro_flush(&rq->lro, 1);
-#endif
+ tcp_lro_flush_all(&rq->lro);
mtx_unlock(&rq->mtx);
}
diff --git a/sys/dev/mlx5/mlx5_en/tcp_tlro.c b/sys/dev/mlx5/mlx5_en/tcp_tlro.c
deleted file mode 100644
index 4b81904..0000000
--- a/sys/dev/mlx5/mlx5_en/tcp_tlro.c
+++ /dev/null
@@ -1,697 +0,0 @@
-/*-
- * Copyright (c) 2015 Mellanox Technologies. 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 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 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 <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/libkern.h>
-#include <sys/mbuf.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/sysctl.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/endian.h>
-#include <sys/socket.h>
-#include <sys/sockopt.h>
-#include <sys/smp.h>
-
-#include <net/if.h>
-#include <net/if_var.h>
-#include <net/ethernet.h>
-
-#if defined(INET) || defined(INET6)
-#include <netinet/in.h>
-#endif
-
-#ifdef INET
-#include <netinet/ip.h>
-#endif
-
-#ifdef INET6
-#include <netinet/ip6.h>
-#endif
-
-#include <netinet/tcp_var.h>
-
-#include "tcp_tlro.h"
-
-#ifndef M_HASHTYPE_LRO_TCP
-#ifndef KLD_MODULE
-#warning "M_HASHTYPE_LRO_TCP is not defined"
-#endif
-#define M_HASHTYPE_LRO_TCP 254
-#endif
-
-static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, tlro,
- CTLFLAG_RW, 0, "TCP turbo LRO parameters");
-
-static MALLOC_DEFINE(M_TLRO, "TLRO", "Turbo LRO");
-
-static int tlro_min_rate = 20; /* Hz */
-
-SYSCTL_INT(_net_inet_tcp_tlro, OID_AUTO, min_rate, CTLFLAG_RWTUN,
- &tlro_min_rate, 0, "Minimum serving rate in Hz");
-
-static int tlro_max_packet = IP_MAXPACKET;
-
-SYSCTL_INT(_net_inet_tcp_tlro, OID_AUTO, max_packet, CTLFLAG_RWTUN,
- &tlro_max_packet, 0, "Maximum packet size in bytes");
-
-typedef struct {
- uint32_t value;
-} __packed uint32_p_t;
-
-static uint16_t
-tcp_tlro_csum(const uint32_p_t *p, size_t l)
-{
- const uint32_p_t *pend = p + (l / 4);
- uint64_t cs;
-
- for (cs = 0; p != pend; p++)
- cs += le32toh(p->value);
- while (cs > 0xffff)
- cs = (cs >> 16) + (cs & 0xffff);
- return (cs);
-}
-
-static void *
-tcp_tlro_get_header(const struct mbuf *m, const u_int off,
- const u_int len)
-{
- if (m->m_len < (off + len))
- return (NULL);
- return (mtod(m, char *) + off);
-}
-
-static uint8_t
-tcp_tlro_info_save_timestamp(struct tlro_mbuf_data *pinfo)
-{
- struct tcphdr *tcp = pinfo->tcp;
- uint32_t *ts_ptr;
-
- if (tcp->th_off < ((TCPOLEN_TSTAMP_APPA + sizeof(*tcp)) >> 2))
- return (0);
-
- ts_ptr = (uint32_t *)(tcp + 1);
- if (*ts_ptr != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
- return (0);
-
- /* Save timestamps */
- pinfo->tcp_ts = ts_ptr[1];
- pinfo->tcp_ts_reply = ts_ptr[2];
- return (1);
-}
-
-static void
-tcp_tlro_info_restore_timestamp(struct tlro_mbuf_data *pinfoa,
- struct tlro_mbuf_data *pinfob)
-{
- struct tcphdr *tcp = pinfoa->tcp;
- uint32_t *ts_ptr;
-
- if (tcp->th_off < ((TCPOLEN_TSTAMP_APPA + sizeof(*tcp)) >> 2))
- return;
-
- ts_ptr = (uint32_t *)(tcp + 1);
- if (*ts_ptr != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
- return;
-
- /* Restore timestamps */
- ts_ptr[1] = pinfob->tcp_ts;
- ts_ptr[2] = pinfob->tcp_ts_reply;
-}
-
-static void
-tcp_tlro_extract_header(struct tlro_mbuf_data *pinfo, struct mbuf *m, int seq)
-{
- uint8_t *phdr = (uint8_t *)pinfo->buf;
- struct ether_header *eh;
- struct ether_vlan_header *vlan;
-#ifdef INET
- struct ip *ip;
-#endif
-#ifdef INET6
- struct ip6_hdr *ip6;
-#endif
- struct tcphdr *tcp;
- uint16_t etype;
- int diff;
- int off;
-
- /* Fill in information */
- pinfo->head = m;
- pinfo->last_tick = ticks;
- pinfo->sequence = seq;
- pinfo->pprev = &m_last(m)->m_next;
-
- off = sizeof(*eh);
- if (m->m_len < off)
- goto error;
- eh = tcp_tlro_get_header(m, 0, sizeof(*eh));
- if (eh == NULL)
- goto error;
- memcpy(phdr, &eh->ether_dhost, ETHER_ADDR_LEN);
- phdr += ETHER_ADDR_LEN;
- memcpy(phdr, &eh->ether_type, sizeof(eh->ether_type));
- phdr += sizeof(eh->ether_type);
- etype = ntohs(eh->ether_type);
-
- if (etype == ETHERTYPE_VLAN) {
- vlan = tcp_tlro_get_header(m, off, sizeof(*vlan));
- if (vlan == NULL)
- goto error;
- memcpy(phdr, &vlan->evl_tag, sizeof(vlan->evl_tag) +
- sizeof(vlan->evl_proto));
- phdr += sizeof(vlan->evl_tag) + sizeof(vlan->evl_proto);
- etype = ntohs(vlan->evl_proto);
- off += sizeof(*vlan) - sizeof(*eh);
- }
- switch (etype) {
-#ifdef INET
- case ETHERTYPE_IP:
- /*
- * Cannot LRO:
- * - Non-IP packets
- * - Fragmented packets
- * - Packets with IPv4 options
- * - Non-TCP packets
- */
- ip = tcp_tlro_get_header(m, off, sizeof(*ip));
- if (ip == NULL ||
- (ip->ip_off & htons(IP_MF | IP_OFFMASK)) != 0 ||
- (ip->ip_p != IPPROTO_TCP) ||
- (ip->ip_hl << 2) != sizeof(*ip))
- goto error;
-
- /* Legacy IP has a header checksum that needs to be correct */
- if (!(m->m_pkthdr.csum_flags & CSUM_IP_CHECKED)) {
- /* Verify IP header */
- if (tcp_tlro_csum((uint32_p_t *)ip, sizeof(*ip)) != 0xFFFF)
- m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
- else
- m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED |
- CSUM_IP_VALID;
- }
- /* Only accept valid checksums */
- if (!(m->m_pkthdr.csum_flags & CSUM_IP_VALID) ||
- !(m->m_pkthdr.csum_flags & CSUM_DATA_VALID))
- goto error;
- memcpy(phdr, &ip->ip_src, sizeof(ip->ip_src) +
- sizeof(ip->ip_dst));
- phdr += sizeof(ip->ip_src) + sizeof(ip->ip_dst);
- if (M_HASHTYPE_GET(m) == M_HASHTYPE_LRO_TCP)
- pinfo->ip_len = m->m_pkthdr.len - off;
- else
- pinfo->ip_len = ntohs(ip->ip_len);
- pinfo->ip_hdrlen = sizeof(*ip);
- pinfo->ip.v4 = ip;
- pinfo->ip_version = 4;
- off += sizeof(*ip);
- break;
-#endif
-#ifdef INET6
- case ETHERTYPE_IPV6:
- /*
- * Cannot LRO:
- * - Non-IP packets
- * - Packets with IPv6 options
- * - Non-TCP packets
- */
- ip6 = tcp_tlro_get_header(m, off, sizeof(*ip6));
- if (ip6 == NULL || ip6->ip6_nxt != IPPROTO_TCP)
- goto error;
- if (!(m->m_pkthdr.csum_flags & CSUM_DATA_VALID))
- goto error;
- memcpy(phdr, &ip6->ip6_src, sizeof(struct in6_addr) +
- sizeof(struct in6_addr));
- phdr += sizeof(struct in6_addr) + sizeof(struct in6_addr);
- if (M_HASHTYPE_GET(m) == M_HASHTYPE_LRO_TCP)
- pinfo->ip_len = m->m_pkthdr.len - off;
- else
- pinfo->ip_len = ntohs(ip6->ip6_plen) + sizeof(*ip6);
- pinfo->ip_hdrlen = sizeof(*ip6);
- pinfo->ip.v6 = ip6;
- pinfo->ip_version = 6;
- off += sizeof(*ip6);
- break;
-#endif
- default:
- goto error;
- }
- tcp = tcp_tlro_get_header(m, off, sizeof(*tcp));
- if (tcp == NULL)
- goto error;
- memcpy(phdr, &tcp->th_sport, sizeof(tcp->th_sport) +
- sizeof(tcp->th_dport));
- phdr += sizeof(tcp->th_sport) +
- sizeof(tcp->th_dport);
- /* Store TCP header length */
- *phdr++ = tcp->th_off;
- if (tcp->th_off < (sizeof(*tcp) >> 2))
- goto error;
-
- /* Compute offset to data payload */
- pinfo->tcp_len = (tcp->th_off << 2);
- off += pinfo->tcp_len;
-
- /* Store more info */
- pinfo->data_off = off;
- pinfo->tcp = tcp;
-
- /* Try to save timestamp, if any */
- *phdr++ = tcp_tlro_info_save_timestamp(pinfo);
-
- /* Verify offset and IP/TCP length */
- if (off > m->m_pkthdr.len ||
- pinfo->ip_len < pinfo->tcp_len)
- goto error;
-
- /* Compute data payload length */
- pinfo->data_len = (pinfo->ip_len - pinfo->tcp_len - pinfo->ip_hdrlen);
-
- /* Trim any padded data */
- diff = (m->m_pkthdr.len - off) - pinfo->data_len;
- if (diff != 0) {
- if (diff < 0)
- goto error;
- else
- m_adj(m, -diff);
- }
- /* Compute header length */
- pinfo->buf_length = phdr - (uint8_t *)pinfo->buf;
- /* Zero-pad rest of buffer */
- memset(phdr, 0, TLRO_MAX_HEADER - pinfo->buf_length);
- return;
-error:
- pinfo->buf_length = 0;
-}
-
-static int
-tcp_tlro_cmp64(const uint64_t *pa, const uint64_t *pb)
-{
- int64_t diff = 0;
- unsigned x;
-
- for (x = 0; x != TLRO_MAX_HEADER / 8; x++) {
- /*
- * NOTE: Endianness does not matter in this
- * comparisation:
- */
- diff = pa[x] - pb[x];
- if (diff != 0)
- goto done;
- }
-done:
- if (diff < 0)
- return (-1);
- else if (diff > 0)
- return (1);
- return (0);
-}
-
-static int
-tcp_tlro_compare_header(const void *_ppa, const void *_ppb)
-{
- const struct tlro_mbuf_ptr *ppa = _ppa;
- const struct tlro_mbuf_ptr *ppb = _ppb;
- struct tlro_mbuf_data *pinfoa = ppa->data;
- struct tlro_mbuf_data *pinfob = ppb->data;
- int ret;
-
- ret = (pinfoa->head == NULL) - (pinfob->head == NULL);
- if (ret != 0)
- goto done;
-
- ret = pinfoa->buf_length - pinfob->buf_length;
- if (ret != 0)
- goto done;
- if (pinfoa->buf_length != 0) {
- ret = tcp_tlro_cmp64(pinfoa->buf, pinfob->buf);
- if (ret != 0)
- goto done;
- ret = ntohl(pinfoa->tcp->th_seq) - ntohl(pinfob->tcp->th_seq);
- if (ret != 0)
- goto done;
- ret = ntohl(pinfoa->tcp->th_ack) - ntohl(pinfob->tcp->th_ack);
- if (ret != 0)
- goto done;
- ret = pinfoa->sequence - pinfob->sequence;
- if (ret != 0)
- goto done;
- }
-done:
- return (ret);
-}
-
-static void
-tcp_tlro_sort(struct tlro_ctrl *tlro)
-{
- if (tlro->curr == 0)
- return;
-
- qsort(tlro->mbuf, tlro->curr, sizeof(struct tlro_mbuf_ptr),
- &tcp_tlro_compare_header);
-}
-
-static int
-tcp_tlro_get_ticks(void)
-{
- int to = tlro_min_rate;
-
- if (to < 1)
- to = 1;
- to = hz / to;
- if (to < 1)
- to = 1;
- return (to);
-}
-
-static void
-tcp_tlro_combine(struct tlro_ctrl *tlro, int force)
-{
- struct tlro_mbuf_data *pinfoa;
- struct tlro_mbuf_data *pinfob;
- uint32_t cs;
- int curr_ticks = ticks;
- int ticks_limit = tcp_tlro_get_ticks();
- unsigned x;
- unsigned y;
- unsigned z;
- int temp;
-
- if (tlro->curr == 0)
- return;
-
- for (y = 0; y != tlro->curr;) {
- struct mbuf *m;
-
- pinfoa = tlro->mbuf[y].data;
- for (x = y + 1; x != tlro->curr; x++) {
- pinfob = tlro->mbuf[x].data;
- if (pinfoa->buf_length != pinfob->buf_length ||
- tcp_tlro_cmp64(pinfoa->buf, pinfob->buf) != 0)
- break;
- }
- if (pinfoa->buf_length == 0) {
- /* Forward traffic which cannot be combined */
- for (z = y; z != x; z++) {
- /* Just forward packets */
- pinfob = tlro->mbuf[z].data;
-
- m = pinfob->head;
-
- /* Reset info structure */
- pinfob->head = NULL;
- pinfob->buf_length = 0;
-
- /* Do stats */
- tlro->lro_flushed++;
-
- /* Input packet to network layer */
- (*tlro->ifp->if_input) (tlro->ifp, m);
- }
- y = z;
- continue;
- }
-
- /* Compute current checksum subtracted some header parts */
- temp = (pinfoa->ip_len - pinfoa->ip_hdrlen);
- cs = ((temp & 0xFF) << 8) + ((temp & 0xFF00) >> 8) +
- tcp_tlro_csum((uint32_p_t *)pinfoa->tcp, pinfoa->tcp_len);
-
- /* Append all fragments into one block */
- for (z = y + 1; z != x; z++) {
-
- pinfob = tlro->mbuf[z].data;
-
- /* Check for command packets */
- if ((pinfoa->tcp->th_flags & ~(TH_ACK | TH_PUSH)) ||
- (pinfob->tcp->th_flags & ~(TH_ACK | TH_PUSH)))
- break;
-
- /* Check if there is enough space */
- if ((pinfoa->ip_len + pinfob->data_len) > tlro_max_packet)
- break;
-
- /* Try to append the new segment */
- temp = ntohl(pinfoa->tcp->th_seq) + pinfoa->data_len;
- if (temp != (int)ntohl(pinfob->tcp->th_seq))
- break;
-
- temp = pinfob->ip_len - pinfob->ip_hdrlen;
- cs += ((temp & 0xFF) << 8) + ((temp & 0xFF00) >> 8) +
- tcp_tlro_csum((uint32_p_t *)pinfob->tcp, pinfob->tcp_len);
- /* Remove fields which appear twice */
- cs += (IPPROTO_TCP << 8);
- if (pinfob->ip_version == 4) {
- cs += tcp_tlro_csum((uint32_p_t *)&pinfob->ip.v4->ip_src, 4);
- cs += tcp_tlro_csum((uint32_p_t *)&pinfob->ip.v4->ip_dst, 4);
- } else {
- cs += tcp_tlro_csum((uint32_p_t *)&pinfob->ip.v6->ip6_src, 16);
- cs += tcp_tlro_csum((uint32_p_t *)&pinfob->ip.v6->ip6_dst, 16);
- }
- /* Remainder computation */
- while (cs > 0xffff)
- cs = (cs >> 16) + (cs & 0xffff);
-
- /* Update window and ack sequence number */
- pinfoa->tcp->th_ack = pinfob->tcp->th_ack;
- pinfoa->tcp->th_win = pinfob->tcp->th_win;
-
- /* Check if we should restore the timestamp */
- tcp_tlro_info_restore_timestamp(pinfoa, pinfob);
-
- /* Accumulate TCP flags */
- pinfoa->tcp->th_flags |= pinfob->tcp->th_flags;
-
- /* update lengths */
- pinfoa->ip_len += pinfob->data_len;
- pinfoa->data_len += pinfob->data_len;
-
- /* Clear mbuf pointer - packet is accumulated */
- m = pinfob->head;
-
- /* Reset info structure */
- pinfob->head = NULL;
- pinfob->buf_length = 0;
-
- /* Append data to mbuf [y] */
- m_adj(m, pinfob->data_off);
- /* Delete mbuf tags, if any */
- m_tag_delete_chain(m, NULL);
- /* Clear packet header flag */
- m->m_flags &= ~M_PKTHDR;
-
- /* Concat mbuf(s) to end of list */
- pinfoa->pprev[0] = m;
- m = m_last(m);
- pinfoa->pprev = &m->m_next;
- pinfoa->head->m_pkthdr.len += pinfob->data_len;
- }
- /* Compute new TCP header checksum */
- pinfoa->tcp->th_sum = 0;
-
- temp = pinfoa->ip_len - pinfoa->ip_hdrlen;
- cs = (cs ^ 0xFFFF) +
- tcp_tlro_csum((uint32_p_t *)pinfoa->tcp, pinfoa->tcp_len) +
- ((temp & 0xFF) << 8) + ((temp & 0xFF00) >> 8);
-
- /* Remainder computation */
- while (cs > 0xffff)
- cs = (cs >> 16) + (cs & 0xffff);
-
- /* Update new checksum */
- pinfoa->tcp->th_sum = ~htole16(cs);
-
- /* Update IP length, if any */
- if (pinfoa->ip_version == 4) {
- if (pinfoa->ip_len > IP_MAXPACKET) {
- M_HASHTYPE_SET(pinfoa->head, M_HASHTYPE_LRO_TCP);
- pinfoa->ip.v4->ip_len = htons(IP_MAXPACKET);
- } else {
- pinfoa->ip.v4->ip_len = htons(pinfoa->ip_len);
- }
- } else {
- if (pinfoa->ip_len > (IP_MAXPACKET + sizeof(*pinfoa->ip.v6))) {
- M_HASHTYPE_SET(pinfoa->head, M_HASHTYPE_LRO_TCP);
- pinfoa->ip.v6->ip6_plen = htons(IP_MAXPACKET);
- } else {
- temp = pinfoa->ip_len - sizeof(*pinfoa->ip.v6);
- pinfoa->ip.v6->ip6_plen = htons(temp);
- }
- }
-
- temp = curr_ticks - pinfoa->last_tick;
- /* Check if packet should be forwarded */
- if (force != 0 || z != x || temp >= ticks_limit ||
- pinfoa->data_len == 0) {
-
- /* Compute new IPv4 header checksum */
- if (pinfoa->ip_version == 4) {
- pinfoa->ip.v4->ip_sum = 0;
- cs = tcp_tlro_csum((uint32_p_t *)pinfoa->ip.v4,
- sizeof(*pinfoa->ip.v4));
- pinfoa->ip.v4->ip_sum = ~htole16(cs);
- }
- /* Forward packet */
- m = pinfoa->head;
-
- /* Reset info structure */
- pinfoa->head = NULL;
- pinfoa->buf_length = 0;
-
- /* Do stats */
- tlro->lro_flushed++;
-
- /* Input packet to network layer */
- (*tlro->ifp->if_input) (tlro->ifp, m);
- }
- y = z;
- }
-
- /* Cleanup all NULL heads */
- for (y = 0; y != tlro->curr; y++) {
- if (tlro->mbuf[y].data->head == NULL) {
- for (z = y + 1; z != tlro->curr; z++) {
- struct tlro_mbuf_ptr ptemp;
- if (tlro->mbuf[z].data->head == NULL)
- continue;
- ptemp = tlro->mbuf[y];
- tlro->mbuf[y] = tlro->mbuf[z];
- tlro->mbuf[z] = ptemp;
- y++;
- }
- break;
- }
- }
- tlro->curr = y;
-}
-
-static void
-tcp_tlro_cleanup(struct tlro_ctrl *tlro)
-{
- while (tlro->curr != 0 &&
- tlro->mbuf[tlro->curr - 1].data->head == NULL)
- tlro->curr--;
-}
-
-void
-tcp_tlro_flush(struct tlro_ctrl *tlro, int force)
-{
- if (tlro->curr == 0)
- return;
-
- tcp_tlro_sort(tlro);
- tcp_tlro_cleanup(tlro);
- tcp_tlro_combine(tlro, force);
-}
-
-int
-tcp_tlro_init(struct tlro_ctrl *tlro, struct ifnet *ifp,
- int max_mbufs)
-{
- ssize_t size;
- uint32_t x;
-
- /* Set zero defaults */
- memset(tlro, 0, sizeof(*tlro));
-
- /* Compute size needed for data */
- size = (sizeof(struct tlro_mbuf_ptr) * max_mbufs) +
- (sizeof(struct tlro_mbuf_data) * max_mbufs);
-
- /* Range check */
- if (max_mbufs <= 0 || size <= 0 || ifp == NULL)
- return (EINVAL);
-
- /* Setup tlro control structure */
- tlro->mbuf = malloc(size, M_TLRO, M_WAITOK | M_ZERO);
- tlro->max = max_mbufs;
- tlro->ifp = ifp;
-
- /* Setup pointer array */
- for (x = 0; x != tlro->max; x++) {
- tlro->mbuf[x].data = ((struct tlro_mbuf_data *)
- &tlro->mbuf[max_mbufs]) + x;
- }
- return (0);
-}
-
-void
-tcp_tlro_free(struct tlro_ctrl *tlro)
-{
- struct tlro_mbuf_data *pinfo;
- struct mbuf *m;
- uint32_t y;
-
- /* Check if not setup */
- if (tlro->mbuf == NULL)
- return;
- /* Free MBUF array and any leftover MBUFs */
- for (y = 0; y != tlro->max; y++) {
-
- pinfo = tlro->mbuf[y].data;
-
- m = pinfo->head;
-
- /* Reset info structure */
- pinfo->head = NULL;
- pinfo->buf_length = 0;
-
- m_freem(m);
- }
- free(tlro->mbuf, M_TLRO);
- /* Reset buffer */
- memset(tlro, 0, sizeof(*tlro));
-}
-
-void
-tcp_tlro_rx(struct tlro_ctrl *tlro, struct mbuf *m)
-{
- if (m->m_len > 0 && tlro->curr < tlro->max) {
- /* do stats */
- tlro->lro_queued++;
-
- /* extract header */
- tcp_tlro_extract_header(tlro->mbuf[tlro->curr++].data,
- m, tlro->sequence++);
- } else if (tlro->ifp != NULL) {
- /* do stats */
- tlro->lro_flushed++;
-
- /* input packet to network layer */
- (*tlro->ifp->if_input) (tlro->ifp, m);
- } else {
- /* packet drop */
- m_freem(m);
- }
-}
diff --git a/sys/dev/mlx5/mlx5_en/tcp_tlro.h b/sys/dev/mlx5/mlx5_en/tcp_tlro.h
deleted file mode 100644
index 40ebdf6..0000000
--- a/sys/dev/mlx5/mlx5_en/tcp_tlro.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * Copyright (c) 2015 Mellanox Technologies. 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 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 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$
- */
-
-#ifndef _TCP_TLRO_H_
-#define _TCP_TLRO_H_
-
-#define TLRO_MAX_HEADER 64 /* bytes */
-
-struct ip;
-struct ip6_hdr;
-struct tcphdr;
-
-struct tlro_mbuf_data {
- union {
-#ifdef INET
- struct ip *v4;
-#endif
-#ifdef INET6
- struct ip6_hdr *v6;
-#endif
- } ip;
- struct tcphdr *tcp;
- struct mbuf *head;
- struct mbuf **pprev;
- int last_tick;
- int sequence;
- int data_len;
- int data_off;
- int ip_hdrlen;
- int ip_len;
- uint32_t tcp_ts;
- uint32_t tcp_ts_reply;
- uint16_t tcp_len;
- uint8_t ip_version;
- uint8_t buf_length; /* in 32-bit words */
- uint64_t buf[TLRO_MAX_HEADER / 8];
-} __aligned(256);
-
-struct tlro_mbuf_ptr {
- struct tlro_mbuf_data *data;
-};
-
-/* NB: This is part of driver structs */
-struct tlro_ctrl {
- struct ifnet *ifp;
- struct tlro_mbuf_ptr *mbuf;
- uint64_t lro_queued;
- uint64_t lro_flushed;
- uint32_t max;
- uint32_t curr;
- int sequence;
-};
-
-int tcp_tlro_init(struct tlro_ctrl *, struct ifnet *, int);
-void tcp_tlro_free(struct tlro_ctrl *);
-void tcp_tlro_flush(struct tlro_ctrl *, int);
-void tcp_tlro_rx(struct tlro_ctrl *, struct mbuf *);
-
-#endif /* _TCP_TLRO_H_ */
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index 02a6ff3..42d96cf 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -198,6 +198,7 @@ struct ukbd_softc {
int sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
int sc_state; /* shift/lock key state */
int sc_accents; /* accent key index (> 0) */
+ int sc_polling; /* polling recursion count */
int sc_led_size;
int sc_kbd_size;
@@ -1983,7 +1984,16 @@ ukbd_poll(keyboard_t *kbd, int on)
struct ukbd_softc *sc = kbd->kb_data;
UKBD_LOCK();
- if (on) {
+ /*
+ * Keep a reference count on polling to allow recursive
+ * cngrab() during a panic for example.
+ */
+ if (on)
+ sc->sc_polling++;
+ else
+ sc->sc_polling--;
+
+ if (sc->sc_polling != 0) {
sc->sc_flags |= UKBD_FLAG_POLLING;
sc->sc_poll_thread = curthread;
} else {
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 44d9321..5cd9174 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -2729,6 +2729,7 @@ product LOGITECH BB13 0xc401 USB-PS/2 Trackball
product LOGITECH RK53 0xc501 Cordless mouse
product LOGITECH RB6 0xc503 Cordless keyboard
product LOGITECH MX700 0xc506 Cordless optical mouse
+product LOGITECH UNIFYING 0xc52b Logitech Unifying Receiver
product LOGITECH QUICKCAMPRO2 0xd001 QuickCam Pro
/* Logitec Corp. products */
diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c
index 6b89b86..3718975 100644
--- a/sys/dev/virtio/network/if_vtnet.c
+++ b/sys/dev/virtio/network/if_vtnet.c
@@ -230,18 +230,32 @@ static void vtnet_disable_interrupts(struct vtnet_softc *);
static int vtnet_tunable_int(struct vtnet_softc *, const char *, int);
/* Tunables. */
+static SYSCTL_NODE(_hw, OID_AUTO, vtnet, CTLFLAG_RD, 0, "VNET driver parameters");
static int vtnet_csum_disable = 0;
TUNABLE_INT("hw.vtnet.csum_disable", &vtnet_csum_disable);
+SYSCTL_INT(_hw_vtnet, OID_AUTO, csum_disable, CTLFLAG_RDTUN,
+ &vtnet_csum_disable, 0, "Disables receive and send checksum offload");
static int vtnet_tso_disable = 0;
TUNABLE_INT("hw.vtnet.tso_disable", &vtnet_tso_disable);
+SYSCTL_INT(_hw_vtnet, OID_AUTO, tso_disable, CTLFLAG_RDTUN, &vtnet_tso_disable,
+ 0, "Disables TCP Segmentation Offload");
static int vtnet_lro_disable = 0;
TUNABLE_INT("hw.vtnet.lro_disable", &vtnet_lro_disable);
+SYSCTL_INT(_hw_vtnet, OID_AUTO, lro_disable, CTLFLAG_RDTUN, &vtnet_lro_disable,
+ 0, "Disables TCP Large Receive Offload");
static int vtnet_mq_disable = 0;
TUNABLE_INT("hw.vtnet.mq_disable", &vtnet_mq_disable);
-static int vtnet_mq_max_pairs = 0;
+SYSCTL_INT(_hw_vtnet, OID_AUTO, mq_disable, CTLFLAG_RDTUN, &vtnet_mq_disable,
+ 0, "Disables Multi Queue support");
+static int vtnet_mq_max_pairs = VTNET_MAX_QUEUE_PAIRS;
TUNABLE_INT("hw.vtnet.mq_max_pairs", &vtnet_mq_max_pairs);
+SYSCTL_INT(_hw_vtnet, OID_AUTO, mq_max_pairs, CTLFLAG_RDTUN,
+ &vtnet_mq_max_pairs, 0, "Sets the maximum number of Multi Queue pairs");
static int vtnet_rx_process_limit = 512;
TUNABLE_INT("hw.vtnet.rx_process_limit", &vtnet_rx_process_limit);
+SYSCTL_INT(_hw_vtnet, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
+ &vtnet_rx_process_limit, 0,
+ "Limits the number RX segments processed in a single pass");
static uma_zone_t vtnet_tx_header_zone;
@@ -597,7 +611,6 @@ static void
vtnet_setup_features(struct vtnet_softc *sc)
{
device_t dev;
- int max_pairs, max;
dev = sc->vtnet_dev;
@@ -646,32 +659,31 @@ vtnet_setup_features(struct vtnet_softc *sc)
if (virtio_with_feature(dev, VIRTIO_NET_F_MQ) &&
sc->vtnet_flags & VTNET_FLAG_CTRL_VQ) {
- max_pairs = virtio_read_dev_config_2(dev,
+ sc->vtnet_max_vq_pairs = virtio_read_dev_config_2(dev,
offsetof(struct virtio_net_config, max_virtqueue_pairs));
- if (max_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
- max_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX)
- max_pairs = 1;
} else
- max_pairs = 1;
+ sc->vtnet_max_vq_pairs = 1;
- if (max_pairs > 1) {
+ if (sc->vtnet_max_vq_pairs > 1) {
/*
- * Limit the maximum number of queue pairs to the number of
- * CPUs or the configured maximum. The actual number of
- * queues that get used may be less.
+ * Limit the maximum number of queue pairs to the lower of
+ * the number of CPUs and the configured maximum.
+ * The actual number of queues that get used may be less.
*/
+ int max;
+
max = vtnet_tunable_int(sc, "mq_max_pairs", vtnet_mq_max_pairs);
- if (max > 0 && max_pairs > max)
- max_pairs = max;
- if (max_pairs > mp_ncpus)
- max_pairs = mp_ncpus;
- if (max_pairs > VTNET_MAX_QUEUE_PAIRS)
- max_pairs = VTNET_MAX_QUEUE_PAIRS;
- if (max_pairs > 1)
- sc->vtnet_flags |= VTNET_FLAG_MULTIQ;
+ if (max > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN) {
+ if (max > mp_ncpus)
+ max = mp_ncpus;
+ if (max > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX)
+ max = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX;
+ if (max > 1) {
+ sc->vtnet_requested_vq_pairs = max;
+ sc->vtnet_flags |= VTNET_FLAG_MULTIQ;
+ }
+ }
}
-
- sc->vtnet_max_vq_pairs = max_pairs;
}
static int
@@ -2982,13 +2994,11 @@ vtnet_set_active_vq_pairs(struct vtnet_softc *sc)
dev = sc->vtnet_dev;
if ((sc->vtnet_flags & VTNET_FLAG_MULTIQ) == 0) {
- MPASS(sc->vtnet_max_vq_pairs == 1);
sc->vtnet_act_vq_pairs = 1;
return;
}
- /* BMV: Just use the maximum configured for now. */
- npairs = sc->vtnet_max_vq_pairs;
+ npairs = sc->vtnet_requested_vq_pairs;
if (vtnet_ctrl_mq_cmd(sc, npairs) != 0) {
device_printf(dev,
@@ -3852,6 +3862,9 @@ vtnet_setup_sysctl(struct vtnet_softc *sc)
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "max_vq_pairs",
CTLFLAG_RD, &sc->vtnet_max_vq_pairs, 0,
"Maximum number of supported virtqueue pairs");
+ SYSCTL_ADD_INT(ctx, child, OID_AUTO, "requested_vq_pairs",
+ CTLFLAG_RD, &sc->vtnet_requested_vq_pairs, 0,
+ "Requested number of virtqueue pairs");
SYSCTL_ADD_INT(ctx, child, OID_AUTO, "act_vq_pairs",
CTLFLAG_RD, &sc->vtnet_act_vq_pairs, 0,
"Number of active virtqueue pairs");
diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/network/if_vtnetvar.h
index f89f6b1..15436d9 100644
--- a/sys/dev/virtio/network/if_vtnetvar.h
+++ b/sys/dev/virtio/network/if_vtnetvar.h
@@ -155,6 +155,7 @@ struct vtnet_softc {
int vtnet_if_flags;
int vtnet_act_vq_pairs;
int vtnet_max_vq_pairs;
+ int vtnet_requested_vq_pairs;
struct virtqueue *vtnet_ctrl_vq;
struct vtnet_mac_filter *vtnet_mac_filter;
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index 72e8792..7ce4789 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -819,10 +819,13 @@ tmpfs_dir_lookup_cookie(struct tmpfs_node *node, off_t cookie,
goto out;
}
- MPASS((cookie & TMPFS_DIRCOOKIE_MASK) == cookie);
- dekey.td_hash = cookie;
- /* Recover if direntry for cookie was removed */
- de = RB_NFIND(tmpfs_dir, dirhead, &dekey);
+ if ((cookie & TMPFS_DIRCOOKIE_MASK) != cookie) {
+ de = NULL;
+ } else {
+ dekey.td_hash = cookie;
+ /* Recover if direntry for cookie was removed */
+ de = RB_NFIND(tmpfs_dir, dirhead, &dekey);
+ }
dc->tdc_tree = de;
dc->tdc_current = de;
if (de != NULL && tmpfs_dirent_duphead(de)) {
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 40f7204..c540a49 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -540,8 +540,8 @@ trap(struct trapframe *frame)
case T_DNA:
#ifdef DEV_NPX
- KASSERT(!PCB_USER_FPU(td->td_pcb),
- ("Unregistered use of FPU in kernel"));
+ if (PCB_USER_FPU(td->td_pcb))
+ panic("Unregistered use of FPU in kernel");
if (npxdna())
goto out;
#endif
diff --git a/sys/i386/linux/linux_ptrace.c b/sys/i386/linux/linux_ptrace.c
index 2925e6b..fbe66b4 100644
--- a/sys/i386/linux/linux_ptrace.c
+++ b/sys/i386/linux/linux_ptrace.c
@@ -69,7 +69,7 @@ __FBSDID("$FreeBSD$");
#define PTRACE_ATTACH 16
#define PTRACE_DETACH 17
-#define PTRACE_SYSCALL 24
+#define LINUX_PTRACE_SYSCALL 24
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
@@ -473,7 +473,7 @@ linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
break;
}
- case PTRACE_SYSCALL:
+ case LINUX_PTRACE_SYSCALL:
/* fall through */
default:
printf("linux: ptrace(%u, ...) not implemented\n",
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 6466a3e..df8e903 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/pioctl.h>
+#include <sys/ptrace.h>
#include <sys/namei.h>
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
@@ -905,7 +906,8 @@ exec_fail_dealloc:
if (error == 0) {
PROC_LOCK(p);
- td->td_dbgflags |= TDB_EXEC;
+ if (p->p_ptevents & PTRACE_EXEC)
+ td->td_dbgflags |= TDB_EXEC;
PROC_UNLOCK(p);
/*
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 929c2c0..125f210 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -338,6 +338,7 @@ exit1(struct thread *td, int rval, int signo)
PROC_LOCK(p);
stopprofclock(p);
p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE);
+ p->p_ptevents = 0;
/*
* Stop the real interval timer. If the handler is currently
@@ -475,8 +476,12 @@ exit1(struct thread *td, int rval, int signo)
*/
clear_orphan(q);
q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
- FOREACH_THREAD_IN_PROC(q, tdt)
- tdt->td_dbgflags &= ~TDB_SUSPEND;
+ q->p_flag2 &= ~P2_PTRACE_FSTP;
+ q->p_ptevents = 0;
+ FOREACH_THREAD_IN_PROC(q, tdt) {
+ tdt->td_dbgflags &= ~(TDB_SUSPEND | TDB_XSIG |
+ TDB_FSTP);
+ }
kern_psignal(q, SIGKILL);
}
PROC_UNLOCK(q);
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 2c98551..c7447fb 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -414,6 +414,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
bzero(&p2->p_startzero,
__rangeof(struct proc, p_startzero, p_endzero));
+ p2->p_ptevents = 0;
/* Tell the prison that we exist. */
prison_proc_hold(p2->p_ucred->cr_prison);
@@ -720,8 +721,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
* but before we wait for the debugger.
*/
_PHOLD(p2);
- if ((p1->p_flag & (P_TRACED | P_FOLLOWFORK)) == (P_TRACED |
- P_FOLLOWFORK)) {
+ if (p1->p_ptevents & PTRACE_FORK) {
/*
* Arrange for debugger to receive the fork event.
*
@@ -1068,21 +1068,19 @@ fork_return(struct thread *td, struct trapframe *frame)
if (td->td_dbgflags & TDB_STOPATFORK) {
sx_xlock(&proctree_lock);
PROC_LOCK(p);
- if ((p->p_pptr->p_flag & (P_TRACED | P_FOLLOWFORK)) ==
- (P_TRACED | P_FOLLOWFORK)) {
+ if (p->p_pptr->p_ptevents & PTRACE_FORK) {
/*
* If debugger still wants auto-attach for the
* parent's children, do it now.
*/
dbg = p->p_pptr->p_pptr;
- p->p_flag |= P_TRACED;
- p->p_oppid = p->p_pptr->p_pid;
+ proc_set_traced(p);
CTR2(KTR_PTRACE,
"fork_return: attaching to new child pid %d: oppid %d",
p->p_pid, p->p_oppid);
proc_reparent(p, dbg);
sx_xunlock(&proctree_lock);
- td->td_dbgflags |= TDB_CHILD | TDB_SCX;
+ td->td_dbgflags |= TDB_CHILD | TDB_SCX | TDB_FSTP;
ptracestop(td, SIGSTOP);
td->td_dbgflags &= ~(TDB_CHILD | TDB_SCX);
} else {
@@ -1102,7 +1100,7 @@ fork_return(struct thread *td, struct trapframe *frame)
PROC_LOCK(p);
td->td_dbgflags |= TDB_SCX;
_STOPEVENT(p, S_SCX, td->td_dbg_sc_code);
- if ((p->p_stops & S_PT_SCX) != 0 ||
+ if ((p->p_ptevents & PTRACE_SCX) != 0 ||
(td->td_dbgflags & TDB_BORN) != 0)
ptracestop(td, SIGTRAP);
td->td_dbgflags &= ~(TDB_SCX | TDB_BORN);
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 72c01f0..04f3423 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -320,11 +320,13 @@ void
kthread_exit(void)
{
struct proc *p;
+ struct thread *td;
- p = curthread->td_proc;
+ td = curthread;
+ p = td->td_proc;
/* A module may be waiting for us to exit. */
- wakeup(curthread);
+ wakeup(td);
/*
* The last exiting thread in a kernel process must tear down
@@ -337,9 +339,10 @@ kthread_exit(void)
rw_wunlock(&tidhash_lock);
kproc_exit(0);
}
- LIST_REMOVE(curthread, td_hash);
+ LIST_REMOVE(td, td_hash);
rw_wunlock(&tidhash_lock);
- umtx_thread_exit(curthread);
+ umtx_thread_exit(td);
+ tdsigcleanup(td);
PROC_SLOCK(p);
thread_exit();
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 2a5e6de..7af14a0 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2191,9 +2191,10 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
!((prop & SA_CONT) && (p->p_flag & P_STOPPED_SIG)))
return (ret);
/*
- * SIGKILL: Remove procfs STOPEVENTs.
+ * SIGKILL: Remove procfs STOPEVENTs and ptrace events.
*/
if (sig == SIGKILL) {
+ p->p_ptevents = 0;
/* from procfs_ioctl.c: PIOCBIC */
p->p_stops = 0;
/* from procfs_ioctl.c: PIOCCONT */
@@ -2525,14 +2526,26 @@ ptracestop(struct thread *td, int sig)
PROC_SUNLOCK(p);
return (sig);
}
+
/*
- * Just make wait() to work, the last stopped thread
- * will win.
+ * Make wait(2) work. Ensure that right after the
+ * attach, the thread which was decided to become the
+ * leader of attach gets reported to the waiter.
+ * Otherwise, just avoid overwriting another thread's
+ * assignment to p_xthread. If another thread has
+ * already set p_xthread, the current thread will get
+ * a chance to report itself upon the next iteration.
*/
- p->p_xsig = sig;
- p->p_xthread = td;
- p->p_flag |= (P_STOPPED_SIG|P_STOPPED_TRACE);
- sig_suspend_threads(td, p, 0);
+ if ((td->td_dbgflags & TDB_FSTP) != 0 ||
+ ((p->p_flag & P2_PTRACE_FSTP) == 0 &&
+ p->p_xthread == NULL)) {
+ p->p_xsig = sig;
+ p->p_xthread = td;
+ td->td_dbgflags &= ~TDB_FSTP;
+ p->p_flag2 &= ~P2_PTRACE_FSTP;
+ p->p_flag |= P_STOPPED_SIG | P_STOPPED_TRACE;
+ sig_suspend_threads(td, p, 0);
+ }
if ((td->td_dbgflags & TDB_STOPATFORK) != 0) {
td->td_dbgflags &= ~TDB_STOPATFORK;
cv_broadcast(&p->p_dbgwait);
@@ -2725,7 +2738,20 @@ issignal(struct thread *td)
SIG_STOPSIGMASK(sigpending);
if (SIGISEMPTY(sigpending)) /* no signal to send */
return (0);
- sig = sig_ffs(&sigpending);
+ if ((p->p_flag & (P_TRACED | P_PPTRACE)) == P_TRACED &&
+ (p->p_flag2 & P2_PTRACE_FSTP) != 0 &&
+ SIGISMEMBER(sigpending, SIGSTOP)) {
+ /*
+ * If debugger just attached, always consume
+ * SIGSTOP from ptrace(PT_ATTACH) first, to
+ * execute the debugger attach ritual in
+ * order.
+ */
+ sig = SIGSTOP;
+ td->td_dbgflags |= TDB_FSTP;
+ } else {
+ sig = sig_ffs(&sigpending);
+ }
if (p->p_stops & S_SIG) {
mtx_unlock(&ps->ps_mtx);
@@ -2742,7 +2768,7 @@ issignal(struct thread *td)
sigqueue_delete(&p->p_sigqueue, sig);
continue;
}
- if (p->p_flag & P_TRACED && (p->p_flag & P_PPTRACE) == 0) {
+ if ((p->p_flag & (P_TRACED | P_PPTRACE)) == P_TRACED) {
/*
* If traced, always stop.
* Remove old signal from queue before the stop.
@@ -2845,6 +2871,8 @@ issignal(struct thread *td)
mtx_unlock(&ps->ps_mtx);
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
&p->p_mtx.lock_object, "Catching SIGSTOP");
+ sigqueue_delete(&td->td_sigqueue, sig);
+ sigqueue_delete(&p->p_sigqueue, sig);
p->p_flag |= P_STOPPED_SIG;
p->p_xsig = sig;
PROC_SLOCK(p);
@@ -2852,7 +2880,7 @@ issignal(struct thread *td)
thread_suspend_switch(td, p);
PROC_SUNLOCK(p);
mtx_lock(&ps->ps_mtx);
- break;
+ goto next;
} else if (prop & SA_IGNORE) {
/*
* Except for SIGCONT, shouldn't get here.
@@ -2883,6 +2911,7 @@ issignal(struct thread *td)
}
sigqueue_delete(&td->td_sigqueue, sig); /* take the signal! */
sigqueue_delete(&p->p_sigqueue, sig);
+next:;
}
/* NOTREACHED */
}
diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c
index 293574c..10e7b2d 100644
--- a/sys/kern/kern_thr.c
+++ b/sys/kern/kern_thr.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/posix4.h>
+#include <sys/ptrace.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
@@ -254,7 +255,7 @@ thread_create(struct thread *td, struct rtprio *rtp,
thread_unlock(td);
if (P_SHOULDSTOP(p))
newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
- if (p->p_flag2 & P2_LWP_EVENTS)
+ if (p->p_ptevents & PTRACE_LWP)
newtd->td_dbgflags |= TDB_BORN;
/*
@@ -354,7 +355,7 @@ kern_thr_exit(struct thread *td)
p->p_pendingexits++;
td->td_dbgflags |= TDB_EXIT;
- if (p->p_flag & P_TRACED && p->p_flag2 & P2_LWP_EVENTS)
+ if (p->p_ptevents & PTRACE_LWP)
ptracestop(td, SIGTRAP);
PROC_UNLOCK(p);
tidhash_remove(td);
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
index f7bbdfb..aad2a1e 100644
--- a/sys/kern/subr_syscall.c
+++ b/sys/kern/subr_syscall.c
@@ -87,7 +87,7 @@ syscallenter(struct thread *td, struct syscall_args *sa)
PROC_LOCK(p);
td->td_dbg_sc_code = sa->code;
td->td_dbg_sc_narg = sa->narg;
- if (p->p_stops & S_PT_SCE)
+ if (p->p_ptevents & PTRACE_SCE)
ptracestop((td), SIGTRAP);
PROC_UNLOCK(p);
}
@@ -208,7 +208,7 @@ syscallret(struct thread *td, int error, struct syscall_args *sa)
*/
if (traced &&
((td->td_dbgflags & (TDB_FORK | TDB_EXEC)) != 0 ||
- (p->p_stops & S_PT_SCX) != 0))
+ (p->p_ptevents & PTRACE_SCX) != 0))
ptracestop(td, SIGTRAP);
td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK);
PROC_UNLOCK(p);
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index af71ea8..751db15 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -586,6 +586,7 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
struct ptrace_lwpinfo32 pl32;
struct ptrace_vm_entry32 pve32;
#endif
+ int ptevents;
} r;
void *addr;
int error = 0;
@@ -600,6 +601,7 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
AUDIT_ARG_VALUE(uap->data);
addr = &r;
switch (uap->req) {
+ case PT_GET_EVENT_MASK:
case PT_GETREGS:
case PT_GETFPREGS:
case PT_GETDBREGS:
@@ -614,6 +616,12 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
case PT_SETDBREGS:
error = COPYIN(uap->addr, &r.dbreg, sizeof r.dbreg);
break;
+ case PT_SET_EVENT_MASK:
+ if (uap->data != sizeof(r.ptevents))
+ error = EINVAL;
+ else
+ error = copyin(uap->addr, &r.ptevents, uap->data);
+ break;
case PT_IO:
error = COPYIN(uap->addr, &r.piod, sizeof r.piod);
break;
@@ -647,7 +655,12 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
case PT_GETDBREGS:
error = COPYOUT(&r.dbreg, uap->addr, sizeof r.dbreg);
break;
+ case PT_GET_EVENT_MASK:
+ /* NB: The size in uap->data is validated in kern_ptrace(). */
+ error = copyout(&r.ptevents, uap->addr, uap->data);
+ break;
case PT_LWPINFO:
+ /* NB: The size in uap->data is validated in kern_ptrace(). */
error = copyout(&r.pl, uap->addr, uap->data);
break;
}
@@ -679,6 +692,17 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
#define PROC_WRITE(w, t, a) proc_write_ ## w (t, a)
#endif
+void
+proc_set_traced(struct proc *p)
+{
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ p->p_flag |= P_TRACED;
+ p->p_flag2 |= P2_PTRACE_FSTP;
+ p->p_ptevents = PTRACE_DEFAULT;
+ p->p_oppid = p->p_pptr->p_pid;
+}
+
int
kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
{
@@ -711,6 +735,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_SYSCALL:
case PT_FOLLOW_FORK:
case PT_LWP_EVENTS:
+ case PT_GET_EVENT_MASK:
+ case PT_SET_EVENT_MASK:
case PT_DETACH:
sx_xlock(&proctree_lock);
proctree_locked = 1;
@@ -884,10 +910,9 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
switch (req) {
case PT_TRACE_ME:
/* set my trace flag and "owner" so it can read/write me */
- p->p_flag |= P_TRACED;
+ proc_set_traced(p);
if (p->p_flag & P_PPWAIT)
p->p_flag |= P_PPTRACE;
- p->p_oppid = p->p_pptr->p_pid;
CTR1(KTR_PTRACE, "PT_TRACE_ME: pid %d", p->p_pid);
break;
@@ -902,8 +927,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
* The old parent is remembered so we can put things back
* on a "detach".
*/
- p->p_flag |= P_TRACED;
- p->p_oppid = p->p_pptr->p_pid;
+ proc_set_traced(p);
if (p->p_pptr != td->td_proc) {
proc_reparent(p, td->td_proc);
}
@@ -941,24 +965,50 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_FOLLOW_FORK:
CTR3(KTR_PTRACE, "PT_FOLLOW_FORK: pid %d %s -> %s", p->p_pid,
- p->p_flag & P_FOLLOWFORK ? "enabled" : "disabled",
+ p->p_ptevents & PTRACE_FORK ? "enabled" : "disabled",
data ? "enabled" : "disabled");
if (data)
- p->p_flag |= P_FOLLOWFORK;
+ p->p_ptevents |= PTRACE_FORK;
else
- p->p_flag &= ~P_FOLLOWFORK;
+ p->p_ptevents &= ~PTRACE_FORK;
break;
case PT_LWP_EVENTS:
CTR3(KTR_PTRACE, "PT_LWP_EVENTS: pid %d %s -> %s", p->p_pid,
- p->p_flag2 & P2_LWP_EVENTS ? "enabled" : "disabled",
+ p->p_ptevents & PTRACE_LWP ? "enabled" : "disabled",
data ? "enabled" : "disabled");
if (data)
- p->p_flag2 |= P2_LWP_EVENTS;
+ p->p_ptevents |= PTRACE_LWP;
else
- p->p_flag2 &= ~P2_LWP_EVENTS;
+ p->p_ptevents &= ~PTRACE_LWP;
break;
+ case PT_GET_EVENT_MASK:
+ if (data != sizeof(p->p_ptevents)) {
+ error = EINVAL;
+ break;
+ }
+ CTR2(KTR_PTRACE, "PT_GET_EVENT_MASK: pid %d mask %#x", p->p_pid,
+ p->p_ptevents);
+ *(int *)addr = p->p_ptevents;
+ break;
+
+ case PT_SET_EVENT_MASK:
+ if (data != sizeof(p->p_ptevents)) {
+ error = EINVAL;
+ break;
+ }
+ tmp = *(int *)addr;
+ if ((tmp & ~(PTRACE_EXEC | PTRACE_SCE | PTRACE_SCX |
+ PTRACE_FORK | PTRACE_LWP)) != 0) {
+ error = EINVAL;
+ break;
+ }
+ CTR3(KTR_PTRACE, "PT_SET_EVENT_MASK: pid %d mask %#x -> %#x",
+ p->p_pid, p->p_ptevents, tmp);
+ p->p_ptevents = tmp;
+ break;
+
case PT_STEP:
case PT_CONTINUE:
case PT_TO_SCE:
@@ -991,24 +1041,24 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
}
switch (req) {
case PT_TO_SCE:
- p->p_stops |= S_PT_SCE;
+ p->p_ptevents |= PTRACE_SCE;
CTR4(KTR_PTRACE,
- "PT_TO_SCE: pid %d, stops = %#x, PC = %#lx, sig = %d",
- p->p_pid, p->p_stops,
+ "PT_TO_SCE: pid %d, events = %#x, PC = %#lx, sig = %d",
+ p->p_pid, p->p_ptevents,
(u_long)(uintfptr_t)addr, data);
break;
case PT_TO_SCX:
- p->p_stops |= S_PT_SCX;
+ p->p_ptevents |= PTRACE_SCX;
CTR4(KTR_PTRACE,
- "PT_TO_SCX: pid %d, stops = %#x, PC = %#lx, sig = %d",
- p->p_pid, p->p_stops,
+ "PT_TO_SCX: pid %d, events = %#x, PC = %#lx, sig = %d",
+ p->p_pid, p->p_ptevents,
(u_long)(uintfptr_t)addr, data);
break;
case PT_SYSCALL:
- p->p_stops |= S_PT_SCE | S_PT_SCX;
+ p->p_ptevents |= PTRACE_SYSCALL;
CTR4(KTR_PTRACE,
- "PT_SYSCALL: pid %d, stops = %#x, PC = %#lx, sig = %d",
- p->p_pid, p->p_stops,
+ "PT_SYSCALL: pid %d, events = %#x, PC = %#lx, sig = %d",
+ p->p_pid, p->p_ptevents,
(u_long)(uintfptr_t)addr, data);
break;
case PT_CONTINUE:
@@ -1027,7 +1077,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
* parent. Otherwise the debugee will be set
* as an orphan of the debugger.
*/
- p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
+ p->p_flag &= ~(P_TRACED | P_WAITED);
if (p->p_oppid != p->p_pptr->p_pid) {
PROC_LOCK(p->p_pptr);
sigqueue_take(p->p_ksi);
@@ -1044,7 +1094,18 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
CTR2(KTR_PTRACE, "PT_DETACH: pid %d, sig %d",
p->p_pid, data);
p->p_oppid = 0;
- p->p_stops = 0;
+ p->p_ptevents = 0;
+ FOREACH_THREAD_IN_PROC(p, td3) {
+ if ((td3->td_dbgflags & TDB_FSTP) != 0) {
+ sigqueue_delete(&td3->td_sigqueue,
+ SIGSTOP);
+ }
+ td3->td_dbgflags &= ~(TDB_XSIG | TDB_FSTP);
+ }
+ if ((p->p_flag2 & P2_PTRACE_FSTP) != 0) {
+ sigqueue_delete(&p->p_sigqueue, SIGSTOP);
+ p->p_flag2 &= ~P2_PTRACE_FSTP;
+ }
/* should we send SIGCHLD? */
/* childproc_continued(p); */
@@ -1065,7 +1126,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
if (req == PT_DETACH) {
FOREACH_THREAD_IN_PROC(p, td3)
- td3->td_dbgflags &= ~TDB_SUSPEND;
+ td3->td_dbgflags &= ~TDB_SUSPEND;
}
/*
* unsuspend all threads, to not let a thread run,
diff --git a/sys/modules/dtb/allwinner/Makefile b/sys/modules/dtb/allwinner/Makefile
index 9dd0799..541e8c0 100644
--- a/sys/modules/dtb/allwinner/Makefile
+++ b/sys/modules/dtb/allwinner/Makefile
@@ -7,7 +7,7 @@ DTS= \
cubieboard2.dts \
olimex-a20-som-evb.dts \
olinuxino-lime.dts \
- pcduino3b.dts \
+ pcduino3.dts \
sinovoip-bpi-m3.dts
.include <bsd.dtb.mk>
diff --git a/sys/modules/mlx5en/Makefile b/sys/modules/mlx5en/Makefile
index a9b48c6..a3f6d6b 100644
--- a/sys/modules/mlx5en/Makefile
+++ b/sys/modules/mlx5en/Makefile
@@ -12,15 +12,14 @@ mlx5_en_txrx.c \
device_if.h bus_if.h vnode_if.h pci_if.h \
opt_inet.h opt_inet6.h opt_rss.h
-.if defined(HAVE_TURBO_LRO)
-CFLAGS+= -DHAVE_TURBO_LRO
-SRCS+= tcp_tlro.c
-.endif
-
.if defined(HAVE_PER_CQ_EVENT_PACKET)
CFLAGS+= -DHAVE_PER_CQ_EVENT_PACKET
.endif
+.if defined(HAVE_TCP_LRO_RX)
+CFLAGS+= -DHAVE_TCP_LRO_RX
+.endif
+
CFLAGS+= -I${.CURDIR}/../../ofed/include
CFLAGS+= -I${.CURDIR}/../../compat/linuxkpi/common/include
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 640025d..6475fe0 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -60,6 +60,7 @@
#define IPFW_ARG_MAX 65534
#define IP_FW_TABLEARG 65535 /* Compat value for old clients */
#define IP_FW_TARG 0 /* Current tablearg value */
+#define IP_FW_NAT44_GLOBAL 65535 /* arg1 value for "nat global" */
/*
* Number of entries in the call stack of the call/return commands.
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index e5ff349..4011253 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -1747,21 +1747,27 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
* If its a fragmented message, lets see if we can find the control
* on the reassembly queues.
*/
- if ((chtype == SCTP_IDATA) && ((chunk_flags & SCTP_DATA_FIRST_FRAG) == 0) && (fsn == 0)) {
+ if ((chtype == SCTP_IDATA) &&
+ ((chunk_flags & SCTP_DATA_FIRST_FRAG) == 0) &&
+ (fsn == 0)) {
/*
* The first *must* be fsn 0, and other (middle/end) pieces
- * can *not* be fsn 0.
+ * can *not* be fsn 0. XXX: This can happen in case of a
+ * wrap around. Ignore is for now.
*/
+ snprintf(msg, sizeof(msg), "FSN zero for MID=%8.8x, but flags=%2.2x",
+ msg_id, chunk_flags);
goto err_out;
}
+ control = sctp_find_reasm_entry(strm, msg_id, ordered, old_data);
+ SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags:0x%x look for control on queues %p\n",
+ chunk_flags, control);
if ((chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) {
/* See if we can find the re-assembly entity */
- control = sctp_find_reasm_entry(strm, msg_id, ordered, old_data);
- SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags:0x%x look for control on queues %p\n",
- chunk_flags, control);
- if (control) {
+ if (control != NULL) {
/* We found something, does it belong? */
if (ordered && (msg_id != control->sinfo_ssn)) {
+ snprintf(msg, sizeof(msg), "Reassembly problem (MID=%8.8x)", msg_id);
err_out:
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15;
@@ -1774,6 +1780,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
* We can't have a switched order with an
* unordered chunk
*/
+ snprintf(msg, sizeof(msg), "All fragments of a user message must be ordered or unordered (TSN=%8.8x)",
+ tsn);
goto err_out;
}
if (!ordered && (((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED) == 0)) {
@@ -1781,6 +1789,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
* We can't have a switched unordered with a
* ordered chunk
*/
+ snprintf(msg, sizeof(msg), "All fragments of a user message must be ordered or unordered (TSN=%8.8x)",
+ tsn);
goto err_out;
}
}
@@ -1790,14 +1800,21 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
* re-assembly going on with the same Stream/Seq (for
* ordered) or in the same Stream for unordered.
*/
- SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags:0x%x look for msg in case we have dup\n",
- chunk_flags);
- if (sctp_find_reasm_entry(strm, msg_id, ordered, old_data)) {
- SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags: 0x%x dup detected on msg_id: %u\n",
- chunk_flags,
- msg_id);
-
- goto err_out;
+ if (control != NULL) {
+ if (ordered || (old_data == 0)) {
+ SCTPDBG(SCTP_DEBUG_XXX, "chunk_flags: 0x%x dup detected on msg_id: %u\n",
+ chunk_flags, msg_id);
+ snprintf(msg, sizeof(msg), "Duplicate MID=%8.8x detected.", msg_id);
+ goto err_out;
+ } else {
+ if ((tsn == control->fsn_included + 1) &&
+ (control->end_added == 0)) {
+ snprintf(msg, sizeof(msg), "Illegal message sequence, missing end for MID: %8.8x", control->fsn_included);
+ goto err_out;
+ } else {
+ control = NULL;
+ }
+ }
}
}
/* now do the tests */
diff --git a/sys/netinet/tcp_fastopen.c b/sys/netinet/tcp_fastopen.c
index ec02d18..e2b3b86 100644
--- a/sys/netinet/tcp_fastopen.c
+++ b/sys/netinet/tcp_fastopen.c
@@ -108,6 +108,7 @@ __FBSDID("$FreeBSD$");
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/rmlock.h>
+#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index c84881e..62c5e0b 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -637,7 +637,10 @@ struct ip6_mtuinfo {
* receiving IF. */
#define IPV6CTL_RFC6204W3 50 /* Accept defroute even when forwarding
enabled */
-#define IPV6CTL_MAXID 51
+#define IPV6CTL_INTRQMAXLEN 51 /* max length of IPv6 netisr queue */
+#define IPV6CTL_INTRDQMAXLEN 52 /* max length of direct IPv6 netisr
+ * queue */
+#define IPV6CTL_MAXID 53
#endif /* __BSD_VISIBLE */
/*
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 6b0fd2d..c0cd811 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/rmlock.h>
#include <sys/syslog.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -145,6 +146,24 @@ static struct netisr_handler ip6_nh = {
#endif
};
+static int
+sysctl_netinet6_intr_queue_maxlen(SYSCTL_HANDLER_ARGS)
+{
+ int error, qlimit;
+
+ netisr_getqlimit(&ip6_nh, &qlimit);
+ error = sysctl_handle_int(oidp, &qlimit, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ if (qlimit < 1)
+ return (EINVAL);
+ return (netisr_setqlimit(&ip6_nh, qlimit));
+}
+SYSCTL_DECL(_net_inet6_ip6);
+SYSCTL_PROC(_net_inet6_ip6, IPV6CTL_INTRQMAXLEN, intr_queue_maxlen,
+ CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_netinet6_intr_queue_maxlen, "I",
+ "Maximum size of the IPv6 input queue");
+
#ifdef RSS
static struct netisr_handler ip6_direct_nh = {
.nh_name = "ip6_direct",
@@ -154,6 +173,24 @@ static struct netisr_handler ip6_direct_nh = {
.nh_policy = NETISR_POLICY_CPU,
.nh_dispatch = NETISR_DISPATCH_HYBRID,
};
+
+static int
+sysctl_netinet6_intr_direct_queue_maxlen(SYSCTL_HANDLER_ARGS)
+{
+ int error, qlimit;
+
+ netisr_getqlimit(&ip6_direct_nh, &qlimit);
+ error = sysctl_handle_int(oidp, &qlimit, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ if (qlimit < 1)
+ return (EINVAL);
+ return (netisr_setqlimit(&ip6_direct_nh, qlimit));
+}
+SYSCTL_PROC(_net_inet6_ip6, IPV6CTL_INTRDQMAXLEN, intr_direct_queue_maxlen,
+ CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_netinet6_intr_direct_queue_maxlen,
+ "I", "Maximum size of the IPv6 direct input queue");
+
#endif
SYSCTL_DECL(_net_inet6_ip6);
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index 60a04d1..315da74 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -2489,7 +2489,7 @@ do { \
set_match(args, f_pos, chain);
/* Check if this is 'global' nat rule */
- if (cmd->arg1 == 0) {
+ if (cmd->arg1 == IP_FW_NAT44_GLOBAL) {
retval = ipfw_nat_ptr(args, NULL, m);
break;
}
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
index d186ba5..52dfe7c 100644
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -524,9 +524,11 @@ import_rule0(struct rule_check_info *ci)
/*
* Alter opcodes:
- * 1) convert tablearg value from 65335 to 0
- * 2) Add high bit to O_SETFIB/O_SETDSCP values (to make room for targ).
+ * 1) convert tablearg value from 65535 to 0
+ * 2) Add high bit to O_SETFIB/O_SETDSCP values (to make room
+ * for targ).
* 3) convert table number in iface opcodes to u16
+ * 4) convert old `nat global` into new 65535
*/
l = krule->cmd_len;
cmd = krule->cmd;
@@ -548,19 +550,21 @@ import_rule0(struct rule_check_info *ci)
case O_NETGRAPH:
case O_NGTEE:
case O_NAT:
- if (cmd->arg1 == 65535)
+ if (cmd->arg1 == IP_FW_TABLEARG)
cmd->arg1 = IP_FW_TARG;
+ else if (cmd->arg1 == 0)
+ cmd->arg1 = IP_FW_NAT44_GLOBAL;
break;
case O_SETFIB:
case O_SETDSCP:
- if (cmd->arg1 == 65535)
+ if (cmd->arg1 == IP_FW_TABLEARG)
cmd->arg1 = IP_FW_TARG;
else
cmd->arg1 |= 0x8000;
break;
case O_LIMIT:
lcmd = (ipfw_insn_limit *)cmd;
- if (lcmd->conn_limit == 65535)
+ if (lcmd->conn_limit == IP_FW_TABLEARG)
lcmd->conn_limit = IP_FW_TARG;
break;
/* Interface tables */
@@ -606,7 +610,7 @@ export_rule0(struct ip_fw *krule, struct ip_fw_rule0 *urule, int len)
/*
* Alter opcodes:
- * 1) convert tablearg value from 0 to 65335
+ * 1) convert tablearg value from 0 to 65535
* 2) Remove highest bit from O_SETFIB/O_SETDSCP values.
* 3) convert table number in iface opcodes to int
*/
@@ -631,19 +635,21 @@ export_rule0(struct ip_fw *krule, struct ip_fw_rule0 *urule, int len)
case O_NGTEE:
case O_NAT:
if (cmd->arg1 == IP_FW_TARG)
- cmd->arg1 = 65535;
+ cmd->arg1 = IP_FW_TABLEARG;
+ else if (cmd->arg1 == IP_FW_NAT44_GLOBAL)
+ cmd->arg1 = 0;
break;
case O_SETFIB:
case O_SETDSCP:
if (cmd->arg1 == IP_FW_TARG)
- cmd->arg1 = 65535;
+ cmd->arg1 = IP_FW_TABLEARG;
else
cmd->arg1 &= ~0x8000;
break;
case O_LIMIT:
lcmd = (ipfw_insn_limit *)cmd;
if (lcmd->conn_limit == IP_FW_TARG)
- lcmd->conn_limit = 65535;
+ lcmd->conn_limit = IP_FW_TABLEARG;
break;
/* Interface tables */
case O_XMIT:
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 0643ef7..5672c78 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -3611,7 +3611,9 @@ pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
*m = NULL;
}
- return (chk);
+ if (chk != PF_PASS)
+ return (EACCES);
+ return (0);
}
static int
@@ -3626,7 +3628,9 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
*m = NULL;
}
- return (chk);
+ if (chk != PF_PASS)
+ return (EACCES);
+ return (0);
}
#endif
@@ -3649,7 +3653,9 @@ pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
m_freem(*m);
*m = NULL;
}
- return chk;
+ if (chk != PF_PASS)
+ return (EACCES);
+ return (0);
}
static int
@@ -3665,7 +3671,9 @@ pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
m_freem(*m);
*m = NULL;
}
- return chk;
+ if (chk != PF_PASS)
+ return (EACCES);
+ return (0);
}
#endif /* INET6 */
diff --git a/sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.c b/sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.c
index d759750..5c7b9ff 100644
--- a/sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1927,6 +1927,13 @@ int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
return err;
}
+int mthca_DIAG_RPRT(struct mthca_dev *dev, int mod,
+ struct mthca_mailbox *mailbox, u8 *status)
+{
+ return mthca_cmd_box(dev, 0, mailbox->dma, 0, mod, CMD_DIAG_RPRT,
+ CMD_TIME_CLASS_A, status);
+}
+
int mthca_NOP(struct mthca_dev *dev, u8 *status)
{
return mthca_cmd(dev, 0, 0x1f, 0, CMD_NOP, msecs_to_jiffies(100), status);
diff --git a/sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.h b/sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.h
index 6efd326..5dd777c 100644
--- a/sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/sys/ofed/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -112,6 +112,15 @@ enum {
DEV_LIM_FLAG_UD_MULTI = 1 << 21,
};
+enum {
+ DIAG_RPRT_Q_XPRT_CIERR = 2,
+ DIAG_RPRT_QR_XPRT_CIERR = 3,
+ DIAG_RPRT_Q_PERF = 4,
+ DIAG_RPRT_QR_PERF = 5,
+ DIAG_RPRT_Q_MISC = 6,
+ DIAG_RPRT_QR_MISC = 7,
+};
+
struct mthca_mailbox {
dma_addr_t dma;
void *buf;
@@ -325,6 +334,8 @@ int mthca_WRITE_MGM(struct mthca_dev *dev, int index,
struct mthca_mailbox *mailbox, u8 *status);
int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
u16 *hash, u8 *status);
+int mthca_DIAG_RPRT(struct mthca_dev *dev, int mod,
+ struct mthca_mailbox *mailbox, u8 *status);
int mthca_NOP(struct mthca_dev *dev, u8 *status);
#endif /* MTHCA_CMD_H */
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 1550742..e25a64b 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -422,6 +422,7 @@ do { \
#define TDB_CHILD 0x00000100 /* New child indicator for ptrace() */
#define TDB_BORN 0x00000200 /* New LWP indicator for ptrace() */
#define TDB_EXIT 0x00000400 /* Exiting LWP indicator for ptrace() */
+#define TDB_FSTP 0x00001000 /* The thread is PT_ATTACH leader */
/*
* "Private" flags kept in td_pflags:
@@ -643,6 +644,7 @@ struct proc {
*/
LIST_ENTRY(proc) p_orphan; /* (e) List of orphan processes. */
LIST_HEAD(, proc) p_orphans; /* (e) Pointer to list of orphans. */
+ u_int p_ptevents; /* (c) ptrace() event mask. */
};
#define p_session p_pgrp->pg_session
@@ -672,7 +674,7 @@ struct proc {
#define P_ADVLOCK 0x00001 /* Process may hold a POSIX advisory lock. */
#define P_CONTROLT 0x00002 /* Has a controlling terminal. */
#define P_KPROC 0x00004 /* Kernel process. */
-#define P_FOLLOWFORK 0x00008 /* Attach parent debugger to children. */
+#define P_UNUSED3 0x00008 /* --available-- */
#define P_PPWAIT 0x00010 /* Parent is waiting for child to exec/exit. */
#define P_PROFIL 0x00020 /* Has started profiling. */
#define P_STOPPROF 0x00040 /* Has thread requesting to stop profiling. */
@@ -711,7 +713,7 @@ struct proc {
#define P2_NOTRACE 0x00000002 /* No ptrace(2) attach or coredumps. */
#define P2_NOTRACE_EXEC 0x00000004 /* Keep P2_NOPTRACE on exec(2). */
#define P2_AST_SU 0x00000008 /* Handles SU ast for kthreads. */
-#define P2_LWP_EVENTS 0x00000010 /* Report LWP events via ptrace(2). */
+#define P2_PTRACE_FSTP 0x00000010 /* SIGSTOP from PT_ATTACH not yet handled. */
/* Flags protected by proctree_lock, kept in p_treeflags. */
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */
@@ -1002,6 +1004,7 @@ void proc_linkup(struct proc *p, struct thread *td);
struct proc *proc_realparent(struct proc *child);
void proc_reap(struct thread *td, struct proc *p, int *status, int options);
void proc_reparent(struct proc *child, struct proc *newparent);
+void proc_set_traced(struct proc *p);
struct pstats *pstats_alloc(void);
void pstats_fork(struct pstats *src, struct pstats *dst);
void pstats_free(struct pstats *ps);
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index 88a587e..0cf25e8 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -66,6 +66,9 @@
#define PT_FOLLOW_FORK 23
#define PT_LWP_EVENTS 24 /* report LWP birth and exit */
+#define PT_GET_EVENT_MASK 25 /* get mask of optional events */
+#define PT_SET_EVENT_MASK 26 /* set mask of optional events */
+
#define PT_GETREGS 33 /* get general-purpose registers */
#define PT_SETREGS 34 /* set general-purpose registers */
#define PT_GETFPREGS 35 /* get floating-point registers */
@@ -79,6 +82,16 @@
#define PT_FIRSTMACH 64 /* for machine-specific requests */
#include <machine/ptrace.h> /* machine-specific requests, if any */
+/* Events used with PT_GET_EVENT_MASK and PT_SET_EVENT_MASK */
+#define PTRACE_EXEC 0x0001
+#define PTRACE_SCE 0x0002
+#define PTRACE_SCX 0x0004
+#define PTRACE_SYSCALL (PTRACE_SCE | PTRACE_SCX)
+#define PTRACE_FORK 0x0008
+#define PTRACE_LWP 0x0010
+
+#define PTRACE_DEFAULT (PTRACE_EXEC)
+
struct ptrace_io_desc {
int piod_op; /* I/O operation */
void *piod_offs; /* child offset */
@@ -136,13 +149,6 @@ struct ptrace_vm_entry {
#ifdef _KERNEL
-/*
- * The flags below are used for ptrace(2) tracing and have no relation
- * to procfs. They are stored in struct proc's p_stops member.
- */
-#define S_PT_SCE 0x000010000
-#define S_PT_SCX 0x000020000
-
int ptrace_set_pc(struct thread *_td, unsigned long _addr);
int ptrace_single_step(struct thread *_td);
int ptrace_clear_single_step(struct thread *_td);
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 1ae83c4..e54db2a 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -2744,6 +2744,8 @@ zfree_start:
goto zfree_start;
}
cache->uc_freebucket = NULL;
+ /* We are no longer associated with this CPU. */
+ critical_exit();
/* Can we throw this on the zone full list? */
if (bucket != NULL) {
@@ -2756,9 +2758,6 @@ zfree_start:
LIST_INSERT_HEAD(&zone->uz_buckets, bucket, ub_link);
}
- /* We are no longer associated with this CPU. */
- critical_exit();
-
/*
* We bump the uz count when the cache size is insufficient to
* handle the working set.
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 4ecc0ea..c37ae13 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -3397,7 +3397,7 @@ vm_page_advise(vm_page_t m, int advice)
* But we do make the page as freeable as we can without
* actually taking the step of unmapping it.
*/
- m->dirty = 0;
+ vm_page_undirty(m);
else if (advice != MADV_DONTNEED)
return;
@@ -3411,9 +3411,11 @@ vm_page_advise(vm_page_t m, int advice)
vm_page_dirty(m);
/*
- * Place clean pages at the head of the inactive queue rather than the
- * tail, thus defeating the queue's LRU operation and ensuring that the
- * page will be reused quickly.
+ * Place clean pages near the head of the inactive queue rather than
+ * the tail, thus defeating the queue's LRU operation and ensuring that
+ * the page will be reused quickly. Dirty pages are given a chance to
+ * cycle once through the inactive queue before becoming eligible for
+ * laundering.
*/
_vm_page_deactivate(m, m->dirty == 0);
}
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index e5a4f8a..5064458 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -266,7 +266,7 @@ vm_pageout_init_marker(vm_page_t marker, u_short queue)
*
* Lock vm object currently associated with `m'. VM_OBJECT_TRYWLOCK is
* known to have failed and page queue must be either PQ_ACTIVE or
- * PQ_INACTIVE. To avoid lock order violation, unlock the page queues
+ * PQ_INACTIVE. To avoid lock order violation, unlock the page queue
* while locking the vm object. Use marker page to detect page queue
* changes and maintain notion of next page on page queue. Return
* TRUE if no changes were detected, FALSE otherwise. vm object is
@@ -884,7 +884,7 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
int act_delta, addl_page_shortage, deficit, error, maxlaunder, maxscan;
int page_shortage, scan_tick, scanned, starting_page_shortage;
int vnodes_skipped;
- boolean_t pageout_ok, queues_locked;
+ boolean_t pageout_ok, queue_locked;
/*
* If we need to reclaim memory ask kernel caches to return
@@ -949,12 +949,12 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
pq = &vmd->vmd_pagequeues[PQ_INACTIVE];
maxscan = pq->pq_cnt;
vm_pagequeue_lock(pq);
- queues_locked = TRUE;
+ queue_locked = TRUE;
for (m = TAILQ_FIRST(&pq->pq_pl);
m != NULL && maxscan-- > 0 && page_shortage > 0;
m = next) {
vm_pagequeue_assert_locked(pq);
- KASSERT(queues_locked, ("unlocked queues"));
+ KASSERT(queue_locked, ("unlocked inactive queue"));
KASSERT(m->queue == PQ_INACTIVE, ("Inactive queue %p", m));
PCPU_INC(cnt.v_pdpages);
@@ -1024,7 +1024,7 @@ unlock_page:
*/
TAILQ_INSERT_AFTER(&pq->pq_pl, m, &vmd->vmd_marker, plinks.q);
vm_pagequeue_unlock(pq);
- queues_locked = FALSE;
+ queue_locked = FALSE;
/*
* Invalid pages can be easily freed. They cannot be
@@ -1112,7 +1112,7 @@ free_page:
m->flags |= PG_WINATCFLS;
requeue_page:
vm_pagequeue_lock(pq);
- queues_locked = TRUE;
+ queue_locked = TRUE;
vm_page_requeue_locked(m);
} else if (maxlaunder > 0) {
/*
@@ -1150,15 +1150,15 @@ requeue_page:
addl_page_shortage++;
}
vm_page_lock_assert(m, MA_NOTOWNED);
- goto relock_queues;
+ goto relock_queue;
}
drop_page:
vm_page_unlock(m);
VM_OBJECT_WUNLOCK(object);
-relock_queues:
- if (!queues_locked) {
+relock_queue:
+ if (!queue_locked) {
vm_pagequeue_lock(pq);
- queues_locked = TRUE;
+ queue_locked = TRUE;
}
next = TAILQ_NEXT(&vmd->vmd_marker, plinks.q);
TAILQ_REMOVE(&pq->pq_pl, &vmd->vmd_marker, plinks.q);
diff --git a/tests/sys/kern/ptrace_test.c b/tests/sys/kern/ptrace_test.c
index 177f412..be978ed 100644
--- a/tests/sys/kern/ptrace_test.c
+++ b/tests/sys/kern/ptrace_test.c
@@ -1355,6 +1355,200 @@ ATF_TC_BODY(ptrace__lwp_events_exec, tc)
ATF_REQUIRE(errno == ECHILD);
}
+static void
+handler(int sig __unused)
+{
+}
+
+static void
+signal_main(void)
+{
+
+ signal(SIGINFO, handler);
+ raise(SIGINFO);
+ exit(0);
+}
+
+/*
+ * Verify that the expected ptrace event is reported for a signal.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__siginfo);
+ATF_TC_BODY(ptrace__siginfo, tc)
+{
+ struct ptrace_lwpinfo pl;
+ pid_t fpid, wpid;
+ int status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ signal_main();
+ }
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* The next event should be for the SIGINFO. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGINFO);
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
+ ATF_REQUIRE(pl.pl_event == PL_EVENT_SIGNAL);
+ ATF_REQUIRE(pl.pl_flags & PL_FLAG_SI);
+ ATF_REQUIRE(pl.pl_siginfo.si_code == SI_LWP);
+ ATF_REQUIRE(pl.pl_siginfo.si_pid == wpid);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* The last event should be for the child process's exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 0);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that the expected ptrace events are reported for PTRACE_EXEC.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_disable);
+ATF_TC_BODY(ptrace__ptrace_exec_disable, tc)
+{
+ pid_t fpid, wpid;
+ int events, status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ exec_thread(NULL);
+ }
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ events = 0;
+ ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
+ sizeof(events)) == 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* Should get one event at exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 0);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+ATF_TC_WITHOUT_HEAD(ptrace__ptrace_exec_enable);
+ATF_TC_BODY(ptrace__ptrace_exec_enable, tc)
+{
+ struct ptrace_lwpinfo pl;
+ pid_t fpid, wpid;
+ int events, status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ exec_thread(NULL);
+ }
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ events = PTRACE_EXEC;
+ ATF_REQUIRE(ptrace(PT_SET_EVENT_MASK, fpid, (caddr_t)&events,
+ sizeof(events)) == 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* The next event should be for the child process's exec. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
+ ATF_REQUIRE((pl.pl_flags & (PL_FLAG_EXEC | PL_FLAG_SCX)) ==
+ (PL_FLAG_EXEC | PL_FLAG_SCX));
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* The last event should be for the child process's exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 0);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+ATF_TC_WITHOUT_HEAD(ptrace__event_mask);
+ATF_TC_BODY(ptrace__event_mask, tc)
+{
+ pid_t fpid, wpid;
+ int events, status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ exit(0);
+ }
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ /* PT_FOLLOW_FORK should toggle the state of PTRACE_FORK. */
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 1) != -1);
+ ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
+ sizeof(events)) == 0);
+ ATF_REQUIRE(events & PTRACE_FORK);
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, fpid, NULL, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
+ sizeof(events)) == 0);
+ ATF_REQUIRE(!(events & PTRACE_FORK));
+
+ /* PT_LWP_EVENTS should toggle the state of PTRACE_LWP. */
+ ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 1) != -1);
+ ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
+ sizeof(events)) == 0);
+ ATF_REQUIRE(events & PTRACE_LWP);
+ ATF_REQUIRE(ptrace(PT_LWP_EVENTS, fpid, NULL, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_GET_EVENT_MASK, fpid, (caddr_t)&events,
+ sizeof(events)) == 0);
+ ATF_REQUIRE(!(events & PTRACE_LWP));
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* Should get one event at exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 0);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -1376,6 +1570,10 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, ptrace__new_child_pl_syscall_code_thread);
ATF_TP_ADD_TC(tp, ptrace__lwp_events);
ATF_TP_ADD_TC(tp, ptrace__lwp_events_exec);
+ ATF_TP_ADD_TC(tp, ptrace__siginfo);
+ ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_disable);
+ ATF_TP_ADD_TC(tp, ptrace__ptrace_exec_enable);
+ ATF_TP_ADD_TC(tp, ptrace__event_mask);
return (atf_no_error());
}
diff --git a/usr.bin/Makefile b/usr.bin/Makefile
index 9d29b4f..1f0c664 100644
--- a/usr.bin/Makefile
+++ b/usr.bin/Makefile
@@ -270,8 +270,9 @@ SUBDIR.${MK_TOOLCHAIN}+= ctags
SUBDIR.${MK_TOOLCHAIN}+= cxxfilt
SUBDIR.${MK_TOOLCHAIN}+= elfcopy
SUBDIR.${MK_TOOLCHAIN}+= file2c
-.if ${MACHINE_ARCH} != "aarch64" && \ # ARM64TODO gprof does not build
- ${MACHINE_CPUARCH} != "riscv" # RISCVTODO gprof does not build
+# ARM64TODO gprof does not build
+# RISCVTODO gprof does not build
+.if ${MACHINE_ARCH} != "aarch64" && ${MACHINE_CPUARCH} != "riscv"
SUBDIR.${MK_TOOLCHAIN}+= gprof
.endif
SUBDIR.${MK_TOOLCHAIN}+= indent
diff --git a/usr.bin/getconf/getconf.1 b/usr.bin/getconf/getconf.1
index 29a2026..6b5116c 100644
--- a/usr.bin/getconf/getconf.1
+++ b/usr.bin/getconf/getconf.1
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 18, 2002
+.Dd August 8, 2016
.Dt GETCONF 1
.Os
.Sh NAME
@@ -122,7 +122,7 @@ Exactly 32-bit integer, long, and pointer; at least 64-bit file offset.
.It Li POSIX_V6_LP64_OFF64
Exactly 32-bit integer; exactly 64-bit long, pointer, and file offset.
.Sy Supported platforms :
-.Tn Alpha ,
+.Tn AMD64 ,
.Tn SPARC64 .
.It Li POSIX_V6_LPBIG_OFFBIG
At least 32-bit integer; at least 64-bit long, pointer, and file offset.
diff --git a/usr.bin/getconf/progenv.gperf b/usr.bin/getconf/progenv.gperf
index 40ce16a..4810553 100644
--- a/usr.bin/getconf/progenv.gperf
+++ b/usr.bin/getconf/progenv.gperf
@@ -30,7 +30,7 @@ static const struct map *in_word_set(const char *str);
* be updated. (We cheat here and define the supported environments
* statically.)
*/
-#if defined(__alpha__) || defined(__sparc64__) || defined(__amd64__)
+#if defined(__sparc64__) || defined(__amd64__)
#define have_LP64_OFF64 NULL
#endif
diff --git a/usr.bin/resizewin/resizewin.1 b/usr.bin/resizewin/resizewin.1
index beb1a0a..b7376c7 100644
--- a/usr.bin/resizewin/resizewin.1
+++ b/usr.bin/resizewin/resizewin.1
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 17, 2016
+.Dd July 9, 2016
.Dt RESIZEWIN 1
.Os
.Sh NAME
@@ -55,10 +55,12 @@ updates the kernel's window size to match the new size.
.Pp
Note that virtually all modern terninals support VT100/ANSI escape
sequences, including xterm, konsole, gnome-terminal iTerm,
-Terminal.app, and puTTY.
+Terminal.app, and PuTTY.
.Sh SEE ALSO
.Xr resize 1 ,
.Xr stty 1
.Sh HISTORY
+The
.Nm
-appeared in FreeBSD 11.
+command first appeared in
+.Fx 11 .
diff --git a/usr.bin/tr/tr.1 b/usr.bin/tr/tr.1
index 37e68f3..2aee69c 100644
--- a/usr.bin/tr/tr.1
+++ b/usr.bin/tr/tr.1
@@ -334,6 +334,10 @@ should be used instead of explicit character ranges like
and
.Dq Li A-Z .
.Pp
+.Dq Li [=equiv=]
+expression and collation for ranges
+are implemented for single byte locales only.
+.Pp
System V has historically implemented character ranges using the syntax
.Dq Li [c-c]
instead of the
diff --git a/usr.bin/tr/tr.c b/usr.bin/tr/tr.c
index 6eea2cb..d54e74c 100644
--- a/usr.bin/tr/tr.c
+++ b/usr.bin/tr/tr.c
@@ -272,10 +272,11 @@ endloop:
if (Cflag && !iswrune(cnt))
continue;
if (cmap_lookup(map, cnt) == OOBCH) {
- if (next(&s2))
+ if (next(&s2)) {
cmap_add(map, cnt, s2.lastch);
- if (sflag)
- cset_add(squeeze, s2.lastch);
+ if (sflag)
+ cset_add(squeeze, s2.lastch);
+ }
} else
cmap_add(map, cnt, cnt);
if ((s2.state == EOS || s2.state == INFINITE) &&
diff --git a/usr.bin/truss/setup.c b/usr.bin/truss/setup.c
index c134405..a14c016 100644
--- a/usr.bin/truss/setup.c
+++ b/usr.bin/truss/setup.c
@@ -223,8 +223,10 @@ add_threads(struct trussinfo *info, struct procinfo *p)
t = new_thread(p, lwps[i]);
if (ptrace(PT_LWPINFO, lwps[i], (caddr_t)&pl, sizeof(pl)) == -1)
err(1, "ptrace(PT_LWPINFO)");
- if (pl.pl_flags & PL_FLAG_SCE)
+ if (pl.pl_flags & PL_FLAG_SCE) {
+ info->curthread = t;
enter_syscall(info, t, &pl);
+ }
}
free(lwps);
}
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
index 3bf7b9d..7046b56 100644
--- a/usr.bin/truss/syscalls.c
+++ b/usr.bin/truss/syscalls.c
@@ -281,6 +281,8 @@ static struct syscall decoded_syscalls[] = {
.args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
{ .name = "rfork", .ret_type = 1, .nargs = 1,
.args = { { Rforkflags, 0 } } },
+ { .name = "rmdir", .ret_type = 1, .nargs = 1,
+ .args = { { Name, 0 } } },
{ .name = "select", .ret_type = 1, .nargs = 5,
.args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
{ Timeval, 4 } } },
OpenPOWER on IntegriCloud