summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-12-17 06:55:25 +0000
committerngie <ngie@FreeBSD.org>2015-12-17 06:55:25 +0000
commit490921132f201193a73d81699cb455aa2ae87357 (patch)
tree447ebf673b9e1d362dbcf1b55fd34fa0de86d693
parent3fed53d02350ae9cbd7b2786b72b83d2e292b8d1 (diff)
parenta7e4d91c2357d6f2c732cccc35fd4ddda5f2d58e (diff)
downloadFreeBSD-src-490921132f201193a73d81699cb455aa2ae87357.zip
FreeBSD-src-490921132f201193a73d81699cb455aa2ae87357.tar.gz
MFhead @ r292396
-rw-r--r--MAINTAINERS10
-rw-r--r--UPDATING6
-rw-r--r--bin/sh/var.c2
-rw-r--r--contrib/llvm/tools/lldb/docs/lldb.15
-rw-r--r--etc/mtree/BSD.tests.dist4
-rwxr-xr-xetc/periodic/daily/800.scrub-zfs4
-rw-r--r--lib/libc/tests/Makefile2
-rw-r--r--lib/libc/tests/nss/Makefile22
-rw-r--r--lib/libc/tests/nss/getaddrinfo_test.c (renamed from tools/regression/lib/libc/nss/test-getaddr.c)383
-rw-r--r--lib/libc/tests/nss/getgr_test.c (renamed from tools/regression/lib/libc/nss/test-getgr.c)285
-rw-r--r--lib/libc/tests/nss/gethostby_test.c1506
-rw-r--r--lib/libc/tests/nss/getproto_test.c (renamed from tools/regression/lib/libc/nss/test-getproto.c)198
-rw-r--r--lib/libc/tests/nss/getpw_test.c (renamed from tools/regression/lib/libc/nss/test-getpw.c)335
-rw-r--r--lib/libc/tests/nss/getrpc_test.c (renamed from tools/regression/lib/libc/nss/test-getrpc.c)253
-rw-r--r--lib/libc/tests/nss/getserv_test.c (renamed from tools/regression/lib/libc/nss/test-getserv.c)207
-rw-r--r--lib/libc/tests/nss/getusershell_test.c (renamed from tools/regression/lib/libc/nss/test-getusershell.c)92
-rw-r--r--lib/libc/tests/nss/testutil.h (renamed from tools/regression/lib/libc/nss/testutil.h)39
-rw-r--r--lib/libc/tests/resolv/Makefile15
-rw-r--r--lib/libc/tests/resolv/mach46
-rw-r--r--lib/libc/tests/resolv/resolv_test.c (renamed from tools/regression/lib/libc/resolv/resolv.c)167
-rw-r--r--lib/libfetch/http.c12
-rw-r--r--lib/libstand/tftp.c20
-rw-r--r--lib/msun/tests/Makefile25
-rw-r--r--lib/msun/tests/cexp_test.c (renamed from tools/regression/lib/msun/test-cexp.c)0
-rw-r--r--lib/msun/tests/conj_test.c (renamed from tools/regression/lib/msun/test-conj.c)0
-rw-r--r--lib/msun/tests/csqrt_test.c (renamed from tools/regression/lib/msun/test-csqrt.c)0
-rw-r--r--lib/msun/tests/fenv_test.c (renamed from tools/regression/lib/msun/test-fenv.c)0
-rw-r--r--lib/msun/tests/fmaxmin_test.c (renamed from tools/regression/lib/msun/test-fmaxmin.c)0
-rw-r--r--lib/msun/tests/ilogb_test.c (renamed from tools/regression/lib/msun/test-ilogb.c)0
-rw-r--r--lib/msun/tests/invctrig_test.c (renamed from tools/regression/lib/msun/test-invctrig.c)8
-rw-r--r--lib/msun/tests/logarithm_test.c (renamed from tools/regression/lib/msun/test-logarithm.c)0
-rw-r--r--lib/msun/tests/lrint_test.c (renamed from tools/regression/lib/msun/test-lrint.c)0
-rw-r--r--lib/msun/tests/nan_test.c (renamed from tools/regression/lib/msun/test-nan.c)0
-rw-r--r--lib/msun/tests/nearbyint_test.c (renamed from tools/regression/lib/msun/test-nearbyint.c)0
-rw-r--r--lib/msun/tests/next_test.c (renamed from tools/regression/lib/msun/test-next.c)0
-rw-r--r--lib/msun/tests/rem_test.c (renamed from tools/regression/lib/msun/test-rem.c)0
-rw-r--r--lib/msun/tests/trig_test.c (renamed from tools/regression/lib/msun/test-trig.c)0
-rw-r--r--secure/lib/libcrypto/engines/Makefile2
-rw-r--r--share/man/man9/VOP_GETPAGES.919
-rw-r--r--share/mk/src.opts.mk6
-rw-r--r--sys/arm/arm/pmap-v6-new.c21
-rw-r--r--sys/boot/efi/loader/arch/amd64/elf64_freebsd.c7
-rw-r--r--sys/boot/efi/loader/arch/arm/exec.c7
-rw-r--r--sys/boot/efi/loader/arch/arm64/exec.c7
-rw-r--r--sys/boot/efi/loader/bootinfo.c54
-rw-r--r--sys/boot/efi/loader/loader_efi.h2
-rw-r--r--sys/boot/i386/libi386/libi386.h1
-rw-r--r--sys/boot/i386/libi386/pxe.c31
-rw-r--r--sys/boot/i386/loader/main.c5
-rw-r--r--sys/cam/ctl/ctl.c2
-rw-r--r--sys/cam/ctl/ctl_backend_block.c40
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c109
-rw-r--r--sys/cddl/dev/dtrace/dtrace_cddl.h3
-rw-r--r--sys/cddl/dev/systrace/systrace.c173
-rw-r--r--sys/compat/linux/linux_dtrace.h4
-rw-r--r--sys/conf/kmod.mk2
-rw-r--r--sys/dev/drm2/i915/i915_gem.c2
-rw-r--r--sys/dev/drm2/ttm/ttm_tt.c3
-rw-r--r--sys/dev/md/md.c9
-rw-r--r--sys/dev/usb/serial/uftdi.c2
-rw-r--r--sys/fs/fuse/fuse_vnops.c50
-rw-r--r--sys/fs/nfsclient/nfs_clbio.c27
-rw-r--r--sys/fs/smbfs/smbfs_io.c46
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c3
-rw-r--r--sys/geom/multipath/g_multipath.c20
-rw-r--r--sys/kern/kern_exec.c43
-rw-r--r--sys/kern/kern_exit.c4
-rw-r--r--sys/kern/kern_fork.c5
-rw-r--r--sys/kern/kern_proc.c29
-rw-r--r--sys/kern/kern_racct.c67
-rw-r--r--sys/kern/kern_sig.c16
-rw-r--r--sys/kern/kern_timeout.c10
-rw-r--r--sys/kern/subr_syscall.c19
-rw-r--r--sys/kern/uipc_shm.c4
-rw-r--r--sys/kern/uipc_syscalls.c2
-rw-r--r--sys/kern/vfs_bio.c2
-rw-r--r--sys/kern/vfs_cache.c2
-rw-r--r--sys/kern/vfs_default.c52
-rw-r--r--sys/kern/vfs_subr.c46
-rw-r--r--sys/kern/vnode_if.src6
-rw-r--r--sys/modules/Makefile1
-rw-r--r--sys/modules/tcp/fastpath/Makefile15
-rw-r--r--sys/net/if_stf.c28
-rw-r--r--sys/net/route.h3
-rw-r--r--sys/netinet/if_ether.c27
-rw-r--r--sys/netinet/in_kdtrace.c2
-rw-r--r--sys/netinet/in_kdtrace.h8
-rw-r--r--sys/netinet/ip_carp.c2
-rw-r--r--sys/netinet/sctp_cc_functions.c54
-rw-r--r--sys/netinet/tcp.h8
-rw-r--r--sys/netinet/tcp_input.c62
-rw-r--r--sys/netinet/tcp_sack.c2
-rw-r--r--sys/netinet/tcp_stacks/fastpath.c2461
-rw-r--r--sys/netinet/tcp_subr.c312
-rw-r--r--sys/netinet/tcp_syncache.c22
-rw-r--r--sys/netinet/tcp_timer.c21
-rw-r--r--sys/netinet/tcp_usrreq.c105
-rw-r--r--sys/netinet/tcp_var.h80
-rw-r--r--sys/netinet/toecore.c2
-rw-r--r--sys/netinet6/in6.c11
-rw-r--r--sys/netinet6/nd6.c3
-rw-r--r--sys/netinet6/nd6_nbr.c3
-rw-r--r--sys/security/mac/mac_framework.c12
-rw-r--r--sys/security/mac/mac_internal.h32
-rw-r--r--sys/sys/buf.h13
-rw-r--r--sys/sys/sysent.h19
-rw-r--r--sys/sys/vnode.h2
-rw-r--r--sys/vm/default_pager.c12
-rw-r--r--sys/vm/device_pager.c23
-rw-r--r--sys/vm/phys_pager.c14
-rw-r--r--sys/vm/sg_pager.c30
-rw-r--r--sys/vm/swap_pager.c166
-rw-r--r--sys/vm/vm_fault.c196
-rw-r--r--sys/vm/vm_glue.c50
-rw-r--r--sys/vm/vm_object.c2
-rw-r--r--sys/vm/vm_object.h2
-rw-r--r--sys/vm/vm_page.c44
-rw-r--r--sys/vm/vm_page.h17
-rw-r--r--sys/vm/vm_pager.c89
-rw-r--r--sys/vm/vm_pager.h10
-rw-r--r--sys/vm/vnode_pager.c362
-rw-r--r--sys/vm/vnode_pager.h3
-rw-r--r--tests/freebsd_test_suite/macros.h15
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc5
-rw-r--r--tools/regression/lib/libc/nss/Makefile12
-rw-r--r--tools/regression/lib/libc/nss/README203
-rw-r--r--tools/regression/lib/libc/nss/mach93
-rw-r--r--tools/regression/lib/libc/nss/test-getaddr.t33
-rw-r--r--tools/regression/lib/libc/nss/test-getgr.t29
-rw-r--r--tools/regression/lib/libc/nss/test-gethostby.c1105
-rw-r--r--tools/regression/lib/libc/nss/test-gethostby.t113
-rw-r--r--tools/regression/lib/libc/nss/test-getproto.t29
-rw-r--r--tools/regression/lib/libc/nss/test-getpw.t29
-rw-r--r--tools/regression/lib/libc/nss/test-getrpc.t29
-rw-r--r--tools/regression/lib/libc/nss/test-getserv.t29
-rw-r--r--tools/regression/lib/libc/nss/test-getusershell.t22
-rw-r--r--tools/regression/lib/libc/resolv/Makefile14
-rw-r--r--tools/regression/lib/libc/resolv/mach93
-rw-r--r--tools/regression/lib/libc/resolv/resolv.t24
-rw-r--r--tools/regression/lib/msun/Makefile8
-rw-r--r--tools/regression/lib/msun/test-cexp.t10
-rw-r--r--tools/regression/lib/msun/test-conj.t10
-rw-r--r--tools/regression/lib/msun/test-csqrt.t10
-rw-r--r--tools/regression/lib/msun/test-fenv.t10
-rw-r--r--tools/regression/lib/msun/test-fmaxmin.t10
-rw-r--r--tools/regression/lib/msun/test-ilogb.t10
-rw-r--r--tools/regression/lib/msun/test-logarithm.t10
-rw-r--r--tools/regression/lib/msun/test-lrint.t10
-rw-r--r--tools/regression/lib/msun/test-nan.t10
-rw-r--r--tools/regression/lib/msun/test-nearbyint.t10
-rw-r--r--tools/regression/lib/msun/test-next.t10
-rw-r--r--tools/regression/lib/msun/test-rem.t10
-rw-r--r--tools/regression/lib/msun/test-trig.t10
-rw-r--r--usr.bin/netstat/ipsec.c28
-rw-r--r--usr.bin/netstat/main.c10
-rw-r--r--usr.sbin/Makefile.arm3
-rw-r--r--usr.sbin/ndp/ndp.c78
157 files changed, 6768 insertions, 4306 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 907e376..5ea2483 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -37,9 +37,12 @@ contrib/llvm/tools/lldb emaste Pre-commit review preferred.
contrib/netbsd-tests freebsd-testing,ngie Pre-commit review requested.
contrib/pjdfstest freebsd-testing,ngie,pjd Pre-commit review requested.
dev/usb/wlan adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org
+*env(3) secteam Due to the problematic security history of this
+ code, please have patches reviewed by secteam.
etc/mail gshapiro Pre-commit review requested. Keep in sync with -STABLE.
etc/sendmail gshapiro Pre-commit review requested. Keep in sync with -STABLE.
fetch des Pre-commit review requested.
+geli pjd Pre-commit review requested (both sys/geom/eli/ and sbin/geom/class/eli/).
isci(4) jimharris Pre-commit review requested.
iwm(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org
iwn(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org
@@ -51,6 +54,7 @@ lpr gad Pre-commit review requested, particularly for
lpd/recvjob.c and lpd/printjob.c.
nanobsd imp Pre-commit phabricator review requested.
net80211 adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org
+nfs freebsd-fs@FreeBSD.org, rmacklem is best for reviews.
nis(8), yp(8) araujo Pre-commit review requested.
nvd(4) jimharris Pre-commit review requested.
nvme(4) jimharris Pre-commit review requested.
@@ -59,6 +63,7 @@ opencrypto jmg Pre-commit review requested. Documentation Required.
openssh des Pre-commit review requested.
openssl benl,jkim Pre-commit review requested.
otus(4) adrian Pre-commit review requested, send to freebsd-wireless@freebsd.org
+pci bus imp,jhb Pre-commit review requested.
pmcstudy(8) rrs Pre-commit review requested.
procfs des Pre-commit review requested.
pseudofs des Pre-commit review requested.
@@ -92,7 +97,6 @@ contrib/openbsm rwatson Pre-commit review requested.
sys/security/audit rwatson Pre-commit review requested.
ahc(4) gibbs Pre-commit review requested.
ahd(4) gibbs Pre-commit review requested.
-pci bus imp,jhb Pre-commit review requested.
cdboot jhb Pre-commit review requested.
pxeboot jhb Pre-commit review requested.
witness jhb Pre-commit review requested.
@@ -122,7 +126,6 @@ file obrien Insists to keep file blocked from other's unapproved
contrib/bzip2 obrien Pre-commit review required.
geom freebsd-geom@FreeBSD.org
geom_concat pjd Pre-commit review preferred.
-geom_eli pjd Pre-commit review preferred.
geom_gate pjd Pre-commit review preferred.
geom_label pjd Pre-commit review preferred.
geom_mirror pjd Pre-commit review preferred.
@@ -133,7 +136,6 @@ geom_stripe pjd Pre-commit review preferred.
geom_zero pjd Pre-commit review preferred.
sbin/geom pjd Pre-commit review preferred.
zfs freebsd-fs@FreeBSD.org
-nfs freebsd-fs@FreeBSD.org, rmacklem is best for reviews.
linux emul emulation Please discuss changes here.
bs{diff,patch} cperciva Pre-commit review requested.
portsnap cperciva Pre-commit review requested.
@@ -143,8 +145,6 @@ lib/libbluetooth emax Pre-commit review preferred.
lib/libsdp emax Pre-commit review preferred.
usr.bin/bluetooth emax Pre-commit review preferred.
usr.sbin/bluetooth emax Pre-commit review preferred.
-*env(3) secteam Due to the problematic security history of this
- code, please have patches reviewed by secteam.
share/zoneinfo edwin Heads-up appreciated, since our data is coming
from a third party source.
usr.sbin/zic edwin Heads-up appreciated, since this code is
diff --git a/UPDATING b/UPDATING
index b020439..52ce52a 100644
--- a/UPDATING
+++ b/UPDATING
@@ -31,6 +31,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20151216:
+ The tftp loader (pxeboot) now uses the option root-path directive. As a
+ consequence it no longer looks for a pxeboot.4th file on the tftp
+ server. Instead it uses the regular /boot infrastructure as with the
+ other loaders.
+
20151211:
The code to start recording plug and play data into the modules has
been committed. While the old tools will properly build a new kernel,
diff --git a/bin/sh/var.c b/bin/sh/var.c
index cfba0ba..c124a5d 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -330,7 +330,7 @@ setvareq(char *s, int flags)
if (vp->flags & VREADONLY) {
if ((flags & (VTEXTFIXED|VSTACK)) == 0)
ckfree(s);
- error("%.*s: is read only", vp->name_len, s);
+ error("%.*s: is read only", vp->name_len, vp->text);
}
if (flags & VNOSET) {
if ((flags & (VTEXTFIXED|VSTACK)) == 0)
diff --git a/contrib/llvm/tools/lldb/docs/lldb.1 b/contrib/llvm/tools/lldb/docs/lldb.1
index 57b0931..b6084e7 100644
--- a/contrib/llvm/tools/lldb/docs/lldb.1
+++ b/contrib/llvm/tools/lldb/docs/lldb.1
@@ -1,4 +1,4 @@
-.Dd June 7, 2012 \" DATE
+.Dd December 16, 2015 \" DATE
.Dt LLDB 1 \" Program name and manual section number
.Os
.Sh NAME \" Section Header - required - don't modify
@@ -8,6 +8,7 @@
.Nm lldb
.Op Fl hvdexw
.Op Fl a Ar arch
+.Op Fl c Ar core-file
.Op Fl l Ar script-language
.Op Fl s Ar lldb-commands
.Op Fl n Ar process-name
@@ -52,6 +53,8 @@ to it as early in the process-launch as possible.
Specifies a currently running process that
.Nm
should attach to.
+.It Fl c, -core Ar core-file
+Specifies the core file to examine.
.It Fl l, -script-language Ar language
Tells the debugger to use the specified scripting language for
user-defined scripts, rather than the default. Valid scripting
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index 3bfa30c..7887ee4 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -271,10 +271,14 @@
..
..
..
+ nss
+ ..
regex
data
..
..
+ resolv
+ ..
rpc
..
ssp
diff --git a/etc/periodic/daily/800.scrub-zfs b/etc/periodic/daily/800.scrub-zfs
index ee0e52a..359be13 100755
--- a/etc/periodic/daily/800.scrub-zfs
+++ b/etc/periodic/daily/800.scrub-zfs
@@ -43,6 +43,10 @@ case "$daily_scrub_zfs_enable" in
rc=3
echo "Skipping faulted pool: ${pool}"
continue ;;
+ *UNAVAIL*)
+ rc=4
+ echo "Skipping unavailable pool: ${pool}"
+ continue ;;
esac
# determine how many days shall be between scrubs
diff --git a/lib/libc/tests/Makefile b/lib/libc/tests/Makefile
index e6ddc15..a9d8c02 100644
--- a/lib/libc/tests/Makefile
+++ b/lib/libc/tests/Makefile
@@ -10,7 +10,9 @@ TESTS_SUBDIRS+= gen
TESTS_SUBDIRS+= hash
TESTS_SUBDIRS+= inet
TESTS_SUBDIRS+= net
+TESTS_SUBDIRS+= nss
TESTS_SUBDIRS+= regex
+TESTS_SUBDIRS+= resolv
TESTS_SUBDIRS+= rpc
TESTS_SUBDIRS+= stdio
TESTS_SUBDIRS+= stdlib
diff --git a/lib/libc/tests/nss/Makefile b/lib/libc/tests/nss/Makefile
new file mode 100644
index 0000000..1b777c2
--- /dev/null
+++ b/lib/libc/tests/nss/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/lib/libc/nss
+BINDIR= ${TESTSDIR}
+
+.PATH: ${.CURDIR:H}/resolv
+
+FILES+= mach
+
+CFLAGS+= -I${SRCTOP}/tests
+
+ATF_TESTS_C+= getaddrinfo_test
+ATF_TESTS_C+= getgr_test
+ATF_TESTS_C+= gethostby_test
+TEST_METADATA.gethostby_test= timeout="1200"
+ATF_TESTS_C+= getpw_test
+ATF_TESTS_C+= getproto_test
+ATF_TESTS_C+= getrpc_test
+ATF_TESTS_C+= getserv_test
+ATF_TESTS_C+= getusershell_test
+
+.include <bsd.test.mk>
diff --git a/tools/regression/lib/libc/nss/test-getaddr.c b/lib/libc/tests/nss/getaddrinfo_test.c
index f0729ec..0c9704f 100644
--- a/tools/regression/lib/libc/nss/test-getaddr.c
+++ b/lib/libc/tests/nss/getaddrinfo_test.c
@@ -28,11 +28,10 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <arpa/inet.h>
-#include <sys/socket.h>
#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
#include <netinet/in.h>
-#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <resolv.h>
@@ -41,6 +40,10 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <stringlist.h>
#include <unistd.h>
+
+#include <atf-c.h>
+
+#include "freebsd_test_suite/macros.h"
#include "testutil.h"
enum test_methods {
@@ -48,7 +51,6 @@ enum test_methods {
TEST_BUILD_SNAPSHOT
};
-static int debug = 0;
static struct addrinfo hints;
static enum test_methods method = TEST_GETADDRINFO;
@@ -59,7 +61,6 @@ DECLARE_2PASS_TEST(addrinfo)
static void clone_addrinfo(struct addrinfo *, struct addrinfo const *);
static int compare_addrinfo(struct addrinfo *, struct addrinfo *, void *);
static void dump_addrinfo(struct addrinfo *);
-static void free_addrinfo(struct addrinfo *);
static void sdump_addrinfo(struct addrinfo *, char *, size_t);
@@ -70,23 +71,23 @@ IMPLEMENT_2PASS_TEST(addrinfo)
static void
clone_addrinfo(struct addrinfo *dest, struct addrinfo const *src)
{
- assert(dest != NULL);
- assert(src != NULL);
+
+ ATF_REQUIRE(dest != NULL);
+ ATF_REQUIRE(src != NULL);
memcpy(dest, src, sizeof(struct addrinfo));
if (src->ai_canonname != NULL)
dest->ai_canonname = strdup(src->ai_canonname);
if (src->ai_addr != NULL) {
- dest->ai_addr = (struct sockaddr *)malloc(src->ai_addrlen);
- assert(dest->ai_addr != NULL);
+ dest->ai_addr = malloc(src->ai_addrlen);
+ ATF_REQUIRE(dest->ai_addr != NULL);
memcpy(dest->ai_addr, src->ai_addr, src->ai_addrlen);
}
if (src->ai_next != NULL) {
- dest->ai_next = (struct addrinfo *)malloc(
- sizeof(struct addrinfo));
- assert(dest->ai_next != NULL);
+ dest->ai_next = malloc(sizeof(struct addrinfo));
+ ATF_REQUIRE(dest->ai_next != NULL);
clone_addrinfo(dest->ai_next, src->ai_next);
}
}
@@ -94,29 +95,30 @@ clone_addrinfo(struct addrinfo *dest, struct addrinfo const *src)
static int
compare_addrinfo_(struct addrinfo *ai1, struct addrinfo *ai2)
{
+
if ((ai1 == NULL) || (ai2 == NULL))
return (-1);
- if ((ai1->ai_flags != ai2->ai_flags) ||
- (ai1->ai_family != ai2->ai_family) ||
- (ai1->ai_socktype != ai2->ai_socktype) ||
- (ai1->ai_protocol != ai2->ai_protocol) ||
- (ai1->ai_addrlen != ai2->ai_addrlen) ||
- (((ai1->ai_addr == NULL) || (ai2->ai_addr == NULL)) &&
- (ai1->ai_addr != ai2->ai_addr)) ||
- (((ai1->ai_canonname == NULL) || (ai2->ai_canonname == NULL)) &&
- (ai1->ai_canonname != ai2->ai_canonname)))
+ if (ai1->ai_flags != ai2->ai_flags ||
+ ai1->ai_family != ai2->ai_family ||
+ ai1->ai_socktype != ai2->ai_socktype ||
+ ai1->ai_protocol != ai2->ai_protocol ||
+ ai1->ai_addrlen != ai2->ai_addrlen ||
+ ((ai1->ai_addr == NULL || ai2->ai_addr == NULL) &&
+ ai1->ai_addr != ai2->ai_addr) ||
+ ((ai1->ai_canonname == NULL || ai2->ai_canonname == NULL) &&
+ ai1->ai_canonname != ai2->ai_canonname))
return (-1);
- if ((ai1->ai_canonname != NULL) &&
- (strcmp(ai1->ai_canonname, ai2->ai_canonname) != 0))
+ if (ai1->ai_canonname != NULL &&
+ strcmp(ai1->ai_canonname, ai2->ai_canonname) != 0)
return (-1);
- if ((ai1->ai_addr != NULL) &&
- (memcmp(ai1->ai_addr, ai2->ai_addr, ai1->ai_addrlen) != 0))
+ if (ai1->ai_addr != NULL &&
+ memcmp(ai1->ai_addr, ai2->ai_addr, ai1->ai_addrlen) != 0)
return (-1);
- if ((ai1->ai_next == NULL) && (ai2->ai_next == NULL))
+ if (ai1->ai_next == NULL && ai2->ai_next == NULL)
return (0);
else
return (compare_addrinfo_(ai1->ai_next, ai2->ai_next));
@@ -127,20 +129,16 @@ compare_addrinfo(struct addrinfo *ai1, struct addrinfo *ai2, void *mdata)
{
int rv;
- if (debug) {
- printf("testing equality of 2 addrinfo structures\n");
- }
+ printf("testing equality of 2 addrinfo structures\n");
rv = compare_addrinfo_(ai1, ai2);
- if (debug) {
- if (rv == 0)
- printf("equal\n");
- else {
- dump_addrinfo(ai1);
- dump_addrinfo(ai2);
- printf("not equal\n");
- }
+ if (rv == 0)
+ printf("equal\n");
+ else {
+ dump_addrinfo(ai1);
+ dump_addrinfo(ai2);
+ printf("not equal\n");
}
return (rv);
@@ -184,18 +182,18 @@ sdump_addrinfo(struct addrinfo *ai, char *buffer, size_t buflen)
return;
buflen -= written;
} else {
- for (i = 0; i < ai->ai_addrlen; ++i ) {
- written = snprintf(buffer, buflen,
- i + 1 != ai->ai_addrlen ? "%d." : "%d",
- ((unsigned char *)ai->ai_addr)[i]);
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
-
- if (buflen == 0)
- return;
- }
+ for (i = 0; i < ai->ai_addrlen; i++) {
+ written = snprintf(buffer, buflen,
+ i + 1 != ai->ai_addrlen ? "%d." : "%d",
+ ((unsigned char *)ai->ai_addr)[i]);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
}
if (ai->ai_next != NULL) {
@@ -226,7 +224,7 @@ addrinfo_read_snapshot_addr(char *addr, unsigned char *result, size_t len)
char *s, *ps, *ts;
ps = addr;
- while ( (s = strsep(&ps, ".")) != NULL) {
+ while ((s = strsep(&ps, ".")) != NULL) {
if (len == 0)
return (-1);
@@ -253,55 +251,53 @@ addrinfo_read_snapshot_ai(struct addrinfo *ai, char *line)
i = 0;
ps = line;
memset(ai, 0, sizeof(struct addrinfo));
- while ( (s = strsep(&ps, " ")) != NULL) {
+ while ((s = strsep(&ps, " ")) != NULL) {
switch (i) {
- case 0:
- case 1:
- case 2:
- case 3:
- pi = &ai->ai_flags + i;
- *pi = (int)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
- break;
- case 4:
- ai->ai_addrlen = (socklen_t)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
- break;
- case 5:
- if (strcmp(s, "(null)") != 0) {
- ai->ai_canonname = strdup(s);
- assert(ai->ai_canonname != NULL);
- }
- break;
- case 6:
- if (strcmp(s, "(null)") != 0) {
- ai->ai_addr = (struct sockaddr *)malloc(
- ai->ai_addrlen);
- assert(ai->ai_addr != NULL);
- memset(ai->ai_addr, 0, ai->ai_addrlen);
- rv = addrinfo_read_snapshot_addr(s,
- (unsigned char *)ai->ai_addr,
- ai->ai_addrlen);
-
- if (rv != 0)
- goto fin;
- }
- break;
- default:
- /* NOTE: should not be reachable */
- rv = -1;
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ pi = &ai->ai_flags + i;
+ *pi = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+ case 4:
+ ai->ai_addrlen = (socklen_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
goto fin;
- };
+ break;
+ case 5:
+ if (strcmp(s, "(null)") != 0) {
+ ai->ai_canonname = strdup(s);
+ ATF_REQUIRE(ai->ai_canonname != NULL);
+ }
+ break;
+ case 6:
+ if (strcmp(s, "(null)") != 0) {
+ ai->ai_addr = calloc(1, ai->ai_addrlen);
+ ATF_REQUIRE(ai->ai_addr != NULL);
+ rv = addrinfo_read_snapshot_addr(s,
+ (unsigned char *)ai->ai_addr,
+ ai->ai_addrlen);
+
+ if (rv != 0)
+ goto fin;
+ }
+ break;
+ default:
+ /* NOTE: should not be reachable */
+ rv = -1;
+ goto fin;
+ }
++i;
}
fin:
- if ((i != 7) || (rv != 0)) {
+ if (i != 7 || rv != 0) {
free_addrinfo(ai);
- memset(ai, 0, sizeof(struct addrinfo));
+ ai = NULL;
return (-1);
}
@@ -315,8 +311,7 @@ addrinfo_read_snapshot_func(struct addrinfo *ai, char *line)
char *s, *ps;
int i, rv;
- if (debug)
- printf("1 line read from snapshot:\n%s\n", line);
+ printf("1 line read from snapshot:\n%s\n", line);
rv = 0;
i = 0;
@@ -331,15 +326,14 @@ addrinfo_read_snapshot_func(struct addrinfo *ai, char *line)
return (-1);
ai2 = ai;
- while ( (s = strsep(&ps, ":")) != NULL) {
- ai2->ai_next = (struct addrinfo *)malloc(
- sizeof(struct addrinfo));
- assert(ai2->ai_next != NULL);
- memset(ai2->ai_next, 0, sizeof(struct addrinfo));
+ while ((s = strsep(&ps, ":")) != NULL) {
+ ai2->ai_next = calloc(1, sizeof(struct addrinfo));
+ ATF_REQUIRE(ai2->ai_next != NULL);
rv = addrinfo_read_snapshot_ai(ai2->ai_next, s);
if (rv != 0) {
free_addrinfo(ai);
+ ai = NULL;
return (-1);
}
@@ -352,39 +346,36 @@ addrinfo_read_snapshot_func(struct addrinfo *ai, char *line)
static int
addrinfo_test_correctness(struct addrinfo *ai, void *mdata)
{
- if (debug) {
- printf("testing correctness with the following data:\n");
- dump_addrinfo(ai);
- }
+
+ printf("testing correctness with the following data:\n");
+ dump_addrinfo(ai);
if (ai == NULL)
goto errfin;
- if (!((ai->ai_family >= 0) && (ai->ai_family < AF_MAX)))
+ if (!(ai->ai_family >= 0 && ai->ai_family < AF_MAX))
goto errfin;
- if ((ai->ai_socktype != 0) && (ai->ai_socktype != SOCK_STREAM) &&
- (ai->ai_socktype != SOCK_DGRAM) && (ai->ai_socktype != SOCK_RAW))
+ if (ai->ai_socktype != 0 && ai->ai_socktype != SOCK_STREAM &&
+ ai->ai_socktype != SOCK_DGRAM && ai->ai_socktype != SOCK_RAW)
goto errfin;
- if ((ai->ai_protocol != 0) && (ai->ai_protocol != IPPROTO_UDP) &&
- (ai->ai_protocol != IPPROTO_TCP))
+ if (ai->ai_protocol != 0 && ai->ai_protocol != IPPROTO_UDP &&
+ ai->ai_protocol != IPPROTO_TCP)
goto errfin;
if ((ai->ai_flags & ~(AI_CANONNAME | AI_NUMERICHOST | AI_PASSIVE)) != 0)
goto errfin;
- if ((ai->ai_addrlen != ai->ai_addr->sa_len) ||
- (ai->ai_family != ai->ai_addr->sa_family))
+ if (ai->ai_addrlen != ai->ai_addr->sa_len ||
+ ai->ai_family != ai->ai_addr->sa_family)
goto errfin;
- if (debug)
- printf("correct\n");
+ printf("correct\n");
return (0);
errfin:
- if (debug)
- printf("incorrect\n");
+ printf("incorrect\n");
return (-1);
}
@@ -395,93 +386,49 @@ addrinfo_read_hostlist_func(struct addrinfo *ai, char *line)
struct addrinfo *result;
int rv;
- if (debug)
- printf("resolving %s: ", line);
+ printf("resolving %s: ", line);
rv = getaddrinfo(line, NULL, &hints, &result);
if (rv == 0) {
- if (debug)
- printf("found\n");
+ printf("found\n");
rv = addrinfo_test_correctness(result, NULL);
if (rv != 0) {
freeaddrinfo(result);
+ result = NULL;
return (rv);
}
clone_addrinfo(ai, result);
freeaddrinfo(result);
+ result = NULL;
} else {
- if (debug)
- printf("not found\n");
+ printf("not found\n");
memset(ai, 0, sizeof(struct addrinfo));
}
return (0);
}
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s [-d] [-46] [-s <file]> -f <file>\n",
- getprogname());
- exit(1);
-}
-
-int
-main(int argc, char **argv)
+void
+run_tests(char *hostlist_file, char *snapshot_file, int ai_family)
{
struct addrinfo_test_data td, td_snap;
- char *snapshot_file, *hostlist_file;
int rv;
- int c;
- if (argc < 2)
- usage();
-
- snapshot_file = NULL;
- hostlist_file = NULL;
memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = PF_UNSPEC;
+ hints.ai_family = ai_family;
hints.ai_flags = AI_CANONNAME;
- while ((c = getopt(argc, argv, "46dns:f:")) != -1)
- switch (c) {
- case '4':
- hints.ai_family = PF_INET;
- break;
- case '6':
- hints.ai_family = PF_INET6;
- break;
- case 'd':
- debug = 1;
- break;
- case 's':
- snapshot_file = strdup(optarg);
- method = TEST_BUILD_SNAPSHOT;
- break;
- case 'f':
- hostlist_file = strdup(optarg);
- break;
- default:
- usage();
- }
+
+ if (snapshot_file != NULL)
+ method = TEST_BUILD_SNAPSHOT;
TEST_DATA_INIT(addrinfo, &td, clone_addrinfo, free_addrinfo);
TEST_DATA_INIT(addrinfo, &td_snap, clone_addrinfo, free_addrinfo);
- if (hostlist_file == NULL)
- usage();
+ ATF_REQUIRE_MSG(access(hostlist_file, R_OK) == 0,
+ "can't access the hostlist file %s\n", hostlist_file);
- if (access(hostlist_file, R_OK) != 0) {
- if (debug)
- printf("can't access the hostlist file %s\n",
- hostlist_file);
-
- usage();
- }
-
- if (debug)
- printf("building host lists from %s\n", hostlist_file);
+ printf("building host lists from %s\n", hostlist_file);
rv = TEST_SNAPSHOT_FILE_READ(addrinfo, hostlist_file, &td,
addrinfo_read_hostlist_func);
@@ -493,9 +440,8 @@ main(int argc, char **argv)
if (errno == ENOENT)
method = TEST_BUILD_SNAPSHOT;
else {
- if (debug)
- printf("can't access the snapshot file %s\n",
- snapshot_file);
+ printf("can't access the snapshot "
+ "file %s\n", snapshot_file);
rv = -1;
goto fin;
@@ -504,8 +450,8 @@ main(int argc, char **argv)
rv = TEST_SNAPSHOT_FILE_READ(addrinfo, snapshot_file,
&td_snap, addrinfo_read_snapshot_func);
if (rv != 0) {
- if (debug)
- printf("error reading snapshot file\n");
+ printf("error reading snapshot file: %s\n",
+ strerror(errno));
goto fin;
}
}
@@ -514,26 +460,97 @@ main(int argc, char **argv)
switch (method) {
case TEST_GETADDRINFO:
if (snapshot_file != NULL)
- rv = DO_2PASS_TEST(addrinfo, &td, &td_snap,
- compare_addrinfo, NULL);
+ ATF_CHECK(DO_2PASS_TEST(addrinfo, &td, &td_snap,
+ compare_addrinfo, NULL) == 0);
break;
case TEST_BUILD_SNAPSHOT:
if (snapshot_file != NULL) {
- rv = TEST_SNAPSHOT_FILE_WRITE(addrinfo, snapshot_file, &td,
- sdump_addrinfo);
+ ATF_CHECK(TEST_SNAPSHOT_FILE_WRITE(addrinfo,
+ snapshot_file, &td, sdump_addrinfo) == 0);
}
break;
default:
- rv = 0;
break;
- };
+ }
fin:
TEST_DATA_DESTROY(addrinfo, &td_snap);
TEST_DATA_DESTROY(addrinfo, &td);
+
free(hostlist_file);
free(snapshot_file);
- return (rv);
+}
+
+#define HOSTLIST_FILE "mach"
+#define RUN_TESTS(tc, snapshot_file, ai_family) do { \
+ char *_hostlist_file; \
+ char *_snapshot_file; \
+ ATF_REQUIRE(0 < asprintf(&_hostlist_file, "%s/%s", \
+ atf_tc_get_config_var(tc, "srcdir"), HOSTLIST_FILE)); \
+ if (snapshot_file == NULL) \
+ _snapshot_file = NULL; \
+ else { \
+ _snapshot_file = strdup(snapshot_file); \
+ ATF_REQUIRE(_snapshot_file != NULL); \
+ } \
+ run_tests(_hostlist_file, _snapshot_file, ai_family); \
+} while(0)
+
+ATF_TC_WITHOUT_HEAD(pf_unspec);
+ATF_TC_BODY(pf_unspec, tc)
+{
+
+ RUN_TESTS(tc, NULL, AF_UNSPEC);
+}
+
+ATF_TC_WITHOUT_HEAD(pf_unspec_with_snapshot);
+ATF_TC_BODY(pf_unspec_with_snapshot, tc)
+{
+
+ RUN_TESTS(tc, "snapshot_ai", AF_UNSPEC);
+}
+
+ATF_TC_WITHOUT_HEAD(pf_inet);
+ATF_TC_BODY(pf_inet, tc)
+{
+
+ ATF_REQUIRE_FEATURE("inet");
+ RUN_TESTS(tc, NULL, AF_INET);
+}
+ATF_TC_WITHOUT_HEAD(pf_inet_with_snapshot);
+ATF_TC_BODY(pf_inet_with_snapshot, tc)
+{
+
+ ATF_REQUIRE_FEATURE("inet");
+ RUN_TESTS(tc, "snapshot_ai4", AF_INET);
}
+ATF_TC_WITHOUT_HEAD(pf_inet6);
+ATF_TC_BODY(pf_inet6, tc)
+{
+
+ ATF_REQUIRE_FEATURE("inet6");
+ RUN_TESTS(tc, NULL, AF_INET6);
+}
+
+ATF_TC_WITHOUT_HEAD(pf_inet6_with_snapshot);
+ATF_TC_BODY(pf_inet6_with_snapshot, tc)
+{
+
+ ATF_REQUIRE_FEATURE("inet6");
+ RUN_TESTS(tc, "snapshot_ai6", AF_INET6);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, pf_unspec);
+ ATF_TP_ADD_TC(tp, pf_unspec_with_snapshot);
+ ATF_TP_ADD_TC(tp, pf_inet);
+ ATF_TP_ADD_TC(tp, pf_inet_with_snapshot);
+ ATF_TP_ADD_TC(tp, pf_inet6);
+ ATF_TP_ADD_TC(tp, pf_inet6_with_snapshot);
+
+ return (atf_no_error());
+}
diff --git a/tools/regression/lib/libc/nss/test-getgr.c b/lib/libc/tests/nss/getgr_test.c
index 0ccebae..d9851ef 100644
--- a/tools/regression/lib/libc/nss/test-getgr.c
+++ b/lib/libc/tests/nss/getgr_test.c
@@ -29,7 +29,6 @@
__FBSDID("$FreeBSD$");
#include <arpa/inet.h>
-#include <assert.h>
#include <errno.h>
#include <grp.h>
#include <stdio.h>
@@ -37,17 +36,19 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <stringlist.h>
#include <unistd.h>
+
+#include <atf-c.h>
+
#include "testutil.h"
enum test_methods {
- TEST_GETGRENT,
- TEST_GETGRNAM,
- TEST_GETGRGID,
- TEST_GETGRENT_2PASS,
- TEST_BUILD_SNAPSHOT
+ TEST_GETGRENT = 1,
+ TEST_GETGRNAM = 2,
+ TEST_GETGRGID = 4,
+ TEST_GETGRENT_2PASS = 8,
+ TEST_BUILD_SNAPSHOT = 16,
};
-static int debug = 0;
static enum test_methods method = TEST_BUILD_SNAPSHOT;
DECLARE_TEST_DATA(group)
@@ -71,8 +72,6 @@ static int group_test_getgrnam(struct group *, void *);
static int group_test_getgrgid(struct group *, void *);
static int group_test_getgrent(struct group *, void *);
-static void usage(void) __attribute__((__noreturn__));
-
IMPLEMENT_TEST_DATA(group)
IMPLEMENT_TEST_FILE_SNAPSHOT(group)
IMPLEMENT_1PASS_TEST(group)
@@ -81,8 +80,8 @@ IMPLEMENT_2PASS_TEST(group)
static void
clone_group(struct group *dest, struct group const *src)
{
- assert(dest != NULL);
- assert(src != NULL);
+ ATF_REQUIRE(dest != NULL);
+ ATF_REQUIRE(src != NULL);
char **cp;
int members_num;
@@ -91,12 +90,12 @@ clone_group(struct group *dest, struct group const *src)
if (src->gr_name != NULL) {
dest->gr_name = strdup(src->gr_name);
- assert(dest->gr_name != NULL);
+ ATF_REQUIRE(dest->gr_name != NULL);
}
if (src->gr_passwd != NULL) {
dest->gr_passwd = strdup(src->gr_passwd);
- assert(dest->gr_passwd != NULL);
+ ATF_REQUIRE(dest->gr_passwd != NULL);
}
dest->gr_gid = src->gr_gid;
@@ -105,14 +104,12 @@ clone_group(struct group *dest, struct group const *src)
for (cp = src->gr_mem; *cp; ++cp)
++members_num;
- dest->gr_mem = (char **)malloc(
- (members_num + 1) * (sizeof(char *)));
- assert(dest->gr_mem != NULL);
- memset(dest->gr_mem, 0, (members_num+1) * (sizeof(char *)));
+ dest->gr_mem = calloc(1, (members_num + 1) * sizeof(char *));
+ ATF_REQUIRE(dest->gr_mem != NULL);
for (cp = src->gr_mem; *cp; ++cp) {
dest->gr_mem[cp - src->gr_mem] = strdup(*cp);
- assert(dest->gr_mem[cp - src->gr_mem] != NULL);
+ ATF_REQUIRE(dest->gr_mem[cp - src->gr_mem] != NULL);
}
}
}
@@ -122,7 +119,7 @@ free_group(struct group *grp)
{
char **cp;
- assert(grp != NULL);
+ ATF_REQUIRE(grp != NULL);
free(grp->gr_name);
free(grp->gr_passwd);
@@ -140,31 +137,31 @@ compare_group(struct group *grp1, struct group *grp2, void *mdata)
if (grp1 == grp2)
return (0);
- if ((grp1 == NULL) || (grp2 == NULL))
+ if (grp1 == NULL || grp2 == NULL)
goto errfin;
- if ((strcmp(grp1->gr_name, grp2->gr_name) != 0) ||
- (strcmp(grp1->gr_passwd, grp2->gr_passwd) != 0) ||
- (grp1->gr_gid != grp2->gr_gid))
+ if (strcmp(grp1->gr_name, grp2->gr_name) != 0 ||
+ strcmp(grp1->gr_passwd, grp2->gr_passwd) != 0 ||
+ grp1->gr_gid != grp2->gr_gid)
goto errfin;
c1 = grp1->gr_mem;
c2 = grp2->gr_mem;
- if ((grp1->gr_mem == NULL) || (grp2->gr_mem == NULL))
+ if (grp1->gr_mem == NULL || grp2->gr_mem == NULL)
goto errfin;
- for (;*c1 && *c2; ++c1, ++c2)
+ for (; *c1 && *c2; ++c1, ++c2)
if (strcmp(*c1, *c2) != 0)
goto errfin;
- if ((*c1 != '\0') || (*c2 != '\0'))
+ if (*c1 != '\0' || *c2 != '\0')
goto errfin;
return 0;
errfin:
- if ((debug) && (mdata == NULL)) {
+ if (mdata == NULL) {
printf("following structures are not equal:\n");
dump_group(grp1);
dump_group(grp2);
@@ -211,54 +208,55 @@ group_read_snapshot_func(struct group *grp, char *line)
char *s, *ps, *ts;
int i;
- if (debug)
- printf("1 line read from snapshot:\n%s\n", line);
+ printf("1 line read from snapshot:\n%s\n", line);
i = 0;
sl = NULL;
ps = line;
memset(grp, 0, sizeof(struct group));
- while ( (s = strsep(&ps, " ")) != NULL) {
+ while ((s = strsep(&ps, " ")) != NULL) {
switch (i) {
- case 0:
- grp->gr_name = strdup(s);
- assert(grp->gr_name != NULL);
+ case 0:
+ grp->gr_name = strdup(s);
+ ATF_REQUIRE(grp->gr_name != NULL);
break;
- case 1:
- grp->gr_passwd = strdup(s);
- assert(grp->gr_passwd != NULL);
+ case 1:
+ grp->gr_passwd = strdup(s);
+ ATF_REQUIRE(grp->gr_passwd != NULL);
break;
- case 2:
- grp->gr_gid = (gid_t)strtol(s, &ts, 10);
- if (*ts != '\0') {
- free(grp->gr_name);
- free(grp->gr_passwd);
- return (-1);
- }
+ case 2:
+ grp->gr_gid = (gid_t)strtol(s, &ts, 10);
+ if (*ts != '\0') {
+ free(grp->gr_name);
+ free(grp->gr_passwd);
+ grp->gr_name = NULL;
+ grp->gr_passwd = NULL;
+ return (-1);
+ }
break;
- default:
- if (sl == NULL) {
- if (strcmp(s, "(null)") == 0)
- return (0);
+ default:
+ if (sl == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
- sl = sl_init();
- assert(sl != NULL);
+ sl = sl_init();
+ ATF_REQUIRE(sl != NULL);
- if (strcmp(s, "nomem") != 0) {
- ts = strdup(s);
- assert(ts != NULL);
- sl_add(sl, ts);
- }
- } else {
+ if (strcmp(s, "nomem") != 0) {
ts = strdup(s);
- assert(ts != NULL);
+ ATF_REQUIRE(ts != NULL);
sl_add(sl, ts);
}
+ } else {
+ ts = strdup(s);
+ ATF_REQUIRE(ts != NULL);
+ sl_add(sl, ts);
+ }
break;
- };
+ }
++i;
}
@@ -308,10 +306,8 @@ group_fill_test_data(struct group_test_data *td)
static int
group_test_correctness(struct group *grp, void *mdata)
{
- if (debug) {
- printf("testing correctness with the following data:\n");
- dump_group(grp);
- }
+ printf("testing correctness with the following data:\n");
+ dump_group(grp);
if (grp == NULL)
goto errfin;
@@ -325,13 +321,11 @@ group_test_correctness(struct group *grp, void *mdata)
if (grp->gr_mem == NULL)
goto errfin;
- if (debug)
- printf("correct\n");
+ printf("correct\n");
return (0);
errfin:
- if (debug)
- printf("incorrect\n");
+ printf("incorrect\n");
return (-1);
}
@@ -352,28 +346,20 @@ group_test_getgrnam(struct group *grp_model, void *mdata)
{
struct group *grp;
- if (debug) {
- printf("testing getgrnam() with the following data:\n");
- dump_group(grp_model);
- }
+ printf("testing getgrnam() with the following data:\n");
+ dump_group(grp_model);
grp = getgrnam(grp_model->gr_name);
if (group_test_correctness(grp, NULL) != 0)
goto errfin;
- if ((compare_group(grp, grp_model, NULL) != 0) &&
- (group_check_ambiguity((struct group_test_data *)mdata, grp)
- !=0))
+ if (compare_group(grp, grp_model, NULL) != 0 &&
+ group_check_ambiguity((struct group_test_data *)mdata, grp) != 0)
goto errfin;
- if (debug)
- printf("ok\n");
return (0);
errfin:
- if (debug)
- printf("not ok\n");
-
return (-1);
}
@@ -382,23 +368,16 @@ group_test_getgrgid(struct group *grp_model, void *mdata)
{
struct group *grp;
- if (debug) {
- printf("testing getgrgid() with the following data...\n");
- dump_group(grp_model);
- }
+ printf("testing getgrgid() with the following data...\n");
+ dump_group(grp_model);
grp = getgrgid(grp_model->gr_gid);
- if ((group_test_correctness(grp, NULL) != 0) ||
- ((compare_group(grp, grp_model, NULL) != 0) &&
- (group_check_ambiguity((struct group_test_data *)mdata, grp)
- != 0))) {
- if (debug)
- printf("not ok\n");
- return (-1);
+ if (group_test_correctness(grp, NULL) != 0 ||
+ (compare_group(grp, grp_model, NULL) != 0 &&
+ group_check_ambiguity((struct group_test_data *)mdata, grp) != 0)) {
+ return (-1);
} else {
- if (debug)
- printf("ok\n");
- return (0);
+ return (0);
}
}
@@ -410,50 +389,11 @@ group_test_getgrent(struct group *grp, void *mdata)
return (group_test_correctness(grp, NULL));
}
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s -nge2 [-d] [-s <file>]\n",
- getprogname());
- exit(1);
-}
-
-int
-main(int argc, char **argv)
+static int
+run_tests(const char *snapshot_file, enum test_methods method)
{
struct group_test_data td, td_snap, td_2pass;
- char *snapshot_file;
int rv;
- int c;
-
- if (argc < 2)
- usage();
-
- snapshot_file = NULL;
- while ((c = getopt(argc, argv, "nge2ds:")) != -1)
- switch (c) {
- case 'd':
- debug++;
- break;
- case 'n':
- method = TEST_GETGRNAM;
- break;
- case 'g':
- method = TEST_GETGRGID;
- break;
- case 'e':
- method = TEST_GETGRENT;
- break;
- case '2':
- method = TEST_GETGRENT_2PASS;
- break;
- case 's':
- snapshot_file = strdup(optarg);
- break;
- default:
- usage();
- }
TEST_DATA_INIT(group, &td, clone_group, free_group);
TEST_DATA_INIT(group, &td_snap, clone_group, free_group);
@@ -462,9 +402,8 @@ main(int argc, char **argv)
if (errno == ENOENT)
method = TEST_BUILD_SNAPSHOT;
else {
- if (debug)
- printf("can't access the file %s\n",
- snapshot_file);
+ printf("can't access the file %s\n",
+ snapshot_file);
rv = -1;
goto fin;
@@ -518,17 +457,85 @@ main(int argc, char **argv)
break;
case TEST_BUILD_SNAPSHOT:
if (snapshot_file != NULL)
- rv = TEST_SNAPSHOT_FILE_WRITE(group, snapshot_file, &td,
- sdump_group);
+ rv = TEST_SNAPSHOT_FILE_WRITE(group, snapshot_file, &td,
+ sdump_group);
break;
default:
rv = 0;
break;
- };
+ }
fin:
TEST_DATA_DESTROY(group, &td_snap);
TEST_DATA_DESTROY(group, &td);
- free(snapshot_file);
+
return (rv);
}
+
+#define SNAPSHOT_FILE "snapshot_grp"
+
+ATF_TC_BODY(getgrent, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getgrent_with_snapshot);
+ATF_TC_BODY(getgrent_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getgrent_with_two_pass);
+ATF_TC_BODY(getgrent_with_two_pass, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRENT_2PASS) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getgrgid);
+ATF_TC_BODY(getgrgid, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRGID) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getgrgid_with_snapshot);
+ATF_TC_BODY(getgrgid_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRGID) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getgrnam);
+ATF_TC_BODY(getgrnam, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRNAM) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getgrnam_with_snapshot);
+ATF_TC_BODY(getgrnam_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETGRNAM) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getgrent);
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getgrent);
+ ATF_TP_ADD_TC(tp, getgrent_with_snapshot);
+ ATF_TP_ADD_TC(tp, getgrent_with_two_pass);
+ ATF_TP_ADD_TC(tp, getgrgid);
+ ATF_TP_ADD_TC(tp, getgrgid_with_snapshot);
+ ATF_TP_ADD_TC(tp, getgrnam);
+ ATF_TP_ADD_TC(tp, getgrnam_with_snapshot);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/nss/gethostby_test.c b/lib/libc/tests/nss/gethostby_test.c
new file mode 100644
index 0000000..bdeafbc
--- /dev/null
+++ b/lib/libc/tests/nss/gethostby_test.c
@@ -0,0 +1,1506 @@
+/*-
+ * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+#include "freebsd_test_suite/macros.h"
+#include "testutil.h"
+
+enum test_methods {
+ TEST_GETHOSTBYNAME2,
+ TEST_GETHOSTBYADDR,
+ TEST_GETHOSTBYNAME2_GETADDRINFO,
+ TEST_GETHOSTBYADDR_GETNAMEINFO,
+ TEST_BUILD_SNAPSHOT,
+ TEST_BUILD_ADDR_SNAPSHOT
+};
+
+static int ipnode_flags = 0;
+static int af_type = AF_INET;
+static bool use_ipnode_functions;
+
+DECLARE_TEST_DATA(hostent)
+DECLARE_TEST_FILE_SNAPSHOT(hostent)
+DECLARE_1PASS_TEST(hostent)
+DECLARE_2PASS_TEST(hostent)
+
+/* These stubs will use gethostby***() or getipnodeby***() functions,
+ * depending on the use_ipnode_functions global variable value */
+static struct hostent *__gethostbyname2(const char *, int);
+static struct hostent *__gethostbyaddr(const void *, socklen_t, int);
+static void __freehostent(struct hostent *);
+
+static void clone_hostent(struct hostent *, struct hostent const *);
+static int compare_hostent(struct hostent *, struct hostent *, void *);
+static void dump_hostent(struct hostent *);
+static void free_hostent(struct hostent *);
+
+static int is_hostent_equal(struct hostent *, struct addrinfo *);
+
+static void sdump_hostent(struct hostent *, char *, size_t);
+static int hostent_read_hostlist_func(struct hostent *, char *);
+static int hostent_read_snapshot_addr(char *, unsigned char *, size_t);
+static int hostent_read_snapshot_func(struct hostent *, char *);
+
+static int hostent_test_correctness(struct hostent *, void *);
+static int hostent_test_gethostbyaddr(struct hostent *, void *);
+static int hostent_test_getaddrinfo_eq(struct hostent *, void *);
+static int hostent_test_getnameinfo_eq(struct hostent *, void *);
+
+static void usage(void) __attribute__((__noreturn__));
+
+IMPLEMENT_TEST_DATA(hostent)
+IMPLEMENT_TEST_FILE_SNAPSHOT(hostent)
+IMPLEMENT_1PASS_TEST(hostent)
+IMPLEMENT_2PASS_TEST(hostent)
+
+static struct hostent *
+__gethostbyname2(const char *name, int af)
+{
+ struct hostent *he;
+ int error;
+
+ if (use_ipnode_functions) {
+ error = 0;
+ he = getipnodebyname(name, af, ipnode_flags, &error);
+ if (he == NULL)
+ errno = error;
+ } else
+ he = gethostbyname2(name, af);
+
+ return (he);
+}
+
+static struct hostent *
+__gethostbyaddr(const void *addr, socklen_t len, int af)
+{
+ struct hostent *he;
+ int error;
+
+ if (use_ipnode_functions) {
+ error = 0;
+ he = getipnodebyaddr(addr, len, af, &error);
+ if (he == NULL)
+ errno = error;
+ } else
+ he = gethostbyaddr(addr, len, af);
+
+ return (he);
+}
+
+static void
+__freehostent(struct hostent *he)
+{
+
+ /* NOTE: checking for he != NULL - just in case */
+ if (use_ipnode_functions && he != NULL)
+ freehostent(he);
+}
+
+static void
+clone_hostent(struct hostent *dest, struct hostent const *src)
+{
+ ATF_REQUIRE(dest != NULL);
+ ATF_REQUIRE(src != NULL);
+
+ char **cp;
+ int aliases_num;
+ int addrs_num;
+ size_t offset;
+
+ memset(dest, 0, sizeof(struct hostent));
+
+ if (src->h_name != NULL) {
+ dest->h_name = strdup(src->h_name);
+ ATF_REQUIRE(dest->h_name != NULL);
+ }
+
+ dest->h_addrtype = src->h_addrtype;
+ dest->h_length = src->h_length;
+
+ if (src->h_aliases != NULL) {
+ aliases_num = 0;
+ for (cp = src->h_aliases; *cp; ++cp)
+ ++aliases_num;
+
+ dest->h_aliases = calloc(1, (aliases_num + 1) *
+ sizeof(char *));
+ ATF_REQUIRE(dest->h_aliases != NULL);
+
+ for (cp = src->h_aliases; *cp; ++cp) {
+ dest->h_aliases[cp - src->h_aliases] = strdup(*cp);
+ ATF_REQUIRE(dest->h_aliases[cp - src->h_aliases] != NULL);
+ }
+ }
+
+ if (src->h_addr_list != NULL) {
+ addrs_num = 0;
+ for (cp = src->h_addr_list; *cp; ++cp)
+ ++addrs_num;
+
+ dest->h_addr_list = calloc(1, (addrs_num + 1) * sizeof(char *));
+ ATF_REQUIRE(dest->h_addr_list != NULL);
+
+ for (cp = src->h_addr_list; *cp; ++cp) {
+ offset = cp - src->h_addr_list;
+ dest->h_addr_list[offset] = malloc(src->h_length);
+ ATF_REQUIRE(dest->h_addr_list[offset] != NULL);
+ memcpy(dest->h_addr_list[offset],
+ src->h_addr_list[offset], src->h_length);
+ }
+ }
+}
+
+static void
+free_hostent(struct hostent *ht)
+{
+ char **cp;
+
+ ATF_REQUIRE(ht != NULL);
+
+ free(ht->h_name);
+
+ if (ht->h_aliases != NULL) {
+ for (cp = ht->h_aliases; *cp; ++cp)
+ free(*cp);
+ free(ht->h_aliases);
+ }
+
+ if (ht->h_addr_list != NULL) {
+ for (cp = ht->h_addr_list; *cp; ++cp)
+ free(*cp);
+ free(ht->h_addr_list);
+ }
+}
+
+static int
+compare_hostent(struct hostent *ht1, struct hostent *ht2, void *mdata)
+{
+ char **c1, **c2, **ct, **cb;
+ int b;
+
+ if (ht1 == ht2)
+ return 0;
+
+ if (ht1 == NULL || ht2 == NULL)
+ goto errfin;
+
+ if (ht1->h_name == NULL || ht2->h_name == NULL)
+ goto errfin;
+
+ if (ht1->h_addrtype != ht2->h_addrtype ||
+ ht1->h_length != ht2->h_length ||
+ strcmp(ht1->h_name, ht2->h_name) != 0)
+ goto errfin;
+
+ c1 = ht1->h_aliases;
+ c2 = ht2->h_aliases;
+
+ if ((ht1->h_aliases == NULL || ht2->h_aliases == NULL) &&
+ ht1->h_aliases != ht2->h_aliases)
+ goto errfin;
+
+ if (c1 != NULL && c2 != NULL) {
+ cb = c1;
+ for (;*c1; ++c1) {
+ b = 0;
+ for (ct = c2; *ct; ++ct) {
+ if (strcmp(*c1, *ct) == 0) {
+ b = 1;
+ break;
+ }
+ }
+ if (b == 0) {
+ printf("h1 aliases item can't be found in h2 "
+ "aliases\n");
+ goto errfin;
+ }
+ }
+
+ c1 = cb;
+ for (;*c2; ++c2) {
+ b = 0;
+ for (ct = c1; *ct; ++ct) {
+ if (strcmp(*c2, *ct) == 0) {
+ b = 1;
+ break;
+ }
+ }
+ if (b == 0) {
+ printf("h2 aliases item can't be found in h1 "
+ "aliases\n");
+ goto errfin;
+ }
+ }
+ }
+
+ c1 = ht1->h_addr_list;
+ c2 = ht2->h_addr_list;
+
+ if ((ht1->h_addr_list == NULL || ht2->h_addr_list== NULL) &&
+ ht1->h_addr_list != ht2->h_addr_list)
+ goto errfin;
+
+ if (c1 != NULL && c2 != NULL) {
+ cb = c1;
+ for (; *c1; ++c1) {
+ b = 0;
+ for (ct = c2; *ct; ++ct) {
+ if (memcmp(*c1, *ct, ht1->h_length) == 0) {
+ b = 1;
+ break;
+ }
+ }
+ if (b == 0) {
+ printf("h1 addresses item can't be found in "
+ "h2 addresses\n");
+ goto errfin;
+ }
+ }
+
+ c1 = cb;
+ for (; *c2; ++c2) {
+ b = 0;
+ for (ct = c1; *ct; ++ct) {
+ if (memcmp(*c2, *ct, ht1->h_length) == 0) {
+ b = 1;
+ break;
+ }
+ }
+ if (b == 0) {
+ printf("h2 addresses item can't be found in "
+ "h1 addresses\n");
+ goto errfin;
+ }
+ }
+ }
+
+ return 0;
+
+errfin:
+ if (mdata == NULL) {
+ printf("following structures are not equal:\n");
+ dump_hostent(ht1);
+ dump_hostent(ht2);
+ }
+
+ return (-1);
+}
+
+static int
+check_addrinfo_for_name(struct addrinfo *ai, char const *name)
+{
+ struct addrinfo *ai2;
+
+ for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
+ if (strcmp(ai2->ai_canonname, name) == 0)
+ return (0);
+ }
+
+ return (-1);
+}
+
+static int
+check_addrinfo_for_addr(struct addrinfo *ai, char const *addr,
+ socklen_t addrlen, int af)
+{
+ struct addrinfo *ai2;
+
+ for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
+ if (af != ai2->ai_family)
+ continue;
+
+ switch (af) {
+ case AF_INET:
+ if (memcmp(addr,
+ (void *)&((struct sockaddr_in *)ai2->ai_addr)->sin_addr,
+ MIN(addrlen, ai2->ai_addrlen)) == 0)
+ return (0);
+ break;
+ case AF_INET6:
+ if (memcmp(addr,
+ (void *)&((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr,
+ MIN(addrlen, ai2->ai_addrlen)) == 0)
+ return (0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return (-1);
+}
+
+static int
+is_hostent_equal(struct hostent *he, struct addrinfo *ai)
+{
+ char **cp;
+ int rv;
+
+#ifdef DEBUG
+ printf("checking equality of he and ai\n");
+#endif
+
+ rv = check_addrinfo_for_name(ai, he->h_name);
+ if (rv != 0) {
+ printf("not equal - he->h_name couldn't be found\n");
+ return (rv);
+ }
+
+ for (cp = he->h_addr_list; *cp; ++cp) {
+ rv = check_addrinfo_for_addr(ai, *cp, he->h_length,
+ he->h_addrtype);
+ if (rv != 0) {
+ printf("not equal - one of he->h_addr_list couldn't be found\n");
+ return (rv);
+ }
+ }
+
+#ifdef DEBUG
+ printf("equal\n");
+#endif
+
+ return (0);
+}
+
+static void
+sdump_hostent(struct hostent *ht, char *buffer, size_t buflen)
+{
+ char **cp;
+ size_t i;
+ int written;
+
+ written = snprintf(buffer, buflen, "%s %d %d",
+ ht->h_name, ht->h_addrtype, ht->h_length);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (ht->h_aliases != NULL) {
+ if (*(ht->h_aliases) != NULL) {
+ for (cp = ht->h_aliases; *cp; ++cp) {
+ written = snprintf(buffer, buflen, " %s",*cp);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+ } else {
+ written = snprintf(buffer, buflen, " noaliases");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+ } else {
+ written = snprintf(buffer, buflen, " (null)");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+
+ written = snprintf(buffer, buflen, " : ");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (ht->h_addr_list != NULL) {
+ if (*(ht->h_addr_list) != NULL) {
+ for (cp = ht->h_addr_list; *cp; ++cp) {
+ for (i = 0; i < ht->h_length; ++i ) {
+ written = snprintf(buffer, buflen,
+ i + 1 != ht->h_length ? "%d." : "%d",
+ (unsigned char)(*cp)[i]);
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+
+ if (buflen == 0)
+ return;
+ }
+
+ if (*(cp + 1) ) {
+ written = snprintf(buffer, buflen, " ");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+ }
+ } else {
+ written = snprintf(buffer, buflen, " noaddrs");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+ } else {
+ written = snprintf(buffer, buflen, " (null)");
+ buffer += written;
+ if (written > buflen)
+ return;
+ buflen -= written;
+ }
+}
+
+static int
+hostent_read_hostlist_func(struct hostent *he, char *line)
+{
+ struct hostent *result;
+ int rv;
+
+#ifdef DEBUG
+ printf("resolving %s: ", line);
+#endif
+ result = __gethostbyname2(line, af_type);
+ if (result != NULL) {
+#ifdef DEBUG
+ printf("found\n");
+#endif
+
+ rv = hostent_test_correctness(result, NULL);
+ if (rv != 0) {
+ __freehostent(result);
+ return (rv);
+ }
+
+ clone_hostent(he, result);
+ __freehostent(result);
+ } else {
+#ifdef DEBUG
+ printf("not found\n");
+#endif
+ memset(he, 0, sizeof(struct hostent));
+ he->h_name = strdup(line);
+ ATF_REQUIRE(he->h_name != NULL);
+ }
+ return (0);
+}
+
+static int
+hostent_read_snapshot_addr(char *addr, unsigned char *result, size_t len)
+{
+ char *s, *ps, *ts;
+
+ ps = addr;
+ while ( (s = strsep(&ps, ".")) != NULL) {
+ if (len == 0)
+ return (-1);
+
+ *result = (unsigned char)strtol(s, &ts, 10);
+ ++result;
+ if (*ts != '\0')
+ return (-1);
+
+ --len;
+ }
+ if (len != 0)
+ return (-1);
+ else
+ return (0);
+}
+
+static int
+hostent_read_snapshot_func(struct hostent *ht, char *line)
+{
+ StringList *sl1, *sl2;
+ char *s, *ps, *ts;
+ int i, rv;
+
+#ifdef DEBUG
+ printf("1 line read from snapshot:\n%s\n", line);
+#endif
+
+ rv = 0;
+ i = 0;
+ sl1 = sl2 = NULL;
+ ps = line;
+ memset(ht, 0, sizeof(struct hostent));
+ while ((s = strsep(&ps, " ")) != NULL) {
+ switch (i) {
+ case 0:
+ ht->h_name = strdup(s);
+ ATF_REQUIRE(ht->h_name != NULL);
+ break;
+
+ case 1:
+ ht->h_addrtype = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+
+ case 2:
+ ht->h_length = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
+ break;
+
+ case 3:
+ if (sl1 == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl1 = sl_init();
+ ATF_REQUIRE(sl1 != NULL);
+
+ if (strcmp(s, "noaliases") != 0) {
+ ts = strdup(s);
+ ATF_REQUIRE(ts != NULL);
+ sl_add(sl1, ts);
+ }
+ } else {
+ if (strcmp(s, ":") == 0)
+ ++i;
+ else {
+ ts = strdup(s);
+ ATF_REQUIRE(ts != NULL);
+ sl_add(sl1, ts);
+ }
+ }
+ break;
+
+ case 4:
+ if (sl2 == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
+
+ sl2 = sl_init();
+ ATF_REQUIRE(sl2 != NULL);
+
+ if (strcmp(s, "noaddrs") != 0) {
+ ts = calloc(1, ht->h_length);
+ ATF_REQUIRE(ts != NULL);
+ rv = hostent_read_snapshot_addr(s,
+ (unsigned char *)ts,
+ ht->h_length);
+ sl_add(sl2, ts);
+ if (rv != 0)
+ goto fin;
+ }
+ } else {
+ ts = calloc(1, ht->h_length);
+ ATF_REQUIRE(ts != NULL);
+ rv = hostent_read_snapshot_addr(s,
+ (unsigned char *)ts, ht->h_length);
+ sl_add(sl2, ts);
+ if (rv != 0)
+ goto fin;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (i != 3 && i != 4)
+ ++i;
+ }
+
+fin:
+ if (sl1 != NULL) {
+ sl_add(sl1, NULL);
+ ht->h_aliases = sl1->sl_str;
+ }
+ if (sl2 != NULL) {
+ sl_add(sl2, NULL);
+ ht->h_addr_list = sl2->sl_str;
+ }
+
+ if ((i != 4) || (rv != 0)) {
+ free_hostent(ht);
+ memset(ht, 0, sizeof(struct hostent));
+ return (-1);
+ }
+
+ /* NOTE: is it a dirty hack or not? */
+ free(sl1);
+ free(sl2);
+ return (0);
+}
+
+static void
+dump_hostent(struct hostent *result)
+{
+ if (result != NULL) {
+ char buffer[1024];
+ sdump_hostent(result, buffer, sizeof(buffer));
+ printf("%s\n", buffer);
+ } else
+ printf("(null)\n");
+}
+
+static int
+hostent_test_correctness(struct hostent *ht, void *mdata)
+{
+
+#ifdef DEBUG
+ printf("testing correctness with the following data:\n");
+ dump_hostent(ht);
+#endif
+
+ if (ht == NULL)
+ goto errfin;
+
+ if (ht->h_name == NULL)
+ goto errfin;
+
+ if (!((ht->h_addrtype >= 0) && (ht->h_addrtype < AF_MAX)))
+ goto errfin;
+
+ if ((ht->h_length != sizeof(struct in_addr)) &&
+ (ht->h_length != sizeof(struct in6_addr)))
+ goto errfin;
+
+ if (ht->h_aliases == NULL)
+ goto errfin;
+
+ if (ht->h_addr_list == NULL)
+ goto errfin;
+
+#ifdef DEBUG
+ printf("correct\n");
+#endif
+
+ return (0);
+errfin:
+ printf("incorrect\n");
+
+ return (-1);
+}
+
+static int
+hostent_test_gethostbyaddr(struct hostent *he, void *mdata)
+{
+ struct hostent *result;
+ struct hostent_test_data *addr_test_data;
+ int rv;
+
+ addr_test_data = (struct hostent_test_data *)mdata;
+
+ /* We should omit unresolved hostents */
+ if (he->h_addr_list != NULL) {
+ char **cp;
+ for (cp = he->h_addr_list; *cp; ++cp) {
+#ifdef DEBUG
+ printf("doing reverse lookup for %s\n", he->h_name);
+#endif
+
+ result = __gethostbyaddr(*cp, he->h_length,
+ he->h_addrtype);
+ if (result == NULL) {
+#ifdef DEBUG
+ printf("%s: warning: reverse lookup failed "
+ "for %s: %s\n", __func__, he->h_name,
+ strerror(errno));
+#endif
+ continue;
+ }
+ rv = hostent_test_correctness(result, NULL);
+ if (rv != 0) {
+ __freehostent(result);
+ return (rv);
+ }
+
+ if (addr_test_data != NULL)
+ TEST_DATA_APPEND(hostent, addr_test_data,
+ result);
+
+ __freehostent(result);
+ }
+ }
+
+ return (0);
+}
+
+static int
+hostent_test_getaddrinfo_eq(struct hostent *he, void *mdata)
+{
+ struct addrinfo *ai, hints;
+ int rv;
+
+ ai = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = af_type;
+ hints.ai_flags = AI_CANONNAME;
+
+ printf("using getaddrinfo() to resolve %s\n", he->h_name);
+
+ /* struct hostent *he was not resolved */
+ if (he->h_addr_list == NULL) {
+ /* We can be sure that he->h_name is not NULL */
+ rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
+ if (rv == 0) {
+ printf("not ok - shouldn't have been resolved\n");
+ return (-1);
+ }
+ } else {
+ rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
+ if (rv != 0) {
+ printf("not ok - should have been resolved\n");
+ return (-1);
+ }
+
+ rv = is_hostent_equal(he, ai);
+ if (rv != 0) {
+ printf("not ok - addrinfo and hostent are not equal\n");
+ return (-1);
+ }
+
+ }
+
+ return (0);
+}
+
+static int
+hostent_test_getnameinfo_eq(struct hostent *he, void *mdata)
+{
+ char **cp;
+ char buffer[NI_MAXHOST];
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *saddr;
+ struct hostent *result;
+ int i, rv;
+
+ if (he->h_addr_list == NULL)
+ return (0);
+
+ for (cp = he->h_addr_list; *cp; ++cp) {
+#ifdef DEBUG
+ printf("doing reverse lookup for %s\n", he->h_name);
+#endif
+ result = __gethostbyaddr(*cp, he->h_length,
+ he->h_addrtype);
+ if (result != NULL) {
+ rv = hostent_test_correctness(result, NULL);
+ if (rv != 0) {
+ __freehostent(result);
+ return (rv);
+ }
+ } else
+ printf("%s: warning: reverse lookup failed "
+ "for %s: %s\n", __func__, he->h_name,
+ strerror(errno));
+
+ switch (he->h_addrtype) {
+ case AF_INET:
+ memset(&sin, 0, sizeof(struct sockaddr_in));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ memcpy(&sin.sin_addr, *cp, he->h_length);
+
+ saddr = (struct sockaddr *)&sin;
+ break;
+ case AF_INET6:
+ memset(&sin6, 0, sizeof(struct sockaddr_in6));
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+ memcpy(&sin6.sin6_addr, *cp, he->h_length);
+
+ saddr = (struct sockaddr *)&sin6;
+ break;
+ default:
+ printf("warning: %d family is unsupported\n",
+ he->h_addrtype);
+ continue;
+ }
+
+ ATF_REQUIRE(saddr != NULL);
+ rv = getnameinfo(saddr, saddr->sa_len, buffer,
+ sizeof(buffer), NULL, 0, NI_NAMEREQD);
+
+ if (rv != 0 && result != NULL) {
+ printf("getnameinfo() didn't make the reverse "
+ "lookup, when it should have (%s)\n",
+ gai_strerror(rv));
+ return (rv);
+ }
+
+ if (rv == 0 && result == NULL) {
+ printf("getnameinfo() made the "
+ "reverse lookup, when it shouldn't have\n");
+ return (rv);
+ }
+
+ if (rv != 0 && result == NULL) {
+#ifdef DEBUG
+ printf("both getnameinfo() and ***byaddr() failed as "
+ "expected\n");
+#endif
+ continue;
+ }
+
+#ifdef DEBUG
+ printf("comparing %s with %s\n", result->h_name,
+ buffer);
+#endif
+
+ /*
+ * An address might reverse resolve to hostname alias or the
+ * official hostname, e.g. moon.vub.ac.be.
+ */
+ bool found_a_match;
+
+ if (strcmp(result->h_name, buffer) == 0) {
+ found_a_match = true;
+#ifdef DEBUG
+ printf("matched official hostname\n");
+#endif
+ } else {
+ for (i = 0; i < nitems(result->h_aliases); i++) {
+ printf("[%d] resolved: %s\n", i,
+ result->h_aliases[i]);
+ if (strcmp(result->h_aliases[i],
+ buffer) == 0) {
+ printf("matched hostname alias\n");
+ found_a_match = true;
+ break;
+ }
+ }
+ }
+ __freehostent(result);
+
+ if (found_a_match) {
+#ifdef DEBUG
+ printf("getnameinfo() and ***byaddr() results are "
+ "equal\n");
+#endif
+ } else {
+ printf("getnameinfo() and ***byaddr() results are not "
+ "equal for %s\n", he->h_name);
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+int
+run_tests(const char *hostlist_file, const char *snapshot_file, int af_type,
+ enum test_methods method, bool use_ipv6_mapping)
+{
+ struct hostent_test_data td, td_addr, td_snap;
+ res_state statp;
+ int rv = -2;
+
+ switch (af_type) {
+ case AF_INET:
+ ATF_REQUIRE_FEATURE("inet");
+ ATF_REQUIRE(!use_ipv6_mapping);
+ break;
+ case AF_INET6:
+ ATF_REQUIRE_FEATURE("inet6");
+ break;
+ default:
+ atf_tc_fail("unhandled address family: %d", af_type);
+ break;
+ }
+
+ if (!use_ipnode_functions) {
+ statp = __res_state();
+ if (statp == NULL || ((statp->options & RES_INIT) == 0 &&
+ res_ninit(statp) == -1)) {
+ printf("error: can't init res_state\n");
+
+ return (-1);
+ }
+
+ if (use_ipv6_mapping)
+ statp->options |= RES_USE_INET6;
+ else
+ statp->options &= ~RES_USE_INET6;
+ }
+
+ TEST_DATA_INIT(hostent, &td, clone_hostent, free_hostent);
+ TEST_DATA_INIT(hostent, &td_addr, clone_hostent, free_hostent);
+ TEST_DATA_INIT(hostent, &td_snap, clone_hostent, free_hostent);
+
+ if (access(hostlist_file, R_OK) != 0) {
+ printf("can't access the hostlist file %s\n", hostlist_file);
+ rv = -1;
+ goto fin;
+ }
+
+#ifdef DEBUG
+ printf("building host lists from %s\n", hostlist_file);
+#endif
+
+ rv = TEST_SNAPSHOT_FILE_READ(hostent, hostlist_file, &td,
+ hostent_read_hostlist_func);
+ if (rv != 0) {
+ printf("failed to read the host list file: %s\n",
+ hostlist_file);
+ goto fin;
+ }
+
+ if (snapshot_file != NULL) {
+ if (access(snapshot_file, W_OK | R_OK) != 0) {
+ if (errno == ENOENT) {
+ if (method != TEST_GETHOSTBYADDR)
+ method = TEST_BUILD_SNAPSHOT;
+ else
+ method = TEST_BUILD_ADDR_SNAPSHOT;
+ } else {
+ printf("can't access the snapshot file %s\n",
+ snapshot_file);
+ rv = -1;
+ goto fin;
+ }
+ } else {
+ rv = TEST_SNAPSHOT_FILE_READ(hostent, snapshot_file,
+ &td_snap, hostent_read_snapshot_func);
+ if (rv != 0) {
+ printf("error reading snapshot file\n");
+ goto fin;
+ }
+ }
+ }
+
+ switch (method) {
+ case TEST_GETHOSTBYNAME2:
+ if (snapshot_file != NULL)
+ rv = DO_2PASS_TEST(hostent, &td, &td_snap,
+ compare_hostent, NULL);
+ break;
+ case TEST_GETHOSTBYADDR:
+ rv = DO_1PASS_TEST(hostent, &td,
+ hostent_test_gethostbyaddr, (void *)&td_addr);
+ if (rv != 0)
+ goto fin;
+
+ if (snapshot_file != NULL)
+ rv = DO_2PASS_TEST(hostent, &td_addr, &td_snap,
+ compare_hostent, NULL);
+ break;
+ case TEST_GETHOSTBYNAME2_GETADDRINFO:
+ rv = DO_1PASS_TEST(hostent, &td,
+ hostent_test_getaddrinfo_eq, NULL);
+ break;
+ case TEST_GETHOSTBYADDR_GETNAMEINFO:
+ rv = DO_1PASS_TEST(hostent, &td,
+ hostent_test_getnameinfo_eq, NULL);
+ break;
+ case TEST_BUILD_SNAPSHOT:
+ if (snapshot_file != NULL) {
+ rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file,
+ &td, sdump_hostent);
+ }
+ break;
+ case TEST_BUILD_ADDR_SNAPSHOT:
+ if (snapshot_file != NULL) {
+ rv = DO_1PASS_TEST(hostent, &td,
+ hostent_test_gethostbyaddr, (void *)&td_addr);
+ if (rv != 0)
+ goto fin;
+ rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file,
+ &td_addr, sdump_hostent);
+ }
+ break;
+ default:
+ rv = 0;
+ break;
+ }
+
+fin:
+ TEST_DATA_DESTROY(hostent, &td_snap);
+ TEST_DATA_DESTROY(hostent, &td_addr);
+ TEST_DATA_DESTROY(hostent, &td);
+
+ return (rv);
+}
+
+#define HOSTLIST_FILE "mach"
+
+#define _RUN_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping) \
+do { \
+ char *_hostlist_file; \
+ char *_snapshot_file; \
+ ATF_REQUIRE(0 < asprintf(&_hostlist_file, "%s/%s", \
+ atf_tc_get_config_var(tc, "srcdir"), HOSTLIST_FILE)); \
+ if (snapshot_file == NULL) \
+ _snapshot_file = NULL; \
+ else { \
+ _snapshot_file = strdup(snapshot_file); \
+ ATF_REQUIRE(_snapshot_file != NULL); \
+ } \
+ ATF_REQUIRE(run_tests(_hostlist_file, _snapshot_file, af_type, \
+ method, use_ipv6_mapping) == 0); \
+} while(0)
+
+#define RUN_HOST_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping) \
+do { \
+ use_ipnode_functions = false; \
+ _RUN_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping); \
+} while(0)
+
+#define RUN_IPNODE_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping) \
+do { \
+ use_ipnode_functions = true; \
+ _RUN_TESTS(tc, snapshot_file, af_type, method, use_ipv6_mapping); \
+} while(0)
+
+ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv4);
+ATF_TC_BODY(gethostbyaddr_ipv4, tc)
+{
+
+ RUN_HOST_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYADDR, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv4_with_snapshot);
+ATF_TC_BODY(gethostbyaddr_ipv4_with_snapshot, tc)
+{
+
+ RUN_HOST_TESTS(tc, "snapshot_htaddr4", AF_INET, TEST_GETHOSTBYADDR, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv6);
+ATF_TC_BODY(gethostbyaddr_ipv6, tc)
+{
+
+ RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv6_AI_V4MAPPED);
+ATF_TC_BODY(gethostbyaddr_ipv6_AI_V4MAPPED, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED;
+ RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, true);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv6_with_snapshot);
+ATF_TC_BODY(gethostbyaddr_ipv6_with_snapshot, tc)
+{
+
+ RUN_HOST_TESTS(tc, "snapshot_htaddr6", AF_INET6, TEST_GETHOSTBYADDR, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyaddr_ipv6_with_snapshot_AI_V4MAPPED);
+ATF_TC_BODY(gethostbyaddr_ipv6_with_snapshot_AI_V4MAPPED, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED;
+ RUN_HOST_TESTS(tc, "snapshot_htaddr6map", AF_INET6, TEST_GETHOSTBYADDR, true);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyname2_getaddrinfo_ipv4);
+ATF_TC_BODY(gethostbyname2_getaddrinfo_ipv4, tc)
+{
+
+ RUN_HOST_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2_GETADDRINFO, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyname2_getaddrinfo_ipv6);
+ATF_TC_BODY(gethostbyname2_getaddrinfo_ipv6, tc)
+{
+
+ RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2_GETADDRINFO, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyaddr_getnameinfo_ipv4);
+ATF_TC_BODY(gethostbyaddr_getnameinfo_ipv4, tc)
+{
+
+ RUN_HOST_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYADDR_GETNAMEINFO, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyaddr_getnameinfo_ipv6);
+ATF_TC_BODY(gethostbyaddr_getnameinfo_ipv6, tc)
+{
+
+ RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR_GETNAMEINFO, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv4);
+ATF_TC_BODY(gethostbyname2_ipv4, tc)
+{
+
+ RUN_HOST_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv4_with_snapshot);
+ATF_TC_BODY(gethostbyname2_ipv4_with_snapshot, tc)
+{
+
+ RUN_HOST_TESTS(tc, "snapshot_htname4", AF_INET, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv6);
+ATF_TC_BODY(gethostbyname2_ipv6, tc)
+{
+
+ RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv6_AI_V4MAPPED);
+ATF_TC_BODY(gethostbyname2_ipv6_AI_V4MAPPED, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED;
+ RUN_HOST_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, true);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv6_with_snapshot);
+ATF_TC_BODY(gethostbyname2_ipv6_with_snapshot, tc)
+{
+
+ RUN_HOST_TESTS(tc, "snapshot_htname6", AF_INET6, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostbyname2_ipv6_with_snapshot_AI_V4MAPPED);
+ATF_TC_BODY(gethostbyname2_ipv6_with_snapshot_AI_V4MAPPED, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED;
+ RUN_HOST_TESTS(tc, "snapshot_htname6map", AF_INET6, TEST_GETHOSTBYNAME2, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv4);
+ATF_TC_BODY(getipnodebyaddr_ipv4, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYADDR, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv4_with_snapshot);
+ATF_TC_BODY(getipnodebyaddr_ipv4_with_snapshot, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, "snapshot_ipnodeaddr4", AF_INET, TEST_GETHOSTBYADDR, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_getnameinfo_ipv4);
+ATF_TC_BODY(getipnodebyaddr_getnameinfo_ipv4, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYADDR_GETNAMEINFO, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6);
+ATF_TC_BODY(getipnodebyaddr_ipv6, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_AI_V4MAPPED);
+ATF_TC_BODY(getipnodebyaddr_ipv6_AI_V4MAPPED, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_AI_V4MAPPED_CFG);
+ATF_TC_BODY(getipnodebyaddr_ipv6_AI_V4MAPPED_CFG, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_AI_V4MAPPED_CFG_AI_ALL);
+ATF_TC_BODY(getipnodebyaddr_ipv6_AI_V4MAPPED_CFG_AI_ALL, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG | AI_ALL;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_with_snapshot);
+ATF_TC_BODY(getipnodebyaddr_ipv6_with_snapshot, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, "snapshot_ipnodeaddr6", AF_INET6, TEST_GETHOSTBYADDR, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED);
+ATF_TC_BODY(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED;
+ RUN_IPNODE_TESTS(tc,
+ "snapshot_ipnodeaddr6_AI_V4MAPPED", AF_INET6,
+ TEST_GETHOSTBYADDR, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG);
+ATF_TC_BODY(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG;
+ RUN_IPNODE_TESTS(tc,
+ "snapshot_ipnodeaddr6_AI_V4MAPPED_CFG", AF_INET6,
+ TEST_GETHOSTBYADDR, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL);
+ATF_TC_BODY(getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG | AI_ALL;
+ RUN_IPNODE_TESTS(tc,
+ "snapshot_ipnodeaddr6_AI_V4MAPPED_CFG_AI_ALL", AF_INET6,
+ TEST_GETHOSTBYADDR, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyaddr_getnameinfo_ipv6);
+ATF_TC_BODY(getipnodebyaddr_getnameinfo_ipv6, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYADDR_GETNAMEINFO, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv4);
+ATF_TC_BODY(getipnodebyname_ipv4, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv4_with_snapshot);
+ATF_TC_BODY(getipnodebyname_ipv4_with_snapshot, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, "snapshot_ipnodename4", AF_INET, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv4_AI_ADDRCONFIG);
+ATF_TC_BODY(getipnodebyname_ipv4_AI_ADDRCONFIG, tc)
+{
+
+ ipnode_flags = AI_ADDRCONFIG;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv4_with_snapshot_AI_ADDRCONFIG);
+ATF_TC_BODY(getipnodebyname_ipv4_with_snapshot_AI_ADDRCONFIG, tc)
+{
+
+ ipnode_flags = AI_ADDRCONFIG;
+ RUN_IPNODE_TESTS(tc, "snapshot_ipnodename4_AI_ADDRCONFIG", AF_INET,
+ TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_getaddrinfo_ipv4);
+ATF_TC_BODY(getipnodebyname_getaddrinfo_ipv4, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET, TEST_GETHOSTBYNAME2_GETADDRINFO, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6);
+ATF_TC_BODY(getipnodebyname_ipv6, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot);
+ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, "snapshot_ipnodename6", AF_INET6, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_ADDRCONFIG);
+ATF_TC_BODY(getipnodebyname_ipv6_AI_ADDRCONFIG, tc)
+{
+
+ ipnode_flags = AI_ADDRCONFIG;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_V4MAPPED);
+ATF_TC_BODY(getipnodebyname_ipv6_AI_V4MAPPED, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_V4MAPPED_CFG);
+ATF_TC_BODY(getipnodebyname_ipv6_AI_V4MAPPED_CFG, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ADDRCONFIG);
+ATF_TC_BODY(getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ADDRCONFIG, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG | AI_ADDRCONFIG;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ALL);
+ATF_TC_BODY(getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ALL, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG | AI_ALL;
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED);
+ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED;
+ RUN_IPNODE_TESTS(tc,
+ "snapshot_ipnodename6_AI_V4MAPPED", AF_INET6,
+ TEST_GETHOSTBYNAME2, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG);
+ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG;
+ RUN_IPNODE_TESTS(tc,
+ "snapshot_ipnodename6_AI_V4MAPPED_CFG", AF_INET6,
+ TEST_GETHOSTBYNAME2, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ADDRCONFIG);
+ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ADDRCONFIG, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG | AI_ADDRCONFIG;
+ RUN_IPNODE_TESTS(tc,
+ "snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ADDRCONFIG", AF_INET6,
+ TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL);
+ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL, tc)
+{
+
+ ipnode_flags = AI_V4MAPPED_CFG | AI_ALL;
+ RUN_IPNODE_TESTS(tc,
+ "snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ALL", AF_INET6,
+ TEST_GETHOSTBYNAME2, true);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_ipv6_with_snapshot_AI_ADDRCONFIG);
+ATF_TC_BODY(getipnodebyname_ipv6_with_snapshot_AI_ADDRCONFIG, tc)
+{
+
+ ipnode_flags = AI_ADDRCONFIG;
+ RUN_IPNODE_TESTS(tc, "snapshot_ipnodename6_AI_ADDRCONFIG", AF_INET6,
+ TEST_GETHOSTBYNAME2, false);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodebyname_getaddrinfo_ipv6);
+ATF_TC_BODY(getipnodebyname_getaddrinfo_ipv6, tc)
+{
+
+ RUN_IPNODE_TESTS(tc, NULL, AF_INET6, TEST_GETHOSTBYNAME2_GETADDRINFO, false);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ /* gethostbyaddr */
+ ATF_TP_ADD_TC(tp, gethostbyaddr_ipv4);
+ ATF_TP_ADD_TC(tp, gethostbyaddr_ipv4_with_snapshot);
+ ATF_TP_ADD_TC(tp, gethostbyaddr_ipv6);
+ ATF_TP_ADD_TC(tp, gethostbyaddr_ipv6_AI_V4MAPPED); /* XXX */
+ ATF_TP_ADD_TC(tp, gethostbyaddr_ipv6_with_snapshot);
+ ATF_TP_ADD_TC(tp, gethostbyaddr_ipv6_with_snapshot_AI_V4MAPPED);
+ ATF_TP_ADD_TC(tp, gethostbyaddr_getnameinfo_ipv4);
+ ATF_TP_ADD_TC(tp, gethostbyaddr_getnameinfo_ipv6);
+
+ /* gethostbyname2 */
+ ATF_TP_ADD_TC(tp, gethostbyname2_getaddrinfo_ipv4);
+ ATF_TP_ADD_TC(tp, gethostbyname2_getaddrinfo_ipv6);
+ ATF_TP_ADD_TC(tp, gethostbyname2_ipv4);
+ ATF_TP_ADD_TC(tp, gethostbyname2_ipv4_with_snapshot);
+ ATF_TP_ADD_TC(tp, gethostbyname2_ipv6);
+ ATF_TP_ADD_TC(tp, gethostbyname2_ipv6_AI_V4MAPPED);
+ ATF_TP_ADD_TC(tp, gethostbyname2_ipv6_with_snapshot);
+ ATF_TP_ADD_TC(tp, gethostbyname2_ipv6_with_snapshot_AI_V4MAPPED);
+
+ /* getipnodebyaddr */
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv4);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv4_with_snapshot);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_getnameinfo_ipv4);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_AI_V4MAPPED);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_AI_V4MAPPED_CFG);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_AI_V4MAPPED_CFG_AI_ALL);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_with_snapshot);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL);
+ ATF_TP_ADD_TC(tp, getipnodebyaddr_getnameinfo_ipv6);
+
+ /* getipnodebyname */
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv4);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv4_with_snapshot);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv4_AI_ADDRCONFIG);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv4_with_snapshot_AI_ADDRCONFIG);
+ ATF_TP_ADD_TC(tp, getipnodebyname_getaddrinfo_ipv4);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_ADDRCONFIG);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_V4MAPPED);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_V4MAPPED_CFG);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ADDRCONFIG);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_AI_V4MAPPED_CFG_AI_ALL);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ADDRCONFIG);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_V4MAPPED_CFG_AI_ALL);
+ ATF_TP_ADD_TC(tp, getipnodebyname_ipv6_with_snapshot_AI_ADDRCONFIG);
+ ATF_TP_ADD_TC(tp, getipnodebyname_getaddrinfo_ipv6);
+
+ return (atf_no_error());
+}
diff --git a/tools/regression/lib/libc/nss/test-getproto.c b/lib/libc/tests/nss/getproto_test.c
index a3ba271..fdb6804 100644
--- a/tools/regression/lib/libc/nss/test-getproto.c
+++ b/lib/libc/tests/nss/getproto_test.c
@@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <stringlist.h>
#include <unistd.h>
+
+#include <atf-c.h>
+
#include "testutil.h"
enum test_methods {
@@ -47,9 +50,6 @@ enum test_methods {
TEST_BUILD_SNAPSHOT
};
-static int debug = 0;
-static enum test_methods method = TEST_BUILD_SNAPSHOT;
-
DECLARE_TEST_DATA(protoent)
DECLARE_TEST_FILE_SNAPSHOT(protoent)
DECLARE_1PASS_TEST(protoent)
@@ -71,8 +71,6 @@ static int protoent_test_getprotobyname(struct protoent *, void *);
static int protoent_test_getprotobynumber(struct protoent *, void *);
static int protoent_test_getprotoent(struct protoent *, void *);
-static void usage(void) __attribute__((__noreturn__));
-
IMPLEMENT_TEST_DATA(protoent)
IMPLEMENT_TEST_FILE_SNAPSHOT(protoent)
IMPLEMENT_1PASS_TEST(protoent)
@@ -101,9 +99,8 @@ clone_protoent(struct protoent *dest, struct protoent const *src)
for (cp = src->p_aliases; *cp; ++cp)
++aliases_num;
- dest->p_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *)));
+ dest->p_aliases = calloc(1, (aliases_num+1) * sizeof(char *));
assert(dest->p_aliases != NULL);
- memset(dest->p_aliases, 0, (aliases_num+1) * (sizeof(char *)));
for (cp = src->p_aliases; *cp; ++cp) {
dest->p_aliases[cp - src->p_aliases] = strdup(*cp);
@@ -157,7 +154,7 @@ compare_protoent(struct protoent *pe1, struct protoent *pe2, void *mdata)
return 0;
errfin:
- if ((debug) && (mdata == NULL)) {
+ if (mdata == NULL) {
printf("following structures are not equal:\n");
dump_protoent(pe1);
dump_protoent(pe2);
@@ -204,8 +201,7 @@ protoent_read_snapshot_func(struct protoent *pe, char *line)
char *s, *ps, *ts;
int i;
- if (debug)
- printf("1 line read from snapshot:\n%s\n", line);
+ printf("1 line read from snapshot:\n%s\n", line);
i = 0;
sl = NULL;
@@ -245,7 +241,7 @@ protoent_read_snapshot_func(struct protoent *pe, char *line)
sl_add(sl, ts);
}
break;
- };
+ }
++i;
}
@@ -294,10 +290,8 @@ protoent_fill_test_data(struct protoent_test_data *td)
static int
protoent_test_correctness(struct protoent *pe, void *mdata)
{
- if (debug) {
- printf("testing correctness with the following data:\n");
- dump_protoent(pe);
- }
+ printf("testing correctness with the following data:\n");
+ dump_protoent(pe);
if (pe == NULL)
goto errfin;
@@ -311,13 +305,11 @@ protoent_test_correctness(struct protoent *pe, void *mdata)
if (pe->p_aliases == NULL)
goto errfin;
- if (debug)
- printf("correct\n");
+ printf("correct\n");
return (0);
errfin:
- if (debug)
- printf("incorrect\n");
+ printf("incorrect\n");
return (-1);
}
@@ -341,10 +333,8 @@ protoent_test_getprotobyname(struct protoent *pe_model, void *mdata)
char **alias;
struct protoent *pe;
- if (debug) {
- printf("testing getprotobyname() with the following data:\n");
- dump_protoent(pe_model);
- }
+ printf("testing getprotobyname() with the following data:\n");
+ dump_protoent(pe_model);
pe = getprotobyname(pe_model->p_name);
if (protoent_test_correctness(pe, NULL) != 0)
@@ -367,13 +357,11 @@ protoent_test_getprotobyname(struct protoent *pe_model, void *mdata)
goto errfin;
}
- if (debug)
- printf("ok\n");
+ printf("ok\n");
return (0);
errfin:
- if (debug)
- printf("not ok\n");
+ printf("not ok\n");
return (-1);
}
@@ -383,23 +371,19 @@ protoent_test_getprotobynumber(struct protoent *pe_model, void *mdata)
{
struct protoent *pe;
- if (debug) {
- printf("testing getprotobyport() with the following data...\n");
- dump_protoent(pe_model);
- }
+ printf("testing getprotobyport() with the following data...\n");
+ dump_protoent(pe_model);
pe = getprotobynumber(pe_model->p_proto);
if ((protoent_test_correctness(pe, NULL) != 0) ||
((compare_protoent(pe, pe_model, NULL) != 0) &&
(protoent_check_ambiguity((struct protoent_test_data *)mdata, pe)
!= 0))) {
- if (debug)
printf("not ok\n");
- return (-1);
+ return (-1);
} else {
- if (debug)
printf("ok\n");
- return (0);
+ return (0);
}
}
@@ -411,50 +395,11 @@ protoent_test_getprotoent(struct protoent *pe, void *mdata)
return (protoent_test_correctness(pe, NULL));
}
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s -nve2 [-d] [-s <file>]\n",
- getprogname());
- exit(1);
-}
-
int
-main(int argc, char **argv)
+run_tests(const char *snapshot_file, enum test_methods method)
{
struct protoent_test_data td, td_snap, td_2pass;
- char *snapshot_file;
int rv;
- int c;
-
- if (argc < 2)
- usage();
-
- snapshot_file = NULL;
- while ((c = getopt(argc, argv, "nve2ds:")) != -1)
- switch (c) {
- case 'd':
- debug++;
- break;
- case 'n':
- method = TEST_GETPROTOBYNAME;
- break;
- case 'v':
- method = TEST_GETPROTOBYNUMBER;
- break;
- case 'e':
- method = TEST_GETPROTOENT;
- break;
- case '2':
- method = TEST_GETPROTOENT_2PASS;
- break;
- case 's':
- snapshot_file = strdup(optarg);
- break;
- default:
- usage();
- }
TEST_DATA_INIT(protoent, &td, clone_protoent, free_protoent);
TEST_DATA_INIT(protoent, &td_snap, clone_protoent, free_protoent);
@@ -463,9 +408,8 @@ main(int argc, char **argv)
if (errno == ENOENT)
method = TEST_BUILD_SNAPSHOT;
else {
- if (debug)
- printf("can't access the file %s\n",
- snapshot_file);
+ printf("can't access the file %s\n",
+ snapshot_file);
rv = -1;
goto fin;
@@ -510,27 +454,103 @@ main(int argc, char **argv)
compare_protoent, NULL);
break;
case TEST_GETPROTOENT_2PASS:
- TEST_DATA_INIT(protoent, &td_2pass, clone_protoent,
- free_protoent);
- rv = protoent_fill_test_data(&td_2pass);
- if (rv != -1)
- rv = DO_2PASS_TEST(protoent, &td, &td_2pass,
- compare_protoent, NULL);
- TEST_DATA_DESTROY(protoent, &td_2pass);
+ TEST_DATA_INIT(protoent, &td_2pass, clone_protoent,
+ free_protoent);
+ rv = protoent_fill_test_data(&td_2pass);
+ if (rv != -1)
+ rv = DO_2PASS_TEST(protoent, &td, &td_2pass,
+ compare_protoent, NULL);
+ TEST_DATA_DESTROY(protoent, &td_2pass);
break;
case TEST_BUILD_SNAPSHOT:
if (snapshot_file != NULL)
- rv = TEST_SNAPSHOT_FILE_WRITE(protoent, snapshot_file, &td,
- sdump_protoent);
+ rv = TEST_SNAPSHOT_FILE_WRITE(protoent, snapshot_file,
+ &td, sdump_protoent);
break;
default:
rv = 0;
break;
- };
+ }
fin:
TEST_DATA_DESTROY(protoent, &td_snap);
TEST_DATA_DESTROY(protoent, &td);
- free(snapshot_file);
+
return (rv);
}
+
+#define SNAPSHOT_FILE "snapshot_proto"
+
+ATF_TC_WITHOUT_HEAD(build_snapshot);
+ATF_TC_BODY(build_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getprotoent);
+ATF_TC_BODY(getprotoent, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getprotoent_with_snapshot);
+ATF_TC_BODY(getprotoent_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getprotoent_with_two_pass);
+ATF_TC_BODY(getprotoent_with_two_pass, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOENT_2PASS) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getprotobyname);
+ATF_TC_BODY(getprotobyname, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNAME) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getprotobyname_with_snapshot);
+ATF_TC_BODY(getprotobyname_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOBYNAME) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getprotobynumber);
+ATF_TC_BODY(getprotobynumber, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETPROTOBYNUMBER) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getprotobynumber_with_snapshot);
+ATF_TC_BODY(getprotobynumber_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPROTOBYNUMBER) == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, build_snapshot);
+ ATF_TP_ADD_TC(tp, getprotoent);
+ ATF_TP_ADD_TC(tp, getprotoent_with_snapshot);
+ ATF_TP_ADD_TC(tp, getprotoent_with_two_pass);
+ ATF_TP_ADD_TC(tp, getprotobyname);
+ ATF_TP_ADD_TC(tp, getprotobyname_with_snapshot);
+ ATF_TP_ADD_TC(tp, getprotobynumber);
+ ATF_TP_ADD_TC(tp, getprotobynumber_with_snapshot);
+
+ return (atf_no_error());
+}
diff --git a/tools/regression/lib/libc/nss/test-getpw.c b/lib/libc/tests/nss/getpw_test.c
index a0b348d..98f890f 100644
--- a/tools/regression/lib/libc/nss/test-getpw.c
+++ b/lib/libc/tests/nss/getpw_test.c
@@ -28,13 +28,15 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <assert.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
+#include <atf-c.h>
+
#include "testutil.h"
enum test_methods {
@@ -45,7 +47,6 @@ enum test_methods {
TEST_BUILD_SNAPSHOT
};
-static int debug = 0;
static enum test_methods method = TEST_BUILD_SNAPSHOT;
DECLARE_TEST_DATA(passwd)
@@ -69,8 +70,6 @@ static int passwd_test_getpwnam(struct passwd *, void *);
static int passwd_test_getpwuid(struct passwd *, void *);
static int passwd_test_getpwent(struct passwd *, void *);
-static void usage(void) __attribute__((__noreturn__));
-
IMPLEMENT_TEST_DATA(passwd)
IMPLEMENT_TEST_FILE_SNAPSHOT(passwd)
IMPLEMENT_1PASS_TEST(passwd)
@@ -79,8 +78,8 @@ IMPLEMENT_2PASS_TEST(passwd)
static void
clone_passwd(struct passwd *dest, struct passwd const *src)
{
- assert(dest != NULL);
- assert(src != NULL);
+ ATF_REQUIRE(dest != NULL);
+ ATF_REQUIRE(src != NULL);
memcpy(dest, src, sizeof(struct passwd));
if (src->pw_name != NULL)
@@ -100,24 +99,23 @@ clone_passwd(struct passwd *dest, struct passwd const *src)
static int
compare_passwd(struct passwd *pwd1, struct passwd *pwd2, void *mdata)
{
- assert(pwd1 != NULL);
- assert(pwd2 != NULL);
+ ATF_REQUIRE(pwd1 != NULL);
+ ATF_REQUIRE(pwd2 != NULL);
if (pwd1 == pwd2)
return (0);
- if ((pwd1->pw_uid != pwd2->pw_uid) ||
- (pwd1->pw_gid != pwd2->pw_gid) ||
- (pwd1->pw_change != pwd2->pw_change) ||
- (pwd1->pw_expire != pwd2->pw_expire) ||
- (pwd1->pw_fields != pwd2->pw_fields) ||
- (strcmp(pwd1->pw_name, pwd2->pw_name) != 0) ||
- (strcmp(pwd1->pw_passwd, pwd2->pw_passwd) != 0) ||
- (strcmp(pwd1->pw_class, pwd2->pw_class) != 0) ||
- (strcmp(pwd1->pw_gecos, pwd2->pw_gecos) != 0) ||
- (strcmp(pwd1->pw_dir, pwd2->pw_dir) != 0) ||
- (strcmp(pwd1->pw_shell, pwd2->pw_shell) != 0)
- )
+ if (pwd1->pw_uid != pwd2->pw_uid ||
+ pwd1->pw_gid != pwd2->pw_gid ||
+ pwd1->pw_change != pwd2->pw_change ||
+ pwd1->pw_expire != pwd2->pw_expire ||
+ pwd1->pw_fields != pwd2->pw_fields ||
+ strcmp(pwd1->pw_name, pwd2->pw_name) != 0 ||
+ strcmp(pwd1->pw_passwd, pwd2->pw_passwd) != 0 ||
+ strcmp(pwd1->pw_class, pwd2->pw_class) != 0 ||
+ strcmp(pwd1->pw_gecos, pwd2->pw_gecos) != 0 ||
+ strcmp(pwd1->pw_dir, pwd2->pw_dir) != 0 ||
+ strcmp(pwd1->pw_shell, pwd2->pw_shell) != 0)
return (-1);
else
return (0);
@@ -137,10 +135,11 @@ free_passwd(struct passwd *pwd)
static void
sdump_passwd(struct passwd *pwd, char *buffer, size_t buflen)
{
- snprintf(buffer, buflen, "%s:%s:%d:%d:%d:%s:%s:%s:%s:%d:%d",
- pwd->pw_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid,
- pwd->pw_change, pwd->pw_class, pwd->pw_gecos, pwd->pw_dir,
- pwd->pw_shell, pwd->pw_expire, pwd->pw_fields);
+ snprintf(buffer, buflen, "%s:%s:%d:%d:%jd:%s:%s:%s:%s:%jd:%d",
+ pwd->pw_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid,
+ (uintmax_t)pwd->pw_change, pwd->pw_class, pwd->pw_gecos,
+ pwd->pw_dir, pwd->pw_shell, (uintmax_t)pwd->pw_expire,
+ pwd->pw_fields);
}
static void
@@ -160,66 +159,67 @@ passwd_read_snapshot_func(struct passwd *pwd, char *line)
char *s, *ps, *ts;
int i;
- if (debug)
- printf("1 line read from snapshot:\n%s\n", line);
+#ifdef DEBUG
+ printf("1 line read from snapshot:\n%s\n", line);
+#endif
i = 0;
ps = line;
memset(pwd, 0, sizeof(struct passwd));
- while ( (s = strsep(&ps, ":")) != NULL) {
+ while ((s = strsep(&ps, ":")) != NULL) {
switch (i) {
- case 0:
- pwd->pw_name = strdup(s);
- assert(pwd->pw_name != NULL);
+ case 0:
+ pwd->pw_name = strdup(s);
+ ATF_REQUIRE(pwd->pw_name != NULL);
break;
- case 1:
- pwd->pw_passwd = strdup(s);
- assert(pwd->pw_passwd != NULL);
+ case 1:
+ pwd->pw_passwd = strdup(s);
+ ATF_REQUIRE(pwd->pw_passwd != NULL);
break;
- case 2:
- pwd->pw_uid = (uid_t)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
+ case 2:
+ pwd->pw_uid = (uid_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
break;
- case 3:
- pwd->pw_gid = (gid_t)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
+ case 3:
+ pwd->pw_gid = (gid_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
break;
- case 4:
- pwd->pw_change = (time_t)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
+ case 4:
+ pwd->pw_change = (time_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
break;
- case 5:
- pwd->pw_class = strdup(s);
- assert(pwd->pw_class != NULL);
+ case 5:
+ pwd->pw_class = strdup(s);
+ ATF_REQUIRE(pwd->pw_class != NULL);
break;
- case 6:
- pwd->pw_gecos = strdup(s);
- assert(pwd->pw_gecos != NULL);
+ case 6:
+ pwd->pw_gecos = strdup(s);
+ ATF_REQUIRE(pwd->pw_gecos != NULL);
break;
- case 7:
- pwd->pw_dir = strdup(s);
- assert(pwd->pw_dir != NULL);
+ case 7:
+ pwd->pw_dir = strdup(s);
+ ATF_REQUIRE(pwd->pw_dir != NULL);
break;
- case 8:
- pwd->pw_shell = strdup(s);
- assert(pwd->pw_shell != NULL);
+ case 8:
+ pwd->pw_shell = strdup(s);
+ ATF_REQUIRE(pwd->pw_shell != NULL);
break;
- case 9:
- pwd->pw_expire = (time_t)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
+ case 9:
+ pwd->pw_expire = (time_t)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
break;
- case 10:
- pwd->pw_fields = (int)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
+ case 10:
+ pwd->pw_fields = (int)strtol(s, &ts, 10);
+ if (*ts != '\0')
+ goto fin;
break;
- default:
+ default:
break;
- };
+ }
++i;
}
@@ -253,10 +253,11 @@ passwd_fill_test_data(struct passwd_test_data *td)
static int
passwd_test_correctness(struct passwd *pwd, void *mdata)
{
- if (debug) {
- printf("testing correctness with the following data:\n");
- dump_passwd(pwd);
- }
+
+#ifdef DEBUG
+ printf("testing correctness with the following data:\n");
+ dump_passwd(pwd);
+#endif
if (pwd == NULL)
return (-1);
@@ -279,13 +280,15 @@ passwd_test_correctness(struct passwd *pwd, void *mdata)
if (pwd->pw_shell == NULL)
goto errfin;
- if (debug)
- printf("correct\n");
+#ifdef DEBUG
+ printf("correct\n");
+#endif
return (0);
errfin:
- if (debug)
- printf("incorrect\n");
+#ifdef DEBUG
+ printf("incorrect\n");
+#endif
return (-1);
}
@@ -306,10 +309,10 @@ passwd_test_getpwnam(struct passwd *pwd_model, void *mdata)
{
struct passwd *pwd;
- if (debug) {
- printf("testing getpwnam() with the following data:\n");
- dump_passwd(pwd_model);
- }
+#ifdef DEBUG
+ printf("testing getpwnam() with the following data:\n");
+ dump_passwd(pwd_model);
+#endif
pwd = getpwnam(pwd_model->pw_name);
if (passwd_test_correctness(pwd, NULL) != 0)
@@ -320,14 +323,15 @@ passwd_test_getpwnam(struct passwd *pwd_model, void *mdata)
!=0))
goto errfin;
- if (debug)
- printf("ok\n");
+#ifdef DEBUG
+ printf("ok\n");
+#endif
return (0);
errfin:
- if (debug)
- printf("not ok\n");
-
+#ifdef DEBUG
+ printf("not ok\n");
+#endif
return (-1);
}
@@ -336,23 +340,25 @@ passwd_test_getpwuid(struct passwd *pwd_model, void *mdata)
{
struct passwd *pwd;
- if (debug) {
- printf("testing getpwuid() with the following data...\n");
- dump_passwd(pwd_model);
- }
+#ifdef DEBUG
+ printf("testing getpwuid() with the following data...\n");
+ dump_passwd(pwd_model);
+#endif
pwd = getpwuid(pwd_model->pw_uid);
if ((passwd_test_correctness(pwd, NULL) != 0) ||
((compare_passwd(pwd, pwd_model, NULL) != 0) &&
(passwd_check_ambiguity((struct passwd_test_data *)mdata, pwd)
!= 0))) {
- if (debug)
+#ifdef DEBUG
printf("not ok\n");
- return (-1);
+#endif
+ return (-1);
} else {
- if (debug)
+#ifdef DEBUG
printf("ok\n");
- return (0);
+#endif
+ return (0);
}
}
@@ -364,50 +370,11 @@ passwd_test_getpwent(struct passwd *pwd, void *mdata)
return (passwd_test_correctness(pwd, NULL));
}
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s -nue2 [-d] [-s <file>]\n",
- getprogname());
- exit(1);
-}
-
-int
-main(int argc, char **argv)
+static int
+run_tests(const char *snapshot_file, enum test_methods method)
{
struct passwd_test_data td, td_snap, td_2pass;
- char *snapshot_file;
int rv;
- int c;
-
- if (argc < 2)
- usage();
-
- snapshot_file = NULL;
- while ((c = getopt(argc, argv, "nue2ds:")) != -1)
- switch (c) {
- case 'd':
- debug++;
- break;
- case 'n':
- method = TEST_GETPWNAM;
- break;
- case 'u':
- method = TEST_GETPWUID;
- break;
- case 'e':
- method = TEST_GETPWENT;
- break;
- case '2':
- method = TEST_GETPWENT_2PASS;
- break;
- case 's':
- snapshot_file = strdup(optarg);
- break;
- default:
- usage();
- }
TEST_DATA_INIT(passwd, &td, clone_passwd, free_passwd);
TEST_DATA_INIT(passwd, &td_snap, clone_passwd, free_passwd);
@@ -416,10 +383,8 @@ main(int argc, char **argv)
if (errno == ENOENT)
method = TEST_BUILD_SNAPSHOT;
else {
- if (debug)
- printf("can't access the file %s\n",
- snapshot_file);
-
+ printf("can't access the file %s\n",
+ snapshot_file);
rv = -1;
goto fin;
}
@@ -464,26 +429,102 @@ main(int argc, char **argv)
compare_passwd, NULL);
break;
case TEST_GETPWENT_2PASS:
- TEST_DATA_INIT(passwd, &td_2pass, clone_passwd, free_passwd);
- rv = passwd_fill_test_data(&td_2pass);
- if (rv != -1)
- rv = DO_2PASS_TEST(passwd, &td, &td_2pass,
- compare_passwd, NULL);
- TEST_DATA_DESTROY(passwd, &td_2pass);
+ TEST_DATA_INIT(passwd, &td_2pass, clone_passwd, free_passwd);
+ rv = passwd_fill_test_data(&td_2pass);
+ if (rv != -1)
+ rv = DO_2PASS_TEST(passwd, &td, &td_2pass,
+ compare_passwd, NULL);
+ TEST_DATA_DESTROY(passwd, &td_2pass);
break;
case TEST_BUILD_SNAPSHOT:
if (snapshot_file != NULL)
- rv = TEST_SNAPSHOT_FILE_WRITE(passwd, snapshot_file, &td,
- sdump_passwd);
+ rv = TEST_SNAPSHOT_FILE_WRITE(passwd, snapshot_file,
+ &td, sdump_passwd);
break;
default:
rv = 0;
break;
- };
+ }
fin:
TEST_DATA_DESTROY(passwd, &td_snap);
TEST_DATA_DESTROY(passwd, &td);
- free(snapshot_file);
+
return (rv);
}
+
+#define SNAPSHOT_FILE "snapshot_pwd"
+
+ATF_TC_WITHOUT_HEAD(build_snapshot);
+ATF_TC_BODY(build_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getpwent);
+ATF_TC_BODY(getpwent, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getpwent_with_snapshot);
+ATF_TC_BODY(getpwent_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getpwent_with_two_pass);
+ATF_TC_BODY(getpwent_with_two_pass, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWENT_2PASS) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getpwnam);
+ATF_TC_BODY(getpwnam, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWNAM) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getpwnam_with_snapshot);
+ATF_TC_BODY(getpwnam_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWNAM) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getpwuid);
+ATF_TC_BODY(getpwuid, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWUID) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getpwuid_with_snapshot);
+ATF_TC_BODY(getpwuid_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETPWUID) == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, build_snapshot);
+ ATF_TP_ADD_TC(tp, getpwent);
+ ATF_TP_ADD_TC(tp, getpwent_with_snapshot);
+ ATF_TP_ADD_TC(tp, getpwent_with_two_pass);
+ ATF_TP_ADD_TC(tp, getpwnam);
+ ATF_TP_ADD_TC(tp, getpwnam_with_snapshot);
+ ATF_TP_ADD_TC(tp, getpwuid);
+ ATF_TP_ADD_TC(tp, getpwuid_with_snapshot);
+
+ return (atf_no_error());
+}
diff --git a/tools/regression/lib/libc/nss/test-getrpc.c b/lib/libc/tests/nss/getrpc_test.c
index 707186e..89de986 100644
--- a/tools/regression/lib/libc/nss/test-getrpc.c
+++ b/lib/libc/tests/nss/getrpc_test.c
@@ -30,13 +30,15 @@ __FBSDID("$FreeBSD$");
#include <arpa/inet.h>
#include <rpc/rpc.h>
-#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stringlist.h>
#include <unistd.h>
+
+#include <atf-c.h>
+
#include "testutil.h"
enum test_methods {
@@ -47,9 +49,6 @@ enum test_methods {
TEST_BUILD_SNAPSHOT
};
-static int debug = 0;
-static enum test_methods method = TEST_BUILD_SNAPSHOT;
-
DECLARE_TEST_DATA(rpcent)
DECLARE_TEST_FILE_SNAPSHOT(rpcent)
DECLARE_1PASS_TEST(rpcent)
@@ -81,8 +80,8 @@ IMPLEMENT_2PASS_TEST(rpcent)
static void
clone_rpcent(struct rpcent *dest, struct rpcent const *src)
{
- assert(dest != NULL);
- assert(src != NULL);
+ ATF_REQUIRE(dest != NULL);
+ ATF_REQUIRE(src != NULL);
char **cp;
int aliases_num;
@@ -91,7 +90,7 @@ clone_rpcent(struct rpcent *dest, struct rpcent const *src)
if (src->r_name != NULL) {
dest->r_name = strdup(src->r_name);
- assert(dest->r_name != NULL);
+ ATF_REQUIRE(dest->r_name != NULL);
}
dest->r_number = src->r_number;
@@ -101,13 +100,12 @@ clone_rpcent(struct rpcent *dest, struct rpcent const *src)
for (cp = src->r_aliases; *cp; ++cp)
++aliases_num;
- dest->r_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *)));
- assert(dest->r_aliases != NULL);
- memset(dest->r_aliases, 0, (aliases_num+1) * (sizeof(char *)));
+ dest->r_aliases = calloc(1, (aliases_num + 1) * sizeof(char *));
+ ATF_REQUIRE(dest->r_aliases != NULL);
for (cp = src->r_aliases; *cp; ++cp) {
dest->r_aliases[cp - src->r_aliases] = strdup(*cp);
- assert(dest->r_aliases[cp - src->r_aliases] != NULL);
+ ATF_REQUIRE(dest->r_aliases[cp - src->r_aliases] != NULL);
}
}
}
@@ -117,7 +115,7 @@ free_rpcent(struct rpcent *rpc)
{
char **cp;
- assert(rpc != NULL);
+ ATF_REQUIRE(rpc != NULL);
free(rpc->r_name);
@@ -157,7 +155,7 @@ compare_rpcent(struct rpcent *rpc1, struct rpcent *rpc2, void *mdata)
return 0;
errfin:
- if ((debug) && (mdata == NULL)) {
+ if (mdata == NULL) {
printf("following structures are not equal:\n");
dump_rpcent(rpc1);
dump_rpcent(rpc2);
@@ -204,49 +202,48 @@ rpcent_read_snapshot_func(struct rpcent *rpc, char *line)
char *s, *ps, *ts;
int i;
- if (debug)
- printf("1 line read from snapshot:\n%s\n", line);
+ printf("1 line read from snapshot:\n%s\n", line);
i = 0;
sl = NULL;
ps = line;
memset(rpc, 0, sizeof(struct rpcent));
- while ( (s = strsep(&ps, " ")) != NULL) {
+ while ((s = strsep(&ps, " ")) != NULL) {
switch (i) {
- case 0:
+ case 0:
rpc->r_name = strdup(s);
- assert(rpc->r_name != NULL);
+ ATF_REQUIRE(rpc->r_name != NULL);
break;
- case 1:
- rpc->r_number = (int)strtol(s, &ts, 10);
- if (*ts != '\0') {
- free(rpc->r_name);
- return (-1);
- }
+ case 1:
+ rpc->r_number = (int)strtol(s, &ts, 10);
+ if (*ts != '\0') {
+ free(rpc->r_name);
+ return (-1);
+ }
break;
- default:
- if (sl == NULL) {
- if (strcmp(s, "(null)") == 0)
- return (0);
+ default:
+ if (sl == NULL) {
+ if (strcmp(s, "(null)") == 0)
+ return (0);
- sl = sl_init();
- assert(sl != NULL);
+ sl = sl_init();
+ ATF_REQUIRE(sl != NULL);
- if (strcmp(s, "noaliases") != 0) {
- ts = strdup(s);
- assert(ts != NULL);
- sl_add(sl, ts);
- }
- } else {
+ if (strcmp(s, "noaliases") != 0) {
ts = strdup(s);
- assert(ts != NULL);
+ ATF_REQUIRE(ts != NULL);
sl_add(sl, ts);
}
+ } else {
+ ts = strdup(s);
+ ATF_REQUIRE(ts != NULL);
+ sl_add(sl, ts);
+ }
break;
- };
- ++i;
+ }
+ i++;
}
if (i < 3) {
@@ -294,10 +291,9 @@ rpcent_fill_test_data(struct rpcent_test_data *td)
static int
rpcent_test_correctness(struct rpcent *rpc, void *mdata)
{
- if (debug) {
- printf("testing correctness with the following data:\n");
- dump_rpcent(rpc);
- }
+
+ printf("testing correctness with the following data:\n");
+ dump_rpcent(rpc);
if (rpc == NULL)
goto errfin;
@@ -311,13 +307,11 @@ rpcent_test_correctness(struct rpcent *rpc, void *mdata)
if (rpc->r_aliases == NULL)
goto errfin;
- if (debug)
- printf("correct\n");
+ printf("correct\n");
return (0);
errfin:
- if (debug)
- printf("incorrect\n");
+ printf("incorrect\n");
return (-1);
}
@@ -341,10 +335,8 @@ rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata)
char **alias;
struct rpcent *rpc;
- if (debug) {
- printf("testing getrpcbyname() with the following data:\n");
- dump_rpcent(rpc_model);
- }
+ printf("testing getrpcbyname() with the following data:\n");
+ dump_rpcent(rpc_model);
rpc = getrpcbyname(rpc_model->r_name);
if (rpcent_test_correctness(rpc, NULL) != 0)
@@ -367,13 +359,11 @@ rpcent_test_getrpcbyname(struct rpcent *rpc_model, void *mdata)
goto errfin;
}
- if (debug)
- printf("ok\n");
+ printf("ok\n");
return (0);
errfin:
- if (debug)
- printf("not ok\n");
+ printf("not ok\n");
return (-1);
}
@@ -383,78 +373,38 @@ rpcent_test_getrpcbynumber(struct rpcent *rpc_model, void *mdata)
{
struct rpcent *rpc;
- if (debug) {
- printf("testing getrpcbyport() with the following data...\n");
- dump_rpcent(rpc_model);
- }
+ printf("testing getrpcbyport() with the following data...\n");
+ dump_rpcent(rpc_model);
rpc = getrpcbynumber(rpc_model->r_number);
- if ((rpcent_test_correctness(rpc, NULL) != 0) ||
- ((compare_rpcent(rpc, rpc_model, NULL) != 0) &&
- (rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc)
- != 0))) {
- if (debug)
+ if (rpcent_test_correctness(rpc, NULL) != 0 ||
+ (compare_rpcent(rpc, rpc_model, NULL) != 0 &&
+ rpcent_check_ambiguity((struct rpcent_test_data *)mdata, rpc)
+ != 0)) {
printf("not ok\n");
- return (-1);
+ return (-1);
} else {
- if (debug)
printf("ok\n");
- return (0);
+ return (0);
}
}
static int
rpcent_test_getrpcent(struct rpcent *rpc, void *mdata)
{
- /* Only correctness can be checked when doing 1-pass test for
- * getrpcent(). */
- return (rpcent_test_correctness(rpc, NULL));
-}
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s -nve2 [-d] [-s <file>]\n",
- getprogname());
- exit(1);
+ /*
+ * Only correctness can be checked when doing 1-pass test for
+ * getrpcent().
+ */
+ return (rpcent_test_correctness(rpc, NULL));
}
int
-main(int argc, char **argv)
+run_tests(const char *snapshot_file, enum test_methods method)
{
struct rpcent_test_data td, td_snap, td_2pass;
- char *snapshot_file;
int rv;
- int c;
-
- if (argc < 2)
- usage();
-
- snapshot_file = NULL;
- while ((c = getopt(argc, argv, "nve2ds:")) != -1)
- switch (c) {
- case 'd':
- debug++;
- break;
- case 'n':
- method = TEST_GETRPCBYNAME;
- break;
- case 'v':
- method = TEST_GETRPCBYNUMBER;
- break;
- case 'e':
- method = TEST_GETRPCENT;
- break;
- case '2':
- method = TEST_GETRPCENT_2PASS;
- break;
- case 's':
- snapshot_file = strdup(optarg);
- break;
- default:
- usage();
- }
TEST_DATA_INIT(rpcent, &td, clone_rpcent, free_rpcent);
TEST_DATA_INIT(rpcent, &td_snap, clone_rpcent, free_rpcent);
@@ -463,9 +413,8 @@ main(int argc, char **argv)
if (errno == ENOENT)
method = TEST_BUILD_SNAPSHOT;
else {
- if (debug)
- printf("can't access the file %s\n",
- snapshot_file);
+ printf("can't access the file %s\n",
+ snapshot_file);
rv = -1;
goto fin;
@@ -525,11 +474,87 @@ main(int argc, char **argv)
default:
rv = 0;
break;
- };
+ }
fin:
TEST_DATA_DESTROY(rpcent, &td_snap);
TEST_DATA_DESTROY(rpcent, &td);
- free(snapshot_file);
+
return (rv);
}
+
+#define SNAPSHOT_FILE "snapshot_rpc"
+
+ATF_TC_WITHOUT_HEAD(build_snapshot);
+ATF_TC_BODY(build_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getrpcbyname);
+ATF_TC_BODY(getrpcbyname, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETRPCBYNAME) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getrpcbyname_with_snapshot);
+ATF_TC_BODY(getrpcbyname_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCBYNAME) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getrpcbynumber);
+ATF_TC_BODY(getrpcbynumber, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETRPCBYNUMBER) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getrpcbynumber_with_snapshot);
+ATF_TC_BODY(getrpcbynumber_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCBYNUMBER) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getrpcbyent);
+ATF_TC_BODY(getrpcbyent, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETRPCENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getrpcbyent_with_snapshot);
+ATF_TC_BODY(getrpcbyent_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETRPCENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getrpcbyent_with_two_pass);
+ATF_TC_BODY(getrpcbyent_with_two_pass, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETRPCENT_2PASS) == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, build_snapshot);
+ ATF_TP_ADD_TC(tp, getrpcbyname);
+ ATF_TP_ADD_TC(tp, getrpcbyname_with_snapshot);
+ ATF_TP_ADD_TC(tp, getrpcbynumber);
+ ATF_TP_ADD_TC(tp, getrpcbynumber_with_snapshot);
+ ATF_TP_ADD_TC(tp, getrpcbyent);
+ ATF_TP_ADD_TC(tp, getrpcbyent_with_snapshot);
+ ATF_TP_ADD_TC(tp, getrpcbyent_with_two_pass);
+
+ return (atf_no_error());
+}
diff --git a/tools/regression/lib/libc/nss/test-getserv.c b/lib/libc/tests/nss/getserv_test.c
index 31e4700..29c1dfa 100644
--- a/tools/regression/lib/libc/nss/test-getserv.c
+++ b/lib/libc/tests/nss/getserv_test.c
@@ -29,7 +29,6 @@
__FBSDID("$FreeBSD$");
#include <arpa/inet.h>
-#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
@@ -37,6 +36,9 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <stringlist.h>
#include <unistd.h>
+
+#include <atf-c.h>
+
#include "testutil.h"
enum test_methods {
@@ -47,9 +49,6 @@ enum test_methods {
TEST_BUILD_SNAPSHOT
};
-static int debug = 0;
-static enum test_methods method = TEST_BUILD_SNAPSHOT;
-
DECLARE_TEST_DATA(servent)
DECLARE_TEST_FILE_SNAPSHOT(servent)
DECLARE_1PASS_TEST(servent)
@@ -71,8 +70,6 @@ static int servent_test_getservbyname(struct servent *, void *);
static int servent_test_getservbyport(struct servent *, void *);
static int servent_test_getservent(struct servent *, void *);
-static void usage(void) __attribute__((__noreturn__));
-
IMPLEMENT_TEST_DATA(servent)
IMPLEMENT_TEST_FILE_SNAPSHOT(servent)
IMPLEMENT_1PASS_TEST(servent)
@@ -81,8 +78,8 @@ IMPLEMENT_2PASS_TEST(servent)
static void
clone_servent(struct servent *dest, struct servent const *src)
{
- assert(dest != NULL);
- assert(src != NULL);
+ ATF_REQUIRE(dest != NULL);
+ ATF_REQUIRE(src != NULL);
char **cp;
int aliases_num;
@@ -91,12 +88,12 @@ clone_servent(struct servent *dest, struct servent const *src)
if (src->s_name != NULL) {
dest->s_name = strdup(src->s_name);
- assert(dest->s_name != NULL);
+ ATF_REQUIRE(dest->s_name != NULL);
}
if (src->s_proto != NULL) {
dest->s_proto = strdup(src->s_proto);
- assert(dest->s_proto != NULL);
+ ATF_REQUIRE(dest->s_proto != NULL);
}
dest->s_port = src->s_port;
@@ -105,13 +102,12 @@ clone_servent(struct servent *dest, struct servent const *src)
for (cp = src->s_aliases; *cp; ++cp)
++aliases_num;
- dest->s_aliases = (char **)malloc((aliases_num+1) * (sizeof(char *)));
- assert(dest->s_aliases != NULL);
- memset(dest->s_aliases, 0, (aliases_num+1) * (sizeof(char *)));
+ dest->s_aliases = calloc(1, (aliases_num + 1) * sizeof(char *));
+ ATF_REQUIRE(dest->s_aliases != NULL);
for (cp = src->s_aliases; *cp; ++cp) {
dest->s_aliases[cp - src->s_aliases] = strdup(*cp);
- assert(dest->s_aliases[cp - src->s_aliases] != NULL);
+ ATF_REQUIRE(dest->s_aliases[cp - src->s_aliases] != NULL);
}
}
}
@@ -121,7 +117,7 @@ free_servent(struct servent *serv)
{
char **cp;
- assert(serv != NULL);
+ ATF_REQUIRE(serv != NULL);
free(serv->s_name);
free(serv->s_proto);
@@ -163,7 +159,7 @@ compare_servent(struct servent *serv1, struct servent *serv2, void *mdata)
return 0;
errfin:
- if ((debug) && (mdata == NULL)) {
+ if (mdata == NULL) {
printf("following structures are not equal:\n");
dump_servent(serv1);
dump_servent(serv2);
@@ -210,8 +206,7 @@ servent_read_snapshot_func(struct servent *serv, char *line)
char *s, *ps, *ts;
int i;
- if (debug)
- printf("1 line read from snapshot:\n%s\n", line);
+ printf("1 line read from snapshot:\n%s\n", line);
i = 0;
sl = NULL;
@@ -221,7 +216,7 @@ servent_read_snapshot_func(struct servent *serv, char *line)
switch (i) {
case 0:
serv->s_name = strdup(s);
- assert(serv->s_name != NULL);
+ ATF_REQUIRE(serv->s_name != NULL);
break;
case 1:
@@ -235,7 +230,7 @@ servent_read_snapshot_func(struct servent *serv, char *line)
case 2:
serv->s_proto = strdup(s);
- assert(serv->s_proto != NULL);
+ ATF_REQUIRE(serv->s_proto != NULL);
break;
default:
@@ -244,20 +239,20 @@ servent_read_snapshot_func(struct servent *serv, char *line)
return (0);
sl = sl_init();
- assert(sl != NULL);
+ ATF_REQUIRE(sl != NULL);
if (strcmp(s, "noaliases") != 0) {
ts = strdup(s);
- assert(ts != NULL);
+ ATF_REQUIRE(ts != NULL);
sl_add(sl, ts);
}
} else {
ts = strdup(s);
- assert(ts != NULL);
+ ATF_REQUIRE(ts != NULL);
sl_add(sl, ts);
}
break;
- };
+ }
++i;
}
@@ -307,10 +302,8 @@ servent_fill_test_data(struct servent_test_data *td)
static int
servent_test_correctness(struct servent *serv, void *mdata)
{
- if (debug) {
- printf("testing correctness with the following data:\n");
- dump_servent(serv);
- }
+ printf("testing correctness with the following data:\n");
+ dump_servent(serv);
if (serv == NULL)
goto errfin;
@@ -327,13 +320,11 @@ servent_test_correctness(struct servent *serv, void *mdata)
if (serv->s_aliases == NULL)
goto errfin;
- if (debug)
- printf("correct\n");
+ printf("correct\n");
return (0);
errfin:
- if (debug)
- printf("incorrect\n");
+ printf("incorrect\n");
return (-1);
}
@@ -357,10 +348,8 @@ servent_test_getservbyname(struct servent *serv_model, void *mdata)
char **alias;
struct servent *serv;
- if (debug) {
- printf("testing getservbyname() with the following data:\n");
- dump_servent(serv_model);
- }
+ printf("testing getservbyname() with the following data:\n");
+ dump_servent(serv_model);
serv = getservbyname(serv_model->s_name, serv_model->s_proto);
if (servent_test_correctness(serv, NULL) != 0)
@@ -369,7 +358,7 @@ servent_test_getservbyname(struct servent *serv_model, void *mdata)
if ((compare_servent(serv, serv_model, NULL) != 0) &&
(servent_check_ambiguity((struct servent_test_data *)mdata, serv)
!=0))
- goto errfin;
+ goto errfin;
for (alias = serv_model->s_aliases; *alias; ++alias) {
serv = getservbyname(*alias, serv_model->s_proto);
@@ -383,13 +372,11 @@ servent_test_getservbyname(struct servent *serv_model, void *mdata)
goto errfin;
}
- if (debug)
- printf("ok\n");
+ printf("ok\n");
return (0);
errfin:
- if (debug)
- printf("not ok\n");
+ printf("not ok\n");
return (-1);
}
@@ -399,23 +386,19 @@ servent_test_getservbyport(struct servent *serv_model, void *mdata)
{
struct servent *serv;
- if (debug) {
- printf("testing getservbyport() with the following data...\n");
- dump_servent(serv_model);
- }
+ printf("testing getservbyport() with the following data...\n");
+ dump_servent(serv_model);
serv = getservbyport(serv_model->s_port, serv_model->s_proto);
if ((servent_test_correctness(serv, NULL) != 0) ||
((compare_servent(serv, serv_model, NULL) != 0) &&
(servent_check_ambiguity((struct servent_test_data *)mdata, serv)
!= 0))) {
- if (debug)
printf("not ok\n");
- return (-1);
+ return (-1);
} else {
- if (debug)
printf("ok\n");
- return (0);
+ return (0);
}
}
@@ -427,50 +410,11 @@ servent_test_getservent(struct servent *serv, void *mdata)
return (servent_test_correctness(serv, NULL));
}
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s -npe2 [-d] [-s <file>]\n",
- getprogname());
- exit(1);
-}
-
int
-main(int argc, char **argv)
+run_tests(const char *snapshot_file, enum test_methods method)
{
struct servent_test_data td, td_snap, td_2pass;
- char *snapshot_file;
int rv;
- int c;
-
- if (argc < 2)
- usage();
-
- snapshot_file = NULL;
- while ((c = getopt(argc, argv, "npe2ds:")) != -1)
- switch (c) {
- case 'd':
- debug++;
- break;
- case 'n':
- method = TEST_GETSERVBYNAME;
- break;
- case 'p':
- method = TEST_GETSERVBYPORT;
- break;
- case 'e':
- method = TEST_GETSERVENT;
- break;
- case '2':
- method = TEST_GETSERVENT_2PASS;
- break;
- case 's':
- snapshot_file = strdup(optarg);
- break;
- default:
- usage();
- }
TEST_DATA_INIT(servent, &td, clone_servent, free_servent);
TEST_DATA_INIT(servent, &td_snap, clone_servent, free_servent);
@@ -479,9 +423,8 @@ main(int argc, char **argv)
if (errno == ENOENT)
method = TEST_BUILD_SNAPSHOT;
else {
- if (debug)
- printf("can't access the file %s\n",
- snapshot_file);
+ printf("can't access the file %s\n",
+ snapshot_file);
rv = -1;
goto fin;
@@ -541,11 +484,87 @@ main(int argc, char **argv)
default:
rv = 0;
break;
- };
+ }
fin:
TEST_DATA_DESTROY(servent, &td_snap);
TEST_DATA_DESTROY(servent, &td);
- free(snapshot_file);
+
return (rv);
}
+
+#define SNAPSHOT_FILE "snapshot_serv"
+
+ATF_TC_WITHOUT_HEAD(build_snapshot);
+ATF_TC_BODY(build_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getservbyname);
+ATF_TC_BODY(getservbyname, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETSERVBYNAME) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getservbyname_with_snapshot);
+ATF_TC_BODY(getservbyname_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETSERVBYNAME) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getservbyport);
+ATF_TC_BODY(getservbyport, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETSERVBYPORT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getservbyport_with_snapshot);
+ATF_TC_BODY(getservbyport_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETSERVBYPORT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getservbyent);
+ATF_TC_BODY(getservbyent, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETSERVENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getservbyent_with_snapshot);
+ATF_TC_BODY(getservbyent_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETSERVENT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getservbyent_with_two_pass);
+ATF_TC_BODY(getservbyent_with_two_pass, tc)
+{
+
+ ATF_REQUIRE(run_tests(NULL, TEST_GETSERVENT_2PASS) == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, build_snapshot);
+ ATF_TP_ADD_TC(tp, getservbyent);
+ ATF_TP_ADD_TC(tp, getservbyent_with_snapshot);
+ ATF_TP_ADD_TC(tp, getservbyent_with_two_pass);
+ ATF_TP_ADD_TC(tp, getservbyname);
+ ATF_TP_ADD_TC(tp, getservbyname_with_snapshot);
+ ATF_TP_ADD_TC(tp, getservbyport);
+ ATF_TP_ADD_TC(tp, getservbyport_with_snapshot);
+
+ return (atf_no_error());
+}
diff --git a/tools/regression/lib/libc/nss/test-getusershell.c b/lib/libc/tests/nss/getusershell_test.c
index b7b835f..ccd8cf9 100644
--- a/tools/regression/lib/libc/nss/test-getusershell.c
+++ b/lib/libc/tests/nss/getusershell_test.c
@@ -34,6 +34,9 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
+#include <atf-c.h>
+
#include "testutil.h"
enum test_methods {
@@ -45,7 +48,6 @@ struct usershell {
char *path;
};
-static int debug = 0;
static enum test_methods method = TEST_GETUSERSHELL;
DECLARE_TEST_DATA(usershell)
@@ -59,10 +61,6 @@ static void free_usershell(struct usershell *);
static void sdump_usershell(struct usershell *, char *, size_t);
static void dump_usershell(struct usershell *);
-static int usershell_read_snapshot_func(struct usershell *, char *);
-
-static void usage(void) __attribute__((__noreturn__));
-
IMPLEMENT_TEST_DATA(usershell)
IMPLEMENT_TEST_FILE_SNAPSHOT(usershell)
IMPLEMENT_2PASS_TEST(usershell)
@@ -129,69 +127,39 @@ dump_usershell(struct usershell *us)
static int
usershell_read_snapshot_func(struct usershell *us, char *line)
{
+
us->path = strdup(line);
- assert(us->path != NULL);
+ ATF_REQUIRE(us->path != NULL);
return (0);
}
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s [-d] -s <file>\n",
- getprogname());
- exit(1);
-}
-
int
-main(int argc, char **argv)
+run_tests(const char *snapshot_file, enum test_methods method)
{
struct usershell_test_data td, td_snap;
struct usershell ushell;
- char *snapshot_file;
int rv;
- int c;
-
- if (argc < 2)
- usage();
rv = 0;
- snapshot_file = NULL;
- while ((c = getopt(argc, argv, "ds:")) != -1) {
- switch (c) {
- case 'd':
- debug = 1;
- break;
- case 's':
- snapshot_file = strdup(optarg);
- break;
- default:
- usage();
- }
- }
TEST_DATA_INIT(usershell, &td, clone_usershell, free_usershell);
TEST_DATA_INIT(usershell, &td_snap, clone_usershell, free_usershell);
setusershell();
while ((ushell.path = getusershell()) != NULL) {
- if (debug) {
- printf("usershell found:\n");
- dump_usershell(&ushell);
- }
+ printf("usershell found:\n");
+ dump_usershell(&ushell);
TEST_DATA_APPEND(usershell, &td, &ushell);
}
endusershell();
-
if (snapshot_file != NULL) {
if (access(snapshot_file, W_OK | R_OK) != 0) {
if (errno == ENOENT)
method = TEST_BUILD_SNAPSHOT;
else {
- if (debug)
- printf("can't access the snapshot file %s\n",
+ printf("can't access the snapshot file %s\n",
snapshot_file);
rv = -1;
@@ -201,8 +169,7 @@ main(int argc, char **argv)
rv = TEST_SNAPSHOT_FILE_READ(usershell, snapshot_file,
&td_snap, usershell_read_snapshot_func);
if (rv != 0) {
- if (debug)
- printf("error reading snapshot file\n");
+ printf("error reading snapshot file\n");
goto fin;
}
}
@@ -210,26 +177,49 @@ main(int argc, char **argv)
switch (method) {
case TEST_GETUSERSHELL:
- if (snapshot_file != NULL) {
- rv = DO_2PASS_TEST(usershell, &td, &td_snap,
- compare_usershell, NULL);
- }
+ rv = DO_2PASS_TEST(usershell, &td, &td_snap,
+ compare_usershell, NULL);
break;
case TEST_BUILD_SNAPSHOT:
if (snapshot_file != NULL) {
- rv = TEST_SNAPSHOT_FILE_WRITE(usershell, snapshot_file, &td,
- sdump_usershell);
+ rv = TEST_SNAPSHOT_FILE_WRITE(usershell, snapshot_file,
+ &td, sdump_usershell);
}
break;
default:
rv = 0;
break;
- };
+ }
fin:
TEST_DATA_DESTROY(usershell, &td_snap);
TEST_DATA_DESTROY(usershell, &td);
- free(snapshot_file);
+
return (rv);
+}
+
+#define SNAPSHOT_FILE "snapshot_usershell"
+
+ATF_TC_WITHOUT_HEAD(getusershell_with_snapshot);
+ATF_TC_BODY(getusershell_with_snapshot, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(getusershell_with_two_pass);
+ATF_TC_BODY(getusershell_with_two_pass, tc)
+{
+
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_BUILD_SNAPSHOT) == 0);
+ ATF_REQUIRE(run_tests(SNAPSHOT_FILE, TEST_GETUSERSHELL) == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getusershell_with_snapshot);
+ ATF_TP_ADD_TC(tp, getusershell_with_two_pass);
+ return (atf_no_error());
}
diff --git a/tools/regression/lib/libc/nss/testutil.h b/lib/libc/tests/nss/testutil.h
index 711c49f..39c4f41 100644
--- a/tools/regression/lib/libc/nss/testutil.h
+++ b/lib/libc/tests/nss/testutil.h
@@ -73,9 +73,9 @@ __##ent##_test_data_init(struct ent##_test_data *td, \
void (*clonef)(struct ent *, struct ent const *), \
void (*freef)(struct ent *)) \
{ \
- assert(td != NULL); \
- assert(clonef != NULL); \
- assert(freef != NULL); \
+ ATF_REQUIRE(td != NULL); \
+ ATF_REQUIRE(clonef != NULL); \
+ ATF_REQUIRE(freef != NULL); \
\
memset(td, 0, sizeof(*td)); \
td->clone_func = clonef; \
@@ -94,11 +94,11 @@ __##ent##_test_data_append(struct ent##_test_data *td, struct ent *app_data)\
{ \
struct ent##_entry *e; \
\
- assert(td != NULL); \
- assert(app_data != NULL); \
+ ATF_REQUIRE(td != NULL); \
+ ATF_REQUIRE(app_data != NULL); \
\
e = (struct ent##_entry *)malloc(sizeof(struct ent##_entry)); \
- assert(e != NULL); \
+ ATF_REQUIRE(e != NULL); \
memset(e, 0, sizeof(struct ent##_entry)); \
\
td->clone_func(&e->data, app_data); \
@@ -112,8 +112,8 @@ __##ent##_test_data_foreach(struct ent##_test_data *td, \
struct ent##_entry *e; \
int rv; \
\
- assert(td != NULL); \
- assert(forf != NULL); \
+ ATF_REQUIRE(td != NULL); \
+ ATF_REQUIRE(forf != NULL); \
\
rv = 0; \
STAILQ_FOREACH(e, &td->snapshot_data, entries) { \
@@ -132,9 +132,9 @@ __##ent##_test_data_compare(struct ent##_test_data *td1, struct ent##_test_data
struct ent##_entry *e1, *e2; \
int rv; \
\
- assert(td1 != NULL); \
- assert(td2 != NULL); \
- assert(cmp_func != NULL); \
+ ATF_REQUIRE(td1 != NULL); \
+ ATF_REQUIRE(td2 != NULL); \
+ ATF_REQUIRE(cmp_func != NULL); \
\
e1 = STAILQ_FIRST(&td1->snapshot_data); \
e2 = STAILQ_FIRST(&td2->snapshot_data); \
@@ -163,8 +163,8 @@ __##ent##_test_data_find(struct ent##_test_data *td, struct ent *data, \
struct ent##_entry *e; \
struct ent *result; \
\
- assert(td != NULL); \
- assert(cmp != NULL); \
+ ATF_REQUIRE(td != NULL); \
+ ATF_REQUIRE(cmp != NULL); \
\
result = NULL; \
STAILQ_FOREACH(e, &td->snapshot_data, entries) { \
@@ -182,7 +182,7 @@ void \
__##ent##_test_data_clear(struct ent##_test_data *td) \
{ \
struct ent##_entry *e; \
- assert(td != NULL); \
+ ATF_REQUIRE(td != NULL); \
\
while (!STAILQ_EMPTY(&td->snapshot_data)) { \
e = STAILQ_FIRST(&td->snapshot_data); \
@@ -190,6 +190,7 @@ __##ent##_test_data_clear(struct ent##_test_data *td) \
\
td->free_func(&e->data); \
free(e); \
+ e = NULL; \
} \
}
@@ -217,7 +218,7 @@ __##ent##_snapshot_write_func(struct ent *data, void *mdata) \
char buffer[1024]; \
struct ent##_snp_param *param; \
\
- assert(data != NULL); \
+ ATF_REQUIRE(data != NULL); \
\
param = (struct ent##_snp_param *)mdata; \
param->sdump_func(data, buffer, sizeof(buffer)); \
@@ -233,8 +234,8 @@ __##ent##_snapshot_write(char const *fname, struct ent##_test_data *td, \
{ \
struct ent##_snp_param param; \
\
- assert(fname != NULL); \
- assert(td != NULL); \
+ ATF_REQUIRE(fname != NULL); \
+ ATF_REQUIRE(td != NULL); \
\
param.fp = fopen(fname, "w"); \
if (param.fp == NULL) \
@@ -258,8 +259,8 @@ __##ent##_snapshot_read(char const *fname, struct ent##_test_data *td, \
size_t len; \
int rv; \
\
- assert(fname != NULL); \
- assert(td != NULL); \
+ ATF_REQUIRE(fname != NULL); \
+ ATF_REQUIRE(td != NULL); \
\
fi = fopen(fname, "r"); \
if (fi == NULL) \
diff --git a/lib/libc/tests/resolv/Makefile b/lib/libc/tests/resolv/Makefile
new file mode 100644
index 0000000..4e4e62be
--- /dev/null
+++ b/lib/libc/tests/resolv/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/lib/libc/resolv
+BINDIR= ${TESTSDIR}
+
+FILES+= mach
+
+ATF_TESTS_C+= resolv_test
+#TEST_METADATA.resolv_test= timeout="1800"
+
+# Note: this test relies on being dynamically linked. You will get a
+# spurious PASS for a statically linked test.
+LIBADD.resolv_test+= pthread
+
+.include <bsd.test.mk>
diff --git a/lib/libc/tests/resolv/mach b/lib/libc/tests/resolv/mach
new file mode 100644
index 0000000..4b47ebb
--- /dev/null
+++ b/lib/libc/tests/resolv/mach
@@ -0,0 +1,46 @@
+# $FreeBSD$
+localhost
+anoncvs.cirr.com
+anoncvs.netbsd.se
+antioche.antioche.eu.org
+centaurus.4web.cz
+chur.math.ntnu.no
+console.netbsd.org
+cvs.netbsd.org
+cvsup.netbsd.se
+ftp.chg.ru
+ftp.estpak.ee
+ftp.fsn.hu
+ftp.funet.fi
+ftp.netbsd.org
+ftp.nluug.nl
+ftp.plig.org
+ftp.uni-erlangen.de
+ftp.xgate.co.kr
+gd.tuwien.ac.at
+gort.ludd.luth.se
+irc.warped.net
+knug.youn.co.kr
+mail.jp.netbsd.org
+mail.netbsd.org
+melanoma.cs.rmit.edu.au
+mirror.aarnet.edu.au
+moon.vub.ac.be
+net.bsd.cz
+netbsd.3miasto.net
+netbsd.4ka.mipt.ru
+netbsd.csie.nctu.edu.tw
+netbsd.enderunix.org
+netbsd.ftp.fu-berlin.de
+netbsd.pair.com
+netbsdiso.interoute.net.uk
+netbsdwww.cs.rmit.edu.au
+netbsdwww.interoute.net.uk
+ns.netbsd.org
+skeleton.phys.spbu.ru
+www.en.netbsd.de
+www.netbsd.cl
+www.netbsd.nl
+www.netbsd.org
+www.netbsd.ro
+zeppo.rediris.es
diff --git a/tools/regression/lib/libc/resolv/resolv.c b/lib/libc/tests/resolv/resolv_test.c
index 2ec3eeb..5c53569 100644
--- a/tools/regression/lib/libc/resolv/resolv.c
+++ b/lib/libc/tests/resolv/resolv_test.c
@@ -39,10 +39,11 @@ __RCSID("$NetBSD: resolv.c,v 1.6 2004/05/23 16:59:11 christos Exp $");
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
-#include <err.h>
#include <string.h>
#include <stringlist.h>
+#include <atf-c.h>
+
#define NTHREADS 10
#define NHOSTS 100
#define WS " \t\n\r"
@@ -54,13 +55,10 @@ enum method {
};
static StringList *hosts = NULL;
-static int debug = 0;
static enum method method = METHOD_GETADDRINFO;
-static int reverse = 0;
static int *ask = NULL;
static int *got = NULL;
-static void usage(void) __attribute__((__noreturn__));
static void load(const char *);
static void resolvone(int);
static void *resolvloop(void *);
@@ -69,15 +67,6 @@ static void run(int *);
static pthread_mutex_t stats = PTHREAD_MUTEX_INITIALIZER;
static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s [-AdHIr] [-h <nhosts>] [-n <nthreads>] <file> ...\n",
- getprogname());
- exit(1);
-}
-
-static void
load(const char *fname)
{
FILE *fp;
@@ -85,7 +74,7 @@ load(const char *fname)
char *line;
if ((fp = fopen(fname, "r")) == NULL)
- err(1, "Cannot open `%s'", fname);
+ ATF_REQUIRE(fp != NULL);
while ((line = fgetln(fp, &len)) != NULL) {
char c = line[len];
char *ptr;
@@ -114,21 +103,17 @@ resolv_getaddrinfo(pthread_t self, char *host, int port)
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(host, portstr, &hints, &res);
- if (debug) {
- len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
- self, host, error ? "not found" : "ok");
- (void)write(STDOUT_FILENO, buf, len);
- }
- if (error == 0 && reverse) {
+ len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
+ self, host, error ? "not found" : "ok");
+ (void)write(STDOUT_FILENO, buf, len);
+ if (error == 0) {
memset(hbuf, 0, sizeof(hbuf));
memset(pbuf, 0, sizeof(pbuf));
getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
pbuf, sizeof(pbuf), 0);
- if (debug) {
- len = snprintf(buf, sizeof(buf),
- "%p: reverse %s %s\n", self, hbuf, pbuf);
- (void)write(STDOUT_FILENO, buf, len);
- }
+ len = snprintf(buf, sizeof(buf),
+ "%p: reverse %s %s\n", self, hbuf, pbuf);
+ (void)write(STDOUT_FILENO, buf, len);
}
if (error == 0)
freeaddrinfo(res);
@@ -143,15 +128,13 @@ resolv_gethostby(pthread_t self, char *host)
int len;
hp = gethostbyname(host);
- if (debug) {
- len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
- self, host, (hp == NULL) ? "not found" : "ok");
- (void)write(STDOUT_FILENO, buf, len);
- }
- if (hp && reverse) {
+ len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
+ self, host, (hp == NULL) ? "not found" : "ok");
+ (void)write(STDOUT_FILENO, buf, len);
+ if (hp) {
memcpy(buf, hp->h_addr, hp->h_length);
hp2 = gethostbyaddr(buf, hp->h_length, hp->h_addrtype);
- if (hp2 && debug) {
+ if (hp2) {
len = snprintf(buf, sizeof(buf),
"%p: reverse %s\n", self, hp2->h_name);
(void)write(STDOUT_FILENO, buf, len);
@@ -168,16 +151,14 @@ resolv_getipnodeby(pthread_t self, char *host)
int len, h_error;
hp = getipnodebyname(host, AF_INET, 0, &h_error);
- if (debug) {
- len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
- self, host, (hp == NULL) ? "not found" : "ok");
- (void)write(STDOUT_FILENO, buf, len);
- }
- if (hp && reverse) {
+ len = snprintf(buf, sizeof(buf), "%p: host %s %s\n",
+ self, host, (hp == NULL) ? "not found" : "ok");
+ (void)write(STDOUT_FILENO, buf, len);
+ if (hp) {
memcpy(buf, hp->h_addr, hp->h_length);
hp2 = getipnodebyaddr(buf, hp->h_length, hp->h_addrtype,
&h_error);
- if (hp2 && debug) {
+ if (hp2) {
len = snprintf(buf, sizeof(buf),
"%p: reverse %s\n", self, hp2->h_name);
(void)write(STDOUT_FILENO, buf, len);
@@ -200,11 +181,9 @@ resolvone(int n)
struct addrinfo hints, *res;
int error, len;
- if (debug) {
- len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
- self, n, host, (int)i);
- (void)write(STDOUT_FILENO, buf, len);
- }
+ len = snprintf(buf, sizeof(buf), "%p: %d resolving %s %d\n",
+ self, n, host, (int)i);
+ (void)write(STDOUT_FILENO, buf, len);
switch (method) {
case METHOD_GETADDRINFO:
error = resolv_getaddrinfo(self, host, i);
@@ -239,13 +218,16 @@ resolvloop(void *p)
static void
run(int *nhosts)
{
- pthread_t self = pthread_self();
- if (pthread_create(&self, NULL, resolvloop, nhosts) != 0)
- err(1, "pthread_create");
+ pthread_t self;
+ int rc;
+
+ self = pthread_self();
+ rc = pthread_create(&self, NULL, resolvloop, nhosts);
+ ATF_REQUIRE_MSG(rc == 0, "pthread_create failed: %s", strerror(rc));
}
-int
-main(int argc, char *argv[])
+static int
+run_tests(const char *hostlist_file, enum method method)
{
int nthreads = NTHREADS;
int nhosts = NHOSTS;
@@ -254,46 +236,18 @@ main(int argc, char *argv[])
srandom(1234);
- while ((c = getopt(argc, argv, "Adh:HIn:r")) != -1)
- switch (c) {
- case 'A':
- method = METHOD_GETADDRINFO;
- break;
- case 'd':
- debug++;
- break;
- case 'h':
- nhosts = atoi(optarg);
- break;
- case 'H':
- method = METHOD_GETHOSTBY;
- break;
- case 'I':
- method = METHOD_GETIPNODEBY;
- break;
- case 'n':
- nthreads = atoi(optarg);
- break;
- case 'r':
- reverse++;
- break;
- default:
- usage();
- }
+ load(hostlist_file);
- for (i = optind; i < argc; i++)
- load(argv[i]);
+ ATF_REQUIRE_MSG(0 < hosts->sl_cur, "0 hosts in %s", hostlist_file);
- if (hosts->sl_cur == 0)
- usage();
+ nleft = malloc(nthreads * sizeof(int));
+ ATF_REQUIRE(nleft != NULL);
- if ((nleft = malloc(nthreads * sizeof(int))) == NULL)
- err(1, "malloc");
- if ((ask = calloc(hosts->sl_cur, sizeof(int))) == NULL)
- err(1, "calloc");
- if ((got = calloc(hosts->sl_cur, sizeof(int))) == NULL)
- err(1, "calloc");
+ ask = calloc(hosts->sl_cur, sizeof(int));
+ ATF_REQUIRE(ask != NULL);
+ got = calloc(hosts->sl_cur, sizeof(int));
+ ATF_REQUIRE(got != NULL);
for (i = 0; i < nthreads; i++) {
nleft[i] = nhosts;
@@ -313,7 +267,7 @@ main(int argc, char *argv[])
c = 0;
for (i = 0; i < hosts->sl_cur; i++) {
if (ask[i] != got[i] && got[i] != 0) {
- warnx("Error: host %s ask %d got %d\n",
+ printf("Error: host %s ask %d got %d\n",
hosts->sl_str[i], ask[i], got[i]);
c++;
}
@@ -324,3 +278,44 @@ main(int argc, char *argv[])
sl_free(hosts, 1);
return c;
}
+
+#define HOSTLIST_FILE "mach"
+
+#define RUN_TESTS(tc, method) \
+do { \
+ char *_hostlist_file; \
+ ATF_REQUIRE(0 < asprintf(&_hostlist_file, "%s/%s", \
+ atf_tc_get_config_var(tc, "srcdir"), HOSTLIST_FILE)); \
+ ATF_REQUIRE(run_tests(_hostlist_file, method) == 0); \
+} while(0)
+
+ATF_TC_WITHOUT_HEAD(getaddrinfo_test);
+ATF_TC_BODY(getaddrinfo_test, tc)
+{
+
+ RUN_TESTS(tc, METHOD_GETADDRINFO);
+}
+
+ATF_TC_WITHOUT_HEAD(gethostby_test);
+ATF_TC_BODY(gethostby_test, tc)
+{
+
+ RUN_TESTS(tc, METHOD_GETHOSTBY);
+}
+
+ATF_TC_WITHOUT_HEAD(getipnodeby_test);
+ATF_TC_BODY(getipnodeby_test, tc)
+{
+
+ RUN_TESTS(tc, METHOD_GETIPNODEBY);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getaddrinfo_test);
+ ATF_TP_ADD_TC(tp, gethostby_test);
+ ATF_TP_ADD_TC(tp, getipnodeby_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index 51cac70..206648d 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -130,8 +130,8 @@ struct httpio
int chunked; /* chunked mode */
char *buf; /* chunk buffer */
size_t bufsize; /* size of chunk buffer */
- ssize_t buflen; /* amount of data currently in buffer */
- int bufpos; /* current read offset in buffer */
+ size_t buflen; /* amount of data currently in buffer */
+ size_t bufpos; /* current read offset in buffer */
int eof; /* end-of-file flag */
int error; /* error flag */
size_t chunksize; /* remaining size of current chunk */
@@ -215,6 +215,7 @@ http_fillbuf(struct httpio *io, size_t len)
if (io->eof)
return (0);
+ /* not chunked: just fetch the requested amount */
if (io->chunked == 0) {
if (http_growbuf(io, len) == -1)
return (-1);
@@ -227,6 +228,7 @@ http_fillbuf(struct httpio *io, size_t len)
return (io->buflen);
}
+ /* chunked, but we ran out: get the next chunk header */
if (io->chunksize == 0) {
switch (http_new_chunk(io)) {
case -1:
@@ -238,6 +240,7 @@ http_fillbuf(struct httpio *io, size_t len)
}
}
+ /* fetch the requested amount, but no more than the current chunk */
if (len > io->chunksize)
len = io->chunksize;
if (http_growbuf(io, len) == -1)
@@ -246,8 +249,9 @@ http_fillbuf(struct httpio *io, size_t len)
io->error = errno;
return (-1);
}
+ io->bufpos = 0;
io->buflen = nbytes;
- io->chunksize -= io->buflen;
+ io->chunksize -= nbytes;
if (io->chunksize == 0) {
if (fetch_read(io->conn, &ch, 1) != 1 || ch != '\r' ||
@@ -255,8 +259,6 @@ http_fillbuf(struct httpio *io, size_t len)
return (-1);
}
- io->bufpos = 0;
-
return (io->buflen);
}
diff --git a/lib/libstand/tftp.c b/lib/libstand/tftp.c
index 6527c4e..001cbfd 100644
--- a/lib/libstand/tftp.c
+++ b/lib/libstand/tftp.c
@@ -399,6 +399,8 @@ tftp_open(const char *path, struct open_file *f)
struct tftp_handle *tftpfile;
struct iodesc *io;
int res;
+ size_t pathsize;
+ const char *extraslash;
if (strcmp(f->f_dev->dv_name, "net") != 0) {
#ifdef __i386__
@@ -424,10 +426,22 @@ tftp_open(const char *path, struct open_file *f)
io->destip = servip;
tftpfile->off = 0;
- tftpfile->path = strdup(path);
+ pathsize = (strlen(rootpath) + 1 + strlen(path) + 1) * sizeof(char);
+ tftpfile->path = malloc(pathsize);
if (tftpfile->path == NULL) {
- free(tftpfile);
- return(ENOMEM);
+ free(tftpfile);
+ return(ENOMEM);
+ }
+ if (rootpath[strlen(rootpath) - 1] == '/' || path[0] == '/')
+ extraslash = "";
+ else
+ extraslash = "/";
+ res = snprintf(tftpfile->path, pathsize, "%s%s%s",
+ rootpath, extraslash, path);
+ if (res < 0 || res > pathsize) {
+ free(tftpfile->path);
+ free(tftpfile);
+ return(ENOMEM);
}
res = tftp_makereq(tftpfile);
diff --git a/lib/msun/tests/Makefile b/lib/msun/tests/Makefile
index 61fd83e..dfac5a2 100644
--- a/lib/msun/tests/Makefile
+++ b/lib/msun/tests/Makefile
@@ -36,11 +36,34 @@ NETBSD_ATF_TESTS_C+= sqrt_test
NETBSD_ATF_TESTS_C+= tan_test
NETBSD_ATF_TESTS_C+= tanh_test
+TAP_TESTS_C+= cexp_test
+TAP_TESTS_C+= conj_test
+TAP_TESTS_C+= csqrt_test
+TAP_TESTS_C+= fenv_test
+TAP_TESTS_C+= fmaxmin_test
+TAP_TESTS_C+= ilogb_test
+TAP_TESTS_C+= invctrig_test
+TAP_TESTS_C+= logarithm_test
+TAP_TESTS_C+= lrint_test
+TAP_TESTS_C+= nan_test
+TAP_TESTS_C+= nearbyint_test
+TAP_TESTS_C+= next_test
+TAP_TESTS_C+= rem_test
+TAP_TESTS_C+= trig_test
+
+.for t in ${TAP_TESTS_C}
+CFLAGS.$t+= -O0
+CFLAGS.$t+= -I${SRCTOP}/tools/regression/lib/msun
+.endfor
+
CSTD= c99
-LIBADD+= m
#COPTS+= -Wfloat-equal
+IGNORE_PRAGMA=
+
+LIBADD+= m
+
# Copied from lib/msun/Makefile
.if ${MACHINE_CPUARCH} == "i386"
ARCH_SUBDIR= i387
diff --git a/tools/regression/lib/msun/test-cexp.c b/lib/msun/tests/cexp_test.c
index 6be71ad..6be71ad 100644
--- a/tools/regression/lib/msun/test-cexp.c
+++ b/lib/msun/tests/cexp_test.c
diff --git a/tools/regression/lib/msun/test-conj.c b/lib/msun/tests/conj_test.c
index 7426f9e..7426f9e 100644
--- a/tools/regression/lib/msun/test-conj.c
+++ b/lib/msun/tests/conj_test.c
diff --git a/tools/regression/lib/msun/test-csqrt.c b/lib/msun/tests/csqrt_test.c
index aa119d1..aa119d1 100644
--- a/tools/regression/lib/msun/test-csqrt.c
+++ b/lib/msun/tests/csqrt_test.c
diff --git a/tools/regression/lib/msun/test-fenv.c b/lib/msun/tests/fenv_test.c
index 0ea6e42..0ea6e42 100644
--- a/tools/regression/lib/msun/test-fenv.c
+++ b/lib/msun/tests/fenv_test.c
diff --git a/tools/regression/lib/msun/test-fmaxmin.c b/lib/msun/tests/fmaxmin_test.c
index 7ddcc87..7ddcc87 100644
--- a/tools/regression/lib/msun/test-fmaxmin.c
+++ b/lib/msun/tests/fmaxmin_test.c
diff --git a/tools/regression/lib/msun/test-ilogb.c b/lib/msun/tests/ilogb_test.c
index a1440c4..a1440c4 100644
--- a/tools/regression/lib/msun/test-ilogb.c
+++ b/lib/msun/tests/ilogb_test.c
diff --git a/tools/regression/lib/msun/test-invctrig.c b/lib/msun/tests/invctrig_test.c
index 78b1119..34e78a1 100644
--- a/tools/regression/lib/msun/test-invctrig.c
+++ b/lib/msun/tests/invctrig_test.c
@@ -281,21 +281,21 @@ test_axes(void)
for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) {
/* Real axis */
z = CMPLXL(nums[i], 0.0);
- if (fabs(nums[i]) <= 1) {
+ if (fabsl(nums[i]) <= 1) {
testall_tol(cacosh, z, CMPLXL(0.0, acos(nums[i])), 1);
testall_tol(cacos, z, CMPLXL(acosl(nums[i]), -0.0), 1);
testall_tol(casin, z, CMPLXL(asinl(nums[i]), 0.0), 1);
testall_tol(catanh, z, CMPLXL(atanh(nums[i]), 0.0), 1);
} else {
testall_tol(cacosh, z,
- CMPLXL(acosh(fabs(nums[i])),
+ CMPLXL(acosh(fabsl(nums[i])),
(nums[i] < 0) ? pi : 0), 1);
testall_tol(cacos, z,
CMPLXL((nums[i] < 0) ? pi : 0,
- -acosh(fabs(nums[i]))), 1);
+ -acosh(fabsl(nums[i]))), 1);
testall_tol(casin, z,
CMPLXL(copysign(pi / 2, nums[i]),
- acosh(fabs(nums[i]))), 1);
+ acosh(fabsl(nums[i]))), 1);
testall_tol(catanh, z,
CMPLXL(atanh(1 / nums[i]), pi / 2), 1);
}
diff --git a/tools/regression/lib/msun/test-logarithm.c b/lib/msun/tests/logarithm_test.c
index 18b9ebe..18b9ebe 100644
--- a/tools/regression/lib/msun/test-logarithm.c
+++ b/lib/msun/tests/logarithm_test.c
diff --git a/tools/regression/lib/msun/test-lrint.c b/lib/msun/tests/lrint_test.c
index ba099aa..ba099aa 100644
--- a/tools/regression/lib/msun/test-lrint.c
+++ b/lib/msun/tests/lrint_test.c
diff --git a/tools/regression/lib/msun/test-nan.c b/lib/msun/tests/nan_test.c
index c12926b..c12926b 100644
--- a/tools/regression/lib/msun/test-nan.c
+++ b/lib/msun/tests/nan_test.c
diff --git a/tools/regression/lib/msun/test-nearbyint.c b/lib/msun/tests/nearbyint_test.c
index 602ea2a..602ea2a 100644
--- a/tools/regression/lib/msun/test-nearbyint.c
+++ b/lib/msun/tests/nearbyint_test.c
diff --git a/tools/regression/lib/msun/test-next.c b/lib/msun/tests/next_test.c
index d16fa77..d16fa77 100644
--- a/tools/regression/lib/msun/test-next.c
+++ b/lib/msun/tests/next_test.c
diff --git a/tools/regression/lib/msun/test-rem.c b/lib/msun/tests/rem_test.c
index 36e3476..36e3476 100644
--- a/tools/regression/lib/msun/test-rem.c
+++ b/lib/msun/tests/rem_test.c
diff --git a/tools/regression/lib/msun/test-trig.c b/lib/msun/tests/trig_test.c
index 1dcce1f..1dcce1f 100644
--- a/tools/regression/lib/msun/test-trig.c
+++ b/lib/msun/tests/trig_test.c
diff --git a/secure/lib/libcrypto/engines/Makefile b/secure/lib/libcrypto/engines/Makefile
index a41dd7b..73ad68c 100644
--- a/secure/lib/libcrypto/engines/Makefile
+++ b/secure/lib/libcrypto/engines/Makefile
@@ -2,5 +2,5 @@
SUBDIR= lib4758cca libaep libatalla libcapi libchil libcswift libgost \
libnuron libsureware libubsec
-
+SUBDIR_PARALLEL=
.include <bsd.subdir.mk>
diff --git a/share/man/man9/VOP_GETPAGES.9 b/share/man/man9/VOP_GETPAGES.9
index 2cc5b7a..4625d9b 100644
--- a/share/man/man9/VOP_GETPAGES.9
+++ b/share/man/man9/VOP_GETPAGES.9
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 12, 2014
+.Dd December 16, 2015
.Dt VOP_GETPAGES 9
.Os
.Sh NAME
@@ -41,7 +41,7 @@
.In sys/vnode.h
.In vm/vm.h
.Ft int
-.Fn VOP_GETPAGES "struct vnode *vp" "vm_page_t *ma" "int count" "int reqpage"
+.Fn VOP_GETPAGES "struct vnode *vp" "vm_page_t *ma" "int count" "int *rbehind" "int *rahead"
.Ft int
.Fn VOP_PUTPAGES "struct vnode *vp" "vm_page_t *ma" "int count" "int sync" "int *rtvals"
.Sh DESCRIPTION
@@ -63,7 +63,7 @@ locks are held.
Both methods return in the same state on both success and error returns.
.Pp
The arguments are:
-.Bl -tag -width reqpage
+.Bl -tag -width rbehind
.It Fa vp
The file to access.
.It Fa ma
@@ -78,9 +78,16 @@ if the write should be synchronous.
An array of VM system result codes indicating the status of each
page written by
.Fn VOP_PUTPAGES .
-.It Fa reqpage
-The index in the page array of the requested page; i.e., the one page which
-the implementation of this method must handle.
+.It Fa rbehind
+Optional pointer to integer specifying number of pages to be read behind, if
+possible.
+If the filesystem supports that feature, number of actually read pages is
+reported back, otherwise zero is returned.
+.It Fa rahead
+Optional pointer to integer specifying number of pages to be read ahead, if
+possible.
+If the filesystem supports that feature, number of actually read pages is
+reported back, otherwise zero is returned.
.El
.Pp
The status of the
diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
index f94e63a..65c4348 100644
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -180,7 +180,6 @@ __DEFAULT_NO_OPTIONS = \
DTRACE_TESTS \
EISA \
HESIOD \
- LLDB \
NAND \
OFED \
OPENLDAP \
@@ -240,6 +239,11 @@ BROKEN_OPTIONS+=PROFILE # "sorry, unimplemented: profiler support for RISC-V"
BROKEN_OPTIONS+=TESTS # "undefined reference to `_Unwind_Resume'"
BROKEN_OPTIONS+=CXX # "libcxxrt.so: undefined reference to `_Unwind_Resume_or_Rethrow'"
.endif
+.if ${__T} == "aarch64" || ${__T} == "amd64"
+__DEFAULT_YES_OPTIONS+=LLDB
+.else
+__DEFAULT_NO_OPTIONS+=LLDB
+.endif
# LLVM lacks support for FreeBSD 64-bit atomic operations for ARMv4/ARMv5
.if ${__T} == "arm" || ${__T} == "armeb"
BROKEN_OPTIONS+=LLDB
diff --git a/sys/arm/arm/pmap-v6-new.c b/sys/arm/arm/pmap-v6-new.c
index 4e58cf6..8d14ed7 100644
--- a/sys/arm/arm/pmap-v6-new.c
+++ b/sys/arm/arm/pmap-v6-new.c
@@ -4153,10 +4153,25 @@ pmap_remove_pages(pmap_t pmap)
uint32_t inuse, bitmask;
boolean_t allfree;
- if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) {
- printf("warning: %s called with non-current pmap\n", __func__);
- return;
+ /*
+ * Assert that the given pmap is only active on the current
+ * CPU. Unfortunately, we cannot block another CPU from
+ * activating the pmap while this function is executing.
+ */
+ KASSERT(pmap == vmspace_pmap(curthread->td_proc->p_vmspace),
+ ("%s: non-current pmap %p", __func__, pmap));
+#if defined(SMP) && defined(INVARIANTS)
+ {
+ cpuset_t other_cpus;
+
+ sched_pin();
+ other_cpus = pmap->pm_active;
+ CPU_CLR(PCPU_GET(cpuid), &other_cpus);
+ sched_unpin();
+ KASSERT(CPU_EMPTY(&other_cpus),
+ ("%s: pmap %p active on other cpus", __func__, pmap));
}
+#endif
SLIST_INIT(&free);
rw_wlock(&pvh_global_lock);
PMAP_LOCK(pmap);
diff --git a/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c b/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
index 0c26072..c1dbec2 100644
--- a/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
+++ b/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
@@ -174,13 +174,6 @@ elf64_exec(struct preloaded_file *fp)
if (err != 0)
return(err);
- status = BS->ExitBootServices(IH, efi_mapkey);
- if (EFI_ERROR(status)) {
- printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
- (long)status);
- return (EINVAL);
- }
-
dev_cleanup();
trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4,
diff --git a/sys/boot/efi/loader/arch/arm/exec.c b/sys/boot/efi/loader/arch/arm/exec.c
index 1cbbce5..7c51e6e 100644
--- a/sys/boot/efi/loader/arch/arm/exec.c
+++ b/sys/boot/efi/loader/arch/arm/exec.c
@@ -82,13 +82,6 @@ __elfN(arm_exec)(struct preloaded_file *fp)
printf("modulep: %#x\n", modulep);
printf("relocation_offset %llx\n", __elfN(relocation_offset));
- status = BS->ExitBootServices(IH, efi_mapkey);
- if (EFI_ERROR(status)) {
- printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
- (long)status);
- return (EINVAL);
- }
-
dev_cleanup();
(*entry)((void *)modulep);
diff --git a/sys/boot/efi/loader/arch/arm64/exec.c b/sys/boot/efi/loader/arch/arm64/exec.c
index d13e97b..0746c05 100644
--- a/sys/boot/efi/loader/arch/arm64/exec.c
+++ b/sys/boot/efi/loader/arch/arm64/exec.c
@@ -118,13 +118,6 @@ elf64_exec(struct preloaded_file *fp)
if (err != 0)
return (err);
- status = BS->ExitBootServices(IH, efi_mapkey);
- if (EFI_ERROR(status)) {
- printf("%s: ExitBootServices() returned 0x%lx\n", __func__,
- (long)status);
- return (EINVAL);
- }
-
/* Clean D-cache under kernel area and invalidate whole I-cache */
clean_addr = efi_translate(fp->f_addr);
clean_size = efi_translate(kernendp) - clean_addr;
diff --git a/sys/boot/efi/loader/bootinfo.c b/sys/boot/efi/loader/bootinfo.c
index 6ef83a8..c9dbe8d 100644
--- a/sys/boot/efi/loader/bootinfo.c
+++ b/sys/boot/efi/loader/bootinfo.c
@@ -55,8 +55,6 @@ __FBSDID("$FreeBSD$");
#include <fdt_platform.h>
#endif
-UINTN efi_mapkey;
-
static const char howto_switches[] = "aCdrgDmphsv";
static int howto_masks[] = {
RB_ASKNAME, RB_CDROM, RB_KDB, RB_DFLTROOT, RB_GDB, RB_MULTIPLE,
@@ -234,12 +232,50 @@ bi_copymodules(vm_offset_t addr)
}
static int
+bi_add_efi_data_and_exit(struct preloaded_file *kfp,
+ struct efi_map_header *efihdr, size_t efisz, EFI_MEMORY_DESCRIPTOR *mm,
+ UINTN sz)
+{
+ UINTN efi_mapkey;
+ UINTN mmsz;
+ UINT32 mmver;
+ EFI_STATUS status;
+ UINTN retry;
+
+ /*
+ * It is possible that the first call to ExitBootServices may change
+ * the map key. Fetch a new map key and retry ExitBootServices in that
+ * case.
+ */
+ for (retry = 2; retry > 0; retry--) {
+ status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver);
+ if (EFI_ERROR(status)) {
+ printf("%s: GetMemoryMap() returned 0x%lx\n", __func__,
+ (long)status);
+ return (EINVAL);
+ }
+ status = BS->ExitBootServices(IH, efi_mapkey);
+ if (EFI_ERROR(status) == 0) {
+ efihdr->memory_size = sz;
+ efihdr->descriptor_size = mmsz;
+ efihdr->descriptor_version = mmver;
+ file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz,
+ efihdr);
+ return (0);
+ }
+ }
+ printf("ExitBootServices() returned 0x%lx\n", (long)status);
+ return (EINVAL);
+}
+
+static int
bi_load_efi_data(struct preloaded_file *kfp)
{
EFI_MEMORY_DESCRIPTOR *mm;
EFI_PHYSICAL_ADDRESS addr;
EFI_STATUS status;
size_t efisz;
+ UINTN efi_mapkey;
UINTN mmsz, pages, sz;
UINT32 mmver;
struct efi_map_header *efihdr;
@@ -294,20 +330,8 @@ bi_load_efi_data(struct preloaded_file *kfp)
efihdr = (struct efi_map_header *)addr;
mm = (void *)((uint8_t *)efihdr + efisz);
sz = (EFI_PAGE_SIZE * pages) - efisz;
- status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver);
- if (EFI_ERROR(status)) {
- printf("%s: GetMemoryMap() returned 0x%lx\n", __func__,
- (long)status);
- return (EINVAL);
- }
-
- efihdr->memory_size = sz;
- efihdr->descriptor_size = mmsz;
- efihdr->descriptor_version = mmver;
- file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz, efihdr);
-
- return (0);
+ return (bi_add_efi_data_and_exit(kfp, efihdr, efisz, mm, sz));
}
/*
diff --git a/sys/boot/efi/loader/loader_efi.h b/sys/boot/efi/loader/loader_efi.h
index f98f094..5819d78 100644
--- a/sys/boot/efi/loader/loader_efi.h
+++ b/sys/boot/efi/loader/loader_efi.h
@@ -44,8 +44,6 @@ ssize_t efi_copyout(const vm_offset_t src, void *dest, const size_t len);
ssize_t efi_readin(const int fd, vm_offset_t dest, const size_t len);
void * efi_translate(vm_offset_t ptr);
-extern UINTN efi_mapkey;
-
void efi_copy_finish(void);
#endif /* _LOADER_EFI_COPY_H_ */
diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h
index ce650dd..839745d 100644
--- a/sys/boot/i386/libi386/libi386.h
+++ b/sys/boot/i386/libi386/libi386.h
@@ -123,5 +123,4 @@ int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip,
int bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
vm_offset_t *kernend, int add_smap);
-char *pxe_default_rc(void);
void pxe_enable(void *pxeinfo);
diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c
index 1b255e9..efa04fc 100644
--- a/sys/boot/i386/libi386/pxe.c
+++ b/sys/boot/i386/libi386/pxe.c
@@ -288,8 +288,10 @@ pxe_open(struct open_file *f, ...)
bootp(pxe_sock, BOOTP_PXE);
if (rootip.s_addr == 0)
rootip.s_addr = bootplayer.sip;
+#ifdef LOADER_NFS_SUPPORT
if (!rootpath[0])
strcpy(rootpath, PXENFSROOTPATH);
+#endif
for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++)
if (rootpath[i] == ':')
@@ -317,13 +319,13 @@ pxe_open(struct open_file *f, ...)
setenv("boot.nfsroot.path", rootpath, 1);
#else
setenv("boot.netif.server", inet_ntoa(rootip), 1);
+ setenv("boot.tftproot.path", rootpath, 1);
#endif
setenv("dhcp.host-name", hostname, 1);
- sprintf(temp, "%08X", ntohl(myip.s_addr));
- setenv("pxeboot.ip", temp, 1);
+ setenv("pxeboot.ip", inet_ntoa(myip), 1);
if (bootplayer.Hardware == ETHER_TYPE) {
- sprintf(temp, "%6D", bootplayer.CAddr, "-");
+ sprintf(temp, "%6D", bootplayer.CAddr, ":");
setenv("pxeboot.hwaddr", temp, 1);
}
}
@@ -705,26 +707,3 @@ readudp(struct iodesc *h, void *pkt, size_t len, time_t timeout)
uh->uh_sport = udpread_p->s_port;
return udpread_p->buffer_size;
}
-
-char *
-pxe_default_rc(void)
-{
- char *rc;
- size_t count, rcsz;
-
- /* XXX It may not be a good idea to modify the PXE boot file. */
- rc = (char *)bootplayer.bootfile;
- rcsz = sizeof(bootplayer.bootfile);
-
- /* Ignore how we define rc and rcsz above -- it can change. */
- if (rcsz < 6)
- return (NULL);
- if (*rc == '\0') {
- strncpy(rc, "pxeboot", rcsz);
- rc[rcsz - 1] = '\0';
- }
- count = strlen(rc);
- strncat(rc, ".4th", rcsz - count - 1);
- printf("PXE: loading Forth from %s\n", rc);
- return (rc);
-}
diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c
index 82465a3..0087338 100644
--- a/sys/boot/i386/loader/main.c
+++ b/sys/boot/i386/loader/main.c
@@ -196,11 +196,6 @@ main(void)
bios_getsmap();
-#ifdef LOADER_TFTP_SUPPORT
- if (kargs->bootflags & KARGS_FLAGS_PXE)
- interact(pxe_default_rc());
- else
-#endif
interact(NULL);
/* if we ever get here, it is an error */
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index d21bd5a..ac886ca 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -6868,6 +6868,8 @@ ctl_log_sense(struct ctl_scsiio *ctsio)
header = (struct scsi_log_header *)ctsio->kern_data_ptr;
header->page = page_index->page_code;
+ if (page_index->page_code == SLS_LOGICAL_BLOCK_PROVISIONING)
+ header->page |= SL_DS;
if (page_index->subpage) {
header->page |= SL_SPF;
header->subpage = page_index->subpage;
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index df65ffd..7671132 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -610,10 +610,10 @@ ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun,
ctl_complete_beio(beio);
}
-SDT_PROBE_DEFINE1(cbb, kernel, read, file_start, "uint64_t");
-SDT_PROBE_DEFINE1(cbb, kernel, write, file_start, "uint64_t");
-SDT_PROBE_DEFINE1(cbb, kernel, read, file_done,"uint64_t");
-SDT_PROBE_DEFINE1(cbb, kernel, write, file_done, "uint64_t");
+SDT_PROBE_DEFINE1(cbb, , read, file_start, "uint64_t");
+SDT_PROBE_DEFINE1(cbb, , write, file_start, "uint64_t");
+SDT_PROBE_DEFINE1(cbb, , read, file_done,"uint64_t");
+SDT_PROBE_DEFINE1(cbb, , write, file_done, "uint64_t");
static void
ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
@@ -638,10 +638,10 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
bzero(&xuio, sizeof(xuio));
if (beio->bio_cmd == BIO_READ) {
- SDT_PROBE(cbb, kernel, read, file_start, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , read, file_start);
xuio.uio_rw = UIO_READ;
} else {
- SDT_PROBE(cbb, kernel, write, file_start, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , write, file_start);
xuio.uio_rw = UIO_WRITE;
}
xuio.uio_offset = beio->io_offset;
@@ -684,7 +684,7 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
error = VOP_READ(be_lun->vn, &xuio, flags, file_data->cred);
VOP_UNLOCK(be_lun->vn, 0);
- SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , read, file_done);
if (error == 0 && xuio.uio_resid > 0) {
/*
* If we red less then requested (EOF), then
@@ -733,7 +733,7 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
VOP_UNLOCK(be_lun->vn, 0);
vn_finished_write(mountpoint);
- SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , write, file_done);
}
mtx_lock(&be_lun->io_lock);
@@ -869,10 +869,10 @@ ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun,
bzero(&xuio, sizeof(xuio));
if (beio->bio_cmd == BIO_READ) {
- SDT_PROBE(cbb, kernel, read, file_start, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , read, file_start);
xuio.uio_rw = UIO_READ;
} else {
- SDT_PROBE(cbb, kernel, write, file_start, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , write, file_start);
xuio.uio_rw = UIO_WRITE;
}
xuio.uio_offset = beio->io_offset;
@@ -903,9 +903,9 @@ ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun,
error = ENXIO;
if (beio->bio_cmd == BIO_READ)
- SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , read, file_done);
else
- SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , write, file_done);
mtx_lock(&be_lun->io_lock);
devstat_end_transaction(beio->lun->disk_stats, beio->io_len,
@@ -1501,10 +1501,10 @@ ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
}
}
-SDT_PROBE_DEFINE1(cbb, kernel, read, start, "uint64_t");
-SDT_PROBE_DEFINE1(cbb, kernel, write, start, "uint64_t");
-SDT_PROBE_DEFINE1(cbb, kernel, read, alloc_done, "uint64_t");
-SDT_PROBE_DEFINE1(cbb, kernel, write, alloc_done, "uint64_t");
+SDT_PROBE_DEFINE1(cbb, , read, start, "uint64_t");
+SDT_PROBE_DEFINE1(cbb, , write, start, "uint64_t");
+SDT_PROBE_DEFINE1(cbb, , read, alloc_done, "uint64_t");
+SDT_PROBE_DEFINE1(cbb, , write, alloc_done, "uint64_t");
static void
ctl_be_block_next(struct ctl_be_block_io *beio)
@@ -1549,9 +1549,9 @@ ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
lbalen = ARGS(io);
if (lbalen->flags & CTL_LLF_WRITE) {
- SDT_PROBE(cbb, kernel, write, start, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , write, start);
} else {
- SDT_PROBE(cbb, kernel, read, start, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , read, start);
}
beio = ctl_alloc_beio(softc);
@@ -1638,10 +1638,10 @@ ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
* need to get the data from the user first.
*/
if (beio->bio_cmd == BIO_READ) {
- SDT_PROBE(cbb, kernel, read, alloc_done, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , read, alloc_done);
be_lun->dispatch(be_lun, beio);
} else {
- SDT_PROBE(cbb, kernel, write, alloc_done, 0, 0, 0, 0, 0);
+ SDT_PROBE0(cbb, , write, alloc_done);
#ifdef CTL_TIME_IO
getbinuptime(&io->io_hdr.dma_start_bt);
#endif
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 d1ed9da..78f8447 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
@@ -5762,96 +5762,54 @@ ioflags(int ioflags)
}
static int
-zfs_getpages(struct vnode *vp, vm_page_t *m, int count, int reqpage)
+zfs_getpages(struct vnode *vp, vm_page_t *m, int count, int *rbehind,
+ int *rahead)
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
objset_t *os = zp->z_zfsvfs->z_os;
- vm_page_t mfirst, mlast, mreq;
+ vm_page_t mlast;
vm_object_t object;
caddr_t va;
struct sf_buf *sf;
off_t startoff, endoff;
int i, error;
vm_pindex_t reqstart, reqend;
- int pcount, lsize, reqsize, size;
+ int lsize, reqsize, size;
- ZFS_ENTER(zfsvfs);
- ZFS_VERIFY_ZP(zp);
-
- pcount = OFF_TO_IDX(round_page(count));
- mreq = m[reqpage];
- object = mreq->object;
+ object = m[0]->object;
error = 0;
- if (pcount > 1 && zp->z_blksz > PAGESIZE) {
- startoff = rounddown(IDX_TO_OFF(mreq->pindex), zp->z_blksz);
- reqstart = OFF_TO_IDX(round_page(startoff));
- if (reqstart < m[0]->pindex)
- reqstart = 0;
- else
- reqstart = reqstart - m[0]->pindex;
- endoff = roundup(IDX_TO_OFF(mreq->pindex) + PAGE_SIZE,
- zp->z_blksz);
- reqend = OFF_TO_IDX(trunc_page(endoff)) - 1;
- if (reqend > m[pcount - 1]->pindex)
- reqend = m[pcount - 1]->pindex;
- reqsize = reqend - m[reqstart]->pindex + 1;
- KASSERT(reqstart <= reqpage && reqpage < reqstart + reqsize,
- ("reqpage beyond [reqstart, reqstart + reqsize[ bounds"));
- } else {
- reqstart = reqpage;
- reqsize = 1;
- }
- mfirst = m[reqstart];
- mlast = m[reqstart + reqsize - 1];
+ ZFS_ENTER(zfsvfs);
+ ZFS_VERIFY_ZP(zp);
zfs_vmobject_wlock(object);
-
- for (i = 0; i < reqstart; i++) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
- for (i = reqstart + reqsize; i < pcount; i++) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
-
- if (mreq->valid && reqsize == 1) {
- if (mreq->valid != VM_PAGE_BITS_ALL)
- vm_page_zero_invalid(mreq, TRUE);
+ if (m[count - 1]->valid != 0 && --count == 0) {
zfs_vmobject_wunlock(object);
- ZFS_EXIT(zfsvfs);
- return (zfs_vm_pagerret_ok);
+ goto out;
}
- PCPU_INC(cnt.v_vnodein);
- PCPU_ADD(cnt.v_vnodepgsin, reqsize);
+ mlast = m[count - 1];
- if (IDX_TO_OFF(mreq->pindex) >= object->un_pager.vnp.vnp_size) {
- for (i = reqstart; i < reqstart + reqsize; i++) {
- if (i != reqpage) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
- }
+ if (IDX_TO_OFF(mlast->pindex) >=
+ object->un_pager.vnp.vnp_size) {
zfs_vmobject_wunlock(object);
ZFS_EXIT(zfsvfs);
return (zfs_vm_pagerret_bad);
}
+ PCPU_INC(cnt.v_vnodein);
+ PCPU_ADD(cnt.v_vnodepgsin, reqsize);
+
lsize = PAGE_SIZE;
if (IDX_TO_OFF(mlast->pindex) + lsize > object->un_pager.vnp.vnp_size)
- lsize = object->un_pager.vnp.vnp_size - IDX_TO_OFF(mlast->pindex);
-
+ lsize = object->un_pager.vnp.vnp_size -
+ IDX_TO_OFF(mlast->pindex);
zfs_vmobject_wunlock(object);
- for (i = reqstart; i < reqstart + reqsize; i++) {
+ for (i = 0; i < count; i++) {
size = PAGE_SIZE;
- if (i == (reqstart + reqsize - 1))
+ if (i == count - 1)
size = lsize;
va = zfs_map_page(m[i], &sf);
error = dmu_read(os, zp->z_id, IDX_TO_OFF(m[i]->pindex),
@@ -5860,24 +5818,25 @@ zfs_getpages(struct vnode *vp, vm_page_t *m, int count, int reqpage)
bzero(va + size, PAGE_SIZE - size);
zfs_unmap_page(sf);
if (error != 0)
- break;
+ goto out;
}
zfs_vmobject_wlock(object);
-
- for (i = reqstart; i < reqstart + reqsize; i++) {
- if (!error)
- m[i]->valid = VM_PAGE_BITS_ALL;
- KASSERT(m[i]->dirty == 0, ("zfs_getpages: page %p is dirty", m[i]));
- if (i != reqpage)
- vm_page_readahead_finish(m[i]);
- }
-
+ for (i = 0; i < count; i++)
+ m[i]->valid = VM_PAGE_BITS_ALL;
zfs_vmobject_wunlock(object);
+out:
ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
ZFS_EXIT(zfsvfs);
- return (error ? zfs_vm_pagerret_error : zfs_vm_pagerret_ok);
+ if (error == 0) {
+ if (rbehind)
+ *rbehind = 0;
+ if (rahead)
+ *rahead = 0;
+ return (zfs_vm_pagerret_ok);
+ } else
+ return (zfs_vm_pagerret_error);
}
static int
@@ -5886,11 +5845,13 @@ zfs_freebsd_getpages(ap)
struct vnode *a_vp;
vm_page_t *a_m;
int a_count;
- int a_reqpage;
+ int *a_rbehind;
+ int *a_rahead;
} */ *ap;
{
- return (zfs_getpages(ap->a_vp, ap->a_m, ap->a_count, ap->a_reqpage));
+ return (zfs_getpages(ap->a_vp, ap->a_m, ap->a_count, ap->a_rbehind,
+ ap->a_rahead));
}
static int
diff --git a/sys/cddl/dev/dtrace/dtrace_cddl.h b/sys/cddl/dev/dtrace/dtrace_cddl.h
index eed32a8..b8ea17a 100644
--- a/sys/cddl/dev/dtrace/dtrace_cddl.h
+++ b/sys/cddl/dev/dtrace/dtrace_cddl.h
@@ -83,8 +83,8 @@ typedef struct kdtrace_thread {
uintptr_t td_dtrace_regv;
#endif
u_int64_t td_hrtime; /* Last time on cpu. */
- int td_errno; /* Syscall return value. */
void *td_dtrace_sscr; /* Saved scratch space location. */
+ void *td_systrace_args; /* syscall probe arguments. */
} kdtrace_thread_t;
/*
@@ -110,6 +110,7 @@ typedef struct kdtrace_thread {
#define t_dtrace_astpc td_dtrace->td_dtrace_astpc
#define t_dtrace_regv td_dtrace->td_dtrace_regv
#define t_dtrace_sscr td_dtrace->td_dtrace_sscr
+#define t_dtrace_systrace_args td_dtrace->td_systrace_args
#define p_dtrace_helpers p_dtrace->p_dtrace_helpers
#define p_dtrace_count p_dtrace->p_dtrace_count
#define p_dtrace_probes p_dtrace->p_dtrace_probes
diff --git a/sys/cddl/dev/systrace/systrace.c b/sys/cddl/dev/systrace/systrace.c
index 1796091..88e680a 100644
--- a/sys/cddl/dev/systrace/systrace.c
+++ b/sys/cddl/dev/systrace/systrace.c
@@ -19,9 +19,6 @@
* CDDL HEADER END
*
* Portions Copyright 2006-2008 John Birrell jb@freebsd.org
- *
- * $FreeBSD$
- *
*/
/*
@@ -30,10 +27,13 @@
*/
#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/cpuvar.h>
+#include <sys/dtrace.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/kdb.h>
@@ -50,13 +50,14 @@
#include <sys/proc.h>
#include <sys/selinfo.h>
#include <sys/smp.h>
-#include <sys/sysproto.h>
#include <sys/sysent.h>
+#include <sys/sysproto.h>
#include <sys/uio.h>
#include <sys/unistd.h>
-#include <machine/stdarg.h>
-#include <sys/dtrace.h>
+#include <cddl/dev/dtrace/dtrace_cddl.h>
+
+#include <machine/stdarg.h>
#ifdef LINUX_SYSTRACE
#if defined(__amd64__)
@@ -134,26 +135,18 @@ extern const char *freebsd32_syscallnames[];
#error 1 << SYSTRACE_SHIFT must exceed number of system calls
#endif
-static d_open_t systrace_open;
-static int systrace_unload(void);
-static void systrace_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
+static void systrace_load(void *);
+static void systrace_unload(void *);
+
+static void systrace_getargdesc(void *, dtrace_id_t, void *,
+ dtrace_argdesc_t *);
+static uint64_t systrace_getargval(void *, dtrace_id_t, void *, int, int);
static void systrace_provide(void *, dtrace_probedesc_t *);
static void systrace_destroy(void *, dtrace_id_t, void *);
static void systrace_enable(void *, dtrace_id_t, void *);
static void systrace_disable(void *, dtrace_id_t, void *);
-static void systrace_load(void *);
-
-static struct cdevsw systrace_cdevsw = {
- .d_version = D_VERSION,
- .d_open = systrace_open,
-#ifndef NATIVE_ABI
- .d_name = "systrace_" MODNAME,
-#else
- .d_name = "systrace",
-#endif
-};
-static union {
+static union {
const char **p_constnames;
char **pp_syscallnames;
} uglyhack = { SYSCALLNAMES };
@@ -174,17 +167,13 @@ static dtrace_pops_t systrace_pops = {
NULL,
NULL,
systrace_getargdesc,
- NULL,
+ systrace_getargval,
NULL,
systrace_destroy
};
-static struct cdev *systrace_cdev;
static dtrace_provider_id_t systrace_id;
-typedef void (*systrace_dtrace_probe_t)(dtrace_id_t, uintptr_t, uintptr_t,
- uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
-
#ifdef NATIVE_ABI
/*
* Probe callback function.
@@ -194,64 +183,80 @@ typedef void (*systrace_dtrace_probe_t)(dtrace_id_t, uintptr_t, uintptr_t,
* compat syscall from something like Linux.
*/
static void
-systrace_probe(u_int32_t id, int sysnum, struct sysent *sysent, void *params,
- int ret)
+systrace_probe(struct syscall_args *sa, enum systrace_probe_t type, int retval)
{
- systrace_dtrace_probe_t probe;
- int n_args = 0;
- u_int64_t uargs[8];
+ uint64_t uargs[nitems(sa->args)];
+ dtrace_id_t id;
+ int n_args, sysnum;
+ sysnum = sa->code;
memset(uargs, 0, sizeof(uargs));
- /*
- * Check if this syscall has an argument conversion function
- * registered.
- */
- if (params && sysent->sy_systrace_args_func != NULL) {
- /*
- * Convert the syscall parameters using the registered
- * function.
- */
- (*sysent->sy_systrace_args_func)(sysnum, params, uargs, &n_args);
- } else if (params) {
+
+ if (type == SYSTRACE_ENTRY) {
+ id = sa->callp->sy_entry;
+
+ if (sa->callp->sy_systrace_args_func != NULL)
+ /*
+ * Convert the syscall parameters using the registered
+ * function.
+ */
+ (*sa->callp->sy_systrace_args_func)(sysnum, sa->args,
+ uargs, &n_args);
+ else
+ /*
+ * Use the built-in system call argument conversion
+ * function to translate the syscall structure fields
+ * into the array of 64-bit values that DTrace expects.
+ */
+ systrace_args(sysnum, sa->args, uargs, &n_args);
/*
- * Use the built-in system call argument conversion
- * function to translate the syscall structure fields
- * into the array of 64-bit values that DTrace
- * expects.
+ * Save probe arguments now so that we can retrieve them if
+ * the getargval method is called from further down the stack.
*/
- systrace_args(sysnum, params, uargs, &n_args);
+ curthread->t_dtrace_systrace_args = uargs;
} else {
- /*
- * Since params is NULL, this is a 'return' probe.
- * Set arg0 and arg1 as the return value of this syscall.
- */
- uargs[0] = uargs[1] = ret;
+ id = sa->callp->sy_return;
+
+ curthread->t_dtrace_systrace_args = NULL;
+ /* Set arg0 and arg1 as the return value of this syscall. */
+ uargs[0] = uargs[1] = retval;
}
/* Process the probe using the converted argments. */
- probe = (systrace_dtrace_probe_t)dtrace_probe;
- probe(id, uargs[0], uargs[1], uargs[2], uargs[3], uargs[4], uargs[5],
- uargs[6], uargs[7]);
+ dtrace_probe(id, uargs[0], uargs[1], uargs[2], uargs[3], uargs[4]);
}
-
#endif
static void
-systrace_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
+systrace_getargdesc(void *arg, dtrace_id_t id, void *parg,
+ dtrace_argdesc_t *desc)
{
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
if (SYSTRACE_ISENTRY((uintptr_t)parg))
- systrace_entry_setargdesc(sysnum, desc->dtargd_ndx,
+ systrace_entry_setargdesc(sysnum, desc->dtargd_ndx,
desc->dtargd_native, sizeof(desc->dtargd_native));
else
- systrace_return_setargdesc(sysnum, desc->dtargd_ndx,
+ systrace_return_setargdesc(sysnum, desc->dtargd_ndx,
desc->dtargd_native, sizeof(desc->dtargd_native));
if (desc->dtargd_native[0] == '\0')
desc->dtargd_ndx = DTRACE_ARGNONE;
+}
- return;
+static uint64_t
+systrace_getargval(void *arg __unused, dtrace_id_t id __unused,
+ void *parg __unused, int argno, int aframes __unused)
+{
+ uint64_t *uargs;
+
+ uargs = curthread->t_dtrace_systrace_args;
+ if (uargs == NULL)
+ /* This is a return probe. */
+ return (0);
+ if (argno >= nitems(((struct syscall_args *)NULL)->args))
+ return (0);
+ return (uargs[argno]);
}
static void
@@ -267,11 +272,13 @@ systrace_provide(void *arg, dtrace_probedesc_t *desc)
uglyhack.pp_syscallnames[i], "entry") != 0)
continue;
- (void) dtrace_probe_create(systrace_id, MODNAME, uglyhack.pp_syscallnames[i],
- "entry", SYSTRACE_ARTIFICIAL_FRAMES,
+ (void)dtrace_probe_create(systrace_id, MODNAME,
+ uglyhack.pp_syscallnames[i], "entry",
+ SYSTRACE_ARTIFICIAL_FRAMES,
(void *)((uintptr_t)SYSTRACE_ENTRY(i)));
- (void) dtrace_probe_create(systrace_id, MODNAME, uglyhack.pp_syscallnames[i],
- "return", SYSTRACE_ARTIFICIAL_FRAMES,
+ (void)dtrace_probe_create(systrace_id, MODNAME,
+ uglyhack.pp_syscallnames[i], "return",
+ SYSTRACE_ARTIFICIAL_FRAMES,
(void *)((uintptr_t)SYSTRACE_RETURN(i)));
}
}
@@ -318,14 +325,11 @@ systrace_disable(void *arg, dtrace_id_t id, void *parg)
}
static void
-systrace_load(void *dummy)
+systrace_load(void *dummy __unused)
{
- /* Create the /dev/dtrace/systrace entry. */
- systrace_cdev = make_dev(&systrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
- DEVNAME);
- if (dtrace_register(PROVNAME, &systrace_attr, DTRACE_PRIV_USER,
- NULL, &systrace_pops, NULL, &systrace_id) != 0)
+ if (dtrace_register(PROVNAME, &systrace_attr, DTRACE_PRIV_USER, NULL,
+ &systrace_pops, NULL, &systrace_id) != 0)
return;
#ifdef NATIVE_ABI
@@ -333,29 +337,24 @@ systrace_load(void *dummy)
#endif
}
-
-static int
-systrace_unload()
+static void
+systrace_unload(void *dummy __unused)
{
- int error = 0;
-
- if ((error = dtrace_unregister(systrace_id)) != 0)
- return (error);
#ifdef NATIVE_ABI
systrace_probe_func = NULL;
#endif
- destroy_dev(systrace_cdev);
-
- return (error);
+ if (dtrace_unregister(systrace_id) != 0)
+ return;
}
static int
systrace_modevent(module_t mod __unused, int type, void *data __unused)
{
- int error = 0;
+ int error;
+ error = 0;
switch (type) {
case MOD_LOAD:
break;
@@ -374,14 +373,10 @@ systrace_modevent(module_t mod __unused, int type, void *data __unused)
return (error);
}
-static int
-systrace_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *td __unused)
-{
- return (0);
-}
-
-SYSINIT(systrace_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_load, NULL);
-SYSUNINIT(systrace_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_unload, NULL);
+SYSINIT(systrace_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
+ systrace_load, NULL);
+SYSUNINIT(systrace_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
+ systrace_unload, NULL);
#ifdef LINUX_SYSTRACE
DEV_MODULE(systrace_linux, systrace_modevent, NULL);
diff --git a/sys/compat/linux/linux_dtrace.h b/sys/compat/linux/linux_dtrace.h
index c446b3e..6e91327 100644
--- a/sys/compat/linux/linux_dtrace.h
+++ b/sys/compat/linux/linux_dtrace.h
@@ -72,8 +72,8 @@
#define LIN_SDT_PROBE_DEFINE5(a, b, c, d, e, f, g, h) _LIN_SDT_PROBE_DEFINE5(\
LINUX_DTRACE, a, b, c, d, e, f, g, h)
-#define LIN_SDT_PROBE0(a, b, c) SDT_PROBE1(LINUX_DTRACE, a, b, \
- c, 0)
+#define LIN_SDT_PROBE0(a, b, c) SDT_PROBE0(LINUX_DTRACE, a, b, \
+ c)
#define LIN_SDT_PROBE1(a, b, c, d) SDT_PROBE1(LINUX_DTRACE, a, b, \
c, d)
#define LIN_SDT_PROBE2(a, b, c, d, e) SDT_PROBE2(LINUX_DTRACE, a, b, \
diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk
index 203d6d7..50000c5 100644
--- a/sys/conf/kmod.mk
+++ b/sys/conf/kmod.mk
@@ -225,7 +225,7 @@ ${FULLPROG}: ${OBJS}
.else
grep -v '^#' < ${EXPORT_SYMS} > export_syms
.endif
- awk -f ${SYSDIR}/conf/kmod_syms.awk ${.TARGET} \
+ ${AWK} -f ${SYSDIR}/conf/kmod_syms.awk ${.TARGET} \
export_syms | xargs -J% ${OBJCOPY} % ${.TARGET}
.endif
.endif
diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c
index 07b516c..95edcf9 100644
--- a/sys/dev/drm2/i915/i915_gem.c
+++ b/sys/dev/drm2/i915/i915_gem.c
@@ -4338,7 +4338,7 @@ i915_gem_wire_page(vm_object_t object, vm_pindex_t pindex, bool *fresh)
page = vm_page_grab(object, pindex, VM_ALLOC_NORMAL);
if (page->valid != VM_PAGE_BITS_ALL) {
if (vm_pager_has_page(object, pindex, NULL, NULL)) {
- rv = vm_pager_get_pages(object, &page, 1, 0);
+ rv = vm_pager_get_pages(object, &page, 1, NULL, NULL);
if (rv != VM_PAGER_OK) {
vm_page_lock(page);
vm_page_free(page);
diff --git a/sys/dev/drm2/ttm/ttm_tt.c b/sys/dev/drm2/ttm/ttm_tt.c
index 2dd6fb4..1e2db3c 100644
--- a/sys/dev/drm2/ttm/ttm_tt.c
+++ b/sys/dev/drm2/ttm/ttm_tt.c
@@ -291,7 +291,8 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
from_page = vm_page_grab(obj, i, VM_ALLOC_NORMAL);
if (from_page->valid != VM_PAGE_BITS_ALL) {
if (vm_pager_has_page(obj, i, NULL, NULL)) {
- rv = vm_pager_get_pages(obj, &from_page, 1, 0);
+ rv = vm_pager_get_pages(obj, &from_page, 1,
+ NULL, NULL);
if (rv != VM_PAGER_OK) {
vm_page_lock(from_page);
vm_page_free(from_page);
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index 6405ad5..2fa9f46 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -1019,7 +1019,8 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
if (m->valid == VM_PAGE_BITS_ALL)
rv = VM_PAGER_OK;
else
- rv = vm_pager_get_pages(sc->object, &m, 1, 0);
+ rv = vm_pager_get_pages(sc->object, &m, 1,
+ NULL, NULL);
if (rv == VM_PAGER_ERROR) {
vm_page_xunbusy(m);
break;
@@ -1046,7 +1047,8 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
}
} else if (bp->bio_cmd == BIO_WRITE) {
if (len != PAGE_SIZE && m->valid != VM_PAGE_BITS_ALL)
- rv = vm_pager_get_pages(sc->object, &m, 1, 0);
+ rv = vm_pager_get_pages(sc->object, &m, 1,
+ NULL, NULL);
else
rv = VM_PAGER_OK;
if (rv == VM_PAGER_ERROR) {
@@ -1065,7 +1067,8 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
m->valid = VM_PAGE_BITS_ALL;
} else if (bp->bio_cmd == BIO_DELETE) {
if (len != PAGE_SIZE && m->valid != VM_PAGE_BITS_ALL)
- rv = vm_pager_get_pages(sc->object, &m, 1, 0);
+ rv = vm_pager_get_pages(sc->object, &m, 1,
+ NULL, NULL);
else
rv = VM_PAGER_OK;
if (rv == VM_PAGER_ERROR) {
diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c
index 936d7f0..136cd55 100644
--- a/sys/dev/usb/serial/uftdi.c
+++ b/sys/dev/usb/serial/uftdi.c
@@ -563,7 +563,7 @@ static const STRUCT_USB_HOST_ID uftdi_devs[] = {
UFTDI_DEV(KOBIL, CONV_B1, 0),
UFTDI_DEV(KOBIL, CONV_KAAN, 0),
UFTDI_DEV(LARSENBRUSGAARD, ALTITRACK, 0),
- UFTDI_DEV(MARVELL, SHEEVAPLUG, 0),
+ UFTDI_DEV(MARVELL, SHEEVAPLUG, UFTDI_JTAG_IFACE(0)),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0100, 0),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0101, 0),
UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0102, 0),
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
index 12b9778..74dbcb2 100644
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -1752,35 +1752,24 @@ fuse_vnop_getpages(struct vop_getpages_args *ap)
td = curthread; /* XXX */
cred = curthread->td_ucred; /* XXX */
pages = ap->a_m;
- count = ap->a_count;
+ npages = ap->a_count;
if (!fsess_opt_mmap(vnode_mount(vp))) {
FS_DEBUG("called on non-cacheable vnode??\n");
return (VM_PAGER_ERROR);
}
- npages = btoc(count);
/*
- * If the requested page is partially valid, just return it and
- * allow the pager to zero-out the blanks. Partially valid pages
- * can only occur at the file EOF.
+ * If the last page is partially valid, just return it and allow
+ * the pager to zero-out the blanks. Partially valid pages can
+ * only occur at the file EOF.
+ *
+ * XXXGL: is that true for FUSE, which is a local filesystem,
+ * but still somewhat disconnected from the kernel?
*/
-
VM_OBJECT_WLOCK(vp->v_object);
- fuse_vm_page_lock_queues();
- if (pages[ap->a_reqpage]->valid != 0) {
- for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage) {
- fuse_vm_page_lock(pages[i]);
- vm_page_free(pages[i]);
- fuse_vm_page_unlock(pages[i]);
- }
- }
- fuse_vm_page_unlock_queues();
- VM_OBJECT_WUNLOCK(vp->v_object);
- return 0;
- }
- fuse_vm_page_unlock_queues();
+ if (pages[npages - 1]->valid != 0 && --npages == 0)
+ goto out;
VM_OBJECT_WUNLOCK(vp->v_object);
/*
@@ -1794,6 +1783,7 @@ fuse_vnop_getpages(struct vop_getpages_args *ap)
PCPU_INC(cnt.v_vnodein);
PCPU_ADD(cnt.v_vnodepgsin, npages);
+ count = npages << PAGE_SHIFT;
iov.iov_base = (caddr_t)kva;
iov.iov_len = count;
uio.uio_iov = &iov;
@@ -1811,17 +1801,6 @@ fuse_vnop_getpages(struct vop_getpages_args *ap)
if (error && (uio.uio_resid == count)) {
FS_DEBUG("error %d\n", error);
- VM_OBJECT_WLOCK(vp->v_object);
- fuse_vm_page_lock_queues();
- for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage) {
- fuse_vm_page_lock(pages[i]);
- vm_page_free(pages[i]);
- fuse_vm_page_unlock(pages[i]);
- }
- }
- fuse_vm_page_unlock_queues();
- VM_OBJECT_WUNLOCK(vp->v_object);
return VM_PAGER_ERROR;
}
/*
@@ -1862,12 +1841,15 @@ fuse_vnop_getpages(struct vop_getpages_args *ap)
*/
;
}
- if (i != ap->a_reqpage)
- vm_page_readahead_finish(m);
}
fuse_vm_page_unlock_queues();
+out:
VM_OBJECT_WUNLOCK(vp->v_object);
- return 0;
+ if (ap->a_rbehind)
+ *ap->a_rbehind = 0;
+ if (ap->a_rahead)
+ *ap->a_rahead = 0;
+ return (VM_PAGER_OK);
}
/*
diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index 53ba7ef..3498dc0 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -100,7 +100,7 @@ ncl_getpages(struct vop_getpages_args *ap)
cred = curthread->td_ucred; /* XXX */
nmp = VFSTONFS(vp->v_mount);
pages = ap->a_m;
- count = ap->a_count;
+ npages = ap->a_count;
if ((object = vp->v_object) == NULL) {
ncl_printf("nfs_getpages: called with non-merged cache vnode??\n");
@@ -126,18 +126,17 @@ ncl_getpages(struct vop_getpages_args *ap)
} else
mtx_unlock(&nmp->nm_mtx);
- npages = btoc(count);
-
/*
* If the requested page is partially valid, just return it and
* allow the pager to zero-out the blanks. Partially valid pages
* can only occur at the file EOF.
+ *
+ * XXXGL: is that true for NFS, where short read can occur???
*/
- if (pages[ap->a_reqpage]->valid != 0) {
- vm_pager_free_nonreq(object, pages, ap->a_reqpage, npages,
- FALSE);
- return (VM_PAGER_OK);
- }
+ VM_OBJECT_WLOCK(object);
+ if (pages[npages - 1]->valid != 0 && --npages == 0)
+ goto out;
+ VM_OBJECT_WUNLOCK(object);
/*
* We use only the kva address for the buffer, but this is extremely
@@ -150,6 +149,7 @@ ncl_getpages(struct vop_getpages_args *ap)
PCPU_INC(cnt.v_vnodein);
PCPU_ADD(cnt.v_vnodepgsin, npages);
+ count = npages << PAGE_SHIFT;
iov.iov_base = (caddr_t) kva;
iov.iov_len = count;
uio.uio_iov = &iov;
@@ -167,8 +167,6 @@ ncl_getpages(struct vop_getpages_args *ap)
if (error && (uio.uio_resid == count)) {
ncl_printf("nfs_getpages: error %d\n", error);
- vm_pager_free_nonreq(object, pages, ap->a_reqpage, npages,
- FALSE);
return (VM_PAGER_ERROR);
}
@@ -212,11 +210,14 @@ ncl_getpages(struct vop_getpages_args *ap)
*/
;
}
- if (i != ap->a_reqpage)
- vm_page_readahead_finish(m);
}
+out:
VM_OBJECT_WUNLOCK(object);
- return (0);
+ if (ap->a_rbehind)
+ *ap->a_rbehind = 0;
+ if (ap->a_rahead)
+ *ap->a_rahead = 0;
+ return (VM_PAGER_OK);
}
/*
diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c
index a567ce6..4de3827 100644
--- a/sys/fs/smbfs/smbfs_io.c
+++ b/sys/fs/smbfs/smbfs_io.c
@@ -424,7 +424,7 @@ smbfs_getpages(ap)
#ifdef SMBFS_RWGENERIC
return vop_stdgetpages(ap);
#else
- int i, error, nextoff, size, toff, npages, count, reqpage;
+ int i, error, nextoff, size, toff, npages, count;
struct uio uio;
struct iovec iov;
vm_offset_t kva;
@@ -436,7 +436,7 @@ smbfs_getpages(ap)
struct smbnode *np;
struct smb_cred *scred;
vm_object_t object;
- vm_page_t *pages, m;
+ vm_page_t *pages;
vp = ap->a_vp;
if ((object = vp->v_object) == NULL) {
@@ -449,29 +449,18 @@ smbfs_getpages(ap)
np = VTOSMB(vp);
smp = VFSTOSMBFS(vp->v_mount);
pages = ap->a_m;
- count = ap->a_count;
- npages = btoc(count);
- reqpage = ap->a_reqpage;
+ npages = ap->a_count;
/*
* If the requested page is partially valid, just return it and
* allow the pager to zero-out the blanks. Partially valid pages
* can only occur at the file EOF.
+ *
+ * XXXGL: is that true for SMB filesystem?
*/
- m = pages[reqpage];
-
VM_OBJECT_WLOCK(object);
- if (m->valid != 0) {
- for (i = 0; i < npages; ++i) {
- if (i != reqpage) {
- vm_page_lock(pages[i]);
- vm_page_free(pages[i]);
- vm_page_unlock(pages[i]);
- }
- }
- VM_OBJECT_WUNLOCK(object);
- return 0;
- }
+ if (pages[npages - 1]->valid != 0 && --npages == 0)
+ goto out;
VM_OBJECT_WUNLOCK(object);
scred = smbfs_malloc_scred();
@@ -484,6 +473,7 @@ smbfs_getpages(ap)
PCPU_INC(cnt.v_vnodein);
PCPU_ADD(cnt.v_vnodepgsin, npages);
+ count = npages << PAGE_SHIFT;
iov.iov_base = (caddr_t) kva;
iov.iov_len = count;
uio.uio_iov = &iov;
@@ -500,22 +490,14 @@ smbfs_getpages(ap)
relpbuf(bp, &smbfs_pbuf_freecnt);
- VM_OBJECT_WLOCK(object);
if (error && (uio.uio_resid == count)) {
printf("smbfs_getpages: error %d\n",error);
- for (i = 0; i < npages; i++) {
- if (reqpage != i) {
- vm_page_lock(pages[i]);
- vm_page_free(pages[i]);
- vm_page_unlock(pages[i]);
- }
- }
- VM_OBJECT_WUNLOCK(object);
return VM_PAGER_ERROR;
}
size = count - uio.uio_resid;
+ VM_OBJECT_WLOCK(object);
for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
vm_page_t m;
nextoff = toff + PAGE_SIZE;
@@ -544,12 +526,14 @@ smbfs_getpages(ap)
*/
;
}
-
- if (i != reqpage)
- vm_page_readahead_finish(m);
}
+out:
VM_OBJECT_WUNLOCK(object);
- return 0;
+ if (ap->a_rbehind)
+ *ap->a_rbehind = 0;
+ if (ap->a_rahead)
+ *ap->a_rahead = 0;
+ return (VM_PAGER_OK);
#endif /* SMBFS_RWGENERIC */
}
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index fa489b2..fcc8782 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -1370,7 +1370,8 @@ retry:
VM_OBJECT_WLOCK(uobj);
goto retry;
} else if (m->valid != VM_PAGE_BITS_ALL)
- rv = vm_pager_get_pages(uobj, &m, 1, 0);
+ rv = vm_pager_get_pages(uobj, &m, 1,
+ NULL, NULL);
else
/* A cached page was reactivated. */
rv = VM_PAGER_OK;
diff --git a/sys/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c
index 0953d18..6644532 100644
--- a/sys/geom/multipath/g_multipath.c
+++ b/sys/geom/multipath/g_multipath.c
@@ -107,8 +107,9 @@ struct g_class g_multipath_class = {
#define MP_NEW 0x00000004
#define MP_POSTED 0x00000008
#define MP_BAD (MP_FAIL | MP_LOST | MP_NEW)
-#define MP_IDLE 0x00000010
-#define MP_IDLE_MASK 0xfffffff0
+#define MP_WITHER 0x00000010
+#define MP_IDLE 0x00000020
+#define MP_IDLE_MASK 0xffffffe0
static int
g_multipath_good(struct g_geom *gp)
@@ -204,6 +205,7 @@ g_mpd(void *arg, int flags __unused)
g_access(cp, -cp->acr, -cp->acw, -cp->ace);
if (w > 0 && cp->provider != NULL &&
(cp->provider->geom->flags & G_GEOM_WITHER) == 0) {
+ cp->index |= MP_WITHER;
g_post_event(g_mpd, cp, M_WAITOK, NULL);
return;
}
@@ -467,23 +469,37 @@ g_multipath_access(struct g_provider *pp, int dr, int dw, int de)
gp = pp->geom;
+ /* Error used if we have no valid consumers. */
+ error = ENXIO;
+
LIST_FOREACH(cp, &gp->consumer, consumer) {
+ if (cp->index & MP_WITHER)
+ continue;
+
error = g_access(cp, dr, dw, de);
if (error) {
badcp = cp;
goto fail;
}
}
+
+ if (error != 0)
+ return (error);
+
sc = gp->softc;
sc->sc_opened += dr + dw + de;
if (sc->sc_stopping && sc->sc_opened == 0)
g_multipath_destroy(gp);
+
return (0);
fail:
LIST_FOREACH(cp, &gp->consumer, consumer) {
if (cp == badcp)
break;
+ if (cp->index & MP_WITHER)
+ continue;
+
(void) g_access(cp, -dr, -dw, -de);
}
return (error);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index a0eb069..741bc3e 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -94,9 +94,9 @@ dtrace_execexit_func_t dtrace_fasttrap_exec;
#endif
SDT_PROVIDER_DECLARE(proc);
-SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *");
-SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int");
-SDT_PROBE_DEFINE1(proc, kernel, , exec__success, "char *");
+SDT_PROBE_DEFINE1(proc, , , exec, "char *");
+SDT_PROBE_DEFINE1(proc, , , exec__failure, "int");
+SDT_PROBE_DEFINE1(proc, , , exec__success, "char *");
MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments");
@@ -423,7 +423,7 @@ do_execve(td, args, mac_p)
| AUDITVNODE1, UIO_SYSSPACE, args->fname, td);
}
- SDT_PROBE1(proc, kernel, , exec, args->fname);
+ SDT_PROBE1(proc, , , exec, args->fname);
interpret:
if (args->fname != NULL) {
@@ -851,7 +851,7 @@ interpret:
vfs_mark_atime(imgp->vp, td->td_ucred);
- SDT_PROBE1(proc, kernel, , exec__success, args->fname);
+ SDT_PROBE1(proc, , , exec__success, args->fname);
VOP_UNLOCK(imgp->vp, 0);
done1:
@@ -923,7 +923,7 @@ exec_fail:
p->p_flag &= ~P_INEXEC;
PROC_UNLOCK(p);
- SDT_PROBE1(proc, kernel, , exec__failure, error);
+ SDT_PROBE1(proc, , , exec__failure, error);
done2:
#ifdef MAC
@@ -950,8 +950,7 @@ int
exec_map_first_page(imgp)
struct image_params *imgp;
{
- int rv, i;
- int initial_pagein;
+ int rv, i, after, initial_pagein;
vm_page_t ma[VM_INITIAL_PAGEIN];
vm_object_t object;
@@ -967,9 +966,18 @@ exec_map_first_page(imgp)
#endif
ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL);
if (ma[0]->valid != VM_PAGE_BITS_ALL) {
- initial_pagein = VM_INITIAL_PAGEIN;
- if (initial_pagein > object->size)
- initial_pagein = object->size;
+ if (!vm_pager_has_page(object, 0, NULL, &after)) {
+ vm_page_lock(ma[0]);
+ vm_page_free(ma[0]);
+ vm_page_unlock(ma[0]);
+ vm_page_xunbusy(ma[0]);
+ VM_OBJECT_WUNLOCK(object);
+ return (EIO);
+ }
+ initial_pagein = min(after, VM_INITIAL_PAGEIN);
+ KASSERT(initial_pagein <= object->size,
+ ("%s: initial_pagein %d object->size %ju",
+ __func__, initial_pagein, (uintmax_t )object->size));
for (i = 1; i < initial_pagein; i++) {
if ((ma[i] = vm_page_next(ma[i - 1])) != NULL) {
if (ma[i]->valid)
@@ -984,14 +992,19 @@ exec_map_first_page(imgp)
}
}
initial_pagein = i;
- rv = vm_pager_get_pages(object, ma, initial_pagein, 0);
+ rv = vm_pager_get_pages(object, ma, initial_pagein, NULL, NULL);
if (rv != VM_PAGER_OK) {
- vm_page_lock(ma[0]);
- vm_page_free(ma[0]);
- vm_page_unlock(ma[0]);
+ for (i = 0; i < initial_pagein; i++) {
+ vm_page_lock(ma[i]);
+ vm_page_free(ma[i]);
+ vm_page_unlock(ma[i]);
+ vm_page_xunbusy(ma[i]);
+ }
VM_OBJECT_WUNLOCK(object);
return (EIO);
}
+ for (i = 1; i < initial_pagein; i++)
+ vm_page_readahead_finish(ma[i]);
}
vm_page_xunbusy(ma[0]);
vm_page_lock(ma[0]);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 6215ecb..ee87e58 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -94,7 +94,7 @@ dtrace_execexit_func_t dtrace_fasttrap_exit;
#endif
SDT_PROVIDER_DECLARE(proc);
-SDT_PROBE_DEFINE1(proc, kernel, , exit, "int");
+SDT_PROBE_DEFINE1(proc, , , exit, "int");
/* Hook for NFS teardown procedure. */
void (*nlminfo_release_p)(struct proc *p);
@@ -569,7 +569,7 @@ exit1(struct thread *td, int rval, int signo)
reason = CLD_DUMPED;
else if (WIFSIGNALED(signo))
reason = CLD_KILLED;
- SDT_PROBE1(proc, kernel, , exit, reason);
+ SDT_PROBE1(proc, , , exit, reason);
#endif
/*
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 1b556be..a395fdd 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -89,8 +89,7 @@ dtrace_fork_func_t dtrace_fasttrap_fork;
#endif
SDT_PROVIDER_DECLARE(proc);
-SDT_PROBE_DEFINE3(proc, kernel, , create, "struct proc *",
- "struct proc *", "int");
+SDT_PROBE_DEFINE3(proc, , , create, "struct proc *", "struct proc *", "int");
#ifndef _SYS_SYSPROTO_H_
struct fork_args {
@@ -748,7 +747,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
* Tell any interested parties about the new process.
*/
knote_fork(&p1->p_klist, p2->p_pid);
- SDT_PROBE3(proc, kernel, , create, p2, p1, flags);
+ SDT_PROBE3(proc, , , create, p2, p1, flags);
/*
* Wait until debugger is attached to child.
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 435a07b..8a3b6ca 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -92,18 +92,15 @@ __FBSDID("$FreeBSD$");
#endif
SDT_PROVIDER_DEFINE(proc);
-SDT_PROBE_DEFINE4(proc, kernel, ctor, entry, "struct proc *", "int",
- "void *", "int");
-SDT_PROBE_DEFINE4(proc, kernel, ctor, return, "struct proc *", "int",
- "void *", "int");
-SDT_PROBE_DEFINE4(proc, kernel, dtor, entry, "struct proc *", "int",
- "void *", "struct thread *");
-SDT_PROBE_DEFINE3(proc, kernel, dtor, return, "struct proc *", "int",
- "void *");
-SDT_PROBE_DEFINE3(proc, kernel, init, entry, "struct proc *", "int",
+SDT_PROBE_DEFINE4(proc, , ctor, entry, "struct proc *", "int", "void *",
"int");
-SDT_PROBE_DEFINE3(proc, kernel, init, return, "struct proc *", "int",
+SDT_PROBE_DEFINE4(proc, , ctor, return, "struct proc *", "int", "void *",
"int");
+SDT_PROBE_DEFINE4(proc, , dtor, entry, "struct proc *", "int", "void *",
+ "struct thread *");
+SDT_PROBE_DEFINE3(proc, , dtor, return, "struct proc *", "int", "void *");
+SDT_PROBE_DEFINE3(proc, , init, entry, "struct proc *", "int", "int");
+SDT_PROBE_DEFINE3(proc, , init, return, "struct proc *", "int", "int");
MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
MALLOC_DEFINE(M_SESSION, "session", "session header");
@@ -196,9 +193,9 @@ proc_ctor(void *mem, int size, void *arg, int flags)
struct proc *p;
p = (struct proc *)mem;
- SDT_PROBE4(proc, kernel, ctor , entry, p, size, arg, flags);
+ SDT_PROBE4(proc, , ctor , entry, p, size, arg, flags);
EVENTHANDLER_INVOKE(process_ctor, p);
- SDT_PROBE4(proc, kernel, ctor , return, p, size, arg, flags);
+ SDT_PROBE4(proc, , ctor , return, p, size, arg, flags);
return (0);
}
@@ -214,7 +211,7 @@ proc_dtor(void *mem, int size, void *arg)
/* INVARIANTS checks go here */
p = (struct proc *)mem;
td = FIRST_THREAD_IN_PROC(p);
- SDT_PROBE4(proc, kernel, dtor, entry, p, size, arg, td);
+ SDT_PROBE4(proc, , dtor, entry, p, size, arg, td);
if (td != NULL) {
#ifdef INVARIANTS
KASSERT((p->p_numthreads == 1),
@@ -227,7 +224,7 @@ proc_dtor(void *mem, int size, void *arg)
EVENTHANDLER_INVOKE(process_dtor, p);
if (p->p_ksi != NULL)
KASSERT(! KSI_ONQ(p->p_ksi), ("SIGCHLD queue"));
- SDT_PROBE3(proc, kernel, dtor, return, p, size, arg);
+ SDT_PROBE3(proc, , dtor, return, p, size, arg);
}
/*
@@ -239,7 +236,7 @@ proc_init(void *mem, int size, int flags)
struct proc *p;
p = (struct proc *)mem;
- SDT_PROBE3(proc, kernel, init, entry, p, size, flags);
+ SDT_PROBE3(proc, , init, entry, p, size, flags);
p->p_sched = (struct p_sched *)&p[1];
mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK | MTX_NEW);
mtx_init(&p->p_slock, "process slock", NULL, MTX_SPIN | MTX_NEW);
@@ -251,7 +248,7 @@ proc_init(void *mem, int size, int flags)
TAILQ_INIT(&p->p_threads); /* all threads in proc */
EVENTHANDLER_INVOKE(process_init, p);
p->p_stats = pstats_alloc();
- SDT_PROBE3(proc, kernel, init, return, p, size, flags);
+ SDT_PROBE3(proc, , init, return, p, size, flags);
return (0);
}
diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c
index a1ad3c9..0c7c0c4 100644
--- a/sys/kern/kern_racct.c
+++ b/sys/kern/kern_racct.c
@@ -102,30 +102,32 @@ static void racct_add_cred_locked(struct ucred *cred, int resource,
uint64_t amount);
SDT_PROVIDER_DEFINE(racct);
-SDT_PROBE_DEFINE3(racct, kernel, rusage, add, "struct proc *", "int",
- "uint64_t");
-SDT_PROBE_DEFINE3(racct, kernel, rusage, add__failure,
+SDT_PROBE_DEFINE3(racct, , rusage, add,
"struct proc *", "int", "uint64_t");
-SDT_PROBE_DEFINE3(racct, kernel, rusage, add__cred, "struct ucred *",
- "int", "uint64_t");
-SDT_PROBE_DEFINE3(racct, kernel, rusage, add__force, "struct proc *",
- "int", "uint64_t");
-SDT_PROBE_DEFINE3(racct, kernel, rusage, set, "struct proc *", "int",
- "uint64_t");
-SDT_PROBE_DEFINE3(racct, kernel, rusage, set__failure,
+SDT_PROBE_DEFINE3(racct, , rusage, add__failure,
"struct proc *", "int", "uint64_t");
-SDT_PROBE_DEFINE3(racct, kernel, rusage, sub, "struct proc *", "int",
- "uint64_t");
-SDT_PROBE_DEFINE3(racct, kernel, rusage, sub__cred, "struct ucred *",
- "int", "uint64_t");
-SDT_PROBE_DEFINE1(racct, kernel, racct, create, "struct racct *");
-SDT_PROBE_DEFINE1(racct, kernel, racct, destroy, "struct racct *");
-SDT_PROBE_DEFINE2(racct, kernel, racct, join, "struct racct *",
+SDT_PROBE_DEFINE3(racct, , rusage, add__cred,
+ "struct ucred *", "int", "uint64_t");
+SDT_PROBE_DEFINE3(racct, , rusage, add__force,
+ "struct proc *", "int", "uint64_t");
+SDT_PROBE_DEFINE3(racct, , rusage, set,
+ "struct proc *", "int", "uint64_t");
+SDT_PROBE_DEFINE3(racct, , rusage, set__failure,
+ "struct proc *", "int", "uint64_t");
+SDT_PROBE_DEFINE3(racct, , rusage, sub,
+ "struct proc *", "int", "uint64_t");
+SDT_PROBE_DEFINE3(racct, , rusage, sub__cred,
+ "struct ucred *", "int", "uint64_t");
+SDT_PROBE_DEFINE1(racct, , racct, create,
"struct racct *");
-SDT_PROBE_DEFINE2(racct, kernel, racct, join__failure,
- "struct racct *", "struct racct *");
-SDT_PROBE_DEFINE2(racct, kernel, racct, leave, "struct racct *",
+SDT_PROBE_DEFINE1(racct, , racct, destroy,
"struct racct *");
+SDT_PROBE_DEFINE2(racct, , racct, join,
+ "struct racct *", "struct racct *");
+SDT_PROBE_DEFINE2(racct, , racct, join__failure,
+ "struct racct *", "struct racct *");
+SDT_PROBE_DEFINE2(racct, , racct, leave,
+ "struct racct *", "struct racct *");
int racct_types[] = {
[RACCT_CPU] =
@@ -445,7 +447,7 @@ racct_create(struct racct **racctp)
if (!racct_enable)
return;
- SDT_PROBE1(racct, kernel, racct, create, racctp);
+ SDT_PROBE1(racct, , racct, create, racctp);
KASSERT(*racctp == NULL, ("racct already allocated"));
@@ -460,7 +462,7 @@ racct_destroy_locked(struct racct **racctp)
ASSERT_RACCT_ENABLED();
- SDT_PROBE1(racct, kernel, racct, destroy, racctp);
+ SDT_PROBE1(racct, , racct, destroy, racctp);
mtx_assert(&racct_lock, MA_OWNED);
KASSERT(racctp != NULL, ("NULL racctp"));
@@ -538,7 +540,7 @@ racct_add_locked(struct proc *p, int resource, uint64_t amount)
ASSERT_RACCT_ENABLED();
- SDT_PROBE3(racct, kernel, rusage, add, p, resource, amount);
+ SDT_PROBE3(racct, , rusage, add, p, resource, amount);
/*
* We need proc lock to dereference p->p_ucred.
@@ -548,8 +550,7 @@ racct_add_locked(struct proc *p, int resource, uint64_t amount)
#ifdef RCTL
error = rctl_enforce(p, resource, amount);
if (error && RACCT_IS_DENIABLE(resource)) {
- SDT_PROBE3(racct, kernel, rusage, add__failure, p, resource,
- amount);
+ SDT_PROBE3(racct, , rusage, add__failure, p, resource, amount);
return (error);
}
#endif
@@ -584,7 +585,7 @@ racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount)
ASSERT_RACCT_ENABLED();
- SDT_PROBE3(racct, kernel, rusage, add__cred, cred, resource, amount);
+ SDT_PROBE3(racct, , rusage, add__cred, cred, resource, amount);
racct_adjust_resource(cred->cr_ruidinfo->ui_racct, resource, amount);
for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
@@ -622,7 +623,7 @@ racct_add_force(struct proc *p, int resource, uint64_t amount)
if (!racct_enable)
return;
- SDT_PROBE3(racct, kernel, rusage, add__force, p, resource, amount);
+ SDT_PROBE3(racct, , rusage, add__force, p, resource, amount);
/*
* We need proc lock to dereference p->p_ucred.
@@ -646,7 +647,7 @@ racct_set_locked(struct proc *p, int resource, uint64_t amount)
ASSERT_RACCT_ENABLED();
- SDT_PROBE3(racct, kernel, rusage, set, p, resource, amount);
+ SDT_PROBE3(racct, , rusage, set, p, resource, amount);
/*
* We need proc lock to dereference p->p_ucred.
@@ -678,8 +679,8 @@ racct_set_locked(struct proc *p, int resource, uint64_t amount)
if (diff_proc > 0) {
error = rctl_enforce(p, resource, diff_proc);
if (error && RACCT_IS_DENIABLE(resource)) {
- SDT_PROBE3(racct, kernel, rusage, set__failure, p,
- resource, amount);
+ SDT_PROBE3(racct, , rusage, set__failure, p, resource,
+ amount);
return (error);
}
}
@@ -722,7 +723,7 @@ racct_set_force_locked(struct proc *p, int resource, uint64_t amount)
ASSERT_RACCT_ENABLED();
- SDT_PROBE3(racct, kernel, rusage, set, p, resource, amount);
+ SDT_PROBE3(racct, , rusage, set, p, resource, amount);
/*
* We need proc lock to dereference p->p_ucred.
@@ -833,7 +834,7 @@ racct_sub(struct proc *p, int resource, uint64_t amount)
if (!racct_enable)
return;
- SDT_PROBE3(racct, kernel, rusage, sub, p, resource, amount);
+ SDT_PROBE3(racct, , rusage, sub, p, resource, amount);
/*
* We need proc lock to dereference p->p_ucred.
@@ -860,7 +861,7 @@ racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount)
ASSERT_RACCT_ENABLED();
- SDT_PROBE3(racct, kernel, rusage, sub__cred, cred, resource, amount);
+ SDT_PROBE3(racct, , rusage, sub__cred, cred, resource, amount);
#ifdef notyet
KASSERT(RACCT_CAN_DROP(resource),
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 767eff0..510b920 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -94,11 +94,11 @@ __FBSDID("$FreeBSD$");
#define ONSIG 32 /* NSIG for osig* syscalls. XXX. */
SDT_PROVIDER_DECLARE(proc);
-SDT_PROBE_DEFINE3(proc, kernel, , signal__send, "struct thread *",
- "struct proc *", "int");
-SDT_PROBE_DEFINE2(proc, kernel, , signal__clear, "int",
- "ksiginfo_t *");
-SDT_PROBE_DEFINE3(proc, kernel, , signal__discard,
+SDT_PROBE_DEFINE3(proc, , , signal__send,
+ "struct thread *", "struct proc *", "int");
+SDT_PROBE_DEFINE2(proc, , , signal__clear,
+ "int", "ksiginfo_t *");
+SDT_PROBE_DEFINE3(proc, , , signal__discard,
"struct thread *", "struct proc *", "int");
static int coredump(struct thread *);
@@ -1308,7 +1308,7 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi,
reschedule_signals(p, new_block, 0);
if (error == 0) {
- SDT_PROBE2(proc, kernel, , signal__clear, sig, ksi);
+ SDT_PROBE2(proc, , , signal__clear, sig, ksi);
if (ksi->ksi_code == SI_TIMER)
itimer_accept(p, ksi->ksi_timerid, ksi);
@@ -2121,7 +2121,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
} else
sigqueue = &td->td_sigqueue;
- SDT_PROBE3(proc, kernel, , signal__send, td, p, sig);
+ SDT_PROBE3(proc, , , signal__send, td, p, sig);
/*
* If the signal is being ignored,
@@ -2132,7 +2132,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
*/
mtx_lock(&ps->ps_mtx);
if (SIGISMEMBER(ps->ps_sigignore, sig)) {
- SDT_PROBE3(proc, kernel, , signal__discard, td, p, sig);
+ SDT_PROBE3(proc, , , signal__discard, td, p, sig);
mtx_unlock(&ps->ps_mtx);
if (ksi && (ksi->ksi_flags & KSI_INS))
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index 5bae716..9c9d25f 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -69,10 +69,8 @@ DPCPU_DECLARE(sbintime_t, hardclocktime);
#endif
SDT_PROVIDER_DEFINE(callout_execute);
-SDT_PROBE_DEFINE1(callout_execute, kernel, , callout__start,
- "struct callout *");
-SDT_PROBE_DEFINE1(callout_execute, kernel, , callout__end,
- "struct callout *");
+SDT_PROBE_DEFINE1(callout_execute, , , callout__start, "struct callout *");
+SDT_PROBE_DEFINE1(callout_execute, , , callout__end, "struct callout *");
#ifdef CALLOUT_PROFILING
static int avg_depth;
@@ -721,9 +719,9 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc,
sbt1 = sbinuptime();
#endif
THREAD_NO_SLEEPING();
- SDT_PROBE1(callout_execute, kernel, , callout__start, c);
+ SDT_PROBE1(callout_execute, , , callout__start, c);
c_func(c_arg);
- SDT_PROBE1(callout_execute, kernel, , callout__end, c);
+ SDT_PROBE1(callout_execute, , , callout__end, c);
THREAD_SLEEPING_OK();
#if defined(DIAGNOSTIC) || defined(CALLOUT_PROFILING)
sbt2 = sbinuptime();
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
index c076326..f7bbdfb 100644
--- a/sys/kern/subr_syscall.c
+++ b/sys/kern/subr_syscall.c
@@ -126,14 +126,9 @@ syscallenter(struct thread *td, struct syscall_args *sa)
goto retval;
#ifdef KDTRACE_HOOKS
- /*
- * If the systrace module has registered it's probe
- * callback and if there is a probe active for the
- * syscall 'entry', process the probe.
- */
+ /* Give the syscall:::entry DTrace probe a chance to fire. */
if (systrace_probe_func != NULL && sa->callp->sy_entry != 0)
- (*systrace_probe_func)(sa->callp->sy_entry, sa->code,
- sa->callp, sa->args, 0);
+ (*systrace_probe_func)(sa, SYSTRACE_ENTRY, 0);
#endif
AUDIT_SYSCALL_ENTER(sa->code, td);
@@ -145,14 +140,10 @@ syscallenter(struct thread *td, struct syscall_args *sa)
td->td_errno = error;
#ifdef KDTRACE_HOOKS
- /*
- * If the systrace module has registered it's probe
- * callback and if there is a probe active for the
- * syscall 'return', process the probe.
- */
+ /* Give the syscall:::return DTrace probe a chance to fire. */
if (systrace_probe_func != NULL && sa->callp->sy_return != 0)
- (*systrace_probe_func)(sa->callp->sy_return, sa->code,
- sa->callp, NULL, (error) ? -1 : td->td_retval[0]);
+ (*systrace_probe_func)(sa, SYSTRACE_RETURN,
+ error ? -1 : td->td_retval[0]);
#endif
syscall_thread_exit(td, sa->callp);
}
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 21cbe49..8df6e43 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -189,7 +189,7 @@ uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio)
m = vm_page_grab(obj, idx, VM_ALLOC_NORMAL);
if (m->valid != VM_PAGE_BITS_ALL) {
if (vm_pager_has_page(obj, idx, NULL, NULL)) {
- rv = vm_pager_get_pages(obj, &m, 1, 0);
+ rv = vm_pager_get_pages(obj, &m, 1, NULL, NULL);
if (rv != VM_PAGER_OK) {
printf(
"uiomove_object: vm_obj %p idx %jd valid %x pager error %d\n",
@@ -460,7 +460,7 @@ retry:
goto retry;
} else if (m->valid != VM_PAGE_BITS_ALL)
rv = vm_pager_get_pages(object, &m, 1,
- 0);
+ NULL, NULL);
else
/* A cached page was reactivated. */
rv = VM_PAGER_OK;
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 54c13024..c33a2cf 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -2033,7 +2033,7 @@ sendfile_readpage(vm_object_t obj, struct vnode *vp, int nd,
VM_OBJECT_WLOCK(obj);
} else {
if (vm_pager_has_page(obj, pindex, NULL, NULL)) {
- rv = vm_pager_get_pages(obj, &m, 1, 0);
+ rv = vm_pager_get_pages(obj, &m, 1, NULL, NULL);
SFSTAT_INC(sf_iocnt);
if (rv != VM_PAGER_OK) {
vm_page_lock(m);
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index ccd1b64..6b8f79f 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -2909,7 +2909,7 @@ getnewbuf(struct vnode *vp, int slpflag, int slptimeo, int maxsize, int gbflags)
} while(buf_scan(false) == 0);
if (reserved)
- bufspace_release(maxsize);
+ atomic_subtract_long(&bufspace, maxsize);
if (bp != NULL) {
bp->b_flags |= B_INVAL;
brelse(bp);
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index ca9f054..ff3736d 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -417,7 +417,6 @@ cache_zap(ncp)
rw_assert(&cache_lock, RA_WLOCKED);
CTR2(KTR_VFS, "cache_zap(%p) vp %p", ncp, ncp->nc_vp);
-#ifdef KDTRACE_HOOKS
if (ncp->nc_vp != NULL) {
SDT_PROBE3(vfs, namecache, zap, done, ncp->nc_dvp,
nc_get_name(ncp), ncp->nc_vp);
@@ -425,7 +424,6 @@ cache_zap(ncp)
SDT_PROBE2(vfs, namecache, zap_negative, done, ncp->nc_dvp,
nc_get_name(ncp));
}
-#endif
vp = NULL;
LIST_REMOVE(ncp, nc_hash);
if (ncp->nc_flag & NCF_ISDOTDOT) {
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index 6ee094b..fd83f87 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -731,12 +731,13 @@ vop_stdgetpages(ap)
struct vnode *a_vp;
vm_page_t *a_m;
int a_count;
- int a_reqpage;
+ int *a_rbehind;
+ int *a_rahead;
} */ *ap;
{
return vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
- ap->a_count, ap->a_reqpage, NULL, NULL);
+ ap->a_count, ap->a_rbehind, ap->a_rahead, NULL, NULL);
}
static int
@@ -744,8 +745,9 @@ vop_stdgetpages_async(struct vop_getpages_async_args *ap)
{
int error;
- error = VOP_GETPAGES(ap->a_vp, ap->a_m, ap->a_count, ap->a_reqpage);
- ap->a_iodone(ap->a_arg, ap->a_m, ap->a_reqpage, error);
+ error = VOP_GETPAGES(ap->a_vp, ap->a_m, ap->a_count, ap->a_rbehind,
+ ap->a_rahead);
+ ap->a_iodone(ap->a_arg, ap->a_m, ap->a_count, error);
return (error);
}
@@ -1034,10 +1036,9 @@ vop_stdallocate(struct vop_allocate_args *ap)
int
vop_stdadvise(struct vop_advise_args *ap)
{
- struct buf *bp;
- struct buflists *bl;
struct vnode *vp;
- daddr_t bn, startn, endn;
+ struct bufobj *bo;
+ daddr_t startn, endn;
off_t start, end;
int bsize, error;
@@ -1074,36 +1075,21 @@ vop_stdadvise(struct vop_advise_args *ap)
VM_OBJECT_WUNLOCK(vp->v_object);
}
- BO_RLOCK(&vp->v_bufobj);
+ bo = &vp->v_bufobj;
+ BO_RLOCK(bo);
bsize = vp->v_bufobj.bo_bsize;
startn = ap->a_start / bsize;
- endn = -1;
- bl = &vp->v_bufobj.bo_clean.bv_hd;
- if (!TAILQ_EMPTY(bl))
- endn = TAILQ_LAST(bl, buflists)->b_lblkno;
- bl = &vp->v_bufobj.bo_dirty.bv_hd;
- if (!TAILQ_EMPTY(bl) &&
- endn < TAILQ_LAST(bl, buflists)->b_lblkno)
- endn = TAILQ_LAST(bl, buflists)->b_lblkno;
- if (ap->a_end != OFF_MAX && endn != -1)
- endn = ap->a_end / bsize;
- BO_RUNLOCK(&vp->v_bufobj);
- /*
- * In the VMIO case, use the B_NOREUSE flag to hint that the
- * pages backing each buffer in the range are unlikely to be
- * reused. Dirty buffers will have the hint applied once
- * they've been written.
- */
- for (bn = startn; bn <= endn; bn++) {
- bp = getblk(vp, bn, bsize, 0, 0, GB_NOCREAT |
- GB_UNMAPPED);
- if (bp == NULL)
+ endn = ap->a_end / bsize;
+ for (;;) {
+ error = bnoreuselist(&bo->bo_clean, bo, startn, endn);
+ if (error == EAGAIN)
+ continue;
+ error = bnoreuselist(&bo->bo_dirty, bo, startn, endn);
+ if (error == EAGAIN)
continue;
- bp->b_flags |= B_RELBUF;
- if (vp->v_object != NULL)
- bp->b_flags |= B_NOREUSE;
- brelse(bp);
+ break;
}
+ BO_RUNLOCK(bo);
VOP_UNLOCK(vp, 0);
break;
default:
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 2ec5bc1..ace97e8 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1652,15 +1652,53 @@ flushbuflist(struct bufv *bufv, int flags, struct bufobj *bo, int slpflag,
bp->b_flags &= ~B_ASYNC;
brelse(bp);
BO_LOCK(bo);
- if (nbp != NULL &&
- (nbp->b_bufobj != bo ||
- nbp->b_lblkno != lblkno ||
- (nbp->b_xflags & (BX_VNDIRTY | BX_VNCLEAN)) != xflags))
+ nbp = gbincore(bo, lblkno);
+ if (nbp == NULL || (nbp->b_xflags & (BX_VNDIRTY | BX_VNCLEAN))
+ != xflags)
break; /* nbp invalid */
}
return (retval);
}
+int
+bnoreuselist(struct bufv *bufv, struct bufobj *bo, daddr_t startn, daddr_t endn)
+{
+ struct buf *bp;
+ int error;
+ daddr_t lblkno;
+
+ ASSERT_BO_LOCKED(bo);
+
+ for (lblkno = startn;; lblkno++) {
+ bp = BUF_PCTRIE_LOOKUP_GE(&bufv->bv_root, lblkno);
+ if (bp == NULL || bp->b_lblkno >= endn)
+ break;
+ error = BUF_TIMELOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
+ LK_INTERLOCK, BO_LOCKPTR(bo), "brlsfl", 0, 0);
+ if (error != 0) {
+ BO_RLOCK(bo);
+ return (error != ENOLCK ? error : EAGAIN);
+ }
+ KASSERT(bp->b_bufobj == bo,
+ ("bp %p wrong b_bufobj %p should be %p",
+ bp, bp->b_bufobj, bo));
+ if ((bp->b_flags & B_MANAGED) == 0)
+ bremfree(bp);
+ bp->b_flags |= B_RELBUF;
+ /*
+ * In the VMIO case, use the B_NOREUSE flag to hint that the
+ * pages backing each buffer in the range are unlikely to be
+ * reused. Dirty buffers will have the hint applied once
+ * they've been written.
+ */
+ if (bp->b_vp->v_object != NULL)
+ bp->b_flags |= B_NOREUSE;
+ brelse(bp);
+ BO_RLOCK(bo);
+ }
+ return (0);
+}
+
/*
* Truncate a file's buffer and pages to a specified length. This
* is in lieu of the old vinvalbuf mechanism, which performed unneeded
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index 63f8eb9..5586a14 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -473,7 +473,8 @@ vop_getpages {
IN struct vnode *vp;
IN vm_page_t *m;
IN int count;
- IN int reqpage;
+ IN int *rbehind;
+ IN int *rahead;
};
@@ -483,7 +484,8 @@ vop_getpages_async {
IN struct vnode *vp;
IN vm_page_t *m;
IN int count;
- IN int reqpage;
+ IN int *rbehind;
+ IN int *rahead;
IN vop_getpages_iodone_t *iodone;
IN void *arg;
};
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 85c3553..dc95750 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -346,6 +346,7 @@ SUBDIR= \
${_syscons} \
sysvipc \
${_ti} \
+ tcp/fastpath \
tests/framework \
tests/callout_test \
tl \
diff --git a/sys/modules/tcp/fastpath/Makefile b/sys/modules/tcp/fastpath/Makefile
new file mode 100644
index 0000000..526b39a
--- /dev/null
+++ b/sys/modules/tcp/fastpath/Makefile
@@ -0,0 +1,15 @@
+#
+# $FreeBSD$
+#
+
+.PATH: ${.CURDIR}/../../../netinet/tcp_stacks
+
+KMOD= fastpath
+SRCS= fastpath.c
+
+#
+# Enable full debugging
+#
+#CFLAGS += -g
+
+.include <bsd.kmod.mk>
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index cbcee14..5209bc8 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -101,6 +101,7 @@
#include <net/vnet.h>
#include <netinet/in.h>
+#include <netinet/in_fib.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
@@ -557,26 +558,13 @@ stf_checkaddr4(struct stf_softc *sc, struct in_addr *in, struct ifnet *inifp)
* perform ingress filter
*/
if (sc && (STF2IFP(sc)->if_flags & IFF_LINK2) == 0 && inifp) {
- struct sockaddr_in sin;
- struct rtentry *rt;
-
- bzero(&sin, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_addr = *in;
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0,
- 0UL, sc->sc_fibnum);
- if (!rt || rt->rt_ifp != inifp) {
-#if 0
- log(LOG_WARNING, "%s: packet from 0x%x dropped "
- "due to ingress filter\n", if_name(STF2IFP(sc)),
- (u_int32_t)ntohl(sin.sin_addr.s_addr));
-#endif
- if (rt)
- RTFREE_LOCKED(rt);
- return -1;
- }
- RTFREE_LOCKED(rt);
+ struct nhop4_basic nh4;
+
+ if (fib4_lookup_nh_basic(sc->sc_fibnum, *in, 0, 0, &nh4) != 0)
+ return (-1);
+
+ if (nh4.nh_ifp != inifp)
+ return (-1);
}
return 0;
diff --git a/sys/net/route.h b/sys/net/route.h
index c1d0997..66f4d77 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -83,6 +83,9 @@ struct rt_metrics {
#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ))
+/* lle state is exported in rmx_state rt_metrics field */
+#define rmx_state rmx_weight
+
#define RT_DEFAULT_FIB 0 /* Explicitly mark fib=0 restricted cases */
#define RT_ALL_FIBS -1 /* Announce event for every fib */
#ifdef _KERNEL
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 2214542..6ca4844 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -855,12 +855,20 @@ match:
arp_check_update_lle(ah, isaddr, ifp, bridged, la);
else if (itaddr.s_addr == myaddr.s_addr) {
/*
- * Reply to our address, but no lle exists yet.
- * do we really have to create an entry?
+ * Request/reply to our address, but no lle exists yet.
+ * Try to create new llentry.
*/
la = lltable_alloc_entry(LLTABLE(ifp), 0, dst);
- if (la == NULL)
- goto drop;
+ if (la == NULL) {
+
+ /*
+ * lle creation may fail if source address belongs
+ * to non-directly connected subnet. However, we
+ * will try to answer the request instead of dropping
+ * frame.
+ */
+ goto reply;
+ }
lltable_set_entry_addr(ifp, la, ar_sha(ah));
IF_AFDATA_WLOCK(ifp);
@@ -1209,7 +1217,8 @@ arp_announce(struct ifnet *ifp)
struct ifaddr *ifa;
struct in_addr *addr, *head;
- if (!(ifp->if_flags & IFF_UP) || (ifp->if_flags & IFF_NOARP))
+ if (!(ifp->if_flags & IFF_UP) || (ifp->if_flags & IFF_NOARP) ||
+ ifp->if_addr == NULL)
return;
entries = 8;
@@ -1246,9 +1255,11 @@ arp_announce(struct ifnet *ifp)
}
IF_ADDR_RUNLOCK(ifp);
- lladdr = IF_LLADDR(ifp);
- for (i = 0; i < cnt; i++) {
- arp_announce_addr(ifp, head + i, lladdr);
+ if (cnt > 0) {
+ lladdr = IF_LLADDR(ifp);
+ for (i = 0; i < cnt; i++) {
+ arp_announce_addr(ifp, head + i, lladdr);
+ }
}
free(head, M_TEMP);
}
diff --git a/sys/netinet/in_kdtrace.c b/sys/netinet/in_kdtrace.c
index f39f0e8..0efe403 100644
--- a/sys/netinet/in_kdtrace.c
+++ b/sys/netinet/in_kdtrace.c
@@ -122,7 +122,7 @@ SDT_PROBE_DEFINE2_XLATE(tcp, , , debug__user,
SDT_PROBE_DEFINE3_XLATE(tcp, , , debug__drop,
"struct tcpcb *", "tcpsinfo_t *" ,
"struct tcphdr *", "tcpinfo_t *",
- "uint8_t *", "ipinfo_t *")
+ "uint8_t *", "ipinfo_t *");
SDT_PROBE_DEFINE6_XLATE(tcp, , , state__change,
"void *", "void *",
diff --git a/sys/netinet/in_kdtrace.h b/sys/netinet/in_kdtrace.h
index ba8355a..a36991e 100644
--- a/sys/netinet/in_kdtrace.h
+++ b/sys/netinet/in_kdtrace.h
@@ -32,13 +32,13 @@
SDT_PROBE6(ip, , , probe, arg0, arg1, arg2, arg3, arg4, arg5)
#define UDP_PROBE(probe, arg0, arg1, arg2, arg3, arg4) \
SDT_PROBE5(udp, , , probe, arg0, arg1, arg2, arg3, arg4)
-#define TCP_PROBE1(probe, arg0) \
+#define TCP_PROBE1(probe, arg0) \
SDT_PROBE1(tcp, , , probe, arg0)
-#define TCP_PROBE2(probe, arg0, arg1) \
+#define TCP_PROBE2(probe, arg0, arg1) \
SDT_PROBE2(tcp, , , probe, arg0, arg1)
-#define TCP_PROBE3(probe, arg0, arg1, arg2) \
+#define TCP_PROBE3(probe, arg0, arg1, arg2) \
SDT_PROBE3(tcp, , , probe, arg0, arg1, arg2)
-#define TCP_PROBE4(probe, arg0, arg1, arg2, arg3) \
+#define TCP_PROBE4(probe, arg0, arg1, arg2, arg3) \
SDT_PROBE4(tcp, , , probe, arg0, arg1, arg2, arg3)
#define TCP_PROBE5(probe, arg0, arg1, arg2, arg3, arg4) \
SDT_PROBE5(tcp, , , probe, arg0, arg1, arg2, arg3, arg4)
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 6989da2..da0ceab 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1045,7 +1045,7 @@ carp_send_na(struct carp_softc *sc)
nd6_na_output_unsolicited_addr(sc->sc_carpdev, IFA_IN6(ifa),
IFA_ND6_NA_BASE_FLAGS(sc->sc_carpdev, ifa));
- nd6_na_unsolicited_addr_delay(ifa);
+ DELAY(nd6_na_unsolicited_addr_delay(ifa));
}
}
diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c
index d616d19..0bddcfd 100644
--- a/sys/netinet/sctp_cc_functions.c
+++ b/sys/netinet/sctp_cc_functions.c
@@ -95,7 +95,7 @@ sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net)
}
sctp_enforce_cwnd_limit(assoc, net);
net->ssthresh = assoc->peers_rwnd;
- SDT_PROBE(sctp, cwnd, net, init,
+ SDT_PROBE5(sctp, cwnd, net, init,
stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
0, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) &
@@ -193,7 +193,7 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb,
}
net->cwnd = net->ssthresh;
sctp_enforce_cwnd_limit(asoc, net);
- SDT_PROBE(sctp, cwnd, net, fr,
+ SDT_PROBE5(sctp, cwnd, net, fr,
stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
old_cwnd, net->cwnd);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
@@ -261,7 +261,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
*/
/* Probe point 5 */
probepoint |= ((5 << 16) | 1);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -282,7 +282,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
oth |= net->cc_mod.rtcc.step_cnt;
oth <<= 16;
oth |= net->cc_mod.rtcc.last_step_state;
- SDT_PROBE(sctp, cwnd, net, rttstep,
+ SDT_PROBE5(sctp, cwnd, net, rttstep,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -306,7 +306,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
*/
/* Probe point 6 */
probepoint |= ((6 << 16) | 0);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -318,7 +318,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
oth |= net->cc_mod.rtcc.step_cnt;
oth <<= 16;
oth |= net->cc_mod.rtcc.last_step_state;
- SDT_PROBE(sctp, cwnd, net, rttstep,
+ SDT_PROBE5(sctp, cwnd, net, rttstep,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -349,7 +349,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw,
*/
/* Probe point 7 */
probepoint |= ((7 << 16) | net->cc_mod.rtcc.ret_from_eq);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -398,7 +398,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
/* We caused it maybe.. back off? */
/* PROBE POINT 1 */
probepoint |= ((1 << 16) | 1);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -416,7 +416,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
}
/* Probe point 2 */
probepoint |= ((2 << 16) | 0);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -429,7 +429,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
oth |= net->cc_mod.rtcc.step_cnt;
oth <<= 16;
oth |= net->cc_mod.rtcc.last_step_state;
- SDT_PROBE(sctp, cwnd, net, rttstep,
+ SDT_PROBE5(sctp, cwnd, net, rttstep,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -453,7 +453,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
/* bw & rtt decreased */
/* Probe point 3 */
probepoint |= ((3 << 16) | 0);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -465,7 +465,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
oth |= net->cc_mod.rtcc.step_cnt;
oth <<= 16;
oth |= net->cc_mod.rtcc.last_step_state;
- SDT_PROBE(sctp, cwnd, net, rttstep,
+ SDT_PROBE5(sctp, cwnd, net, rttstep,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -485,7 +485,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
/* The bw decreased but rtt stayed the same */
/* Probe point 4 */
probepoint |= ((4 << 16) | 0);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -497,7 +497,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
oth |= net->cc_mod.rtcc.step_cnt;
oth <<= 16;
oth |= net->cc_mod.rtcc.last_step_state;
- SDT_PROBE(sctp, cwnd, net, rttstep,
+ SDT_PROBE5(sctp, cwnd, net, rttstep,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -535,7 +535,7 @@ cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
*/
/* PROBE POINT 0 */
probepoint = (((uint64_t) net->cwnd) << 32);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -547,7 +547,7 @@ cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6
oth |= net->cc_mod.rtcc.step_cnt;
oth <<= 16;
oth |= net->cc_mod.rtcc.last_step_state;
- SDT_PROBE(sctp, cwnd, net, rttstep,
+ SDT_PROBE5(sctp, cwnd, net, rttstep,
vtag,
((net->cc_mod.rtcc.lbw << 32) | nbw),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -647,7 +647,7 @@ cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw)
/* Can't determine do not change */
probepoint |= ((0xd << 16) | inst_ind);
}
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((nbw << 32) | inst_bw),
((net->cc_mod.rtcc.lbw_rtt << 32) | rtt),
@@ -807,7 +807,7 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
(((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) |
(stcb->rport);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
nbw,
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -906,7 +906,7 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
sctp_log_cwnd(stcb, net, incr,
SCTP_CWND_LOG_FROM_SS);
}
- SDT_PROBE(sctp, cwnd, net, ack,
+ SDT_PROBE5(sctp, cwnd, net, ack,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
@@ -969,7 +969,7 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
}
net->cwnd += incr;
sctp_enforce_cwnd_limit(asoc, net);
- SDT_PROBE(sctp, cwnd, net, ack,
+ SDT_PROBE5(sctp, cwnd, net, ack,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
@@ -1001,7 +1001,7 @@ sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net)
old_cwnd = net->cwnd;
net->cwnd = net->mtu;
- SDT_PROBE(sctp, cwnd, net, ack,
+ SDT_PROBE5(sctp, cwnd, net, ack,
stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
old_cwnd, net->cwnd);
SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
@@ -1072,7 +1072,7 @@ sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
}
net->cwnd = net->mtu;
net->partial_bytes_acked = 0;
- SDT_PROBE(sctp, cwnd, net, to,
+ SDT_PROBE5(sctp, cwnd, net, to,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
@@ -1132,7 +1132,7 @@ sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets *
net->RTO <<= 1;
}
net->cwnd = net->ssthresh;
- SDT_PROBE(sctp, cwnd, net, ecn,
+ SDT_PROBE5(sctp, cwnd, net, ecn,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
@@ -1251,7 +1251,7 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
sctp_enforce_cwnd_limit(&stcb->asoc, net);
if (net->cwnd - old_cwnd != 0) {
/* log only changes */
- SDT_PROBE(sctp, cwnd, net, pd,
+ SDT_PROBE5(sctp, cwnd, net, pd,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
@@ -1274,7 +1274,7 @@ sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
if (burst_limit) {
net->cwnd = (net->flight_size + (burst_limit * net->mtu));
sctp_enforce_cwnd_limit(&stcb->asoc, net);
- SDT_PROBE(sctp, cwnd, net, bl,
+ SDT_PROBE5(sctp, cwnd, net, bl,
stcb->asoc.my_vtag,
((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
net,
@@ -1350,7 +1350,7 @@ sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb,
probepoint = (((uint64_t) net->cwnd) << 32);
/* Probe point 8 */
probepoint |= ((8 << 16) | 0);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
((net->cc_mod.rtcc.lbw << 32) | 0),
((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt),
@@ -1413,7 +1413,7 @@ sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb,
vtag = (net->rtt << 32) |
(((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) |
(stcb->rport);
- SDT_PROBE(sctp, cwnd, net, rttvar,
+ SDT_PROBE5(sctp, cwnd, net, rttvar,
vtag,
0,
0,
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
index 3760860..294e994 100644
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -167,7 +167,7 @@ struct tcphdr {
#define TCP_KEEPCNT 1024 /* L,N number of keepalives before close */
#define TCP_PCAP_OUT 2048 /* number of output packets to keep */
#define TCP_PCAP_IN 4096 /* number of input packets to keep */
-
+#define TCP_FUNCTION_BLK 8192 /* Set the tcp function pointers to the specified stack */
/* Start of reserved space for third-party user-settable options. */
#define TCP_VENDOR SO_VENDOR
@@ -245,5 +245,11 @@ struct tcp_info {
u_int32_t __tcpi_pad[26]; /* Padding. */
};
#endif
+#define TCP_FUNCTION_NAME_LEN_MAX 32
+
+struct tcp_function_set {
+ char function_set_name[TCP_FUNCTION_NAME_LEN_MAX];
+ uint32_t pcbcnt;
+};
#endif /* !_NETINET_TCP_H_ */
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index f73c397..140cee7 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -230,23 +230,6 @@ VNET_DEFINE(struct inpcbhead, tcb);
#define tcb6 tcb /* for KAME src sync over BSD*'s */
VNET_DEFINE(struct inpcbinfo, tcbinfo);
-static void tcp_dooptions(struct tcpopt *, u_char *, int, int);
-static void tcp_do_segment(struct mbuf *, struct tcphdr *,
- struct socket *, struct tcpcb *, int, int, uint8_t,
- int);
-static void tcp_dropwithreset(struct mbuf *, struct tcphdr *,
- struct tcpcb *, int, int);
-static void tcp_pulloutofband(struct socket *,
- struct tcphdr *, struct mbuf *, int);
-static void tcp_xmit_timer(struct tcpcb *, int);
-static void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *);
-static void inline cc_ack_received(struct tcpcb *tp, struct tcphdr *th,
- uint16_t type);
-static void inline cc_conn_init(struct tcpcb *tp);
-static void inline cc_post_recovery(struct tcpcb *tp, struct tcphdr *th);
-static void inline hhook_run_tcp_est_in(struct tcpcb *tp,
- struct tcphdr *th, struct tcpopt *to);
-
/*
* TCP statistics are stored in an "array" of counter(9)s.
*/
@@ -272,7 +255,7 @@ kmod_tcpstat_inc(int statnum)
/*
* Wrapper for the TCP established input helper hook.
*/
-static void inline
+void
hhook_run_tcp_est_in(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to)
{
struct tcp_hhook_data hhook_data;
@@ -290,7 +273,7 @@ hhook_run_tcp_est_in(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to)
/*
* CC wrapper hook functions
*/
-static void inline
+void
cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type)
{
INP_WLOCK_ASSERT(tp->t_inpcb);
@@ -322,7 +305,7 @@ cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type)
}
}
-static void inline
+void
cc_conn_init(struct tcpcb *tp)
{
struct hc_metrics_lite metrics;
@@ -446,7 +429,7 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
}
}
-static void inline
+void inline
cc_post_recovery(struct tcpcb *tp, struct tcphdr *th)
{
INP_WLOCK_ASSERT(tp->t_inpcb);
@@ -601,9 +584,6 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
struct tcpopt to; /* options in this segment */
char *s = NULL; /* address and port logging */
int ti_locked;
-#define TI_UNLOCKED 1
-#define TI_RLOCKED 2
-
#ifdef TCPDEBUG
/*
* The size of tcp_saveipgen must be the size of the max ip header,
@@ -1175,7 +1155,7 @@ relocked:
* contains. tcp_do_segment() consumes
* the mbuf chain and unlocks the inpcb.
*/
- tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen,
+ tp->t_fb->tfb_tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen,
iptos, ti_locked);
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
return (IPPROTO_DONE);
@@ -1421,7 +1401,7 @@ relocked:
* state. tcp_do_segment() always consumes the mbuf chain, unlocks
* the inpcb, and unlocks pcbinfo.
*/
- tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos, ti_locked);
+ tp->t_fb->tfb_tcp_do_segment(m, th, so, tp, drop_hdrlen, tlen, iptos, ti_locked);
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
return (IPPROTO_DONE);
@@ -1476,7 +1456,7 @@ drop:
return (IPPROTO_DONE);
}
-static void
+void
tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos,
int ti_locked)
@@ -1788,7 +1768,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->t_rxtcur);
sowwakeup(so);
if (sbavail(&so->so_snd))
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
goto check_delack;
}
} else if (th->th_ack == tp->snd_una &&
@@ -1907,7 +1887,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->t_flags |= TF_DELACK;
} else {
tp->t_flags |= TF_ACKNOW;
- tcp_output(tp);
+ tp->t_fb->tfb_tcp_output(tp);
}
goto check_delack;
}
@@ -2522,7 +2502,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
}
} else
tp->snd_cwnd += tp->t_maxseg;
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
goto drop;
} else if (tp->t_dupacks == tcprexmtthresh) {
tcp_seq onxt = tp->snd_nxt;
@@ -2556,12 +2536,12 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tcps_sack_recovery_episode);
tp->sack_newdata = tp->snd_nxt;
tp->snd_cwnd = tp->t_maxseg;
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
goto drop;
}
tp->snd_nxt = th->th_ack;
tp->snd_cwnd = tp->t_maxseg;
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
KASSERT(tp->snd_limited <= 2,
("%s: tp->snd_limited too big",
__func__));
@@ -2608,7 +2588,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
(tp->snd_nxt - tp->snd_una);
SOCKBUF_UNLOCK(&so->so_snd);
if (avail > 0)
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
sent = tp->snd_max - oldsndmax;
if (sent > tp->t_maxseg) {
KASSERT((tp->t_dupacks == 2 &&
@@ -3074,7 +3054,7 @@ dodata: /* XXX */
* Return any desired output.
*/
if (needoutput || (tp->t_flags & TF_ACKNOW))
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
check_delack:
KASSERT(ti_locked == TI_UNLOCKED, ("%s: check_delack ti_locked %d",
@@ -3122,7 +3102,7 @@ dropafterack:
ti_locked = TI_UNLOCKED;
tp->t_flags |= TF_ACKNOW;
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
INP_WUNLOCK(tp->t_inpcb);
m_freem(m);
return;
@@ -3168,7 +3148,7 @@ drop:
* The mbuf must still include the original packet header.
* tp may be NULL.
*/
-static void
+void
tcp_dropwithreset(struct mbuf *m, struct tcphdr *th, struct tcpcb *tp,
int tlen, int rstreason)
{
@@ -3231,7 +3211,7 @@ drop:
/*
* Parse TCP options and place in tcpopt.
*/
-static void
+void
tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags)
{
int opt, optlen;
@@ -3325,7 +3305,7 @@ tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags)
* It is still reflected in the segment length for
* sequencing purposes.
*/
-static void
+void
tcp_pulloutofband(struct socket *so, struct tcphdr *th, struct mbuf *m,
int off)
{
@@ -3358,7 +3338,7 @@ tcp_pulloutofband(struct socket *so, struct tcphdr *th, struct mbuf *m,
* Collect new round-trip time estimate
* and update averages and current timeout.
*/
-static void
+void
tcp_xmit_timer(struct tcpcb *tp, int rtt)
{
int delta;
@@ -3738,7 +3718,7 @@ tcp_mssopt(struct in_conninfo *inc)
* By setting snd_nxt to ti_ack, this forces retransmission timer to
* be started again.
*/
-static void
+void
tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th)
{
tcp_seq onxt = tp->snd_nxt;
@@ -3755,7 +3735,7 @@ tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th)
*/
tp->snd_cwnd = tp->t_maxseg + BYTES_THIS_ACK(tp, th);
tp->t_flags |= TF_ACKNOW;
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
tp->snd_cwnd = ocwnd;
if (SEQ_GT(onxt, tp->snd_nxt))
tp->snd_nxt = onxt;
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c
index 82e2251..1e31871 100644
--- a/sys/netinet/tcp_sack.c
+++ b/sys/netinet/tcp_sack.c
@@ -599,7 +599,7 @@ tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th)
if (tp->snd_cwnd > tp->snd_ssthresh)
tp->snd_cwnd = tp->snd_ssthresh;
tp->t_flags |= TF_ACKNOW;
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
}
#if 0
diff --git a/sys/netinet/tcp_stacks/fastpath.c b/sys/netinet/tcp_stacks/fastpath.c
new file mode 100644
index 0000000..85b24f6
--- /dev/null
+++ b/sys/netinet/tcp_stacks/fastpath.c
@@ -0,0 +1,2461 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2007-2008,2010
+ * Swinburne University of Technology, Melbourne, Australia.
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
+ * Copyright (c) 2015 Netflix Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Lawrence Stewart,
+ * James Healy and David Hayes, made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
+ *
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
+ * Portions of this software were developed by Randall R. Stewart while
+ * working for Netflix Inc.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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.
+ *
+ * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ipfw.h" /* for ipfw_fwd */
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_ipsec.h"
+#include "opt_kdtrace.h"
+#include "opt_tcpdebug.h"
+
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/hhook.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/proc.h> /* for proc0 declaration */
+#include <sys/protosw.h>
+#include <sys/sdt.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */
+
+#include <vm/uma.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/route.h>
+#include <net/vnet.h>
+
+#define TCPSTATES /* for logging */
+
+#include <netinet/cc.h>
+#include <netinet/in.h>
+#include <netinet/in_kdtrace.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h> /* required for icmp_var.h */
+#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
+#include <netinet/ip_var.h>
+#include <netinet/ip_options.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet6/in6_pcb.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/nd6.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet6/tcp6_var.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_syncache.h>
+#ifdef TCPDEBUG
+#include <netinet/tcp_debug.h>
+#endif /* TCPDEBUG */
+#ifdef TCP_OFFLOAD
+#include <netinet/tcp_offload.h>
+#endif
+
+#ifdef IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/ipsec6.h>
+#endif /*IPSEC*/
+
+#include <machine/in_cksum.h>
+
+#include <security/mac/mac_framework.h>
+
+const int tcprexmtthresh;
+
+VNET_DECLARE(int, tcp_autorcvbuf_inc);
+#define V_tcp_autorcvbuf_inc VNET(tcp_autorcvbuf_inc)
+VNET_DECLARE(int, tcp_autorcvbuf_max);
+#define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max)
+VNET_DECLARE(int, tcp_do_rfc3042);
+#define V_tcp_do_rfc3042 VNET(tcp_do_rfc3042)
+VNET_DECLARE(int, tcp_do_autorcvbuf);
+#define V_tcp_do_autorcvbuf VNET(tcp_do_autorcvbuf)
+VNET_DECLARE(int, tcp_insecure_rst);
+#define V_tcp_insecure_rst VNET(tcp_insecure_rst)
+VNET_DECLARE(int, tcp_insecure_syn);
+#define V_tcp_insecure_syn VNET(tcp_insecure_syn)
+
+static void tcp_do_segment_fastslow(struct mbuf *, struct tcphdr *,
+ struct socket *, struct tcpcb *, int, int, uint8_t,
+ int);
+
+static void tcp_do_segment_fastack(struct mbuf *, struct tcphdr *,
+ struct socket *, struct tcpcb *, int, int, uint8_t,
+ int);
+
+/*
+ * Indicate whether this ack should be delayed. We can delay the ack if
+ * following conditions are met:
+ * - There is no delayed ack timer in progress.
+ * - Our last ack wasn't a 0-sized window. We never want to delay
+ * the ack that opens up a 0-sized window.
+ * - LRO wasn't used for this segment. We make sure by checking that the
+ * segment size is not larger than the MSS.
+ * - Delayed acks are enabled or this is a half-synchronized T/TCP
+ * connection.
+ */
+#define DELAY_ACK(tp, tlen) \
+ ((!tcp_timer_active(tp, TT_DELACK) && \
+ (tp->t_flags & TF_RXWIN0SENT) == 0) && \
+ (tlen <= tp->t_maxopd) && \
+ (V_tcp_delack_enabled || (tp->t_flags & TF_NEEDSYN)))
+
+/*
+ * So how is this faster than the normal fast ack?
+ * It basically allows us to also stay in the fastpath
+ * when a window-update ack also arrives. In testing
+ * we saw only 25-30% of connections doing fastpath
+ * due to the fact that along with moving forward
+ * in sequence the window was also updated.
+ */
+static void
+tcp_do_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so,
+ struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen,
+ int ti_locked, u_long tiwin)
+{
+ int acked;
+ int winup_only=0;
+#ifdef TCPDEBUG
+ /*
+ * The size of tcp_saveipgen must be the size of the max ip header,
+ * now IPv6.
+ */
+ u_char tcp_saveipgen[IP6_HDR_LEN];
+ struct tcphdr tcp_savetcp;
+ short ostate = 0;
+#endif
+ /*
+ * The following if statment will be true if
+ * we are doing the win_up_in_fp <and>
+ * - We have more new data (SEQ_LT(tp->snd_wl1, th->th_seq)) <or>
+ * - No more new data, but we have an ack for new data
+ * (tp->snd_wl1 == th->th_seq && SEQ_LT(tp->snd_wl2, th->th_ack))
+ * - No more new data, the same ack point but the window grew
+ * (tp->snd_wl1 == th->th_seq && tp->snd_wl2 == th->th_ack && twin > tp->snd_wnd)
+ */
+ if ((SEQ_LT(tp->snd_wl1, th->th_seq) ||
+ (tp->snd_wl1 == th->th_seq && (SEQ_LT(tp->snd_wl2, th->th_ack) ||
+ (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))))) {
+ /* keep track of pure window updates */
+ if (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) {
+ winup_only = 1;
+ TCPSTAT_INC(tcps_rcvwinupd);
+ }
+ tp->snd_wnd = tiwin;
+ tp->snd_wl1 = th->th_seq;
+ tp->snd_wl2 = th->th_ack;
+ if (tp->snd_wnd > tp->max_sndwnd)
+ tp->max_sndwnd = tp->snd_wnd;
+ }
+ /*
+ * If last ACK falls within this segment's sequence numbers,
+ * record the timestamp.
+ * NOTE that the test is modified according to the latest
+ * proposal of the tcplw@cray.com list (Braden 1993/04/26).
+ */
+ if ((to->to_flags & TOF_TS) != 0 &&
+ SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
+ tp->ts_recent_age = tcp_ts_getticks();
+ tp->ts_recent = to->to_tsval;
+ }
+ /*
+ * This is a pure ack for outstanding data.
+ */
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ }
+ ti_locked = TI_UNLOCKED;
+
+ TCPSTAT_INC(tcps_predack);
+
+ /*
+ * "bad retransmit" recovery.
+ */
+ if (tp->t_rxtshift == 1 &&
+ tp->t_flags & TF_PREVVALID &&
+ (int)(ticks - tp->t_badrxtwin) < 0) {
+ cc_cong_signal(tp, th, CC_RTO_ERR);
+ }
+
+ /*
+ * Recalculate the transmit timer / rtt.
+ *
+ * Some boxes send broken timestamp replies
+ * during the SYN+ACK phase, ignore
+ * timestamps of 0 or we could calculate a
+ * huge RTT and blow up the retransmit timer.
+ */
+ if ((to->to_flags & TOF_TS) != 0 &&
+ to->to_tsecr) {
+ u_int t;
+
+ t = tcp_ts_getticks() - to->to_tsecr;
+ if (!tp->t_rttlow || tp->t_rttlow > t)
+ tp->t_rttlow = t;
+ tcp_xmit_timer(tp,
+ TCP_TS_TO_TICKS(t) + 1);
+ } else if (tp->t_rtttime &&
+ SEQ_GT(th->th_ack, tp->t_rtseq)) {
+ if (!tp->t_rttlow ||
+ tp->t_rttlow > ticks - tp->t_rtttime)
+ tp->t_rttlow = ticks - tp->t_rtttime;
+ tcp_xmit_timer(tp,
+ ticks - tp->t_rtttime);
+ }
+ if (winup_only == 0) {
+ acked = BYTES_THIS_ACK(tp, th);
+
+ /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */
+ hhook_run_tcp_est_in(tp, th, to);
+
+ TCPSTAT_ADD(tcps_rcvackbyte, acked);
+ sbdrop(&so->so_snd, acked);
+ if (SEQ_GT(tp->snd_una, tp->snd_recover) &&
+ SEQ_LEQ(th->th_ack, tp->snd_recover))
+ tp->snd_recover = th->th_ack - 1;
+
+ /*
+ * Let the congestion control algorithm update
+ * congestion control related information. This
+ * typically means increasing the congestion
+ * window.
+ */
+ cc_ack_received(tp, th, CC_ACK);
+
+ tp->snd_una = th->th_ack;
+ /*
+ * Pull snd_wl2 up to prevent seq wrap relative
+ * to th_ack.
+ */
+ tp->snd_wl2 = th->th_ack;
+ tp->t_dupacks = 0;
+ m_freem(m);
+
+ /*
+ * If all outstanding data are acked, stop
+ * retransmit timer, otherwise restart timer
+ * using current (possibly backed-off) value.
+ * If process is waiting for space,
+ * wakeup/selwakeup/signal. If data
+ * are ready to send, let tcp_output
+ * decide between more output or persist.
+ */
+#ifdef TCPDEBUG
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_INPUT, ostate, tp,
+ (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+#endif
+ if (tp->snd_una == tp->snd_max)
+ tcp_timer_activate(tp, TT_REXMT, 0);
+ else if (!tcp_timer_active(tp, TT_PERSIST))
+ tcp_timer_activate(tp, TT_REXMT,
+ tp->t_rxtcur);
+ } else {
+ /*
+ * Window update only, just free the mbufs and
+ * send out whatever we can.
+ */
+ m_freem(m);
+ }
+ sowwakeup(so);
+ if (sbavail(&so->so_snd))
+ (void) tcp_output(tp);
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: check_delack ti_locked %d",
+ __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (tp->t_flags & TF_DELACK) {
+ tp->t_flags &= ~TF_DELACK;
+ tcp_timer_activate(tp, TT_DELACK, tcp_delacktime);
+ }
+ INP_WUNLOCK(tp->t_inpcb);
+}
+
+/*
+ * Here nothing is really faster, its just that we
+ * have broken out the fast-data path also just like
+ * the fast-ack.
+ */
+static void
+tcp_do_fastnewdata(struct mbuf *m, struct tcphdr *th, struct socket *so,
+ struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen,
+ int ti_locked, u_long tiwin)
+{
+ int newsize = 0; /* automatic sockbuf scaling */
+#ifdef TCPDEBUG
+ /*
+ * The size of tcp_saveipgen must be the size of the max ip header,
+ * now IPv6.
+ */
+ u_char tcp_saveipgen[IP6_HDR_LEN];
+ struct tcphdr tcp_savetcp;
+ short ostate = 0;
+#endif
+ /*
+ * If last ACK falls within this segment's sequence numbers,
+ * record the timestamp.
+ * NOTE that the test is modified according to the latest
+ * proposal of the tcplw@cray.com list (Braden 1993/04/26).
+ */
+ if ((to->to_flags & TOF_TS) != 0 &&
+ SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
+ tp->ts_recent_age = tcp_ts_getticks();
+ tp->ts_recent = to->to_tsval;
+ }
+
+ /*
+ * This is a pure, in-sequence data packet with
+ * nothing on the reassembly queue and we have enough
+ * buffer space to take it.
+ */
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ }
+ ti_locked = TI_UNLOCKED;
+
+ /* Clean receiver SACK report if present */
+ if ((tp->t_flags & TF_SACK_PERMIT) && tp->rcv_numsacks)
+ tcp_clean_sackreport(tp);
+ TCPSTAT_INC(tcps_preddat);
+ tp->rcv_nxt += tlen;
+ /*
+ * Pull snd_wl1 up to prevent seq wrap relative to
+ * th_seq.
+ */
+ tp->snd_wl1 = th->th_seq;
+ /*
+ * Pull rcv_up up to prevent seq wrap relative to
+ * rcv_nxt.
+ */
+ tp->rcv_up = tp->rcv_nxt;
+ TCPSTAT_ADD(tcps_rcvbyte, tlen);
+#ifdef TCPDEBUG
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_INPUT, ostate, tp,
+ (void *)tcp_saveipgen, &tcp_savetcp, 0);
+#endif
+ /*
+ * Automatic sizing of receive socket buffer. Often the send
+ * buffer size is not optimally adjusted to the actual network
+ * conditions at hand (delay bandwidth product). Setting the
+ * buffer size too small limits throughput on links with high
+ * bandwidth and high delay (eg. trans-continental/oceanic links).
+ *
+ * On the receive side the socket buffer memory is only rarely
+ * used to any significant extent. This allows us to be much
+ * more aggressive in scaling the receive socket buffer. For
+ * the case that the buffer space is actually used to a large
+ * extent and we run out of kernel memory we can simply drop
+ * the new segments; TCP on the sender will just retransmit it
+ * later. Setting the buffer size too big may only consume too
+ * much kernel memory if the application doesn't read() from
+ * the socket or packet loss or reordering makes use of the
+ * reassembly queue.
+ *
+ * The criteria to step up the receive buffer one notch are:
+ * 1. Application has not set receive buffer size with
+ * SO_RCVBUF. Setting SO_RCVBUF clears SB_AUTOSIZE.
+ * 2. the number of bytes received during the time it takes
+ * one timestamp to be reflected back to us (the RTT);
+ * 3. received bytes per RTT is within seven eighth of the
+ * current socket buffer size;
+ * 4. receive buffer size has not hit maximal automatic size;
+ *
+ * This algorithm does one step per RTT at most and only if
+ * we receive a bulk stream w/o packet losses or reorderings.
+ * Shrinking the buffer during idle times is not necessary as
+ * it doesn't consume any memory when idle.
+ *
+ * TODO: Only step up if the application is actually serving
+ * the buffer to better manage the socket buffer resources.
+ */
+ if (V_tcp_do_autorcvbuf &&
+ (to->to_flags & TOF_TS) &&
+ to->to_tsecr &&
+ (so->so_rcv.sb_flags & SB_AUTOSIZE)) {
+ if (TSTMP_GT(to->to_tsecr, tp->rfbuf_ts) &&
+ to->to_tsecr - tp->rfbuf_ts < hz) {
+ if (tp->rfbuf_cnt >
+ (so->so_rcv.sb_hiwat / 8 * 7) &&
+ so->so_rcv.sb_hiwat <
+ V_tcp_autorcvbuf_max) {
+ newsize =
+ min(so->so_rcv.sb_hiwat +
+ V_tcp_autorcvbuf_inc,
+ V_tcp_autorcvbuf_max);
+ }
+ /* Start over with next RTT. */
+ tp->rfbuf_ts = 0;
+ tp->rfbuf_cnt = 0;
+ } else
+ tp->rfbuf_cnt += tlen; /* add up */
+ }
+
+ /* Add data to socket buffer. */
+ SOCKBUF_LOCK(&so->so_rcv);
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ m_freem(m);
+ } else {
+ /*
+ * Set new socket buffer size.
+ * Give up when limit is reached.
+ */
+ if (newsize)
+ if (!sbreserve_locked(&so->so_rcv,
+ newsize, so, NULL))
+ so->so_rcv.sb_flags &= ~SB_AUTOSIZE;
+ m_adj(m, drop_hdrlen); /* delayed header drop */
+ sbappendstream_locked(&so->so_rcv, m, 0);
+ }
+ /* NB: sorwakeup_locked() does an implicit unlock. */
+ sorwakeup_locked(so);
+ if (DELAY_ACK(tp, tlen)) {
+ tp->t_flags |= TF_DELACK;
+ } else {
+ tp->t_flags |= TF_ACKNOW;
+ tcp_output(tp);
+ }
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: check_delack ti_locked %d",
+ __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (tp->t_flags & TF_DELACK) {
+ tp->t_flags &= ~TF_DELACK;
+ tcp_timer_activate(tp, TT_DELACK, tcp_delacktime);
+ }
+ INP_WUNLOCK(tp->t_inpcb);
+}
+
+/*
+ * The slow-path is the clone of the long long part
+ * of tcp_do_segment past all the fast-path stuff. We
+ * use it here by two different callers, the fast/slow and
+ * the fastack only.
+ */
+static void
+tcp_do_slowpath(struct mbuf *m, struct tcphdr *th, struct socket *so,
+ struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen,
+ int ti_locked, u_long tiwin, int thflags)
+{
+ int acked, ourfinisacked, needoutput = 0;
+ int rstreason, todrop, win;
+ char *s;
+ struct in_conninfo *inc;
+ struct mbuf *mfree = NULL;
+#ifdef TCPDEBUG
+ /*
+ * The size of tcp_saveipgen must be the size of the max ip header,
+ * now IPv6.
+ */
+ u_char tcp_saveipgen[IP6_HDR_LEN];
+ struct tcphdr tcp_savetcp;
+ short ostate = 0;
+#endif
+ /*
+ * Calculate amount of space in receive window,
+ * and then do TCP input processing.
+ * Receive window is amount of space in rcv queue,
+ * but not less than advertised window.
+ */
+ inc = &tp->t_inpcb->inp_inc;
+ win = sbspace(&so->so_rcv);
+ if (win < 0)
+ win = 0;
+ tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt));
+
+ /* Reset receive buffer auto scaling when not in bulk receive mode. */
+ tp->rfbuf_ts = 0;
+ tp->rfbuf_cnt = 0;
+
+ switch (tp->t_state) {
+
+ /*
+ * If the state is SYN_RECEIVED:
+ * if seg contains an ACK, but not for our SYN/ACK, send a RST.
+ */
+ case TCPS_SYN_RECEIVED:
+ if ((thflags & TH_ACK) &&
+ (SEQ_LEQ(th->th_ack, tp->snd_una) ||
+ SEQ_GT(th->th_ack, tp->snd_max))) {
+ rstreason = BANDLIM_RST_OPENPORT;
+ goto dropwithreset;
+ }
+ break;
+
+ /*
+ * If the state is SYN_SENT:
+ * if seg contains an ACK, but not for our SYN, drop the input.
+ * if seg contains a RST, then drop the connection.
+ * if seg does not contain SYN, then drop it.
+ * Otherwise this is an acceptable SYN segment
+ * initialize tp->rcv_nxt and tp->irs
+ * if seg contains ack then advance tp->snd_una
+ * if seg contains an ECE and ECN support is enabled, the stream
+ * is ECN capable.
+ * if SYN has been acked change to ESTABLISHED else SYN_RCVD state
+ * arrange for segment to be acked (eventually)
+ * continue processing rest of data/controls, beginning with URG
+ */
+ case TCPS_SYN_SENT:
+ if ((thflags & TH_ACK) &&
+ (SEQ_LEQ(th->th_ack, tp->iss) ||
+ SEQ_GT(th->th_ack, tp->snd_max))) {
+ rstreason = BANDLIM_UNLIMITED;
+ goto dropwithreset;
+ }
+ if ((thflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) {
+ TCP_PROBE5(connect__refused, NULL, tp,
+ mtod(m, const char *), tp, th);
+ tp = tcp_drop(tp, ECONNREFUSED);
+ }
+ if (thflags & TH_RST)
+ goto drop;
+ if (!(thflags & TH_SYN))
+ goto drop;
+
+ tp->irs = th->th_seq;
+ tcp_rcvseqinit(tp);
+ if (thflags & TH_ACK) {
+ TCPSTAT_INC(tcps_connects);
+ soisconnected(so);
+#ifdef MAC
+ mac_socketpeer_set_from_mbuf(m, so);
+#endif
+ /* Do window scaling on this connection? */
+ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+ (TF_RCVD_SCALE|TF_REQ_SCALE)) {
+ tp->rcv_scale = tp->request_r_scale;
+ }
+ tp->rcv_adv += imin(tp->rcv_wnd,
+ TCP_MAXWIN << tp->rcv_scale);
+ tp->snd_una++; /* SYN is acked */
+ /*
+ * If there's data, delay ACK; if there's also a FIN
+ * ACKNOW will be turned on later.
+ */
+ if (DELAY_ACK(tp, tlen) && tlen != 0)
+ tcp_timer_activate(tp, TT_DELACK,
+ tcp_delacktime);
+ else
+ tp->t_flags |= TF_ACKNOW;
+
+ if ((thflags & TH_ECE) && V_tcp_do_ecn) {
+ tp->t_flags |= TF_ECN_PERMIT;
+ TCPSTAT_INC(tcps_ecn_shs);
+ }
+
+ /*
+ * Received <SYN,ACK> in SYN_SENT[*] state.
+ * Transitions:
+ * SYN_SENT --> ESTABLISHED
+ * SYN_SENT* --> FIN_WAIT_1
+ */
+ tp->t_starttime = ticks;
+ if (tp->t_flags & TF_NEEDFIN) {
+ tcp_state_change(tp, TCPS_FIN_WAIT_1);
+ tp->t_flags &= ~TF_NEEDFIN;
+ thflags &= ~TH_SYN;
+ } else {
+ tcp_state_change(tp, TCPS_ESTABLISHED);
+ TCP_PROBE5(connect__established, NULL, tp,
+ mtod(m, const char *), tp, th);
+ cc_conn_init(tp);
+ tcp_timer_activate(tp, TT_KEEP,
+ TP_KEEPIDLE(tp));
+ }
+ } else {
+ /*
+ * Received initial SYN in SYN-SENT[*] state =>
+ * simultaneous open.
+ * If it succeeds, connection is * half-synchronized.
+ * Otherwise, do 3-way handshake:
+ * SYN-SENT -> SYN-RECEIVED
+ * SYN-SENT* -> SYN-RECEIVED*
+ */
+ tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN);
+ tcp_timer_activate(tp, TT_REXMT, 0);
+ tcp_state_change(tp, TCPS_SYN_RECEIVED);
+ }
+
+ KASSERT(ti_locked == TI_RLOCKED, ("%s: trimthenstep6: "
+ "ti_locked %d", __func__, ti_locked));
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ /*
+ * Advance th->th_seq to correspond to first data byte.
+ * If data, trim to stay within window,
+ * dropping FIN if necessary.
+ */
+ th->th_seq++;
+ if (tlen > tp->rcv_wnd) {
+ todrop = tlen - tp->rcv_wnd;
+ m_adj(m, -todrop);
+ tlen = tp->rcv_wnd;
+ thflags &= ~TH_FIN;
+ TCPSTAT_INC(tcps_rcvpackafterwin);
+ TCPSTAT_ADD(tcps_rcvbyteafterwin, todrop);
+ }
+ tp->snd_wl1 = th->th_seq - 1;
+ tp->rcv_up = th->th_seq;
+ /*
+ * Client side of transaction: already sent SYN and data.
+ * If the remote host used T/TCP to validate the SYN,
+ * our data will be ACK'd; if so, enter normal data segment
+ * processing in the middle of step 5, ack processing.
+ * Otherwise, goto step 6.
+ */
+ if (thflags & TH_ACK)
+ goto process_ACK;
+
+ goto step6;
+
+ /*
+ * If the state is LAST_ACK or CLOSING or TIME_WAIT:
+ * do normal processing.
+ *
+ * NB: Leftover from RFC1644 T/TCP. Cases to be reused later.
+ */
+ case TCPS_LAST_ACK:
+ case TCPS_CLOSING:
+ break; /* continue normal processing */
+ }
+
+ /*
+ * States other than LISTEN or SYN_SENT.
+ * First check the RST flag and sequence number since reset segments
+ * are exempt from the timestamp and connection count tests. This
+ * fixes a bug introduced by the Stevens, vol. 2, p. 960 bugfix
+ * below which allowed reset segments in half the sequence space
+ * to fall though and be processed (which gives forged reset
+ * segments with a random sequence number a 50 percent chance of
+ * killing a connection).
+ * Then check timestamp, if present.
+ * Then check the connection count, if present.
+ * Then check that at least some bytes of segment are within
+ * receive window. If segment begins before rcv_nxt,
+ * drop leading data (and SYN); if nothing left, just ack.
+ */
+ if (thflags & TH_RST) {
+ /*
+ * RFC5961 Section 3.2
+ *
+ * - RST drops connection only if SEG.SEQ == RCV.NXT.
+ * - If RST is in window, we send challenge ACK.
+ *
+ * Note: to take into account delayed ACKs, we should
+ * test against last_ack_sent instead of rcv_nxt.
+ * Note 2: we handle special case of closed window, not
+ * covered by the RFC.
+ */
+ if ((SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
+ SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) ||
+ (tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) {
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ KASSERT(ti_locked == TI_RLOCKED,
+ ("%s: TH_RST ti_locked %d, th %p tp %p",
+ __func__, ti_locked, th, tp));
+ KASSERT(tp->t_state != TCPS_SYN_SENT,
+ ("%s: TH_RST for TCPS_SYN_SENT th %p tp %p",
+ __func__, th, tp));
+
+ if (V_tcp_insecure_rst ||
+ tp->last_ack_sent == th->th_seq) {
+ TCPSTAT_INC(tcps_drops);
+ /* Drop the connection. */
+ switch (tp->t_state) {
+ case TCPS_SYN_RECEIVED:
+ so->so_error = ECONNREFUSED;
+ goto close;
+ case TCPS_ESTABLISHED:
+ case TCPS_FIN_WAIT_1:
+ case TCPS_FIN_WAIT_2:
+ case TCPS_CLOSE_WAIT:
+ so->so_error = ECONNRESET;
+ close:
+ tcp_state_change(tp, TCPS_CLOSED);
+ /* FALLTHROUGH */
+ default:
+ tp = tcp_close(tp);
+ }
+ } else {
+ TCPSTAT_INC(tcps_badrst);
+ /* Send challenge ACK. */
+ tcp_respond(tp, mtod(m, void *), th, m,
+ tp->rcv_nxt, tp->snd_nxt, TH_ACK);
+ tp->last_ack_sent = tp->rcv_nxt;
+ m = NULL;
+ }
+ }
+ goto drop;
+ }
+
+ /*
+ * RFC5961 Section 4.2
+ * Send challenge ACK for any SYN in synchronized state.
+ */
+ if ((thflags & TH_SYN) && tp->t_state != TCPS_SYN_SENT) {
+ KASSERT(ti_locked == TI_RLOCKED,
+ ("tcp_do_segment: TH_SYN ti_locked %d", ti_locked));
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+
+ TCPSTAT_INC(tcps_badsyn);
+ if (V_tcp_insecure_syn &&
+ SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
+ SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) {
+ tp = tcp_drop(tp, ECONNRESET);
+ rstreason = BANDLIM_UNLIMITED;
+ } else {
+ /* Send challenge ACK. */
+ tcp_respond(tp, mtod(m, void *), th, m, tp->rcv_nxt,
+ tp->snd_nxt, TH_ACK);
+ tp->last_ack_sent = tp->rcv_nxt;
+ m = NULL;
+ }
+ goto drop;
+ }
+
+ /*
+ * RFC 1323 PAWS: If we have a timestamp reply on this segment
+ * and it's less than ts_recent, drop it.
+ */
+ if ((to->to_flags & TOF_TS) != 0 && tp->ts_recent &&
+ TSTMP_LT(to->to_tsval, tp->ts_recent)) {
+
+ /* Check to see if ts_recent is over 24 days old. */
+ if (tcp_ts_getticks() - tp->ts_recent_age > TCP_PAWS_IDLE) {
+ /*
+ * Invalidate ts_recent. If this segment updates
+ * ts_recent, the age will be reset later and ts_recent
+ * will get a valid value. If it does not, setting
+ * ts_recent to zero will at least satisfy the
+ * requirement that zero be placed in the timestamp
+ * echo reply when ts_recent isn't valid. The
+ * age isn't reset until we get a valid ts_recent
+ * because we don't want out-of-order segments to be
+ * dropped when ts_recent is old.
+ */
+ tp->ts_recent = 0;
+ } else {
+ TCPSTAT_INC(tcps_rcvduppack);
+ TCPSTAT_ADD(tcps_rcvdupbyte, tlen);
+ TCPSTAT_INC(tcps_pawsdrop);
+ if (tlen)
+ goto dropafterack;
+ goto drop;
+ }
+ }
+
+ /*
+ * In the SYN-RECEIVED state, validate that the packet belongs to
+ * this connection before trimming the data to fit the receive
+ * window. Check the sequence number versus IRS since we know
+ * the sequence numbers haven't wrapped. This is a partial fix
+ * for the "LAND" DoS attack.
+ */
+ if (tp->t_state == TCPS_SYN_RECEIVED && SEQ_LT(th->th_seq, tp->irs)) {
+ rstreason = BANDLIM_RST_OPENPORT;
+ goto dropwithreset;
+ }
+
+ todrop = tp->rcv_nxt - th->th_seq;
+ if (todrop > 0) {
+ if (thflags & TH_SYN) {
+ thflags &= ~TH_SYN;
+ th->th_seq++;
+ if (th->th_urp > 1)
+ th->th_urp--;
+ else
+ thflags &= ~TH_URG;
+ todrop--;
+ }
+ /*
+ * Following if statement from Stevens, vol. 2, p. 960.
+ */
+ if (todrop > tlen
+ || (todrop == tlen && (thflags & TH_FIN) == 0)) {
+ /*
+ * Any valid FIN must be to the left of the window.
+ * At this point the FIN must be a duplicate or out
+ * of sequence; drop it.
+ */
+ thflags &= ~TH_FIN;
+
+ /*
+ * Send an ACK to resynchronize and drop any data.
+ * But keep on processing for RST or ACK.
+ */
+ tp->t_flags |= TF_ACKNOW;
+ todrop = tlen;
+ TCPSTAT_INC(tcps_rcvduppack);
+ TCPSTAT_ADD(tcps_rcvdupbyte, todrop);
+ } else {
+ TCPSTAT_INC(tcps_rcvpartduppack);
+ TCPSTAT_ADD(tcps_rcvpartdupbyte, todrop);
+ }
+ drop_hdrlen += todrop; /* drop from the top afterwards */
+ th->th_seq += todrop;
+ tlen -= todrop;
+ if (th->th_urp > todrop)
+ th->th_urp -= todrop;
+ else {
+ thflags &= ~TH_URG;
+ th->th_urp = 0;
+ }
+ }
+
+ /*
+ * If new data are received on a connection after the
+ * user processes are gone, then RST the other end.
+ */
+ if ((so->so_state & SS_NOFDREF) &&
+ tp->t_state > TCPS_CLOSE_WAIT && tlen) {
+ KASSERT(ti_locked == TI_RLOCKED, ("%s: SS_NOFDEREF && "
+ "CLOSE_WAIT && tlen ti_locked %d", __func__, ti_locked));
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: %s: Received %d bytes of data "
+ "after socket was closed, "
+ "sending RST and removing tcpcb\n",
+ s, __func__, tcpstates[tp->t_state], tlen);
+ free(s, M_TCPLOG);
+ }
+ tp = tcp_close(tp);
+ TCPSTAT_INC(tcps_rcvafterclose);
+ rstreason = BANDLIM_UNLIMITED;
+ goto dropwithreset;
+ }
+
+ /*
+ * If segment ends after window, drop trailing data
+ * (and PUSH and FIN); if nothing left, just ACK.
+ */
+ todrop = (th->th_seq + tlen) - (tp->rcv_nxt + tp->rcv_wnd);
+ if (todrop > 0) {
+ TCPSTAT_INC(tcps_rcvpackafterwin);
+ if (todrop >= tlen) {
+ TCPSTAT_ADD(tcps_rcvbyteafterwin, tlen);
+ /*
+ * If window is closed can only take segments at
+ * window edge, and have to drop data and PUSH from
+ * incoming segments. Continue processing, but
+ * remember to ack. Otherwise, drop segment
+ * and ack.
+ */
+ if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) {
+ tp->t_flags |= TF_ACKNOW;
+ TCPSTAT_INC(tcps_rcvwinprobe);
+ } else
+ goto dropafterack;
+ } else
+ TCPSTAT_ADD(tcps_rcvbyteafterwin, todrop);
+ m_adj(m, -todrop);
+ tlen -= todrop;
+ thflags &= ~(TH_PUSH|TH_FIN);
+ }
+
+ /*
+ * If last ACK falls within this segment's sequence numbers,
+ * record its timestamp.
+ * NOTE:
+ * 1) That the test incorporates suggestions from the latest
+ * proposal of the tcplw@cray.com list (Braden 1993/04/26).
+ * 2) That updating only on newer timestamps interferes with
+ * our earlier PAWS tests, so this check should be solely
+ * predicated on the sequence space of this segment.
+ * 3) That we modify the segment boundary check to be
+ * Last.ACK.Sent <= SEG.SEQ + SEG.Len
+ * instead of RFC1323's
+ * Last.ACK.Sent < SEG.SEQ + SEG.Len,
+ * This modified check allows us to overcome RFC1323's
+ * limitations as described in Stevens TCP/IP Illustrated
+ * Vol. 2 p.869. In such cases, we can still calculate the
+ * RTT correctly when RCV.NXT == Last.ACK.Sent.
+ */
+ if ((to->to_flags & TOF_TS) != 0 &&
+ SEQ_LEQ(th->th_seq, tp->last_ack_sent) &&
+ SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen +
+ ((thflags & (TH_SYN|TH_FIN)) != 0))) {
+ tp->ts_recent_age = tcp_ts_getticks();
+ tp->ts_recent = to->to_tsval;
+ }
+
+ /*
+ * If the ACK bit is off: if in SYN-RECEIVED state or SENDSYN
+ * flag is on (half-synchronized state), then queue data for
+ * later processing; else drop segment and return.
+ */
+ if ((thflags & TH_ACK) == 0) {
+ if (tp->t_state == TCPS_SYN_RECEIVED ||
+ (tp->t_flags & TF_NEEDSYN))
+ goto step6;
+ else if (tp->t_flags & TF_ACKNOW)
+ goto dropafterack;
+ else
+ goto drop;
+ }
+
+ /*
+ * Ack processing.
+ */
+ switch (tp->t_state) {
+
+ /*
+ * In SYN_RECEIVED state, the ack ACKs our SYN, so enter
+ * ESTABLISHED state and continue processing.
+ * The ACK was checked above.
+ */
+ case TCPS_SYN_RECEIVED:
+
+ TCPSTAT_INC(tcps_connects);
+ soisconnected(so);
+ /* Do window scaling? */
+ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+ (TF_RCVD_SCALE|TF_REQ_SCALE)) {
+ tp->rcv_scale = tp->request_r_scale;
+ tp->snd_wnd = tiwin;
+ }
+ /*
+ * Make transitions:
+ * SYN-RECEIVED -> ESTABLISHED
+ * SYN-RECEIVED* -> FIN-WAIT-1
+ */
+ tp->t_starttime = ticks;
+ if (tp->t_flags & TF_NEEDFIN) {
+ tcp_state_change(tp, TCPS_FIN_WAIT_1);
+ tp->t_flags &= ~TF_NEEDFIN;
+ } else {
+ tcp_state_change(tp, TCPS_ESTABLISHED);
+ TCP_PROBE5(accept__established, NULL, tp,
+ mtod(m, const char *), tp, th);
+ cc_conn_init(tp);
+ tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
+ }
+ /*
+ * If segment contains data or ACK, will call tcp_reass()
+ * later; if not, do so now to pass queued data to user.
+ */
+ if (tlen == 0 && (thflags & TH_FIN) == 0)
+ (void) tcp_reass(tp, (struct tcphdr *)0, 0,
+ (struct mbuf *)0);
+ tp->snd_wl1 = th->th_seq - 1;
+ /* FALLTHROUGH */
+
+ /*
+ * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
+ * ACKs. If the ack is in the range
+ * tp->snd_una < th->th_ack <= tp->snd_max
+ * then advance tp->snd_una to th->th_ack and drop
+ * data from the retransmission queue. If this ACK reflects
+ * more up to date window information we update our window information.
+ */
+ case TCPS_ESTABLISHED:
+ case TCPS_FIN_WAIT_1:
+ case TCPS_FIN_WAIT_2:
+ case TCPS_CLOSE_WAIT:
+ case TCPS_CLOSING:
+ case TCPS_LAST_ACK:
+ if (SEQ_GT(th->th_ack, tp->snd_max)) {
+ TCPSTAT_INC(tcps_rcvacktoomuch);
+ goto dropafterack;
+ }
+ if ((tp->t_flags & TF_SACK_PERMIT) &&
+ ((to->to_flags & TOF_SACK) ||
+ !TAILQ_EMPTY(&tp->snd_holes)))
+ tcp_sack_doack(tp, to, th->th_ack);
+ else
+ /*
+ * Reset the value so that previous (valid) value
+ * from the last ack with SACK doesn't get used.
+ */
+ tp->sackhint.sacked_bytes = 0;
+
+ /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */
+ hhook_run_tcp_est_in(tp, th, to);
+
+ if (SEQ_LEQ(th->th_ack, tp->snd_una)) {
+ if (tlen == 0 && tiwin == tp->snd_wnd) {
+ /*
+ * If this is the first time we've seen a
+ * FIN from the remote, this is not a
+ * duplicate and it needs to be processed
+ * normally. This happens during a
+ * simultaneous close.
+ */
+ if ((thflags & TH_FIN) &&
+ (TCPS_HAVERCVDFIN(tp->t_state) == 0)) {
+ tp->t_dupacks = 0;
+ break;
+ }
+ TCPSTAT_INC(tcps_rcvdupack);
+ /*
+ * If we have outstanding data (other than
+ * a window probe), this is a completely
+ * duplicate ack (ie, window info didn't
+ * change and FIN isn't set),
+ * the ack is the biggest we've
+ * seen and we've seen exactly our rexmt
+ * threshhold of them, assume a packet
+ * has been dropped and retransmit it.
+ * Kludge snd_nxt & the congestion
+ * window so we send only this one
+ * packet.
+ *
+ * We know we're losing at the current
+ * window size so do congestion avoidance
+ * (set ssthresh to half the current window
+ * and pull our congestion window back to
+ * the new ssthresh).
+ *
+ * Dup acks mean that packets have left the
+ * network (they're now cached at the receiver)
+ * so bump cwnd by the amount in the receiver
+ * to keep a constant cwnd packets in the
+ * network.
+ *
+ * When using TCP ECN, notify the peer that
+ * we reduced the cwnd.
+ */
+ if (!tcp_timer_active(tp, TT_REXMT) ||
+ th->th_ack != tp->snd_una)
+ tp->t_dupacks = 0;
+ else if (++tp->t_dupacks > tcprexmtthresh ||
+ IN_FASTRECOVERY(tp->t_flags)) {
+ cc_ack_received(tp, th, CC_DUPACK);
+ if ((tp->t_flags & TF_SACK_PERMIT) &&
+ IN_FASTRECOVERY(tp->t_flags)) {
+ int awnd;
+
+ /*
+ * Compute the amount of data in flight first.
+ * We can inject new data into the pipe iff
+ * we have less than 1/2 the original window's
+ * worth of data in flight.
+ */
+ if (V_tcp_do_rfc6675_pipe)
+ awnd = tcp_compute_pipe(tp);
+ else
+ awnd = (tp->snd_nxt - tp->snd_fack) +
+ tp->sackhint.sack_bytes_rexmit;
+
+ if (awnd < tp->snd_ssthresh) {
+ tp->snd_cwnd += tp->t_maxseg;
+ if (tp->snd_cwnd > tp->snd_ssthresh)
+ tp->snd_cwnd = tp->snd_ssthresh;
+ }
+ } else
+ tp->snd_cwnd += tp->t_maxseg;
+ (void) tp->t_fb->tfb_tcp_output(tp);
+ goto drop;
+ } else if (tp->t_dupacks == tcprexmtthresh) {
+ tcp_seq onxt = tp->snd_nxt;
+
+ /*
+ * If we're doing sack, check to
+ * see if we're already in sack
+ * recovery. If we're not doing sack,
+ * check to see if we're in newreno
+ * recovery.
+ */
+ if (tp->t_flags & TF_SACK_PERMIT) {
+ if (IN_FASTRECOVERY(tp->t_flags)) {
+ tp->t_dupacks = 0;
+ break;
+ }
+ } else {
+ if (SEQ_LEQ(th->th_ack,
+ tp->snd_recover)) {
+ tp->t_dupacks = 0;
+ break;
+ }
+ }
+ /* Congestion signal before ack. */
+ cc_cong_signal(tp, th, CC_NDUPACK);
+ cc_ack_received(tp, th, CC_DUPACK);
+ tcp_timer_activate(tp, TT_REXMT, 0);
+ tp->t_rtttime = 0;
+ if (tp->t_flags & TF_SACK_PERMIT) {
+ TCPSTAT_INC(
+ tcps_sack_recovery_episode);
+ tp->sack_newdata = tp->snd_nxt;
+ tp->snd_cwnd = tp->t_maxseg;
+ (void) tp->t_fb->tfb_tcp_output(tp);
+ goto drop;
+ }
+ tp->snd_nxt = th->th_ack;
+ tp->snd_cwnd = tp->t_maxseg;
+ (void) tp->t_fb->tfb_tcp_output(tp);
+ KASSERT(tp->snd_limited <= 2,
+ ("%s: tp->snd_limited too big",
+ __func__));
+ tp->snd_cwnd = tp->snd_ssthresh +
+ tp->t_maxseg *
+ (tp->t_dupacks - tp->snd_limited);
+ if (SEQ_GT(onxt, tp->snd_nxt))
+ tp->snd_nxt = onxt;
+ goto drop;
+ } else if (V_tcp_do_rfc3042) {
+ /*
+ * Process first and second duplicate
+ * ACKs. Each indicates a segment
+ * leaving the network, creating room
+ * for more. Make sure we can send a
+ * packet on reception of each duplicate
+ * ACK by increasing snd_cwnd by one
+ * segment. Restore the original
+ * snd_cwnd after packet transmission.
+ */
+ cc_ack_received(tp, th, CC_DUPACK);
+ u_long oldcwnd = tp->snd_cwnd;
+ tcp_seq oldsndmax = tp->snd_max;
+ u_int sent;
+ int avail;
+
+ KASSERT(tp->t_dupacks == 1 ||
+ tp->t_dupacks == 2,
+ ("%s: dupacks not 1 or 2",
+ __func__));
+ if (tp->t_dupacks == 1)
+ tp->snd_limited = 0;
+ tp->snd_cwnd =
+ (tp->snd_nxt - tp->snd_una) +
+ (tp->t_dupacks - tp->snd_limited) *
+ tp->t_maxseg;
+ /*
+ * Only call tcp_output when there
+ * is new data available to be sent.
+ * Otherwise we would send pure ACKs.
+ */
+ SOCKBUF_LOCK(&so->so_snd);
+ avail = sbavail(&so->so_snd) -
+ (tp->snd_nxt - tp->snd_una);
+ SOCKBUF_UNLOCK(&so->so_snd);
+ if (avail > 0)
+ (void) tp->t_fb->tfb_tcp_output(tp);
+ sent = tp->snd_max - oldsndmax;
+ if (sent > tp->t_maxseg) {
+ KASSERT((tp->t_dupacks == 2 &&
+ tp->snd_limited == 0) ||
+ (sent == tp->t_maxseg + 1 &&
+ tp->t_flags & TF_SENTFIN),
+ ("%s: sent too much",
+ __func__));
+ tp->snd_limited = 2;
+ } else if (sent > 0)
+ ++tp->snd_limited;
+ tp->snd_cwnd = oldcwnd;
+ goto drop;
+ }
+ } else
+ tp->t_dupacks = 0;
+ break;
+ }
+
+ KASSERT(SEQ_GT(th->th_ack, tp->snd_una),
+ ("%s: th_ack <= snd_una", __func__));
+
+ /*
+ * If the congestion window was inflated to account
+ * for the other side's cached packets, retract it.
+ */
+ if (IN_FASTRECOVERY(tp->t_flags)) {
+ if (SEQ_LT(th->th_ack, tp->snd_recover)) {
+ if (tp->t_flags & TF_SACK_PERMIT)
+ tcp_sack_partialack(tp, th);
+ else
+ tcp_newreno_partial_ack(tp, th);
+ } else
+ cc_post_recovery(tp, th);
+ }
+ tp->t_dupacks = 0;
+ /*
+ * If we reach this point, ACK is not a duplicate,
+ * i.e., it ACKs something we sent.
+ */
+ if (tp->t_flags & TF_NEEDSYN) {
+ /*
+ * T/TCP: Connection was half-synchronized, and our
+ * SYN has been ACK'd (so connection is now fully
+ * synchronized). Go to non-starred state,
+ * increment snd_una for ACK of SYN, and check if
+ * we can do window scaling.
+ */
+ tp->t_flags &= ~TF_NEEDSYN;
+ tp->snd_una++;
+ /* Do window scaling? */
+ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+ (TF_RCVD_SCALE|TF_REQ_SCALE)) {
+ tp->rcv_scale = tp->request_r_scale;
+ /* Send window already scaled. */
+ }
+ }
+
+process_ACK:
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ acked = BYTES_THIS_ACK(tp, th);
+ TCPSTAT_INC(tcps_rcvackpack);
+ TCPSTAT_ADD(tcps_rcvackbyte, acked);
+
+ /*
+ * If we just performed our first retransmit, and the ACK
+ * arrives within our recovery window, then it was a mistake
+ * to do the retransmit in the first place. Recover our
+ * original cwnd and ssthresh, and proceed to transmit where
+ * we left off.
+ */
+ if (tp->t_rxtshift == 1 && tp->t_flags & TF_PREVVALID &&
+ (int)(ticks - tp->t_badrxtwin) < 0)
+ cc_cong_signal(tp, th, CC_RTO_ERR);
+
+ /*
+ * If we have a timestamp reply, update smoothed
+ * round trip time. If no timestamp is present but
+ * transmit timer is running and timed sequence
+ * number was acked, update smoothed round trip time.
+ * Since we now have an rtt measurement, cancel the
+ * timer backoff (cf., Phil Karn's retransmit alg.).
+ * Recompute the initial retransmit timer.
+ *
+ * Some boxes send broken timestamp replies
+ * during the SYN+ACK phase, ignore
+ * timestamps of 0 or we could calculate a
+ * huge RTT and blow up the retransmit timer.
+ */
+ if ((to->to_flags & TOF_TS) != 0 && to->to_tsecr) {
+ u_int t;
+
+ t = tcp_ts_getticks() - to->to_tsecr;
+ if (!tp->t_rttlow || tp->t_rttlow > t)
+ tp->t_rttlow = t;
+ tcp_xmit_timer(tp, TCP_TS_TO_TICKS(t) + 1);
+ } else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) {
+ if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime)
+ tp->t_rttlow = ticks - tp->t_rtttime;
+ tcp_xmit_timer(tp, ticks - tp->t_rtttime);
+ }
+
+ /*
+ * If all outstanding data is acked, stop retransmit
+ * timer and remember to restart (more output or persist).
+ * If there is more data to be acked, restart retransmit
+ * timer, using current (possibly backed-off) value.
+ */
+ if (th->th_ack == tp->snd_max) {
+ tcp_timer_activate(tp, TT_REXMT, 0);
+ needoutput = 1;
+ } else if (!tcp_timer_active(tp, TT_PERSIST))
+ tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur);
+
+ /*
+ * If no data (only SYN) was ACK'd,
+ * skip rest of ACK processing.
+ */
+ if (acked == 0)
+ goto step6;
+
+ /*
+ * Let the congestion control algorithm update congestion
+ * control related information. This typically means increasing
+ * the congestion window.
+ */
+ cc_ack_received(tp, th, CC_ACK);
+
+ SOCKBUF_LOCK(&so->so_snd);
+ if (acked > sbavail(&so->so_snd)) {
+ tp->snd_wnd -= sbavail(&so->so_snd);
+ mfree = sbcut_locked(&so->so_snd,
+ (int)sbavail(&so->so_snd));
+ ourfinisacked = 1;
+ } else {
+ mfree = sbcut_locked(&so->so_snd, acked);
+ tp->snd_wnd -= acked;
+ ourfinisacked = 0;
+ }
+ /* NB: sowwakeup_locked() does an implicit unlock. */
+ sowwakeup_locked(so);
+ m_freem(mfree);
+ /* Detect una wraparound. */
+ if (!IN_RECOVERY(tp->t_flags) &&
+ SEQ_GT(tp->snd_una, tp->snd_recover) &&
+ SEQ_LEQ(th->th_ack, tp->snd_recover))
+ tp->snd_recover = th->th_ack - 1;
+ /* XXXLAS: Can this be moved up into cc_post_recovery? */
+ if (IN_RECOVERY(tp->t_flags) &&
+ SEQ_GEQ(th->th_ack, tp->snd_recover)) {
+ EXIT_RECOVERY(tp->t_flags);
+ }
+ tp->snd_una = th->th_ack;
+ if (tp->t_flags & TF_SACK_PERMIT) {
+ if (SEQ_GT(tp->snd_una, tp->snd_recover))
+ tp->snd_recover = tp->snd_una;
+ }
+ if (SEQ_LT(tp->snd_nxt, tp->snd_una))
+ tp->snd_nxt = tp->snd_una;
+
+ switch (tp->t_state) {
+
+ /*
+ * In FIN_WAIT_1 STATE in addition to the processing
+ * for the ESTABLISHED state if our FIN is now acknowledged
+ * then enter FIN_WAIT_2.
+ */
+ case TCPS_FIN_WAIT_1:
+ if (ourfinisacked) {
+ /*
+ * If we can't receive any more
+ * data, then closing user can proceed.
+ * Starting the timer is contrary to the
+ * specification, but if we don't get a FIN
+ * we'll hang forever.
+ *
+ * XXXjl:
+ * we should release the tp also, and use a
+ * compressed state.
+ */
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ soisdisconnected(so);
+ tcp_timer_activate(tp, TT_2MSL,
+ (tcp_fast_finwait2_recycle ?
+ tcp_finwait2_timeout :
+ TP_MAXIDLE(tp)));
+ }
+ tcp_state_change(tp, TCPS_FIN_WAIT_2);
+ }
+ break;
+
+ /*
+ * In CLOSING STATE in addition to the processing for
+ * the ESTABLISHED state if the ACK acknowledges our FIN
+ * then enter the TIME-WAIT state, otherwise ignore
+ * the segment.
+ */
+ case TCPS_CLOSING:
+ if (ourfinisacked) {
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ tcp_twstart(tp);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ m_freem(m);
+ return;
+ }
+ break;
+
+ /*
+ * In LAST_ACK, we may still be waiting for data to drain
+ * and/or to be acked, as well as for the ack of our FIN.
+ * If our FIN is now acknowledged, delete the TCB,
+ * enter the closed state and return.
+ */
+ case TCPS_LAST_ACK:
+ if (ourfinisacked) {
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ tp = tcp_close(tp);
+ goto drop;
+ }
+ break;
+ }
+ }
+
+step6:
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ /*
+ * Update window information.
+ * Don't look at window if no ACK: TAC's send garbage on first SYN.
+ */
+ if ((thflags & TH_ACK) &&
+ (SEQ_LT(tp->snd_wl1, th->th_seq) ||
+ (tp->snd_wl1 == th->th_seq && (SEQ_LT(tp->snd_wl2, th->th_ack) ||
+ (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))))) {
+ /* keep track of pure window updates */
+ if (tlen == 0 &&
+ tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd)
+ TCPSTAT_INC(tcps_rcvwinupd);
+ tp->snd_wnd = tiwin;
+ tp->snd_wl1 = th->th_seq;
+ tp->snd_wl2 = th->th_ack;
+ if (tp->snd_wnd > tp->max_sndwnd)
+ tp->max_sndwnd = tp->snd_wnd;
+ needoutput = 1;
+ }
+
+ /*
+ * Process segments with URG.
+ */
+ if ((thflags & TH_URG) && th->th_urp &&
+ TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ /*
+ * This is a kludge, but if we receive and accept
+ * random urgent pointers, we'll crash in
+ * soreceive. It's hard to imagine someone
+ * actually wanting to send this much urgent data.
+ */
+ SOCKBUF_LOCK(&so->so_rcv);
+ if (th->th_urp + sbavail(&so->so_rcv) > sb_max) {
+ th->th_urp = 0; /* XXX */
+ thflags &= ~TH_URG; /* XXX */
+ SOCKBUF_UNLOCK(&so->so_rcv); /* XXX */
+ goto dodata; /* XXX */
+ }
+ /*
+ * If this segment advances the known urgent pointer,
+ * then mark the data stream. This should not happen
+ * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
+ * a FIN has been received from the remote side.
+ * In these states we ignore the URG.
+ *
+ * According to RFC961 (Assigned Protocols),
+ * the urgent pointer points to the last octet
+ * of urgent data. We continue, however,
+ * to consider it to indicate the first octet
+ * of data past the urgent section as the original
+ * spec states (in one of two places).
+ */
+ if (SEQ_GT(th->th_seq+th->th_urp, tp->rcv_up)) {
+ tp->rcv_up = th->th_seq + th->th_urp;
+ so->so_oobmark = sbavail(&so->so_rcv) +
+ (tp->rcv_up - tp->rcv_nxt) - 1;
+ if (so->so_oobmark == 0)
+ so->so_rcv.sb_state |= SBS_RCVATMARK;
+ sohasoutofband(so);
+ tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
+ }
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ /*
+ * Remove out of band data so doesn't get presented to user.
+ * This can happen independent of advancing the URG pointer,
+ * but if two URG's are pending at once, some out-of-band
+ * data may creep in... ick.
+ */
+ if (th->th_urp <= (u_long)tlen &&
+ !(so->so_options & SO_OOBINLINE)) {
+ /* hdr drop is delayed */
+ tcp_pulloutofband(so, th, m, drop_hdrlen);
+ }
+ } else {
+ /*
+ * If no out of band data is expected,
+ * pull receive urgent pointer along
+ * with the receive window.
+ */
+ if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
+ tp->rcv_up = tp->rcv_nxt;
+ }
+dodata: /* XXX */
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ /*
+ * Process the segment text, merging it into the TCP sequencing queue,
+ * and arranging for acknowledgment of receipt if necessary.
+ * This process logically involves adjusting tp->rcv_wnd as data
+ * is presented to the user (this happens in tcp_usrreq.c,
+ * case PRU_RCVD). If a FIN has already been received on this
+ * connection then we just ignore the text.
+ */
+ if ((tlen || (thflags & TH_FIN)) &&
+ TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ tcp_seq save_start = th->th_seq;
+ m_adj(m, drop_hdrlen); /* delayed header drop */
+ /*
+ * Insert segment which includes th into TCP reassembly queue
+ * with control block tp. Set thflags to whether reassembly now
+ * includes a segment with FIN. This handles the common case
+ * inline (segment is the next to be received on an established
+ * connection, and the queue is empty), avoiding linkage into
+ * and removal from the queue and repetition of various
+ * conversions.
+ * Set DELACK for segments received in order, but ack
+ * immediately when segments are out of order (so
+ * fast retransmit can work).
+ */
+ if (th->th_seq == tp->rcv_nxt &&
+ LIST_EMPTY(&tp->t_segq) &&
+ TCPS_HAVEESTABLISHED(tp->t_state)) {
+ if (DELAY_ACK(tp, tlen))
+ tp->t_flags |= TF_DELACK;
+ else
+ tp->t_flags |= TF_ACKNOW;
+ tp->rcv_nxt += tlen;
+ thflags = th->th_flags & TH_FIN;
+ TCPSTAT_INC(tcps_rcvpack);
+ TCPSTAT_ADD(tcps_rcvbyte, tlen);
+ SOCKBUF_LOCK(&so->so_rcv);
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
+ m_freem(m);
+ else
+ sbappendstream_locked(&so->so_rcv, m, 0);
+ /* NB: sorwakeup_locked() does an implicit unlock. */
+ sorwakeup_locked(so);
+ } else {
+ /*
+ * XXX: Due to the header drop above "th" is
+ * theoretically invalid by now. Fortunately
+ * m_adj() doesn't actually frees any mbufs
+ * when trimming from the head.
+ */
+ thflags = tcp_reass(tp, th, &tlen, m);
+ tp->t_flags |= TF_ACKNOW;
+ }
+ if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT))
+ tcp_update_sack_list(tp, save_start, save_start + tlen);
+#if 0
+ /*
+ * Note the amount of data that peer has sent into
+ * our window, in order to estimate the sender's
+ * buffer size.
+ * XXX: Unused.
+ */
+ if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt))
+ len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt);
+ else
+ len = so->so_rcv.sb_hiwat;
+#endif
+ } else {
+ m_freem(m);
+ thflags &= ~TH_FIN;
+ }
+
+ /*
+ * If FIN is received ACK the FIN and let the user know
+ * that the connection is closing.
+ */
+ if (thflags & TH_FIN) {
+ if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ socantrcvmore(so);
+ /*
+ * If connection is half-synchronized
+ * (ie NEEDSYN flag on) then delay ACK,
+ * so it may be piggybacked when SYN is sent.
+ * Otherwise, since we received a FIN then no
+ * more input can be expected, send ACK now.
+ */
+ if (tp->t_flags & TF_NEEDSYN)
+ tp->t_flags |= TF_DELACK;
+ else
+ tp->t_flags |= TF_ACKNOW;
+ tp->rcv_nxt++;
+ }
+ switch (tp->t_state) {
+
+ /*
+ * In SYN_RECEIVED and ESTABLISHED STATES
+ * enter the CLOSE_WAIT state.
+ */
+ case TCPS_SYN_RECEIVED:
+ tp->t_starttime = ticks;
+ /* FALLTHROUGH */
+ case TCPS_ESTABLISHED:
+ tcp_state_change(tp, TCPS_CLOSE_WAIT);
+ break;
+
+ /*
+ * If still in FIN_WAIT_1 STATE FIN has not been acked so
+ * enter the CLOSING state.
+ */
+ case TCPS_FIN_WAIT_1:
+ tcp_state_change(tp, TCPS_CLOSING);
+ break;
+
+ /*
+ * In FIN_WAIT_2 state enter the TIME_WAIT state,
+ * starting the time-wait timer, turning off the other
+ * standard timers.
+ */
+ case TCPS_FIN_WAIT_2:
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ KASSERT(ti_locked == TI_RLOCKED, ("%s: dodata "
+ "TCP_FIN_WAIT_2 ti_locked: %d", __func__,
+ ti_locked));
+
+ tcp_twstart(tp);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ return;
+ }
+ }
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ }
+ ti_locked = TI_UNLOCKED;
+
+#ifdef TCPDEBUG
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_INPUT, ostate, tp, (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+#endif
+ TCP_PROBE3(debug__input, tp, th, mtod(m, const char *));
+
+ /*
+ * Return any desired output.
+ */
+ if (needoutput || (tp->t_flags & TF_ACKNOW))
+ (void) tp->t_fb->tfb_tcp_output(tp);
+
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: check_delack ti_locked %d",
+ __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (tp->t_flags & TF_DELACK) {
+ tp->t_flags &= ~TF_DELACK;
+ tcp_timer_activate(tp, TT_DELACK, tcp_delacktime);
+ }
+ INP_WUNLOCK(tp->t_inpcb);
+ return;
+
+dropafterack:
+ /*
+ * Generate an ACK dropping incoming segment if it occupies
+ * sequence space, where the ACK reflects our state.
+ *
+ * We can now skip the test for the RST flag since all
+ * paths to this code happen after packets containing
+ * RST have been dropped.
+ *
+ * In the SYN-RECEIVED state, don't send an ACK unless the
+ * segment we received passes the SYN-RECEIVED ACK test.
+ * If it fails send a RST. This breaks the loop in the
+ * "LAND" DoS attack, and also prevents an ACK storm
+ * between two listening ports that have been sent forged
+ * SYN segments, each with the source address of the other.
+ */
+ if (tp->t_state == TCPS_SYN_RECEIVED && (thflags & TH_ACK) &&
+ (SEQ_GT(tp->snd_una, th->th_ack) ||
+ SEQ_GT(th->th_ack, tp->snd_max)) ) {
+ rstreason = BANDLIM_RST_OPENPORT;
+ goto dropwithreset;
+ }
+#ifdef TCPDEBUG
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+#endif
+ TCP_PROBE3(debug__input, tp, th, mtod(m, const char *));
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ }
+ ti_locked = TI_UNLOCKED;
+
+ tp->t_flags |= TF_ACKNOW;
+ (void) tp->t_fb->tfb_tcp_output(tp);
+ INP_WUNLOCK(tp->t_inpcb);
+ m_freem(m);
+ return;
+
+dropwithreset:
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ }
+ ti_locked = TI_UNLOCKED;
+
+ if (tp != NULL) {
+ tcp_dropwithreset(m, th, tp, tlen, rstreason);
+ INP_WUNLOCK(tp->t_inpcb);
+ } else
+ tcp_dropwithreset(m, th, NULL, tlen, rstreason);
+ return;
+
+drop:
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ ti_locked = TI_UNLOCKED;
+ }
+#ifdef INVARIANTS
+ else
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+#endif
+
+ /*
+ * Drop space held by incoming segment and return.
+ */
+#ifdef TCPDEBUG
+ if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+#endif
+ TCP_PROBE3(debug__input, tp, th, mtod(m, const char *));
+ if (tp != NULL)
+ INP_WUNLOCK(tp->t_inpcb);
+ m_freem(m);
+}
+
+
+/*
+ * Do fast slow is a combination of the original
+ * tcp_dosegment and a split fastpath, one function
+ * for the fast-ack which also includes allowing fastpath
+ * for window advanced in sequence acks. And also a
+ * sub-function that handles the insequence data.
+ */
+void
+tcp_do_segment_fastslow(struct mbuf *m, struct tcphdr *th, struct socket *so,
+ struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos,
+ int ti_locked)
+{
+ int thflags;
+ u_long tiwin;
+ char *s;
+ int can_enter;
+ struct in_conninfo *inc;
+ struct tcpopt to;
+
+ thflags = th->th_flags;
+ tp->sackhint.last_sack_ack = 0;
+ inc = &tp->t_inpcb->inp_inc;
+ /*
+ * If this is either a state-changing packet or current state isn't
+ * established, we require a write lock on tcbinfo. Otherwise, we
+ * allow the tcbinfo to be in either alocked or unlocked, as the
+ * caller may have unnecessarily acquired a write lock due to a race.
+ */
+ if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 ||
+ tp->t_state != TCPS_ESTABLISHED) {
+ KASSERT(ti_locked == TI_RLOCKED, ("%s ti_locked %d for "
+ "SYN/FIN/RST/!EST", __func__, ti_locked));
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ } else {
+#ifdef INVARIANTS
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ } else {
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: EST "
+ "ti_locked: %d", __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ }
+#endif
+ }
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+ KASSERT(tp->t_state > TCPS_LISTEN, ("%s: TCPS_LISTEN",
+ __func__));
+ KASSERT(tp->t_state != TCPS_TIME_WAIT, ("%s: TCPS_TIME_WAIT",
+ __func__));
+
+ /*
+ * Segment received on connection.
+ * Reset idle time and keep-alive timer.
+ * XXX: This should be done after segment
+ * validation to ignore broken/spoofed segs.
+ */
+ tp->t_rcvtime = ticks;
+ if (TCPS_HAVEESTABLISHED(tp->t_state))
+ tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
+
+ /*
+ * Unscale the window into a 32-bit value.
+ * For the SYN_SENT state the scale is zero.
+ */
+ tiwin = th->th_win << tp->snd_scale;
+
+ /*
+ * TCP ECN processing.
+ */
+ if (tp->t_flags & TF_ECN_PERMIT) {
+ if (thflags & TH_CWR)
+ tp->t_flags &= ~TF_ECN_SND_ECE;
+ switch (iptos & IPTOS_ECN_MASK) {
+ case IPTOS_ECN_CE:
+ tp->t_flags |= TF_ECN_SND_ECE;
+ TCPSTAT_INC(tcps_ecn_ce);
+ break;
+ case IPTOS_ECN_ECT0:
+ TCPSTAT_INC(tcps_ecn_ect0);
+ break;
+ case IPTOS_ECN_ECT1:
+ TCPSTAT_INC(tcps_ecn_ect1);
+ break;
+ }
+ /* Congestion experienced. */
+ if (thflags & TH_ECE) {
+ cc_cong_signal(tp, th, CC_ECN);
+ }
+ }
+
+ /*
+ * Parse options on any incoming segment.
+ */
+ tcp_dooptions(&to, (u_char *)(th + 1),
+ (th->th_off << 2) - sizeof(struct tcphdr),
+ (thflags & TH_SYN) ? TO_SYN : 0);
+
+ /*
+ * If echoed timestamp is later than the current time,
+ * fall back to non RFC1323 RTT calculation. Normalize
+ * timestamp if syncookies were used when this connection
+ * was established.
+ */
+ if ((to.to_flags & TOF_TS) && (to.to_tsecr != 0)) {
+ to.to_tsecr -= tp->ts_offset;
+ if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks()))
+ to.to_tsecr = 0;
+ }
+ /*
+ * If timestamps were negotiated during SYN/ACK they should
+ * appear on every segment during this session and vice versa.
+ */
+ if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) {
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Timestamp missing, "
+ "no action\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+ if (!(tp->t_flags & TF_RCVD_TSTMP) && (to.to_flags & TOF_TS)) {
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Timestamp not expected, "
+ "no action\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+
+ /*
+ * Process options only when we get SYN/ACK back. The SYN case
+ * for incoming connections is handled in tcp_syncache.
+ * According to RFC1323 the window field in a SYN (i.e., a <SYN>
+ * or <SYN,ACK>) segment itself is never scaled.
+ * XXX this is traditional behavior, may need to be cleaned up.
+ */
+ if (tp->t_state == TCPS_SYN_SENT && (thflags & TH_SYN)) {
+ if ((to.to_flags & TOF_SCALE) &&
+ (tp->t_flags & TF_REQ_SCALE)) {
+ tp->t_flags |= TF_RCVD_SCALE;
+ tp->snd_scale = to.to_wscale;
+ }
+ /*
+ * Initial send window. It will be updated with
+ * the next incoming segment to the scaled value.
+ */
+ tp->snd_wnd = th->th_win;
+ if (to.to_flags & TOF_TS) {
+ tp->t_flags |= TF_RCVD_TSTMP;
+ tp->ts_recent = to.to_tsval;
+ tp->ts_recent_age = tcp_ts_getticks();
+ }
+ if (to.to_flags & TOF_MSS)
+ tcp_mss(tp, to.to_mss);
+ if ((tp->t_flags & TF_SACK_PERMIT) &&
+ (to.to_flags & TOF_SACKPERM) == 0)
+ tp->t_flags &= ~TF_SACK_PERMIT;
+ }
+ can_enter = 0;
+ if (__predict_true((tlen == 0))) {
+ /*
+ * The ack moved forward and we have a window (non-zero)
+ * <or>
+ * The ack did not move forward, but the window increased.
+ */
+ if (__predict_true((SEQ_GT(th->th_ack, tp->snd_una) && tiwin) ||
+ ((th->th_ack == tp->snd_una) && tiwin && (tiwin > tp->snd_wnd)))) {
+ can_enter = 1;
+ }
+ } else {
+ /*
+ * Data incoming, use the old entry criteria
+ * for fast-path with data.
+ */
+ if ((tiwin && tiwin == tp->snd_wnd)) {
+ can_enter = 1;
+ }
+ }
+ /*
+ * Header prediction: check for the two common cases
+ * of a uni-directional data xfer. If the packet has
+ * no control flags, is in-sequence, the window didn't
+ * change and we're not retransmitting, it's a
+ * candidate. If the length is zero and the ack moved
+ * forward, we're the sender side of the xfer. Just
+ * free the data acked & wake any higher level process
+ * that was blocked waiting for space. If the length
+ * is non-zero and the ack didn't move, we're the
+ * receiver side. If we're getting packets in-order
+ * (the reassembly queue is empty), add the data to
+ * the socket buffer and note that we need a delayed ack.
+ * Make sure that the hidden state-flags are also off.
+ * Since we check for TCPS_ESTABLISHED first, it can only
+ * be TH_NEEDSYN.
+ */
+ if (__predict_true(tp->t_state == TCPS_ESTABLISHED &&
+ th->th_seq == tp->rcv_nxt &&
+ (thflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
+ tp->snd_nxt == tp->snd_max &&
+ can_enter &&
+ ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&
+ LIST_EMPTY(&tp->t_segq) &&
+ ((to.to_flags & TOF_TS) == 0 ||
+ TSTMP_GEQ(to.to_tsval, tp->ts_recent)))) {
+ if (__predict_true((tlen == 0) &&
+ (SEQ_LEQ(th->th_ack, tp->snd_max) &&
+ !IN_RECOVERY(tp->t_flags) &&
+ (to.to_flags & TOF_SACK) == 0 &&
+ TAILQ_EMPTY(&tp->snd_holes)))) {
+ /* We are done */
+ tcp_do_fastack(m, th, so, tp, &to, drop_hdrlen, tlen,
+ ti_locked, tiwin);
+ return;
+ } else if ((tlen) &&
+ (th->th_ack == tp->snd_una &&
+ tlen <= sbspace(&so->so_rcv))) {
+ tcp_do_fastnewdata(m, th, so, tp, &to, drop_hdrlen, tlen,
+ ti_locked, tiwin);
+ /* We are done */
+ return;
+ }
+ }
+ tcp_do_slowpath(m, th, so, tp, &to, drop_hdrlen, tlen,
+ ti_locked, tiwin, thflags);
+}
+
+
+/*
+ * This subfunction is used to try to highly optimize the
+ * fast path. We again allow window updates that are
+ * in sequence to remain in the fast-path. We also add
+ * in the __predict's to attempt to help the compiler.
+ * Note that if we return a 0, then we can *not* process
+ * it and the caller should push the packet into the
+ * slow-path.
+ */
+static int
+tcp_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so,
+ struct tcpcb *tp, struct tcpopt *to, int drop_hdrlen, int tlen,
+ int ti_locked, u_long tiwin)
+{
+ int acked;
+ int winup_only=0;
+#ifdef TCPDEBUG
+ /*
+ * The size of tcp_saveipgen must be the size of the max ip header,
+ * now IPv6.
+ */
+ u_char tcp_saveipgen[IP6_HDR_LEN];
+ struct tcphdr tcp_savetcp;
+ short ostate = 0;
+#endif
+
+
+ if (__predict_false(SEQ_LEQ(th->th_ack, tp->snd_una))) {
+ /* Old ack, behind (or duplicate to) the last one rcv'd */
+ return (0);
+ }
+ if (__predict_false(th->th_ack == tp->snd_una) &&
+ __predict_false(tiwin <= tp->snd_wnd)) {
+ /* duplicate ack <or> a shrinking dup ack with shrinking window */
+ return (0);
+ }
+ if (__predict_false(tiwin == 0)) {
+ /* zero window */
+ return (0);
+ }
+ if (__predict_false(SEQ_GT(th->th_ack, tp->snd_max))) {
+ /* Above what we have sent? */
+ return (0);
+ }
+ if (__predict_false(tp->snd_nxt != tp->snd_max)) {
+ /* We are retransmitting */
+ return (0);
+ }
+ if (__predict_false(tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))) {
+ /* We need a SYN or a FIN, unlikely.. */
+ return (0);
+ }
+ if((to->to_flags & TOF_TS) && __predict_false(TSTMP_LT(to->to_tsval, tp->ts_recent))) {
+ /* Timestamp is behind .. old ack with seq wrap? */
+ return (0);
+ }
+ if (__predict_false(IN_RECOVERY(tp->t_flags))) {
+ /* Still recovering */
+ return (0);
+ }
+ if (__predict_false(to->to_flags & TOF_SACK)) {
+ /* Sack included in the ack.. */
+ return (0);
+ }
+ if (!TAILQ_EMPTY(&tp->snd_holes)) {
+ /* We have sack holes on our scoreboard */
+ return (0);
+ }
+ /* Ok if we reach here, we can process a fast-ack */
+
+ /* Did the window get updated? */
+ if (tiwin != tp->snd_wnd) {
+ /* keep track of pure window updates */
+ if (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) {
+ winup_only = 1;
+ TCPSTAT_INC(tcps_rcvwinupd);
+ }
+ tp->snd_wnd = tiwin;
+ tp->snd_wl1 = th->th_seq;
+ if (tp->snd_wnd > tp->max_sndwnd)
+ tp->max_sndwnd = tp->snd_wnd;
+ }
+ /*
+ * Pull snd_wl2 up to prevent seq wrap relative
+ * to th_ack.
+ */
+ tp->snd_wl2 = th->th_ack;
+ /*
+ * If last ACK falls within this segment's sequence numbers,
+ * record the timestamp.
+ * NOTE that the test is modified according to the latest
+ * proposal of the tcplw@cray.com list (Braden 1993/04/26).
+ */
+ if ((to->to_flags & TOF_TS) != 0 &&
+ SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
+ tp->ts_recent_age = tcp_ts_getticks();
+ tp->ts_recent = to->to_tsval;
+ }
+ /*
+ * This is a pure ack for outstanding data.
+ */
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
+ }
+ ti_locked = TI_UNLOCKED;
+
+ TCPSTAT_INC(tcps_predack);
+
+ /*
+ * "bad retransmit" recovery.
+ */
+ if (tp->t_rxtshift == 1 &&
+ tp->t_flags & TF_PREVVALID &&
+ (int)(ticks - tp->t_badrxtwin) < 0) {
+ cc_cong_signal(tp, th, CC_RTO_ERR);
+ }
+
+ /*
+ * Recalculate the transmit timer / rtt.
+ *
+ * Some boxes send broken timestamp replies
+ * during the SYN+ACK phase, ignore
+ * timestamps of 0 or we could calculate a
+ * huge RTT and blow up the retransmit timer.
+ */
+ if ((to->to_flags & TOF_TS) != 0 &&
+ to->to_tsecr) {
+ u_int t;
+
+ t = tcp_ts_getticks() - to->to_tsecr;
+ if (!tp->t_rttlow || tp->t_rttlow > t)
+ tp->t_rttlow = t;
+ tcp_xmit_timer(tp,
+ TCP_TS_TO_TICKS(t) + 1);
+ } else if (tp->t_rtttime &&
+ SEQ_GT(th->th_ack, tp->t_rtseq)) {
+ if (!tp->t_rttlow ||
+ tp->t_rttlow > ticks - tp->t_rtttime)
+ tp->t_rttlow = ticks - tp->t_rtttime;
+ tcp_xmit_timer(tp,
+ ticks - tp->t_rtttime);
+ }
+ if (winup_only == 0) {
+ acked = BYTES_THIS_ACK(tp, th);
+
+ /* Run HHOOK_TCP_ESTABLISHED_IN helper hooks. */
+ hhook_run_tcp_est_in(tp, th, to);
+
+ TCPSTAT_ADD(tcps_rcvackbyte, acked);
+ sbdrop(&so->so_snd, acked);
+ if (SEQ_GT(tp->snd_una, tp->snd_recover) &&
+ SEQ_LEQ(th->th_ack, tp->snd_recover))
+ tp->snd_recover = th->th_ack - 1;
+
+ /*
+ * Let the congestion control algorithm update
+ * congestion control related information. This
+ * typically means increasing the congestion
+ * window.
+ */
+ cc_ack_received(tp, th, CC_ACK);
+
+ tp->snd_una = th->th_ack;
+ tp->t_dupacks = 0;
+ m_freem(m);
+
+ /*
+ * If all outstanding data are acked, stop
+ * retransmit timer, otherwise restart timer
+ * using current (possibly backed-off) value.
+ * If process is waiting for space,
+ * wakeup/selwakeup/signal. If data
+ * are ready to send, let tcp_output
+ * decide between more output or persist.
+ */
+#ifdef TCPDEBUG
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_INPUT, ostate, tp,
+ (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+#endif
+ if (tp->snd_una == tp->snd_max)
+ tcp_timer_activate(tp, TT_REXMT, 0);
+ else if (!tcp_timer_active(tp, TT_PERSIST))
+ tcp_timer_activate(tp, TT_REXMT,
+ tp->t_rxtcur);
+ /* Wake up the socket if we have room to write more */
+ sowwakeup(so);
+ } else {
+ /*
+ * Window update only, just free the mbufs and
+ * send out whatever we can.
+ */
+ m_freem(m);
+ }
+ if (sbavail(&so->so_snd))
+ (void) tcp_output(tp);
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: check_delack ti_locked %d",
+ __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+
+ if (tp->t_flags & TF_DELACK) {
+ tp->t_flags &= ~TF_DELACK;
+ tcp_timer_activate(tp, TT_DELACK, tcp_delacktime);
+ }
+ INP_WUNLOCK(tp->t_inpcb);
+ return (1);
+}
+
+/*
+ * This tcp-do-segment concentrates on making the fastest
+ * ack processing path. It does not have a fast-path for
+ * data (it possibly could which would then eliminate the
+ * need for fast-slow above). For a content distributor having
+ * large outgoing elephants and very very little coming in
+ * having no fastpath for data does not really help (since you
+ * don't get much data in). The most important thing is
+ * processing ack's quickly and getting the rest of the data
+ * output to the peer as quickly as possible. This routine
+ * seems to be about an overall 3% faster then the old
+ * tcp_do_segment and keeps us in the fast-path for packets
+ * much more (by allowing window updates to also stay in the fastpath).
+ */
+void
+tcp_do_segment_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so,
+ struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos,
+ int ti_locked)
+{
+ int thflags;
+ u_long tiwin;
+ char *s;
+ struct in_conninfo *inc;
+ struct tcpopt to;
+
+ thflags = th->th_flags;
+ tp->sackhint.last_sack_ack = 0;
+ inc = &tp->t_inpcb->inp_inc;
+ /*
+ * If this is either a state-changing packet or current state isn't
+ * established, we require a write lock on tcbinfo. Otherwise, we
+ * allow the tcbinfo to be in either alocked or unlocked, as the
+ * caller may have unnecessarily acquired a write lock due to a race.
+ */
+ if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 ||
+ tp->t_state != TCPS_ESTABLISHED) {
+ KASSERT(ti_locked == TI_RLOCKED, ("%s ti_locked %d for "
+ "SYN/FIN/RST/!EST", __func__, ti_locked));
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ } else {
+#ifdef INVARIANTS
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ } else {
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: EST "
+ "ti_locked: %d", __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ }
+#endif
+ }
+ INP_WLOCK_ASSERT(tp->t_inpcb);
+ KASSERT(tp->t_state > TCPS_LISTEN, ("%s: TCPS_LISTEN",
+ __func__));
+ KASSERT(tp->t_state != TCPS_TIME_WAIT, ("%s: TCPS_TIME_WAIT",
+ __func__));
+
+ /*
+ * Segment received on connection.
+ * Reset idle time and keep-alive timer.
+ * XXX: This should be done after segment
+ * validation to ignore broken/spoofed segs.
+ */
+ tp->t_rcvtime = ticks;
+ if (TCPS_HAVEESTABLISHED(tp->t_state))
+ tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
+
+ /*
+ * Unscale the window into a 32-bit value.
+ * For the SYN_SENT state the scale is zero.
+ */
+ tiwin = th->th_win << tp->snd_scale;
+
+ /*
+ * TCP ECN processing.
+ */
+ if (tp->t_flags & TF_ECN_PERMIT) {
+ if (thflags & TH_CWR)
+ tp->t_flags &= ~TF_ECN_SND_ECE;
+ switch (iptos & IPTOS_ECN_MASK) {
+ case IPTOS_ECN_CE:
+ tp->t_flags |= TF_ECN_SND_ECE;
+ TCPSTAT_INC(tcps_ecn_ce);
+ break;
+ case IPTOS_ECN_ECT0:
+ TCPSTAT_INC(tcps_ecn_ect0);
+ break;
+ case IPTOS_ECN_ECT1:
+ TCPSTAT_INC(tcps_ecn_ect1);
+ break;
+ }
+ /* Congestion experienced. */
+ if (thflags & TH_ECE) {
+ cc_cong_signal(tp, th, CC_ECN);
+ }
+ }
+
+ /*
+ * Parse options on any incoming segment.
+ */
+ tcp_dooptions(&to, (u_char *)(th + 1),
+ (th->th_off << 2) - sizeof(struct tcphdr),
+ (thflags & TH_SYN) ? TO_SYN : 0);
+
+ /*
+ * If echoed timestamp is later than the current time,
+ * fall back to non RFC1323 RTT calculation. Normalize
+ * timestamp if syncookies were used when this connection
+ * was established.
+ */
+ if ((to.to_flags & TOF_TS) && (to.to_tsecr != 0)) {
+ to.to_tsecr -= tp->ts_offset;
+ if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks()))
+ to.to_tsecr = 0;
+ }
+ /*
+ * If timestamps were negotiated during SYN/ACK they should
+ * appear on every segment during this session and vice versa.
+ */
+ if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) {
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Timestamp missing, "
+ "no action\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+ if (!(tp->t_flags & TF_RCVD_TSTMP) && (to.to_flags & TOF_TS)) {
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
+ log(LOG_DEBUG, "%s; %s: Timestamp not expected, "
+ "no action\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+
+ /*
+ * Process options only when we get SYN/ACK back. The SYN case
+ * for incoming connections is handled in tcp_syncache.
+ * According to RFC1323 the window field in a SYN (i.e., a <SYN>
+ * or <SYN,ACK>) segment itself is never scaled.
+ * XXX this is traditional behavior, may need to be cleaned up.
+ */
+ if (tp->t_state == TCPS_SYN_SENT && (thflags & TH_SYN)) {
+ if ((to.to_flags & TOF_SCALE) &&
+ (tp->t_flags & TF_REQ_SCALE)) {
+ tp->t_flags |= TF_RCVD_SCALE;
+ tp->snd_scale = to.to_wscale;
+ }
+ /*
+ * Initial send window. It will be updated with
+ * the next incoming segment to the scaled value.
+ */
+ tp->snd_wnd = th->th_win;
+ if (to.to_flags & TOF_TS) {
+ tp->t_flags |= TF_RCVD_TSTMP;
+ tp->ts_recent = to.to_tsval;
+ tp->ts_recent_age = tcp_ts_getticks();
+ }
+ if (to.to_flags & TOF_MSS)
+ tcp_mss(tp, to.to_mss);
+ if ((tp->t_flags & TF_SACK_PERMIT) &&
+ (to.to_flags & TOF_SACKPERM) == 0)
+ tp->t_flags &= ~TF_SACK_PERMIT;
+ }
+ /*
+ * Header prediction: check for the two common cases
+ * of a uni-directional data xfer. If the packet has
+ * no control flags, is in-sequence, the window didn't
+ * change and we're not retransmitting, it's a
+ * candidate. If the length is zero and the ack moved
+ * forward, we're the sender side of the xfer. Just
+ * free the data acked & wake any higher level process
+ * that was blocked waiting for space. If the length
+ * is non-zero and the ack didn't move, we're the
+ * receiver side. If we're getting packets in-order
+ * (the reassembly queue is empty), add the data to
+ * the socket buffer and note that we need a delayed ack.
+ * Make sure that the hidden state-flags are also off.
+ * Since we check for TCPS_ESTABLISHED first, it can only
+ * be TH_NEEDSYN.
+ */
+ if (__predict_true(tp->t_state == TCPS_ESTABLISHED) &&
+ __predict_true(((to.to_flags & TOF_SACK) == 0)) &&
+ __predict_true(tlen == 0) &&
+ __predict_true((thflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK) &&
+ __predict_true(LIST_EMPTY(&tp->t_segq)) &&
+ __predict_true(th->th_seq == tp->rcv_nxt)) {
+ if (tcp_fastack(m, th, so, tp, &to, drop_hdrlen, tlen,
+ ti_locked, tiwin)) {
+ return;
+ }
+ }
+ tcp_do_slowpath(m, th, so, tp, &to, drop_hdrlen, tlen,
+ ti_locked, tiwin, thflags);
+}
+
+struct tcp_function_block __tcp_fastslow = {
+ "fastslow",
+ tcp_output,
+ tcp_do_segment_fastslow,
+ tcp_default_ctloutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0
+
+};
+
+struct tcp_function_block __tcp_fastack = {
+ "fastack",
+ tcp_output,
+ tcp_do_segment_fastack,
+ tcp_default_ctloutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0
+};
+
+static int
+tcp_addfastpaths(module_t mod, int type, void *data)
+{
+ int err=0;
+
+ switch (type) {
+ case MOD_LOAD:
+ err = register_tcp_functions(&__tcp_fastack, M_WAITOK);
+ if (err) {
+ printf("Failed to register fastack module -- err:%d\n", err);
+ return(err);
+ }
+ err = register_tcp_functions(&__tcp_fastslow, M_WAITOK);
+ if (err) {
+ printf("Failed to register fastslow module -- err:%d\n", err);
+ deregister_tcp_functions(&__tcp_fastack);
+ return(err);
+ }
+ break;
+ case MOD_QUIESCE:
+ if ((__tcp_fastslow.tfb_refcnt) ||( __tcp_fastack.tfb_refcnt)) {
+ return(EBUSY);
+ }
+ break;
+ case MOD_UNLOAD:
+ err = deregister_tcp_functions(&__tcp_fastack);
+ if (err == EBUSY)
+ break;
+ err = deregister_tcp_functions(&__tcp_fastslow);
+ if (err == EBUSY)
+ break;
+ err = 0;
+ break;
+ default:
+ return (EOPNOTSUPP);
+ }
+ return (err);
+}
+
+static moduledata_t new_tcp_fastpaths = {
+ .name = "tcp_fastpaths",
+ .evhand = tcp_addfastpaths,
+ .priv = 0
+};
+
+MODULE_VERSION(kern_tcpfastpaths, 1);
+DECLARE_MODULE(kern_tcpfastpaths, new_tcp_fastpaths, SI_SUB_PSEUDO, SI_ORDER_ANY);
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 29af766..00869a6 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/jail.h>
#include <sys/malloc.h>
+#include <sys/refcount.h>
#include <sys/mbuf.h>
#ifdef INET6
#include <sys/domain.h>
@@ -125,6 +126,8 @@ VNET_DEFINE(int, tcp_mssdflt) = TCP_MSS;
VNET_DEFINE(int, tcp_v6mssdflt) = TCP6_MSS;
#endif
+struct rwlock tcp_function_lock;
+
static int
sysctl_net_inet_tcp_mss_check(SYSCTL_HANDLER_ARGS)
{
@@ -236,6 +239,179 @@ static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th,
void *ip4hdr, const void *ip6hdr);
static void tcp_timer_discard(struct tcpcb *, uint32_t);
+
+static struct tcp_function_block tcp_def_funcblk = {
+ "default",
+ tcp_output,
+ tcp_do_segment,
+ tcp_default_ctloutput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0
+};
+
+struct tcp_funchead t_functions;
+static struct tcp_function_block *tcp_func_set_ptr = &tcp_def_funcblk;
+
+static struct tcp_function_block *
+find_tcp_functions_locked(struct tcp_function_set *fs)
+{
+ struct tcp_function *f;
+ struct tcp_function_block *blk=NULL;
+
+ TAILQ_FOREACH(f, &t_functions, tf_next) {
+ if (strcmp(f->tf_fb->tfb_tcp_block_name, fs->function_set_name) == 0) {
+ blk = f->tf_fb;
+ break;
+ }
+ }
+ return(blk);
+}
+
+static struct tcp_function_block *
+find_tcp_fb_locked(struct tcp_function_block *blk, struct tcp_function **s)
+{
+ struct tcp_function_block *rblk=NULL;
+ struct tcp_function *f;
+
+ TAILQ_FOREACH(f, &t_functions, tf_next) {
+ if (f->tf_fb == blk) {
+ rblk = blk;
+ if (s) {
+ *s = f;
+ }
+ break;
+ }
+ }
+ return (rblk);
+}
+
+struct tcp_function_block *
+find_and_ref_tcp_functions(struct tcp_function_set *fs)
+{
+ struct tcp_function_block *blk;
+
+ rw_rlock(&tcp_function_lock);
+ blk = find_tcp_functions_locked(fs);
+ if (blk)
+ refcount_acquire(&blk->tfb_refcnt);
+ rw_runlock(&tcp_function_lock);
+ return(blk);
+}
+
+struct tcp_function_block *
+find_and_ref_tcp_fb(struct tcp_function_block *blk)
+{
+ struct tcp_function_block *rblk;
+
+ rw_rlock(&tcp_function_lock);
+ rblk = find_tcp_fb_locked(blk, NULL);
+ if (rblk)
+ refcount_acquire(&rblk->tfb_refcnt);
+ rw_runlock(&tcp_function_lock);
+ return(rblk);
+}
+
+
+static int
+sysctl_net_inet_default_tcp_functions(SYSCTL_HANDLER_ARGS)
+{
+ int error=ENOENT;
+ struct tcp_function_set fs;
+ struct tcp_function_block *blk;
+
+ memset(&fs, 0, sizeof(fs));
+ rw_rlock(&tcp_function_lock);
+ blk = find_tcp_fb_locked(tcp_func_set_ptr, NULL);
+ if (blk) {
+ /* Found him */
+ strcpy(fs.function_set_name, blk->tfb_tcp_block_name);
+ fs.pcbcnt = blk->tfb_refcnt;
+ }
+ rw_runlock(&tcp_function_lock);
+ error = sysctl_handle_string(oidp, fs.function_set_name,
+ sizeof(fs.function_set_name), req);
+
+ /* Check for error or no change */
+ if (error != 0 || req->newptr == NULL)
+ return(error);
+
+ rw_wlock(&tcp_function_lock);
+ blk = find_tcp_functions_locked(&fs);
+ if ((blk == NULL) ||
+ (blk->tfb_flags & TCP_FUNC_BEING_REMOVED)) {
+ error = ENOENT;
+ goto done;
+ }
+ tcp_func_set_ptr = blk;
+done:
+ rw_wunlock(&tcp_function_lock);
+ return (error);
+}
+
+SYSCTL_PROC(_net_inet_tcp, OID_AUTO, functions_default,
+ CTLTYPE_STRING | CTLFLAG_RW,
+ NULL, 0, sysctl_net_inet_default_tcp_functions, "A",
+ "Set/get the default TCP functions");
+
+static int
+sysctl_net_inet_list_available(SYSCTL_HANDLER_ARGS)
+{
+ int error, cnt, linesz;
+ struct tcp_function *f;
+ char *buffer, *cp;
+ size_t bufsz, outsz;
+
+ cnt = 0;
+ rw_rlock(&tcp_function_lock);
+ TAILQ_FOREACH(f, &t_functions, tf_next) {
+ cnt++;
+ }
+ rw_runlock(&tcp_function_lock);
+
+ bufsz = (cnt+2) * (TCP_FUNCTION_NAME_LEN_MAX + 12) + 1;
+ buffer = malloc(bufsz, M_TEMP, M_WAITOK);
+
+ error = 0;
+ cp = buffer;
+
+ linesz = snprintf(cp, bufsz, "\n%-32s%c %s\n", "Stack", 'D', "PCB count");
+ cp += linesz;
+ bufsz -= linesz;
+ outsz = linesz;
+
+ rw_rlock(&tcp_function_lock);
+ TAILQ_FOREACH(f, &t_functions, tf_next) {
+ linesz = snprintf(cp, bufsz, "%-32s%c %u\n",
+ f->tf_fb->tfb_tcp_block_name,
+ (f->tf_fb == tcp_func_set_ptr) ? '*' : ' ',
+ f->tf_fb->tfb_refcnt);
+ if (linesz >= bufsz) {
+ error = EOVERFLOW;
+ break;
+ }
+ cp += linesz;
+ bufsz -= linesz;
+ outsz += linesz;
+ }
+ rw_runlock(&tcp_function_lock);
+ if (error == 0)
+ error = sysctl_handle_string(oidp, buffer, outsz + 1, req);
+ free(buffer, M_TEMP);
+ return (error);
+}
+
+SYSCTL_PROC(_net_inet_tcp, OID_AUTO, functions_available,
+ CTLTYPE_STRING|CTLFLAG_RD,
+ NULL, 0, sysctl_net_inet_list_available, "A",
+ "list available TCP Function sets");
+
/*
* Target size of TCP PCB hash tables. Must be a power of two.
*
@@ -263,6 +439,8 @@ static VNET_DEFINE(uma_zone_t, tcpcb_zone);
#define V_tcpcb_zone VNET(tcpcb_zone)
MALLOC_DEFINE(M_TCPLOG, "tcplog", "TCP address and flags print buffers");
+MALLOC_DEFINE(M_TCPFUNCTIONS, "tcpfunc", "TCP function set memory");
+
static struct mtx isn_mtx;
#define ISN_LOCK_INIT() mtx_init(&isn_mtx, "isn_mtx", NULL, MTX_DEF)
@@ -311,6 +489,96 @@ maketcp_hashsize(int size)
return (hashsize);
}
+int
+register_tcp_functions(struct tcp_function_block *blk, int wait)
+{
+ struct tcp_function_block *lblk;
+ struct tcp_function *n;
+ struct tcp_function_set fs;
+
+ if ((blk->tfb_tcp_output == NULL) ||
+ (blk->tfb_tcp_do_segment == NULL) ||
+ (blk->tfb_tcp_ctloutput == NULL) ||
+ (strlen(blk->tfb_tcp_block_name) == 0)) {
+ /*
+ * These functions are required and you
+ * need a name.
+ */
+ return (EINVAL);
+ }
+ if (blk->tfb_tcp_timer_stop_all ||
+ blk->tfb_tcp_timers_left ||
+ blk->tfb_tcp_timer_activate ||
+ blk->tfb_tcp_timer_active ||
+ blk->tfb_tcp_timer_stop) {
+ /*
+ * If you define one timer function you
+ * must have them all.
+ */
+ if ((blk->tfb_tcp_timer_stop_all == NULL) ||
+ (blk->tfb_tcp_timers_left == NULL) ||
+ (blk->tfb_tcp_timer_activate == NULL) ||
+ (blk->tfb_tcp_timer_active == NULL) ||
+ (blk->tfb_tcp_timer_stop == NULL)) {
+ return (EINVAL);
+ }
+ }
+ n = malloc(sizeof(struct tcp_function), M_TCPFUNCTIONS, wait);
+ if (n == NULL) {
+ return (ENOMEM);
+ }
+ n->tf_fb = blk;
+ strcpy(fs.function_set_name, blk->tfb_tcp_block_name);
+ rw_wlock(&tcp_function_lock);
+ lblk = find_tcp_functions_locked(&fs);
+ if (lblk) {
+ /* Duplicate name space not allowed */
+ rw_wunlock(&tcp_function_lock);
+ free(n, M_TCPFUNCTIONS);
+ return (EALREADY);
+ }
+ refcount_init(&blk->tfb_refcnt, 0);
+ blk->tfb_flags = 0;
+ TAILQ_INSERT_TAIL(&t_functions, n, tf_next);
+ rw_wunlock(&tcp_function_lock);
+ return(0);
+}
+
+int
+deregister_tcp_functions(struct tcp_function_block *blk)
+{
+ struct tcp_function_block *lblk;
+ struct tcp_function *f;
+ int error=ENOENT;
+
+ if (strcmp(blk->tfb_tcp_block_name, "default") == 0) {
+ /* You can't un-register the default */
+ return (EPERM);
+ }
+ rw_wlock(&tcp_function_lock);
+ if (blk == tcp_func_set_ptr) {
+ /* You can't free the current default */
+ rw_wunlock(&tcp_function_lock);
+ return (EBUSY);
+ }
+ if (blk->tfb_refcnt) {
+ /* Still tcb attached, mark it. */
+ blk->tfb_flags |= TCP_FUNC_BEING_REMOVED;
+ rw_wunlock(&tcp_function_lock);
+ return (EBUSY);
+ }
+ lblk = find_tcp_fb_locked(blk, &f);
+ if (lblk) {
+ /* Found */
+ TAILQ_REMOVE(&t_functions, f, tf_next);
+ f->tf_fb = NULL;
+ free(f, M_TCPFUNCTIONS);
+ error = 0;
+ }
+ rw_wunlock(&tcp_function_lock);
+ return (error);
+}
+
void
tcp_init(void)
{
@@ -325,7 +593,10 @@ tcp_init(void)
if (hhook_head_register(HHOOK_TYPE_TCP, HHOOK_TCP_EST_OUT,
&V_tcp_hhh[HHOOK_TCP_EST_OUT], HHOOK_NOWAIT|HHOOK_HEADISINVNET) != 0)
printf("%s: WARNING: unable to register helper hook\n", __func__);
-
+ /* Setup the tcp function block list */
+ TAILQ_INIT(&t_functions);
+ rw_init_flags(&tcp_function_lock, "tcp_func_lock" , 0);
+ register_tcp_functions(&tcp_def_funcblk, M_WAITOK);
hashsize = TCBHASHSIZE;
TUNABLE_INT_FETCH(tcbhash_tuneable, &hashsize);
if (hashsize == 0) {
@@ -768,7 +1039,13 @@ tcp_newtcpcb(struct inpcb *inp)
tp->ccv = &tm->ccv;
tp->ccv->type = IPPROTO_TCP;
tp->ccv->ccvc.tcp = tp;
-
+ rw_rlock(&tcp_function_lock);
+ tp->t_fb = tcp_func_set_ptr;
+ refcount_acquire(&tp->t_fb->tfb_refcnt);
+ rw_runlock(&tcp_function_lock);
+ if (tp->t_fb->tfb_tcp_fb_init) {
+ (*tp->t_fb->tfb_tcp_fb_init)(tp);
+ }
/*
* Use the current system default CC algorithm.
*/
@@ -779,12 +1056,18 @@ tcp_newtcpcb(struct inpcb *inp)
if (CC_ALGO(tp)->cb_init != NULL)
if (CC_ALGO(tp)->cb_init(tp->ccv) > 0) {
+ if (tp->t_fb->tfb_tcp_fb_fini)
+ (*tp->t_fb->tfb_tcp_fb_fini)(tp);
+ refcount_release(&tp->t_fb->tfb_refcnt);
uma_zfree(V_tcpcb_zone, tm);
return (NULL);
}
tp->osd = &tm->osd;
if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) {
+ if (tp->t_fb->tfb_tcp_fb_fini)
+ (*tp->t_fb->tfb_tcp_fb_fini)(tp);
+ refcount_release(&tp->t_fb->tfb_refcnt);
uma_zfree(V_tcpcb_zone, tm);
return (NULL);
}
@@ -925,7 +1208,7 @@ tcp_drop(struct tcpcb *tp, int errno)
if (TCPS_HAVERCVDSYN(tp->t_state)) {
tcp_state_change(tp, TCPS_CLOSED);
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
TCPSTAT_INC(tcps_drops);
} else
TCPSTAT_INC(tcps_conndrops);
@@ -960,6 +1243,10 @@ tcp_discardcb(struct tcpcb *tp)
tcp_timer_stop(tp, TT_KEEP);
tcp_timer_stop(tp, TT_2MSL);
tcp_timer_stop(tp, TT_DELACK);
+ if (tp->t_fb->tfb_tcp_timer_stop_all) {
+ /* Call the stop-all function of the methods */
+ tp->t_fb->tfb_tcp_timer_stop_all(tp);
+ }
/*
* If we got enough samples through the srtt filter,
@@ -1044,6 +1331,14 @@ tcp_discardcb(struct tcpcb *tp)
inp->inp_ppcb = NULL;
if ((tp->t_timers->tt_flags & TT_MASK) == 0) {
/* We own the last reference on tcpcb, let's free it. */
+ if ((tp->t_fb->tfb_tcp_timers_left) &&
+ (tp->t_fb->tfb_tcp_timers_left(tp))) {
+ /* Some fb timers left running! */
+ return;
+ }
+ if (tp->t_fb->tfb_tcp_fb_fini)
+ (*tp->t_fb->tfb_tcp_fb_fini)(tp);
+ refcount_release(&tp->t_fb->tfb_refcnt);
tp->t_inpcb = NULL;
uma_zfree(V_tcpcb_zone, tp);
released = in_pcbrele_wlocked(inp);
@@ -1105,6 +1400,14 @@ tcp_timer_discard(struct tcpcb *tp, uint32_t timer_type)
tp->t_timers->tt_flags &= ~timer_type;
if ((tp->t_timers->tt_flags & TT_MASK) == 0) {
/* We own the last reference on this tcpcb, let's free it. */
+ if ((tp->t_fb->tfb_tcp_timers_left) &&
+ (tp->t_fb->tfb_tcp_timers_left(tp))) {
+ /* Some fb timers left running! */
+ goto leave;
+ }
+ if (tp->t_fb->tfb_tcp_fb_fini)
+ (*tp->t_fb->tfb_tcp_fb_fini)(tp);
+ refcount_release(&tp->t_fb->tfb_refcnt);
tp->t_inpcb = NULL;
uma_zfree(V_tcpcb_zone, tp);
if (in_pcbrele_wlocked(inp)) {
@@ -1113,6 +1416,7 @@ tcp_timer_discard(struct tcpcb *tp, uint32_t timer_type)
return;
}
}
+leave:
INP_WUNLOCK(inp);
INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
@@ -1865,7 +2169,7 @@ tcp_mtudisc(struct inpcb *inp, int mtuoffer)
tp->snd_recover = tp->snd_max;
if (tp->t_flags & TF_SACK_PERMIT)
EXIT_FASTRECOVERY(tp->t_flags);
- tcp_output(tp);
+ tp->t_fb->tfb_tcp_output(tp);
}
#ifdef INET
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index e5a38d5..8ad1b22 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/hash.h>
+#include <sys/refcount.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/limits.h>
@@ -626,6 +627,7 @@ done:
static struct socket *
syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
{
+ struct tcp_function_block *blk;
struct inpcb *inp = NULL;
struct socket *so;
struct tcpcb *tp;
@@ -817,6 +819,26 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
tp->irs = sc->sc_irs;
tcp_rcvseqinit(tp);
tcp_sendseqinit(tp);
+ blk = sototcpcb(lso)->t_fb;
+ if (blk != tp->t_fb) {
+ /*
+ * Our parents t_fb was not the default,
+ * we need to release our ref on tp->t_fb and
+ * pickup one on the new entry.
+ */
+ struct tcp_function_block *rblk;
+
+ rblk = find_and_ref_tcp_fb(blk);
+ KASSERT(rblk != NULL,
+ ("cannot find blk %p out of syncache?", blk));
+ if (tp->t_fb->tfb_tcp_fb_fini)
+ (*tp->t_fb->tfb_tcp_fb_fini)(tp);
+ refcount_release(&tp->t_fb->tfb_refcnt);
+ tp->t_fb = rblk;
+ if (tp->t_fb->tfb_tcp_fb_init) {
+ (*tp->t_fb->tfb_tcp_fb_init)(tp);
+ }
+ }
tp->snd_wl1 = sc->sc_irs;
tp->snd_max = tp->iss + 1;
tp->snd_nxt = tp->iss + 1;
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index d129586..6a24ce7 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -292,7 +292,7 @@ tcp_timer_delack(void *xtp)
tp->t_flags |= TF_ACKNOW;
TCPSTAT_INC(tcps_delack);
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
INP_WUNLOCK(inp);
CURVNET_RESTORE();
}
@@ -543,7 +543,7 @@ tcp_timer_persist(void *xtp)
}
tcp_setpersist(tp);
tp->t_flags |= TF_FORCEDATA;
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
tp->t_flags &= ~TF_FORCEDATA;
out:
@@ -798,7 +798,7 @@ tcp_timer_rexmt(void * xtp)
cc_cong_signal(tp, NULL, CC_RTO);
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
out:
#ifdef TCPDEBUG
@@ -858,6 +858,10 @@ tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta)
f_reset = TT_2MSL_RST;
break;
default:
+ if (tp->t_fb->tfb_tcp_timer_activate) {
+ tp->t_fb->tfb_tcp_timer_activate(tp, timer_type, delta);
+ return;
+ }
panic("tp %p bad timer_type %#x", tp, timer_type);
}
if (delta == 0) {
@@ -904,6 +908,9 @@ tcp_timer_active(struct tcpcb *tp, uint32_t timer_type)
t_callout = &tp->t_timers->tt_2msl;
break;
default:
+ if (tp->t_fb->tfb_tcp_timer_active) {
+ return(tp->t_fb->tfb_tcp_timer_active(tp, timer_type));
+ }
panic("tp %p bad timer_type %#x", tp, timer_type);
}
return callout_active(t_callout);
@@ -945,6 +952,14 @@ tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type)
f_reset = TT_2MSL_RST;
break;
default:
+ if (tp->t_fb->tfb_tcp_timer_stop) {
+ /*
+ * XXXrrs we need to look at this with the
+ * stop case below (flags).
+ */
+ tp->t_fb->tfb_tcp_timer_stop(tp, timer_type);
+ return;
+ }
panic("tp %p bad timer_type %#x", tp, timer_type);
}
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index a1f8a0c..42e2ea7 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/limits.h>
#include <sys/malloc.h>
+#include <sys/refcount.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/mbuf.h>
@@ -509,7 +510,7 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto out;
#endif
tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
- error = tcp_output(tp);
+ error = tp->t_fb->tfb_tcp_output(tp);
out:
TCPDEBUG2(PRU_CONNECT);
INP_WUNLOCK(inp);
@@ -579,7 +580,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
(error = tcp_offload_connect(so, nam)) == 0)
goto out;
#endif
- error = tcp_output(tp);
+ error = tp->t_fb->tfb_tcp_output(tp);
goto out;
}
#endif
@@ -597,7 +598,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto out;
#endif
tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
- error = tcp_output(tp);
+ error = tp->t_fb->tfb_tcp_output(tp);
out:
TCPDEBUG2(PRU_CONNECT);
@@ -773,7 +774,7 @@ tcp_usr_shutdown(struct socket *so)
socantsendmore(so);
tcp_usrclosed(tp);
if (!(inp->inp_flags & INP_DROPPED))
- error = tcp_output(tp);
+ error = tp->t_fb->tfb_tcp_output(tp);
out:
TCPDEBUG2(PRU_SHUTDOWN);
@@ -809,7 +810,7 @@ tcp_usr_rcvd(struct socket *so, int flags)
tcp_offload_rcvd(tp);
else
#endif
- tcp_output(tp);
+ tp->t_fb->tfb_tcp_output(tp);
out:
TCPDEBUG2(PRU_RCVD);
@@ -911,7 +912,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
!(flags & PRUS_NOTREADY)) {
if (flags & PRUS_MORETOCOME)
tp->t_flags |= TF_MORETOCOME;
- error = tcp_output(tp);
+ error = tp->t_fb->tfb_tcp_output(tp);
if (flags & PRUS_MORETOCOME)
tp->t_flags &= ~TF_MORETOCOME;
}
@@ -961,7 +962,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
tp->snd_up = tp->snd_una + sbavail(&so->so_snd);
if (!(flags & PRUS_NOTREADY)) {
tp->t_flags |= TF_FORCEDATA;
- error = tcp_output(tp);
+ error = tp->t_fb->tfb_tcp_output(tp);
tp->t_flags &= ~TF_FORCEDATA;
}
}
@@ -997,7 +998,7 @@ tcp_usr_ready(struct socket *so, struct mbuf *m, int count)
error = sbready(&so->so_snd, m, count);
SOCKBUF_UNLOCK(&so->so_snd);
if (error == 0)
- error = tcp_output(tp);
+ error = tp->t_fb->tfb_tcp_output(tp);
INP_WUNLOCK(inp);
return (error);
@@ -1349,13 +1350,11 @@ tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti)
int
tcp_ctloutput(struct socket *so, struct sockopt *sopt)
{
- int error, opt, optval;
- u_int ui;
+ int error;
struct inpcb *inp;
struct tcpcb *tp;
- struct tcp_info ti;
- char buf[TCP_CA_NAME_MAX];
- struct cc_algo *algo;
+ struct tcp_function_block *blk;
+ struct tcp_function_set fsn;
error = 0;
inp = sotoinpcb(so);
@@ -1383,7 +1382,83 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
INP_WUNLOCK(inp);
return (ECONNRESET);
}
+ tp = intotcpcb(inp);
+ /*
+ * Protect the TCP option TCP_FUNCTION_BLK so
+ * that a sub-function can *never* overwrite this.
+ */
+ if ((sopt->sopt_dir == SOPT_SET) &&
+ (sopt->sopt_name == TCP_FUNCTION_BLK)) {
+ INP_WUNLOCK(inp);
+ error = sooptcopyin(sopt, &fsn, sizeof fsn,
+ sizeof fsn);
+ if (error)
+ return (error);
+ INP_WLOCK_RECHECK(inp);
+ if (tp->t_state != TCPS_CLOSED) {
+ /*
+ * The user has advanced the state
+ * past the initial point, we can't
+ * switch since we are down the road
+ * and a new set of functions may
+ * not be compatibile.
+ */
+ INP_WUNLOCK(inp);
+ return(EINVAL);
+ }
+ blk = find_and_ref_tcp_functions(&fsn);
+ if (blk == NULL) {
+ INP_WUNLOCK(inp);
+ return (ENOENT);
+ }
+ if (tp->t_fb != blk) {
+ if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) {
+ refcount_release(&blk->tfb_refcnt);
+ INP_WUNLOCK(inp);
+ return (ENOENT);
+ }
+ /*
+ * Release the old refcnt, the
+ * lookup acquires a ref on the
+ * new one.
+ */
+ if (tp->t_fb->tfb_tcp_fb_fini)
+ (*tp->t_fb->tfb_tcp_fb_fini)(tp);
+ refcount_release(&tp->t_fb->tfb_refcnt);
+ tp->t_fb = blk;
+ if (tp->t_fb->tfb_tcp_fb_init) {
+ (*tp->t_fb->tfb_tcp_fb_init)(tp);
+ }
+ }
+#ifdef TCP_OFFLOAD
+ if (tp->t_flags & TF_TOE) {
+ tcp_offload_ctloutput(tp, sopt->sopt_dir,
+ sopt->sopt_name);
+ }
+#endif
+ INP_WUNLOCK(inp);
+ return (error);
+ } else if ((sopt->sopt_dir == SOPT_GET) &&
+ (sopt->sopt_name == TCP_FUNCTION_BLK)) {
+ strcpy(fsn.function_set_name, tp->t_fb->tfb_tcp_block_name);
+ fsn.pcbcnt = tp->t_fb->tfb_refcnt;
+ INP_WUNLOCK(inp);
+ error = sooptcopyout(sopt, &fsn, sizeof fsn);
+ return (error);
+ }
+ /* Pass in the INP locked, called must unlock it */
+ return (tp->t_fb->tfb_tcp_ctloutput(so, sopt, inp, tp));
+}
+int
+tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct tcpcb *tp)
+{
+ int error, opt, optval;
+ u_int ui;
+ struct tcp_info ti;
+ struct cc_algo *algo;
+ char buf[TCP_CA_NAME_MAX];
+
switch (sopt->sopt_dir) {
case SOPT_SET:
switch (sopt->sopt_name) {
@@ -1451,7 +1526,7 @@ unlock_and_done:
else if (tp->t_flags & TF_NOPUSH) {
tp->t_flags &= ~TF_NOPUSH;
if (TCPS_HAVEESTABLISHED(tp->t_state))
- error = tcp_output(tp);
+ error = tp->t_fb->tfb_tcp_output(tp);
}
goto unlock_and_done;
@@ -1770,7 +1845,7 @@ tcp_disconnect(struct tcpcb *tp)
sbflush(&so->so_rcv);
tcp_usrclosed(tp);
if (!(inp->inp_flags & INP_DROPPED))
- tcp_output(tp);
+ tp->t_fb->tfb_tcp_output(tp);
}
}
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index bf8347a..2b3954a 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -89,6 +89,52 @@ struct tcptemp {
#define tcp6cb tcpcb /* for KAME src sync over BSD*'s */
+/*
+ * TODO: We yet need to brave plowing in
+ * to tcp_input() and the pru_usrreq() block.
+ * Right now these go to the old standards which
+ * are somewhat ok, but in the long term may
+ * need to be changed. If we do tackle tcp_input()
+ * then we need to get rid of the tcp_do_segment()
+ * function below.
+ */
+/* Flags for tcp functions */
+#define TCP_FUNC_BEING_REMOVED 0x01 /* Can no longer be referenced */
+struct tcpcb;
+struct inpcb;
+struct sockopt;
+struct socket;
+
+struct tcp_function_block {
+ char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX];
+ int (*tfb_tcp_output)(struct tcpcb *);
+ void (*tfb_tcp_do_segment)(struct mbuf *, struct tcphdr *,
+ struct socket *, struct tcpcb *,
+ int, int, uint8_t,
+ int);
+ int (*tfb_tcp_ctloutput)(struct socket *so, struct sockopt *sopt,
+ struct inpcb *inp, struct tcpcb *tp);
+ /* Optional memory allocation/free routine */
+ void (*tfb_tcp_fb_init)(struct tcpcb *);
+ void (*tfb_tcp_fb_fini)(struct tcpcb *);
+ /* Optional timers, must define all if you define one */
+ int (*tfb_tcp_timer_stop_all)(struct tcpcb *);
+ int (*tfb_tcp_timers_left)(struct tcpcb *);
+ void (*tfb_tcp_timer_activate)(struct tcpcb *,
+ uint32_t, u_int);
+ int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t);
+ void (*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t);
+ volatile uint32_t tfb_refcnt;
+ uint32_t tfb_flags;
+};
+
+struct tcp_function {
+ TAILQ_ENTRY(tcp_function) tf_next;
+ struct tcp_function_block *tf_fb;
+};
+
+TAILQ_HEAD(tcp_funchead, tcp_function);
+
/*
* Tcp control block, one per tcp; fields:
* Organized for 16 byte cacheline efficiency.
@@ -207,9 +253,10 @@ struct tcpcb {
u_int t_tsomaxsegsize; /* TSO maximum segment size in bytes */
u_int t_pmtud_saved_maxopd; /* pre-blackhole MSS */
u_int t_flags2; /* More tcpcb flags storage */
-
uint32_t t_ispare[8]; /* 5 UTO, 3 TBD */
- void *t_pspare2[4]; /* 1 TCP_SIGNATURE, 3 TBD */
+ struct tcp_function_block *t_fb;/* TCP function call block */
+ void *t_fb_ptr; /* Pointer to t_fb specific data */
+ void *t_pspare2[2]; /* 1 TCP_SIGNATURE, 1 TBD */
#if defined(_KERNEL) && defined(TCPPCAP)
struct mbufq t_inpkts; /* List of saved input packets. */
struct mbufq t_outpkts; /* List of saved output packets. */
@@ -534,6 +581,8 @@ struct tcpstat {
#define tcps_rcvmemdrop tcps_rcvreassfull /* compat */
#ifdef _KERNEL
+#define TI_UNLOCKED 1
+#define TI_RLOCKED 2
#include <sys/counter.h>
VNET_PCPUSTAT_DECLARE(struct tcpstat, tcpstat); /* tcp statistics */
@@ -684,7 +733,32 @@ char *tcp_log_vain(struct in_conninfo *, struct tcphdr *, void *,
int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *);
void tcp_reass_global_init(void);
void tcp_reass_flush(struct tcpcb *);
+void tcp_dooptions(struct tcpopt *, u_char *, int, int);
+void tcp_dropwithreset(struct mbuf *, struct tcphdr *,
+ struct tcpcb *, int, int);
+void tcp_pulloutofband(struct socket *,
+ struct tcphdr *, struct mbuf *, int);
+void tcp_xmit_timer(struct tcpcb *, int);
+void tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *);
+void cc_ack_received(struct tcpcb *tp, struct tcphdr *th,
+ uint16_t type);
+void cc_conn_init(struct tcpcb *tp);
+void cc_post_recovery(struct tcpcb *tp, struct tcphdr *th);
+void cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type);
+void hhook_run_tcp_est_in(struct tcpcb *tp,
+ struct tcphdr *th, struct tcpopt *to);
+
int tcp_input(struct mbuf **, int *, int);
+void tcp_do_segment(struct mbuf *, struct tcphdr *,
+ struct socket *, struct tcpcb *, int, int, uint8_t,
+ int);
+
+int register_tcp_functions(struct tcp_function_block *blk, int wait);
+int deregister_tcp_functions(struct tcp_function_block *blk);
+struct tcp_function_block *find_and_ref_tcp_functions(struct tcp_function_set *fs);
+struct tcp_function_block *find_and_ref_tcp_fb(struct tcp_function_block *blk);
+int tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct tcpcb *tp);
+
u_long tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *);
u_long tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *);
void tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *,
@@ -752,8 +826,6 @@ int tcp_newreno(struct tcpcb *, struct tcphdr *);
u_long tcp_seq_subtract(u_long, u_long );
int tcp_compute_pipe(struct tcpcb *);
-void cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type);
-
static inline void
tcp_fields_to_host(struct tcphdr *th)
{
diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c
index 87d8856..ef82f8a 100644
--- a/sys/netinet/toecore.c
+++ b/sys/netinet/toecore.c
@@ -509,7 +509,7 @@ toe_connect_failed(struct toedev *tod, struct inpcb *inp, int err)
KASSERT(!(tp->t_flags & TF_TOE),
("%s: tp %p still offloaded.", __func__, tp));
tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
- (void) tcp_output(tp);
+ (void) tp->t_fb->tfb_tcp_output(tp);
} else {
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index e815a96..c2f4397 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2359,13 +2359,20 @@ in6_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
sdl->sdl_index = ifp->if_index;
sdl->sdl_type = ifp->if_type;
bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
- ndpc.rtm.rtm_rmx.rmx_expire = lle->la_expire +
- lle->lle_remtime / hz;
+ if (lle->la_expire != 0)
+ ndpc.rtm.rtm_rmx.rmx_expire = lle->la_expire +
+ lle->lle_remtime / hz +
+ time_second - time_uptime;
ndpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
if (lle->la_flags & LLE_STATIC)
ndpc.rtm.rtm_flags |= RTF_STATIC;
if (lle->la_flags & LLE_IFADDR)
ndpc.rtm.rtm_flags |= RTF_PINNED;
+ if (lle->ln_router != 0)
+ ndpc.rtm.rtm_flags |= RTF_GATEWAY;
+ ndpc.rtm.rtm_rmx.rmx_pksent = lle->la_asked;
+ /* Store state in rmx_weight value */
+ ndpc.rtm.rtm_rmx.rmx_state = lle->ln_state;
ndpc.rtm.rtm_index = ifp->if_index;
error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc));
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index d0bcc9d..d2a457d 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -209,6 +209,7 @@ nd6_ifnet_link_event(void *arg __unused, struct ifnet *ifp, int linkstate)
if (linkstate == LINK_STATE_UP && V_nd6_on_link)
nd6_na_output_unsolicited(ifp);
}
+
void
nd6_init(void)
{
@@ -1748,7 +1749,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
if (ln->la_expire == 0)
nbi->expire = 0;
else
- nbi->expire = ln->la_expire +
+ nbi->expire = ln->la_expire + ln->lle_remtime / hz +
(time_second - time_uptime);
LLE_RUNLOCK(ln);
break;
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 0717e11..07ad0cc 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -1646,7 +1646,8 @@ nd6_na_output_unsolicited(struct ifnet *ifp)
i++;
if (i == cnt)
break;
- DELAY(ann1->delay);
+ /* XXX DELAY needs to be done in taskqueue to avoid stalling. */
+ //DELAY(ann1->delay);
}
free(head, M_TEMP);
}
diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c
index 0f0a2ff..d76b280 100644
--- a/sys/security/mac/mac_framework.c
+++ b/sys/security/mac/mac_framework.c
@@ -93,11 +93,11 @@ __FBSDID("$FreeBSD$");
SDT_PROVIDER_DEFINE(mac);
SDT_PROVIDER_DEFINE(mac_framework);
-SDT_PROBE_DEFINE2(mac, kernel, policy, modevent, "int",
+SDT_PROBE_DEFINE2(mac, , policy, modevent, "int",
"struct mac_policy_conf *");
-SDT_PROBE_DEFINE1(mac, kernel, policy, register,
+SDT_PROBE_DEFINE1(mac, , policy, register,
"struct mac_policy_conf *");
-SDT_PROBE_DEFINE1(mac, kernel, policy, unregister,
+SDT_PROBE_DEFINE1(mac, , policy, unregister,
"struct mac_policy_conf *");
/*
@@ -444,7 +444,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
(*(mpc->mpc_ops->mpo_init))(mpc);
mac_policy_update();
- SDT_PROBE(mac, kernel, policy, register, mpc, 0, 0, 0, 0);
+ SDT_PROBE1(mac, , policy, register, mpc);
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
mpc->mpc_name);
@@ -491,7 +491,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
mac_policy_update();
mac_policy_xunlock();
- SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0);
+ SDT_PROBE1(mac, , policy, unregister, mpc);
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
mpc->mpc_name);
@@ -517,7 +517,7 @@ mac_policy_modevent(module_t mod, int type, void *data)
}
#endif
- SDT_PROBE(mac, kernel, policy, modevent, type, mpc, 0, 0, 0);
+ SDT_PROBE2(mac, , policy, modevent, type, mpc);
switch (type) {
case MOD_LOAD:
if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h
index ceb1e87..2ecffc6 100644
--- a/sys/security/mac/mac_internal.h
+++ b/sys/security/mac/mac_internal.h
@@ -74,35 +74,35 @@ SDT_PROVIDER_DECLARE(mac); /* MAC Framework-level events. */
SDT_PROVIDER_DECLARE(mac_framework); /* Entry points to MAC. */
#define MAC_CHECK_PROBE_DEFINE4(name, arg0, arg1, arg2, arg3) \
- SDT_PROBE_DEFINE5(mac_framework, kernel, name, mac__check__err, \
+ SDT_PROBE_DEFINE5(mac_framework, , name, mac__check__err, \
"int", arg0, arg1, arg2, arg3); \
- SDT_PROBE_DEFINE5(mac_framework, kernel, name, mac__check__ok, \
+ SDT_PROBE_DEFINE5(mac_framework, , name, mac__check__ok, \
"int", arg0, arg1, arg2, arg3);
#define MAC_CHECK_PROBE_DEFINE3(name, arg0, arg1, arg2) \
- SDT_PROBE_DEFINE4(mac_framework, kernel, name, mac__check__err, \
+ SDT_PROBE_DEFINE4(mac_framework, , name, mac__check__err, \
"int", arg0, arg1, arg2); \
- SDT_PROBE_DEFINE4(mac_framework, kernel, name, mac__check__ok, \
+ SDT_PROBE_DEFINE4(mac_framework, , name, mac__check__ok, \
"int", arg0, arg1, arg2);
#define MAC_CHECK_PROBE_DEFINE2(name, arg0, arg1) \
- SDT_PROBE_DEFINE3(mac_framework, kernel, name, mac__check__err, \
+ SDT_PROBE_DEFINE3(mac_framework, , name, mac__check__err, \
"int", arg0, arg1); \
- SDT_PROBE_DEFINE3(mac_framework, kernel, name, mac__check__ok, \
+ SDT_PROBE_DEFINE3(mac_framework, , name, mac__check__ok, \
"int", arg0, arg1);
#define MAC_CHECK_PROBE_DEFINE1(name, arg0) \
- SDT_PROBE_DEFINE2(mac_framework, kernel, name, mac__check__err, \
+ SDT_PROBE_DEFINE2(mac_framework, , name, mac__check__err, \
"int", arg0); \
- SDT_PROBE_DEFINE2(mac_framework, kernel, name, mac__check__ok, \
+ SDT_PROBE_DEFINE2(mac_framework, , name, mac__check__ok, \
"int", arg0);
#define MAC_CHECK_PROBE4(name, error, arg0, arg1, arg2, arg3) do { \
if (error) { \
- SDT_PROBE(mac_framework, kernel, name, mac__check__err, \
+ SDT_PROBE5(mac_framework, , name, mac__check__err, \
error, arg0, arg1, arg2, arg3); \
} else { \
- SDT_PROBE(mac_framework, kernel, name, mac__check__ok, \
+ SDT_PROBE5(mac_framework, , name, mac__check__ok, \
0, arg0, arg1, arg2, arg3); \
} \
} while (0)
@@ -116,18 +116,18 @@ SDT_PROVIDER_DECLARE(mac_framework); /* Entry points to MAC. */
#endif
#define MAC_GRANT_PROBE_DEFINE2(name, arg0, arg1) \
- SDT_PROBE_DEFINE3(mac_framework, kernel, name, mac__grant__err, \
+ SDT_PROBE_DEFINE3(mac_framework, , name, mac__grant__err, \
"int", arg0, arg1); \
- SDT_PROBE_DEFINE3(mac_framework, kernel, name, mac__grant__ok, \
+ SDT_PROBE_DEFINE3(mac_framework, , name, mac__grant__ok, \
"int", arg0, arg1);
#define MAC_GRANT_PROBE2(name, error, arg0, arg1) do { \
if (error) { \
- SDT_PROBE(mac_framework, kernel, name, mac__grant__err, \
- error, arg0, arg1, 0, 0); \
+ SDT_PROBE3(mac_framework, , name, mac__grant__err, \
+ error, arg0, arg1); \
} else { \
- SDT_PROBE(mac_framework, kernel, name, mac__grant__ok, \
- error, arg0, arg1, 0, 0); \
+ SDT_PROBE3(mac_framework, , name, mac__grant__ok, \
+ error, arg0, arg1); \
} \
} while (0)
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index 75b41f3..c85b88f 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -122,14 +122,13 @@ struct buf {
struct ucred *b_rcred; /* Read credentials reference. */
struct ucred *b_wcred; /* Write credentials reference. */
union {
- TAILQ_ENTRY(buf) bu_freelist; /* (Q) */
+ TAILQ_ENTRY(buf) b_freelist; /* (Q) */
struct {
- void (*pg_iodone)(void *, vm_page_t *, int, int);
- int pg_reqpage;
- } bu_pager;
- } b_union;
-#define b_freelist b_union.bu_freelist
-#define b_pager b_union.bu_pager
+ void (*b_pgiodone)(void *, vm_page_t *, int, int);
+ int b_pgbefore;
+ int b_pgafter;
+ };
+ };
union cluster_info {
TAILQ_HEAD(cluster_list_head, buf) cluster_head;
TAILQ_ENTRY(buf) cluster_entry;
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index fe78fb4..d5b88eb 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -38,18 +38,18 @@ struct rlimit;
struct sysent;
struct thread;
struct ksiginfo;
+struct syscall_args;
+
+enum systrace_probe_t {
+ SYSTRACE_ENTRY,
+ SYSTRACE_RETURN,
+};
typedef int sy_call_t(struct thread *, void *);
-/* Used by the machine dependent syscall() code. */
-typedef void (*systrace_probe_func_t)(u_int32_t, int, struct sysent *, void *,
- int);
-
-/*
- * Used by loaded syscalls to convert arguments to a DTrace array
- * of 64-bit arguments.
- */
-typedef void (*systrace_args_func_t)(int, void *, u_int64_t *, int *);
+typedef void (*systrace_probe_func_t)(struct syscall_args *,
+ enum systrace_probe_t, int);
+typedef void (*systrace_args_func_t)(int, void *, uint64_t *, int *);
extern systrace_probe_func_t systrace_probe_func;
@@ -84,7 +84,6 @@ struct sysent { /* system call table */
struct image_params;
struct __sigset;
-struct syscall_args;
struct trapframe;
struct vnode;
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 2ee63f2..7706b25 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -605,6 +605,8 @@ struct vnode;
typedef int (*vn_get_ino_t)(struct mount *, void *, int, struct vnode **);
+int bnoreuselist(struct bufv *bufv, struct bufobj *bo, daddr_t startn,
+ daddr_t endn);
/* cache_* may belong in namei.h. */
void cache_changesize(int newhashsize);
#define cache_enter(dvp, vp, cnp) \
diff --git a/sys/vm/default_pager.c b/sys/vm/default_pager.c
index 98dee45..f334cd7 100644
--- a/sys/vm/default_pager.c
+++ b/sys/vm/default_pager.c
@@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$");
static vm_object_t default_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
vm_ooffset_t, struct ucred *);
static void default_pager_dealloc(vm_object_t);
-static int default_pager_getpages(vm_object_t, vm_page_t *, int, int);
+static int default_pager_getpages(vm_object_t, vm_page_t *, int, int *, int *);
static void default_pager_putpages(vm_object_t, vm_page_t *, int,
boolean_t, int *);
static boolean_t default_pager_haspage(vm_object_t, vm_pindex_t, int *,
@@ -122,13 +122,11 @@ default_pager_dealloc(object)
* see a vm_page with assigned swap here.
*/
static int
-default_pager_getpages(object, m, count, reqpage)
- vm_object_t object;
- vm_page_t *m;
- int count;
- int reqpage;
+default_pager_getpages(vm_object_t object, vm_page_t *m, int count,
+ int *rbehind, int *rahead)
{
- return VM_PAGER_FAIL;
+
+ return (VM_PAGER_FAIL);
}
/*
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index a0446be..5473081 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -59,7 +59,7 @@ static void dev_pager_init(void);
static vm_object_t dev_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
vm_ooffset_t, struct ucred *);
static void dev_pager_dealloc(vm_object_t);
-static int dev_pager_getpages(vm_object_t, vm_page_t *, int, int);
+static int dev_pager_getpages(vm_object_t, vm_page_t *, int, int *, int *);
static void dev_pager_putpages(vm_object_t, vm_page_t *, int, int, int *);
static boolean_t dev_pager_haspage(vm_object_t, vm_pindex_t, int *, int *);
static void dev_pager_free_page(vm_object_t object, vm_page_t m);
@@ -257,28 +257,33 @@ dev_pager_dealloc(vm_object_t object)
}
static int
-dev_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int reqpage)
+dev_pager_getpages(vm_object_t object, vm_page_t *ma, int count, int *rbehind,
+ int *rahead)
{
int error;
+ /* Since our haspage reports zero after/before, the count is 1. */
+ KASSERT(count == 1, ("%s: count %d", __func__, count));
VM_OBJECT_ASSERT_WLOCKED(object);
error = object->un_pager.devp.ops->cdev_pg_fault(object,
- IDX_TO_OFF(ma[reqpage]->pindex), PROT_READ, &ma[reqpage]);
+ IDX_TO_OFF(ma[0]->pindex), PROT_READ, &ma[0]);
VM_OBJECT_ASSERT_WLOCKED(object);
- vm_pager_free_nonreq(object, ma, reqpage, count, TRUE);
-
if (error == VM_PAGER_OK) {
KASSERT((object->type == OBJT_DEVICE &&
- (ma[reqpage]->oflags & VPO_UNMANAGED) != 0) ||
+ (ma[0]->oflags & VPO_UNMANAGED) != 0) ||
(object->type == OBJT_MGTDEVICE &&
- (ma[reqpage]->oflags & VPO_UNMANAGED) == 0),
- ("Wrong page type %p %p", ma[reqpage], object));
+ (ma[0]->oflags & VPO_UNMANAGED) == 0),
+ ("Wrong page type %p %p", ma[0], object));
if (object->type == OBJT_DEVICE) {
TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist,
- ma[reqpage], plinks.q);
+ ma[0], plinks.q);
}
+ if (rbehind)
+ *rbehind = 0;
+ if (rahead)
+ *rahead = 0;
}
return (error);
diff --git a/sys/vm/phys_pager.c b/sys/vm/phys_pager.c
index 885a451..02e819e 100644
--- a/sys/vm/phys_pager.c
+++ b/sys/vm/phys_pager.c
@@ -139,7 +139,8 @@ phys_pager_dealloc(vm_object_t object)
* Fill as many pages as vm_fault has allocated for us.
*/
static int
-phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
+phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
+ int *rahead)
{
int i;
@@ -154,14 +155,11 @@ phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
("phys_pager_getpages: partially valid page %p", m[i]));
KASSERT(m[i]->dirty == 0,
("phys_pager_getpages: dirty page %p", m[i]));
- /* The requested page must remain busy, the others not. */
- if (i == reqpage) {
- vm_page_lock(m[i]);
- vm_page_flash(m[i]);
- vm_page_unlock(m[i]);
- } else
- vm_page_xunbusy(m[i]);
}
+ if (rbehind)
+ *rbehind = 0;
+ if (rahead)
+ *rahead = 0;
return (VM_PAGER_OK);
}
diff --git a/sys/vm/sg_pager.c b/sys/vm/sg_pager.c
index 23ebd3a..26aa1d3 100644
--- a/sys/vm/sg_pager.c
+++ b/sys/vm/sg_pager.c
@@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$");
static vm_object_t sg_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
vm_ooffset_t, struct ucred *);
static void sg_pager_dealloc(vm_object_t);
-static int sg_pager_getpages(vm_object_t, vm_page_t *, int, int);
+static int sg_pager_getpages(vm_object_t, vm_page_t *, int, int *, int *);
static void sg_pager_putpages(vm_object_t, vm_page_t *, int,
boolean_t, int *);
static boolean_t sg_pager_haspage(vm_object_t, vm_pindex_t, int *,
@@ -135,7 +135,8 @@ sg_pager_dealloc(vm_object_t object)
}
static int
-sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
+sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
+ int *rahead)
{
struct sglist *sg;
vm_page_t m_paddr, page;
@@ -145,11 +146,13 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
size_t space;
int i;
+ /* Since our haspage reports zero after/before, the count is 1. */
+ KASSERT(count == 1, ("%s: count %d", __func__, count));
VM_OBJECT_ASSERT_WLOCKED(object);
sg = object->handle;
memattr = object->memattr;
VM_OBJECT_WUNLOCK(object);
- offset = m[reqpage]->pindex;
+ offset = m[0]->pindex;
/*
* Lookup the physical address of the requested page. An initial
@@ -178,26 +181,23 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
}
/* Return a fake page for the requested page. */
- KASSERT(!(m[reqpage]->flags & PG_FICTITIOUS),
+ KASSERT(!(m[0]->flags & PG_FICTITIOUS),
("backing page for SG is fake"));
/* Construct a new fake page. */
page = vm_page_getfake(paddr, memattr);
VM_OBJECT_WLOCK(object);
TAILQ_INSERT_TAIL(&object->un_pager.sgp.sgp_pglist, page, plinks.q);
-
- /* Free the original pages and insert this fake page into the object. */
- for (i = 0; i < count; i++) {
- if (i == reqpage &&
- vm_page_replace(page, object, offset) != m[i])
- panic("sg_pager_getpages: invalid place replacement");
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
- m[reqpage] = page;
+ if (vm_page_replace(page, object, offset) != m[0])
+ panic("sg_pager_getpages: invalid place replacement");
+ m[0] = page;
page->valid = VM_PAGE_BITS_ALL;
+ if (rbehind)
+ *rbehind = 0;
+ if (rahead)
+ *rahead = 0;
+
return (VM_PAGER_OK);
}
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 0bd4883..f243eca 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -357,9 +357,10 @@ static vm_object_t
swap_pager_alloc(void *handle, vm_ooffset_t size,
vm_prot_t prot, vm_ooffset_t offset, struct ucred *);
static void swap_pager_dealloc(vm_object_t object);
-static int swap_pager_getpages(vm_object_t, vm_page_t *, int, int);
-static int swap_pager_getpages_async(vm_object_t, vm_page_t *, int, int,
- pgo_getpages_iodone_t, void *);
+static int swap_pager_getpages(vm_object_t, vm_page_t *, int, int *,
+ int *);
+static int swap_pager_getpages_async(vm_object_t, vm_page_t *, int, int *,
+ int *, pgo_getpages_iodone_t, void *);
static void swap_pager_putpages(vm_object_t, vm_page_t *, int, boolean_t, int *);
static boolean_t
swap_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, int *after);
@@ -413,16 +414,6 @@ static void swp_pager_meta_free(vm_object_t, vm_pindex_t, daddr_t);
static void swp_pager_meta_free_all(vm_object_t);
static daddr_t swp_pager_meta_ctl(vm_object_t, vm_pindex_t, int);
-static void
-swp_pager_free_nrpage(vm_page_t m)
-{
-
- vm_page_lock(m);
- if (m->wire_count == 0)
- vm_page_free(m);
- vm_page_unlock(m);
-}
-
/*
* SWP_SIZECHECK() - update swap_pager_full indication
*
@@ -1103,16 +1094,12 @@ swap_pager_unswapped(vm_page_t m)
* left busy, but the others adjusted.
*/
static int
-swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
+swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
+ int *rahead)
{
struct buf *bp;
- vm_page_t mreq;
- int i;
- int j;
daddr_t blk;
- mreq = m[reqpage];
-
/*
* Calculate range to retrieve. The pages have already been assigned
* their swapblks. We require a *contiguous* range but we know it to
@@ -1122,45 +1109,18 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
*
* The swp_*() calls must be made with the object locked.
*/
- blk = swp_pager_meta_ctl(mreq->object, mreq->pindex, 0);
+ blk = swp_pager_meta_ctl(m[0]->object, m[0]->pindex, 0);
- for (i = reqpage - 1; i >= 0; --i) {
- daddr_t iblk;
-
- iblk = swp_pager_meta_ctl(m[i]->object, m[i]->pindex, 0);
- if (blk != iblk + (reqpage - i))
- break;
- }
- ++i;
-
- for (j = reqpage + 1; j < count; ++j) {
- daddr_t jblk;
-
- jblk = swp_pager_meta_ctl(m[j]->object, m[j]->pindex, 0);
- if (blk != jblk - (j - reqpage))
- break;
- }
-
- /*
- * free pages outside our collection range. Note: we never free
- * mreq, it must remain busy throughout.
- */
- if (0 < i || j < count) {
- int k;
-
- for (k = 0; k < i; ++k)
- swp_pager_free_nrpage(m[k]);
- for (k = j; k < count; ++k)
- swp_pager_free_nrpage(m[k]);
- }
-
- /*
- * Return VM_PAGER_FAIL if we have nothing to do. Return mreq
- * still busy, but the others unbusied.
- */
if (blk == SWAPBLK_NONE)
return (VM_PAGER_FAIL);
+#ifdef INVARIANTS
+ for (int i = 0; i < count; i++)
+ KASSERT(blk + i ==
+ swp_pager_meta_ctl(m[i]->object, m[i]->pindex, 0),
+ ("%s: range is not contiguous", __func__));
+#endif
+
/*
* Getpbuf() can sleep.
*/
@@ -1175,21 +1135,16 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
bp->b_iodone = swp_pager_async_iodone;
bp->b_rcred = crhold(thread0.td_ucred);
bp->b_wcred = crhold(thread0.td_ucred);
- bp->b_blkno = blk - (reqpage - i);
- bp->b_bcount = PAGE_SIZE * (j - i);
- bp->b_bufsize = PAGE_SIZE * (j - i);
- bp->b_pager.pg_reqpage = reqpage - i;
+ bp->b_blkno = blk;
+ bp->b_bcount = PAGE_SIZE * count;
+ bp->b_bufsize = PAGE_SIZE * count;
+ bp->b_npages = count;
VM_OBJECT_WLOCK(object);
- {
- int k;
-
- for (k = i; k < j; ++k) {
- bp->b_pages[k - i] = m[k];
- m[k]->oflags |= VPO_SWAPINPROG;
- }
+ for (int i = 0; i < count; i++) {
+ bp->b_pages[i] = m[i];
+ m[i]->oflags |= VPO_SWAPINPROG;
}
- bp->b_npages = j - i;
PCPU_INC(cnt.v_swapin);
PCPU_ADD(cnt.v_swappgsin, bp->b_npages);
@@ -1221,8 +1176,8 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
* is set in the meta-data.
*/
VM_OBJECT_WLOCK(object);
- while ((mreq->oflags & VPO_SWAPINPROG) != 0) {
- mreq->oflags |= VPO_SWAPSLEEP;
+ while ((m[0]->oflags & VPO_SWAPINPROG) != 0) {
+ m[0]->oflags |= VPO_SWAPSLEEP;
PCPU_INC(cnt.v_intrans);
if (VM_OBJECT_SLEEP(object, &object->paging_in_progress, PSWP,
"swread", hz * 20)) {
@@ -1233,15 +1188,18 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
}
/*
- * mreq is left busied after completion, but all the other pages
- * are freed. If we had an unrecoverable read error the page will
- * not be valid.
+ * If we had an unrecoverable read error pages will not be valid.
*/
- if (mreq->valid != VM_PAGE_BITS_ALL) {
- return (VM_PAGER_ERROR);
- } else {
- return (VM_PAGER_OK);
- }
+ for (int i = 0; i < count; i++)
+ if (m[i]->valid != VM_PAGE_BITS_ALL)
+ return (VM_PAGER_ERROR);
+
+ if (rbehind)
+ *rbehind = 0;
+ if (rahead)
+ *rahead = 0;
+
+ return (VM_PAGER_OK);
/*
* A final note: in a low swap situation, we cannot deallocate swap
@@ -1259,11 +1217,11 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
*/
static int
swap_pager_getpages_async(vm_object_t object, vm_page_t *m, int count,
- int reqpage, pgo_getpages_iodone_t iodone, void *arg)
+ int *rbehind, int *rahead, pgo_getpages_iodone_t iodone, void *arg)
{
int r, error;
- r = swap_pager_getpages(object, m, count, reqpage);
+ r = swap_pager_getpages(object, m, count, rbehind, rahead);
VM_OBJECT_WUNLOCK(object);
switch (r) {
case VM_PAGER_OK:
@@ -1527,33 +1485,11 @@ swp_pager_async_iodone(struct buf *bp)
*/
if (bp->b_iocmd == BIO_READ) {
/*
- * When reading, reqpage needs to stay
- * locked for the parent, but all other
- * pages can be freed. We still want to
- * wakeup the parent waiting on the page,
- * though. ( also: pg_reqpage can be -1 and
- * not match anything ).
- *
- * We have to wake specifically requested pages
- * up too because we cleared VPO_SWAPINPROG and
- * someone may be waiting for that.
- *
* NOTE: for reads, m->dirty will probably
* be overridden by the original caller of
* getpages so don't play cute tricks here.
*/
m->valid = 0;
- if (i != bp->b_pager.pg_reqpage)
- swp_pager_free_nrpage(m);
- else {
- vm_page_lock(m);
- vm_page_flash(m);
- vm_page_unlock(m);
- }
- /*
- * If i == bp->b_pager.pg_reqpage, do not wake
- * the page up. The caller needs to.
- */
} else {
/*
* If a write error occurs, reactivate page
@@ -1575,38 +1511,12 @@ swp_pager_async_iodone(struct buf *bp)
* want to do that anyway, but it was an optimization
* that existed in the old swapper for a time before
* it got ripped out due to precisely this problem.
- *
- * If not the requested page then deactivate it.
- *
- * Note that the requested page, reqpage, is left
- * busied, but we still have to wake it up. The
- * other pages are released (unbusied) by
- * vm_page_xunbusy().
*/
KASSERT(!pmap_page_is_mapped(m),
("swp_pager_async_iodone: page %p is mapped", m));
- m->valid = VM_PAGE_BITS_ALL;
KASSERT(m->dirty == 0,
("swp_pager_async_iodone: page %p is dirty", m));
-
- /*
- * We have to wake specifically requested pages
- * up too because we cleared VPO_SWAPINPROG and
- * could be waiting for it in getpages. However,
- * be sure to not unbusy getpages specifically
- * requested page - getpages expects it to be
- * left busy.
- */
- if (i != bp->b_pager.pg_reqpage) {
- vm_page_lock(m);
- vm_page_deactivate(m);
- vm_page_unlock(m);
- vm_page_xunbusy(m);
- } else {
- vm_page_lock(m);
- vm_page_flash(m);
- vm_page_unlock(m);
- }
+ m->valid = VM_PAGE_BITS_ALL;
} else {
/*
* For write success, clear the dirty
@@ -1727,7 +1637,7 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex)
return;
}
- if (swap_pager_getpages(object, &m, 1, 0) != VM_PAGER_OK)
+ if (swap_pager_getpages(object, &m, 1, NULL, NULL) != VM_PAGER_OK)
panic("swap_pager_force_pagein: read from swap failed");/*XXX*/
vm_object_pip_wakeup(object);
vm_page_dirty(m);
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 6990d12..a7e3d37 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -107,13 +107,8 @@ __FBSDID("$FreeBSD$");
#define PFBAK 4
#define PFFOR 4
-static int vm_fault_additional_pages(vm_page_t, int, int, vm_page_t *, int *);
-
-#define VM_FAULT_READ_BEHIND 8
#define VM_FAULT_READ_DEFAULT (1 + VM_FAULT_READ_AHEAD_INIT)
#define VM_FAULT_READ_MAX (1 + VM_FAULT_READ_AHEAD_MAX)
-#define VM_FAULT_NINCR (VM_FAULT_READ_MAX / VM_FAULT_READ_BEHIND)
-#define VM_FAULT_SUM (VM_FAULT_NINCR * (VM_FAULT_NINCR + 1) / 2)
#define VM_FAULT_DONTNEED_MIN 1048576
@@ -133,7 +128,7 @@ struct faultstate {
static void vm_fault_dontneed(const struct faultstate *fs, vm_offset_t vaddr,
int ahead);
static void vm_fault_prefault(const struct faultstate *fs, vm_offset_t addra,
- int faultcount, int reqpage);
+ int backward, int forward);
static inline void
release_page(struct faultstate *fs)
@@ -288,11 +283,10 @@ vm_fault_hold(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
int fault_flags, vm_page_t *m_hold)
{
vm_prot_t prot;
- int alloc_req, era, faultcount, nera, reqpage, result;
+ int alloc_req, era, faultcount, nera, result;
boolean_t growstack, is_first_object_locked, wired;
int map_generation;
vm_object_t next_object;
- vm_page_t marray[VM_FAULT_READ_MAX];
int hardfault;
struct faultstate fs;
struct vnode *vp;
@@ -303,7 +297,7 @@ vm_fault_hold(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
growstack = TRUE;
PCPU_INC(cnt.v_vm_faults);
fs.vp = NULL;
- faultcount = reqpage = 0;
+ faultcount = 0;
RetryFault:;
@@ -389,7 +383,7 @@ RetryFault:;
FALSE);
VM_OBJECT_RUNLOCK(fs.first_object);
if (!wired)
- vm_fault_prefault(&fs, vaddr, 0, 0);
+ vm_fault_prefault(&fs, vaddr, PFBAK, PFFOR);
vm_map_lookup_done(fs.map, fs.entry);
curthread->td_ru.ru_minflt++;
return (KERN_SUCCESS);
@@ -652,36 +646,13 @@ vnode_locked:
("vm_fault: vnode-backed object mapped by system map"));
/*
- * now we find out if any other pages should be paged
- * in at this time this routine checks to see if the
- * pages surrounding this fault reside in the same
- * object as the page for this fault. If they do,
- * then they are faulted in also into the object. The
- * array "marray" returned contains an array of
- * vm_page_t structs where one of them is the
- * vm_page_t passed to the routine. The reqpage
- * return value is the index into the marray for the
- * vm_page_t passed to the routine.
- *
- * fs.m plus the additional pages are exclusive busied.
+ * Page in the requested page and hint the pager,
+ * that it may bring up surrounding pages.
*/
- faultcount = vm_fault_additional_pages(
- fs.m, behind, ahead, marray, &reqpage);
-
- rv = faultcount ?
- vm_pager_get_pages(fs.object, marray, faultcount,
- reqpage) : VM_PAGER_FAIL;
-
+ rv = vm_pager_get_pages(fs.object, &fs.m, 1,
+ &behind, &ahead);
if (rv == VM_PAGER_OK) {
- /*
- * Found the page. Leave it busy while we play
- * with it.
- *
- * Pager could have changed the page. Pager
- * is responsible for disposition of old page
- * if moved.
- */
- fs.m = marray[reqpage];
+ faultcount = behind + 1 + ahead;
hardfault++;
break; /* break to PAGE HAS BEEN FOUND */
}
@@ -965,16 +936,13 @@ vnode_locked:
}
/*
* If the page was filled by a pager, update the map entry's
- * last read offset. Since the pager does not return the
- * actual set of pages that it read, this update is based on
- * the requested set. Typically, the requested and actual
- * sets are the same.
+ * last read offset.
*
* XXX The following assignment modifies the map
* without holding a write lock on it.
*/
if (hardfault)
- fs.entry->next_read = fs.pindex + faultcount - reqpage;
+ fs.entry->next_read = fs.pindex + ahead + 1;
vm_fault_dirty(fs.entry, fs.m, prot, fault_type, fault_flags, TRUE);
vm_page_assert_xbusied(fs.m);
@@ -997,7 +965,9 @@ vnode_locked:
fault_type | (wired ? PMAP_ENTER_WIRED : 0), 0);
if (faultcount != 1 && (fault_flags & VM_FAULT_WIRE) == 0 &&
wired == 0)
- vm_fault_prefault(&fs, vaddr, faultcount, reqpage);
+ vm_fault_prefault(&fs, vaddr,
+ faultcount > 0 ? behind : PFBAK,
+ faultcount > 0 ? ahead : PFFOR);
VM_OBJECT_WLOCK(fs.object);
vm_page_lock(fs.m);
@@ -1114,7 +1084,7 @@ vm_fault_dontneed(const struct faultstate *fs, vm_offset_t vaddr, int ahead)
*/
static void
vm_fault_prefault(const struct faultstate *fs, vm_offset_t addra,
- int faultcount, int reqpage)
+ int backward, int forward)
{
pmap_t pmap;
vm_map_entry_t entry;
@@ -1122,19 +1092,12 @@ vm_fault_prefault(const struct faultstate *fs, vm_offset_t addra,
vm_offset_t addr, starta;
vm_pindex_t pindex;
vm_page_t m;
- int backward, forward, i;
+ int i;
pmap = fs->map->pmap;
if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace))
return;
- if (faultcount > 0) {
- backward = reqpage;
- forward = faultcount - reqpage - 1;
- } else {
- backward = PFBAK;
- forward = PFFOR;
- }
entry = fs->entry;
starta = addra - backward * PAGE_SIZE;
@@ -1465,133 +1428,6 @@ again:
}
}
-
-/*
- * This routine checks around the requested page for other pages that
- * might be able to be faulted in. This routine brackets the viable
- * pages for the pages to be paged in.
- *
- * Inputs:
- * m, rbehind, rahead
- *
- * Outputs:
- * marray (array of vm_page_t), reqpage (index of requested page)
- *
- * Return value:
- * number of pages in marray
- */
-static int
-vm_fault_additional_pages(m, rbehind, rahead, marray, reqpage)
- vm_page_t m;
- int rbehind;
- int rahead;
- vm_page_t *marray;
- int *reqpage;
-{
- int i,j;
- vm_object_t object;
- vm_pindex_t pindex, startpindex, endpindex, tpindex;
- vm_page_t rtm;
- int cbehind, cahead;
-
- VM_OBJECT_ASSERT_WLOCKED(m->object);
-
- object = m->object;
- pindex = m->pindex;
- cbehind = cahead = 0;
-
- /*
- * if the requested page is not available, then give up now
- */
- if (!vm_pager_has_page(object, pindex, &cbehind, &cahead)) {
- return 0;
- }
-
- if ((cbehind == 0) && (cahead == 0)) {
- *reqpage = 0;
- marray[0] = m;
- return 1;
- }
-
- if (rahead > cahead) {
- rahead = cahead;
- }
-
- if (rbehind > cbehind) {
- rbehind = cbehind;
- }
-
- /*
- * scan backward for the read behind pages -- in memory
- */
- if (pindex > 0) {
- if (rbehind > pindex) {
- rbehind = pindex;
- startpindex = 0;
- } else {
- startpindex = pindex - rbehind;
- }
-
- if ((rtm = TAILQ_PREV(m, pglist, listq)) != NULL &&
- rtm->pindex >= startpindex)
- startpindex = rtm->pindex + 1;
-
- /* tpindex is unsigned; beware of numeric underflow. */
- for (i = 0, tpindex = pindex - 1; tpindex >= startpindex &&
- tpindex < pindex; i++, tpindex--) {
-
- rtm = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL |
- VM_ALLOC_IFNOTCACHED);
- if (rtm == NULL) {
- /*
- * Shift the allocated pages to the
- * beginning of the array.
- */
- for (j = 0; j < i; j++) {
- marray[j] = marray[j + tpindex + 1 -
- startpindex];
- }
- break;
- }
-
- marray[tpindex - startpindex] = rtm;
- }
- } else {
- startpindex = 0;
- i = 0;
- }
-
- marray[i] = m;
- /* page offset of the required page */
- *reqpage = i;
-
- tpindex = pindex + 1;
- i++;
-
- /*
- * scan forward for the read ahead pages
- */
- endpindex = tpindex + rahead;
- if ((rtm = TAILQ_NEXT(m, listq)) != NULL && rtm->pindex < endpindex)
- endpindex = rtm->pindex;
- if (endpindex > object->size)
- endpindex = object->size;
-
- for (; tpindex < endpindex; i++, tpindex++) {
-
- rtm = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL |
- VM_ALLOC_IFNOTCACHED);
- if (rtm == NULL) {
- break;
- }
-
- marray[i] = rtm;
- }
-
- /* return number of pages */
- return i;
-}
-
/*
* Block entry into the machine-independent layer's page fault handler by
* the calling thread. Subsequent calls to vm_fault() by that thread will
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
index f00dce1..e1538db 100644
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -238,7 +238,7 @@ vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset)
pindex = OFF_TO_IDX(offset);
m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL);
if (m->valid != VM_PAGE_BITS_ALL) {
- rv = vm_pager_get_pages(object, &m, 1, 0);
+ rv = vm_pager_get_pages(object, &m, 1, NULL, NULL);
if (rv != VM_PAGER_OK) {
vm_page_lock(m);
vm_page_free(m);
@@ -567,37 +567,37 @@ vm_thread_swapin(struct thread *td)
{
vm_object_t ksobj;
vm_page_t ma[KSTACK_MAX_PAGES];
- int i, j, pages, rv;
+ int pages;
pages = td->td_kstack_pages;
ksobj = td->td_kstack_obj;
VM_OBJECT_WLOCK(ksobj);
- for (i = 0; i < pages; i++)
+ for (int i = 0; i < pages; i++)
ma[i] = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL |
VM_ALLOC_WIRED);
- for (i = 0; i < pages; i++) {
- if (ma[i]->valid != VM_PAGE_BITS_ALL) {
- vm_page_assert_xbusied(ma[i]);
- vm_object_pip_add(ksobj, 1);
- for (j = i + 1; j < pages; j++) {
- if (ma[j]->valid != VM_PAGE_BITS_ALL)
- vm_page_assert_xbusied(ma[j]);
- if (ma[j]->valid == VM_PAGE_BITS_ALL)
- break;
- }
- rv = vm_pager_get_pages(ksobj, ma + i, j - i, 0);
- if (rv != VM_PAGER_OK)
- panic("vm_thread_swapin: cannot get kstack for proc: %d",
- td->td_proc->p_pid);
- /*
- * All pages in the array are in place, due to the
- * pager is always the swap pager, which doesn't
- * free or remove wired non-req pages from object.
- */
- vm_object_pip_wakeup(ksobj);
- vm_page_xunbusy(ma[i]);
- } else if (vm_page_xbusied(ma[i]))
+ for (int i = 0; i < pages;) {
+ int j, a, count, rv;
+
+ vm_page_assert_xbusied(ma[i]);
+ if (ma[i]->valid == VM_PAGE_BITS_ALL) {
vm_page_xunbusy(ma[i]);
+ i++;
+ continue;
+ }
+ vm_object_pip_add(ksobj, 1);
+ for (j = i + 1; j < pages; j++)
+ if (ma[j]->valid == VM_PAGE_BITS_ALL)
+ break;
+ rv = vm_pager_has_page(ksobj, ma[i]->pindex, NULL, &a);
+ KASSERT(rv == 1, ("%s: missing page %p", __func__, ma[i]));
+ count = min(a + 1, j - i);
+ rv = vm_pager_get_pages(ksobj, ma + i, count, NULL, NULL);
+ KASSERT(rv == VM_PAGER_OK, ("%s: cannot get kstack for proc %d",
+ __func__, td->td_proc->p_pid));
+ vm_object_pip_wakeup(ksobj);
+ for (j = i; j < i + count; j++)
+ vm_page_xunbusy(ma[j]);
+ i += count;
}
VM_OBJECT_WUNLOCK(ksobj);
pmap_qenter(td->td_kstack, ma, pages);
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 9c5c83a..bc0e4c0 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -2014,7 +2014,7 @@ vm_object_populate(vm_object_t object, vm_pindex_t start, vm_pindex_t end)
for (pindex = start; pindex < end; pindex++) {
m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL);
if (m->valid != VM_PAGE_BITS_ALL) {
- rv = vm_pager_get_pages(object, &m, 1, 0);
+ rv = vm_pager_get_pages(object, &m, 1, NULL, NULL);
if (rv != VM_PAGER_OK) {
vm_page_lock(m);
vm_page_free(m);
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 894a8d5..ca2d73a 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -243,6 +243,8 @@ extern struct vm_object kmem_object_store;
rw_try_upgrade(&(object)->lock)
#define VM_OBJECT_WLOCK(object) \
rw_wlock(&(object)->lock)
+#define VM_OBJECT_WOWNED(object) \
+ rw_wowned(&(object)->lock)
#define VM_OBJECT_WUNLOCK(object) \
rw_wunlock(&(object)->lock)
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index e5edf77..2e6b56a 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -979,38 +979,28 @@ vm_page_free_zero(vm_page_t m)
/*
* Unbusy and handle the page queueing for a page from the VOP_GETPAGES()
- * array which is not the request page.
+ * array which was optionally read ahead or behind.
*/
void
vm_page_readahead_finish(vm_page_t m)
{
- if (m->valid != 0) {
- /*
- * Since the page is not the requested page, whether
- * it should be activated or deactivated is not
- * obvious. Empirical results have shown that
- * deactivating the page is usually the best choice,
- * unless the page is wanted by another thread.
- */
- vm_page_lock(m);
- if ((m->busy_lock & VPB_BIT_WAITERS) != 0)
- vm_page_activate(m);
- else
- vm_page_deactivate(m);
- vm_page_unlock(m);
- vm_page_xunbusy(m);
- } else {
- /*
- * Free the completely invalid page. Such page state
- * occurs due to the short read operation which did
- * not covered our page at all, or in case when a read
- * error happens.
- */
- vm_page_lock(m);
- vm_page_free(m);
- vm_page_unlock(m);
- }
+ /* We shouldn't put invalid pages on queues. */
+ KASSERT(m->valid != 0, ("%s: %p is invalid", __func__, m));
+
+ /*
+ * Since the page is not the actually needed one, whether it should
+ * be activated or deactivated is not obvious. Empirical results
+ * have shown that deactivating the page is usually the best choice,
+ * unless the page is wanted by another thread.
+ */
+ vm_page_lock(m);
+ if ((m->busy_lock & VPB_BIT_WAITERS) != 0)
+ vm_page_activate(m);
+ else
+ vm_page_deactivate(m);
+ vm_page_unlock(m);
+ vm_page_xunbusy(m);
}
/*
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index 1fa61eb..9abd31c 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -514,37 +514,38 @@ void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line);
#define vm_page_assert_sbusied(m) \
KASSERT(vm_page_sbusied(m), \
("vm_page_assert_sbusied: page %p not shared busy @ %s:%d", \
- (void *)m, __FILE__, __LINE__));
+ (m), __FILE__, __LINE__))
#define vm_page_assert_unbusied(m) \
KASSERT(!vm_page_busied(m), \
("vm_page_assert_unbusied: page %p busy @ %s:%d", \
- (void *)m, __FILE__, __LINE__));
+ (m), __FILE__, __LINE__))
#define vm_page_assert_xbusied(m) \
KASSERT(vm_page_xbusied(m), \
("vm_page_assert_xbusied: page %p not exclusive busy @ %s:%d", \
- (void *)m, __FILE__, __LINE__));
+ (m), __FILE__, __LINE__))
#define vm_page_busied(m) \
((m)->busy_lock != VPB_UNBUSIED)
#define vm_page_sbusy(m) do { \
if (!vm_page_trysbusy(m)) \
- panic("%s: page %p failed shared busing", __func__, m); \
+ panic("%s: page %p failed shared busying", __func__, \
+ (m)); \
} while (0)
#define vm_page_tryxbusy(m) \
- (atomic_cmpset_acq_int(&m->busy_lock, VPB_UNBUSIED, \
+ (atomic_cmpset_acq_int(&(m)->busy_lock, VPB_UNBUSIED, \
VPB_SINGLE_EXCLUSIVER))
#define vm_page_xbusied(m) \
- ((m->busy_lock & VPB_SINGLE_EXCLUSIVER) != 0)
+ (((m)->busy_lock & VPB_SINGLE_EXCLUSIVER) != 0)
#define vm_page_xbusy(m) do { \
if (!vm_page_tryxbusy(m)) \
- panic("%s: page %p failed exclusive busing", __func__, \
- m); \
+ panic("%s: page %p failed exclusive busying", __func__, \
+ (m)); \
} while (0)
#define vm_page_xunbusy(m) do { \
diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c
index 40d7d4e..7a1e6ae 100644
--- a/sys/vm/vm_pager.c
+++ b/sys/vm/vm_pager.c
@@ -88,7 +88,7 @@ int cluster_pbuf_freecnt = -1; /* unlimited to begin with */
struct buf *swbuf;
-static int dead_pager_getpages(vm_object_t, vm_page_t *, int, int);
+static int dead_pager_getpages(vm_object_t, vm_page_t *, int, int *, int *);
static vm_object_t dead_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
vm_ooffset_t, struct ucred *);
static void dead_pager_putpages(vm_object_t, vm_page_t *, int, int, int *);
@@ -96,13 +96,11 @@ static boolean_t dead_pager_haspage(vm_object_t, vm_pindex_t, int *, int *);
static void dead_pager_dealloc(vm_object_t);
static int
-dead_pager_getpages(obj, ma, count, req)
- vm_object_t obj;
- vm_page_t *ma;
- int count;
- int req;
+dead_pager_getpages(vm_object_t obj, vm_page_t *ma, int count, int *rbehind,
+ int *rahead)
{
- return VM_PAGER_FAIL;
+
+ return (VM_PAGER_FAIL);
}
static vm_object_t
@@ -282,45 +280,47 @@ vm_pager_assert_in(vm_object_t object, vm_page_t *m, int count)
* The requested page must be fully valid on successful return.
*/
int
-vm_pager_get_pages(vm_object_t object, vm_page_t *m, int count, int reqpage)
+vm_pager_get_pages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
+ int *rahead)
{
+#ifdef INVARIANTS
+ vm_pindex_t pindex = m[0]->pindex;
+#endif
int r;
vm_pager_assert_in(object, m, count);
- r = (*pagertab[object->type]->pgo_getpages)(object, m, count, reqpage);
+ r = (*pagertab[object->type]->pgo_getpages)(object, m, count, rbehind,
+ rahead);
if (r != VM_PAGER_OK)
return (r);
- /*
- * If pager has replaced the page, assert that it had
- * updated the array. Also assert that page is still
- * busied.
- */
- KASSERT(m[reqpage] == vm_page_lookup(object, m[reqpage]->pindex),
- ("%s: mismatch page %p pindex %ju", __func__,
- m[reqpage], (uintmax_t )m[reqpage]->pindex));
- vm_page_assert_xbusied(m[reqpage]);
-
- /*
- * Pager didn't fill up entire page. Zero out
- * partially filled data.
- */
- if (m[reqpage]->valid != VM_PAGE_BITS_ALL)
- vm_page_zero_invalid(m[reqpage], TRUE);
-
+ for (int i = 0; i < count; i++) {
+ /*
+ * If pager has replaced a page, assert that it had
+ * updated the array.
+ */
+ KASSERT(m[i] == vm_page_lookup(object, pindex++),
+ ("%s: mismatch page %p pindex %ju", __func__,
+ m[i], (uintmax_t )pindex - 1));
+ /*
+ * Zero out partially filled data.
+ */
+ if (m[i]->valid != VM_PAGE_BITS_ALL)
+ vm_page_zero_invalid(m[i], TRUE);
+ }
return (VM_PAGER_OK);
}
int
vm_pager_get_pages_async(vm_object_t object, vm_page_t *m, int count,
- int reqpage, pgo_getpages_iodone_t iodone, void *arg)
+ int *rbehind, int *rahead, pgo_getpages_iodone_t iodone, void *arg)
{
vm_pager_assert_in(object, m, count);
return ((*pagertab[object->type]->pgo_getpages_async)(object, m,
- count, reqpage, iodone, arg));
+ count, rbehind, rahead, iodone, arg));
}
/*
@@ -355,39 +355,6 @@ vm_pager_object_lookup(struct pagerlst *pg_list, void *handle)
}
/*
- * Free the non-requested pages from the given array. To remove all pages,
- * caller should provide out of range reqpage number.
- */
-void
-vm_pager_free_nonreq(vm_object_t object, vm_page_t ma[], int reqpage,
- int npages, boolean_t object_locked)
-{
- enum { UNLOCKED, CALLER_LOCKED, INTERNALLY_LOCKED } locked;
- int i;
-
- if (object_locked) {
- VM_OBJECT_ASSERT_WLOCKED(object);
- locked = CALLER_LOCKED;
- } else {
- VM_OBJECT_ASSERT_UNLOCKED(object);
- locked = UNLOCKED;
- }
- for (i = 0; i < npages; ++i) {
- if (i != reqpage) {
- if (locked == UNLOCKED) {
- VM_OBJECT_WLOCK(object);
- locked = INTERNALLY_LOCKED;
- }
- vm_page_lock(ma[i]);
- vm_page_free(ma[i]);
- vm_page_unlock(ma[i]);
- }
- }
- if (locked == INTERNALLY_LOCKED)
- VM_OBJECT_WUNLOCK(object);
-}
-
-/*
* initialize a physical buffer
*/
diff --git a/sys/vm/vm_pager.h b/sys/vm/vm_pager.h
index 6884729..4b7d100 100644
--- a/sys/vm/vm_pager.h
+++ b/sys/vm/vm_pager.h
@@ -50,9 +50,9 @@ typedef void pgo_init_t(void);
typedef vm_object_t pgo_alloc_t(void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t,
struct ucred *);
typedef void pgo_dealloc_t(vm_object_t);
-typedef int pgo_getpages_t(vm_object_t, vm_page_t *, int, int);
+typedef int pgo_getpages_t(vm_object_t, vm_page_t *, int, int *, int *);
typedef void pgo_getpages_iodone_t(void *, vm_page_t *, int, int);
-typedef int pgo_getpages_async_t(vm_object_t, vm_page_t *, int, int,
+typedef int pgo_getpages_async_t(vm_object_t, vm_page_t *, int, int *, int *,
pgo_getpages_iodone_t, void *);
typedef void pgo_putpages_t(vm_object_t, vm_page_t *, int, int, int *);
typedef boolean_t pgo_haspage_t(vm_object_t, vm_pindex_t, int *, int *);
@@ -106,14 +106,12 @@ vm_object_t vm_pager_allocate(objtype_t, void *, vm_ooffset_t, vm_prot_t,
vm_ooffset_t, struct ucred *);
void vm_pager_bufferinit(void);
void vm_pager_deallocate(vm_object_t);
-int vm_pager_get_pages(vm_object_t, vm_page_t *, int, int);
-int vm_pager_get_pages_async(vm_object_t, vm_page_t *, int, int,
+int vm_pager_get_pages(vm_object_t, vm_page_t *, int, int *, int *);
+int vm_pager_get_pages_async(vm_object_t, vm_page_t *, int, int *, int *,
pgo_getpages_iodone_t, void *);
static __inline boolean_t vm_pager_has_page(vm_object_t, vm_pindex_t, int *, int *);
void vm_pager_init(void);
vm_object_t vm_pager_object_lookup(struct pagerlst *, void *);
-void vm_pager_free_nonreq(vm_object_t object, vm_page_t ma[], int reqpage,
- int npages, boolean_t object_locked);
static __inline void
vm_pager_put_pages(
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 96510ac..ff30f4d 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -84,11 +84,9 @@ static int vnode_pager_addr(struct vnode *vp, vm_ooffset_t address,
static int vnode_pager_input_smlfs(vm_object_t object, vm_page_t m);
static int vnode_pager_input_old(vm_object_t object, vm_page_t m);
static void vnode_pager_dealloc(vm_object_t);
-static int vnode_pager_local_getpages0(struct vnode *, vm_page_t *, int, int,
- vop_getpages_iodone_t, void *);
-static int vnode_pager_getpages(vm_object_t, vm_page_t *, int, int);
-static int vnode_pager_getpages_async(vm_object_t, vm_page_t *, int, int,
- vop_getpages_iodone_t, void *);
+static int vnode_pager_getpages(vm_object_t, vm_page_t *, int, int *, int *);
+static int vnode_pager_getpages_async(vm_object_t, vm_page_t *, int, int *,
+ int *, vop_getpages_iodone_t, void *);
static void vnode_pager_putpages(vm_object_t, vm_page_t *, int, int, int *);
static boolean_t vnode_pager_haspage(vm_object_t, vm_pindex_t, int *, int *);
static vm_object_t vnode_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
@@ -673,15 +671,15 @@ vnode_pager_input_old(vm_object_t object, vm_page_t m)
* backing vp's VOP_GETPAGES.
*/
static int
-vnode_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
+vnode_pager_getpages(vm_object_t object, vm_page_t *m, int count, int *rbehind,
+ int *rahead)
{
- int rtval;
struct vnode *vp;
- int bytes = count * PAGE_SIZE;
+ int rtval;
vp = object->handle;
VM_OBJECT_WUNLOCK(object);
- rtval = VOP_GETPAGES(vp, m, bytes, reqpage);
+ rtval = VOP_GETPAGES(vp, m, count, rbehind, rahead);
KASSERT(rtval != EOPNOTSUPP,
("vnode_pager: FS getpages not implemented\n"));
VM_OBJECT_WLOCK(object);
@@ -690,15 +688,14 @@ vnode_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
static int
vnode_pager_getpages_async(vm_object_t object, vm_page_t *m, int count,
- int reqpage, vop_getpages_iodone_t iodone, void *arg)
+ int *rbehind, int *rahead, vop_getpages_iodone_t iodone, void *arg)
{
struct vnode *vp;
int rtval;
vp = object->handle;
VM_OBJECT_WUNLOCK(object);
- rtval = VOP_GETPAGES_ASYNC(vp, m, count * PAGE_SIZE, reqpage,
- iodone, arg);
+ rtval = VOP_GETPAGES_ASYNC(vp, m, count, rbehind, rahead, iodone, arg);
KASSERT(rtval != EOPNOTSUPP,
("vnode_pager: FS getpages_async not implemented\n"));
VM_OBJECT_WLOCK(object);
@@ -714,48 +711,16 @@ int
vnode_pager_local_getpages(struct vop_getpages_args *ap)
{
- return (vnode_pager_local_getpages0(ap->a_vp, ap->a_m, ap->a_count,
- ap->a_reqpage, NULL, NULL));
+ return (vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
+ ap->a_rbehind, ap->a_rahead, NULL, NULL));
}
int
vnode_pager_local_getpages_async(struct vop_getpages_async_args *ap)
{
- return (vnode_pager_local_getpages0(ap->a_vp, ap->a_m, ap->a_count,
- ap->a_reqpage, ap->a_iodone, ap->a_arg));
-}
-
-static int
-vnode_pager_local_getpages0(struct vnode *vp, vm_page_t *m, int bytecount,
- int reqpage, vop_getpages_iodone_t iodone, void *arg)
-{
- vm_page_t mreq;
-
- mreq = m[reqpage];
-
- /*
- * Since the caller has busied the requested page, that page's valid
- * field will not be changed by other threads.
- */
- vm_page_assert_xbusied(mreq);
-
- /*
- * The requested page has valid blocks. Invalid part can only
- * exist at the end of file, and the page is made fully valid
- * by zeroing in vm_pager_get_pages(). Free non-requested
- * pages, since no i/o is done to read its content.
- */
- if (mreq->valid != 0) {
- vm_pager_free_nonreq(mreq->object, m, reqpage,
- round_page(bytecount) / PAGE_SIZE, FALSE);
- if (iodone != NULL)
- iodone(arg, m, reqpage, 0);
- return (VM_PAGER_OK);
- }
-
- return (vnode_pager_generic_getpages(vp, m, bytecount, reqpage,
- iodone, arg));
+ return (vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count,
+ ap->a_rbehind, ap->a_rahead, ap->a_iodone, ap->a_arg));
}
/*
@@ -763,25 +728,43 @@ vnode_pager_local_getpages0(struct vnode *vp, vm_page_t *m, int bytecount,
* own vnodes if they fail to implement VOP_GETPAGES.
*/
int
-vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount,
- int reqpage, vop_getpages_iodone_t iodone, void *arg)
+vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int count,
+ int *a_rbehind, int *a_rahead, vop_getpages_iodone_t iodone, void *arg)
{
vm_object_t object;
struct bufobj *bo;
struct buf *bp;
- daddr_t firstaddr, reqblock;
- off_t foff, pib;
- int pbefore, pafter, i, size, bsize, first, last, *freecnt;
- int count, error, before, after, secmask;
+ off_t foff;
+ int bsize, pagesperblock, *freecnt;
+ int error, before, after, rbehind, rahead, poff, i;
+ int bytecount, secmask;
KASSERT(vp->v_type != VCHR && vp->v_type != VBLK,
- ("vnode_pager_generic_getpages does not support devices"));
+ ("%s does not support devices", __func__));
+
if (vp->v_iflag & VI_DOOMED)
return (VM_PAGER_BAD);
object = vp->v_object;
- count = bytecount / PAGE_SIZE;
+ foff = IDX_TO_OFF(m[0]->pindex);
bsize = vp->v_mount->mnt_stat.f_iosize;
+ pagesperblock = bsize / PAGE_SIZE;
+
+ KASSERT(foff < object->un_pager.vnp.vnp_size,
+ ("%s: page %p offset beyond vp %p size", __func__, m[0], vp));
+ KASSERT(count <= sizeof(bp->b_pages),
+ ("%s: requested %d pages", __func__, count));
+
+ /*
+ * The last page has valid blocks. Invalid part can only
+ * exist at the end of file, and the page is made fully valid
+ * by zeroing in vm_pager_get_pages().
+ */
+ if (m[count - 1]->valid != 0 && --count == 0) {
+ if (iodone != NULL)
+ iodone(arg, m, 1, 0);
+ return (VM_PAGER_OK);
+ }
/*
* Synchronous and asynchronous paging operations use different
@@ -800,130 +783,182 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount,
* If the file system doesn't support VOP_BMAP, use old way of
* getting pages via VOP_READ.
*/
- error = VOP_BMAP(vp, IDX_TO_OFF(m[reqpage]->pindex) / bsize, &bo,
- &reqblock, &after, &before);
+ error = VOP_BMAP(vp, foff / bsize, &bo, &bp->b_blkno, &after, &before);
if (error == EOPNOTSUPP) {
relpbuf(bp, freecnt);
VM_OBJECT_WLOCK(object);
- for (i = 0; i < count; i++)
- if (i != reqpage) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
- PCPU_INC(cnt.v_vnodein);
- PCPU_INC(cnt.v_vnodepgsin);
- error = vnode_pager_input_old(object, m[reqpage]);
+ for (i = 0; i < count; i++) {
+ PCPU_INC(cnt.v_vnodein);
+ PCPU_INC(cnt.v_vnodepgsin);
+ error = vnode_pager_input_old(object, m[i]);
+ if (error)
+ break;
+ }
VM_OBJECT_WUNLOCK(object);
return (error);
} else if (error != 0) {
relpbuf(bp, freecnt);
- vm_pager_free_nonreq(object, m, reqpage, count, FALSE);
return (VM_PAGER_ERROR);
-
- /*
- * If the blocksize is smaller than a page size, then use
- * special small filesystem code.
- */
- } else if ((PAGE_SIZE / bsize) > 1) {
- relpbuf(bp, freecnt);
- vm_pager_free_nonreq(object, m, reqpage, count, FALSE);
- PCPU_INC(cnt.v_vnodein);
- PCPU_INC(cnt.v_vnodepgsin);
- return (vnode_pager_input_smlfs(object, m[reqpage]));
}
/*
- * Since the caller has busied the requested page, that page's valid
- * field will not be changed by other threads.
+ * If the file system supports BMAP, but blocksize is smaller
+ * than a page size, then use special small filesystem code.
*/
- vm_page_assert_xbusied(m[reqpage]);
+ if (pagesperblock == 0) {
+ for (i = 0; i < count; i++) {
+ PCPU_INC(cnt.v_vnodein);
+ PCPU_INC(cnt.v_vnodepgsin);
+ error = vnode_pager_input_smlfs(object, m[i]);
+ if (error)
+ break;
+ }
+ return (error);
+ }
/*
- * If we have a completely valid page available to us, we can
- * clean up and return. Otherwise we have to re-read the
- * media.
+ * A sparse file can be encountered only for a single page request,
+ * which may not be preceeded by call to vm_pager_haspage().
*/
- if (m[reqpage]->valid == VM_PAGE_BITS_ALL) {
- relpbuf(bp, freecnt);
- vm_pager_free_nonreq(object, m, reqpage, count, FALSE);
- return (VM_PAGER_OK);
- } else if (reqblock == -1) {
+ if (bp->b_blkno == -1) {
+ KASSERT(count == 1,
+ ("%s: array[%d] request to a sparse file %p", __func__,
+ count, vp));
relpbuf(bp, freecnt);
- pmap_zero_page(m[reqpage]);
- KASSERT(m[reqpage]->dirty == 0,
- ("vnode_pager_generic_getpages: page %p is dirty", m));
+ pmap_zero_page(m[0]);
+ KASSERT(m[0]->dirty == 0, ("%s: page %p is dirty",
+ __func__, m[0]));
VM_OBJECT_WLOCK(object);
- m[reqpage]->valid = VM_PAGE_BITS_ALL;
- vm_pager_free_nonreq(object, m, reqpage, count, TRUE);
+ m[0]->valid = VM_PAGE_BITS_ALL;
VM_OBJECT_WUNLOCK(object);
return (VM_PAGER_OK);
- } else if (m[reqpage]->valid != 0) {
- VM_OBJECT_WLOCK(object);
- m[reqpage]->valid = 0;
- VM_OBJECT_WUNLOCK(object);
}
- pib = IDX_TO_OFF(m[reqpage]->pindex) % bsize;
- pbefore = ((daddr_t)before * bsize + pib) / PAGE_SIZE;
- pafter = ((daddr_t)(after + 1) * bsize - pib) / PAGE_SIZE - 1;
- first = reqpage < pbefore ? 0 : reqpage - pbefore;
- last = reqpage + pafter >= count ? count - 1 : reqpage + pafter;
- if (first > 0 || last + 1 < count) {
+ bp->b_blkno += (foff % bsize) / DEV_BSIZE;
+
+ /* Recalculate blocks available after/before to pages. */
+ poff = (foff % bsize) / PAGE_SIZE;
+ before *= pagesperblock;
+ before += poff;
+ after *= pagesperblock;
+ after += pagesperblock - (poff + 1);
+ if (m[0]->pindex + after >= object->size)
+ after = object->size - 1 - m[0]->pindex;
+ KASSERT(count <= after + 1, ("%s: %d pages asked, can do only %d",
+ __func__, count, after + 1));
+ after -= count - 1;
+
+ /* Trim requested rbehind/rahead to possible values. */
+ rbehind = a_rbehind ? *a_rbehind : 0;
+ rahead = a_rahead ? *a_rahead : 0;
+ rbehind = min(rbehind, before);
+ rbehind = min(rbehind, m[0]->pindex);
+ rahead = min(rahead, after);
+ rahead = min(rahead, object->size - m[count - 1]->pindex);
+ KASSERT(rbehind + rahead + count <= sizeof(bp->b_pages),
+ ("%s: behind %d ahead %d count %d", __func__,
+ rbehind, rahead, count));
+
+ /*
+ * Fill in the bp->b_pages[] array with requested and optional
+ * read behind or read ahead pages. Read behind pages are looked
+ * up in a backward direction, down to a first cached page. Same
+ * for read ahead pages, but there is no need to shift the array
+ * in case of encountering a cached page.
+ */
+ i = bp->b_npages = 0;
+ if (rbehind) {
+ vm_pindex_t startpindex, tpindex;
+ vm_page_t p;
+
VM_OBJECT_WLOCK(object);
- for (i = 0; i < first; i++) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
+ startpindex = m[0]->pindex - rbehind;
+ if ((p = TAILQ_PREV(m[0], pglist, listq)) != NULL &&
+ p->pindex >= startpindex)
+ startpindex = p->pindex + 1;
+
+ /* tpindex is unsigned; beware of numeric underflow. */
+ for (tpindex = m[0]->pindex - 1;
+ tpindex >= startpindex && tpindex < m[0]->pindex;
+ tpindex--, i++) {
+ p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL |
+ VM_ALLOC_IFNOTCACHED);
+ if (p == NULL) {
+ /* Shift the array. */
+ for (int j = 0; j < i; j++)
+ bp->b_pages[j] = bp->b_pages[j +
+ tpindex + 1 - startpindex];
+ break;
+ }
+ bp->b_pages[tpindex - startpindex] = p;
}
- for (i = last + 1; i < count; i++) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
+
+ bp->b_pgbefore = i;
+ bp->b_npages += i;
+ bp->b_blkno -= IDX_TO_OFF(i) / DEV_BSIZE;
+ } else
+ bp->b_pgbefore = 0;
+
+ /* Requested pages. */
+ for (int j = 0; j < count; j++, i++)
+ bp->b_pages[i] = m[j];
+ bp->b_npages += count;
+
+ if (rahead) {
+ vm_pindex_t endpindex, tpindex;
+ vm_page_t p;
+
+ if (!VM_OBJECT_WOWNED(object))
+ VM_OBJECT_WLOCK(object);
+ endpindex = m[count - 1]->pindex + rahead + 1;
+ if ((p = TAILQ_NEXT(m[count - 1], listq)) != NULL &&
+ p->pindex < endpindex)
+ endpindex = p->pindex;
+ if (endpindex > object->size)
+ endpindex = object->size;
+
+ for (tpindex = m[count - 1]->pindex + 1;
+ tpindex < endpindex; i++, tpindex++) {
+ p = vm_page_alloc(object, tpindex, VM_ALLOC_NORMAL |
+ VM_ALLOC_IFNOTCACHED);
+ if (p == NULL)
+ break;
+ bp->b_pages[i] = p;
}
- VM_OBJECT_WUNLOCK(object);
- }
- /*
- * here on direct device I/O
- */
- firstaddr = reqblock;
- firstaddr += pib / DEV_BSIZE;
- firstaddr -= IDX_TO_OFF(reqpage - first) / DEV_BSIZE;
+ bp->b_pgafter = i - bp->b_npages;
+ bp->b_npages = i;
+ } else
+ bp->b_pgafter = 0;
- /*
- * The first and last page have been calculated now, move
- * input pages to be zero based, and adjust the count.
- */
- m += first;
- reqpage -= first;
- count = last - first + 1;
+ if (VM_OBJECT_WOWNED(object))
+ VM_OBJECT_WUNLOCK(object);
- /*
- * calculate the file virtual address for the transfer
- */
- foff = IDX_TO_OFF(m[0]->pindex);
+ /* Report back actual behind/ahead read. */
+ if (a_rbehind)
+ *a_rbehind = bp->b_pgbefore;
+ if (a_rahead)
+ *a_rahead = bp->b_pgafter;
- /*
- * calculate the size of the transfer
- */
- size = count * PAGE_SIZE;
- KASSERT(count > 0, ("zero count"));
- if ((foff + size) > object->un_pager.vnp.vnp_size)
- size = object->un_pager.vnp.vnp_size - foff;
- KASSERT(size > 0, ("zero size"));
+ KASSERT(bp->b_npages <= sizeof(bp->b_pages),
+ ("%s: buf %p overflowed", __func__, bp));
/*
- * round up physical size for real devices.
+ * Recalculate first offset and bytecount with regards to read behind.
+ * Truncate bytecount to vnode real size and round up physical size
+ * for real devices.
*/
+ foff = IDX_TO_OFF(bp->b_pages[0]->pindex);
+ bytecount = bp->b_npages << PAGE_SHIFT;
+ if ((foff + bytecount) > object->un_pager.vnp.vnp_size)
+ bytecount = object->un_pager.vnp.vnp_size - foff;
secmask = bo->bo_bsize - 1;
KASSERT(secmask < PAGE_SIZE && secmask > 0,
- ("vnode_pager_generic_getpages: sector size %d too large",
- secmask + 1));
- size = (size + secmask) & ~secmask;
+ ("%s: sector size %d too large", __func__, secmask + 1));
+ bytecount = (bytecount + secmask) & ~secmask;
/*
- * and map the pages to be read into the kva, if the filesystem
+ * And map the pages to be read into the kva, if the filesystem
* requires mapped buffers.
*/
if ((vp->v_mount->mnt_kern_flag & MNTK_UNMAPPED_BUFS) != 0 &&
@@ -932,41 +967,32 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount,
bp->b_offset = 0;
} else {
bp->b_data = bp->b_kvabase;
- pmap_qenter((vm_offset_t)bp->b_data, m, count);
+ pmap_qenter((vm_offset_t)bp->b_data, bp->b_pages, bp->b_npages);
}
- /* build a minimal buffer header */
+ /* Build a minimal buffer header. */
bp->b_iocmd = BIO_READ;
KASSERT(bp->b_rcred == NOCRED, ("leaking read ucred"));
KASSERT(bp->b_wcred == NOCRED, ("leaking write ucred"));
bp->b_rcred = crhold(curthread->td_ucred);
bp->b_wcred = crhold(curthread->td_ucred);
- bp->b_blkno = firstaddr;
pbgetbo(bo, bp);
bp->b_vp = vp;
- bp->b_bcount = size;
- bp->b_bufsize = size;
- bp->b_runningbufspace = bp->b_bufsize;
- for (i = 0; i < count; i++)
- bp->b_pages[i] = m[i];
- bp->b_npages = count;
- bp->b_pager.pg_reqpage = reqpage;
- atomic_add_long(&runningbufspace, bp->b_runningbufspace);
+ bp->b_bcount = bp->b_bufsize = bp->b_runningbufspace = bytecount;
+ bp->b_iooffset = dbtob(bp->b_blkno);
+ atomic_add_long(&runningbufspace, bp->b_runningbufspace);
PCPU_INC(cnt.v_vnodein);
- PCPU_ADD(cnt.v_vnodepgsin, count);
-
- /* do the input */
- bp->b_iooffset = dbtob(bp->b_blkno);
+ PCPU_ADD(cnt.v_vnodepgsin, bp->b_npages);
if (iodone != NULL) { /* async */
- bp->b_pager.pg_iodone = iodone;
+ bp->b_pgiodone = iodone;
bp->b_caller1 = arg;
bp->b_iodone = vnode_pager_generic_getpages_done_async;
bp->b_flags |= B_ASYNC;
BUF_KERNPROC(bp);
bstrategy(bp);
- /* Good bye! */
+ return (VM_PAGER_OK);
} else {
bp->b_iodone = bdone;
bstrategy(bp);
@@ -977,9 +1003,8 @@ vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount,
bp->b_vp = NULL;
pbrelbo(bp);
relpbuf(bp, &vnode_pbuf_freecnt);
+ return (error != 0 ? VM_PAGER_ERROR : VM_PAGER_OK);
}
-
- return (error != 0 ? VM_PAGER_ERROR : VM_PAGER_OK);
}
static void
@@ -988,8 +1013,9 @@ vnode_pager_generic_getpages_done_async(struct buf *bp)
int error;
error = vnode_pager_generic_getpages_done(bp);
- bp->b_pager.pg_iodone(bp->b_caller1, bp->b_pages,
- bp->b_pager.pg_reqpage, error);
+ /* Run the iodone upon the requested range. */
+ bp->b_pgiodone(bp->b_caller1, bp->b_pages + bp->b_pgbefore,
+ bp->b_npages - bp->b_pgbefore - bp->b_pgafter, error);
for (int i = 0; i < bp->b_npages; i++)
bp->b_pages[i] = NULL;
bp->b_vp = NULL;
@@ -1052,8 +1078,8 @@ vnode_pager_generic_getpages_done(struct buf *bp)
object->un_pager.vnp.vnp_size - tfoff)) == 0,
("%s: page %p is dirty", __func__, mt));
}
-
- if (i != bp->b_pager.pg_reqpage)
+
+ if (i < bp->b_pgbefore || i >= bp->b_npages - bp->b_pgafter)
vm_page_readahead_finish(mt);
}
VM_OBJECT_WUNLOCK(object);
diff --git a/sys/vm/vnode_pager.h b/sys/vm/vnode_pager.h
index 1ff16eb..a94b09b 100644
--- a/sys/vm/vnode_pager.h
+++ b/sys/vm/vnode_pager.h
@@ -41,7 +41,8 @@
#ifdef _KERNEL
int vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m,
- int count, int reqpage, vop_getpages_iodone_t iodone, void *arg);
+ int count, int *rbehind, int *rahead, vop_getpages_iodone_t iodone,
+ void *arg);
int vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *m,
int count, boolean_t sync,
int *rtvals);
diff --git a/tests/freebsd_test_suite/macros.h b/tests/freebsd_test_suite/macros.h
index 8d95f05..98da0ed 100644
--- a/tests/freebsd_test_suite/macros.h
+++ b/tests/freebsd_test_suite/macros.h
@@ -38,6 +38,13 @@
#include <atf-c.h>
+#define ATF_REQUIRE_FEATURE(_feature_name) do { \
+ if (feature_present(_feature_name) == 0) { \
+ atf_tc_skip("kernel feature (%s) not present", \
+ _feature_name); \
+ } \
+} while(0)
+
#define ATF_REQUIRE_KERNEL_MODULE(_mod_name) do { \
if (modfind(_mod_name) == -1) { \
atf_tc_skip("module %s could not be resolved: %s", \
@@ -45,6 +52,14 @@
} \
} while(0)
+#define PLAIN_REQUIRE_FEATURE(_feature_name, _exit_code) do { \
+ if (feature_present(_feature_name) == 0) { \
+ printf("kernel feature (%s) not present\n", \
+ _feature_name); \
+ _exit(_exit_code); \
+ } \
+} while(0)
+
#define PLAIN_REQUIRE_KERNEL_MODULE(_mod_name, _exit_code) do { \
if (modfind(_mod_name) == -1) { \
printf("module %s could not be resolved: %s\n", \
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 0e9c955..779f596 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -4254,6 +4254,11 @@ OLD_DIRS+=usr/include/c++/v1
# to be filled in
#.endif
+.if ${MK_LLDB} == no
+OLD_FILES+=usr/bin/lldb
+OLD_FILES+=usr/share/man/man1/lldb.1.gz
+.endif
+
.if ${MK_LOCALES} == no
OLD_FILES+=usr/share/locale/af_ZA.ISO8859-1/LC_COLLATE
OLD_FILES+=usr/share/locale/af_ZA.ISO8859-1/LC_CTYPE
diff --git a/tools/regression/lib/libc/nss/Makefile b/tools/regression/lib/libc/nss/Makefile
deleted file mode 100644
index 8c8a514..0000000
--- a/tools/regression/lib/libc/nss/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# $FreeBSD$
-
-TESTS= test-getaddr test-getgr test-gethostby test-getpw test-getproto\
- test-getrpc test-getserv test-getusershell
-CFLAGS+= -g -Wall
-
-.PHONY: tests
-tests: ${TESTS}
-
-.PHONY: clean
-clean:
- -rm -f ${TESTS}
diff --git a/tools/regression/lib/libc/nss/README b/tools/regression/lib/libc/nss/README
deleted file mode 100644
index bf32913..0000000
--- a/tools/regression/lib/libc/nss/README
+++ /dev/null
@@ -1,203 +0,0 @@
-$FreeBSD$
-
-A brief how-to
---------------
-
-Each nsswitch regression test does 2 kinds of actions:
-1. It runs a series of queries and tests the correctness of results.
- There are 2 basic criteria which are used for that:
- - numbers must be in the correct range
- - certain pointers should not be NULL
-
-2. It makes a snapshot of the results of all queries that were made.
- The idea of snapshots is to test that nsswitch-related function
- calls behave equally (i.e. return same results for the same queries)
- between system upgrades. When the test is executed and the snapshot is
- already created, the test will compare the result of each query with
- the appropriate result from the snapshot and will signal if they
- differ.
-
-In order for nsswitch tests to be as useful as possible you should use
-them in the following way:
-
-Step 1 (before upgrading your system).
-Build the tests with "make" command and execute them with "prove -v"
-command. If there are errors during the execution, then appropriate
-nsswitch functions should be checked. Note, that errors on this state
-can happen only if the particular function return incorrect data.
-
-After the stage 1 a number of "snapshot_[test name]" files will appear
-in your test folder.
-
-Step 2 (after upgrading you system).
-Rebuild the tests with "make clean; make" command and execute them
-again with "prove -v" (check that "snapshot_[test name]" files
-are in the same folder with tests). On this stage regression tests
-will catch not only the correctness errors, but will also determine
-the changes in nsswitch functions behaviour.
-
-In case of the test failure you will get the following message:
-
-To get more details about the error you should do the following:
-Step 1. Run the test alone with debug output enabled.
-Step 2. Mail the snapshot file and the debug test output to the
-freebsd-current@ mailing list.
-
-Example testing session for getpwXXX() family of functions
-----------------------------------------------------------
-1. make
-
-2. prove -v ./test-getpw.t
-
- test-getpw....1..8
- ok 1 - getpwnam()
- ok 2 - getpwuid()
- ok 3 - getpwent()
- ok 4 - getpwent() 2-pass
- ok 5 - building snapshot, if needed
- ok 6 - getpwnam() snapshot
- ok 7 - getpwuid() snapshot
- ok 8 - getpwent() snapshot
- ok
- All tests successful.
- Files=1, Tests=8, 1 wallclock secs ( 0.00 cusr + 0.20 csys = 0.20 CPU)
-
-
-3. Upgrading the system.
-
-4. make clean; make
-
-5. prove -v ./test-getpw.t (suppose that something has gone wrong)
-
- test-getpw....1..8
- ok 1 - getpwnam()
- ok 2 - getpwuid()
- ok 3 - getpwent()
- ok 4 - getpwent() 2-pass
- ok 5 - building snapshot, if needed
- not ok 6 - getpwnam() snapshot
- ok 7 - getpwuid() snapshot
- not ok 8 - getpwent() snapshot
- FAILED tests 6, 8
- Failed 2/8 tests, 75.00% okay
- Failed 1/1 test scripts, 0.00% okay. 2/8 subtests failed, 75.00% okay.
-
-6. We see that test number 6 failed. According to get-getpw.t, this test
- is executed like this:
- do_test 6 'getpwnam() snapshot' '-n -s snapshot_pwd'
-
- To determine why the test has failed, we need to run it in debug mode -
- it means adding "-d" to the options list.
-
-7. ./test-getpw -dn -s snapshot_pwd
- ...
- testing getpwnam() with the following data:
- toor:*:0:0:0::ne-again Superuser:/root::0:4831
- testing correctness with the following data:
- toor:*:0:0:0::Bourne-again Superuser:/root::0:4831
- correct
- not ok
-
-8. Here we can see that the data from snapshot (first "toor" line) and
- the data received from the getpwnam() call (second "toor" line) are
- different. It is the reason why the test has failed. If you can't
- (or don't want) to investigate the problem by yourself, mail
- the test debug output and the snapshot file to the developers list.
-
-Notes on using standalone nsswitch tests
-----------------------------------------
-
-All nsswitch tests have [-d] optional command line argument which enables
-debug output. The debug output can be extremely helpful to determine the
-cause of test failure.
-
-In all nsswitch tests -s <file> command line argument specifies the
-snapshot file. If this file doesn't exist, it would be built during
-test execution. If it already exists then it will be used to check
-the results of particular function calls. This argument is mostly
-optional, but some tests (test-getaddr and test-getusershell) force
-it to be specified.
-
-test-gethostby and test-getaddr require the list of hostnames, that should
-be queried during the test. This list must be specified via -f <file>
-command line argument. Each hostname should occupy exactly one line
-in the file.
-
-Detailed tests description
---------------------------
-
-./test-getaddr - tests the getaddrinfo() function.
- Usage: test-getaddr [-d] [-46] [-s <file>] -f <file>
- -d - enable debug output
- -4 - force IPv4 usage
- -6 - force IPv6 usage
- -s - build/use specified snapshot file
- -f - use specified hostnames list for testing
-
-./test-getgr
- Usage: test-getgr -nge2 [-d] [-s <file>]
- -d - enable debug output
- -n - test getgrnam(3)
- -g - test getgrgid(3)
- -e - test getgrent(3)
- -2 - test getgrent(3) in 2-pass mode
- -s - build/use specified snapshot file
-
-./test-gethostby
- Usage: test-gethostby -na2i [-o] [-d] [-m46] [-s <file>] -f <file>
- -n - test gethostbyname2(3)
- -a - test gethostbyaddr(3)
- -2 - test gethostbyname2(3) results to be equal with getaddrinfo(3)
- results for the similar query
- -i - test gethostbyaddr(3) results to be equal with getnameinfo(3)
- results for the similar query
- -o - use getipnodebyname(3)/getipnodebyaddr(3) for testing instead of
- gethostbyname2(3)/gethostbyaddr(3)
- -d - enable debug output
- -m - force IPv4-to-IPv6 mapping
- -4 - force IPv4 usage
- -6 - force IPv6 usage
- -s - build/use specified snapshot file
- -f - use specified hostnames list for testing
-
-./test-getproto
- Usage: test-getproto -nve2 [-d] [-s <file>]
- -d - enable debug output
- -n - test getprotobyname(3)
- -v - test getprotobynumber(3)
- -e - test getprotoent(3)
- -2 - test getprotoent(3) in 2-pass mode
- -s - build/use specified snapshot file
-
-./test-getpw
- Usage: test-getpw -nue2 [-d] [-s <file>]
- -d - enable debug output
- -n - test getpwnam(3)
- -u - test getpwuid(3)
- -e - test getpwent(3)
- -2 - test getpwent(3) in 2-pass mode
- -s - build/use snapshot file
-
-./test-getrpc
- Usage: test-getrpc -nve2 [-d] [-s <file>]
- -d - enable debug output
- -n - test getrpcbyname(3)
- -v - test getrpcbynumber(3)
- -e - test getrpcent(3)
- -2 - test getrpcent(3) in 2-pass mode
- -s - build/use specified snapshot file
-
-./test-getserv
- Usage: test-getserv -npe2 [-d] [-s <file>]
- -d - enable debug output
- -n - test getservbyname(3)
- -p - test getservbyport(3)
- -e - test getservent(3)
- -2 - test getservent(3) in 2-pass mode
- -s - build/use specified snapshot file
-
-./test-getusershell
- Usage: test-getusershell [-d] -s <file>
- -d - enable debug output
- -s - build/use specified snapshot file
-
diff --git a/tools/regression/lib/libc/nss/mach b/tools/regression/lib/libc/nss/mach
deleted file mode 100644
index ab7ce24..0000000
--- a/tools/regression/lib/libc/nss/mach
+++ /dev/null
@@ -1,93 +0,0 @@
-# $FreeBSD$
-localhost
-above.warped.net
-anoncvs.cirr.com
-anoncvs.isc.netbsd.org
-anoncvs.leo.org
-anoncvs.netbsd.lt
-anoncvs.netbsd.ro
-anoncvs.netbsd.se
-antioche.antioche.eu.org
-boulder.tele.dk
-centaurus.4web.cz
-chur.math.ntnu.no
-console.netbsd.org
-cvs.fi.netbsd.org
-cvs.mikrolahti.fi
-cvs.netbsd.org
-cvsup-netbsd.leo.org
-cvsup.netbsd.se
-cvsup.pasta.cs.uit.no
-ftp.bitcon.no
-ftp.chg.ru
-ftp.duth.gr
-ftp.estpak.ee
-ftp.fsn.hu
-ftp.funet.fi
-ftp.grondar.za
-ftp.leo.org
-ftp.netbsd.lt
-ftp.netbsd.org
-ftp.nluug.nl
-ftp.plig.org
-ftp.uni-erlangen.de
-ftp.xgate.co.kr
-gd.tuwien.ac.at
-gort.ludd.luth.se
-grappa.unix-ag.uni-kl.de
-info.wins.uva.nl
-irc.warped.net
-knug.youn.co.kr
-lala.iri.co.jp
-mail.jp.netbsd.org
-mail.kr.netbsd.org
-mail.netbsd.org
-melanoma.cs.rmit.edu.au
-mirror.aarnet.edu.au
-mirror.netbsd.com.br
-mirror03.inet.tele.dk
-moon.vub.ac.be
-nbwww.sergei.cc
-net.bsd.cz
-netbsd.3miasto.net
-netbsd.4ka.mipt.ru
-netbsd.apk.od.ua
-netbsd.csie.nctu.edu.tw
-netbsd.enderunix.org
-netbsd.ftp.fu-berlin.de
-netbsd.netlead.com.au
-netbsd.nsysu.edu.tw
-netbsd.pair.com
-netbsd.stevens-tech.edu
-netbsd.triada.bg
-netbsd.unix.net.nz
-netbsd.unixtech.be
-netbsd.vejas.lt
-netbsd.wagener-consulting.lu
-netbsd.zarco.org
-netbsdiso.interoute.net.uk
-netbsdwww.bitcon.no
-netbsdwww.cordef.com.pl
-netbsdwww.cs.rmit.edu.au
-netbsdwww.interoute.net.uk
-news.gw.com
-ns.netbsd.org
-pigu.iri.co.jp
-pluto.cdpa.nsysu.edu.tw
-projects.slowass.net
-server6.pasta.cs.uit.no
-skeleton.phys.spbu.ru
-snoopy.allbsd.org
-spike.allbsd.org
-sundry.netbsd.org
-tanya.sergei.cc
-web-a.fi.gw.com
-web-a.us.gw.com
-web.netbsd.mirror.arhea.net
-www.en.netbsd.de
-www.netbsd.cl
-www.netbsd.nl
-www.netbsd.org
-www.netbsd.ro
-zathras.netbsd.org
-zeppo.rediris.es
diff --git a/tools/regression/lib/libc/nss/test-getaddr.t b/tools/regression/lib/libc/nss/test-getaddr.t
deleted file mode 100644
index b3020f0..0000000
--- a/tools/regression/lib/libc/nss/test-getaddr.t
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..6
-#Tests with hints.ai_family is set to PF_UNSPEC
-do_test 1 'getaddrinfo() (PF_UNSPEC)' '-f mach'
-do_test 2 'getaddrinfo() snapshot (PF_UNSPEC)' '-f mach -s snapshot_ai'
-
-#Tests with hints.ai_family is set to PF_INET
-do_test 3 'getaddrinfo() (PF_INET)' '-f mach'
-do_test 4 'getaddrinfo() snapshot (PF_INET)' '-4 -f mach -s snapshot_ai4'
-
-#Tests with hints.ai_family is set to PF_INET6
-do_test 5 'getaddrinfo() (PF_INET6)' '-f mach'
-do_test 6 'getaddrinfo() snapshot (PF_INET6)' '-6 -f mach -s snapshot_ai6'
-
diff --git a/tools/regression/lib/libc/nss/test-getgr.t b/tools/regression/lib/libc/nss/test-getgr.t
deleted file mode 100644
index e2cf8e5..0000000
--- a/tools/regression/lib/libc/nss/test-getgr.t
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..8
-do_test 1 'getgrnam()' '-n'
-do_test 2 'getgrgid()' '-g'
-do_test 3 'getgrent()' '-e'
-do_test 4 'getgrent() 2-pass' '-2'
-do_test 5 'building snapshot, if needed' '-s snapshot_grp'
-do_test 6 'getgrnam() snapshot' '-n -s snapshot_grp'
-do_test 7 'getgrgid() snapshot' '-g -s snapshot_grp'
-do_test 8 'getgrent() snapshot' '-e -s snapshot_grp'
diff --git a/tools/regression/lib/libc/nss/test-gethostby.c b/tools/regression/lib/libc/nss/test-gethostby.c
deleted file mode 100644
index 9e7bdf5..0000000
--- a/tools/regression/lib/libc/nss/test-gethostby.c
+++ /dev/null
@@ -1,1105 +0,0 @@
-/*-
- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <assert.h>
-#include <errno.h>
-#include <netdb.h>
-#include <resolv.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stringlist.h>
-#include <unistd.h>
-#include "testutil.h"
-
-#ifndef min
-#define min(a,b) (((a)<(b))?(a):(b))
-#endif
-
-enum test_methods {
- TEST_GETHOSTBYNAME2,
- TEST_GETHOSTBYADDR,
- TEST_GETHOSTBYNAME2_GETADDRINFO,
- TEST_GETHOSTBYADDR_GETNAMEINFO,
- TEST_BUILD_SNAPSHOT,
- TEST_BUILD_ADDR_SNAPSHOT
-};
-
-static int use_ipnode_functions = 0;
-static int use_ipv6_mapping = 0;
-static int ipnode_flags = 0;
-static int debug = 0;
-static int af_type = AF_INET;
-static enum test_methods method = TEST_BUILD_SNAPSHOT;
-
-DECLARE_TEST_DATA(hostent)
-DECLARE_TEST_FILE_SNAPSHOT(hostent)
-DECLARE_1PASS_TEST(hostent)
-DECLARE_2PASS_TEST(hostent)
-
-/* These stubs will use gethostby***() or getipnodeby***() functions,
- * depending on the use_ipnode_functions global variable value */
-static struct hostent *__gethostbyname2(const char *, int);
-static struct hostent *__gethostbyaddr(const void *, socklen_t, int);
-static void __freehostent(struct hostent *);
-
-static void clone_hostent(struct hostent *, struct hostent const *);
-static int compare_hostent(struct hostent *, struct hostent *, void *);
-static void dump_hostent(struct hostent *);
-static void free_hostent(struct hostent *);
-
-static int is_hostent_equal(struct hostent *, struct addrinfo *);
-
-static void sdump_hostent(struct hostent *, char *, size_t);
-static int hostent_read_hostlist_func(struct hostent *, char *);
-static int hostent_read_snapshot_addr(char *, unsigned char *, size_t);
-static int hostent_read_snapshot_func(struct hostent *, char *);
-
-static int hostent_test_correctness(struct hostent *, void *);
-static int hostent_test_gethostbyaddr(struct hostent *, void *);
-static int hostent_test_getaddrinfo_eq(struct hostent *, void *);
-static int hostent_test_getnameinfo_eq(struct hostent *, void *);
-
-static void usage(void) __attribute__((__noreturn__));
-
-IMPLEMENT_TEST_DATA(hostent)
-IMPLEMENT_TEST_FILE_SNAPSHOT(hostent)
-IMPLEMENT_1PASS_TEST(hostent)
-IMPLEMENT_2PASS_TEST(hostent)
-
-static struct hostent *
-__gethostbyname2(const char *name, int af)
-{
- struct hostent *he;
- int error;
-
- if (use_ipnode_functions == 0)
- he = gethostbyname2(name, af);
- else {
- error = 0;
- he = getipnodebyname(name, af, ipnode_flags, &error);
- if (he == NULL)
- errno = error;
- }
-
- return (he);
-}
-
-static struct hostent *
-__gethostbyaddr(const void *addr, socklen_t len, int af)
-{
- struct hostent *he;
- int error;
-
- if (use_ipnode_functions == 0)
- he = gethostbyaddr(addr, len, af);
- else {
- error = 0;
- he = getipnodebyaddr(addr, len, af, &error);
- if (he == NULL)
- errno = error;
- }
-
- return (he);
-}
-
-static void
-__freehostent(struct hostent *he)
-{
- /* NOTE: checking for he != NULL - just in case */
- if ((use_ipnode_functions != 0) && (he != NULL))
- freehostent(he);
-}
-
-static void
-clone_hostent(struct hostent *dest, struct hostent const *src)
-{
- assert(dest != NULL);
- assert(src != NULL);
-
- char **cp;
- int aliases_num;
- int addrs_num;
- size_t offset;
-
- memset(dest, 0, sizeof(struct hostent));
-
- if (src->h_name != NULL) {
- dest->h_name = strdup(src->h_name);
- assert(dest->h_name != NULL);
- }
-
- dest->h_addrtype = src->h_addrtype;
- dest->h_length = src->h_length;
-
- if (src->h_aliases != NULL) {
- aliases_num = 0;
- for (cp = src->h_aliases; *cp; ++cp)
- ++aliases_num;
-
- dest->h_aliases = (char **)malloc((aliases_num + 1) *
- (sizeof(char *)));
- assert(dest->h_aliases != NULL);
- memset(dest->h_aliases, 0, (aliases_num + 1) *
- (sizeof(char *)));
-
- for (cp = src->h_aliases; *cp; ++cp) {
- dest->h_aliases[cp - src->h_aliases] = strdup(*cp);
- assert(dest->h_aliases[cp - src->h_aliases] != NULL);
- }
- }
-
- if (src->h_addr_list != NULL) {
- addrs_num = 0;
- for (cp = src->h_addr_list; *cp; ++cp)
- ++addrs_num;
-
- dest->h_addr_list = (char **)malloc((addrs_num + 1) *
- (sizeof(char *)));
- assert(dest->h_addr_list != NULL);
- memset(dest->h_addr_list, 0, (addrs_num + 1) *
- (sizeof(char *)));
-
- for (cp = src->h_addr_list; *cp; ++cp) {
- offset = cp - src->h_addr_list;
- dest->h_addr_list[offset] =
- (char *)malloc(src->h_length);
- assert(dest->h_addr_list[offset] != NULL);
- memcpy(dest->h_addr_list[offset],
- src->h_addr_list[offset], src->h_length);
- }
- }
-}
-
-static void
-free_hostent(struct hostent *ht)
-{
- char **cp;
-
- assert(ht != NULL);
-
- free(ht->h_name);
-
- if (ht->h_aliases != NULL) {
- for (cp = ht->h_aliases; *cp; ++cp)
- free(*cp);
- free(ht->h_aliases);
- }
-
- if (ht->h_addr_list != NULL) {
- for (cp = ht->h_addr_list; *cp; ++cp)
- free(*cp);
- free(ht->h_addr_list);
- }
-}
-
-static int
-compare_hostent(struct hostent *ht1, struct hostent *ht2, void *mdata)
-{
- char **c1, **c2, **ct, **cb;
- int b;
-
- if (ht1 == ht2)
- return 0;
-
- if ((ht1 == NULL) || (ht2 == NULL))
- goto errfin;
-
- if ((ht1->h_name == NULL) || (ht2->h_name == NULL))
- goto errfin;
-
- if ((ht1->h_addrtype != ht2->h_addrtype) ||
- (ht1->h_length != ht2->h_length) ||
- (strcmp(ht1->h_name, ht2->h_name) != 0))
- goto errfin;
-
- c1 = ht1->h_aliases;
- c2 = ht2->h_aliases;
-
- if (((ht1->h_aliases == NULL) || (ht2->h_aliases == NULL)) &&
- (ht1->h_aliases != ht2->h_aliases))
- goto errfin;
-
- if ((c1 != NULL) && (c2 != NULL)) {
- cb = c1;
- for (;*c1; ++c1) {
- b = 0;
- for (ct = c2; *ct; ++ct) {
- if (strcmp(*c1, *ct) == 0) {
- b = 1;
- break;
- }
- }
- if (b == 0) {
- if (debug)
- printf("h1 aliases item can't be "\
- "found in h2 aliases\n");
- goto errfin;
- }
- }
-
- c1 = cb;
- for (;*c2; ++c2) {
- b = 0;
- for (ct = c1; *ct; ++ct) {
- if (strcmp(*c2, *ct) == 0) {
- b = 1;
- break;
- }
- }
- if (b == 0) {
- if (debug)
- printf("h2 aliases item can't be "\
- " found in h1 aliases\n");
- goto errfin;
- }
- }
- }
-
- c1 = ht1->h_addr_list;
- c2 = ht2->h_addr_list;
-
- if (((ht1->h_addr_list == NULL) || (ht2->h_addr_list== NULL)) &&
- (ht1->h_addr_list != ht2->h_addr_list))
- goto errfin;
-
- if ((c1 != NULL) && (c2 != NULL)) {
- cb = c1;
- for (;*c1; ++c1) {
- b = 0;
- for (ct = c2; *ct; ++ct) {
- if (memcmp(*c1, *ct, ht1->h_length) == 0) {
- b = 1;
- break;
- }
- }
- if (b == 0) {
- if (debug)
- printf("h1 addresses item can't be "\
- "found in h2 addresses\n");
- goto errfin;
- }
- }
-
- c1 = cb;
- for (;*c2; ++c2) {
- b = 0;
- for (ct = c1; *ct; ++ct) {
- if (memcmp(*c2, *ct, ht1->h_length) == 0) {
- b = 1;
- break;
- }
- }
- if (b == 0) {
- if (debug)
- printf("h2 addresses item can't be "\
- "found in h1 addresses\n");
- goto errfin;
- }
- }
- }
-
- return 0;
-
-errfin:
- if ((debug) && (mdata == NULL)) {
- printf("following structures are not equal:\n");
- dump_hostent(ht1);
- dump_hostent(ht2);
- }
-
- return (-1);
-}
-
-static int
-check_addrinfo_for_name(struct addrinfo *ai, char const *name)
-{
- struct addrinfo *ai2;
-
- for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
- if (strcmp(ai2->ai_canonname, name) == 0)
- return (0);
- }
-
- return (-1);
-}
-
-static int
-check_addrinfo_for_addr(struct addrinfo *ai, char const *addr,
- socklen_t addrlen, int af)
-{
- struct addrinfo *ai2;
-
- for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
- if (af != ai2->ai_family)
- continue;
-
- switch (af) {
- case AF_INET:
- if (memcmp(addr,
- (void *)&((struct sockaddr_in *)ai2->ai_addr)->sin_addr,
- min(addrlen, ai2->ai_addrlen)) == 0)
- return (0);
- break;
- case AF_INET6:
- if (memcmp(addr,
- (void *)&((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr,
- min(addrlen, ai2->ai_addrlen)) == 0)
- return (0);
- break;
- default:
- break;
- }
- }
-
- return (-1);
-}
-
-static int
-is_hostent_equal(struct hostent *he, struct addrinfo *ai)
-{
- char **cp;
- int rv;
-
- if (debug)
- printf("checking equality of he and ai\n");
-
- rv = check_addrinfo_for_name(ai, he->h_name);
- if (rv != 0) {
- if (debug)
- printf("not equal - he->h_name couldn't be found\n");
-
- return (rv);
- }
-
- for (cp = he->h_addr_list; *cp; ++cp) {
- rv = check_addrinfo_for_addr(ai, *cp, he->h_length,
- he->h_addrtype);
- if (rv != 0) {
- if (debug)
- printf("not equal - one of he->h_addr_list couldn't be found\n");
-
- return (rv);
- }
- }
-
- if (debug)
- printf("equal\n");
-
- return (0);
-}
-
-static void
-sdump_hostent(struct hostent *ht, char *buffer, size_t buflen)
-{
- char **cp;
- size_t i;
- int written;
-
- written = snprintf(buffer, buflen, "%s %d %d",
- ht->h_name, ht->h_addrtype, ht->h_length);
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
-
- if (ht->h_aliases != NULL) {
- if (*(ht->h_aliases) != NULL) {
- for (cp = ht->h_aliases; *cp; ++cp) {
- written = snprintf(buffer, buflen, " %s",*cp);
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
-
- if (buflen == 0)
- return;
- }
- } else {
- written = snprintf(buffer, buflen, " noaliases");
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
- }
- } else {
- written = snprintf(buffer, buflen, " (null)");
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
- }
-
- written = snprintf(buffer, buflen, " : ");
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
-
- if (ht->h_addr_list != NULL) {
- if (*(ht->h_addr_list) != NULL) {
- for (cp = ht->h_addr_list; *cp; ++cp) {
- for (i = 0; i < ht->h_length; ++i ) {
- written = snprintf(buffer, buflen,
- i + 1 != ht->h_length ? "%d." : "%d",
- (unsigned char)(*cp)[i]);
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
-
- if (buflen == 0)
- return;
- }
-
- if (*(cp + 1) ) {
- written = snprintf(buffer, buflen, " ");
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
- }
- }
- } else {
- written = snprintf(buffer, buflen, " noaddrs");
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
- }
- } else {
- written = snprintf(buffer, buflen, " (null)");
- buffer += written;
- if (written > buflen)
- return;
- buflen -= written;
- }
-}
-
-static int
-hostent_read_hostlist_func(struct hostent *he, char *line)
-{
- struct hostent *result;
- int rv;
-
- if (debug)
- printf("resolving %s: ", line);
- result = __gethostbyname2(line, af_type);
- if (result != NULL) {
- if (debug)
- printf("found\n");
-
- rv = hostent_test_correctness(result, NULL);
- if (rv != 0) {
- __freehostent(result);
- return (rv);
- }
-
- clone_hostent(he, result);
- __freehostent(result);
- } else {
- if (debug)
- printf("not found\n");
-
- memset(he, 0, sizeof(struct hostent));
- he->h_name = strdup(line);
- assert(he->h_name != NULL);
- }
- return (0);
-}
-
-static int
-hostent_read_snapshot_addr(char *addr, unsigned char *result, size_t len)
-{
- char *s, *ps, *ts;
-
- ps = addr;
- while ( (s = strsep(&ps, ".")) != NULL) {
- if (len == 0)
- return (-1);
-
- *result = (unsigned char)strtol(s, &ts, 10);
- ++result;
- if (*ts != '\0')
- return (-1);
-
- --len;
- }
- if (len != 0)
- return (-1);
- else
- return (0);
-}
-
-static int
-hostent_read_snapshot_func(struct hostent *ht, char *line)
-{
- StringList *sl1, *sl2;
- char *s, *ps, *ts;
- int i, rv;
-
- if (debug)
- printf("1 line read from snapshot:\n%s\n", line);
-
- rv = 0;
- i = 0;
- sl1 = sl2 = NULL;
- ps = line;
- memset(ht, 0, sizeof(struct hostent));
- while ( (s = strsep(&ps, " ")) != NULL) {
- switch (i) {
- case 0:
- ht->h_name = strdup(s);
- assert(ht->h_name != NULL);
- break;
-
- case 1:
- ht->h_addrtype = (int)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
- break;
-
- case 2:
- ht->h_length = (int)strtol(s, &ts, 10);
- if (*ts != '\0')
- goto fin;
- break;
-
- case 3:
- if (sl1 == NULL) {
- if (strcmp(s, "(null)") == 0)
- return (0);
-
- sl1 = sl_init();
- assert(sl1 != NULL);
-
- if (strcmp(s, "noaliases") != 0) {
- ts = strdup(s);
- assert(ts != NULL);
- sl_add(sl1, ts);
- }
- } else {
- if (strcmp(s, ":") == 0)
- ++i;
- else {
- ts = strdup(s);
- assert(ts != NULL);
- sl_add(sl1, ts);
- }
- }
- break;
-
- case 4:
- if (sl2 == NULL) {
- if (strcmp(s, "(null)") == 0)
- return (0);
-
- sl2 = sl_init();
- assert(sl2 != NULL);
-
- if (strcmp(s, "noaddrs") != 0) {
- ts = (char *)malloc(ht->h_length);
- assert(ts != NULL);
- memset(ts, 0, ht->h_length);
- rv = hostent_read_snapshot_addr(s,\
- (unsigned char *)ts, ht->h_length);
- sl_add(sl2, ts);
- if (rv != 0)
- goto fin;
- }
- } else {
- ts = (char *)malloc(ht->h_length);
- assert(ts != NULL);
- memset(ts, 0, ht->h_length);
- rv = hostent_read_snapshot_addr(s,\
- (unsigned char *)ts, ht->h_length);
- sl_add(sl2, ts);
- if (rv != 0)
- goto fin;
- }
- break;
- default:
- break;
- };
-
- if ((i != 3) && (i != 4))
- ++i;
- }
-
-fin:
- if (sl1 != NULL) {
- sl_add(sl1, NULL);
- ht->h_aliases = sl1->sl_str;
- }
- if (sl2 != NULL) {
- sl_add(sl2, NULL);
- ht->h_addr_list = sl2->sl_str;
- }
-
- if ((i != 4) || (rv != 0)) {
- free_hostent(ht);
- memset(ht, 0, sizeof(struct hostent));
- return (-1);
- }
-
- /* NOTE: is it a dirty hack or not? */
- free(sl1);
- free(sl2);
- return (0);
-}
-
-static void
-dump_hostent(struct hostent *result)
-{
- if (result != NULL) {
- char buffer[1024];
- sdump_hostent(result, buffer, sizeof(buffer));
- printf("%s\n", buffer);
- } else
- printf("(null)\n");
-}
-
-static int
-hostent_test_correctness(struct hostent *ht, void *mdata)
-{
- if (debug) {
- printf("testing correctness with the following data:\n");
- dump_hostent(ht);
- }
-
- if (ht == NULL)
- goto errfin;
-
- if (ht->h_name == NULL)
- goto errfin;
-
- if (!((ht->h_addrtype >= 0) && (ht->h_addrtype < AF_MAX)))
- goto errfin;
-
- if ((ht->h_length != sizeof(struct in_addr)) &&
- (ht->h_length != sizeof(struct in6_addr)))
- goto errfin;
-
- if (ht->h_aliases == NULL)
- goto errfin;
-
- if (ht->h_addr_list == NULL)
- goto errfin;
-
- if (debug)
- printf("correct\n");
-
- return (0);
-errfin:
- if (debug)
- printf("incorrect\n");
-
- return (-1);
-}
-
-static int
-hostent_test_gethostbyaddr(struct hostent *he, void *mdata)
-{
- struct hostent *result;
- struct hostent_test_data *addr_test_data;
- int rv;
-
- addr_test_data = (struct hostent_test_data *)mdata;
-
- /* We should omit unresolved hostents */
- if (he->h_addr_list != NULL) {
- char **cp;
- for (cp = he->h_addr_list; *cp; ++cp) {
- if (debug)
- printf("doing reverse lookup for %s\n", he->h_name);
-
- result = __gethostbyaddr(*cp, he->h_length,
- he->h_addrtype);
- if (result == NULL) {
- if (debug)
- printf("warning: reverse lookup failed\n");
-
- continue;
- }
- rv = hostent_test_correctness(result, NULL);
- if (rv != 0) {
- __freehostent(result);
- return (rv);
- }
-
- if (addr_test_data != NULL)
- TEST_DATA_APPEND(hostent, addr_test_data, result);
-
- __freehostent(result);
- }
- }
-
- return (0);
-}
-
-static int
-hostent_test_getaddrinfo_eq(struct hostent *he, void *mdata)
-{
- struct addrinfo *ai, hints;
- int rv;
-
- ai = NULL;
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = af_type;
- hints.ai_flags = AI_CANONNAME;
-
- if (debug)
- printf("using getaddrinfo() to resolve %s\n", he->h_name);
-
- /* struct hostent *he was not resolved */
- if (he->h_addr_list == NULL) {
- /* We can be sure that he->h_name is not NULL */
- rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
- if (rv == 0) {
- if (debug)
- printf("not ok - shouldn't have been resolved\n");
- return (-1);
- }
- } else {
- rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
- if (rv != 0) {
- if (debug)
- printf("not ok - should have beed resolved\n");
- return (-1);
- }
-
- rv = is_hostent_equal(he, ai);
- if (rv != 0) {
- if (debug)
- printf("not ok - addrinfo and hostent are not equal\n");
- return (-1);
- }
-
- }
-
- return (0);
-}
-
-static int
-hostent_test_getnameinfo_eq(struct hostent *he, void *mdata)
-{
- char buffer[NI_MAXHOST];
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- struct sockaddr *saddr;
- struct hostent *result;
- int rv;
-
- if (he->h_addr_list != NULL) {
- char **cp;
- for (cp = he->h_addr_list; *cp; ++cp) {
- if (debug)
- printf("doing reverse lookup for %s\n", he->h_name);
-
- result = __gethostbyaddr(*cp, he->h_length,
- he->h_addrtype);
- if (result != NULL) {
- rv = hostent_test_correctness(result, NULL);
- if (rv != 0) {
- __freehostent(result);
- return (rv);
- }
- } else {
- if (debug)
- printf("reverse lookup failed\n");
- }
-
- switch (he->h_addrtype) {
- case AF_INET:
- memset(&sin, 0, sizeof(struct sockaddr_in));
- sin.sin_len = sizeof(struct sockaddr_in);
- sin.sin_family = AF_INET;
- memcpy(&sin.sin_addr, *cp, he->h_length);
-
- saddr = (struct sockaddr *)&sin;
- break;
- case AF_INET6:
- memset(&sin6, 0, sizeof(struct sockaddr_in6));
- sin6.sin6_len = sizeof(struct sockaddr_in6);
- sin6.sin6_family = AF_INET6;
- memcpy(&sin6.sin6_addr, *cp, he->h_length);
-
- saddr = (struct sockaddr *)&sin6;
- break;
- default:
- if (debug)
- printf("warning: %d family is unsupported\n",
- he->h_addrtype);
- continue;
- }
-
- assert(saddr != NULL);
- rv = getnameinfo(saddr, saddr->sa_len, buffer,
- sizeof(buffer), NULL, 0, NI_NAMEREQD);
-
- if ((rv != 0) && (result != NULL)) {
- if (debug)
- printf("not ok - getnameinfo() didn't make the reverse lookup, when it should have (%s)\n",
- gai_strerror(rv));
- return (rv);
- }
-
- if ((rv == 0) && (result == NULL)) {
- if (debug)
- printf("not ok - getnameinfo() made the reverse lookup, when it shouldn't have\n");
- return (rv);
- }
-
- if ((rv != 0) && (result == NULL)) {
- if (debug)
- printf("ok - both getnameinfo() and ***byaddr() failed\n");
-
- continue;
- }
-
- if (debug)
- printf("comparing %s with %s\n", result->h_name,
- buffer);
-
- rv = strcmp(result->h_name, buffer);
- __freehostent(result);
-
- if (rv != 0) {
- if (debug)
- printf("not ok - getnameinfo() and ***byaddr() results are not equal\n");
- return (rv);
- } else {
- if (debug)
- printf("ok - getnameinfo() and ***byaddr() results are equal\n");
- }
- }
- }
-
- return (0);
-}
-
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "Usage: %s -na2i [-o] [-d] [-46] [-mAcM] [-C] [-s <file>] -f <file>\n",
- getprogname());
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- struct hostent_test_data td, td_addr, td_snap;
- char *snapshot_file, *hostlist_file;
- res_state statp;
- int rv;
- int c;
-
- if (argc < 2)
- usage();
-
- snapshot_file = NULL;
- hostlist_file = NULL;
- while ((c = getopt(argc, argv, "nad2iod46mAcMs:f:")) != -1)
- switch (c) {
- case '4':
- af_type = AF_INET;
- break;
- case '6':
- af_type = AF_INET6;
- break;
- case 'M':
- af_type = AF_INET6;
- use_ipv6_mapping = 1;
- ipnode_flags |= AI_V4MAPPED_CFG;
- break;
- case 'm':
- af_type = AF_INET6;
- use_ipv6_mapping = 1;
- ipnode_flags |= AI_V4MAPPED;
- break;
- case 'c':
- ipnode_flags |= AI_ADDRCONFIG;
- break;
- case 'A':
- ipnode_flags |= AI_ALL;
- break;
- case 'o':
- use_ipnode_functions = 1;
- break;
- case 'd':
- debug = 1;
- break;
- case 'n':
- method = TEST_GETHOSTBYNAME2;
- break;
- case 'a':
- method = TEST_GETHOSTBYADDR;
- break;
- case '2':
- method = TEST_GETHOSTBYNAME2_GETADDRINFO;
- break;
- case 'i':
- method = TEST_GETHOSTBYADDR_GETNAMEINFO;
- break;
- case 's':
- snapshot_file = strdup(optarg);
- break;
- case 'f':
- hostlist_file = strdup(optarg);
- break;
- default:
- usage();
- }
-
- if (use_ipnode_functions == 0) {
- statp = __res_state();
- if ((statp == NULL) || ((statp->options & RES_INIT) == 0 &&
- res_ninit(statp) == -1)) {
- if (debug)
- printf("error: can't init res_state\n");
-
- free(snapshot_file);
- free(hostlist_file);
- return (-1);
- }
-
- if (use_ipv6_mapping == 0)
- statp->options &= ~RES_USE_INET6;
- else
- statp->options |= RES_USE_INET6;
- }
-
- TEST_DATA_INIT(hostent, &td, clone_hostent, free_hostent);
- TEST_DATA_INIT(hostent, &td_addr, clone_hostent, free_hostent);
- TEST_DATA_INIT(hostent, &td_snap, clone_hostent, free_hostent);
-
- if (hostlist_file == NULL)
- usage();
-
- if (access(hostlist_file, R_OK) != 0) {
- if (debug)
- printf("can't access the hostlist file %s\n",
- hostlist_file);
-
- usage();
- }
-
- if (debug)
- printf("building host lists from %s\n", hostlist_file);
-
- rv = TEST_SNAPSHOT_FILE_READ(hostent, hostlist_file, &td,
- hostent_read_hostlist_func);
- if (rv != 0)
- goto fin;
-
- if (snapshot_file != NULL) {
- if (access(snapshot_file, W_OK | R_OK) != 0) {
- if (errno == ENOENT) {
- if (method != TEST_GETHOSTBYADDR)
- method = TEST_BUILD_SNAPSHOT;
- else
- method = TEST_BUILD_ADDR_SNAPSHOT;
- } else {
- if (debug)
- printf("can't access the snapshot file %s\n",
- snapshot_file);
-
- rv = -1;
- goto fin;
- }
- } else {
- rv = TEST_SNAPSHOT_FILE_READ(hostent, snapshot_file,
- &td_snap, hostent_read_snapshot_func);
- if (rv != 0) {
- if (debug)
- printf("error reading snapshot file\n");
- goto fin;
- }
- }
- }
-
- switch (method) {
- case TEST_GETHOSTBYNAME2:
- if (snapshot_file != NULL)
- rv = DO_2PASS_TEST(hostent, &td, &td_snap,
- compare_hostent, NULL);
- break;
- case TEST_GETHOSTBYADDR:
- rv = DO_1PASS_TEST(hostent, &td,
- hostent_test_gethostbyaddr, (void *)&td_addr);
-
- if (snapshot_file != NULL)
- rv = DO_2PASS_TEST(hostent, &td_addr, &td_snap,
- compare_hostent, NULL);
- break;
- case TEST_GETHOSTBYNAME2_GETADDRINFO:
- rv = DO_1PASS_TEST(hostent, &td,
- hostent_test_getaddrinfo_eq, NULL);
- break;
- case TEST_GETHOSTBYADDR_GETNAMEINFO:
- rv = DO_1PASS_TEST(hostent, &td,
- hostent_test_getnameinfo_eq, NULL);
- break;
- case TEST_BUILD_SNAPSHOT:
- if (snapshot_file != NULL) {
- rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file, &td,
- sdump_hostent);
- }
- break;
- case TEST_BUILD_ADDR_SNAPSHOT:
- if (snapshot_file != NULL) {
- rv = DO_1PASS_TEST(hostent, &td,
- hostent_test_gethostbyaddr, (void *)&td_addr);
-
- rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file,
- &td_addr, sdump_hostent);
- }
- break;
- default:
- rv = 0;
- break;
- };
-
-fin:
- TEST_DATA_DESTROY(hostent, &td_snap);
- TEST_DATA_DESTROY(hostent, &td_addr);
- TEST_DATA_DESTROY(hostent, &td);
- free(hostlist_file);
- free(snapshot_file);
-
- return (rv);
-}
-
diff --git a/tools/regression/lib/libc/nss/test-gethostby.t b/tools/regression/lib/libc/nss/test-gethostby.t
deleted file mode 100644
index 42bed00..0000000
--- a/tools/regression/lib/libc/nss/test-gethostby.t
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..46
-#Tests for gethostby***() functions
-#IPv4-driven testing
-do_test 1 'gethostbyname2() (IPv4)' '-4 -n -f mach'
-do_test 2 'gethostbyaddr() (IPv4)' '-4 -a -f mach'
-do_test 3 'gethostbyname2()-getaddrinfo() (IPv4)' '-4 -2 -f mach'
-do_test 4 'gethostbyaddr()-getnameinfo() (IPv4)' '-4 -i -f mach'
-do_test 5 'gethostbyname2() snapshot (IPv4)'\
- '-4 -n -s snapshot_htname4 -f mach'
-do_test 6 'gethostbyaddr() snapshot (IPv4)'\
- '-4 -a -s snapshot_htaddr4 -f mach'
-
-#IPv6-driven testing
-do_test 7 'gethostbyname2() (IPv6)' '-6 -n -f mach'
-do_test 8 'gethostbyaddr() (IPv6)' '-6 -a -f mach'
-do_test 9 'gethostbyname2()-getaddrinfo() (IPv6)' '-6 -2 -f mach'
-do_test 10 'gethostbyaddr()-getnameinfo() (IPv6)' '-6 -i -f mach'
-do_test 11 'gethostbyname2() snapshot (IPv6)'\
- '-6 -n -s snapshot_htname6 -f mach'
-do_test 12 'gethostbyaddr() snapshot (IPv6)'\
- '-6 -a -s snapshot_htaddr6 -f mach'
-
-#Mapped IPv6-driven testing (getaddrinfo() equality test is useless here)
-do_test 13 'gethostbyname2() (IPv6 mapped)' '-m -n -f mach'
-do_test 14 'gethostbyaddr() (IPv6 mapped)' '-m -a -f mach'
-do_test 15 'gethostbyname2() snapshot (IPv6 mapped)'\
- '-m -n -s snapshot_htname6map -f mach'
-do_test 16 'gethostbyaddr() snapshot (IPv6 mapped)'\
- '-m -a -s snapshot_htaddr6map -f mach'
-
-#Tests for getipnodeby***() functions
-#IPv4-driven testing, flags are 0
-do_test 17 'getipnodebyname() (IPv4)' '-o -4 -n -f mach'
-do_test 18 'getipnodebyaddr() (IPv4)' '-o -4 -a -f mach'
-do_test 19 'getipnodebyname()-getaddrinfo() (IPv4)' '-o -4 -2 -f mach'
-do_test 20 'getipnodebyaddr()-getnameinfo() (IPv4)' '-o -4 -i -f mach'
-do_test 21 'getipnodebyname() snapshot (IPv4)'\
- '-o -4 -n -s snapshot_ipnodename4 -f mach'
-do_test 22 'getipnodebyname() snapshot (IPv4)'\
- '-o -4 -a -s snapshot_ipnodeaddr4 -f mach'
-
-#IPv6-driven testing, flags are 0
-do_test 23 'getipnodebyname() (IPv6)' '-o -6 -n -f mach'
-do_test 24 'getipnodebyaddr() (IPv6)' '-o -6 -a -f mach'
-do_test 25 'getipnodebyname()-getaddrinfo() (IPv6)' '-o -6 -2 -f mach'
-do_test 26 'getipnodebyaddr()-getnameinfo() (IPv6)' '-o -6 -i -f mach'
-do_test 27 'getipnodebyname() snapshot (IPv6)'\
- '-o -6 -n -s snapshot_ipnodename6 -f mach'
-do_test 28 'getipnodebyaddr() snapshot (IPv6)'\
- '-o -6 -a -s snapshot_ipnodeaddr6 -f mach'
-
-#Mapped IPv6-driven testing, flags are AI_V4MAPPED
-do_test 29 'getipnodebyname() (IPv6, AI_V4MAPPED)' '-o -m -n -f mach'
-do_test 30 'getipnodebyaddr() (IPv6, AI_V4MAPPED)' '-o -m -a -f mach'
-do_test 31 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED)'\
- '-o -m -n -s snapshot_ipnodename6_AI_V4MAPPED -f mach'
-do_test 32 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED)'\
- '-o -m -a -s snapshot_ipnodeaddr6_AI_V4MAPPED -f mach'
-
-#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG
-do_test 33 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG)' '-o -M -n -f mach'
-do_test 34 'getipnodebyaddr() (IPv6, AI_V4MAPPED_CFG)' '-o -M -a -f mach'
-do_test 35 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG)'\
- '-o -M -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG -f mach'
-do_test 36 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED_CFG)'\
- '-o -M -a -s snapshot_ipnodeaddr6_AI_V4MAPPED_CFG -f mach'
-
-#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG | AI_ALL
-do_test 37 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\
- '-o -MA -n -f mach'
-do_test 38 'getipnodebyaddr() (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\
- '-o -MA -a -f mach'
-do_test 39 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\
- '-o -MA -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ALL -f mach'
-do_test 40 'getipnodebyaddr() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ALL)'\
- '-o -MA -a -s snapshot_ipnodeaddr6_AI_V4MAPPED_CFG_AI_ALL -f mach'
-
-#Mapped IPv6-driven testing, flags are AI_V4MAPPED_CFG | AI_ADDRCONFIG
-do_test 41 'getipnodebyname() (IPv6, AI_V4MAPPED_CFG | AI_ADDRCONFIG)'\
- '-o -Mc -n -f mach'
-do_test 42 'getipnodebyname() snapshot (IPv6, AI_V4MAPPED_CFG | AI_ADDRCONFIG)'\
- '-o -Mc -n -s snapshot_ipnodename6_AI_V4MAPPED_CFG_AI_ADDRCONFIG -f mach'
-
-#IPv4-driven testing, flags are AI_ADDRCONFIG
-do_test 43 'getipnodebyname() (IPv4, AI_ADDRCONFIG)' '-o -4c -n -f mach'
-do_test 44 'getipnodebyname() snapshot (IPv4, AI_ADDRCONFIG)'\
- '-o -4c -n -s snapshot_ipnodename4_AI_ADDRCONFIG -f mach'
-
-#IPv6-driven testing, flags are AI_ADDRCONFIG
-do_test 45 'getipnodebyname() (IPv6, AI_ADDRCONFIG)' '-o -6c -n -f mach'
-do_test 46 'getipnodebyname() snapshot (IPv6, AI_ADDRCONFIG)'\
- '-o -6c -n -s snapshot_ipnodename6_AI_ADDRCONFIG -f mach'
-
diff --git a/tools/regression/lib/libc/nss/test-getproto.t b/tools/regression/lib/libc/nss/test-getproto.t
deleted file mode 100644
index f582d31..0000000
--- a/tools/regression/lib/libc/nss/test-getproto.t
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..8
-do_test 1 'getprotobyname()' '-n'
-do_test 2 'getprotobynumber()' '-v'
-do_test 3 'getprotoent()' '-e'
-do_test 4 'getprotoent() 2-pass' '-2'
-do_test 5 'building snapshot, if needed' '-s snapshot_proto'
-do_test 6 'getprotobyname() snapshot' '-n -s snapshot_proto'
-do_test 7 'getprotobynumber() snapshot' '-v -s snapshot_proto'
-do_test 8 'getprotoent() snapshot' '-e -s snapshot_proto'
diff --git a/tools/regression/lib/libc/nss/test-getpw.t b/tools/regression/lib/libc/nss/test-getpw.t
deleted file mode 100644
index 5172177..0000000
--- a/tools/regression/lib/libc/nss/test-getpw.t
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..8
-do_test 1 'getpwnam()' '-n'
-do_test 2 'getpwuid()' '-u'
-do_test 3 'getpwent()' '-e'
-do_test 4 'getpwent() 2-pass' '-2'
-do_test 5 'building snapshot, if needed' '-s snapshot_pwd'
-do_test 6 'getpwnam() snapshot' '-n -s snapshot_pwd'
-do_test 7 'getpwuid() snapshot' '-u -s snapshot_pwd'
-do_test 8 'getpwent() snapshot' '-e -s snapshot_pwd'
diff --git a/tools/regression/lib/libc/nss/test-getrpc.t b/tools/regression/lib/libc/nss/test-getrpc.t
deleted file mode 100644
index 831a086..0000000
--- a/tools/regression/lib/libc/nss/test-getrpc.t
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..8
-do_test 1 'getrpcbyname()' '-n'
-do_test 2 'getrpcbynumber()' '-v'
-do_test 3 'getrpcent()' '-e'
-do_test 4 'getrpcent() 2-pass' '-2'
-do_test 5 'building snapshot, if needed' '-s snapshot_rpc'
-do_test 6 'getrpcbyname() snapshot' '-n -s snapshot_rpc'
-do_test 7 'getrpcbynumber() snapshot' '-v -s snapshot_rpc'
-do_test 8 'getrpcent() snapshot' '-e -s snapshot_rpc'
diff --git a/tools/regression/lib/libc/nss/test-getserv.t b/tools/regression/lib/libc/nss/test-getserv.t
deleted file mode 100644
index 60a6c50..0000000
--- a/tools/regression/lib/libc/nss/test-getserv.t
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..8
-do_test 1 'getservbyname()' '-n'
-do_test 2 'getservbyport()' '-p'
-do_test 3 'getservent()' '-e'
-do_test 4 'getservent() 2-pass' '-2'
-do_test 5 'building snapshot, if needed' '-s snapshot_serv'
-do_test 6 'getservbyname() snapshot' '-n -s snapshot_serv'
-do_test 7 'getservbyport() snapshot' '-p -s snapshot_serv'
-do_test 8 'getservent() snapshot' '-e -s snapshot_serv'
diff --git a/tools/regression/lib/libc/nss/test-getusershell.t b/tools/regression/lib/libc/nss/test-getusershell.t
deleted file mode 100644
index 16a392a..0000000
--- a/tools/regression/lib/libc/nss/test-getusershell.t
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..1
-do_test 1 'getusershell() snapshot' '-s snapshot_usershell'
diff --git a/tools/regression/lib/libc/resolv/Makefile b/tools/regression/lib/libc/resolv/Makefile
deleted file mode 100644
index 18a71bc..0000000
--- a/tools/regression/lib/libc/resolv/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# $NetBSD: Makefile,v 1.1 2004/05/13 19:17:12 christos Exp $
-# $FreeBSD$
-
-PROG= resolv
-MAN=
-
-# Note: this test relies on being dynamically linked. You will get a
-# spurious PASS for a statically linked test.
-LIBADD+= pthread
-
-regress: ${PROG}
- ./${PROG} -r ${.CURDIR}/mach
-
-.include <bsd.prog.mk>
diff --git a/tools/regression/lib/libc/resolv/mach b/tools/regression/lib/libc/resolv/mach
deleted file mode 100644
index ab7ce24..0000000
--- a/tools/regression/lib/libc/resolv/mach
+++ /dev/null
@@ -1,93 +0,0 @@
-# $FreeBSD$
-localhost
-above.warped.net
-anoncvs.cirr.com
-anoncvs.isc.netbsd.org
-anoncvs.leo.org
-anoncvs.netbsd.lt
-anoncvs.netbsd.ro
-anoncvs.netbsd.se
-antioche.antioche.eu.org
-boulder.tele.dk
-centaurus.4web.cz
-chur.math.ntnu.no
-console.netbsd.org
-cvs.fi.netbsd.org
-cvs.mikrolahti.fi
-cvs.netbsd.org
-cvsup-netbsd.leo.org
-cvsup.netbsd.se
-cvsup.pasta.cs.uit.no
-ftp.bitcon.no
-ftp.chg.ru
-ftp.duth.gr
-ftp.estpak.ee
-ftp.fsn.hu
-ftp.funet.fi
-ftp.grondar.za
-ftp.leo.org
-ftp.netbsd.lt
-ftp.netbsd.org
-ftp.nluug.nl
-ftp.plig.org
-ftp.uni-erlangen.de
-ftp.xgate.co.kr
-gd.tuwien.ac.at
-gort.ludd.luth.se
-grappa.unix-ag.uni-kl.de
-info.wins.uva.nl
-irc.warped.net
-knug.youn.co.kr
-lala.iri.co.jp
-mail.jp.netbsd.org
-mail.kr.netbsd.org
-mail.netbsd.org
-melanoma.cs.rmit.edu.au
-mirror.aarnet.edu.au
-mirror.netbsd.com.br
-mirror03.inet.tele.dk
-moon.vub.ac.be
-nbwww.sergei.cc
-net.bsd.cz
-netbsd.3miasto.net
-netbsd.4ka.mipt.ru
-netbsd.apk.od.ua
-netbsd.csie.nctu.edu.tw
-netbsd.enderunix.org
-netbsd.ftp.fu-berlin.de
-netbsd.netlead.com.au
-netbsd.nsysu.edu.tw
-netbsd.pair.com
-netbsd.stevens-tech.edu
-netbsd.triada.bg
-netbsd.unix.net.nz
-netbsd.unixtech.be
-netbsd.vejas.lt
-netbsd.wagener-consulting.lu
-netbsd.zarco.org
-netbsdiso.interoute.net.uk
-netbsdwww.bitcon.no
-netbsdwww.cordef.com.pl
-netbsdwww.cs.rmit.edu.au
-netbsdwww.interoute.net.uk
-news.gw.com
-ns.netbsd.org
-pigu.iri.co.jp
-pluto.cdpa.nsysu.edu.tw
-projects.slowass.net
-server6.pasta.cs.uit.no
-skeleton.phys.spbu.ru
-snoopy.allbsd.org
-spike.allbsd.org
-sundry.netbsd.org
-tanya.sergei.cc
-web-a.fi.gw.com
-web-a.us.gw.com
-web.netbsd.mirror.arhea.net
-www.en.netbsd.de
-www.netbsd.cl
-www.netbsd.nl
-www.netbsd.org
-www.netbsd.ro
-zathras.netbsd.org
-zeppo.rediris.es
diff --git a/tools/regression/lib/libc/resolv/resolv.t b/tools/regression/lib/libc/resolv/resolv.t
deleted file mode 100644
index 278ba06..0000000
--- a/tools/regression/lib/libc/resolv/resolv.t
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-do_test() {
- number=$1
- comment=$2
- opt=$3
- if ./$executable $opt; then
- echo "ok $number - $comment"
- else
- echo "not ok $number - $comment"
- fi
-}
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-echo 1..3
-do_test 1 'getaddrinfo()' '-r mach'
-do_test 2 'gethostbyname()' '-rH mach'
-do_test 3 'getipnodebyname()' '-rI mach'
diff --git a/tools/regression/lib/msun/Makefile b/tools/regression/lib/msun/Makefile
index dbf582f..8b301cb 100644
--- a/tools/regression/lib/msun/Makefile
+++ b/tools/regression/lib/msun/Makefile
@@ -1,10 +1,8 @@
# $FreeBSD$
-TESTS= test-cexp test-conj test-csqrt test-ctrig \
- test-exponential test-fenv test-fma \
- test-fmaxmin test-ilogb test-invtrig test-invctrig \
- test-logarithm test-lrint \
- test-lround test-nan test-nearbyint test-next test-rem test-trig
+TESTS= test-ctrig \
+ test-exponential test-fma \
+ test-lround test-nearbyint test-next test-rem test-trig
CFLAGS+= -O0 -lm -Wno-unknown-pragmas
.PHONY: tests
diff --git a/tools/regression/lib/msun/test-cexp.t b/tools/regression/lib/msun/test-cexp.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-cexp.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-conj.t b/tools/regression/lib/msun/test-conj.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-conj.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-csqrt.t b/tools/regression/lib/msun/test-csqrt.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-csqrt.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-fenv.t b/tools/regression/lib/msun/test-fenv.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-fenv.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-fmaxmin.t b/tools/regression/lib/msun/test-fmaxmin.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-fmaxmin.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-ilogb.t b/tools/regression/lib/msun/test-ilogb.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-ilogb.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-logarithm.t b/tools/regression/lib/msun/test-logarithm.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-logarithm.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-lrint.t b/tools/regression/lib/msun/test-lrint.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-lrint.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-nan.t b/tools/regression/lib/msun/test-nan.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-nan.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-nearbyint.t b/tools/regression/lib/msun/test-nearbyint.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-nearbyint.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-next.t b/tools/regression/lib/msun/test-next.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-next.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-rem.t b/tools/regression/lib/msun/test-rem.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-rem.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/tools/regression/lib/msun/test-trig.t b/tools/regression/lib/msun/test-trig.t
deleted file mode 100644
index 8bdfd03..0000000
--- a/tools/regression/lib/msun/test-trig.t
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-cd `dirname $0`
-
-executable=`basename $0 .t`
-
-make $executable 2>&1 > /dev/null
-
-exec ./$executable
diff --git a/usr.bin/netstat/ipsec.c b/usr.bin/netstat/ipsec.c
index f3309ff..1347a93 100644
--- a/usr.bin/netstat/ipsec.c
+++ b/usr.bin/netstat/ipsec.c
@@ -216,10 +216,17 @@ ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ipsecstat ipsecstat;
- if (off == 0)
- return;
+ if (strcmp(name, "ipsec6") == 0) {
+ if (fetch_stats("net.inet6.ipsec6.ipsecstats", off,&ipsecstat,
+ sizeof(ipsecstat), kread_counters) != 0)
+ return;
+ } else {
+ if (fetch_stats("net.inet.ipsec.ipsecstats", off, &ipsecstat,
+ sizeof(ipsecstat), kread_counters) != 0)
+ return;
+ }
+
xo_emit("{T:/%s}:\n", name);
- kread_counters(off, (char *)&ipsecstat, sizeof(ipsecstat));
print_ipsecstats(&ipsecstat);
}
@@ -318,10 +325,11 @@ ah_stats(u_long off, const char *name, int family __unused, int proto __unused)
{
struct ahstat ahstat;
- if (off == 0)
+ if (fetch_stats("net.inet.ah.stats", off, &ahstat,
+ sizeof(ahstat), kread_counters) != 0)
return;
+
xo_emit("{T:/%s}:\n", name);
- kread_counters(off, (char *)&ahstat, sizeof(ahstat));
print_ahstats(&ahstat);
}
@@ -377,10 +385,11 @@ esp_stats(u_long off, const char *name, int family __unused, int proto __unused)
{
struct espstat espstat;
- if (off == 0)
+ if (fetch_stats("net.inet.esp.stats", off, &espstat,
+ sizeof(espstat), kread_counters) != 0)
return;
+
xo_emit("{T:/%s}:\n", name);
- kread_counters(off, (char *)&espstat, sizeof(espstat));
print_espstats(&espstat);
}
@@ -434,10 +443,11 @@ ipcomp_stats(u_long off, const char *name, int family __unused,
{
struct ipcompstat ipcompstat;
- if (off == 0)
+ if (fetch_stats("net.inet.ipcomp.stats", off, &ipcompstat,
+ sizeof(ipcompstat), kread_counters) != 0)
return;
+
xo_emit("{T:/%s}:\n", name);
- kread_counters(off, (char *)&ipcompstat, sizeof(ipcompstat));
print_ipcompstats(&ipcompstat);
}
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
index ce9e81a..e8cf914 100644
--- a/usr.bin/netstat/main.c
+++ b/usr.bin/netstat/main.c
@@ -108,13 +108,13 @@ static struct protox {
igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP },
#ifdef IPSEC
{ -1, N_IPSEC4STAT, 1, NULL, /* keep as compat */
- ipsec_stats, NULL, "ipsec", 0, 0},
+ ipsec_stats, NULL, "ipsec", 1, 0},
{ -1, N_AHSTAT, 1, NULL,
- ah_stats, NULL, "ah", 0, 0},
+ ah_stats, NULL, "ah", 1, 0},
{ -1, N_ESPSTAT, 1, NULL,
- esp_stats, NULL, "esp", 0, 0},
+ esp_stats, NULL, "esp", 1, 0},
{ -1, N_IPCOMPSTAT, 1, NULL,
- ipcomp_stats, NULL, "ipcomp", 0, 0},
+ ipcomp_stats, NULL, "ipcomp", 1, 0},
#endif
{ N_RIPCBINFO, N_PIMSTAT, 1, protopr,
pim_stats, NULL, "pim", 1, IPPROTO_PIM },
@@ -146,7 +146,7 @@ static struct protox ip6protox[] = {
#endif
#ifdef IPSEC
{ -1, N_IPSEC6STAT, 1, NULL,
- ipsec_stats, NULL, "ipsec6", 0, 0 },
+ ipsec_stats, NULL, "ipsec6", 1, 0 },
#endif
#ifdef notyet
{ -1, N_PIM6STAT, 1, NULL,
diff --git a/usr.sbin/Makefile.arm b/usr.sbin/Makefile.arm
index b21bc52..590b8cd 100644
--- a/usr.sbin/Makefile.arm
+++ b/usr.sbin/Makefile.arm
@@ -1,4 +1,5 @@
# $FreeBSD$
-SUBDIR+= ofwdump
SUBDIR+= kgmon
+SUBDIR+= mount_smbfs
+SUBDIR+= ofwdump
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c
index 85cb67c..8c498ec 100644
--- a/usr.sbin/ndp/ndp.c
+++ b/usr.sbin/ndp/ndp.c
@@ -563,8 +563,8 @@ dump(struct sockaddr_in6 *addr, int cflag)
struct sockaddr_in6 *sin;
struct sockaddr_dl *sdl;
extern int h_errno;
- struct in6_nbrinfo *nbi;
struct timeval now;
+ u_long expire;
int addrwidth;
int llwidth;
int ifwidth;
@@ -676,52 +676,46 @@ again:;
llwidth, llwidth, ether_str(sdl), ifwidth, ifwidth, ifname);
/* Print neighbor discovery specific information */
- nbi = getnbrinfo(&sin->sin6_addr, sdl->sdl_index, 1);
- if (nbi) {
- if (nbi->expire > now.tv_sec) {
- printf(" %-9.9s",
- sec2str(nbi->expire - now.tv_sec));
- } else if (nbi->expire == 0)
- printf(" %-9.9s", "permanent");
- else
- printf(" %-9.9s", "expired");
+ expire = rtm->rtm_rmx.rmx_expire;
+ if (expire > now.tv_sec)
+ printf(" %-9.9s", sec2str(expire - now.tv_sec));
+ else if (expire == 0)
+ printf(" %-9.9s", "permanent");
+ else
+ printf(" %-9.9s", "expired");
- switch (nbi->state) {
- case ND6_LLINFO_NOSTATE:
- printf(" N");
- break;
+ switch (rtm->rtm_rmx.rmx_state) {
+ case ND6_LLINFO_NOSTATE:
+ printf(" N");
+ break;
#ifdef ND6_LLINFO_WAITDELETE
- case ND6_LLINFO_WAITDELETE:
- printf(" W");
- break;
+ case ND6_LLINFO_WAITDELETE:
+ printf(" W");
+ break;
#endif
- case ND6_LLINFO_INCOMPLETE:
- printf(" I");
- break;
- case ND6_LLINFO_REACHABLE:
- printf(" R");
- break;
- case ND6_LLINFO_STALE:
- printf(" S");
- break;
- case ND6_LLINFO_DELAY:
- printf(" D");
- break;
- case ND6_LLINFO_PROBE:
- printf(" P");
- break;
- default:
- printf(" ?");
- break;
- }
-
- isrouter = nbi->isrouter;
- prbs = nbi->asked;
- } else {
- warnx("failed to get neighbor information");
- printf(" ");
+ case ND6_LLINFO_INCOMPLETE:
+ printf(" I");
+ break;
+ case ND6_LLINFO_REACHABLE:
+ printf(" R");
+ break;
+ case ND6_LLINFO_STALE:
+ printf(" S");
+ break;
+ case ND6_LLINFO_DELAY:
+ printf(" D");
+ break;
+ case ND6_LLINFO_PROBE:
+ printf(" P");
+ break;
+ default:
+ printf(" ?");
+ break;
}
+ isrouter = rtm->rtm_flags & RTF_GATEWAY;
+ prbs = rtm->rtm_rmx.rmx_pksent;
+
/*
* other flags. R: router, P: proxy, W: ??
*/
OpenPOWER on IntegriCloud