Merge ^/head r293430 through r293685.

This commit is contained in:
Dimitry Andric 2016-01-11 19:36:44 +00:00
commit 89d3f0ea4e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang380-import/; revision=293687
193 changed files with 2461 additions and 2054 deletions

View File

@ -570,9 +570,8 @@ _worldtmp: .PHONY
.else
rm -rf ${WORLDTMP}/legacy/usr/include
# XXX - These three can depend on any header file.
rm -f ${OBJTREE}${.CURDIR}/usr.bin/kdump/ioctl.c
rm -f ${OBJTREE}${.CURDIR}/lib/libsysdecode/ioctl.c
rm -f ${OBJTREE}${.CURDIR}/usr.bin/kdump/kdump_subr.c
rm -f ${OBJTREE}${.CURDIR}/usr.bin/truss/ioctl.c
.endif
.for _dir in \
lib usr legacy/bin legacy/usr
@ -1425,11 +1424,13 @@ _vtfontcvt= usr.bin/vtfontcvt
_sed= usr.bin/sed
.endif
.if ${BOOTSTRAPPING} < 1000002
.if ${BOOTSTRAPPING} < 1000033
_libopenbsd= lib/libopenbsd
_m4= usr.bin/m4
_lex= usr.bin/lex
${_bt}-usr.bin/m4: ${_bt}-lib/libopenbsd
${_bt}-usr.bin/lex: ${_bt}-usr.bin/m4
.endif
.if ${BOOTSTRAPPING} < 1000026
@ -1443,12 +1444,6 @@ ${_bt}-usr.sbin/nmtree: ${_bt}-lib/libnetbsd
_cat= bin/cat
.endif
.if ${BOOTSTRAPPING} < 1000033
_lex= usr.bin/lex
${_bt}-usr.bin/lex: ${_bt}-usr.bin/m4
.endif
# r277259 crunchide: Correct 64-bit section header offset
# r281674 crunchide: always include both 32- and 64-bit ELF support
# r285986 crunchen: use STRIPBIN rather than STRIP

View File

@ -1039,12 +1039,12 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
reffunc(cmdentry.u.func);
savehandler = handler;
if (setjmp(jmploc.loc)) {
freeparam(&shellparam);
shellparam = saveparam;
popredir();
unreffunc(cmdentry.u.func);
poplocalvars();
localvars = savelocalvars;
freeparam(&shellparam);
shellparam = saveparam;
funcnest--;
handler = savehandler;
longjmp(handler->loc, 1);

View File

@ -111,6 +111,7 @@ FILES+= local1.0
FILES+= local2.0
FILES+= local3.0
FILES+= local4.0
FILES+= local5.0
.if ${MK_NLS} != "no"
FILES+= locale1.0
.endif

View File

@ -0,0 +1,15 @@
# $FreeBSD$
f() {
local PATH IFS elem
IFS=:
for elem in ''$PATH''; do
PATH=/var/empty/$elem:$PATH
done
ls -d / >/dev/null
}
p1=$(command -v ls)
f
p2=$(command -v ls)
[ "$p1" = "$p2" ]

View File

@ -791,6 +791,7 @@ poplocalvars(void)
{
struct localvar *lvp;
struct var *vp;
int islocalevar;
INTOFF;
while ((lvp = localvars) != NULL) {
@ -803,10 +804,20 @@ poplocalvars(void)
} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
(void)unsetvar(vp->text);
} else {
islocalevar = (vp->flags | lvp->flags) & VEXPORT &&
localevar(lvp->text);
if ((vp->flags & VTEXTFIXED) == 0)
ckfree(vp->text);
vp->flags = lvp->flags;
vp->text = lvp->text;
if (vp->func)
(*vp->func)(vp->text + vp->name_len + 1);
if (islocalevar) {
change_env(vp->text, vp->flags & VEXPORT &&
(vp->flags & VUNSET) == 0);
setlocale(LC_ALL, "");
updatecharset();
}
}
ckfree(lvp);
}

View File

@ -1437,7 +1437,7 @@ main(int argc, char *argv[])
for (;;) {
r = poll (hv_kvp_poll_fd, 1, 100);
r = poll (hv_kvp_poll_fd, 1, INFTIM);
KVP_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\n",
r, hv_kvp_poll_fd[0].revents);

View File

@ -2,6 +2,9 @@
GCCDIR= ${.CURDIR}/../../../contrib/gcc
GCCLIB= ${.CURDIR}/../../../contrib/gcclibs
COMPILERRTDIR= ${.CURDIR}/../../../contrib/compiler-rt
UNWINDINCDIR= ${.CURDIR}/../../../contrib/llvm/projects/libunwind/include
UNWINDSRCDIR= ${.CURDIR}/../../../contrib/llvm/projects/libunwind/src
SHLIB_NAME= libgcc_s.so.1
SHLIBDIR?= /lib
@ -67,8 +70,37 @@ LIB2ADD = $(LIB2FUNCS_EXTRA)
LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
# Additional sources to handle exceptions; overridden by targets as needed.
.if ${MK_LLVM_LIBUNWIND} != "no"
.PATH: ${COMPILERRTDIR}/lib/builtins
.PATH: ${UNWINDSRCDIR}
LIB2ADDEH = gcc_personality_v0.c \
int_util.c \
Unwind-EHABI.cpp \
Unwind-sjlj.c \
UnwindLevel1-gcc-ext.c \
UnwindLevel1.c \
UnwindRegistersRestore.S \
UnwindRegistersSave.S \
libunwind.cpp
CFLAGS+= -I${UNWINDINCDIR} -I${.CURDIR}
.if empty(CXXFLAGS:M-std=*)
CXXFLAGS+= -std=c++11
.endif
CXXFLAGS+= -fno-rtti
.else # MK_LLVM_LIBUNWIND
.if ${TARGET_CPUARCH} == "arm"
LIB2ADDEH = unwind-arm.c libunwind.S pr-support.c unwind-c.c
.else
LIB2ADDEH = unwind-dw2.c unwind-dw2-fde-glibc.c unwind-sjlj.c gthr-gnat.c \
unwind-c.c
.endif
.endif # MK_LLVM_LIBUNWIND
LIB2ADDEHSTATIC = $(LIB2ADDEH)
LIB2ADDEHSHARED = $(LIB2ADDEH)
@ -116,7 +148,6 @@ CFLAGS.clang+= -fheinous-gnu-extensions
LIB1ASMSRC = lib1funcs.asm
LIB1ASMFUNCS = _dvmd_tls _bb_init_func
LIB2ADDEH = unwind-arm.c libunwind.S pr-support.c unwind-c.c
# Some compilers generate __aeabi_ functions libgcc_s is missing
LIBADD+= compiler_rt
.endif
@ -160,7 +191,10 @@ LIB2_DIVMOD_FUNCS:= ${LIB2_DIVMOD_FUNCS:S/${sym}//g}
.endfor
.endif
COMMONHDRS= tm.h tconfig.h options.h unwind.h gthr-default.h
COMMONHDRS= tm.h tconfig.h options.h gthr-default.h
.if ${MK_LLVM_LIBUNWIND} == no
COMMONHDRS+= unwind.h
.endif
#-----------------------------------------------------------------------
#
@ -170,6 +204,9 @@ HIDE = -fvisibility=hidden -DHIDE_EXPORTS
CC_T = ${CC} -c ${CFLAGS} ${HIDE} -fPIC
CC_P = ${CC} -c ${CFLAGS} ${HIDE} -p -fPIC
CC_S = ${CC} -c ${CFLAGS} ${PICFLAG} -DSHARED
CXX_T = ${CXX} -c ${CXXFLAGS} ${HIDE} -fPIC
CXX_P = ${CXX} -c ${CXXFLAGS} ${HIDE} -p -fPIC
CXX_S = ${CXX} -c ${CXXFLAGS} ${PICFLAG} -DSHARED
#-----------------------------------------------------------------------
#
@ -284,16 +321,26 @@ EH_OBJS_S = ${LIB2ADDEHSHARED:R:S/$/.So/}
EH_CFLAGS = -fexceptions -D__GLIBC__=3 -DElfW=__ElfN
SOBJS += ${EH_OBJS_S}
.for _src in ${LIB2ADDEHSTATIC}
.for _src in ${LIB2ADDEHSTATIC:M*.c}
${_src:R:S/$/.o/}: ${_src} ${COMMONHDRS}
${CC_T} ${EH_CFLAGS} -o ${.TARGET} ${.IMPSRC}
${_src:R:S/$/.po/}: ${_src} ${COMMONHDRS}
${CC_P} ${EH_CFLAGS} -o ${.TARGET} ${.IMPSRC}
.endfor
.for _src in ${LIB2ADDEHSHARED}
.for _src in ${LIB2ADDEHSTATIC:M*.cpp}
${_src:R:S/$/.o/}: ${_src} ${COMMONHDRS}
${CXX_T} ${EH_CFLAGS} -o ${.TARGET} ${.IMPSRC}
${_src:R:S/$/.po/}: ${_src} ${COMMONHDRS}
${CXX_P} ${EH_CFLAGS} -o ${.TARGET} ${.IMPSRC}
.endfor
.for _src in ${LIB2ADDEHSHARED:M*.c}
${_src:R:S/$/.So/}: ${_src} ${COMMONHDRS}
${CC_S} ${EH_CFLAGS} -o ${.TARGET} ${.IMPSRC}
.endfor
.for _src in ${LIB2ADDEHSHARED:M*.cpp}
${_src:R:S/$/.So/}: ${_src} ${COMMONHDRS}
${CXX_S} ${EH_CFLAGS} -o ${.TARGET} ${.IMPSRC}
.endfor
#-----------------------------------------------------------------------

View File

@ -59,10 +59,12 @@
#define _POSIX_TZNAME_MAX 3
#endif
#if __POSIX_VISIBLE >= 200112
#define BC_BASE_MAX 99 /* max ibase/obase values in bc(1) */
#define BC_DIM_MAX 2048 /* max array elements in bc(1) */
#define BC_SCALE_MAX 99 /* max scale value in bc(1) */
#define BC_STRING_MAX 1000 /* max const string length in bc(1) */
#define CHARCLASS_NAME_MAX 14 /* max character class name size */
#define COLL_WEIGHTS_MAX 10 /* max weights for order keyword */
#define EXPR_NEST_MAX 32 /* max expressions nested in expr(1) */
#define LINE_MAX 2048 /* max bytes in an input line */
@ -72,11 +74,14 @@
#define _POSIX2_BC_DIM_MAX 2048
#define _POSIX2_BC_SCALE_MAX 99
#define _POSIX2_BC_STRING_MAX 1000
#define _POSIX2_CHARCLASS_NAME_MAX 14
#define _POSIX2_COLL_WEIGHTS_MAX 2
#define _POSIX2_EQUIV_CLASS_MAX 2
#define _POSIX2_EXPR_NEST_MAX 32
#define _POSIX2_LINE_MAX 2048
#define _POSIX2_RE_DUP_MAX 255
#endif
#endif
#if __POSIX_VISIBLE >= 199309
#define _POSIX_AIO_LISTIO_MAX 2
@ -110,8 +115,6 @@
#define _POSIX_TRACE_SYS_MAX 8
#define _POSIX_TRACE_USER_EVENT_MAX 32
#define _POSIX_TTY_NAME_MAX 9
#define _POSIX2_CHARCLASS_NAME_MAX 14
#define _POSIX2_COLL_WEIGHTS_MAX 2
#define _POSIX_RE_DUP_MAX _POSIX2_RE_DUP_MAX
#endif

View File

@ -7,6 +7,7 @@ OBJS= ${SRCS:N*.h:R:S/$/.o/g}
OBJS+= Scrt1.o gcrt1.o
CFLAGS+= -I${.CURDIR}/../common \
-I${.CURDIR}/../../libc/include
STATIC_CFLAGS+= -mlong-calls
FILES= ${OBJS}
FILESMODE= ${LIBMODE}
@ -23,14 +24,14 @@ CLEANFILES+= crt1.s gcrt1.s Scrt1.s
# directly compiled to .o files.
crt1.s: crt1.c
${CC} ${CFLAGS} -S -o ${.TARGET} ${.CURDIR}/crt1.c
${CC} ${CFLAGS} ${STATIC_CFLAGS} -S -o ${.TARGET} ${.CURDIR}/crt1.c
sed ${SED_FIX_NOTE} ${.TARGET}
crt1.o: crt1.s
${CC} ${ACFLAGS} -c -o ${.TARGET} crt1.s
gcrt1.s: crt1.c
${CC} ${CFLAGS} -DGCRT -S -o ${.TARGET} ${.CURDIR}/crt1.c
${CC} ${CFLAGS} ${STATIC_CFLAGS} -DGCRT -S -o ${.TARGET} ${.CURDIR}/crt1.c
sed ${SED_FIX_NOTE} ${.TARGET}
gcrt1.o: gcrt1.s

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 7, 2010
.Dd January 7, 2016
.Dt SENDFILE 2
.Os
.Sh NAME
@ -46,7 +46,7 @@
The
.Fn sendfile
system call
sends a regular file specified by descriptor
sends a regular file or shared memory object specified by descriptor
.Fa fd
out a stream socket specified by descriptor
.Fa s .
@ -101,32 +101,55 @@ the system will write the total number of bytes sent on the socket to the
variable pointed to by
.Fa sbytes .
.Pp
The
The least significant 16 bits of
.Fa flags
argument is a bitmap of these values:
.Bl -item -offset indent
.It
.Dv SF_NODISKIO .
This flag causes any
.Fn sendfile
call which would block on disk I/O to instead
return
.Er EBUSY .
Busy servers may benefit by transferring requests that would
block to a separate I/O worker thread.
.It
.Dv SF_MNOWAIT .
Do not wait for some kernel resource to become available,
in particular,
.Vt mbuf
and
.Vt sf_buf .
The flag does not make the
.Fn sendfile
syscall truly non-blocking, since other resources are still allocated
in a blocking fashion.
.It
.Dv SF_SYNC .
.Bl -tag -offset indent
.It Dv SF_NODISKIO
This flag causes
.Nm
to return
.Er EBUSY
instead of blocking when a busy page is encountered.
This rare situation can happen if some other process is now working
with the same region of the file.
It is advised to retry the operation after a short period.
.Pp
Note that in older
.Fx
versions the
.Dv SF_NODISKIO
had slightly different notion.
The flag prevented
.Nm
to run I/O operations in case if an invalid (not cached) page is encountered,
thus avoiding blocking on I/O.
Starting with
.Fx 11
.Nm
sending files off the
.Xr ffs 7
filesystem doesn't block on I/O
(see
.Sx IMPLEMENTATION NOTES
), so the condition no longer applies.
However, it is safe if an application utilizes
.Dv SF_NODISKIO
and on
.Er EBUSY
performs the same action as it did in
older
.Fx
versions, e.g.
.Xr aio_read 2,
.Xr read 2
or
.Nm
in a different context.
.It Dv SF_NOCACHE
The data sent to socket will not be cached by the virtual memory system,
and will be freed directly to the pool of free pages.
.It Dv SF_SYNC
.Nm
sleeps until the network stack no longer references the VM pages
of the file, making subsequent modifications to it safe.
@ -134,6 +157,22 @@ Please note that this is not a guarantee that the data has actually
been sent.
.El
.Pp
The most significant 16 bits of
.Fa flags
specify amount of pages that
.Nm
may read ahead when reading the file.
A macro
.Fn SF_FLAGS
is provided to combine readahead amount and flags.
Example shows specifing readahead of 16 pages and
.Dv SF_NOCACHE
flag:
.Pp
.Bd -literal -offset indent -compact
SF_FLAGS(16, SF_NOCACHE)
.Ed
.Pp
When using a socket marked for non-blocking I/O,
.Fn sendfile
may send fewer bytes than requested.
@ -149,6 +188,18 @@ The
.Fx
implementation of
.Fn sendfile
doesn't block on disk I/O when it sends a file off the
.Xr ffs 7
filesystem.
The syscall returns success before the actual I/O completes, and data
is put into the socket later unattended.
However, the order of data in the socket is preserved, so it is safe
to do further writes to the socket.
.Pp
The
.Fx
implementation of
.Fn sendfile
is "zero-copy", meaning that it has been optimized so that copying of the file data is avoided.
.Sh TUNING
On some architectures, this system call internally uses a special
@ -232,12 +283,10 @@ The
argument
is not a valid socket descriptor.
.It Bq Er EBUSY
Completing the entire transfer would have required disk I/O, so
it was aborted.
Partial data may have been sent.
(This error can only occur when
A busy page was encountered and
.Dv SF_NODISKIO
is specified.)
had been specified.
Partial data may have been sent.
.It Bq Er EFAULT
An invalid address was specified for an argument.
.It Bq Er EINTR
@ -310,9 +359,19 @@ first appeared in
.Fx 3.0 .
This manual page first appeared in
.Fx 3.1 .
In
.Fx 10
support for sending shared memory descriptors had been introduced.
In
.Fx 11
a non-blocking implementation had been introduced.
.Sh AUTHORS
The
The initial implementation of
.Fn sendfile
system call
and this manual page were written by
.An David G. Lawrence Aq Mt dg@dglawrence.com .
The
.Fx 11
implementation was written by
.An Gleb Smirnoff Aq Mt glebius@FreeBSD.org .

View File

@ -46,7 +46,7 @@ tohex(char **buf, int len, uint32_t val)
char *walker = *buf;
int i;
for (i = len - 1; i >= 0; i++) {
for (i = len - 1; i >= 0; i--) {
walker[i] = hexstr[val & 0xf];
val >>= 4;
}
@ -107,5 +107,5 @@ uuid_to_string(const uuid_t *u, char **s, uint32_t *status)
tohex(&w, 2, u->node[3]);
tohex(&w, 2, u->node[4]);
tohex(&w, 2, u->node[5]);
*w++ - '\0';
*w++ = '\0';
}

View File

@ -275,6 +275,7 @@ extra_chroot_setup() {
PBUILD_FLAGS="${PBUILD_FLAGS} OSREL=${REVISION}"
chroot ${CHROOTDIR} make -C /usr/ports/textproc/docproj \
${PBUILD_FLAGS} OPTIONS_UNSET="FOP IGOR" \
FORCE_PKG_REGISTER=1 \
install clean distclean
fi
fi

View File

@ -33,7 +33,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 9, 2014
.Dd January 11, 2016
.Dt ISMT 4
.Os
.Sh NAME
@ -54,6 +54,6 @@ in the Intel Atom S1200 and C2000 CPUs.
The
.Nm
driver first appeared in
.Fx 11.0 .
.Fx 10.3 .
.Sh AUTHORS
.An Jim Harris Aq Mt jimharris@FreeBSD.org

View File

@ -1,7 +1,7 @@
.\" DO NOT EDIT-- this file is automatically generated.
.\" from FreeBSD: head/tools/build/options/makeman 292283 2015-12-15 18:42:30Z bdrewery
.\" $FreeBSD$
.Dd December 15, 2015
.Dd January 9, 2016
.Dt SRC.CONF 5
.Os
.Sh NAME
@ -948,9 +948,30 @@ Set to not build the
.Nm libthr
(1:1 threading)
library.
.It Va WITHOUT_LLDB
.\" from FreeBSD: head/tools/build/options/WITHOUT_LLDB 289275 2015-10-14 00:23:31Z emaste
Set to not build the LLDB debugger.
.Pp
It is a default setting on
arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, pc98/i386, powerpc/powerpc, powerpc/powerpc64 and sparc64/sparc64.
.It Va WITH_LLDB
.\" from FreeBSD: head/tools/build/options/WITH_LLDB 255722 2013-09-20 01:52:02Z emaste
Set to build the LLDB debugger.
.Pp
It is a default setting on
amd64/amd64 and arm64/aarch64.
.It Va WITHOUT_LLVM_LIBUNWIND
.\" from FreeBSD: head/tools/build/options/WITHOUT_LLVM_LIBUNWIND 293450 2016-01-09 00:42:07Z emaste
Set to use GCC's stack unwinder (instead of LLVM's libunwind).
.Pp
It is a default setting on
amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, pc98/i386, powerpc/powerpc, powerpc/powerpc64 and sparc64/sparc64.
.It Va WITH_LLVM_LIBUNWIND
.\" from FreeBSD: head/tools/build/options/WITH_LLVM_LIBUNWIND 293450 2016-01-09 00:42:07Z emaste
Set to use LLVM's libunwind stack unwinder (instead of GCC's unwinder).
.Pp
It is a default setting on
arm64/aarch64.
.It Va WITHOUT_LOCALES
.\" from FreeBSD: head/tools/build/options/WITHOUT_LOCALES 156932 2006-03-21 07:50:50Z ru
Set to not build localization files; see

View File

@ -344,6 +344,7 @@ adrian -> loos
adrian -> monthadar
adrian -> ray
adrian -> rmh
adrian -> sephe
ae -> melifaro
@ -404,6 +405,7 @@ das -> rodrigc
delphij -> gabor
delphij -> rafan
delphij -> sephe
des -> anholt
des -> hmp

View File

@ -231,9 +231,9 @@ __DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC
# In-tree binutils/gcc are older versions without modern architecture support.
.if ${__T} == "aarch64" || ${__T} == "riscv64"
BROKEN_OPTIONS+=BINUTILS BINUTILS_BOOTSTRAP GCC GCC_BOOTSTRAP GDB
__DEFAULT_YES_OPTIONS+=ELFCOPY_AS_OBJCOPY
__DEFAULT_YES_OPTIONS+=ELFCOPY_AS_OBJCOPY LLVM_LIBUNWIND
.else
__DEFAULT_NO_OPTIONS+=ELFCOPY_AS_OBJCOPY
__DEFAULT_NO_OPTIONS+=ELFCOPY_AS_OBJCOPY LLVM_LIBUNWIND
.endif
.if ${__T} == "riscv64"
BROKEN_OPTIONS+=PROFILE # "sorry, unimplemented: profiler support for RISC-V"

View File

@ -80,6 +80,7 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);

View File

@ -322,6 +322,13 @@ trap(struct trapframe *frame)
break;
case T_PAGEFLT: /* page fault */
/*
* Emulator can take care about this trap?
*/
if (*p->p_sysent->sv_trap != NULL &&
(*p->p_sysent->sv_trap)(td) == 0)
goto userout;
addr = frame->tf_addr;
i = trap_pfault(frame, TRUE);
if (i == -1)

View File

@ -129,6 +129,7 @@ static void linux_set_syscall_retval(struct thread *td, int error);
static int linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa);
static void linux_exec_setregs(struct thread *td, struct image_params *imgp,
u_long stack);
static int linux_vsyscall(struct thread *td);
/*
* Linux syscalls return negative errno's, we do positive and map them
@ -746,6 +747,53 @@ exec_linux_imgact_try(struct image_params *imgp)
return(error);
}
#define LINUX_VSYSCALL_START (-10UL << 20)
#define LINUX_VSYSCALL_SZ 1024
const unsigned long linux_vsyscall_vector[] = {
LINUX_SYS_gettimeofday,
LINUX_SYS_linux_time,
/* getcpu not implemented */
};
static int
linux_vsyscall(struct thread *td)
{
struct trapframe *frame;
uint64_t retqaddr;
int code, traced;
int error;
frame = td->td_frame;
/* Check %rip for vsyscall area */
if (__predict_true(frame->tf_rip < LINUX_VSYSCALL_START))
return (EINVAL);
if ((frame->tf_rip & (LINUX_VSYSCALL_SZ - 1)) != 0)
return (EINVAL);
code = (frame->tf_rip - LINUX_VSYSCALL_START) / LINUX_VSYSCALL_SZ;
if (code >= nitems(linux_vsyscall_vector))
return (EINVAL);
/*
* vsyscall called as callq *(%rax), so we must
* use return address from %rsp and also fixup %rsp
*/
error = copyin((void *)frame->tf_rsp, &retqaddr, sizeof(retqaddr));
if (error)
return (error);
frame->tf_rip = retqaddr;
frame->tf_rax = linux_vsyscall_vector[code];
frame->tf_rsp += 8;
traced = (frame->tf_flags & PSL_T);
amd64_syscall(td, traced);
return (0);
}
struct sysentvec elf_linux_sysvec = {
.sv_size = LINUX_SYS_MAXSYSCALL,
.sv_table = linux_sysent,
@ -778,7 +826,8 @@ struct sysentvec elf_linux_sysvec = {
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
.sv_thread_detach = linux_thread_detach
.sv_thread_detach = linux_thread_detach,
.sv_trap = linux_vsyscall,
};
static void

View File

@ -1040,6 +1040,7 @@ struct sysentvec elf_linux_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
.sv_thread_detach = linux_thread_detach,
.sv_trap = NULL,
};
static void

View File

@ -86,6 +86,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);

View File

@ -87,6 +87,8 @@ static struct sysentvec elf64_freebsd_sysvec = {
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);

View File

@ -211,7 +211,6 @@ fsread(ufs_ino_t inode, void *buf, size_t nbyte)
break;
}
if (sblock_try[n] == -1) {
printf("Not ufs\n");
return -1;
}
dsk_meta++;

View File

@ -41,14 +41,13 @@ CFLAGS+= -fPIC
LDFLAGS+= -Wl,-znocombreloc
.endif
.if ${MACHINE_CPUARCH} == "arm" || ${MACHINE_CPUARCH} == "i386"
#
# Add libstand for the runtime functions used by the compiler - for example
# __aeabi_* (arm) or __divdi3 (i386).
# as well as required string and memory functions for all platforms.
#
DPADD+= ${LIBSTAND}
LDADD+= -lstand
.endif
DPADD+= ${LDSCRIPT}

View File

@ -24,6 +24,7 @@ __FBSDID("$FreeBSD$");
#include <sys/dirent.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
#include <stand.h>
#include <efi.h>
#include <eficonsctl.h>
@ -33,28 +34,8 @@ __FBSDID("$FreeBSD$");
#define BSIZEMAX 16384
typedef int putc_func_t(char c, void *arg);
struct sp_data {
char *sp_buf;
u_int sp_len;
u_int sp_size;
};
static const char digits[] = "0123456789abcdef";
static void panic(const char *fmt, ...) __dead2;
static int printf(const char *fmt, ...);
static int putchar(char c, void *arg);
static int vprintf(const char *fmt, va_list ap);
static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
static int __putc(char c, void *arg);
static int __puts(const char *s, putc_func_t *putc, void *arg);
static int __sputc(char c, void *arg);
static char *__uitoa(char *buf, u_int val, int base);
static char *__ultoa(char *buf, u_long val, int base);
void panic(const char *fmt, ...) __dead2;
void putchar(int c);
static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet);
static void load(const char *fname);
@ -62,39 +43,6 @@ static void load(const char *fname);
static EFI_SYSTEM_TABLE *systab;
static EFI_HANDLE *image;
static void
bcopy(const void *src, void *dst, size_t len)
{
const char *s = src;
char *d = dst;
while (len-- != 0)
*d++ = *s++;
}
static void
memcpy(void *dst, const void *src, size_t len)
{
bcopy(src, dst, len);
}
static void
bzero(void *b, size_t len)
{
char *p = b;
while (len-- != 0)
*p++ = 0;
}
static int
strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2 && *s1; s1++, s2++)
;
return ((u_char)*s1 - (u_char)*s2);
}
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
@ -250,7 +198,6 @@ fsstat(ufs_ino_t inode)
break;
}
if (sblock_try[n] == -1) {
printf("Not ufs\n");
return -1;
}
dsk_meta++;
@ -346,38 +293,22 @@ load(const char *fname)
EFI_ERROR_CODE(status));
}
static void
void
panic(const char *fmt, ...)
{
char buf[128];
va_list ap;
printf("panic: ");
va_start(ap, fmt);
vsnprintf(buf, sizeof buf, fmt, ap);
printf("panic: %s\n", buf);
vprintf(fmt, ap);
va_end(ap);
printf("\n");
while (1) {}
}
static int
printf(const char *fmt, ...)
{
va_list ap;
int ret;
/* Don't annoy the user as we probe for partitions */
if (strcmp(fmt,"Not ufs\n") == 0)
return 0;
va_start(ap, fmt);
ret = vprintf(fmt, ap);
va_end(ap);
return (ret);
}
static int
putchar(char c, void *arg)
void
putchar(int c)
{
CHAR16 buf[2];
@ -389,187 +320,4 @@ putchar(char c, void *arg)
buf[0] = c;
buf[1] = 0;
systab->ConOut->OutputString(systab->ConOut, buf);
return (1);
}
static int
vprintf(const char *fmt, va_list ap)
{
int ret;
ret = __printf(fmt, putchar, 0, ap);
return (ret);
}
static int
vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
{
struct sp_data sp;
int ret;
sp.sp_buf = str;
sp.sp_len = 0;
sp.sp_size = sz;
ret = __printf(fmt, __sputc, &sp, ap);
return (ret);
}
static int
__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
{
char buf[(sizeof(long) * 8) + 1];
char *nbuf;
u_long ul;
u_int ui;
int lflag;
int sflag;
char *s;
int pad;
int ret;
int c;
nbuf = &buf[sizeof buf - 1];
ret = 0;
while ((c = *fmt++) != 0) {
if (c != '%') {
ret += putc(c, arg);
continue;
}
lflag = 0;
sflag = 0;
pad = 0;
reswitch: c = *fmt++;
switch (c) {
case '#':
sflag = 1;
goto reswitch;
case '%':
ret += putc('%', arg);
break;
case 'c':
c = va_arg(ap, int);
ret += putc(c, arg);
break;
case 'd':
if (lflag == 0) {
ui = (u_int)va_arg(ap, int);
if (ui < (int)ui) {
ui = -ui;
ret += putc('-', arg);
}
s = __uitoa(nbuf, ui, 10);
} else {
ul = (u_long)va_arg(ap, long);
if (ul < (long)ul) {
ul = -ul;
ret += putc('-', arg);
}
s = __ultoa(nbuf, ul, 10);
}
ret += __puts(s, putc, arg);
break;
case 'l':
lflag = 1;
goto reswitch;
case 'o':
if (lflag == 0) {
ui = (u_int)va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 8);
} else {
ul = (u_long)va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 8);
}
ret += __puts(s, putc, arg);
break;
case 'p':
ul = (u_long)va_arg(ap, void *);
s = __ultoa(nbuf, ul, 16);
ret += __puts("0x", putc, arg);
ret += __puts(s, putc, arg);
break;
case 's':
s = va_arg(ap, char *);
ret += __puts(s, putc, arg);
break;
case 'u':
if (lflag == 0) {
ui = va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 10);
} else {
ul = va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 10);
}
ret += __puts(s, putc, arg);
break;
case 'x':
if (lflag == 0) {
ui = va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 16);
} else {
ul = va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 16);
}
if (sflag)
ret += __puts("0x", putc, arg);
ret += __puts(s, putc, arg);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
pad = pad * 10 + c - '0';
goto reswitch;
default:
break;
}
}
return (ret);
}
static int
__sputc(char c, void *arg)
{
struct sp_data *sp;
sp = arg;
if (sp->sp_len < sp->sp_size)
sp->sp_buf[sp->sp_len++] = c;
sp->sp_buf[sp->sp_len] = '\0';
return (1);
}
static int
__puts(const char *s, putc_func_t *putc, void *arg)
{
const char *p;
int ret;
ret = 0;
for (p = s; *p != '\0'; p++)
ret += putc(*p, arg);
return (ret);
}
static char *
__uitoa(char *buf, u_int ui, int base)
{
char *p;
p = buf;
*p = '\0';
do
*--p = digits[ui % base];
while ((ui /= base) != 0);
return (p);
}
static char *
__ultoa(char *buf, u_long ul, int base)
{
char *p;
p = buf;
*p = '\0';
do
*--p = digits[ul % base];
while ((ul /= base) != 0);
return (p);
}

View File

@ -296,7 +296,8 @@ extract_currdev(void)
}
#ifdef LOADER_ZFS_SUPPORT
init_zfs_bootenv(zfs_fmtdev(&new_currdev));
if (new_currdev.d_type == DEVT_ZFS)
init_zfs_bootenv(zfs_fmtdev(&new_currdev));
#endif
env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
@ -311,9 +312,14 @@ init_zfs_bootenv(char *currdev)
{
char *beroot;
if (strlen(currdev) == 0)
return;
if(strncmp(currdev, "zfs:", 4) != 0)
return;
/* Remove the trailing : */
currdev[strlen(currdev) - 1] = '\0';
setenv("zfs_be_active", currdev, 1);
setenv("zfs_be_currpage", "1", 1);
/* Do not overwrite if already set */
setenv("vfs.root.mountfrom", currdev, 0);
/* Forward past zfs: */
@ -323,9 +329,7 @@ init_zfs_bootenv(char *currdev)
beroot = strrchr(currdev, '/');
if (beroot != NULL)
beroot[0] = '\0';
beroot = currdev;
setenv("zfs_be_root", beroot, 1);
}
#endif
@ -394,6 +398,7 @@ static int
command_reloadbe(int argc, char *argv[])
{
int err;
char *root;
if (argc > 2) {
command_errmsg = "wrong number of arguments";
@ -403,6 +408,11 @@ command_reloadbe(int argc, char *argv[])
if (argc == 2) {
err = zfs_bootenv(argv[1]);
} else {
root = getenv("zfs_be_root");
if (root == NULL) {
/* There does not appear to be a ZFS pool here, exit without error */
return (CMD_OK);
}
err = zfs_bootenv(getenv("zfs_be_root"));
}

View File

@ -564,10 +564,6 @@ printf(const char *fmt, ...)
va_list ap;
int ret;
/* Don't annoy the user as we probe for partitions */
if (strcmp(fmt,"Not ufs\n") == 0)
return 0;
va_start(ap, fmt);
ret = vprintf(fmt, ap);
va_end(ap);

View File

@ -1,136 +1,12 @@
# $FreeBSD$
# Originally from $NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $
#
# Notes:
# - We don't use the libc strerror/sys_errlist because the string table is
# quite large.
#
MAN=
.include <bsd.own.mk>
MK_SSP= no
.include <src.opts.mk>
LIBSTAND_SRC= ${.CURDIR}/../../../../lib/libstand
LIBC_SRC= ${LIBSTAND_SRC}/../libc
.PATH: ${LIBSTAND_SRC}
LIB= stand
INTERNALLIB=
MK_PROFILE= no
NO_PIC=
INCS=
MAN=
.PATH: ${LIBSTAND_SRC}
WARNS?= 0
# standalone components and stuff we have modified locally
SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \
globals.c pager.c printf.c strdup.c strerror.c strtol.c strtoul.c random.c \
sbrk.c twiddle.c zalloc.c zalloc_malloc.c
# private (pruned) versions of libc string functions
SRCS+= strcasecmp.c
.PATH: ${LIBC_SRC}/net
SRCS+= ntoh.c
# string functions from libc
.PATH: ${LIBC_SRC}/string
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "powerpc" || \
${MACHINE_CPUARCH} == "sparc64" || ${MACHINE_CPUARCH} == "amd64" || \
${MACHINE_CPUARCH} == "arm"
SRCS+= bcmp.c bcopy.c bzero.c ffs.c memccpy.c memchr.c memcmp.c memcpy.c \
memmove.c memset.c qdivrem.c strcat.c strchr.c strcmp.c strcpy.c \
strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c \
strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
.endif
.if ${MACHINE_CPUARCH} == "arm"
.PATH: ${LIBC_SRC}/arm/gen
SRCS+= divsi3.S
.endif
.if ${MACHINE_CPUARCH} == "powerpc"
.PATH: ${LIBC_SRC}/quad
SRCS+= ashldi3.c ashrdi3.c
.PATH: ${LIBC_SRC}/powerpc/gen
SRCS+= syncicache.c
.endif
# uuid functions from libc
.PATH: ${LIBC_SRC}/uuid
SRCS+= uuid_equal.c uuid_is_nil.c
# _setjmp/_longjmp
.if ${MACHINE_CPUARCH} == "amd64"
.PATH: ${LIBSTAND_SRC}/amd64
.elif ${MACHINE_ARCH} == "powerpc64"
.PATH: ${LIBSTAND_SRC}/powerpc
.else
.PATH: ${LIBSTAND_SRC}/${MACHINE_CPUARCH}
.endif
SRCS+= _setjmp.S
# decompression functionality from libbz2
# NOTE: to actually test this functionality after libbz2 upgrade compile
# loader(8) with LOADER_BZIP2_SUPPORT defined
.PATH: ${LIBSTAND_SRC}/../../contrib/bzip2
CFLAGS+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS
SRCS+= libstand_bzlib_private.h
.for file in bzlib.c crctable.c decompress.c huffman.c randtable.c
SRCS+= _${file}
CLEANFILES+= _${file}
_${file}: ${file}
sed "s|bzlib_private\.h|libstand_bzlib_private.h|" \
${.ALLSRC} > ${.TARGET}
.endfor
CLEANFILES+= libstand_bzlib_private.h
libstand_bzlib_private.h: bzlib_private.h
sed -e 's|<stdlib.h>|"stand.h"|' \
${.ALLSRC} > ${.TARGET}
# decompression functionality from libz
.PATH: ${LIBSTAND_SRC}/../libz
CFLAGS+=-DHAVE_MEMCPY -I${LIBSTAND_SRC}/../libz
SRCS+= adler32.c crc32.c libstand_zutil.h libstand_gzguts.h
.for file in infback.c inffast.c inflate.c inftrees.c zutil.c
SRCS+= _${file}
CLEANFILES+= _${file}
_${file}: ${file}
sed -e "s|zutil\.h|libstand_zutil.h|" \
-e "s|gzguts\.h|libstand_gzguts.h|" \
${.ALLSRC} > ${.TARGET}
.endfor
# depend on stand.h being able to be included multiple times
.for file in zutil.h gzguts.h
CLEANFILES+= libstand_${file}
libstand_${file}: ${file}
sed -e 's|<fcntl.h>|"stand.h"|' \
-e 's|<stddef.h>|"stand.h"|' \
-e 's|<string.h>|"stand.h"|' \
-e 's|<stdio.h>|"stand.h"|' \
-e 's|<stdlib.h>|"stand.h"|' \
${.ALLSRC} > ${.TARGET}
.endfor
# io routines
SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c \
fstat.c close.c lseek.c open.c read.c write.c readdir.c
# network routines
SRCS+= arp.c ether.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c
# network info services:
SRCS+= bootp.c rarp.c bootparam.c
# boot filesystems
SRCS+= ufs.c nfs.c cd9660.c tftp.c gzipfs.c bzipfs.c
SRCS+= dosfs.c ext2fs.c
SRCS+= splitfs.c
.include <bsd.stand.mk>
.include <bsd.lib.mk>
.include "${LIBSTAND_SRC}/Makefile"

View File

@ -6,7 +6,6 @@ DIRDEPS = \
include/arpa \
include/xlocale \
lib/libbz2 \
lib/libstand \
.include <dirdeps.mk>

View File

@ -168,6 +168,7 @@ extract_currdev(void)
zdev.d_type = zdev.d_dev->dv_type;
dev = *(struct disk_devdesc *)&zdev;
init_zfs_bootenv(zfs_fmtdev(&dev));
} else
#endif
@ -191,10 +192,6 @@ extract_currdev(void)
dev.d_unit = 0;
}
#if defined(USERBOOT_ZFS_SUPPORT)
init_zfs_bootenv(zfs_fmtdev(&dev));
#endif
env_setenv("currdev", EV_VOLATILE, userboot_fmtdev(&dev),
userboot_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, userboot_fmtdev(&dev),
@ -207,9 +204,14 @@ init_zfs_bootenv(char *currdev)
{
char *beroot;
if (strlen(currdev) == 0)
return;
if(strncmp(currdev, "zfs:", 4) != 0)
return;
/* Remove the trailing : */
currdev[strlen(currdev) - 1] = '\0';
setenv("zfs_be_active", currdev, 1);
setenv("zfs_be_currpage", "1", 1);
/* Do not overwrite if already set */
setenv("vfs.root.mountfrom", currdev, 0);
/* Forward past zfs: */
@ -219,9 +221,7 @@ init_zfs_bootenv(char *currdev)
beroot = strrchr(currdev, '/');
if (beroot != NULL)
beroot[0] = '\0';
beroot = currdev;
setenv("zfs_be_root", beroot, 1);
}
@ -273,6 +273,7 @@ static int
command_reloadbe(int argc, char *argv[])
{
int err;
char *root;
if (argc > 2) {
command_errmsg = "wrong number of arguments";
@ -282,7 +283,11 @@ command_reloadbe(int argc, char *argv[])
if (argc == 2) {
err = zfs_bootenv(argv[1]);
} else {
err = zfs_bootenv(getenv("zfs_be_root"));
root = getenv("zfs_be_root");
if (root == NULL) {
return (CMD_OK);
}
err = zfs_bootenv(root);
}
if (err != 0) {

View File

@ -413,7 +413,7 @@ struct zfs_probe_args {
int fd;
const char *devname;
uint64_t *pool_guid;
uint16_t secsz;
u_int secsz;
};
static int
@ -712,13 +712,18 @@ zfs_list(const char *name)
int
zfs_bootenv(const char *name)
{
static char poolname[ZFS_MAXNAMELEN], *dsname;
static char poolname[ZFS_MAXNAMELEN], *dsname, *root;
char becount[4];
uint64_t objid;
spa_t *spa;
int len, rv, pages, perpage, currpage;
if (strcmp(name, getenv("zfs_be_root")) != 0) {
if (name == NULL)
return (EINVAL);
if ((root = getenv("zfs_be_root")) == NULL)
return (EINVAL);
if (strcmp(name, root) != 0) {
if (setenv("zfs_be_root", name, 1) != 0)
return (ENOMEM);
}

View File

@ -78,6 +78,9 @@ static void
vdev_geom_attrchanged(struct g_consumer *cp, const char *attr)
{
vdev_t *vd;
spa_t *spa;
char *physpath;
int error, physpath_len;
vd = cp->private;
if (vd == NULL)
@ -87,6 +90,47 @@ vdev_geom_attrchanged(struct g_consumer *cp, const char *attr)
vdev_geom_set_rotation_rate(vd, cp);
return;
}
if (strcmp(attr, "GEOM::physpath") != 0)
return;
if (g_access(cp, 1, 0, 0) != 0)
return;
/*
* Record/Update physical path information for this device.
*/
spa = vd->vdev_spa;
physpath_len = MAXPATHLEN;
physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO);
error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath);
g_access(cp, -1, 0, 0);
if (error == 0) {
char *old_physpath;
old_physpath = vd->vdev_physpath;
vd->vdev_physpath = spa_strdup(physpath);
spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
if (old_physpath != NULL) {
int held_lock;
held_lock = spa_config_held(spa, SCL_STATE, RW_WRITER);
if (held_lock == 0) {
g_topology_unlock();
spa_config_enter(spa, SCL_STATE, FTAG,
RW_WRITER);
}
spa_strfree(old_physpath);
if (held_lock == 0) {
spa_config_exit(spa, SCL_STATE, FTAG);
g_topology_lock();
}
}
}
g_free(physpath);
}
static void
@ -97,8 +141,10 @@ vdev_geom_orphan(struct g_consumer *cp)
g_topology_assert();
vd = cp->private;
if (vd == NULL)
if (vd == NULL) {
/* Vdev close in progress. Ignore the event. */
return;
}
/*
* Orphan callbacks occur from the GEOM event thread.
@ -120,7 +166,7 @@ vdev_geom_orphan(struct g_consumer *cp)
}
static struct g_consumer *
vdev_geom_attach(struct g_provider *pp)
vdev_geom_attach(struct g_provider *pp, vdev_t *vd)
{
struct g_geom *gp;
struct g_consumer *cp;
@ -139,6 +185,7 @@ vdev_geom_attach(struct g_provider *pp)
if (gp == NULL) {
gp = g_new_geomf(&zfs_vdev_class, "zfs::vdev");
gp->orphan = vdev_geom_orphan;
gp->attrchanged = vdev_geom_attrchanged;
cp = g_new_consumer(gp);
if (g_attach(cp, pp) != 0) {
g_wither_geom(gp, ENXIO);
@ -175,28 +222,56 @@ vdev_geom_attach(struct g_provider *pp)
ZFS_LOG(1, "Used existing consumer for %s.", pp->name);
}
}
/*
* BUG: cp may already belong to a vdev. This could happen if:
* 1) That vdev is a shared spare, or
* 2) We are trying to reopen a missing vdev and we are scanning by
* guid. In that case, we'll ultimately fail to open this consumer,
* but not until after setting the private field.
* The solution is to:
* 1) Don't set the private field until after the open succeeds, and
* 2) Set it to a linked list of vdevs, not just a single vdev
*/
cp->private = vd;
vd->vdev_tsd = cp;
/* Fetch initial physical path information for this device. */
vdev_geom_attrchanged(cp, "GEOM::physpath");
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
return (cp);
}
static void
vdev_geom_detach(void *arg, int flag __unused)
vdev_geom_close_locked(vdev_t *vd)
{
struct g_geom *gp;
struct g_consumer *cp;
g_topology_assert();
cp = arg;
gp = cp->geom;
cp = vd->vdev_tsd;
if (cp == NULL)
return;
ZFS_LOG(1, "Closing access to %s.", cp->provider->name);
KASSERT(vd->vdev_tsd == cp, ("%s: vdev_tsd is not cp", __func__));
vd->vdev_tsd = NULL;
vd->vdev_delayed_close = B_FALSE;
cp->private = NULL;
gp = cp->geom;
g_access(cp, -1, 0, -1);
/* Destroy consumer on last close. */
if (cp->acr == 0 && cp->ace == 0) {
ZFS_LOG(1, "Destroyed consumer to %s.", cp->provider->name);
if (cp->acw > 0)
g_access(cp, 0, -cp->acw, 0);
g_detach(cp);
if (cp->provider != NULL) {
ZFS_LOG(1, "Destroyed consumer to %s.",
cp->provider->name);
g_detach(cp);
}
g_destroy_consumer(cp);
}
/* Destroy geom if there are no consumers left. */
@ -490,7 +565,7 @@ vdev_geom_read_guids(struct g_consumer *cp, uint64_t *pguid, uint64_t *vguid)
}
static struct g_consumer *
vdev_geom_attach_by_guids(uint64_t pool_guid, uint64_t vdev_guid)
vdev_geom_attach_by_guids(vdev_t *vd)
{
struct g_class *mp;
struct g_geom *gp, *zgp;
@ -519,9 +594,10 @@ vdev_geom_attach_by_guids(uint64_t pool_guid, uint64_t vdev_guid)
vdev_geom_read_guids(zcp, &pguid, &vguid);
g_topology_lock();
vdev_geom_detach_taster(zcp);
if (pguid != pool_guid || vguid != vdev_guid)
if (pguid != spa_guid(vd->vdev_spa) ||
vguid != vd->vdev_guid)
continue;
cp = vdev_geom_attach(pp);
cp = vdev_geom_attach(pp, vd);
if (cp == NULL) {
printf("ZFS WARNING: Unable to "
"attach to %s.\n", pp->name);
@ -551,7 +627,7 @@ vdev_geom_open_by_guids(vdev_t *vd)
g_topology_assert();
ZFS_LOG(1, "Searching by guid [%ju].", (uintmax_t)vd->vdev_guid);
cp = vdev_geom_attach_by_guids(spa_guid(vd->vdev_spa), vd->vdev_guid);
cp = vdev_geom_attach_by_guids(vd);
if (cp != NULL) {
len = strlen(cp->provider->name) + strlen("/dev/") + 1;
buf = kmem_alloc(len, KM_SLEEP);
@ -585,7 +661,7 @@ vdev_geom_open_by_path(vdev_t *vd, int check_guid)
pp = g_provider_by_name(vd->vdev_path + sizeof("/dev/") - 1);
if (pp != NULL) {
ZFS_LOG(1, "Found provider by name %s.", vd->vdev_path);
cp = vdev_geom_attach(pp);
cp = vdev_geom_attach(pp, vd);
if (cp != NULL && check_guid && ISP2(pp->sectorsize) &&
pp->sectorsize <= VDEV_PAD_SIZE) {
g_topology_unlock();
@ -593,7 +669,7 @@ vdev_geom_open_by_path(vdev_t *vd, int check_guid)
g_topology_lock();
if (pguid != spa_guid(vd->vdev_spa) ||
vguid != vd->vdev_guid) {
vdev_geom_detach(cp, 0);
vdev_geom_close_locked(vd);
cp = NULL;
ZFS_LOG(1, "guid mismatch for provider %s: "
"%ju:%ju != %ju:%ju.", vd->vdev_path,
@ -675,7 +751,8 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
!ISP2(cp->provider->sectorsize)) {
ZFS_LOG(1, "Provider %s has unsupported sectorsize.",
vd->vdev_path);
vdev_geom_detach(cp, 0);
vdev_geom_close_locked(vd);
error = EINVAL;
cp = NULL;
} else if (cp->acw == 0 && (spa_mode(vd->vdev_spa) & FWRITE) != 0) {
@ -692,19 +769,17 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
if (error != 0) {
printf("ZFS WARNING: Unable to open %s for writing (error=%d).\n",
vd->vdev_path, error);
vdev_geom_detach(cp, 0);
vdev_geom_close_locked(vd);
cp = NULL;
}
}
g_topology_unlock();
PICKUP_GIANT();
if (cp == NULL) {
vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
return (error);
}
cp->private = vd;
vd->vdev_tsd = cp;
pp = cp->provider;
/*
@ -727,12 +802,6 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
*/
vd->vdev_nowritecache = B_FALSE;
if (vd->vdev_physpath != NULL)
spa_strfree(vd->vdev_physpath);
bufsize = sizeof("/dev/") + strlen(pp->name);
vd->vdev_physpath = kmem_alloc(bufsize, KM_SLEEP);
snprintf(vd->vdev_physpath, bufsize, "/dev/%s", pp->name);
/*
* Determine the device's rotation rate.
*/
@ -744,15 +813,12 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
static void
vdev_geom_close(vdev_t *vd)
{
struct g_consumer *cp;
cp = vd->vdev_tsd;
if (cp == NULL)
return;
vd->vdev_tsd = NULL;
vd->vdev_delayed_close = B_FALSE;
cp->private = NULL; /* XXX locking */
g_post_event(vdev_geom_detach, cp, M_WAITOK, NULL);
DROP_GIANT();
g_topology_lock();
vdev_geom_close_locked(vd);
g_topology_unlock();
PICKUP_GIANT();
}
static void

View File

@ -134,6 +134,7 @@ struct sysentvec ia32_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);

View File

@ -1099,8 +1099,12 @@ linux_get_robust_list(struct thread *td, struct linux_get_robust_list_args *args
ESRCH);
return (ESRCH);
}
if (SV_PROC_ABI(td2->td_proc) != SV_ABI_LINUX)
if (SV_PROC_ABI(td2->td_proc) != SV_ABI_LINUX) {
LIN_SDT_PROBE1(futex, linux_get_robust_list, return,
EPERM);
PROC_UNLOCK(td2->td_proc);
return (EPERM);
}
em = em_find(td2);
KASSERT(em != NULL, ("get_robust_list: emuldata notfound.\n"));

View File

@ -194,6 +194,7 @@ struct sysentvec svr4_sysvec = {
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
const char svr4_emul_path[] = "/compat/svr4";

View File

@ -50,6 +50,7 @@ static const char rcsid[] = "@(#)$Id$";
# include <net/netisr.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_fib.h>
#include <netinet/in_var.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@ -712,17 +713,16 @@ ipf_fastroute(m0, mpp, fin, fdp)
{
register struct ip *ip, *mhip;
register struct mbuf *m = *mpp;
register struct route *ro;
int len, off, error = 0, hlen, code;
struct ifnet *ifp, *sifp;
struct sockaddr_in *dst;
struct route iproute;
struct sockaddr_in dst;
struct nhop4_extended nh4;
int has_nhop = 0;
u_long fibnum = 0;
u_short ip_off;
frdest_t node;
frentry_t *fr;
ro = NULL;
#ifdef M_WRITABLE
/*
* HOT FIX/KLUDGE:
@ -766,11 +766,10 @@ ipf_fastroute(m0, mpp, fin, fdp)
/*
* Route packet.
*/
ro = &iproute;
bzero(ro, sizeof (*ro));
dst = (struct sockaddr_in *)&ro->ro_dst;
dst->sin_family = AF_INET;
dst->sin_addr = ip->ip_dst;
bzero(&dst, sizeof (dst));
dst.sin_family = AF_INET;
dst.sin_addr = ip->ip_dst;
dst.sin_len = sizeof(dst);
fr = fin->fin_fr;
if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
@ -790,25 +789,22 @@ ipf_fastroute(m0, mpp, fin, fdp)
}
if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
dst->sin_addr = fdp->fd_ip;
dst.sin_addr = fdp->fd_ip;
dst->sin_len = sizeof(*dst);
in_rtalloc(ro, M_GETFIB(m0));
if ((ifp == NULL) && (ro->ro_rt != NULL))
ifp = ro->ro_rt->rt_ifp;
if ((ro->ro_rt == NULL) || (ifp == NULL)) {
fibnum = M_GETFIB(m0);
if (fib4_lookup_nh_ext(fibnum, dst.sin_addr, NHR_REF, 0, &nh4) != 0) {
if (in_localaddr(ip->ip_dst))
error = EHOSTUNREACH;
else
error = ENETUNREACH;
goto bad;
}
if (ro->ro_rt->rt_flags & RTF_GATEWAY)
dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
if (ro->ro_rt)
counter_u64_add(ro->ro_rt->rt_pksent, 1);
has_nhop = 1;
if (ifp == NULL)
ifp = nh4.nh_ifp;
if (nh4.nh_flags & NHF_GATEWAY)
dst.sin_addr = nh4.nh_addr;
/*
* For input packets which are being "fastrouted", they won't
@ -852,8 +848,8 @@ ipf_fastroute(m0, mpp, fin, fdp)
if (ntohs(ip->ip_len) <= ifp->if_mtu) {
if (!ip->ip_sum)
ip->ip_sum = in_cksum(m, hlen);
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
ro
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)&dst,
NULL
);
goto done;
}
@ -935,8 +931,8 @@ ipf_fastroute(m0, mpp, fin, fdp)
m->m_act = 0;
if (error == 0)
error = (*ifp->if_output)(ifp, m,
(struct sockaddr *)dst,
ro
(struct sockaddr *)&dst,
NULL
);
else
FREE_MB_T(m);
@ -948,9 +944,9 @@ ipf_fastroute(m0, mpp, fin, fdp)
else
ipfmain.ipf_frouteok[1]++;
if ((ro != NULL) && (ro->ro_rt != NULL)) {
RTFREE(ro->ro_rt);
}
if (has_nhop)
fib4_free_nh_ext(fibnum, &nh4);
return 0;
bad:
if (error == EMSGSIZE) {
@ -971,18 +967,11 @@ int
ipf_verifysrc(fin)
fr_info_t *fin;
{
struct sockaddr_in *dst;
struct route iproute;
struct nhop4_basic nh4;
bzero((char *)&iproute, sizeof(iproute));
dst = (struct sockaddr_in *)&iproute.ro_dst;
dst->sin_len = sizeof(*dst);
dst->sin_family = AF_INET;
dst->sin_addr = fin->fin_src;
in_rtalloc(&iproute, 0);
if (iproute.ro_rt == NULL)
return 0;
return (fin->fin_ifp == iproute.ro_rt->rt_ifp);
if (fib4_lookup_nh_basic(0, fin->fin_src, 0, 0, &nh4) != 0)
return (0);
return (fin->fin_ifp == nh4.nh_ifp);
}

View File

@ -3642,6 +3642,9 @@ setup_intr_handlers(struct adapter *sc)
#ifdef DEV_NETMAP
struct sge_nm_rxq *nm_rxq;
#endif
#ifdef RSS
int nbuckets = rss_getnumbuckets();
#endif
/*
* Setup interrupts.
@ -3700,6 +3703,10 @@ setup_intr_handlers(struct adapter *sc)
t4_intr, rxq, s);
if (rc != 0)
return (rc);
#ifdef RSS
bus_bind_intr(sc->dev, irq->res,
rss_getcpu(q % nbuckets));
#endif
irq++;
rid++;
vi->nintr++;

View File

@ -205,6 +205,7 @@
* requires ACR[6].
*/
#define com_icr 5 /* index control register (R/W) */
#define REG_ICR com_icr
/*
* 16950 register #7. It is the same as com_scr except it has a different
@ -220,6 +221,7 @@
*/
#define com_acr 0 /* additional control register (R/W) */
#define REG_ACR com_acr
#define ACR_ASE 0x80 /* ASR/RFL/TFL enable */
#define ACR_ICRE 0x40 /* ICR enable */
#define ACR_TLE 0x20 /* TTL/RTL enable */

View File

@ -98,6 +98,9 @@ SYSCTL_INT(_kern_iscsi, OID_AUTO, maxtags, CTLFLAG_RWTUN, &maxtags,
static int fail_on_disconnection = 0;
SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_disconnection, CTLFLAG_RWTUN,
&fail_on_disconnection, 0, "Destroy CAM SIM on connection failure");
static int fail_on_shutdown = 1;
SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_shutdown, CTLFLAG_RWTUN,
&fail_on_shutdown, 0, "Fail disconnected sessions on shutdown");
static MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI initiator");
static uma_zone_t iscsi_outstanding_zone;
@ -417,8 +420,6 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is)
sc = is->is_softc;
sx_xlock(&sc->sc_lock);
TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
sx_xunlock(&sc->sc_lock);
icl_conn_close(is->is_conn);
callout_drain(&is->is_callout);
@ -450,6 +451,9 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is)
#ifdef ICL_KERNEL_PROXY
cv_destroy(&is->is_login_cv);
#endif
TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
sx_xunlock(&sc->sc_lock);
ISCSI_SESSION_DEBUG(is, "terminated");
free(is, M_ISCSI);
@ -473,12 +477,7 @@ iscsi_maintenance_thread(void *arg)
STAILQ_EMPTY(&is->is_postponed))
cv_wait(&is->is_maintenance_cv, &is->is_lock);
if (is->is_reconnecting) {
ISCSI_SESSION_UNLOCK(is);
iscsi_maintenance_thread_reconnect(is);
continue;
}
/* Terminate supersedes reconnect. */
if (is->is_terminating) {
ISCSI_SESSION_UNLOCK(is);
iscsi_maintenance_thread_terminate(is);
@ -486,6 +485,12 @@ iscsi_maintenance_thread(void *arg)
return;
}
if (is->is_reconnecting) {
ISCSI_SESSION_UNLOCK(is);
iscsi_maintenance_thread_reconnect(is);
continue;
}
iscsi_session_send_postponed(is);
ISCSI_SESSION_UNLOCK(is);
}
@ -605,6 +610,11 @@ iscsi_callout(void *context)
return;
out:
if (is->is_terminating) {
ISCSI_SESSION_UNLOCK(is);
return;
}
ISCSI_SESSION_UNLOCK(is);
if (reconnect_needed)
@ -2326,30 +2336,62 @@ iscsi_poll(struct cam_sim *sim)
}
static void
iscsi_shutdown(struct iscsi_softc *sc)
iscsi_terminate_sessions(struct iscsi_softc *sc)
{
struct iscsi_session *is;
/*
* Trying to reconnect during system shutdown would lead to hang.
*/
fail_on_disconnection = 1;
sx_slock(&sc->sc_lock);
TAILQ_FOREACH(is, &sc->sc_sessions, is_next)
iscsi_session_terminate(is);
while(!TAILQ_EMPTY(&sc->sc_sessions)) {
ISCSI_DEBUG("waiting for sessions to terminate");
cv_wait(&sc->sc_cv, &sc->sc_lock);
}
ISCSI_DEBUG("all sessions terminated");
sx_sunlock(&sc->sc_lock);
}
static void
iscsi_shutdown_pre(struct iscsi_softc *sc)
{
struct iscsi_session *is;
if (!fail_on_shutdown)
return;
/*
* If we have any sessions waiting for reconnection, request
* maintenance thread to fail them immediately instead of waiting
* for reconnect timeout.
*
* This prevents LUNs with mounted filesystems that are supported
* by disconnected iSCSI sessions from hanging, however it will
* fail all queued BIOs.
*/
ISCSI_DEBUG("forcing failing all disconnected sessions due to shutdown");
fail_on_disconnection = 1;
sx_slock(&sc->sc_lock);
TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
ISCSI_SESSION_LOCK(is);
if (is->is_waiting_for_iscsid)
if (!is->is_connected) {
ISCSI_SESSION_DEBUG(is, "force failing disconnected session early");
iscsi_session_reconnect(is);
}
ISCSI_SESSION_UNLOCK(is);
}
sx_sunlock(&sc->sc_lock);
}
static void
iscsi_shutdown_post(struct iscsi_softc *sc)
{
ISCSI_DEBUG("removing all sessions due to shutdown");
iscsi_terminate_sessions(sc);
}
static int
iscsi_load(void)
{
@ -2372,8 +2414,16 @@ iscsi_load(void)
}
sc->sc_cdev->si_drv1 = sc;
sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync,
iscsi_shutdown, sc, SHUTDOWN_PRI_DEFAULT-1);
sc->sc_shutdown_pre_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync,
iscsi_shutdown_pre, sc, SHUTDOWN_PRI_FIRST);
/*
* shutdown_post_sync needs to run after filesystem shutdown and before
* CAM shutdown - otherwise when rebooting with an iSCSI session that is
* disconnected but has outstanding requests, dashutdown() will hang on
* cam_periph_runccb().
*/
sc->sc_shutdown_post_eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
iscsi_shutdown_post, sc, SHUTDOWN_PRI_DEFAULT - 1);
return (0);
}
@ -2381,7 +2431,6 @@ iscsi_load(void)
static int
iscsi_unload(void)
{
struct iscsi_session *is, *tmp;
if (sc->sc_cdev != NULL) {
ISCSI_DEBUG("removing device node");
@ -2389,18 +2438,12 @@ iscsi_unload(void)
ISCSI_DEBUG("device node removed");
}
if (sc->sc_shutdown_eh != NULL)
EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_eh);
if (sc->sc_shutdown_pre_eh != NULL)
EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_pre_eh);
if (sc->sc_shutdown_post_eh != NULL)
EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_post_eh);
sx_slock(&sc->sc_lock);
TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp)
iscsi_session_terminate(is);
while(!TAILQ_EMPTY(&sc->sc_sessions)) {
ISCSI_DEBUG("waiting for sessions to terminate");
cv_wait(&sc->sc_cv, &sc->sc_lock);
}
ISCSI_DEBUG("all sessions terminated");
sx_sunlock(&sc->sc_lock);
iscsi_terminate_sessions(sc);
uma_zdestroy(iscsi_outstanding_zone);
sx_destroy(&sc->sc_lock);

View File

@ -131,7 +131,8 @@ struct iscsi_softc {
TAILQ_HEAD(, iscsi_session) sc_sessions;
struct cv sc_cv;
unsigned int sc_last_session_id;
eventhandler_tag sc_shutdown_eh;
eventhandler_tag sc_shutdown_pre_eh;
eventhandler_tag sc_shutdown_post_eh;
};
#endif /* !ISCSI_H */

View File

@ -42,12 +42,16 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/ic/ns16550.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/puc/puc_bus.h>
#include <dev/puc/puc_cfg.h>
#include <dev/puc/puc_bfe.h>
static puc_config_f puc_config_advantech;
static puc_config_f puc_config_amc;
static puc_config_f puc_config_diva;
static puc_config_f puc_config_exar;
@ -691,10 +695,25 @@ const struct puc_cfg puc_pci_devices[] = {
.config_function = puc_config_exar_pcie
},
/*
* The Advantech PCI-1602 Rev. A use the first two ports of an Oxford
* Semiconductor OXuPCI954. Note these boards have a hardware bug in
* that they drive the RS-422/485 transmitters after power-on until a
* driver initalizes the UARTs.
*/
{ 0x13fe, 0x1600, 0x1602, 0x0002,
"Advantech PCI-1602",
"Advantech PCI-1602 Rev. A",
DEFAULT_RCLK * 8,
PUC_PORT_2S, 0x10, 0, 8,
.config_function = puc_config_advantech
},
/* Advantech PCI-1602 Rev. B1/PCI-1603 are also based on OXuPCI952. */
{ 0x13fe, 0xa102, 0x13fe, 0xa102,
"Advantech 2-port PCI (PCI-1602 Rev. B1/PCI-1603)",
DEFAULT_RCLK * 8,
PUC_PORT_2S, 0x10, 4, 0,
.config_function = puc_config_advantech
},
{ 0x1407, 0x0100, 0xffff, 0,
@ -1255,6 +1274,92 @@ const struct puc_cfg puc_pci_devices[] = {
{ 0xffff, 0, 0xffff, 0, NULL, 0 }
};
static int
puc_config_advantech(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
intptr_t *res __unused)
{
const struct puc_cfg *cfg;
struct resource *cres;
struct puc_bar *bar;
device_t cdev, dev;
bus_size_t off;
int base, crtype, fixed, high, i, oxpcie;
uint8_t acr, func, mask;
if (cmd != PUC_CFG_SETUP)
return (ENXIO);
base = fixed = oxpcie = 0;
crtype = SYS_RES_IOPORT;
acr = mask = 0x0;
func = high = 1;
off = 0x60;
cfg = sc->sc_cfg;
switch (cfg->subvendor) {
case 0x13fe:
switch (cfg->device) {
case 0xa102:
high = 0;
break;
default:
break;
}
default:
break;
}
if (fixed == 1)
goto setup;
dev = sc->sc_dev;
cdev = pci_find_dbsf(pci_get_domain(dev), pci_get_bus(dev),
pci_get_slot(dev), func);
if (cdev == NULL) {
device_printf(dev, "could not find config function\n");
return (ENXIO);
}
i = PCIR_BAR(0);
cres = bus_alloc_resource_any(cdev, crtype, &i, RF_ACTIVE);
if (cres == NULL) {
device_printf(dev, "could not allocate config resource\n");
return (ENXIO);
}
if (oxpcie == 0) {
mask = bus_read_1(cres, off);
if (pci_get_function(dev) == 1)
base = 4;
}
setup:
for (i = 0; i < sc->sc_nports; ++i) {
device_printf(dev, "port %d: ", i);
bar = puc_get_bar(sc, cfg->rid + i * cfg->d_rid);
if (bar == NULL) {
printf("could not get BAR\n");
continue;
}
if (fixed == 0) {
if ((mask & (1 << (base + i))) == 0) {
acr = 0;
printf("RS-232\n");
} else {
acr = (high == 1 ? 0x18 : 0x10);
printf("RS-422/RS-485, active-%s auto-DTR\n",
high == 1 ? "high" : "low");
}
}
bus_write_1(bar->b_res, REG_SPR, REG_ACR);
bus_write_1(bar->b_res, REG_ICR, acr);
}
bus_release_resource(cdev, crtype, rman_get_rid(cres), cres);
return (0);
}
static int
puc_config_amc(struct puc_softc *sc __unused, enum puc_cfg_cmd cmd, int port,
intptr_t *res)
@ -1360,24 +1465,17 @@ puc_config_quatech(struct puc_softc *sc, enum puc_cfg_cmd cmd,
bar = puc_get_bar(sc, cfg->rid);
if (bar == NULL)
return (ENXIO);
/* Set DLAB in the LCR register of UART 0. */
bus_write_1(bar->b_res, 3, 0x80);
/* Write 0 to the SPR register of UART 0. */
bus_write_1(bar->b_res, 7, 0);
/* Read back the contents of the SPR register of UART 0. */
v0 = bus_read_1(bar->b_res, 7);
/* Write a specific value to the SPR register of UART 0. */
bus_write_1(bar->b_res, 7, 0x80 + -cfg->clock);
/* Read back the contents of the SPR register of UART 0. */
v1 = bus_read_1(bar->b_res, 7);
/* Clear DLAB in the LCR register of UART 0. */
bus_write_1(bar->b_res, 3, 0);
/* Save the two values read-back from the SPR register. */
bus_write_1(bar->b_res, REG_LCR, LCR_DLAB);
bus_write_1(bar->b_res, REG_SPR, 0);
v0 = bus_read_1(bar->b_res, REG_SPR);
bus_write_1(bar->b_res, REG_SPR, 0x80 + -cfg->clock);
v1 = bus_read_1(bar->b_res, REG_SPR);
bus_write_1(bar->b_res, REG_LCR, 0);
sc->sc_cfg_data = (v0 << 8) | v1;
if (v0 == 0 && v1 == 0x80 + -cfg->clock) {
/*
* The SPR register echoed the two values written
* by us. This means that the SPAD jumper is set.
* by us. This means that the SPAD jumper is set.
*/
device_printf(sc->sc_dev, "warning: extra features "
"not usable -- SPAD compatibility enabled\n");
@ -1385,7 +1483,7 @@ puc_config_quatech(struct puc_softc *sc, enum puc_cfg_cmd cmd,
}
if (v0 != 0) {
/*
* The first value doesn't match. This can only mean
* The first value doesn't match. This can only mean
* that the SPAD jumper is not set and that a non-
* standard fixed clock multiplier jumper is set.
*/
@ -1399,8 +1497,8 @@ puc_config_quatech(struct puc_softc *sc, enum puc_cfg_cmd cmd,
return (0);
}
/*
* The first value matched, but the second didn't. We know
* that the SPAD jumper is not set. We also know that the
* The first value matched, but the second didn't. We know
* that the SPAD jumper is not set. We also know that the
* clock rate multiplier is software controlled *and* that
* we just programmed it to the maximum allowed.
*/
@ -1415,8 +1513,8 @@ puc_config_quatech(struct puc_softc *sc, enum puc_cfg_cmd cmd,
/*
* XXX With the SPAD jumper applied, there's no
* easy way of knowing if there's also a clock
* rate multiplier jumper installed. Let's hope
* not...
* rate multiplier jumper installed. Let's hope
* not ...
*/
*res = DEFAULT_RCLK;
} else if (v0 == 0) {
@ -1678,15 +1776,15 @@ puc_config_oxford_pcie(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
case PUC_CFG_GET_NPORTS:
/*
* Check if we are being called from puc_bfe_attach()
* or puc_bfe_probe(). If puc_bfe_probe(), we cannot
* puc_get_bar(), so we return a value of 16. This has cosmetic
* side-effects at worst; in PUC_CFG_GET_DESC,
* (int)sc->sc_cfg_data will not contain the true number of
* ports in PUC_CFG_GET_DESC, but we are not implementing that
* call for this device family anyway.
* or puc_bfe_probe(). If puc_bfe_probe(), we cannot
* puc_get_bar(), so we return a value of 16. This has
* cosmetic side-effects at worst; in PUC_CFG_GET_DESC,
* sc->sc_cfg_data will not contain the true number of
* ports in PUC_CFG_GET_DESC, but we are not implementing
* that call for this device family anyway.
*
* The check is for initialisation of sc->sc_bar[idx], which is
* only done in puc_bfe_attach().
* The check is for initialization of sc->sc_bar[idx],
* which is only done in puc_bfe_attach().
*/
idx = 0;
do {

View File

@ -1683,7 +1683,7 @@ rtwn_tx(struct rtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 0));
}
/* Set sequence number (already little endian). */
txd->txdseq = *(uint16_t *)wh->i_seq;
txd->txdseq = htole16(M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE);
if (!qos) {
/* Use HW sequence numbering for non-QoS frames. */

View File

@ -238,6 +238,7 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
#define EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE 0
#define EFSYS_OPT_SIENA 1
#define EFSYS_OPT_HUNTINGTON 1
#define EFSYS_OPT_MEDFORD 0
#ifdef DEBUG
#define EFSYS_OPT_CHECK_REG 1
#else

View File

@ -1634,7 +1634,7 @@ ti_newbuf_jumbo(struct ti_softc *sc, int idx, struct mbuf *m_old)
m[i]->m_data = (void *)sf_buf_kva(sf[i]);
m[i]->m_len = PAGE_SIZE;
MEXTADD(m[i], sf_buf_kva(sf[i]), PAGE_SIZE,
sf_buf_mext, (void*)sf_buf_kva(sf[i]), sf[i],
sf_mext_free, (void*)sf_buf_kva(sf[i]), sf[i],
0, EXT_DISPOSABLE);
m[i]->m_next = m[i+1];
}
@ -1699,7 +1699,7 @@ ti_newbuf_jumbo(struct ti_softc *sc, int idx, struct mbuf *m_old)
if (m[i])
m_freem(m[i]);
if (sf[i])
sf_buf_mext((void *)sf_buf_kva(sf[i]), sf[i]);
sf_mext_free((void *)sf_buf_kva(sf[i]), sf[i]);
}
return (ENOBUFS);
}

View File

@ -57,6 +57,7 @@ struct ofwfb_softc {
int iso_palette;
};
static void ofwfb_initialize(struct vt_device *vd);
static vd_probe_t ofwfb_probe;
static vd_init_t ofwfb_init;
static vd_bitblt_text_t ofwfb_bitblt_text;
@ -124,6 +125,18 @@ ofwfb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw,
uint8_t c[4];
} ch1, ch2;
#ifdef __powerpc__
/* Deal with unmapped framebuffers */
if (sc->fb_flags & FB_FLAG_NOWRITE) {
if (pmap_bootstrapped) {
sc->fb_flags &= ~FB_FLAG_NOWRITE;
ofwfb_initialize(vd);
} else {
return;
}
}
#endif
fgc = sc->fb_cmap[fg];
bgc = sc->fb_cmap[bg];
b = m = 0;
@ -271,6 +284,11 @@ ofwfb_initialize(struct vt_device *vd)
cell_t retval;
uint32_t oldpix;
sc->fb.fb_cmsize = 16;
if (sc->fb.fb_flags & FB_FLAG_NOWRITE)
return;
/*
* Set up the color map
*/
@ -318,8 +336,6 @@ ofwfb_initialize(struct vt_device *vd)
panic("Unknown color space depth %d", sc->fb.fb_bpp);
break;
}
sc->fb.fb_cmsize = 16;
}
static int
@ -466,6 +482,11 @@ ofwfb_init(struct vt_device *vd)
#if defined(__powerpc__)
OF_decode_addr(node, fb_phys, &sc->sc_memt, &sc->fb.fb_vbase);
sc->fb.fb_pbase = sc->fb.fb_vbase; /* 1:1 mapped */
#ifdef __powerpc64__
/* Real mode under a hypervisor probably doesn't cover FB */
if (!(mfmsr() & (PSL_HV | PSL_DR)))
sc->fb.fb_flags |= FB_FLAG_NOWRITE;
#endif
#else
/* No ability to interpret assigned-addresses otherwise */
return (CN_DEAD);

View File

@ -102,9 +102,6 @@ ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb)
fs = ip->i_e2fs;
lbn = bn;
/*
* TODO: need to implement read ahead to improve the performance.
*/
if (runp != NULL)
*runp = 0;
@ -112,15 +109,25 @@ ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb)
*runb = 0;
ext4_ext_find_extent(fs, ip, lbn, &path);
ep = path.ep_ext;
if (ep == NULL)
ret = EIO;
else {
*bnp = fsbtodb(fs, lbn - ep->e_blk +
(ep->e_start_lo | (daddr_t)ep->e_start_hi << 32));
if (path.ep_is_sparse) {
*bnp = -1;
if (runp != NULL)
*runp = path.ep_sparse_ext.e_len -
(lbn - path.ep_sparse_ext.e_blk) - 1;
} else {
ep = path.ep_ext;
if (ep == NULL)
ret = EIO;
else {
*bnp = fsbtodb(fs, lbn - ep->e_blk +
(ep->e_start_lo | (daddr_t)ep->e_start_hi << 32));
if (*bnp == 0)
*bnp = -1;
if (*bnp == 0)
*bnp = -1;
if (runp != NULL)
*runp = ep->e_len - (lbn - ep->e_blk) - 1;
}
}
if (path.ep_bp != NULL) {

View File

@ -66,13 +66,14 @@ static void
ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn)
{
struct ext4_extent_header *ehp = path->ep_header;
struct ext4_extent *l, *r, *m;
struct ext4_extent *first, *l, *r, *m;
if (ehp->eh_ecount == 0)
return;
l = (struct ext4_extent *)(char *)(ehp + 1);
r = (struct ext4_extent *)(char *)(ehp + 1) + ehp->eh_ecount - 1;
first = (struct ext4_extent *)(char *)(ehp + 1);
l = first;
r = first + ehp->eh_ecount - 1;
while (l <= r) {
m = l + (r - l) / 2;
if (lbn < m->e_blk)
@ -81,7 +82,25 @@ ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn)
l = m + 1;
}
if (l == first) {
path->ep_sparse_ext.e_blk = lbn;
path->ep_sparse_ext.e_len = first->e_blk - lbn;
path->ep_sparse_ext.e_start_hi = 0;
path->ep_sparse_ext.e_start_lo = 0;
path->ep_is_sparse = 1;
return;
}
path->ep_ext = l - 1;
if (path->ep_ext->e_blk + path->ep_ext->e_len <= lbn) {
path->ep_sparse_ext.e_blk = lbn;
if (l <= (first + ehp->eh_ecount - 1))
path->ep_sparse_ext.e_len = l->e_blk - lbn;
else // XXX: where does it end?
path->ep_sparse_ext.e_len = 1;
path->ep_sparse_ext.e_start_hi = 0;
path->ep_sparse_ext.e_start_lo = 0;
path->ep_is_sparse = 1;
}
}
/*
@ -169,6 +188,7 @@ ext4_ext_find_extent(struct m_ext2fs *fs, struct inode *ip,
path->ep_depth = i;
path->ep_ext = NULL;
path->ep_index = NULL;
path->ep_is_sparse = 0;
ext4_ext_binsearch(ip, path, lbn);
return (path);

View File

@ -84,7 +84,11 @@ struct ext4_extent_cache {
struct ext4_extent_path {
uint16_t ep_depth;
struct buf *ep_bp;
struct ext4_extent *ep_ext;
int ep_is_sparse;
union {
struct ext4_extent ep_sparse_ext;
struct ext4_extent *ep_ext;
};
struct ext4_extent_index *ep_index;
struct ext4_extent_header *ep_header;
};

View File

@ -590,7 +590,7 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp)
* while Linux keeps the super block in a locked buffer.
*/
ump->um_e2fs = malloc(sizeof(struct m_ext2fs),
M_EXT2MNT, M_WAITOK);
M_EXT2MNT, M_WAITOK | M_ZERO);
ump->um_e2fs->e2fs = malloc(sizeof(struct ext2fs),
M_EXT2MNT, M_WAITOK);
mtx_init(EXT2_MTX(ump), "EXT2FS", "EXT2FS Lock", MTX_DEF);

View File

@ -1787,6 +1787,7 @@ ext2_ioctl(struct vop_ioctl_args *ap)
static int
ext4_ext_read(struct vop_read_args *ap)
{
static unsigned char zeroes[EXT2_MAX_BLOCK_SIZE];
struct vnode *vp;
struct inode *ip;
struct uio *uio;
@ -1831,11 +1832,15 @@ ext4_ext_read(struct vop_read_args *ap)
switch (cache_type) {
case EXT4_EXT_CACHE_NO:
ext4_ext_find_extent(fs, ip, lbn, &path);
ep = path.ep_ext;
if (path.ep_is_sparse)
ep = &path.ep_sparse_ext;
else
ep = path.ep_ext;
if (ep == NULL)
return (EIO);
ext4_ext_put_cache(ip, ep, EXT4_EXT_CACHE_IN);
ext4_ext_put_cache(ip, ep,
path.ep_is_sparse ? EXT4_EXT_CACHE_GAP : EXT4_EXT_CACHE_IN);
newblk = lbn - ep->e_blk + (ep->e_start_lo |
(daddr_t)ep->e_start_hi << 32);
@ -1848,7 +1853,7 @@ ext4_ext_read(struct vop_read_args *ap)
case EXT4_EXT_CACHE_GAP:
/* block has not been allocated yet */
return (0);
break;
case EXT4_EXT_CACHE_IN:
newblk = lbn - nex.e_blk + (nex.e_start_lo |
@ -1859,24 +1864,34 @@ ext4_ext_read(struct vop_read_args *ap)
panic("%s: invalid cache type", __func__);
}
error = bread(ip->i_devvp, fsbtodb(fs, newblk), size, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
size -= bp->b_resid;
if (size < xfersize) {
if (size == 0) {
bqrelse(bp);
break;
if (cache_type == EXT4_EXT_CACHE_GAP ||
(cache_type == EXT4_EXT_CACHE_NO && path.ep_is_sparse)) {
if (xfersize > sizeof(zeroes))
xfersize = sizeof(zeroes);
error = uiomove(zeroes, xfersize, uio);
if (error)
return (error);
} else {
error = bread(ip->i_devvp, fsbtodb(fs, newblk), size,
NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
xfersize = size;
size -= bp->b_resid;
if (size < xfersize) {
if (size == 0) {
bqrelse(bp);
break;
}
xfersize = size;
}
error = uiomove(bp->b_data + blkoffset, xfersize, uio);
bqrelse(bp);
if (error)
return (error);
}
error = uiomove(bp->b_data + blkoffset, (int)xfersize, uio);
bqrelse(bp);
if (error)
return (error);
}
return (0);

View File

@ -333,18 +333,18 @@ smbfs_smb_flush(struct smbnode *np, struct smb_cred *scred)
}
int
smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
smbfs_smb_setfsize(struct smbnode *np, int64_t newsize, struct smb_cred *scred)
{
struct smb_share *ssp = np->n_mount->sm_share;
struct smb_rq *rqp;
struct mbchain *mbp;
int error;
if (!smbfs_smb_seteof(np, (int64_t) newsize, scred)) {
if (!smbfs_smb_seteof(np, newsize, scred)) {
np->n_flag |= NFLUSHWIRE;
return (0);
}
/* XXX: We should use SMB_COM_WRITE_ANDX to support large offsets */
error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
if (error)
return (error);
@ -352,7 +352,7 @@ smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM);
mb_put_uint16le(mbp, 0);
mb_put_uint32le(mbp, newsize);
mb_put_uint32le(mbp, (uint32_t)newsize);
mb_put_uint16le(mbp, 0);
smb_rq_wend(rqp);
smb_rq_bstart(rqp);

View File

@ -128,7 +128,8 @@ int smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
off_t start, off_t end, struct smb_cred *scred);
int smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
struct smb_cred *scred);
int smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred);
int smbfs_smb_setfsize(struct smbnode *np, int64_t newsize,
struct smb_cred *scred);
int smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
struct smbfattr *fap, struct smb_cred *scred);

View File

@ -358,7 +358,8 @@ smbfs_setattr(ap)
doclose = 1;
}
if (error == 0)
error = smbfs_smb_setfsize(np, vap->va_size, scred);
error = smbfs_smb_setfsize(np,
(int64_t)vap->va_size, scred);
if (doclose)
smbfs_smb_close(ssp, np->n_fid, NULL, scred);
if (error) {

View File

@ -87,6 +87,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);

View File

@ -90,6 +90,7 @@ struct sysentvec ibcs2_svr3_sysvec = {
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
static int

View File

@ -985,6 +985,7 @@ struct sysentvec linux_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
.sv_thread_detach = linux_thread_detach,
.sv_trap = NULL,
};
INIT_SYSENTVEC(aout_sysvec, &linux_sysvec);
@ -1021,6 +1022,7 @@ struct sysentvec elf_linux_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
.sv_thread_detach = linux_thread_detach,
.sv_trap = NULL,
};
static void

View File

@ -97,6 +97,7 @@ struct sysentvec aout_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
#elif defined(__amd64__)

View File

@ -414,6 +414,7 @@ struct sysentvec null_sysvec = {
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
/*

View File

@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
@ -46,6 +47,17 @@ __FBSDID("$FreeBSD$");
#include <sys/ktrace.h>
#endif
/*
* A bound below which cv_waiters is valid. Once cv_waiters reaches this bound,
* cv_signal must manually check the wait queue for threads.
*/
#define CV_WAITERS_BOUND INT_MAX
#define CV_WAITERS_INC(cvp) do { \
if ((cvp)->cv_waiters < CV_WAITERS_BOUND) \
(cvp)->cv_waiters++; \
} while (0)
/*
* Common sanity checks for cv_wait* functions.
*/
@ -122,7 +134,7 @@ _cv_wait(struct cv *cvp, struct lock_object *lock)
sleepq_lock(cvp);
cvp->cv_waiters++;
CV_WAITERS_INC(cvp);
if (lock == &Giant.lock_object)
mtx_assert(&Giant, MA_OWNED);
DROP_GIANT();
@ -184,7 +196,7 @@ _cv_wait_unlock(struct cv *cvp, struct lock_object *lock)
sleepq_lock(cvp);
cvp->cv_waiters++;
CV_WAITERS_INC(cvp);
DROP_GIANT();
sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR, 0);
@ -240,7 +252,7 @@ _cv_wait_sig(struct cv *cvp, struct lock_object *lock)
sleepq_lock(cvp);
cvp->cv_waiters++;
CV_WAITERS_INC(cvp);
if (lock == &Giant.lock_object)
mtx_assert(&Giant, MA_OWNED);
DROP_GIANT();
@ -307,7 +319,7 @@ _cv_timedwait_sbt(struct cv *cvp, struct lock_object *lock, sbintime_t sbt,
sleepq_lock(cvp);
cvp->cv_waiters++;
CV_WAITERS_INC(cvp);
if (lock == &Giant.lock_object)
mtx_assert(&Giant, MA_OWNED);
DROP_GIANT();
@ -376,7 +388,7 @@ _cv_timedwait_sig_sbt(struct cv *cvp, struct lock_object *lock,
sleepq_lock(cvp);
cvp->cv_waiters++;
CV_WAITERS_INC(cvp);
if (lock == &Giant.lock_object)
mtx_assert(&Giant, MA_OWNED);
DROP_GIANT();
@ -422,8 +434,15 @@ cv_signal(struct cv *cvp)
wakeup_swapper = 0;
sleepq_lock(cvp);
if (cvp->cv_waiters > 0) {
cvp->cv_waiters--;
wakeup_swapper = sleepq_signal(cvp, SLEEPQ_CONDVAR, 0, 0);
if (cvp->cv_waiters == CV_WAITERS_BOUND &&
sleepq_lookup(cvp) == NULL) {
cvp->cv_waiters = 0;
} else {
if (cvp->cv_waiters < CV_WAITERS_BOUND)
cvp->cv_waiters--;
wakeup_swapper = sleepq_signal(cvp, SLEEPQ_CONDVAR, 0,
0);
}
}
sleepq_release(cvp);
if (wakeup_swapper)

View File

@ -338,6 +338,9 @@ mb_free_ext(struct mbuf *m)
case EXT_SFBUF:
sf_ext_free(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
break;
case EXT_SFBUF_NOCACHE:
sf_ext_free_nocache(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
break;
default:
KASSERT(m->m_ext.ext_cnt != NULL,
("%s: no refcounting pointer on %p", __func__, m));
@ -404,6 +407,7 @@ mb_dupcl(struct mbuf *n, const struct mbuf *m)
switch (m->m_ext.ext_type) {
case EXT_SFBUF:
case EXT_SFBUF_NOCACHE:
sf_ext_ref(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
break;
default:

View File

@ -68,6 +68,23 @@ static u_long sb_efficiency = 8; /* parameter for sbreserve() */
static struct mbuf *sbcut_internal(struct sockbuf *sb, int len);
static void sbflush_internal(struct sockbuf *sb);
/*
* Our own version of m_clrprotoflags(), that can preserve M_NOTREADY.
*/
static void
sbm_clrprotoflags(struct mbuf *m, int flags)
{
int mask;
mask = ~M_PROTOFLAGS;
if (flags & PRUS_NOTREADY)
mask |= M_NOTREADY;
while (m) {
m->m_flags &= mask;
m = m->m_next;
}
}
/*
* Mark ready "count" mbufs starting with "m".
*/
@ -569,7 +586,7 @@ sblastmbufchk(struct sockbuf *sb, const char *file, int line)
* are discarded and mbufs are compacted where possible.
*/
void
sbappend_locked(struct sockbuf *sb, struct mbuf *m)
sbappend_locked(struct sockbuf *sb, struct mbuf *m, int flags)
{
struct mbuf *n;
@ -577,7 +594,7 @@ sbappend_locked(struct sockbuf *sb, struct mbuf *m)
if (m == 0)
return;
m_clrprotoflags(m);
sbm_clrprotoflags(m, flags);
SBLASTRECORDCHK(sb);
n = sb->sb_mb;
if (n) {
@ -620,11 +637,11 @@ sbappend_locked(struct sockbuf *sb, struct mbuf *m)
* are discarded and mbufs are compacted where possible.
*/
void
sbappend(struct sockbuf *sb, struct mbuf *m)
sbappend(struct sockbuf *sb, struct mbuf *m, int flags)
{
SOCKBUF_LOCK(sb);
sbappend_locked(sb, m);
sbappend_locked(sb, m, flags);
SOCKBUF_UNLOCK(sb);
}

View File

@ -113,15 +113,6 @@ static int getpeername1(struct thread *td, struct getpeername_args *uap,
counter_u64_t sfstat[sizeof(struct sfstat) / sizeof(uint64_t)];
/*
* sendfile(2)-related variables and associated sysctls
*/
static SYSCTL_NODE(_kern_ipc, OID_AUTO, sendfile, CTLFLAG_RW, 0,
"sendfile(2) tunables");
static int sfreadahead = 1;
SYSCTL_INT(_kern_ipc_sendfile, OID_AUTO, readahead, CTLFLAG_RW,
&sfreadahead, 0, "Number of sendfile(2) read-ahead MAXBSIZE blocks");
static void
sfstat_init(const void *unused)
{
@ -1858,13 +1849,12 @@ sf_ext_free(void *arg1, void *arg2)
sf_buf_free(sf);
vm_page_lock(pg);
vm_page_unwire(pg, PQ_INACTIVE);
/*
* Check for the object going away on us. This can
* happen since we don't hold a reference to it.
* If so, we're responsible for freeing the page.
*/
if (pg->wire_count == 0 && pg->object == NULL)
if (vm_page_unwire(pg, PQ_INACTIVE) && pg->object == NULL)
vm_page_free(pg);
vm_page_unlock(pg);
@ -1877,6 +1867,43 @@ sf_ext_free(void *arg1, void *arg2)
}
}
/*
* Same as above, but forces the page to be detached from the object
* and go into free pool.
*/
void
sf_ext_free_nocache(void *arg1, void *arg2)
{
struct sf_buf *sf = arg1;
struct sendfile_sync *sfs = arg2;
vm_page_t pg = sf_buf_page(sf);
sf_buf_free(sf);
vm_page_lock(pg);
if (vm_page_unwire(pg, PQ_NONE)) {
vm_object_t obj;
/* Try to free the page, but only if it is cheap to. */
if ((obj = pg->object) == NULL)
vm_page_free(pg);
else if (!vm_page_xbusied(pg) && VM_OBJECT_TRYWLOCK(obj)) {
vm_page_free(pg);
VM_OBJECT_WUNLOCK(obj);
} else
vm_page_deactivate(pg);
}
vm_page_unlock(pg);
if (sfs != NULL) {
mtx_lock(&sfs->mtx);
KASSERT(sfs->count > 0, ("Sendfile sync botchup count == 0"));
if (--sfs->count == 0)
cv_signal(&sfs->cv);
mtx_unlock(&sfs->mtx);
}
}
/*
* sendfile(2)
*
@ -1974,103 +2001,252 @@ freebsd4_sendfile(struct thread *td, struct freebsd4_sendfile_args *uap)
}
#endif /* COMPAT_FREEBSD4 */
static int
sendfile_readpage(vm_object_t obj, struct vnode *vp, int nd,
off_t off, int xfsize, int bsize, struct thread *td, vm_page_t *res)
/*
* How much data to put into page i of n.
* Only first and last pages are special.
*/
static inline off_t
xfsize(int i, int n, off_t off, off_t len)
{
vm_page_t m;
vm_pindex_t pindex;
ssize_t resid;
int error, readahead, rv;
pindex = OFF_TO_IDX(off);
VM_OBJECT_WLOCK(obj);
m = vm_page_grab(obj, pindex, (vp != NULL ? VM_ALLOC_NOBUSY |
VM_ALLOC_IGN_SBUSY : 0) | VM_ALLOC_WIRED | VM_ALLOC_NORMAL);
if (i == 0)
return (omin(PAGE_SIZE - (off & PAGE_MASK), len));
/*
* Check if page is valid for what we need, otherwise initiate I/O.
*
* The non-zero nd argument prevents disk I/O, instead we
* return the caller what he specified in nd. In particular,
* if we already turned some pages into mbufs, nd == EAGAIN
* and the main function send them the pages before we come
* here again and block.
*/
if (m->valid != 0 && vm_page_is_valid(m, off & PAGE_MASK, xfsize)) {
if (vp == NULL)
vm_page_xunbusy(m);
VM_OBJECT_WUNLOCK(obj);
*res = m;
return (0);
} else if (nd != 0) {
if (vp == NULL)
vm_page_xunbusy(m);
error = nd;
goto free_page;
if (i == n - 1 && ((off + len) & PAGE_MASK) > 0)
return ((off + len) & PAGE_MASK);
return (PAGE_SIZE);
}
/*
* Offset within object for i page.
*/
static inline vm_offset_t
vmoff(int i, off_t off)
{
if (i == 0)
return ((vm_offset_t)off);
return (trunc_page(off + i * PAGE_SIZE));
}
/*
* Pretend as if we don't have enough space, subtract xfsize() of
* all pages that failed.
*/
static inline void
fixspace(int old, int new, off_t off, int *space)
{
KASSERT(old > new, ("%s: old %d new %d", __func__, old, new));
/* Subtract last one. */
*space -= xfsize(old - 1, old, off, *space);
old--;
if (new == old)
/* There was only one page. */
return;
/* Subtract first one. */
if (new == 0) {
*space -= xfsize(0, old, off, *space);
new++;
}
/*
* Get the page from backing store.
*/
error = 0;
if (vp != NULL) {
VM_OBJECT_WUNLOCK(obj);
readahead = sfreadahead * MAXBSIZE;
/* Rest of pages are full sized. */
*space -= (old - new) * PAGE_SIZE;
KASSERT(*space >= 0, ("%s: space went backwards", __func__));
}
/*
* Structure describing a single sendfile(2) I/O, which may consist of
* several underlying pager I/Os.
*
* The syscall context allocates the structure and initializes 'nios'
* to 1. As sendfile_swapin() runs through pages and starts asynchronous
* paging operations, it increments 'nios'.
*
* Every I/O completion calls sf_iodone(), which decrements the 'nios', and
* the syscall also calls sf_iodone() after allocating all mbufs, linking them
* and sending to socket. Whoever reaches zero 'nios' is responsible to
* call pru_ready on the socket, to notify it of readyness of the data.
*/
struct sf_io {
volatile u_int nios;
u_int error;
int npages;
struct file *sock_fp;
struct mbuf *m;
vm_page_t pa[];
};
static void
sf_iodone(void *arg, vm_page_t *pg, int count, int error)
{
struct sf_io *sfio = arg;
struct socket *so;
for (int i = 0; i < count; i++)
vm_page_xunbusy(pg[i]);
if (error)
sfio->error = error;
if (!refcount_release(&sfio->nios))
return;
so = sfio->sock_fp->f_data;
if (sfio->error) {
struct mbuf *m;
/*
* Use vn_rdwr() instead of the pager interface for
* the vnode, to allow the read-ahead.
* I/O operation failed. The state of data in the socket
* is now inconsistent, and all what we can do is to tear
* it down. Protocol abort method would tear down protocol
* state, free all ready mbufs and detach not ready ones.
* We will free the mbufs corresponding to this I/O manually.
*
* XXXMAC: Because we don't have fp->f_cred here, we
* pass in NOCRED. This is probably wrong, but is
* consistent with our original implementation.
* The socket would be marked with EIO and made available
* for read, so that application receives EIO on next
* syscall and eventually closes the socket.
*/
error = vn_rdwr(UIO_READ, vp, NULL, readahead, trunc_page(off),
UIO_NOCOPY, IO_NODELOCKED | IO_VMIO | ((readahead /
bsize) << IO_SEQSHIFT), td->td_ucred, NOCRED, &resid, td);
SFSTAT_INC(sf_iocnt);
VM_OBJECT_WLOCK(obj);
so->so_proto->pr_usrreqs->pru_abort(so);
so->so_error = EIO;
m = sfio->m;
for (int i = 0; i < sfio->npages; i++)
m = m_free(m);
} else {
if (vm_pager_has_page(obj, pindex, NULL, NULL)) {
rv = vm_pager_get_pages(obj, &m, 1, NULL, NULL);
SFSTAT_INC(sf_iocnt);
if (rv != VM_PAGER_OK) {
vm_page_lock(m);
vm_page_free(m);
vm_page_unlock(m);
m = NULL;
error = EIO;
}
} else {
pmap_zero_page(m);
m->valid = VM_PAGE_BITS_ALL;
m->dirty = 0;
}
if (m != NULL)
vm_page_xunbusy(m);
CURVNET_SET(so->so_vnet);
(void )(so->so_proto->pr_usrreqs->pru_ready)(so, sfio->m,
sfio->npages);
CURVNET_RESTORE();
}
if (error == 0) {
*res = m;
} else if (m != NULL) {
free_page:
vm_page_lock(m);
vm_page_unwire(m, PQ_INACTIVE);
/* XXXGL: curthread */
fdrop(sfio->sock_fp, curthread);
free(sfio, M_TEMP);
}
/*
* Iterate through pages vector and request paging for non-valid pages.
*/
static int
sendfile_swapin(vm_object_t obj, struct sf_io *sfio, off_t off, off_t len,
int npages, int rhpages, int flags)
{
vm_page_t *pa = sfio->pa;
int nios;
nios = 0;
flags = (flags & SF_NODISKIO) ? VM_ALLOC_NOWAIT : 0;
/*
* First grab all the pages and wire them. Note that we grab
* only required pages. Readahead pages are dealt with later.
*/
VM_OBJECT_WLOCK(obj);
for (int i = 0; i < npages; i++) {
pa[i] = vm_page_grab(obj, OFF_TO_IDX(vmoff(i, off)),
VM_ALLOC_WIRED | VM_ALLOC_NORMAL | flags);
if (pa[i] == NULL) {
npages = i;
rhpages = 0;
break;
}
}
for (int i = 0; i < npages;) {
int j, a, count, rv;
/* Skip valid pages. */
if (vm_page_is_valid(pa[i], vmoff(i, off) & PAGE_MASK,
xfsize(i, npages, off, len))) {
vm_page_xunbusy(pa[i]);
SFSTAT_INC(sf_pages_valid);
i++;
continue;
}
/*
* See if anyone else might know about this page. If
* not and it is not valid, then free it.
* Now 'i' points to first invalid page, iterate further
* to make 'j' point at first valid after a bunch of
* invalid ones.
*/
if (m->wire_count == 0 && m->valid == 0 && !vm_page_busied(m))
vm_page_free(m);
vm_page_unlock(m);
for (j = i + 1; j < npages; j++)
if (vm_page_is_valid(pa[j], vmoff(j, off) & PAGE_MASK,
xfsize(j, npages, off, len))) {
SFSTAT_INC(sf_pages_valid);
break;
}
/*
* Now we got region of invalid pages between 'i' and 'j'.
* Check that they belong to pager. They may not be there,
* which is a regular situation for shmem pager. For vnode
* pager this happens only in case of sparse file.
*
* Important feature of vm_pager_has_page() is the hint
* stored in 'a', about how many pages we can pagein after
* this page in a single I/O.
*/
while (!vm_pager_has_page(obj, OFF_TO_IDX(vmoff(i, off)),
NULL, &a) && i < j) {
pmap_zero_page(pa[i]);
pa[i]->valid = VM_PAGE_BITS_ALL;
pa[i]->dirty = 0;
vm_page_xunbusy(pa[i]);
i++;
}
if (i == j)
continue;
/*
* We want to pagein as many pages as possible, limited only
* by the 'a' hint and actual request.
*
* We should not pagein into already valid page, thus if
* 'j' didn't reach last page, trim by that page.
*
* When the pagein fulfils the request, also specify readahead.
*/
if (j < npages)
a = min(a, j - i - 1);
count = min(a + 1, npages - i);
refcount_acquire(&sfio->nios);
rv = vm_pager_get_pages_async(obj, pa + i, count, NULL,
i + count == npages ? &rhpages : NULL,
&sf_iodone, sfio);
KASSERT(rv == VM_PAGER_OK, ("%s: pager fail obj %p page %p",
__func__, obj, pa[i]));
SFSTAT_INC(sf_iocnt);
SFSTAT_ADD(sf_pages_read, count);
if (i + count == npages)
SFSTAT_ADD(sf_rhpages_read, rhpages);
#ifdef INVARIANTS
for (j = i; j < i + count && j < npages; j++)
KASSERT(pa[j] == vm_page_lookup(obj,
OFF_TO_IDX(vmoff(j, off))),
("pa[j] %p lookup %p\n", pa[j],
vm_page_lookup(obj, OFF_TO_IDX(vmoff(j, off)))));
#endif
i += count;
nios++;
}
KASSERT(error != 0 || (m->wire_count > 0 &&
vm_page_is_valid(m, off & PAGE_MASK, xfsize)),
("wrong page state m %p off %#jx xfsize %d", m, (uintmax_t)off,
xfsize));
VM_OBJECT_WUNLOCK(obj);
return (error);
if (nios == 0 && npages != 0)
SFSTAT_INC(sf_noiocnt);
return (nios);
}
static int
@ -2178,80 +2354,65 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct vnode *vp;
struct vm_object *obj;
struct socket *so;
struct mbuf *m;
struct mbuf *m, *mh, *mhtail;
struct sf_buf *sf;
struct vm_page *pg;
struct shmfd *shmfd;
struct sendfile_sync *sfs;
struct vattr va;
off_t off, xfsize, fsbytes, sbytes, rem, obj_size;
int error, bsize, nd, hdrlen, mnw;
off_t off, sbytes, rem, obj_size;
int error, softerr, bsize, hdrlen;
pg = NULL;
obj = NULL;
so = NULL;
m = NULL;
m = mh = NULL;
sfs = NULL;
fsbytes = sbytes = 0;
hdrlen = mnw = 0;
rem = nbytes;
obj_size = 0;
sbytes = 0;
softerr = 0;
error = sendfile_getobj(td, fp, &obj, &vp, &shmfd, &obj_size, &bsize);
if (error != 0)
return (error);
if (rem == 0)
rem = obj_size;
error = kern_sendfile_getsock(td, sockfd, &sock_fp, &so);
if (error != 0)
goto out;
/*
* Do not wait on memory allocations but return ENOMEM for
* caller to retry later.
* XXX: Experimental.
*/
if (flags & SF_MNOWAIT)
mnw = 1;
if (flags & SF_SYNC) {
sfs = malloc(sizeof *sfs, M_TEMP, M_WAITOK | M_ZERO);
mtx_init(&sfs->mtx, "sendfile", NULL, MTX_DEF);
cv_init(&sfs->cv, "sendfile");
}
#ifdef MAC
error = mac_socket_check_send(td->td_ucred, so);
if (error != 0)
goto out;
#endif
SFSTAT_INC(sf_syscalls);
SFSTAT_ADD(sf_rhpages_requested, SF_READAHEAD(flags));
if (flags & SF_SYNC) {
sfs = malloc(sizeof *sfs, M_TEMP, M_WAITOK | M_ZERO);
mtx_init(&sfs->mtx, "sendfile", NULL, MTX_DEF);
cv_init(&sfs->cv, "sendfile");
}
/* If headers are specified copy them into mbufs. */
if (hdr_uio != NULL) {
if (hdr_uio != NULL && hdr_uio->uio_resid > 0) {
hdr_uio->uio_td = td;
hdr_uio->uio_rw = UIO_WRITE;
if (hdr_uio->uio_resid > 0) {
/*
* In FBSD < 5.0 the nbytes to send also included
* the header. If compat is specified subtract the
* header size from nbytes.
*/
if (kflags & SFK_COMPAT) {
if (nbytes > hdr_uio->uio_resid)
nbytes -= hdr_uio->uio_resid;
else
nbytes = 0;
}
m = m_uiotombuf(hdr_uio, (mnw ? M_NOWAIT : M_WAITOK),
0, 0, 0);
if (m == NULL) {
error = mnw ? EAGAIN : ENOBUFS;
goto out;
}
hdrlen = m_length(m, NULL);
/*
* In FBSD < 5.0 the nbytes to send also included
* the header. If compat is specified subtract the
* header size from nbytes.
*/
if (kflags & SFK_COMPAT) {
if (nbytes > hdr_uio->uio_resid)
nbytes -= hdr_uio->uio_resid;
else
nbytes = 0;
}
}
mh = m_uiotombuf(hdr_uio, M_WAITOK, 0, 0, 0);
hdrlen = m_length(mh, &mhtail);
} else
hdrlen = 0;
rem = nbytes ? omin(nbytes, obj_size - offset) : obj_size - offset;
/*
* Protect against multiple writers to the socket.
@ -2272,21 +2433,13 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
* The outer loop checks the state and available space of the socket
* and takes care of the overall progress.
*/
for (off = offset; ; ) {
for (off = offset; rem > 0; ) {
struct sf_io *sfio;
vm_page_t *pa;
struct mbuf *mtail;
int loopbytes;
int space;
int done;
if ((nbytes != 0 && nbytes == fsbytes) ||
(nbytes == 0 && obj_size == fsbytes))
break;
int nios, space, npages, rhpages;
mtail = NULL;
loopbytes = 0;
space = 0;
done = 0;
/*
* Check the socket state for ongoing connection,
* no errors and space in socket buffer.
@ -2362,49 +2515,58 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
VOP_UNLOCK(vp, 0);
goto done;
}
obj_size = va.va_size;
if (va.va_size != obj_size) {
if (nbytes == 0)
rem += va.va_size - obj_size;
else if (offset + nbytes > va.va_size)
rem -= (offset + nbytes - va.va_size);
obj_size = va.va_size;
}
}
if (space > rem)
space = rem;
npages = howmany(space + (off & PAGE_MASK), PAGE_SIZE);
/*
* Calculate maximum allowed number of pages for readahead
* at this iteration. First, we allow readahead up to "rem".
* If application wants more, let it be, but there is no
* reason to go above MAXPHYS. Also check against "obj_size",
* since vm_pager_has_page() can hint beyond EOF.
*/
rhpages = howmany(rem + (off & PAGE_MASK), PAGE_SIZE) - npages;
rhpages += SF_READAHEAD(flags);
rhpages = min(howmany(MAXPHYS, PAGE_SIZE), rhpages);
rhpages = min(howmany(obj_size - trunc_page(off), PAGE_SIZE) -
npages, rhpages);
sfio = malloc(sizeof(struct sf_io) +
npages * sizeof(vm_page_t), M_TEMP, M_WAITOK);
refcount_init(&sfio->nios, 1);
sfio->error = 0;
nios = sendfile_swapin(obj, sfio, off, space, npages, rhpages,
flags);
/*
* Loop and construct maximum sized mbuf chain to be bulk
* dumped into socket buffer.
*/
while (space > loopbytes) {
vm_offset_t pgoff;
pa = sfio->pa;
for (int i = 0; i < npages; i++) {
struct mbuf *m0;
/*
* Calculate the amount to transfer.
* Not to exceed a page, the EOF,
* or the passed in nbytes.
* If a page wasn't grabbed successfully, then
* trim the array. Can happen only with SF_NODISKIO.
*/
pgoff = (vm_offset_t)(off & PAGE_MASK);
rem = obj_size - offset;
if (nbytes != 0)
rem = omin(rem, nbytes);
rem -= fsbytes + loopbytes;
xfsize = omin(PAGE_SIZE - pgoff, rem);
xfsize = omin(space - loopbytes, xfsize);
if (xfsize <= 0) {
done = 1; /* all data sent */
break;
}
/*
* Attempt to look up the page. Allocate
* if not found or wait and loop if busy.
*/
if (m != NULL)
nd = EAGAIN; /* send what we already got */
else if ((flags & SF_NODISKIO) != 0)
nd = EBUSY;
else
nd = 0;
error = sendfile_readpage(obj, vp, nd, off,
xfsize, bsize, td, &pg);
if (error != 0) {
if (error == EAGAIN)
error = 0; /* not a real error */
if (pa[i] == NULL) {
SFSTAT_INC(sf_busy);
fixspace(npages, i, off, &space);
npages = i;
softerr = EBUSY;
break;
}
@ -2417,56 +2579,59 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
* threads might exhaust the buffers and then
* deadlock.
*/
sf = sf_buf_alloc(pg, (mnw || m != NULL) ? SFB_NOWAIT :
SFB_CATCH);
sf = sf_buf_alloc(pa[i],
m != NULL ? SFB_NOWAIT : SFB_CATCH);
if (sf == NULL) {
SFSTAT_INC(sf_allocfail);
vm_page_lock(pg);
vm_page_unwire(pg, PQ_INACTIVE);
KASSERT(pg->object != NULL,
("%s: object disappeared", __func__));
vm_page_unlock(pg);
for (int j = i; j < npages; j++) {
vm_page_lock(pa[j]);
vm_page_unwire(pa[j], PQ_INACTIVE);
vm_page_unlock(pa[j]);
}
if (m == NULL)
error = (mnw ? EAGAIN : EINTR);
softerr = ENOBUFS;
fixspace(npages, i, off, &space);
npages = i;
break;
}
/*
* Get an mbuf and set it up as having
* external storage.
*/
m0 = m_get((mnw ? M_NOWAIT : M_WAITOK), MT_DATA);
if (m0 == NULL) {
error = (mnw ? EAGAIN : ENOBUFS);
sf_ext_free(sf, NULL);
break;
}
/*
* Attach EXT_SFBUF external storage.
*/
m0->m_ext.ext_buf = (caddr_t )sf_buf_kva(sf);
m0 = m_get(M_WAITOK, MT_DATA);
m0->m_ext.ext_buf = (char *)sf_buf_kva(sf);
m0->m_ext.ext_size = PAGE_SIZE;
m0->m_ext.ext_arg1 = sf;
m0->m_ext.ext_arg2 = sfs;
m0->m_ext.ext_type = EXT_SFBUF;
/*
* SF_NOCACHE sets the page as being freed upon send.
* However, we ignore it for the last page in 'space',
* if the page is truncated, and we got more data to
* send (rem > space), or if we have readahead
* configured (rhpages > 0).
*/
if ((flags & SF_NOCACHE) == 0 ||
(i == npages - 1 &&
((off + space) & PAGE_MASK) &&
(rem > space || rhpages > 0)))
m0->m_ext.ext_type = EXT_SFBUF;
else
m0->m_ext.ext_type = EXT_SFBUF_NOCACHE;
m0->m_ext.ext_flags = 0;
m0->m_flags |= (M_EXT|M_RDONLY);
m0->m_data = (char *)sf_buf_kva(sf) + pgoff;
m0->m_len = xfsize;
m0->m_flags |= (M_EXT | M_RDONLY);
if (nios)
m0->m_flags |= M_NOTREADY;
m0->m_data = (char *)sf_buf_kva(sf) +
(vmoff(i, off) & PAGE_MASK);
m0->m_len = xfsize(i, npages, off, space);
if (i == 0)
sfio->m = m0;
/* Append to mbuf chain. */
if (mtail != NULL)
mtail->m_next = m0;
else if (m != NULL)
m_last(m)->m_next = m0;
else
m = m0;
mtail = m0;
/* Keep track of bits processed. */
loopbytes += xfsize;
off += xfsize;
if (sfs != NULL) {
mtx_lock(&sfs->mtx);
sfs->count++;
@ -2477,49 +2642,60 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
if (vp != NULL)
VOP_UNLOCK(vp, 0);
/* Add the buffer chain to the socket buffer. */
if (m != NULL) {
int mlen, err;
/* Keep track of bytes processed. */
off += space;
rem -= space;
mlen = m_length(m, NULL);
SOCKBUF_LOCK(&so->so_snd);
if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
error = EPIPE;
SOCKBUF_UNLOCK(&so->so_snd);
goto done;
}
SOCKBUF_UNLOCK(&so->so_snd);
CURVNET_SET(so->so_vnet);
/* Avoid error aliasing. */
err = (*so->so_proto->pr_usrreqs->pru_send)
(so, 0, m, NULL, NULL, td);
CURVNET_RESTORE();
if (err == 0) {
/*
* We need two counters to get the
* file offset and nbytes to send
* right:
* - sbytes contains the total amount
* of bytes sent, including headers.
* - fsbytes contains the total amount
* of bytes sent from the file.
*/
sbytes += mlen;
fsbytes += mlen;
if (hdrlen) {
fsbytes -= hdrlen;
hdrlen = 0;
}
} else if (error == 0)
error = err;
m = NULL; /* pru_send always consumes */
/* Prepend header, if any. */
if (hdrlen) {
mhtail->m_next = m;
m = mh;
mh = NULL;
}
/* Quit outer loop on error or when we're done. */
if (done)
break;
if (error != 0)
if (m == NULL) {
KASSERT(softerr, ("%s: m NULL, no error", __func__));
error = softerr;
free(sfio, M_TEMP);
goto done;
}
/* Add the buffer chain to the socket buffer. */
KASSERT(m_length(m, NULL) == space + hdrlen,
("%s: mlen %u space %d hdrlen %d",
__func__, m_length(m, NULL), space, hdrlen));
CURVNET_SET(so->so_vnet);
if (nios == 0) {
/*
* If sendfile_swapin() didn't initiate any I/Os,
* which happens if all data is cached in VM, then
* we can send data right now without the
* PRUS_NOTREADY flag.
*/
free(sfio, M_TEMP);
error = (*so->so_proto->pr_usrreqs->pru_send)
(so, 0, m, NULL, NULL, td);
} else {
sfio->sock_fp = sock_fp;
sfio->npages = npages;
fhold(sock_fp);
error = (*so->so_proto->pr_usrreqs->pru_send)
(so, PRUS_NOTREADY, m, NULL, NULL, td);
sf_iodone(sfio, NULL, 0, 0);
}
CURVNET_RESTORE();
m = NULL; /* pru_send always consumes */
if (error)
goto done;
sbytes += space + hdrlen;
if (hdrlen)
hdrlen = 0;
if (softerr) {
error = softerr;
goto done;
}
}
/*
@ -2552,6 +2728,8 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
fdrop(sock_fp, td);
if (m)
m_freem(m);
if (mh)
m_freem(mh);
if (sfs != NULL) {
mtx_lock(&sfs->mtx);

View File

@ -981,7 +981,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
control))
control = NULL;
} else
sbappend_locked(&so2->so_rcv, m);
sbappend_locked(&so2->so_rcv, m, flags);
break;
case SOCK_SEQPACKET: {

View File

@ -81,6 +81,7 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
static Elf64_Brandinfo freebsd_brand_info = {
@ -135,6 +136,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
static Elf32_Brandinfo freebsd_brand_info = {

View File

@ -104,6 +104,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_syscallnames = freebsd32_syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);

View File

@ -113,9 +113,8 @@ arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
error = 0;
#if defined(INET) || defined(INET6)
if (ro != NULL && ro->ro_rt != NULL &&
(ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
is_gw = 1;
if (ro != NULL)
is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#endif
switch (dst->sa_family) {

View File

@ -202,7 +202,6 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m,
uint32_t *pflags)
{
struct ether_header *eh;
struct rtentry *rt;
uint32_t lleflags = 0;
int error = 0;
#if defined(INET) || defined(INET6)
@ -253,8 +252,7 @@ ether_resolve_addr(struct ifnet *ifp, struct mbuf *m,
}
if (error == EHOSTDOWN) {
rt = (ro != NULL) ? ro->ro_rt : NULL;
if (rt != NULL && (rt->rt_flags & RTF_GATEWAY) != 0)
if (ro != NULL && (ro->ro_flags & RT_HAS_GW) != 0)
error = EHOSTUNREACH;
}

View File

@ -119,9 +119,8 @@ fddi_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
getmicrotime(&ifp->if_lastchange);
#if defined(INET) || defined(INET6)
if (ro != NULL && ro->ro_rt != NULL &&
(ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
is_gw = 1;
if (ro != NULL)
is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#endif
switch (dst->sa_family) {

View File

@ -106,9 +106,8 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
}
#if defined(INET) || defined(INET6)
if (ro != NULL && ro->ro_rt != NULL &&
(ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
is_gw = 1;
if (ro != NULL)
is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#endif
/*
* For unicast, we make a tag to store the lladdr of the
@ -145,10 +144,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
* doesn't fit into the arp model.
*/
if (unicast) {
is_gw = 0;
if (ro != NULL && ro->ro_rt != NULL &&
(ro->ro_rt->rt_flags & RTF_GATEWAY) != 0)
is_gw = 1;
error = arpresolve(ifp, is_gw, m, dst, (u_char *) destfw, NULL);
if (error)
return (error == EWOULDBLOCK ? 0 : error);

View File

@ -214,12 +214,8 @@ iso88025_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
struct rtentry *rt0 = NULL;
int is_gw = 0;
if (ro != NULL) {
rt0 = ro->ro_rt;
if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0)
is_gw = 1;
}
if (ro != NULL)
is_gw = (ro->ro_flags & RT_HAS_GW) != 0;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error)

View File

@ -202,15 +202,12 @@ looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
struct route *ro)
{
u_int32_t af;
struct rtentry *rt = NULL;
#ifdef MAC
int error;
#endif
M_ASSERTPKTHDR(m); /* check if we have the packet header */
if (ro != NULL)
rt = ro->ro_rt;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error) {
@ -219,10 +216,9 @@ looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
}
#endif
if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
if (ro != NULL && ro->ro_flags & (RT_REJECT|RT_BLACKHOLE)) {
m_freem(m);
return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
return (ro->ro_flags & RT_BLACKHOLE ? 0 : EHOSTUNREACH);
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);

View File

@ -197,14 +197,49 @@ rt_mpath_conflict(struct radix_node_head *rnh, struct rtentry *rt,
return (0);
}
void
rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
static struct rtentry *
rt_mpath_selectrte(struct rtentry *rte, uint32_t hash)
{
struct radix_node *rn0, *rn;
u_int32_t n;
struct rtentry *rt;
int64_t weight;
/* beyond here, we use rn as the master copy */
rn0 = rn = (struct radix_node *)rte;
n = rn_mpath_count(rn0);
/* gw selection by Modulo-N Hash (RFC2991) XXX need improvement? */
hash += hashjitter;
hash %= n;
for (weight = abs((int32_t)hash), rt = rte;
weight >= rt->rt_weight && rn;
weight -= rt->rt_weight) {
/* stay within the multipath routes */
if (rn->rn_dupedkey && rn->rn_mask != rn->rn_dupedkey->rn_mask)
break;
rn = rn->rn_dupedkey;
rt = (struct rtentry *)rn;
}
return (rt);
}
struct rtentry *
rt_mpath_select(struct rtentry *rte, uint32_t hash)
{
if (rn_mpath_next((struct radix_node *)rte) == NULL)
return (rte);
return (rt_mpath_selectrte(rte, hash));
}
void
rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
{
struct rtentry *rt;
/*
* XXX we don't attempt to lookup cached route again; what should
* be done for sendto(3) case?
@ -222,34 +257,18 @@ rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
return;
}
/* beyond here, we use rn as the master copy */
rn0 = rn = (struct radix_node *)ro->ro_rt;
n = rn_mpath_count(rn0);
/* gw selection by Modulo-N Hash (RFC2991) XXX need improvement? */
hash += hashjitter;
hash %= n;
for (weight = abs((int32_t)hash), rt = ro->ro_rt;
weight >= rt->rt_weight && rn;
weight -= rt->rt_weight) {
/* stay within the multipath routes */
if (rn->rn_dupedkey && rn->rn_mask != rn->rn_dupedkey->rn_mask)
break;
rn = rn->rn_dupedkey;
rt = (struct rtentry *)rn;
}
rt = rt_mpath_selectrte(ro->ro_rt, hash);
/* XXX try filling rt_gwroute and avoid unreachable gw */
/* gw selection has failed - there must be only zero weight routes */
if (!rn) {
if (!rt) {
RT_UNLOCK(ro->ro_rt);
ro->ro_rt = NULL;
return;
}
if (ro->ro_rt != rt) {
RTFREE_LOCKED(ro->ro_rt);
ro->ro_rt = (struct rtentry *)rn;
ro->ro_rt = rt;
RT_LOCK(ro->ro_rt);
RT_ADDREF(ro->ro_rt);

View File

@ -52,6 +52,7 @@ int rt_mpath_conflict(struct radix_node_head *, struct rtentry *,
struct sockaddr *);
void rtalloc_mpath_fib(struct route *, u_int32_t, u_int);
#define rtalloc_mpath(_route, _hash) rtalloc_mpath_fib((_route), (_hash), 0)
struct rtentry *rt_mpath_select(struct rtentry *, uint32_t);
struct radix_node *rn_mpath_lookup(void *, void *,
struct radix_node_head *);
int rt_mpath_deldup(struct rtentry *, struct rtentry *);

View File

@ -568,7 +568,7 @@ rtredirect_fib(struct sockaddr *dst,
struct sockaddr *src,
u_int fibnum)
{
struct rtentry *rt, *rt0 = NULL;
struct rtentry *rt;
int error = 0;
short *stat = NULL;
struct rt_addrinfo info;
@ -627,7 +627,7 @@ rtredirect_fib(struct sockaddr *dst,
* Create new route, rather than smashing route to net.
*/
create:
rt0 = rt;
RTFREE(rt);
rt = NULL;
flags |= RTF_DYNAMIC;
@ -637,21 +637,14 @@ rtredirect_fib(struct sockaddr *dst,
info.rti_info[RTAX_NETMASK] = netmask;
info.rti_ifa = ifa;
info.rti_flags = flags;
if (rt0 != NULL)
RT_UNLOCK(rt0); /* drop lock to avoid LOR with RNH */
error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum);
if (rt != NULL) {
RT_LOCK(rt);
if (rt0 != NULL)
EVENTHANDLER_INVOKE(route_redirect_event, rt0, rt, dst);
flags = rt->rt_flags;
}
if (rt0 != NULL)
RTFREE(rt0);
stat = &V_rtstat.rts_dynamic;
} else {
struct rtentry *gwrt;
/*
* Smash the current notion of the gateway to
@ -669,11 +662,7 @@ rtredirect_fib(struct sockaddr *dst,
RADIX_NODE_HEAD_LOCK(rnh);
RT_LOCK(rt);
rt_setgate(rt, rt_key(rt), gateway);
gwrt = rtalloc1(gateway, 1, RTF_RNH_LOCKED);
RADIX_NODE_HEAD_UNLOCK(rnh);
EVENTHANDLER_INVOKE(route_redirect_event, rt, gwrt, dst);
if (gwrt)
RTFREE_LOCKED(gwrt);
}
} else
error = EHOSTUNREACH;
@ -858,7 +847,7 @@ rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info, int flags)
src = rt_key(rt);
dst = info->rti_info[RTAX_DST];
sa_len = src->sa_len;
if (src != NULL && dst != NULL) {
if (dst != NULL) {
if (src->sa_len > dst->sa_len)
return (ENOMEM);
memcpy(dst, src, src->sa_len);

View File

@ -64,9 +64,13 @@ struct route {
#define RT_CACHING_CONTEXT 0x1 /* XXX: not used anywhere */
#define RT_NORTREF 0x2 /* doesn't hold reference on ro_rt */
#define RT_L2_ME (1 << RT_L2_ME_BIT)
#define RT_MAY_LOOP (1 << RT_MAY_LOOP_BIT)
#define RT_HAS_HEADER (1 << RT_HAS_HEADER_BIT)
#define RT_L2_ME (1 << RT_L2_ME_BIT) /* 0x0004 */
#define RT_MAY_LOOP (1 << RT_MAY_LOOP_BIT) /* 0x0008 */
#define RT_HAS_HEADER (1 << RT_HAS_HEADER_BIT) /* 0x0010 */
#define RT_REJECT 0x0020 /* Destination is reject */
#define RT_BLACKHOLE 0x0040 /* Destination is blackhole */
#define RT_HAS_GW 0x0080 /* Destination has GW */
struct rt_metrics {
u_long rmx_locks; /* Kernel must leave these values alone */
@ -215,6 +219,21 @@ fib_rte_to_nh_flags(int rt_flags)
return (res);
}
#ifdef _KERNEL
/* rte<>ro_flags translation */
static inline void
rt_update_ro_flags(struct route *ro)
{
int rt_flags = ro->ro_rt->rt_flags;
ro->ro_flags &= ~ (RT_REJECT|RT_BLACKHOLE|RT_HAS_GW);
ro->ro_flags |= (rt_flags & RTF_REJECT) ? RT_REJECT : 0;
ro->ro_flags |= (rt_flags & RTF_BLACKHOLE) ? RT_BLACKHOLE : 0;
ro->ro_flags |= (rt_flags & RTF_GATEWAY) ? RT_HAS_GW : 0;
}
#endif
/*
* Routing statistics.
*/
@ -467,9 +486,6 @@ int rib_lookup_info(uint32_t, const struct sockaddr *, uint32_t, uint32_t,
struct rt_addrinfo *);
void rib_free_info(struct rt_addrinfo *info);
#include <sys/eventhandler.h>
typedef void (*rtevent_redirect_fn)(void *, struct rtentry *, struct rtentry *, struct sockaddr *);
EVENTHANDLER_DECLARE(route_redirect_event, rtevent_redirect_fn);
#endif
#endif

View File

@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/eventhandler.h>
#include <sys/linker.h>
#include <sys/mbuf.h>
#include <sys/module.h>

View File

@ -972,7 +972,7 @@ ng_btsocket_rfcomm_send(struct socket *so, int flags, struct mbuf *m,
}
/* Put the packet on the socket's send queue and wakeup RFCOMM task */
sbappend(&pcb->so->so_snd, m);
sbappend(&pcb->so->so_snd, m, flags);
m = NULL;
if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_SENDING)) {
@ -2396,7 +2396,7 @@ ng_btsocket_rfcomm_receive_uih(ng_btsocket_rfcomm_session_p s, int dlci,
error = ENOBUFS;
} else {
/* Append packet to the socket receive queue */
sbappend(&pcb->so->so_rcv, m0);
sbappend(&pcb->so->so_rcv, m0, 0);
m0 = NULL;
sorwakeup(pcb->so);

View File

@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/counter.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/limits.h>
#include <sys/mbuf.h>
#include <sys/syslog.h>

View File

@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/counter.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/limits.h>
#include <sys/mbuf.h>
#include <sys/syslog.h>

View File

@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/counter.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/limits.h>
#include <sys/mbuf.h>
#include <sys/socket.h>

View File

@ -200,6 +200,13 @@ fib4_lookup_nh_ext(uint32_t fibnum, struct in_addr dst, uint32_t flags,
rn = rh->rnh_matchaddr((void *)&sin, rh);
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
rte = RNTORT(rn);
#ifdef RADIX_MPATH
rte = rt_mpath_select(rte, flowid);
if (rte == NULL) {
RADIX_NODE_HEAD_RUNLOCK(rh);
return (ENOENT);
}
#endif
/* Ensure route & ifp is UP */
if (RT_LINK_IS_UP(rte->rt_ifp)) {
fib4_rte_to_nh_extended(rte, dst, flags, pnh4);

View File

@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/callout.h>
#include <sys/eventhandler.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/rmlock.h>

View File

@ -65,6 +65,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>

View File

@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/stddef.h>
#include <sys/eventhandler.h>
#include <sys/lock.h>
#include <sys/ktr.h>
#include <sys/malloc.h>

View File

@ -376,6 +376,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
ia = ifatoia(rte->rt_ifa);
ifp = rte->rt_ifp;
counter_u64_add(rte->rt_pksent, 1);
rt_update_ro_flags(ro);
if (rte->rt_flags & RTF_GATEWAY)
gw = (struct sockaddr_in *)rte->rt_gateway;
if (rte->rt_flags & RTF_HOST)

View File

@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/eventhandler.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>

View File

@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/eventhandler.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>

View File

@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/callout.h>
#include <sys/eventhandler.h>
#include <sys/hhook.h>
#include <sys/kernel.h>
#include <sys/khelp.h>

View File

@ -70,7 +70,6 @@ static TAILQ_HEAD(, toedev) toedev_list;
static eventhandler_tag listen_start_eh;
static eventhandler_tag listen_stop_eh;
static eventhandler_tag lle_event_eh;
static eventhandler_tag route_redirect_eh;
static int
toedev_connect(struct toedev *tod __unused, struct socket *so __unused,
@ -437,17 +436,6 @@ toe_lle_event(void *arg __unused, struct llentry *lle, int evt)
tod->tod_l2_update(tod, ifp, sa, lladdr, vtag);
}
/*
* XXX: implement.
*/
static void
toe_route_redirect_event(void *arg __unused, struct rtentry *rt0,
struct rtentry *rt1, struct sockaddr *sa)
{
return;
}
/*
* Returns 0 or EWOULDBLOCK on success (any other value is an error). 0 means
* lladdr and vtag are valid on return, EWOULDBLOCK means the TOE driver's
@ -534,8 +522,6 @@ toecore_load(void)
toe_listen_stop_event, NULL, EVENTHANDLER_PRI_ANY);
lle_event_eh = EVENTHANDLER_REGISTER(lle_event, toe_lle_event, NULL,
EVENTHANDLER_PRI_ANY);
route_redirect_eh = EVENTHANDLER_REGISTER(route_redirect_event,
toe_route_redirect_event, NULL, EVENTHANDLER_PRI_ANY);
return (0);
}
@ -553,7 +539,6 @@ toecore_unload(void)
EVENTHANDLER_DEREGISTER(tcp_offload_listen_start, listen_start_eh);
EVENTHANDLER_DEREGISTER(tcp_offload_listen_stop, listen_stop_eh);
EVENTHANDLER_DEREGISTER(lle_event, lle_event_eh);
EVENTHANDLER_DEREGISTER(route_redirect_event, route_redirect_eh);
mtx_unlock(&toedev_lock);
mtx_destroy(&toedev_lock);

View File

@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/eventhandler.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/errno.h>

View File

@ -2114,13 +2114,13 @@ icmp6_rip6_input(struct mbuf **mp, int off)
void
icmp6_reflect(struct mbuf *m, size_t off)
{
struct in6_addr src, *srcp = NULL;
struct in6_addr src6, *srcp;
struct ip6_hdr *ip6;
struct icmp6_hdr *icmp6;
struct in6_ifaddr *ia = NULL;
struct ifnet *outif = NULL;
int plen;
int type, code;
int type, code, hlim;
/* too short to reflect */
if (off < sizeof(struct ip6_hdr)) {
@ -2166,6 +2166,8 @@ icmp6_reflect(struct mbuf *m, size_t off)
icmp6 = (struct icmp6_hdr *)(ip6 + 1);
type = icmp6->icmp6_type; /* keep type for statistics */
code = icmp6->icmp6_code; /* ditto. */
hlim = 0;
srcp = NULL;
/*
* If the incoming packet was addressed directly to us (i.e. unicast),
@ -2177,34 +2179,43 @@ icmp6_reflect(struct mbuf *m, size_t off)
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
ia = in6ifa_ifwithaddr(&ip6->ip6_dst, 0 /* XXX */);
if (ia != NULL && !(ia->ia6_flags &
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)))
srcp = &ia->ia_addr.sin6_addr;
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
src6 = ia->ia_addr.sin6_addr;
srcp = &src6;
if (m->m_pkthdr.rcvif != NULL) {
/* XXX: This may not be the outgoing interface */
hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
} else
hlim = V_ip6_defhlim;
}
if (ia != NULL)
ifa_free(&ia->ia_ifa);
}
if (srcp == NULL) {
int e;
struct sockaddr_in6 sin6;
int error;
struct in6_addr dst6;
uint32_t scopeid;
/*
* This case matches to multicasts, our anycast, or unicasts
* that we do not own. Select a source address based on the
* source address of the erroneous packet.
*/
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */
in6_splitscope(&ip6->ip6_dst, &dst6, &scopeid);
error = in6_selectsrc_addr(RT_DEFAULT_FIB, &dst6,
scopeid, NULL, &src6, &hlim);
e = in6_selectsrc(&sin6, NULL, NULL, NULL, &outif, &src);
if (e) {
if (error) {
char ip6buf[INET6_ADDRSTRLEN];
nd6log((LOG_DEBUG,
"icmp6_reflect: source can't be determined: "
"dst=%s, error=%d\n",
ip6_sprintf(ip6buf, &sin6.sin6_addr), e));
ip6_sprintf(ip6buf, &ip6->ip6_dst), error));
goto bad;
}
srcp = &src;
srcp = &src6;
}
/*
* ip6_input() drops a packet if its src is multicast.
@ -2216,13 +2227,7 @@ icmp6_reflect(struct mbuf *m, size_t off)
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
ip6->ip6_nxt = IPPROTO_ICMPV6;
if (outif)
ip6->ip6_hlim = ND_IFINFO(outif)->chlim;
else if (m->m_pkthdr.rcvif) {
/* XXX: This may not be the outgoing interface */
ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
} else
ip6->ip6_hlim = V_ip6_defhlim;
ip6->ip6_hlim = hlim;
icmp6->icmp6_cksum = 0;
icmp6->icmp6_cksum = in6_cksum(m, IPPROTO_ICMPV6,
@ -2238,13 +2243,9 @@ icmp6_reflect(struct mbuf *m, size_t off)
if (outif)
icmp6_ifoutstat_inc(outif, type, code);
if (ia != NULL)
ifa_free(&ia->ia_ifa);
return;
bad:
if (ia != NULL)
ifa_free(&ia->ia_ifa);
m_freem(m);
return;
}

View File

@ -241,6 +241,13 @@ fib6_lookup_nh_ext(uint32_t fibnum, const struct in6_addr *dst,uint32_t scopeid,
rn = rh->rnh_matchaddr((void *)&sin6, rh);
if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
rte = RNTORT(rn);
#ifdef RADIX_MPATH
rte = rt_mpath_select(rte, flowid);
if (rte == NULL) {
RADIX_NODE_HEAD_RUNLOCK(rh);
return (ENOENT);
}
#endif
/* Ensure route & ifp is UP */
if (RT_LINK_IS_UP(rte->rt_ifp)) {
fib6_rte_to_nh_extended(rte, &sin6.sin6_addr, flags,

View File

@ -328,7 +328,6 @@ in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
{
register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
int error = 0;
struct ifnet *ifp = NULL;
int scope_ambiguous = 0;
struct in6_addr in6a;
@ -358,20 +357,15 @@ in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
return (error);
error = in6_selectsrc(sin6, inp->in6p_outputopts,
inp, inp->inp_cred, &ifp, &in6a);
error = in6_selectsrc_socket(sin6, inp->in6p_outputopts,
inp, inp->inp_cred, scope_ambiguous, &in6a, NULL);
if (error)
return (error);
if (ifp && scope_ambiguous &&
(error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) {
return(error);
}
/*
* Do not update this earlier, in case we return with an error.
*
* XXX: this in6_selectsrc result might replace the bound local
* XXX: this in6_selectsrc_socket result might replace the bound local
* address with the address specified by setsockopt(IPV6_PKTINFO).
* Is it the intended behavior?
*/

View File

@ -107,7 +107,6 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
{
struct rtentry *rt = (struct rtentry *)treenodes;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt);
struct radix_node *ret;
RADIX_NODE_HEAD_WLOCK_ASSERT(head);
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
@ -148,34 +147,7 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
rt->rt_mtu = IN6_LINKMTU(rt->rt_ifp);
}
ret = rn_addroute(v_arg, n_arg, head, treenodes);
if (ret == NULL) {
struct rtentry *rt2;
/*
* We are trying to add a net route, but can't.
* The following case should be allowed, so we'll make a
* special check for this:
* Two IPv6 addresses with the same prefix is assigned
* to a single interrface.
* # ifconfig if0 inet6 3ffe:0501::1 prefix 64 alias (*1)
* # ifconfig if0 inet6 3ffe:0501::2 prefix 64 alias (*2)
* In this case, (*1) and (*2) want to add the same
* net route entry, 3ffe:0501:: -> if0.
* This case should not raise an error.
*/
rt2 = in6_rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED,
rt->rt_fibnum);
if (rt2) {
if (((rt2->rt_flags & (RTF_HOST|RTF_GATEWAY)) == 0)
&& rt2->rt_gateway
&& rt2->rt_gateway->sa_family == AF_LINK
&& rt2->rt_ifp == rt->rt_ifp) {
ret = rt2->rt_nodes;
}
RTFREE_LOCKED(rt2);
}
}
return (ret);
return (rn_addroute(v_arg, n_arg, head, treenodes));
}
/*

View File

@ -136,6 +136,9 @@ static int selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
static int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct ifnet **,
struct ifnet *, u_int);
static int in6_selectsrc(uint32_t, struct sockaddr_in6 *,
struct ip6_pktopts *, struct inpcb *, struct ucred *,
struct ifnet **, struct in6_addr *);
static struct in6_addrpolicy *lookup_addrsel_policy(struct sockaddr_in6 *);
@ -175,9 +178,9 @@ static struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *);
goto out; /* XXX: we can't use 'break' here */ \
} while(0)
int
in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct inpcb *inp, struct ucred *cred,
static int
in6_selectsrc(uint32_t fibnum, struct sockaddr_in6 *dstsock,
struct ip6_pktopts *opts, struct inpcb *inp, struct ucred *cred,
struct ifnet **ifpp, struct in6_addr *srcp)
{
struct rm_priotracker in6_ifa_tracker;
@ -228,7 +231,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
/* get the outgoing interface */
if ((error = in6_selectif(dstsock, opts, mopts, &ifp, oifp,
(inp != NULL) ? inp->inp_inc.inc_fibnum : RT_DEFAULT_FIB))
fibnum))
!= 0)
return (error);
@ -544,6 +547,79 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
return (0);
}
/*
* Select source address based on @inp, @dstsock and @opts.
* Stores selected address to @srcp. If @scope_ambiguous is set,
* embed scope from selected outgoing interface. If @hlim pointer
* is provided, stores calculated hop limit there.
* Returns 0 on success.
*/
int
in6_selectsrc_socket(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct inpcb *inp, struct ucred *cred, int scope_ambiguous,
struct in6_addr *srcp, int *hlim)
{
struct ifnet *retifp;
uint32_t fibnum;
int error;
fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : RT_DEFAULT_FIB;
retifp = NULL;
error = in6_selectsrc(fibnum, dstsock, opts, inp, cred, &retifp, srcp);
if (error != 0)
return (error);
if (hlim != NULL)
*hlim = in6_selecthlim(inp, retifp);
if (retifp == NULL || scope_ambiguous == 0)
return (0);
/*
* Application should provide a proper zone ID or the use of
* default zone IDs should be enabled. Unfortunately, some
* applications do not behave as it should, so we need a
* workaround. Even if an appropriate ID is not determined
* (when it's required), if we can determine the outgoing
* interface. determine the zone ID based on the interface.
*/
error = in6_setscope(&dstsock->sin6_addr, retifp, NULL);
return (error);
}
/*
* Select source address based on @fibnum, @dst and @scopeid.
* Stores selected address to @srcp.
* Returns 0 on success.
*
* Used by non-socket based consumers (ND code mostly)
*/
int
in6_selectsrc_addr(uint32_t fibnum, const struct in6_addr *dst,
uint32_t scopeid, struct ifnet *ifp, struct in6_addr *srcp,
int *hlim)
{
struct ifnet *retifp;
struct sockaddr_in6 dst_sa;
int error;
retifp = ifp;
bzero(&dst_sa, sizeof(dst_sa));
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = *dst;
dst_sa.sin6_scope_id = scopeid;
sa6_embedscope(&dst_sa, 0);
error = in6_selectsrc(fibnum, &dst_sa, NULL, NULL, NULL, &retifp, srcp);
if (hlim != NULL)
*hlim = in6_selecthlim(NULL, retifp);
return (error);
}
/*
* clone - meaningful only for bsdi and freebsd
*/

View File

@ -418,9 +418,10 @@ int rip6_usrreq(struct socket *,
int dest6_input(struct mbuf **, int *, int);
int none_input(struct mbuf **, int *, int);
int in6_selectsrc(struct sockaddr_in6 *, struct ip6_pktopts *,
struct inpcb *inp, struct ucred *cred,
struct ifnet **, struct in6_addr *);
int in6_selectsrc_socket(struct sockaddr_in6 *, struct ip6_pktopts *,
struct inpcb *, struct ucred *, int, struct in6_addr *, int *);
int in6_selectsrc_addr(uint32_t, const struct in6_addr *,
uint32_t, struct ifnet *, struct in6_addr *, int *);
int in6_selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
struct rtentry **);

View File

@ -481,27 +481,21 @@ nd6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *saddr6,
ifa_free(ifa);
} else {
int error;
struct sockaddr_in6 dst_sa;
struct in6_addr src_in;
struct ifnet *oifp;
struct in6_addr dst6, src6;
uint32_t scopeid;
bzero(&dst_sa, sizeof(dst_sa));
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = ip6->ip6_dst;
oifp = ifp;
error = in6_selectsrc(&dst_sa, NULL,
NULL, NULL, &oifp, &src_in);
in6_splitscope(&ip6->ip6_dst, &dst6, &scopeid);
error = in6_selectsrc_addr(RT_DEFAULT_FIB, &dst6,
scopeid, ifp, &src6, NULL);
if (error) {
char ip6buf[INET6_ADDRSTRLEN];
nd6log((LOG_DEBUG, "%s: source can't be "
"determined: dst=%s, error=%d\n", __func__,
ip6_sprintf(ip6buf, &dst_sa.sin6_addr),
ip6_sprintf(ip6buf, &dst6),
error));
goto bad;
}
ip6->ip6_src = src_in;
ip6->ip6_src = src6;
}
} else {
/*
@ -941,12 +935,12 @@ nd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
{
struct mbuf *m;
struct m_tag *mtag;
struct ifnet *oifp;
struct ip6_hdr *ip6;
struct nd_neighbor_advert *nd_na;
struct ip6_moptions im6o;
struct in6_addr src, daddr6;
struct sockaddr_in6 dst_sa;
struct in6_addr daddr6, dst6, src6;
uint32_t scopeid;
int icmp6len, maxlen, error;
caddr_t mac = NULL;
@ -998,24 +992,21 @@ nd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
flags &= ~ND_NA_FLAG_SOLICITED;
}
ip6->ip6_dst = daddr6;
bzero(&dst_sa, sizeof(struct sockaddr_in6));
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(struct sockaddr_in6);
dst_sa.sin6_addr = daddr6;
/*
* Select a source whose scope is the same as that of the dest.
*/
oifp = ifp;
error = in6_selectsrc(&dst_sa, NULL, NULL, NULL, &oifp, &src);
in6_splitscope(&daddr6, &dst6, &scopeid);
error = in6_selectsrc_addr(RT_DEFAULT_FIB, &dst6,
scopeid, ifp, &src6, NULL);
if (error) {
char ip6buf[INET6_ADDRSTRLEN];
nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
"determined: dst=%s, error=%d\n",
ip6_sprintf(ip6buf, &dst_sa.sin6_addr), error));
ip6_sprintf(ip6buf, &daddr6), error));
goto bad;
}
ip6->ip6_src = src;
ip6->ip6_src = src6;
nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
nd_na->nd_na_code = 0;

View File

@ -397,6 +397,7 @@ rip6_output(struct mbuf *m, struct socket *so, ...)
int type = 0, code = 0; /* for ICMPv6 output statistics only */
int scope_ambiguous = 0;
int use_defzone = 0;
int hlim = 0;
struct in6_addr in6a;
va_list ap;
@ -460,8 +461,9 @@ rip6_output(struct mbuf *m, struct socket *so, ...)
/*
* Source address selection.
*/
error = in6_selectsrc(dstsock, optp, in6p, so->so_cred,
&oifp, &in6a);
error = in6_selectsrc_socket(dstsock, optp, in6p, so->so_cred,
scope_ambiguous, &in6a, &hlim);
if (error)
goto bad;
error = prison_check_ip6(in6p->inp_cred, &in6a);
@ -469,19 +471,6 @@ rip6_output(struct mbuf *m, struct socket *so, ...)
goto bad;
ip6->ip6_src = in6a;
if (oifp && scope_ambiguous) {
/*
* Application should provide a proper zone ID or the use of
* default zone IDs should be enabled. Unfortunately, some
* applications do not behave as it should, so we need a
* workaround. Even if an appropriate ID is not determined
* (when it's required), if we can determine the outgoing
* interface. determine the zone ID based on the interface.
*/
error = in6_setscope(&dstsock->sin6_addr, oifp, NULL);
if (error != 0)
goto bad;
}
ip6->ip6_dst = dstsock->sin6_addr;
/*
@ -496,7 +485,7 @@ rip6_output(struct mbuf *m, struct socket *so, ...)
* ip6_plen will be filled in ip6_output, so not fill it here.
*/
ip6->ip6_nxt = in6p->inp_ip_p;
ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
ip6->ip6_hlim = hlim;
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
in6p->in6p_cksum != -1) {
@ -784,7 +773,6 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
struct inpcb *inp;
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
struct in6_addr in6a;
struct ifnet *ifp = NULL;
int error = 0, scope_ambiguous = 0;
inp = sotoinpcb(so);
@ -813,21 +801,14 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
INP_INFO_WLOCK(&V_ripcbinfo);
INP_WLOCK(inp);
/* Source address selection. XXX: need pcblookup? */
error = in6_selectsrc(addr, inp->in6p_outputopts,
inp, so->so_cred, &ifp, &in6a);
error = in6_selectsrc_socket(addr, inp->in6p_outputopts,
inp, so->so_cred, scope_ambiguous, &in6a, NULL);
if (error) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
return (error);
}
/* XXX: see above */
if (ifp && scope_ambiguous &&
(error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
return (error);
}
inp->in6p_faddr = addr->sin6_addr;
inp->in6p_laddr = in6a;
soisconnected(so);

View File

@ -631,7 +631,6 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
struct udphdr *udp6;
struct in6_addr *laddr, *faddr, in6a;
struct sockaddr_in6 *sin6 = NULL;
struct ifnet *oifp = NULL;
int cscov_partial = 0;
int scope_ambiguous = 0;
u_short fport;
@ -731,15 +730,10 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
}
if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
error = in6_selectsrc(sin6, optp, inp,
td->td_ucred, &oifp, &in6a);
error = in6_selectsrc_socket(sin6, optp, inp,
td->td_ucred, scope_ambiguous, &in6a, NULL);
if (error)
goto release;
if (oifp && scope_ambiguous &&
(error = in6_setscope(&sin6->sin6_addr,
oifp, NULL))) {
goto release;
}
laddr = &in6a;
} else
laddr = &inp->in6p_laddr; /* XXX */

View File

@ -2097,7 +2097,7 @@ export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
i->count = table_get_count(ch, tc);
i->limit = tc->limit;
i->flags |= (tc->locked != 0) ? IPFW_TGFLAGS_LOCKED : 0;
i->size = tc->count * sizeof(ipfw_obj_tentry);
i->size = i->count * sizeof(ipfw_obj_tentry);
i->size += sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
strlcpy(i->tablename, tc->tablename, sizeof(i->tablename));
ti = KIDX_TO_TI(ch, tc->no.kidx);

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