1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00

Merging ^/head r278298 through r278350.

This commit is contained in:
Dimitry Andric 2015-02-07 12:57:40 +00:00
commit b40d827331
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang360-import/; revision=278351
72 changed files with 2240 additions and 328 deletions

View File

@ -41,6 +41,7 @@ LINE("libcrypt", "Crypt Library (libcrypt, \\-lcrypt)")
LINE("libcurses", "Curses Library (libcurses, \\-lcurses)")
LINE("libcuse", "Userland Character Device Library (libcuse, \\-lcuse)")
LINE("libdevattr", "Device attribute and event library (libdevattr, \\-ldevattr)")
LINE("libdevctl", "Device Control Library (libdevctl, \\-ldevctl)")
LINE("libdevinfo", "Device and Resource Information Utility Library (libdevinfo, \\-ldevinfo)")
LINE("libdevstat", "Device Statistics Library (libdevstat, \\-ldevstat)")
LINE("libdisk", "Interface to Slice and Partition Labels Library (libdisk, \\-ldisk)")

View File

@ -28,7 +28,7 @@ extra_commands="config console status"
need_dad_wait=
# extact_var jail name param num defval
# extract_var jail name param num defval
# Extract value from ${jail_$jail_$name} or ${jail_$name} and
# set it to $param. If not defined, $defval is used.
# When $num is [0-9]*, ${jail_$jail_$name$num} are looked up and

View File

@ -165,13 +165,14 @@ static_inet()
static_inet6()
{
local _action _if _skip fibmod fibs
local _action _if _skip fibmod fibs allfibs
_action=$1
_if=$2
# get the number of FIBs supported.
fibs=$((`${SYSCTL_N} net.fibs` - 1))
if [ "$fibs" -gt 0 ]; then
allfibs=`${SYSCTL_N} net.add_addr_allfibs`
if [ "$fibs" -gt 0 ] && [ "$allfibs" -ne 0 ]; then
fibmod="-fib 0-$fibs"
else
fibmod=

View File

@ -41,6 +41,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_libcom_err} \
libcompat \
libcrypt \
libdevctl \
libdevinfo \
libdevstat \
libdpv \

View File

@ -9,6 +9,10 @@ CFLAGS+= -I${.CURDIR}/../common \
-I${.CURDIR}/../../libc/include \
-mlongcall
# XXX: See the log for r232932 as to why the above -mlongcall is needed. Since
# clang doesn't support -mlongcall, and testing shows a clang linked with a
# clang-built csu segfaults, this must currently be compiled with gcc. Once
# clang supports -mlongcall, or we get a fixed ld, this can be revisited.
CC:= gcc
COMPILER_TYPE:= gcc

View File

@ -85,10 +85,13 @@ getdiskbyname(const char *name)
cq++, cp++;
*cq = '\0';
if (cgetstr(buf, "ty", &cq) > 0 && strcmp(cq, "removable") == 0)
dp->d_flags |= D_REMOVABLE;
else if (cq && strcmp(cq, "simulated") == 0)
dp->d_flags |= D_RAMDISK;
if (cgetstr(buf, "ty", &cq) > 0) {
if (strcmp(cq, "removable") == 0)
dp->d_flags |= D_REMOVABLE;
else if (cq && strcmp(cq, "simulated") == 0)
dp->d_flags |= D_RAMDISK;
free(cq);
}
if (cgetcap(buf, "sf", ':') != NULL)
dp->d_flags |= D_BADSECT;
@ -100,9 +103,10 @@ getdiskbyname(const char *name)
getnumdflt(dp->d_nsectors, "ns", 0);
getnumdflt(dp->d_ncylinders, "nc", 0);
if (cgetstr(buf, "dt", &cq) > 0)
if (cgetstr(buf, "dt", &cq) > 0) {
dp->d_type = gettype(cq, dktypenames);
else
free(cq);
} else
getnumdflt(dp->d_type, "dt", 0);
getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks);
getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders);
@ -140,8 +144,11 @@ getdiskbyname(const char *name)
pp->p_frag = 8;
}
getnumdflt(pp->p_fstype, ptype, 0);
if (pp->p_fstype == 0 && cgetstr(buf, ptype, &cq) > 0)
pp->p_fstype = gettype(cq, fstypenames);
if (pp->p_fstype == 0)
if (cgetstr(buf, ptype, &cq) >= 0) {
pp->p_fstype = gettype(cq, fstypenames);
free(cq);
}
max = p;
}
}

View File

@ -14,7 +14,7 @@
#include <sys/cdefs.h>
#if 0
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
__RCSID("$NetBSD: tdelete.c,v 1.6 2012/06/25 22:32:45 abs Exp $");
#endif /* LIBC_SCCS and not lint */
#endif
__FBSDID("$FreeBSD$");
@ -25,9 +25,9 @@ __FBSDID("$FreeBSD$");
/*
* delete node with given key
* find a node with given key
*
* vkey: key to be deleted
* vkey: key to be found
* vrootp: address of the root of the tree
* compar: function to carry out node comparisons
*/
@ -65,7 +65,8 @@ tdelete(const void * __restrict vkey, void ** __restrict vrootp,
q->rlink = (*rootp)->rlink;
}
}
free(*rootp); /* D4: Free node */
if (p != *rootp)
free(*rootp); /* D4: Free node */
*rootp = q; /* link parent to new node */
return p;
}

8
lib/libdevctl/Makefile Normal file
View File

@ -0,0 +1,8 @@
# $FreeBSD$
LIB= devctl
SRCS= devctl.c
INCS= devctl.h
MAN= devctl.3
.include <bsd.lib.mk>

295
lib/libdevctl/devctl.3 Normal file
View File

@ -0,0 +1,295 @@
.\"
.\" Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd December 26, 2014
.Dt DEVCTL 3
.Os
.Sh NAME
.Nm devctl ,
.Nm devctl_attach ,
.Nm devctl_detach ,
.Nm devctl_disable ,
.Nm devctl_enable ,
.Nm devctl_resume ,
.Nm devctl_suspend
.Nd device control library
.Sh LIBRARY
.Lb libdevctl
.Sh SYNOPSIS
.In devctl.h
.Ft int
.Fn devctl_attach "const char *device"
.Ft int
.Fn devctl_detach "const char *device" "bool force"
.Ft int
.Fn devctl_disable "const char *device" "bool force_detach"
.Ft int
.Fn devctl_enable "const char *device"
.Ft int
.Fn devctl_resume "const char *device"
.Ft int
.Fn devctl_suspend "const char *device"
.Ft int
.Fn devctl_set_driver "const char *device" "const char *driver" "bool force"
.Sh DESCRIPTION
The
.Nm
library adjusts the state of devices in the kernel's internal device
hierarchy.
Each control operation accepts a
.Fa device
argument that identifies the device to adjust.
The
.Fa device
may be specified as either the name of an existing device or as a
bus-specific address.
The following bus-specific address formats are currently supported:
.Bl -tag -offset indent
.It Sy pci Ns Fa domain Ns : Ns Fa bus Ns : Ns Fa slot Ns : Ns Fa function
A PCI device with the specified
.Fa domain ,
.Fa bus ,
.Fa slot ,
and
.Fa function .
.It Sy pci Ns Fa bus Ns : Ns Fa slot Ns : Ns Fa function
A PCI device in domain zero with the specified
.Fa bus ,
.Fa slot ,
and
.Fa function .
.It Fa handle
A device with an ACPI handle of
.Fa handle .
The handle must be specified as an absolute path and must begin with a
.Dq \e .
.El
.Pp
The
.Fn devctl_attach
function probes a device and attaches a suitable device driver if one is
found.
.Pp
The
.Fn devctl_detach
function detaches a device from its current device driver.
The device is left detached until either a new driver for its parent
bus is loaded or the device is explicitly probed via
.Fn devctl_attach .
If
.Fa force
is true,
the current device driver will be detached even if the device is busy.
.Pp
The
.Fn devctl_disable
function disables a device.
If the device is currently attached to a device driver,
the device driver will be detached from the device,
but the device will retain its current name.
If
.Fa force_detach
is true,
the current device driver will be detached even if the device is busy.
The device will remain disabled and detached until it is explicitly enabled
via
.Fn devctl_enable .
.Pp
The
.Fn devctl_enable
function re-enables a disabled device.
The device will probe and attach if a suitable device driver is found.
.Pp
The
.Fn devctl_suspend
function suspends a device.
This may include placing the device in a reduced power state,
but any device driver currently attached to the device will remain attached.
.Pp
The
.Fn devctl_resume
function resumes a suspended device to a fully working state.
.Pp
The
.Fn devctl_set_driver
function attaches a device driver named
.Fa driver
to a device.
If the device is already attached and
.Fa force
is false,
the request will fail.
If the device is already attached and
.Fa force
is true,
the device will be detached from its current device driver before it is
attached to the new device driver.
.Sh RETURN VALUES
.Rv -std devctl_attach devctl_detach devctl_disable devctl_enable \
devctl_suspend devctl_resume devctl_set_driver
.Sh ERRORS
In addition to specific errors noted below,
all of the
.Nm
functions may fail for any of the errors described in
.Xr open 2
as well as:
.Bl -tag -width Er
.It Bq Er EINVAL
The device name is too long.
.It Bq Er ENOENT
No existing device matches the specified name or location.
.It Bq Er EPERM
The current process is not permitted to adjust the state of
.Fa device .
.El
.Pp
The
.Fn devctl_attach
function may fail if:
.Bl -tag -width Er
.It Bq Er EBUSY
The device is already attached.
.It Bq Er ENOMEM
An internal memory allocation request failed.
.It Bq Er ENXIO
The device is disabled.
.It Bq Er ENXIO
No suitable driver for the device could be found,
or the driver failed to attach.
.El
.Pp
The
.Fn devctl_detach
function may fail if:
.Bl -tag -width Er
.It Bq Er EBUSY
The current device driver for
.Fa device
is busy and cannot detach at this time.
Note that some drivers may return this even if
.Fa force
is true.
.It Bq Er ENXIO
The device is not attached to a driver.
.It Bq Er ENXIO
The current device driver for
.Fa device
does not support detaching.
.El
.Pp
The
.Fn devctl_enable
function may fail if:
.Bl -tag -width Er
.It Bq Er EBUSY
The device is already enabled.
.It Bq Er ENOMEM
An internal memory allocation request failed.
.It Bq Er ENXIO
No suitable driver for the device could be found,
or the driver failed to attach.
.El
.Pp
The
.Fn devctl_disable
function may fail if:
.Bl -tag -width Er
.It Bq Er EBUSY
The current device driver for
.Fa device
is busy and cannot detach at this time.
Note that some drivers may return this even if
.Fa force_detach
is true.
.It Bq Er ENXIO
The device is already disabled.
.It Bq Er ENXIO
The current device driver for
.Fa device
does not support detaching.
.El
.Pp
The
.Fn devctl_suspend
function may fail if:
.Bl -tag -width Er
.It Bq Er EBUSY
The device is already suspended.
.It Bq Er EINVAL
The device to be suspended is the root bus device.
.El
.Pp
The
.Fn devctl_resume
function may fail if:
.Bl -tag -width Er
.It Bq Er EINVAL
The device is not suspended.
.It Bq Er EINVAL
The device to be resumed is the root bus device.
.El
.Pp
The
.Fn devctl_set_driver
function may fail if:
.Bl -tag -width Er
.It Bq Er EBUSY
The device is currently attached to a device driver and
.Fa force
is false.
.It Bq Er EBUSY
The current device driver for
.Fa device
is busy and cannot detach at this time.
.It Bq Er EFAULT
The
.Fa driver
argument points outside the process' allocated address space.
.It Bq Er ENOENT
No device driver with the requested name exists.
.It Bq Er ENOMEM
An internal memory allocation request failed.
.It Bq Er ENXIO
The device is disabled.
.It Bq Er ENXIO
The new device driver failed to attach.
.El
.Sh SEE ALSO
.Xr devinfo 3 ,
.Xr devstat 3 ,
.Xr devctl 8
.Sh HISTORY
The
.Nm
library first appeared in
.Fx 11.0 .
.Sh BUGS
If a device is suspended individually via
.Fn devctl_suspend
and the entire machine is subsequently suspended,
the device will be resumed when the machine resumes.

124
lib/libdevctl/devctl.c Normal file
View File

@ -0,0 +1,124 @@
/*-
* Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/bus.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include "devctl.h"
static int
devctl_request(u_long cmd, struct devreq *req)
{
static int devctl2_fd = -1;
if (devctl2_fd == -1) {
devctl2_fd = open("/dev/devctl2", O_RDONLY);
if (devctl2_fd == -1)
return (-1);
}
return (ioctl(devctl2_fd, cmd, req));
}
static int
devctl_simple_request(u_long cmd, const char *name, int flags)
{
struct devreq req;
memset(&req, 0, sizeof(req));
if (strlcpy(req.dr_name, name, sizeof(req.dr_name)) >=
sizeof(req.dr_name)) {
errno = EINVAL;
return (-1);
}
req.dr_flags = flags;
return (devctl_request(cmd, &req));
}
int
devctl_attach(const char *device)
{
return (devctl_simple_request(DEV_ATTACH, device, 0));
}
int
devctl_detach(const char *device, bool force)
{
return (devctl_simple_request(DEV_DETACH, device, force ?
DEVF_FORCE_DETACH : 0));
}
int
devctl_enable(const char *device)
{
return (devctl_simple_request(DEV_ENABLE, device, 0));
}
int
devctl_disable(const char *device, bool force_detach)
{
return (devctl_simple_request(DEV_DISABLE, device, force_detach ?
DEVF_FORCE_DETACH : 0));
}
int
devctl_suspend(const char *device)
{
return (devctl_simple_request(DEV_SUSPEND, device, 0));
}
int
devctl_resume(const char *device)
{
return (devctl_simple_request(DEV_RESUME, device, 0));
}
int
devctl_set_driver(const char *device, const char *driver, bool force)
{
struct devreq req;
memset(&req, 0, sizeof(req));
if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >=
sizeof(req.dr_name)) {
errno = EINVAL;
return (-1);
}
req.dr_data = __DECONST(char *, driver);
if (force)
req.dr_flags |= DEVF_SET_DRIVER_DETACH;
return (devctl_request(DEV_SET_DRIVER, &req));
}

42
lib/libdevctl/devctl.h Normal file
View File

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __DEVCTL_H__
#define __DEVCTL_H__
#include <stdbool.h>
int devctl_attach(const char *device);
int devctl_detach(const char *device, bool force);
int devctl_enable(const char *device);
int devctl_disable(const char *device, bool force_detach);
int devctl_suspend(const char *device);
int devctl_resume(const char *device);
int devctl_set_driver(const char *device, const char *driver, bool force);
#endif /* !__DEVCTL_H__ */

View File

@ -50,7 +50,7 @@ struct devinfo_dev {
char *dd_location; /* Where bus thinks dev at */
uint32_t dd_devflags; /* API flags */
uint16_t dd_flags; /* internal dev flags */
devinfo_state_t dd_state; /* attacement state of dev */
devinfo_state_t dd_state; /* attachment state of dev */
};
struct devinfo_rman {

View File

@ -62,12 +62,15 @@ __FBSDID("$FreeBSD$");
#include <netgraph/ng_atmllc.h>
#include <netgraph/ng_bpf.h>
#include <netgraph/ng_bridge.h>
#include <netgraph/ng_car.h>
#include <netgraph/ng_cisco.h>
#include <netgraph/ng_deflate.h>
#include <netgraph/ng_device.h>
#include <netgraph/ng_echo.h>
#include <netgraph/ng_eiface.h>
#include <netgraph/ng_etf.h>
#include <netgraph/ng_ether.h>
#include <netgraph/ng_ether_echo.h>
#include <netgraph/ng_frame_relay.h>
#include <netgraph/ng_gif.h>
#include <netgraph/ng_gif_demux.h>
@ -81,15 +84,20 @@ __FBSDID("$FreeBSD$");
#include <netgraph/ng_lmi.h>
#include <netgraph/ng_mppc.h>
#include <netgraph/ng_nat.h>
#include <netgraph/netflow/ng_netflow.h>
#include <netgraph/ng_one2many.h>
#include <netgraph/ng_patch.h>
#include <netgraph/ng_pipe.h>
#include <netgraph/ng_ppp.h>
#include <netgraph/ng_pppoe.h>
#include <netgraph/ng_pptpgre.h>
#include <netgraph/ng_pred1.h>
#include <netgraph/ng_rfc1490.h>
#include <netgraph/ng_socket.h>
#include <netgraph/ng_source.h>
#include <netgraph/ng_split.h>
#include <netgraph/ng_sppp.h>
#include <netgraph/ng_tag.h>
#include <netgraph/ng_tcpmss.h>
#include <netgraph/ng_tee.h>
#include <netgraph/ng_tty.h>
@ -129,12 +137,15 @@ static const struct ng_cookie cookies[] = {
COOKIE(ATMLLC),
COOKIE(BPF),
COOKIE(BRIDGE),
COOKIE(CAR),
COOKIE(CISCO),
COOKIE(DEFLATE),
COOKIE(DEVICE),
COOKIE(ECHO),
COOKIE(EIFACE),
COOKIE(ETF),
COOKIE(ETHER),
COOKIE(ETHER_ECHO),
COOKIE(FRAMERELAY),
COOKIE(GIF),
COOKIE(GIF_DEMUX),
@ -149,15 +160,20 @@ static const struct ng_cookie cookies[] = {
COOKIE(LMI),
COOKIE(MPPC),
COOKIE(NAT),
COOKIE(NETFLOW),
COOKIE(ONE2MANY),
COOKIE(PATCH),
COOKIE(PIPE),
COOKIE(PPP),
COOKIE(PPPOE),
COOKIE(PPTPGRE),
COOKIE(PRED1),
COOKIE(RFC1490),
COOKIE(SOCKET),
COOKIE(SOURCE),
COOKIE(SPLIT),
COOKIE(SPPP),
COOKIE(TAG),
COOKIE(TCPMSS),
COOKIE(TEE),
COOKIE(TTY),
@ -181,9 +197,8 @@ NgSetDebug(int level)
{
int old = _gNgDebugLevel;
if (level < 0)
level = old;
_gNgDebugLevel = level;
if (level >= 0)
_gNgDebugLevel = level;
return (old);
}
@ -225,10 +240,10 @@ _NgDebugMsg(const struct ng_mesg *msg, const char *path)
/* Display header stuff */
NGLOGX("NG_MESG :");
NGLOGX(" vers %d", msg->header.version);
NGLOGX(" arglen %d", msg->header.arglen);
NGLOGX(" flags %ld", msg->header.flags);
NGLOGX(" token %lu", (u_long)msg->header.token);
NGLOGX(" cookie %s (%d)",
NGLOGX(" arglen %u", msg->header.arglen);
NGLOGX(" flags %x", msg->header.flags);
NGLOGX(" token %u", msg->header.token);
NGLOGX(" cookie %s (%u)",
NgCookie(msg->header.typecookie), msg->header.typecookie);
/* At lower debugging levels, skip ASCII translation */

View File

@ -86,16 +86,13 @@ _pthread_barrier_init(pthread_barrier_t *barrier,
if (barrier == NULL || count <= 0)
return (EINVAL);
bar = malloc(sizeof(struct pthread_barrier));
bar = calloc(1, sizeof(struct pthread_barrier));
if (bar == NULL)
return (ENOMEM);
_thr_umutex_init(&bar->b_lock);
_thr_ucond_init(&bar->b_cv);
bar->b_cycle = 0;
bar->b_waiters = 0;
bar->b_count = count;
bar->b_refcount = 0;
*barrier = bar;
return (0);

View File

@ -27,38 +27,28 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <limits.h>
#include <math.h>
double
scalbln (double x, long n)
{
int in;
#define NMAX 65536
#define NMIN -65536
in = (int)n;
if (in != n)
in = (n > 0) ? INT_MAX: INT_MIN;
return (scalbn(x, in));
double
scalbln(double x, long n)
{
return (scalbn(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
}
float
scalblnf (float x, long n)
scalblnf(float x, long n)
{
int in;
in = (int)n;
if (in != n)
in = (n > 0) ? INT_MAX: INT_MIN;
return (scalbnf(x, in));
return (scalbnf(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
}
long double
scalblnl (long double x, long n)
scalblnl(long double x, long n)
{
int in;
in = (int)n;
if (in != n)
in = (n > 0) ? INT_MAX: INT_MIN;
return (scalbnl(x, in));
return (scalbnl(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
}

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 30, 2012
.Dd February 6, 2015
.Dt WITNESS 4
.Os
.Sh NAME
@ -32,7 +32,9 @@
.Nd lock validation facility
.Sh SYNOPSIS
.Cd options WITNESS
.Cd options WITNESS_COUNT
.Cd options WITNESS_KDB
.Cd options WITNESS_NO_VNODE
.Cd options WITNESS_SKIPSPIN
.Sh DESCRIPTION
The
@ -56,6 +58,28 @@ does not recurse on a non-recursive lock,
or attempt an upgrade on a shared lock held by another thread.
If any of these checks fail, then the kernel will panic.
.Pp
The
.Dv WITNESS_COUNT
kernel option controls the maximum number of
.Xr witness 4
entries that are tracked in the kernel.
The maximum number of entries can be queried via the
.Va debug.witness.count
sysctl.
It can also be set from the
.Xr loader 8
via the
.Va debug.witness.count
environment variable.
.Pp
The
.Dv WITNESS_NO_VNODE
kernel option tells
.Xr witness 4
to ignore locking issues between
.Xr vnode 9
objects.
.Pp
The flag that controls whether or not the kernel debugger is entered when a
lock order violation is detected can be set in a variety of ways.
By default, the flag is off, but if the

View File

@ -39,6 +39,7 @@ LIBCRYPT?= ${DESTDIR}${LIBDIR}/libcrypt.a
LIBCRYPTO?= ${DESTDIR}${LIBDIR}/libcrypto.a
LIBCTF?= ${DESTDIR}${LIBDIR}/libctf.a
LIBCURSES?= ${DESTDIR}${LIBDIR}/libcurses.a
LIBDEVCTL?= ${DESTDIR}${LIBDIR}/libdevctl.a
LIBDEVINFO?= ${DESTDIR}${LIBDIR}/libdevinfo.a
LIBDEVSTAT?= ${DESTDIR}${LIBDIR}/libdevstat.a
LIBDIALOG?= ${DESTDIR}${LIBDIR}/libdialog.a

View File

@ -72,6 +72,7 @@ _LIBRARIES= \
ctf \
cuse \
cxxrt \
devctl \
devinfo \
devstat \
dialog \

View File

@ -1064,15 +1064,28 @@ void
ipi_startup(int apic_id, int vector)
{
/*
* This attempts to follow the algorithm described in the
* Intel Multiprocessor Specification v1.4 in section B.4.
* For each IPI, we allow the local APIC ~20us to deliver the
* IPI. If that times out, we panic.
*/
/*
* first we do an INIT IPI: this INIT IPI might be run, resetting
* and running the target CPU. OR this INIT IPI might be latched (P5
* bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
* ignored.
*/
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_LEVEL |
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
lapic_ipi_wait(-1);
lapic_ipi_wait(20);
/* Explicitly deassert the INIT IPI. */
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_LEVEL |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT,
apic_id);
DELAY(10000); /* wait ~10mS */
/*
@ -1084,9 +1097,11 @@ ipi_startup(int apic_id, int vector)
* will run.
*/
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
vector, apic_id);
lapic_ipi_wait(-1);
if (!lapic_ipi_wait(20))
panic("Failed to deliver first STARTUP IPI to APIC %d",
apic_id);
DELAY(200); /* wait ~200uS */
/*
@ -1096,9 +1111,12 @@ ipi_startup(int apic_id, int vector)
* recognized after hardware RESET or INIT IPI.
*/
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
vector, apic_id);
lapic_ipi_wait(-1);
if (!lapic_ipi_wait(20))
panic("Failed to deliver second STARTUP IPI to APIC %d",
apic_id);
DELAY(200); /* wait ~200uS */
}

View File

@ -29,21 +29,21 @@ dev/mbox/mbox_if.m standard
dev/ofw/ofw_cpu.c standard
# VideoCore driver
contrib/vchiq/interface/compat/vchi_bsd.c standard \
contrib/vchiq/interface/compat/vchi_bsd.c optional vchiq \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c standard \
contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c optional vchiq \
compile-with "${NORMAL_C} -Wno-unused -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_arm.c standard \
contrib/vchiq/interface/vchiq_arm/vchiq_arm.c optional vchiq \
compile-with "${NORMAL_C} -Wno-unused -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_connected.c standard \
contrib/vchiq/interface/vchiq_arm/vchiq_connected.c optional vchiq \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_core.c standard \
contrib/vchiq/interface/vchiq_arm/vchiq_core.c optional vchiq \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c standard \
contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c optional vchiq \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c standard \
contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c optional vchiq \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_shim.c standard \
contrib/vchiq/interface/vchiq_arm/vchiq_shim.c optional vchiq \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_util.c standard \
contrib/vchiq/interface/vchiq_arm/vchiq_util.c optional vchiq \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"

View File

@ -129,9 +129,12 @@ device smsc
device spibus
device bcm2835_spi
device vchiq
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
# Note: DTB is normally loaded and modified by RPi boot loader, then
# handed to kernel via U-Boot and ubldr.
#options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=rpi.dts
#makeoptions FDT_DTS_FILE=rpi.dts
makeoptions MODULES_EXTRA=dtb/rpi

View File

@ -2,20 +2,19 @@ FAT template boot filesystem created by generate-fat.sh
DO NOT EDIT
$FreeBSD$
begin 644 fat.tmpl.bz2
M0EIH.3%!62936=AO?&0`&J9____[ZZKJJ_^N_ZO^Z_^[OO_\`5`(0!0&#$D"
M0$)$2&(<P`(\K5,M9"5%&DQ---,FAH,0```T````R-!HQ`&30`-&"#)ID$JF
M1)[U4_5-&@`T```#0&AH````````````(,F`$P`!,`1IA&````"9-,308`1@
M````!))!BDVI/U0`]0R>H:`81HT#)D!H-#U`T#31IH-&(``R8$9_I)6[MY/,
M(H=/()+4&!(3V0"20C3J5$L5@2`219,"T6JI,@0"2*2\=LAD6=>N6<O!'F<.
MQ2`;9$.P]202R&N9I3BX[E0;C7/9BF'`((K?M1ZK0B2Q;BLJ9!(`21P&1:;B
MDD)S!-L5BL5BL/173`@@M!!!!!X@BQ0@@@@@@CJ"A!!!"!`TWD!B!`@0($"J
M9(E`B,1(D2)$B;V]S&-,&#!@P8,'1\*$+59`:41,';;/)32*G*Q52N![20F8
M9CCYSB#!2=[EG.),$:P,>(8QSW'U+N42P^'5X@7X``23=EA``#Z,O)^-VTX@
M`+E!=,&6PV11C:*D8K#^<%FTG-%!@PR72@\ZU0B<D6I$FT/1\<A#/`;ET5$)
MKT-MBW97\J.P/H0ADE"(EBN6";@5#$2#!(\F/E8M+!8-A-S"+$U5[\J>F1Y]
MF-FPGL2L>4QCU&O/>89^#H$6^<;&WKC9W52KUX."CM6+GD;(=1!MUD,,?Y[]
MTLAG0];,:B^]M%BH0J1":_C-*2I9R3AS#,&0>$RCY'T/R?HR!?'5$MILQ:!"
M+;10A*!&^<(_/8>D8<CDN9]HO)OH13W(Q())?'R2WTV9*G_4T<=Y!'1+'9,(
J1-/V<ME.&9Q3LKI2S$(`$D,``'_=FF*).\[A.)#4HU1=R13A0D-AO?&0
M0EIH.3%!629362AK*D(`&I+____[ZZKJZ_^N_ZO^Z_Z_OJ[L`4`!7I0$#&$"
M0$!$3&(<P`(;J*C:0E0E#30&AH`T````9#0```9````#)ZF0:,-3U/409,`)
M@`"8`C3",````$R:8F@P`C`````"24U,D>I-DTU,)ZAZ0VA-!M0T'J`>H#"9
M'I#0-H&HQI&0&3&FH>H>*`JHHU3V]1%/4/2``T#0`!H``#0`````#1H,@``6
M'1&G'&@?$6[T#A)?X8$A160"20BO#")0J4TB1*4GXF$B4I,&>43+=_?K=#3*
M6]<E0HE`UBF?(J%8BRF#?8OQ2'D)`)(EL2;F4.'R>R"ZNKJZI,9*68E8*E2Q
M4J5*E3'(1830A"$(12A-"<(0A#]VD)H0A"$,>I0FA"$(0I\>P^=F5:M6K5JU
M:DI3:64UN;[7%5B]Y-^\]@_K@B:N\/,5F%&H<\G#IXQXAEFC&D?![6%0'6MR
MX1@@%FC"FD`M7,/SXFNG:2`'-0<-C$8^+$N.7M1B,^6)9,DV9,0A\OL<:C"L
ML1V&,<\9YRB>XV#BG")'6NKRK^("UF2XO?_L!#29">MGDF$R3).!PX&%E,4C
M''=(FL1.`_3?CN@-IB2PI3!FF\<8X.X@D,>CA90I)#M$XRPNDFJELL<3=1?8
M2B7\5Z64,!7Z;EEBW-MXN-4IJ@W$462]-*\YCR,-B,5[W?=3&L/U>SX,WV#\
M\B`:I"'0Z)5"$1B.E)(K[5I4RS`%R$>Y\D0NR*,;<9CZ:^V3P(I?D<D#!UC)
D^M-HEE3SAN-8O0FQ$(`$(DF`?ZQ]'U2F_XNY(IPH2!0UE2$`
`
end

View File

@ -20,7 +20,7 @@ OUTPUT_FILE=fat.tmpl
dd if=/dev/zero of=$OUTPUT_FILE bs=512 count=$FAT_SIZE
DEVICE=`mdconfig -a -f $OUTPUT_FILE`
newfs_msdos -F 12 $DEVICE
newfs_msdos -F 12 -L EFI $DEVICE
mkdir stub
mount -t msdosfs /dev/$DEVICE stub

View File

@ -89,7 +89,7 @@ variable logoY
0 25 at-xy
;
: fbsdbw-logo ( x y -- ) \ "FreeBSD" logo in B/W (12 rows x 21 columns)
: fbsdbw-logo ( x y -- ) \ "FreeBSD" logo in B/W (13 rows x 21 columns)
\ We used to use the beastie himself as our default... until the
\ eventual complaint derided his reign of the advanced boot-menu.
@ -106,16 +106,17 @@ variable logoY
5 + swap 6 + swap
2dup at-xy ." ______" 1+
2dup at-xy ." | ____|" 1+
2dup at-xy ." | |__ _ __ ___ ___ " 1+
2dup at-xy ." | __|| '__/ _ \/ _ \" 1+
2dup at-xy ." | | | | | __/ __/" 1+
2dup at-xy ." | ____| __ ___ ___ " 1+
2dup at-xy ." | |__ | '__/ _ \/ _ \" 1+
2dup at-xy ." | __|| | | __/ __/" 1+
2dup at-xy ." | | | | | | |" 1+
2dup at-xy ." |_| |_| \___|\___|" 1+
2dup at-xy ." ____ _____ _____" 1+
2dup at-xy ." | _ \ / ____| __ \" 1+
2dup at-xy ." | |_) | (___ | | | |" 1+
2dup at-xy ." | _ < \___ \| | | |" 1+
2dup at-xy ." | |_) |____) | |__| |" 1+
2dup at-xy ." | | | |" 1+
at-xy ." |____/|_____/|_____/"
\ Put the cursor back at the bottom

View File

@ -33,13 +33,14 @@ variable brandY
2 brandX !
1 brandY !
: fbsd-logo ( x y -- ) \ "FreeBSD" [wide] logo in B/W (6 rows x 42 columns)
: fbsd-logo ( x y -- ) \ "FreeBSD" [wide] logo in B/W (7 rows x 42 columns)
2dup at-xy ." ______ ____ _____ _____ " 1+
2dup at-xy ." | ____| | _ \ / ____| __ \ " 1+
2dup at-xy ." | |___ _ __ ___ ___ | |_) | (___ | | | |" 1+
2dup at-xy ." | ___| '__/ _ \/ _ \| _ < \___ \| | | |" 1+
2dup at-xy ." | | | | | __/ __/| |_) |____) | |__| |" 1+
2dup at-xy ." | | | | | | || | | |" 1+
at-xy ." |_| |_| \___|\___||____/|_____/|_____/ "
\ Put the cursor back at the bottom

View File

@ -1222,7 +1222,7 @@ cfiscsi_session_unregister_initiator(struct cfiscsi_session *cs)
}
static struct cfiscsi_session *
cfiscsi_session_new(struct cfiscsi_softc *softc)
cfiscsi_session_new(struct cfiscsi_softc *softc, const char *offload)
{
struct cfiscsi_session *cs;
int error;
@ -1242,7 +1242,11 @@ cfiscsi_session_new(struct cfiscsi_softc *softc)
cv_init(&cs->cs_login_cv, "cfiscsi_login");
#endif
cs->cs_conn = icl_new_conn(NULL, "cfiscsi", &cs->cs_lock);
cs->cs_conn = icl_new_conn(offload, "cfiscsi", &cs->cs_lock);
if (cs->cs_conn == NULL) {
free(cs, M_CFISCSI);
return (NULL);
}
cs->cs_conn->ic_receive = cfiscsi_receive_callback;
cs->cs_conn->ic_error = cfiscsi_error_callback;
cs->cs_conn->ic_prv0 = cs;
@ -1325,7 +1329,7 @@ cfiscsi_accept(struct socket *so, struct sockaddr *sa, int portal_id)
{
struct cfiscsi_session *cs;
cs = cfiscsi_session_new(&cfiscsi_softc);
cs = cfiscsi_session_new(&cfiscsi_softc, NULL);
if (cs == NULL) {
CFISCSI_WARN("failed to create session");
return;
@ -1469,7 +1473,7 @@ cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
mtx_unlock(&cfiscsi_softc.lock);
} else {
#endif
cs = cfiscsi_session_new(softc);
cs = cfiscsi_session_new(softc, cihp->offload);
if (cs == NULL) {
ci->status = CTL_ISCSI_ERROR;
snprintf(ci->error_str, sizeof(ci->error_str),
@ -1620,6 +1624,7 @@ cfiscsi_ioctl_list(struct ctl_iscsi *ci)
"<max_data_segment_length>%zd</max_data_segment_length>"
"<immediate_data>%d</immediate_data>"
"<iser>%d</iser>"
"<offload>%s</offload>"
"</connection>\n",
cs->cs_id,
cs->cs_initiator_name, cs->cs_initiator_addr, cs->cs_initiator_alias,
@ -1629,7 +1634,8 @@ cfiscsi_ioctl_list(struct ctl_iscsi *ci)
cs->cs_conn->ic_data_crc32c ? "CRC32C" : "None",
cs->cs_max_data_segment_length,
cs->cs_immediate_data,
cs->cs_conn->ic_iser);
cs->cs_conn->ic_iser,
cs->cs_conn->ic_offload);
if (error != 0)
break;
}
@ -1749,6 +1755,26 @@ cfiscsi_ioctl_logout(struct ctl_iscsi *ci)
ci->status = CTL_ISCSI_OK;
}
static void
cfiscsi_ioctl_limits(struct ctl_iscsi *ci)
{
struct ctl_iscsi_limits_params *cilp;
int error;
cilp = (struct ctl_iscsi_limits_params *)&(ci->data);
error = icl_limits(cilp->offload, &cilp->data_segment_limit);
if (error != 0) {
ci->status = CTL_ISCSI_ERROR;
snprintf(ci->error_str, sizeof(ci->error_str),
"%s: icl_limits failed with error %d",
__func__, error);
return;
}
ci->status = CTL_ISCSI_OK;
}
#ifdef ICL_KERNEL_PROXY
static void
cfiscsi_ioctl_listen(struct ctl_iscsi *ci)
@ -2176,6 +2202,9 @@ cfiscsi_ioctl(struct cdev *dev,
case CTL_ISCSI_LOGOUT:
cfiscsi_ioctl_logout(ci);
break;
case CTL_ISCSI_LIMITS:
cfiscsi_ioctl_limits(ci);
break;
#ifdef ICL_KERNEL_PROXY
case CTL_ISCSI_LISTEN:
cfiscsi_ioctl_listen(ci);

View File

@ -657,6 +657,7 @@ typedef enum {
CTL_ISCSI_LIST,
CTL_ISCSI_LOGOUT,
CTL_ISCSI_TERMINATE,
CTL_ISCSI_LIMITS,
#if defined(ICL_KERNEL_PROXY) || 1
/*
* We actually need those in all cases, but leave the ICL_KERNEL_PROXY,
@ -677,6 +678,7 @@ typedef enum {
#define CTL_ISCSI_NAME_LEN 224 /* 223 bytes, by RFC 3720, + '\0' */
#define CTL_ISCSI_ADDR_LEN 47 /* INET6_ADDRSTRLEN + '\0' */
#define CTL_ISCSI_ALIAS_LEN 128 /* Arbitrary. */
#define CTL_ISCSI_OFFLOAD_LEN 8 /* Arbitrary. */
struct ctl_iscsi_handoff_params {
char initiator_name[CTL_ISCSI_NAME_LEN];
@ -698,11 +700,12 @@ struct ctl_iscsi_handoff_params {
uint32_t max_burst_length;
uint32_t first_burst_length;
uint32_t immediate_data;
char offload[CTL_ISCSI_OFFLOAD_LEN];
#ifdef ICL_KERNEL_PROXY
int connection_id;
int spare[3];
int spare[1];
#else
int spare[4];
int spare[2];
#endif
};
@ -733,6 +736,14 @@ struct ctl_iscsi_terminate_params {
int spare[4];
};
struct ctl_iscsi_limits_params {
char offload[CTL_ISCSI_OFFLOAD_LEN];
/* passed to kernel */
size_t data_segment_limit;
/* passed to userland */
int spare[4];
};
#ifdef ICL_KERNEL_PROXY
struct ctl_iscsi_listen_params {
int iser;
@ -780,6 +791,7 @@ union ctl_iscsi_data {
struct ctl_iscsi_list_params list;
struct ctl_iscsi_logout_params logout;
struct ctl_iscsi_terminate_params terminate;
struct ctl_iscsi_limits_params limits;
#ifdef ICL_KERNEL_PROXY
struct ctl_iscsi_listen_params listen;
struct ctl_iscsi_accept_params accept;

View File

@ -3193,7 +3193,7 @@ libkern/jenkins_hash.c standard
libkern/murmur3_32.c standard
libkern/mcount.c optional profiling-routine
libkern/memcchr.c standard
libkern/memchr.c optional fdt | gdb
libkern/memchr.c standard
libkern/memcmp.c standard
libkern/memmem.c optional gdb
libkern/qsort.c standard

View File

@ -174,7 +174,7 @@ SYSTEM_OBJS= locore.o ${MDOBJS} ${OBJS}
SYSTEM_OBJS+= ${SYSTEM_CFILES:.c=.o}
SYSTEM_OBJS+= hack.So
SYSTEM_LD= @${LD} -Bdynamic -T ${LDSCRIPT} ${_LDFLAGS} --no-warn-mismatch \
-warn-common -export-dynamic -dynamic-linker /red/herring \
--warn-common --export-dynamic --dynamic-linker /red/herring \
-o ${.TARGET} -X ${SYSTEM_OBJS} vers.o
SYSTEM_LD_TAIL= @${OBJCOPY} --strip-symbol gcc2_compiled. ${.TARGET} ; \
${SIZE} ${.TARGET} ; chmod 755 ${.TARGET}

View File

@ -317,12 +317,12 @@ typedef struct {
/* Support for multiple INIs */
struct ar9300_ini_array {
u_int32_t *ia_array;
const u_int32_t *ia_array;
u_int32_t ia_rows;
u_int32_t ia_columns;
};
#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
(iniarray)->ia_array = (u_int32_t *)(array); \
(iniarray)->ia_array = (const u_int32_t *)(array); \
(iniarray)->ia_rows = (rows); \
(iniarray)->ia_columns = (columns); \
} while (0)

View File

@ -101,6 +101,7 @@ int acpi_quirks;
/* Supported sleep states. */
static BOOLEAN acpi_sleep_states[ACPI_S_STATE_COUNT];
static void acpi_lookup(void *arg, const char *name, device_t *dev);
static int acpi_modevent(struct module *mod, int event, void *junk);
static int acpi_probe(device_t dev);
static int acpi_attach(device_t dev);
@ -671,8 +672,10 @@ acpi_attach(device_t dev)
/* Register ACPI again to pass the correct argument of pm_func. */
power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc);
if (!acpi_disabled("bus"))
if (!acpi_disabled("bus")) {
EVENTHANDLER_REGISTER(dev_lookup, acpi_lookup, NULL, 1000);
acpi_probe_children(dev);
}
/* Update all GPEs and enable runtime GPEs. */
status = AcpiUpdateAllGpes();
@ -3401,6 +3404,31 @@ acpi_disabled(char *subsys)
return (0);
}
static void
acpi_lookup(void *arg, const char *name, device_t *dev)
{
ACPI_HANDLE handle;
if (*dev != NULL)
return;
/*
* Allow any handle name that is specified as an absolute path and
* starts with '\'. We could restrict this to \_SB and friends,
* but see acpi_probe_children() for notes on why we scan the entire
* namespace for devices.
*
* XXX: The pathname argument to AcpiGetHandle() should be fixed to
* be const.
*/
if (name[0] != '\\')
return;
if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, __DECONST(char *, name),
&handle)))
return;
*dev = acpi_get_device(handle);
}
/*
* Control interface.
*

44
sys/dev/cxgbe/if_cxl.c Normal file
View File

@ -0,0 +1,44 @@
/*-
* Copyright (c) 2015 Chelsio Communications, Inc.
* All rights reserved.
* Written by: Navdeep Parhar <np@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
static int
mod_event(module_t mod, int cmd, void *arg)
{
return (0);
}
static moduledata_t if_cxl_mod = {"if_cxl", mod_event};
DECLARE_MODULE(if_cxl, if_cxl_mod, SI_SUB_EXEC, SI_ORDER_ANY);
MODULE_VERSION(if_cxl, 1);
MODULE_DEPEND(if_cxl, cxl, 1, 1, 1);

View File

@ -8215,7 +8215,12 @@ toe_capability(struct port_info *pi, int enable)
return (ENODEV);
if (enable) {
if (!(sc->flags & FULL_INIT_DONE)) {
/*
* We need the port's queues around so that we're able to send
* and receive CPLs to/from the TOE even if the ifnet for this
* port has never been UP'd administratively.
*/
if (!(pi->flags & PORT_INIT_DONE)) {
rc = cxgbe_init_synchronized(pi);
if (rc)
return (rc);

View File

@ -49,6 +49,23 @@ __FBSDID("$FreeBSD$");
#include <dev/ipmi/ipmivars.h>
#endif
/*
* Driver request structures are allocated on the stack via alloca() to
* avoid calling malloc(), especially for the watchdog handler.
* To avoid too much stack growth, a previously allocated structure can
* be reused via IPMI_INIT_DRIVER_REQUEST(), but the caller should ensure
* that there is adequate reply/request space in the original allocation.
*/
#define IPMI_INIT_DRIVER_REQUEST(req, addr, cmd, reqlen, replylen) \
bzero((req), sizeof(struct ipmi_request)); \
ipmi_init_request((req), NULL, 0, (addr), (cmd), (reqlen), (replylen))
#define IPMI_ALLOC_DRIVER_REQUEST(req, addr, cmd, reqlen, replylen) \
(req) = __builtin_alloca(sizeof(struct ipmi_request) + \
(reqlen) + (replylen)); \
IPMI_INIT_DRIVER_REQUEST((req), (addr), (cmd), (reqlen), \
(replylen))
#ifdef IPMB
static int ipmi_ipmb_checksum(u_char, int);
static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char,
@ -181,8 +198,8 @@ ipmi_dtor(void *arg)
*/
dev->ipmi_closing = 1;
while (dev->ipmi_requests > 0) {
msleep(&dev->ipmi_requests, &sc->ipmi_lock, PWAIT,
"ipmidrain", 0);
msleep(&dev->ipmi_requests, &sc->ipmi_requests_lock,
PWAIT, "ipmidrain", 0);
ipmi_purge_completed_requests(dev);
}
}
@ -215,7 +232,7 @@ ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn,
u_char slave_addr = 0x52;
int error;
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_SEND_MSG, data_len + 8, 0);
req->ir_request[0] = channel;
req->ir_request[1] = slave_addr;
@ -231,7 +248,6 @@ ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn,
ipmi_submit_driver_request(sc, req);
error = req->ir_error;
ipmi_free_request(req);
return (error);
}
@ -243,7 +259,7 @@ ipmi_handle_attn(struct ipmi_softc *sc)
int error;
device_printf(sc->ipmi_dev, "BMC has a message\n");
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_GET_MSG_FLAGS, 0, 1);
ipmi_submit_driver_request(sc, req);
@ -257,9 +273,7 @@ ipmi_handle_attn(struct ipmi_softc *sc)
"watchdog about to go off");
}
if (req->ir_reply[0] & IPMI_MSG_AVAILABLE) {
ipmi_free_request(req);
req = ipmi_alloc_driver_request(
IPMI_ALLOC_DRIVER_REQUEST(req,
IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, 0,
16);
@ -268,7 +282,6 @@ ipmi_handle_attn(struct ipmi_softc *sc)
}
}
error = req->ir_error;
ipmi_free_request(req);
return (error);
}
@ -478,15 +491,11 @@ ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data,
* Request management.
*/
/* Allocate a new request with request and reply buffers. */
struct ipmi_request *
ipmi_alloc_request(struct ipmi_device *dev, long msgid, uint8_t addr,
uint8_t command, size_t requestlen, size_t replylen)
static __inline void
ipmi_init_request(struct ipmi_request *req, struct ipmi_device *dev, long msgid,
uint8_t addr, uint8_t command, size_t requestlen, size_t replylen)
{
struct ipmi_request *req;
req = malloc(sizeof(struct ipmi_request) + requestlen + replylen,
M_IPMI, M_WAITOK | M_ZERO);
req->ir_owner = dev;
req->ir_msgid = msgid;
req->ir_addr = addr;
@ -499,6 +508,18 @@ ipmi_alloc_request(struct ipmi_device *dev, long msgid, uint8_t addr,
req->ir_reply = (char *)&req[1] + requestlen;
req->ir_replybuflen = replylen;
}
}
/* Allocate a new request with request and reply buffers. */
struct ipmi_request *
ipmi_alloc_request(struct ipmi_device *dev, long msgid, uint8_t addr,
uint8_t command, size_t requestlen, size_t replylen)
{
struct ipmi_request *req;
req = malloc(sizeof(struct ipmi_request) + requestlen + replylen,
M_IPMI, M_WAITOK | M_ZERO);
ipmi_init_request(req, dev, msgid, addr, command, requestlen, replylen);
return (req);
}
@ -533,21 +554,13 @@ ipmi_complete_request(struct ipmi_softc *sc, struct ipmi_request *req)
}
}
/* Enqueue an internal driver request and wait until it is completed. */
/* Perform an internal driver request. */
int
ipmi_submit_driver_request(struct ipmi_softc *sc, struct ipmi_request *req,
int timo)
{
int error;
IPMI_LOCK(sc);
error = sc->ipmi_enqueue_request(sc, req);
if (error == 0)
error = msleep(req, &sc->ipmi_lock, 0, "ipmireq", timo);
if (error == 0)
error = req->ir_error;
IPMI_UNLOCK(sc);
return (error);
return (sc->ipmi_driver_request(sc, req, timo));
}
/*
@ -564,7 +577,7 @@ ipmi_dequeue_request(struct ipmi_softc *sc)
IPMI_LOCK_ASSERT(sc);
while (!sc->ipmi_detaching && TAILQ_EMPTY(&sc->ipmi_pending_requests))
cv_wait(&sc->ipmi_request_added, &sc->ipmi_lock);
cv_wait(&sc->ipmi_request_added, &sc->ipmi_requests_lock);
if (sc->ipmi_detaching)
return (NULL);
@ -598,7 +611,7 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
if (sec > 0xffff / 10)
return (EINVAL);
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_SET_WDOG, 6, 0);
if (sec) {
@ -622,9 +635,7 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
if (error)
device_printf(sc->ipmi_dev, "Failed to set watchdog\n");
else if (sec) {
ipmi_free_request(req);
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_RESET_WDOG, 0, 0);
error = ipmi_submit_driver_request(sc, req, 0);
@ -633,7 +644,6 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
"Failed to reset watchdog\n");
}
ipmi_free_request(req);
return (error);
/*
dump_watchdog(sc);
@ -680,7 +690,8 @@ ipmi_startup(void *arg)
dev = sc->ipmi_dev;
/* Initialize interface-independent state. */
mtx_init(&sc->ipmi_lock, device_get_nameunit(dev), "ipmi", MTX_DEF);
mtx_init(&sc->ipmi_requests_lock, "ipmi requests", NULL, MTX_DEF);
mtx_init(&sc->ipmi_io_lock, "ipmi io", NULL, MTX_DEF);
cv_init(&sc->ipmi_request_added, "ipmireq");
TAILQ_INIT(&sc->ipmi_pending_requests);
@ -693,28 +704,24 @@ ipmi_startup(void *arg)
}
/* Send a GET_DEVICE_ID request. */
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_GET_DEVICE_ID, 0, 15);
error = ipmi_submit_driver_request(sc, req, MAX_TIMEOUT);
if (error == EWOULDBLOCK) {
device_printf(dev, "Timed out waiting for GET_DEVICE_ID\n");
ipmi_free_request(req);
return;
} else if (error) {
device_printf(dev, "Failed GET_DEVICE_ID: %d\n", error);
ipmi_free_request(req);
return;
} else if (req->ir_compcode != 0) {
device_printf(dev,
"Bad completion code for GET_DEVICE_ID: %d\n",
req->ir_compcode);
ipmi_free_request(req);
return;
} else if (req->ir_replylen < 5) {
device_printf(dev, "Short reply for GET_DEVICE_ID: %d\n",
req->ir_replylen);
ipmi_free_request(req);
return;
}
@ -724,9 +731,7 @@ ipmi_startup(void *arg)
req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f,
req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4);
ipmi_free_request(req);
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_CLEAR_FLAGS, 1, 0);
ipmi_submit_driver_request(sc, req, 0);
@ -738,25 +743,21 @@ ipmi_startup(void *arg)
if (req->ir_compcode == 0xc1) {
device_printf(dev, "Clear flags illegal\n");
}
ipmi_free_request(req);
for (i = 0; i < 8; i++) {
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_GET_CHANNEL_INFO, 1, 0);
req->ir_request[0] = i;
ipmi_submit_driver_request(sc, req, 0);
if (req->ir_compcode != 0) {
ipmi_free_request(req);
if (req->ir_compcode != 0)
break;
}
ipmi_free_request(req);
}
device_printf(dev, "Number of channels %d\n", i);
/* probe for watchdog */
req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_GET_WDOG, 0, 0);
ipmi_submit_driver_request(sc, req, 0);
@ -767,7 +768,6 @@ ipmi_startup(void *arg)
sc->ipmi_watchdog_tag = EVENTHANDLER_REGISTER(watchdog_list,
ipmi_wd_event, sc, 0);
}
ipmi_free_request(req);
sc->ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev),
UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev));
@ -834,14 +834,16 @@ ipmi_detach(device_t dev)
sc->ipmi_detaching = 1;
if (sc->ipmi_kthread) {
cv_broadcast(&sc->ipmi_request_added);
msleep(sc->ipmi_kthread, &sc->ipmi_lock, 0, "ipmi_wait", 0);
msleep(sc->ipmi_kthread, &sc->ipmi_requests_lock, 0,
"ipmi_wait", 0);
}
IPMI_UNLOCK(sc);
if (sc->ipmi_irq)
bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq);
ipmi_release_resources(dev);
mtx_destroy(&sc->ipmi_lock);
mtx_destroy(&sc->ipmi_io_lock);
mtx_destroy(&sc->ipmi_requests_lock);
return (0);
}

View File

@ -321,6 +321,8 @@ kcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
u_char *cp, data;
int i, state;
IPMI_IO_LOCK(sc);
/* Send the request. */
if (!kcs_start_write(sc)) {
device_printf(sc->ipmi_dev, "KCS: Failed to start write\n");
@ -444,6 +446,7 @@ kcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
}
i++;
}
IPMI_IO_UNLOCK(sc);
req->ir_replylen = i;
#ifdef KCS_DEBUG
device_printf(sc->ipmi_dev, "KCS: READ finished (%d bytes)\n", i);
@ -457,6 +460,7 @@ kcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req)
return (1);
fail:
kcs_error(sc);
IPMI_IO_UNLOCK(sc);
return (0);
}
@ -492,6 +496,21 @@ kcs_startup(struct ipmi_softc *sc)
device_get_nameunit(sc->ipmi_dev)));
}
static int
kcs_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
{
int i, ok;
ok = 0;
for (i = 0; i < 3 && !ok; i++)
ok = kcs_polled_request(sc, req);
if (ok)
req->ir_error = 0;
else
req->ir_error = EIO;
return (req->ir_error);
}
int
ipmi_kcs_attach(struct ipmi_softc *sc)
{
@ -500,6 +519,7 @@ ipmi_kcs_attach(struct ipmi_softc *sc)
/* Setup function pointers. */
sc->ipmi_startup = kcs_startup;
sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
sc->ipmi_driver_request = kcs_driver_request;
/* See if we can talk to the controller. */
status = INB(sc, KCS_CTL_STS);

View File

@ -364,8 +364,11 @@ smic_loop(void *arg)
while ((req = ipmi_dequeue_request(sc)) != NULL) {
IPMI_UNLOCK(sc);
ok = 0;
for (i = 0; i < 3 && !ok; i++)
for (i = 0; i < 3 && !ok; i++) {
IPMI_IO_LOCK(sc);
ok = smic_polled_request(sc, req);
IPMI_IO_UNLOCK(sc);
}
if (ok)
req->ir_error = 0;
else
@ -385,6 +388,24 @@ smic_startup(struct ipmi_softc *sc)
"%s: smic", device_get_nameunit(sc->ipmi_dev)));
}
static int
smic_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
{
int i, ok;
ok = 0;
for (i = 0; i < 3 && !ok; i++) {
IPMI_IO_LOCK(sc);
ok = smic_polled_request(sc, req);
IPMI_IO_UNLOCK(sc);
}
if (ok)
req->ir_error = 0;
else
req->ir_error = EIO;
return (req->ir_error);
}
int
ipmi_smic_attach(struct ipmi_softc *sc)
{
@ -393,6 +414,7 @@ ipmi_smic_attach(struct ipmi_softc *sc)
/* Setup function pointers. */
sc->ipmi_startup = smic_startup;
sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
sc->ipmi_driver_request = smic_driver_request;
/* See if we can talk to the controller. */
flags = INB(sc, SMIC_FLAGS);

View File

@ -359,6 +359,22 @@ ssif_startup(struct ipmi_softc *sc)
"%s: ssif", device_get_nameunit(sc->ipmi_dev)));
}
static int
ssif_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo)
{
int error;
IPMI_LOCK(sc);
error = ipmi_polled_enqueue_request(sc, req);
if (error == 0)
error = msleep(req, &sc->ipmi_requests_lock, 0, "ipmireq",
timo);
if (error == 0)
error = req->ir_error;
IPMI_UNLOCK(sc);
return (error);
}
int
ipmi_ssif_attach(struct ipmi_softc *sc, device_t smbus, int smbus_address)
{
@ -370,6 +386,7 @@ ipmi_ssif_attach(struct ipmi_softc *sc, device_t smbus, int smbus_address)
/* Setup function pointers. */
sc->ipmi_startup = ssif_startup;
sc->ipmi_enqueue_request = ipmi_polled_enqueue_request;
sc->ipmi_driver_request = ssif_driver_request;
return (0);
}

View File

@ -95,6 +95,7 @@ struct ipmi_softc {
} _iface;
int ipmi_io_rid;
int ipmi_io_type;
struct mtx ipmi_io_lock;
struct resource *ipmi_io_res[MAX_RES];
int ipmi_io_spacing;
int ipmi_irq_rid;
@ -107,12 +108,13 @@ struct ipmi_softc {
eventhandler_tag ipmi_watchdog_tag;
int ipmi_watchdog_active;
struct intr_config_hook ipmi_ich;
struct mtx ipmi_lock;
struct mtx ipmi_requests_lock;
struct cv ipmi_request_added;
struct proc *ipmi_kthread;
driver_intr_t *ipmi_intr;
int (*ipmi_startup)(struct ipmi_softc *);
int (*ipmi_enqueue_request)(struct ipmi_softc *, struct ipmi_request *);
int (*ipmi_driver_request)(struct ipmi_softc *, struct ipmi_request *, int);
};
#define ipmi_ssif_smbus_address _iface.ssif.smbus_address
@ -183,12 +185,13 @@ struct ipmi_ipmb {
#define IPMI_ADDR(netfn, lun) ((netfn) << 2 | (lun))
#define IPMI_REPLY_ADDR(addr) ((addr) + 0x4)
#define IPMI_LOCK(sc) mtx_lock(&(sc)->ipmi_lock)
#define IPMI_UNLOCK(sc) mtx_unlock(&(sc)->ipmi_lock)
#define IPMI_LOCK_ASSERT(sc) mtx_assert(&(sc)->ipmi_lock, MA_OWNED)
#define IPMI_LOCK(sc) mtx_lock(&(sc)->ipmi_requests_lock)
#define IPMI_UNLOCK(sc) mtx_unlock(&(sc)->ipmi_requests_lock)
#define IPMI_LOCK_ASSERT(sc) mtx_assert(&(sc)->ipmi_requests_lock, MA_OWNED)
#define ipmi_alloc_driver_request(addr, cmd, reqlen, replylen) \
ipmi_alloc_request(NULL, 0, (addr), (cmd), (reqlen), (replylen))
#define IPMI_IO_LOCK(sc) mtx_lock(&(sc)->ipmi_io_lock)
#define IPMI_IO_UNLOCK(sc) mtx_unlock(&(sc)->ipmi_io_lock)
#define IPMI_IO_LOCK_ASSERT(sc) mtx_assert(&(sc)->ipmi_io_lock, MA_OWNED)
#if __FreeBSD_version < 601105
#define bus_read_1(r, o) \

View File

@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/limits.h>
#include <sys/linker.h>
#include <sys/fcntl.h>
#include <sys/conf.h>
@ -4824,8 +4825,8 @@ pci_child_location_str_method(device_t dev, device_t child, char *buf,
size_t buflen)
{
snprintf(buf, buflen, "slot=%d function=%d", pci_get_slot(child),
pci_get_function(child));
snprintf(buf, buflen, "pci%d:%d:%d:%d", pci_get_domain(child),
pci_get_bus(child), pci_get_slot(child), pci_get_function(child));
return (0);
}
@ -4855,10 +4856,60 @@ pci_assign_interrupt_method(device_t dev, device_t child)
cfg->intpin));
}
static void
pci_lookup(void *arg, const char *name, device_t *dev)
{
long val;
char *end;
int domain, bus, slot, func;
if (*dev != NULL)
return;
/*
* Accept pciconf-style selectors of either pciD:B:S:F or
* pciB:S:F. In the latter case, the domain is assumed to
* be zero.
*/
if (strncmp(name, "pci", 3) != 0)
return;
val = strtol(name + 3, &end, 10);
if (val < 0 || val > INT_MAX || *end != ':')
return;
domain = val;
val = strtol(end + 1, &end, 10);
if (val < 0 || val > INT_MAX || *end != ':')
return;
bus = val;
val = strtol(end + 1, &end, 10);
if (val < 0 || val > INT_MAX)
return;
slot = val;
if (*end == ':') {
val = strtol(end + 1, &end, 10);
if (val < 0 || val > INT_MAX || *end != '\0')
return;
func = val;
} else if (*end == '\0') {
func = slot;
slot = bus;
bus = domain;
domain = 0;
} else
return;
if (domain > PCI_DOMAINMAX || bus > PCI_BUSMAX || slot > PCI_SLOTMAX ||
func > PCIE_ARI_FUNCMAX || (slot != 0 && func > PCI_FUNCMAX))
return;
*dev = pci_find_dbsf(domain, bus, slot, func);
}
static int
pci_modevent(module_t mod, int what, void *arg)
{
static struct cdev *pci_cdev;
static eventhandler_tag tag;
switch (what) {
case MOD_LOAD:
@ -4867,9 +4918,13 @@ pci_modevent(module_t mod, int what, void *arg)
pci_cdev = make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644,
"pci");
pci_load_vendor_data();
tag = EVENTHANDLER_REGISTER(dev_lookup, pci_lookup, NULL,
1000);
break;
case MOD_UNLOAD:
if (tag != NULL)
EVENTHANDLER_DEREGISTER(dev_lookup, tag);
destroy_dev(pci_cdev);
break;
}

View File

@ -1137,15 +1137,28 @@ void
ipi_startup(int apic_id, int vector)
{
/*
* This attempts to follow the algorithm described in the
* Intel Multiprocessor Specification v1.4 in section B.4.
* For each IPI, we allow the local APIC ~20us to deliver the
* IPI. If that times out, we panic.
*/
/*
* first we do an INIT IPI: this INIT IPI might be run, resetting
* and running the target CPU. OR this INIT IPI might be latched (P5
* bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
* ignored.
*/
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_LEVEL |
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
lapic_ipi_wait(-1);
lapic_ipi_wait(20);
/* Explicitly deassert the INIT IPI. */
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_LEVEL |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT,
apic_id);
DELAY(10000); /* wait ~10mS */
/*
@ -1157,9 +1170,11 @@ ipi_startup(int apic_id, int vector)
* will run.
*/
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
vector, apic_id);
lapic_ipi_wait(-1);
if (!lapic_ipi_wait(20))
panic("Failed to deliver first STARTUP IPI to APIC %d",
apic_id);
DELAY(200); /* wait ~200uS */
/*
@ -1169,9 +1184,12 @@ ipi_startup(int apic_id, int vector)
* recognized after hardware RESET or INIT IPI.
*/
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
vector, apic_id);
lapic_ipi_wait(-1);
if (!lapic_ipi_wait(20))
panic("Failed to deliver second STARTUP IPI to APIC %d",
apic_id);
DELAY(200); /* wait ~200uS */
}

View File

@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/poll.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/condvar.h>
#include <sys/queue.h>
@ -128,15 +129,6 @@ struct device {
device_state_t state; /**< current device state */
uint32_t devflags; /**< api level flags for device_get_flags() */
u_int flags; /**< internal device flags */
#define DF_ENABLED 0x01 /* device should be probed/attached */
#define DF_FIXEDCLASS 0x02 /* devclass specified at create time */
#define DF_WILDCARD 0x04 /* unit was originally wildcard */
#define DF_DESCMALLOCED 0x08 /* description was malloced */
#define DF_QUIET 0x10 /* don't print verbose attach message */
#define DF_DONENOMATCH 0x20 /* don't execute DEVICE_NOMATCH again */
#define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */
#define DF_REBID 0x80 /* Can rebid after attach */
#define DF_SUSPENDED 0x100 /* Device is suspended. */
u_int order; /**< order from device_add_child_ordered() */
void *ivars; /**< instance variables */
void *softc; /**< current driver's variables */
@ -148,6 +140,8 @@ struct device {
static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
static void devctl2_init(void);
#ifdef BUS_DEBUG
static int bus_debug = 1;
@ -432,6 +426,7 @@ devinit(void)
cv_init(&devsoftc.cv, "dev cv");
TAILQ_INIT(&devsoftc.devq);
knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx);
devctl2_init();
}
static int
@ -2647,6 +2642,15 @@ device_is_attached(device_t dev)
return (dev->state >= DS_ATTACHED);
}
/**
* @brief Return non-zero if the device is currently suspended.
*/
int
device_is_suspended(device_t dev)
{
return ((dev->flags & DF_SUSPENDED) != 0);
}
/**
* @brief Set the devclass of a device
* @see devclass_add_device().
@ -5031,3 +5035,253 @@ bus_free_resource(device_t dev, int type, struct resource *r)
return (0);
return (bus_release_resource(dev, type, rman_get_rid(r), r));
}
/*
* /dev/devctl2 implementation. The existing /dev/devctl device has
* implicit semantics on open, so it could not be reused for this.
* Another option would be to call this /dev/bus?
*/
static int
find_device(struct devreq *req, device_t *devp)
{
device_t dev;
/*
* First, ensure that the name is nul terminated.
*/
if (memchr(req->dr_name, '\0', sizeof(req->dr_name)) == NULL)
return (EINVAL);
/*
* Second, try to find an attached device whose name matches
* 'name'.
*/
TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
if (dev->nameunit != NULL &&
strcmp(dev->nameunit, req->dr_name) == 0) {
*devp = dev;
return (0);
}
}
/* Finally, give device enumerators a chance. */
dev = NULL;
EVENTHANDLER_INVOKE(dev_lookup, req->dr_name, &dev);
if (dev == NULL)
return (ENOENT);
*devp = dev;
return (0);
}
static bool
driver_exists(struct device *bus, const char *driver)
{
devclass_t dc;
for (dc = bus->devclass; dc != NULL; dc = dc->parent) {
if (devclass_find_driver_internal(dc, driver) != NULL)
return (true);
}
return (false);
}
static int
devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
{
struct devreq *req;
device_t dev;
int error, old;
/* Locate the device to control. */
mtx_lock(&Giant);
req = (struct devreq *)data;
switch (cmd) {
case DEV_ATTACH:
case DEV_DETACH:
case DEV_ENABLE:
case DEV_DISABLE:
case DEV_SUSPEND:
case DEV_RESUME:
case DEV_SET_DRIVER:
error = priv_check(td, PRIV_DRIVER);
if (error == 0)
error = find_device(req, &dev);
break;
default:
error = ENOTTY;
break;
}
if (error) {
mtx_unlock(&Giant);
return (error);
}
/* Perform the requested operation. */
switch (cmd) {
case DEV_ATTACH:
if (device_is_attached(dev) && (dev->flags & DF_REBID) == 0)
error = EBUSY;
else if (!device_is_enabled(dev))
error = ENXIO;
else
error = device_probe_and_attach(dev);
break;
case DEV_DETACH:
if (!device_is_attached(dev)) {
error = ENXIO;
break;
}
if (!(req->dr_flags & DEVF_FORCE_DETACH)) {
error = device_quiesce(dev);
if (error)
break;
}
error = device_detach(dev);
break;
case DEV_ENABLE:
if (device_is_enabled(dev)) {
error = EBUSY;
break;
}
/*
* If the device has been probed but not attached (e.g.
* when it has been disabled by a loader hint), just
* attach the device rather than doing a full probe.
*/
device_enable(dev);
if (device_is_alive(dev)) {
/*
* If the device was disabled via a hint, clear
* the hint.
*/
if (resource_disabled(dev->driver->name, dev->unit))
resource_unset_value(dev->driver->name,
dev->unit, "disabled");
error = device_attach(dev);
} else
error = device_probe_and_attach(dev);
break;
case DEV_DISABLE:
if (!device_is_enabled(dev)) {
error = ENXIO;
break;
}
if (!(req->dr_flags & DEVF_FORCE_DETACH)) {
error = device_quiesce(dev);
if (error)
break;
}
/*
* Force DF_FIXEDCLASS on around detach to preserve
* the existing name.
*/
old = dev->flags;
dev->flags |= DF_FIXEDCLASS;
error = device_detach(dev);
if (!(old & DF_FIXEDCLASS))
dev->flags &= ~DF_FIXEDCLASS;
if (error == 0)
device_disable(dev);
break;
case DEV_SUSPEND:
if (device_is_suspended(dev)) {
error = EBUSY;
break;
}
if (device_get_parent(dev) == NULL) {
error = EINVAL;
break;
}
error = BUS_SUSPEND_CHILD(device_get_parent(dev), dev);
break;
case DEV_RESUME:
if (!device_is_suspended(dev)) {
error = EINVAL;
break;
}
if (device_get_parent(dev) == NULL) {
error = EINVAL;
break;
}
error = BUS_RESUME_CHILD(device_get_parent(dev), dev);
break;
case DEV_SET_DRIVER: {
devclass_t dc;
char driver[128];
error = copyinstr(req->dr_data, driver, sizeof(driver), NULL);
if (error)
break;
if (driver[0] == '\0') {
error = EINVAL;
break;
}
if (dev->devclass != NULL &&
strcmp(driver, dev->devclass->name) == 0)
/* XXX: Could possibly force DF_FIXEDCLASS on? */
break;
/*
* Scan drivers for this device's bus looking for at
* least one matching driver.
*/
if (dev->parent == NULL) {
error = EINVAL;
break;
}
if (!driver_exists(dev->parent, driver)) {
error = ENOENT;
break;
}
dc = devclass_create(driver);
if (dc == NULL) {
error = ENOMEM;
break;
}
/* Detach device if necessary. */
if (device_is_attached(dev)) {
if (req->dr_flags & DEVF_SET_DRIVER_DETACH)
error = device_detach(dev);
else
error = EBUSY;
if (error)
break;
}
/* Clear any previously-fixed device class and unit. */
if (dev->flags & DF_FIXEDCLASS)
devclass_delete_device(dev->devclass, dev);
dev->flags |= DF_WILDCARD;
dev->unit = -1;
/* Force the new device class. */
error = devclass_add_device(dc, dev);
if (error)
break;
dev->flags |= DF_FIXEDCLASS;
error = device_probe_and_attach(dev);
break;
}
}
mtx_unlock(&Giant);
return (error);
}
static struct cdevsw devctl2_cdevsw = {
.d_version = D_VERSION,
.d_ioctl = devctl2_ioctl,
.d_name = "devctl2",
};
static void
devctl2_init(void)
{
make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL,
UID_ROOT, GID_WHEEL, 0600, "devctl2");
}

View File

@ -461,3 +461,31 @@ resource_disabled(const char *name, int unit)
return (0);
return (value);
}
/*
* Clear a value associated with a device by removing it from
* the kernel environment. This only removes a hint for an
* exact unit.
*/
int
resource_unset_value(const char *name, int unit, const char *resname)
{
char varname[128];
const char *retname, *retvalue;
int error, line;
size_t len;
line = 0;
error = resource_find(&line, NULL, name, &unit, resname, NULL,
&retname, NULL, NULL, NULL, NULL, &retvalue);
if (error)
return (error);
retname -= strlen("hint.");
len = retvalue - retname - 1;
if (len > sizeof(varname) - 1)
return (ENAMETOOLONG);
memcpy(varname, retname, len);
varname[len] = '\0';
return (kern_unsetenv(varname));
}

View File

@ -735,6 +735,8 @@ _zfs= zfs
.endif
SUBDIR+=${MODULES_EXTRA}
.for reject in ${WITHOUT_MODULES}
SUBDIR:= ${SUBDIR:N${reject}}
.endfor

View File

@ -6,6 +6,7 @@ SYSDIR?=${.CURDIR}/../..
.include "${SYSDIR}/conf/kern.opts.mk"
SUBDIR= if_cxgbe
SUBDIR+= if_cxl
SUBDIR+= t4_firmware
SUBDIR+= t5_firmware
SUBDIR+= ${_tom}

View File

@ -0,0 +1,11 @@
#
# $FreeBSD$
#
CXGBE= ${.CURDIR}/../../../dev/cxgbe
.PATH: ${CXGBE}
KMOD= if_cxl
SRCS= if_cxl.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,5 @@
# $FreeBSD$
# DTS files for the Raspberry Pi-B
DTS=rpi.dts
.include <bsd.dtb.mk>

View File

@ -31,6 +31,7 @@
#include <machine/_limits.h>
#include <sys/_bus_dma.h>
#include <sys/ioccom.h>
/**
* @defgroup NEWBUS newbus - a generic framework for managing devices
@ -70,14 +71,61 @@ struct u_device {
char dv_pnpinfo[128]; /**< @brief Plug and play info */
char dv_location[128]; /**< @brief Where is the device? */
uint32_t dv_devflags; /**< @brief API Flags for device */
uint16_t dv_flags; /**< @brief flags for dev date */
uint16_t dv_flags; /**< @brief flags for dev state */
device_state_t dv_state; /**< @brief State of attachment */
/* XXX more driver info? */
};
/* Flags exported via dv_flags. */
#define DF_ENABLED 0x01 /* device should be probed/attached */
#define DF_FIXEDCLASS 0x02 /* devclass specified at create time */
#define DF_WILDCARD 0x04 /* unit was originally wildcard */
#define DF_DESCMALLOCED 0x08 /* description was malloced */
#define DF_QUIET 0x10 /* don't print verbose attach message */
#define DF_DONENOMATCH 0x20 /* don't execute DEVICE_NOMATCH again */
#define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */
#define DF_REBID 0x80 /* Can rebid after attach */
#define DF_SUSPENDED 0x100 /* Device is suspended. */
/**
* @brief Device request structure used for ioctl's.
*
* Used for ioctl's on /dev/devctl2. All device ioctl's
* must have parameter definitions which begin with dr_name.
*/
struct devreq_buffer {
void *buffer;
size_t length;
};
struct devreq {
char dr_name[128];
int dr_flags; /* request-specific flags */
union {
struct devreq_buffer dru_buffer;
void *dru_data;
} dr_dru;
#define dr_buffer dr_dru.dru_buffer /* variable-sized buffer */
#define dr_data dr_dru.dru_data /* fixed-size buffer */
};
#define DEV_ATTACH _IOW('D', 1, struct devreq)
#define DEV_DETACH _IOW('D', 2, struct devreq)
#define DEV_ENABLE _IOW('D', 3, struct devreq)
#define DEV_DISABLE _IOW('D', 4, struct devreq)
#define DEV_SUSPEND _IOW('D', 5, struct devreq)
#define DEV_RESUME _IOW('D', 6, struct devreq)
#define DEV_SET_DRIVER _IOW('D', 7, struct devreq)
/* Flags for DEV_DETACH and DEV_DISABLE. */
#define DEVF_FORCE_DETACH 0x0000001
/* Flags for DEV_SET_DRIVER. */
#define DEVF_SET_DRIVER_DETACH 0x0000001 /* Detach existing driver. */
#ifdef _KERNEL
#include <sys/queue.h>
#include <sys/eventhandler.h>
#include <sys/kobj.h>
/**
@ -93,6 +141,14 @@ void devctl_notify(const char *__system, const char *__subsystem,
void devctl_queue_data_f(char *__data, int __flags);
void devctl_queue_data(char *__data);
/**
* Device name parsers. Hook to allow device enumerators to map
* scheme-specific names to a device.
*/
typedef void (*dev_lookup_fn)(void *arg, const char *name,
device_t *result);
EVENTHANDLER_DECLARE(dev_lookup, dev_lookup_fn);
/**
* @brief A device driver (included mainly for compatibility with
* FreeBSD 4.x).
@ -454,6 +510,7 @@ struct sysctl_oid *device_get_sysctl_tree(device_t dev);
int device_is_alive(device_t dev); /* did probe succeed? */
int device_is_attached(device_t dev); /* did attach succeed? */
int device_is_enabled(device_t dev);
int device_is_suspended(device_t dev);
int device_is_quiet(device_t dev);
int device_print_prettyname(device_t dev);
int device_printf(device_t dev, const char *, ...) __printflike(2, 3);
@ -517,6 +574,8 @@ int resource_set_long(const char *name, int unit, const char *resname,
long value);
int resource_set_string(const char *name, int unit, const char *resname,
const char *value);
int resource_unset_value(const char *name, int unit, const char *resname);
/*
* Functions for maintaining and checking consistency of
* bus information exported to userspace.

View File

@ -1452,22 +1452,22 @@ SYSINIT(apic_setup_io, SI_SUB_INTR, SI_ORDER_THIRD, apic_setup_io, NULL);
static int
native_lapic_ipi_wait(int delay)
{
int x, incr;
int x;
/*
* Wait delay loops for IPI to be sent. This is highly bogus
* since this is sensitive to CPU clock speed. If delay is
* Wait delay microseconds for IPI to be sent. If delay is
* -1, we wait forever.
*/
if (delay == -1) {
incr = 0;
delay = 1;
} else
incr = 1;
for (x = 0; x < delay; x += incr) {
while ((lapic->icr_lo & APIC_DELSTAT_MASK) != APIC_DELSTAT_IDLE)
ia32_pause();
return (1);
}
for (x = 0; x < delay; x += 5) {
if ((lapic->icr_lo & APIC_DELSTAT_MASK) == APIC_DELSTAT_IDLE)
return (1);
ia32_pause();
DELAY(5);
}
return (0);
}
@ -1501,9 +1501,9 @@ native_lapic_ipi_raw(register_t icrlo, u_int dest)
intr_restore(saveintr);
}
#define BEFORE_SPIN 1000000
#define BEFORE_SPIN 50000
#ifdef DETECT_DEADLOCK
#define AFTER_SPIN 1000
#define AFTER_SPIN 50
#endif
static void
@ -1514,7 +1514,7 @@ native_lapic_ipi_vectored(u_int vector, int dest)
KASSERT((vector & ~APIC_VECTOR_MASK) == 0,
("%s: invalid vector %d", __func__, vector));
icrlo = APIC_DESTMODE_PHY | APIC_TRIGMOD_EDGE;
icrlo = APIC_DESTMODE_PHY | APIC_TRIGMOD_EDGE | APIC_LEVEL_ASSERT;
/*
* IPI_STOP_HARD is just a "fake" vector used to send a NMI.
@ -1522,9 +1522,9 @@ native_lapic_ipi_vectored(u_int vector, int dest)
* the vector.
*/
if (vector == IPI_STOP_HARD)
icrlo |= APIC_DELMODE_NMI | APIC_LEVEL_ASSERT;
icrlo |= APIC_DELMODE_NMI;
else
icrlo |= vector | APIC_DELMODE_FIXED | APIC_LEVEL_DEASSERT;
icrlo |= vector | APIC_DELMODE_FIXED;
destfield = 0;
switch (dest) {
case APIC_IPI_DEST_SELF:

View File

@ -41,6 +41,7 @@
.Op Fl e Ar extras-manifest
.Op Fl f Ar filelist
.Op Fl k Ar keydir Op Fl K Ar user
.Op Fl l Ar label
.Op Fl p Ar master.passwd Op Fl g Ar group
.Op Fl s Ar size
.Ar image-file
@ -94,6 +95,8 @@ If no
.Fl K
argument is supplied then the files will be installed in the root user's
directory.
.It Fl l Ar label
Set the file system volume label.
.It Fl p Ar master.passwd Op Fl g Ar group
Install an alternate
.Ar master.passwd

View File

@ -75,7 +75,7 @@ KEYDIR=
KEYUSERS=
PASSWD=
while getopts "B:de:f:g:K:k:p:s:" opt; do
while getopts "B:de:f:g:K:k:l:p:s:" opt; do
case "$opt" in
B) BFLAG="-B ${OPTARG}" ;;
d) DEBUG=1 ;;
@ -84,6 +84,7 @@ while getopts "B:de:f:g:K:k:p:s:" opt; do
g) GROUP="${OPTARG}" ;;
K) KEYUSERS="${KEYUSERS} ${OPTARG}" ;;
k) KEYDIR="${OPTARG}" ;;
l) LABEL="${OPTARG}" ;;
p) PASSWD="${OPTARG}" ;;
s) SIZE="${OPTARG}" ;;
*) usage ;;
@ -165,13 +166,15 @@ if [ -n "${FILELIST}" ]; then
awk '
!/ type=/ { file = $1 }
/ type=/ { if ($1 == file) {print} }' >> ${manifest}
else
elif [ -n "${EXTRAS}" ]; then
# Start with all the files in BSDROOT/METALOG except those in
# one of the EXTRAS manifests.
grep -h type=file ${EXTRAS} | cut -d' ' -f1 | \
sort -u ${BSDROOT}/METALOG - | awk '
!/ type=/ { file = $1 }
/ type=/ { if ($1 != file) {print} }' >> ${manifest}
else
sort -u ${BSDROOT}/METALOG >> ${manifest}
fi
# For each extras file, add contents keys relative to the directory the
@ -228,9 +231,12 @@ if [ -n "${KEYDIR}" ]; then
done
fi
if [ -n "${LABEL}" ]; then
LABELFLAG="-o label=${LABEL}"
fi
if [ -n "${SIZE}" ]; then
SIZEFLAG="-s ${SIZE}"
fi
cd ${BSDROOT}; makefs ${DUPFLAG} -N ${DBDIR} ${SIZEFLAG} ${BFLAG} \
-t ffs -f 256 ${IMGFILE} ${manifest}
-t ffs ${LABELFLAG} -f 256 ${IMGFILE} ${manifest}

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 8, 2005
.Dd February 6, 2015
.Dt KTRDUMP 8
.Os
.Sh NAME
@ -34,9 +34,9 @@
.Sh SYNOPSIS
.Nm
.Op Fl cfqrtH
.Op Fl e Ar execfile
.Op Fl i Ar ktrfile
.Op Fl m Ar corefile
.Op Fl M Ar core
.Op Fl N Ar system
.Op Fl o Ar outfile
.Sh DESCRIPTION
The
@ -44,7 +44,7 @@ The
utility is used to dump the contents of the kernel ktr trace buffer.
.Pp
The following options are available:
.Bl -tag -width ".Fl e Ar execfile"
.Bl -tag -width ".Fl i Ar ktrfile"
.It Fl c
Print the CPU number that each entry was logged from.
.It Fl f
@ -61,11 +61,11 @@ Print the thread ID for each entry.
File containing saved ktr trace events; for more information see the
.Xr ktr 4
manual page.
.It Fl e Ar execfile
.It Fl N Ar system
The kernel image to resolve symbols from.
The default is the value returned via
.Xr getbootfile 3 .
.It Fl m Ar corefile
.It Fl M Ar core
The core file or memory image to read from.
The default is
.Pa /dev/mem .

View File

@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
#define SBUFLEN 128
#define USAGE \
"usage: ktrdump [-cfqrtH] [-e execfile] [-i ktrfile] [-m corefile] [-o outfile]\n"
"usage: ktrdump [-cfqrtH] [-i ktrfile] [-M core] [-N system] [-o outfile]\n"
static void usage(void);
@ -59,9 +59,9 @@ static struct nlist nl[] = {
};
static int cflag;
static int eflag;
static int fflag;
static int mflag;
static int Mflag;
static int Nflag;
static int qflag;
static int rflag;
static int tflag;
@ -103,16 +103,17 @@ main(int ac, char **av)
* Parse commandline arguments.
*/
out = stdout;
while ((c = getopt(ac, av, "cfqrtHe:i:m:o:")) != -1)
while ((c = getopt(ac, av, "cfqrtHe:i:m:M:N:o:")) != -1)
switch (c) {
case 'c':
cflag = 1;
break;
case 'N':
case 'e':
if (strlcpy(execfile, optarg, sizeof(execfile))
>= sizeof(execfile))
errx(1, "%s: File name too long", optarg);
eflag = 1;
Nflag = 1;
break;
case 'f':
fflag = 1;
@ -122,11 +123,12 @@ main(int ac, char **av)
if ((in = open(optarg, O_RDONLY)) == -1)
err(1, "%s", optarg);
break;
case 'M':
case 'm':
if (strlcpy(corefile, optarg, sizeof(corefile))
>= sizeof(corefile))
errx(1, "%s: File name too long", optarg);
mflag = 1;
Mflag = 1;
break;
case 'o':
if ((out = fopen(optarg, "w")) == NULL)
@ -157,8 +159,8 @@ main(int ac, char **av)
* Open our execfile and corefile, resolve needed symbols and read in
* the trace buffer.
*/
if ((kd = kvm_openfiles(eflag ? execfile : NULL,
mflag ? corefile : NULL, NULL, O_RDONLY, errbuf)) == NULL)
if ((kd = kvm_openfiles(Nflag ? execfile : NULL,
Mflag ? corefile : NULL, NULL, O_RDONLY, errbuf)) == NULL)
errx(1, "%s", errbuf);
if (kvm_nlist(kd, nl) != 0 ||
kvm_read(kd, nl[0].n_value, &version, sizeof(version)) == -1)

View File

@ -19,6 +19,7 @@ SUBDIR= adduser \
ctld \
daemon \
dconschat \
devctl \
devinfo \
digictl \
diskinfo \

View File

@ -3439,6 +3439,7 @@ struct cctl_islist_conn {
char *header_digest;
char *data_digest;
char *max_data_segment_length;;
char *offload;;
int immediate_data;
int iser;
STAILQ_ENTRY(cctl_islist_conn) links;
@ -3552,6 +3553,9 @@ cctl_islist_end_element(void *user_data, const char *name)
} else if (strcmp(name, "max_data_segment_length") == 0) {
cur_conn->max_data_segment_length = str;
str = NULL;
} else if (strcmp(name, "offload") == 0) {
cur_conn->offload = str;
str = NULL;
} else if (strcmp(name, "immediate_data") == 0) {
cur_conn->immediate_data = atoi(str);
} else if (strcmp(name, "iser") == 0) {
@ -3559,8 +3563,12 @@ cctl_islist_end_element(void *user_data, const char *name)
} else if (strcmp(name, "connection") == 0) {
islist->cur_conn = NULL;
} else if (strcmp(name, "ctlislist") == 0) {
} else
errx(1, "unknown element %s", name);
/* Nothing. */
} else {
/*
* Unknown element; ignore it for forward compatiblity.
*/
}
free(str);
}
@ -3668,6 +3676,7 @@ cctl_islist(int fd, int argc, char **argv, char *combinedopt)
printf("DataSegmentLen: %s\n", conn->max_data_segment_length);
printf("ImmediateData: %s\n", conn->immediate_data ? "Yes" : "No");
printf("iSER (RDMA): %s\n", conn->iser ? "Yes" : "No");
printf("Offload driver: %s\n", conn->offload);
printf("\n");
}
} else {

View File

@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 1, 2015
.Dd February 6, 2015
.Dt CTL.CONF 5
.Os
.Sh NAME
@ -66,7 +66,7 @@ file is:
.No target Ar name {
.Dl auth-group Ar name
.Dl portal-group Ar name
.Dl portal-group Ar name Op Ar agname
.Dl lun Ar number Ar name
.Dl lun Ar number No {
.Dl path Ar path
@ -310,12 +310,17 @@ This clause is mutually exclusive with
.Sy auth-group ;
one cannot use
both in a single target.
.It Ic portal-group Ar name
.It Ic offload Ar driver
Define iSCSI hardware offload driver to use for this target.
.It Ic portal-group Ar name Op Ar agname
Assign a previously defined portal group to the target.
The default portal group is
.Qq Ar default ,
which makes the target available
on TCP port 3260 on all configured IPv4 and IPv6 addresses.
Optional second argument specifies auth group name for connections
to this specific portal group.
If second argument is not specified, target auth group is used.
.It Ic redirect Aq Ar address
IPv4 or IPv6 address to redirect initiators to.
When configured, all initiators attempting to connect to this target

View File

@ -91,6 +91,7 @@ conf_new(void)
TAILQ_INIT(&conf->conf_luns);
TAILQ_INIT(&conf->conf_targets);
TAILQ_INIT(&conf->conf_auth_groups);
TAILQ_INIT(&conf->conf_ports);
TAILQ_INIT(&conf->conf_portal_groups);
TAILQ_INIT(&conf->conf_isns);
@ -124,6 +125,7 @@ conf_delete(struct conf *conf)
portal_group_delete(pg);
TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp)
isns_delete(is);
assert(TAILQ_EMPTY(&conf->conf_ports));
free(conf->conf_pidfile_path);
free(conf);
}
@ -609,6 +611,7 @@ portal_group_new(struct conf *conf, const char *name)
log_err(1, "calloc");
pg->pg_name = checked_strdup(name);
TAILQ_INIT(&pg->pg_portals);
TAILQ_INIT(&pg->pg_ports);
pg->pg_conf = conf;
pg->pg_tag = 0; /* Assigned later in conf_apply(). */
TAILQ_INSERT_TAIL(&conf->conf_portal_groups, pg, pg_next);
@ -620,7 +623,10 @@ void
portal_group_delete(struct portal_group *pg)
{
struct portal *portal, *tmp;
struct port *port, *tport;
TAILQ_FOREACH_SAFE(port, &pg->pg_ports, p_pgs, tport)
port_delete(port);
TAILQ_REMOVE(&pg->pg_conf->conf_portal_groups, pg, pg_next);
TAILQ_FOREACH_SAFE(portal, &pg->pg_portals, p_next, tmp)
@ -784,6 +790,7 @@ isns_do_register(struct isns *isns, int s, const char *hostname)
struct target *target;
struct portal *portal;
struct portal_group *pg;
struct port *port;
struct isns_req *req;
int res = 0;
uint32_t error;
@ -807,11 +814,14 @@ isns_do_register(struct isns *isns, int s, const char *hostname)
isns_req_add_32(req, 33, 1); /* 1 -- Target*/
if (target->t_alias != NULL)
isns_req_add_str(req, 34, target->t_alias);
pg = target->t_portal_group;
isns_req_add_32(req, 51, pg->pg_tag);
TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
isns_req_add_addr(req, 49, portal->p_ai);
isns_req_add_port(req, 50, portal->p_ai);
TAILQ_FOREACH(port, &target->t_ports, p_ts) {
if ((pg = port->p_portal_group) == NULL)
continue;
isns_req_add_32(req, 51, pg->pg_tag);
TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
isns_req_add_addr(req, 49, portal->p_ai);
isns_req_add_port(req, 50, portal->p_ai);
}
}
}
res = isns_req_send(s, req);
@ -1123,6 +1133,68 @@ valid_iscsi_name(const char *name)
return (true);
}
struct port *
port_new(struct conf *conf, struct target *target, struct portal_group *pg)
{
struct port *port;
port = calloc(1, sizeof(*port));
if (port == NULL)
log_err(1, "calloc");
asprintf(&port->p_name, "%s-%s", pg->pg_name, target->t_name);
if (port_find(conf, port->p_name) != NULL) {
log_warnx("duplicate port \"%s\"", port->p_name);
free(port);
return (NULL);
}
port->p_conf = conf;
TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
TAILQ_INSERT_TAIL(&target->t_ports, port, p_ts);
port->p_target = target;
TAILQ_INSERT_TAIL(&pg->pg_ports, port, p_pgs);
port->p_portal_group = pg;
return (port);
}
struct port *
port_find(const struct conf *conf, const char *name)
{
struct port *port;
TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
if (strcasecmp(port->p_name, name) == 0)
return (port);
}
return (NULL);
}
struct port *
port_find_in_pg(const struct portal_group *pg, const char *target)
{
struct port *port;
TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) {
if (strcasecmp(port->p_target->t_name, target) == 0)
return (port);
}
return (NULL);
}
void
port_delete(struct port *port)
{
if (port->p_portal_group)
TAILQ_REMOVE(&port->p_portal_group->pg_ports, port, p_pgs);
if (port->p_target)
TAILQ_REMOVE(&port->p_target->t_ports, port, p_ts);
TAILQ_REMOVE(&port->p_conf->conf_ports, port, p_next);
free(port->p_name);
free(port);
}
struct target *
target_new(struct conf *conf, const char *name)
{
@ -1151,6 +1223,7 @@ target_new(struct conf *conf, const char *name)
targ->t_name[i] = tolower(targ->t_name[i]);
targ->t_conf = conf;
TAILQ_INIT(&targ->t_ports);
TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
return (targ);
@ -1159,7 +1232,10 @@ target_new(struct conf *conf, const char *name)
void
target_delete(struct target *targ)
{
struct port *port, *tport;
TAILQ_FOREACH_SAFE(port, &targ->t_ports, p_ts, tport)
port_delete(port);
TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next);
free(targ->t_name);
@ -1196,11 +1272,20 @@ target_set_redirection(struct target *target, const char *addr)
return (0);
}
void
target_set_ctl_port(struct target *target, uint32_t value)
int
target_set_offload(struct target *target, const char *offload)
{
target->t_ctl_port = value;
if (target->t_offload != NULL) {
log_warnx("cannot set offload to \"%s\" for "
"target \"%s\"; already defined",
offload, target->t_name);
return (1);
}
target->t_offload = checked_strdup(offload);
return (0);
}
struct lun *
@ -1445,6 +1530,8 @@ conf_print(struct conf *conf)
fprintf(stderr, "target %s {\n", targ->t_name);
if (targ->t_alias != NULL)
fprintf(stderr, "\t alias %s\n", targ->t_alias);
if (targ->t_offload != NULL)
fprintf(stderr, "\t offload %s\n", targ->t_offload);
fprintf(stderr, "}\n");
}
}
@ -1508,6 +1595,7 @@ conf_verify(struct conf *conf)
{
struct auth_group *ag;
struct portal_group *pg;
struct port *port;
struct target *targ;
struct lun *lun;
bool found;
@ -1527,10 +1615,10 @@ conf_verify(struct conf *conf)
"default");
assert(targ->t_auth_group != NULL);
}
if (targ->t_portal_group == NULL) {
targ->t_portal_group = portal_group_find(conf,
"default");
assert(targ->t_portal_group != NULL);
if (TAILQ_EMPTY(&targ->t_ports)) {
pg = portal_group_find(conf, "default");
assert(pg != NULL);
port_new(conf, targ, pg);
}
found = false;
for (i = 0; i < MAX_LUNS; i++) {
@ -1558,20 +1646,14 @@ conf_verify(struct conf *conf)
if (pg->pg_discovery_filter == PG_FILTER_UNKNOWN)
pg->pg_discovery_filter = PG_FILTER_NONE;
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
if (targ->t_portal_group == pg)
break;
}
if (pg->pg_redirection != NULL) {
if (targ != NULL) {
if (!TAILQ_EMPTY(&pg->pg_ports)) {
if (pg->pg_redirection != NULL) {
log_debugx("portal-group \"%s\" assigned "
"to target \"%s\", but configured "
"to target, but configured "
"for redirection",
pg->pg_name, targ->t_name);
pg->pg_name);
}
pg->pg_unassigned = false;
} else if (targ != NULL) {
pg->pg_unassigned = false;
} else {
if (strcmp(pg->pg_name, "default") != 0)
log_warnx("portal-group \"%s\" not assigned "
@ -1592,6 +1674,12 @@ conf_verify(struct conf *conf)
break;
}
}
TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
if (port->p_auth_group == ag) {
found = true;
break;
}
}
TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
if (pg->pg_discovery_auth_group == ag) {
found = true;
@ -1613,10 +1701,10 @@ conf_verify(struct conf *conf)
static int
conf_apply(struct conf *oldconf, struct conf *newconf)
{
struct target *oldtarg, *newtarg, *tmptarg;
struct lun *oldlun, *newlun, *tmplun;
struct portal_group *oldpg, *newpg;
struct portal *oldp, *newp;
struct port *oldport, *newport, *tmpport;
struct isns *oldns, *newns;
pid_t otherpid;
int changed, cumulated_error = 0, error, sockbuf;
@ -1684,17 +1772,17 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
* really happen, so leave it as it is for now.
*/
/*
* First, remove any targets present in the old configuration
* First, remove any ports present in the old configuration
* and missing in the new one.
*/
TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {
newtarg = target_find(newconf, oldtarg->t_name);
if (newtarg != NULL)
TAILQ_FOREACH_SAFE(oldport, &oldconf->conf_ports, p_next, tmpport) {
newport = port_find(newconf, oldport->p_name);
if (newport != NULL)
continue;
error = kernel_port_remove(oldtarg);
error = kernel_port_remove(oldport);
if (error != 0) {
log_warnx("failed to remove target %s",
oldtarg->t_name);
log_warnx("failed to remove port %s",
oldport->p_name);
/*
* XXX: Uncomment after fixing the root cause.
*
@ -1809,21 +1897,21 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
}
/*
* Now add new targets or modify existing ones.
* Now add new ports or modify existing ones.
*/
TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) {
oldtarg = target_find(oldconf, newtarg->t_name);
TAILQ_FOREACH(newport, &newconf->conf_ports, p_next) {
oldport = port_find(oldconf, newport->p_name);
if (oldtarg == NULL)
error = kernel_port_add(newtarg);
else {
target_set_ctl_port(newtarg, oldtarg->t_ctl_port);
error = kernel_port_update(newtarg);
if (oldport == NULL) {
error = kernel_port_add(newport);
} else {
newport->p_ctl_port = oldport->p_ctl_port;
error = kernel_port_update(newport);
}
if (error != 0) {
log_warnx("failed to %s target %s",
(oldtarg == NULL) ? "add" : "update",
newtarg->t_name);
log_warnx("failed to %s port %s",
(oldport == NULL) ? "add" : "update",
newport->p_name);
/*
* XXX: Uncomment after fixing the root cause.
*

View File

@ -119,11 +119,25 @@ struct portal_group {
int pg_discovery_filter;
bool pg_unassigned;
TAILQ_HEAD(, portal) pg_portals;
TAILQ_HEAD(, port) pg_ports;
char *pg_redirection;
uint16_t pg_tag;
};
struct port {
TAILQ_ENTRY(port) p_next;
TAILQ_ENTRY(port) p_pgs;
TAILQ_ENTRY(port) p_ts;
struct conf *p_conf;
char *p_name;
struct auth_group *p_auth_group;
struct portal_group *p_portal_group;
struct target *p_target;
uint32_t p_ctl_port;
};
struct lun_option {
TAILQ_ENTRY(lun_option) lo_next;
struct lun *lo_lun;
@ -152,12 +166,11 @@ struct target {
struct conf *t_conf;
struct lun *t_luns[MAX_LUNS];
struct auth_group *t_auth_group;
struct portal_group *t_portal_group;
TAILQ_HEAD(, port) t_ports;
char *t_name;
char *t_alias;
char *t_offload;
char *t_redirection;
uint32_t t_ctl_port;
};
struct isns {
@ -172,6 +185,7 @@ struct conf {
TAILQ_HEAD(, lun) conf_luns;
TAILQ_HEAD(, target) conf_targets;
TAILQ_HEAD(, auth_group) conf_auth_groups;
TAILQ_HEAD(, port) conf_ports;
TAILQ_HEAD(, portal_group) conf_portal_groups;
TAILQ_HEAD(, isns) conf_isns;
int conf_isns_period;
@ -199,6 +213,7 @@ struct conf {
struct connection {
struct portal *conn_portal;
struct port *conn_port;
struct target *conn_target;
int conn_socket;
int conn_session_type;
@ -209,6 +224,7 @@ struct connection {
struct sockaddr_storage conn_initiator_sa;
uint32_t conn_cmdsn;
uint32_t conn_statsn;
size_t conn_data_segment_limit;
size_t conn_max_data_segment_length;
size_t conn_max_burst_length;
int conn_immediate_data;
@ -317,14 +333,21 @@ void isns_register(struct isns *isns, struct isns *oldisns);
void isns_check(struct isns *isns);
void isns_deregister(struct isns *isns);
struct port *port_new(struct conf *conf, struct target *target,
struct portal_group *pg);
struct port *port_find(const struct conf *conf, const char *name);
struct port *port_find_in_pg(const struct portal_group *pg,
const char *target);
void port_delete(struct port *port);
struct target *target_new(struct conf *conf, const char *name);
void target_delete(struct target *target);
struct target *target_find(struct conf *conf,
const char *name);
int target_set_redirection(struct target *target,
const char *addr);
void target_set_ctl_port(struct target *target,
uint32_t value);
int target_set_offload(struct target *target,
const char *offload);
struct lun *lun_new(struct conf *conf, const char *name);
void lun_delete(struct lun *lun);
@ -351,9 +374,11 @@ int kernel_lun_add(struct lun *lun);
int kernel_lun_resize(struct lun *lun);
int kernel_lun_remove(struct lun *lun);
void kernel_handoff(struct connection *conn);
int kernel_port_add(struct target *targ);
int kernel_port_update(struct target *targ);
int kernel_port_remove(struct target *targ);
void kernel_limits(const char *offload,
size_t *max_data_segment_length);
int kernel_port_add(struct port *port);
int kernel_port_update(struct port *port);
int kernel_port_remove(struct port *port);
void kernel_capsicate(void);
#ifdef ICL_KERNEL_PROXY

View File

@ -162,6 +162,7 @@ logout_new_response(struct pdu *request)
static void
discovery_add_target(struct keys *response_keys, const struct target *targ)
{
struct port *port;
struct portal *portal;
char *buf;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
@ -169,7 +170,10 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
int ret;
keys_add(response_keys, "TargetName", targ->t_name);
TAILQ_FOREACH(portal, &targ->t_portal_group->pg_portals, p_next) {
TAILQ_FOREACH(port, &targ->t_ports, p_ts) {
if (port->p_portal_group == NULL)
continue;
TAILQ_FOREACH(portal, &port->p_portal_group->pg_portals, p_next) {
ai = portal->p_ai;
ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
@ -183,13 +187,13 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
if (strcmp(hbuf, "0.0.0.0") == 0)
continue;
ret = asprintf(&buf, "%s:%s,%d", hbuf, sbuf,
targ->t_portal_group->pg_tag);
port->p_portal_group->pg_tag);
break;
case AF_INET6:
if (strcmp(hbuf, "::") == 0)
continue;
ret = asprintf(&buf, "[%s]:%s,%d", hbuf, sbuf,
targ->t_portal_group->pg_tag);
port->p_portal_group->pg_tag);
break;
default:
continue;
@ -198,19 +202,24 @@ discovery_add_target(struct keys *response_keys, const struct target *targ)
log_err(1, "asprintf");
keys_add(response_keys, "TargetAddress", buf);
free(buf);
}
}
}
static bool
discovery_target_filtered_out(const struct connection *conn,
const struct target *targ)
const struct port *port)
{
const struct auth_group *ag;
const struct portal_group *pg;
const struct target *targ;
const struct auth *auth;
int error;
ag = targ->t_auth_group;
targ = port->p_target;
ag = port->p_auth_group;
if (ag == NULL)
ag = targ->t_auth_group;
pg = conn->conn_portal->p_portal_group;
assert(pg->pg_discovery_auth_group != PG_FILTER_UNKNOWN);
@ -265,8 +274,8 @@ discovery(struct connection *conn)
{
struct pdu *request, *response;
struct keys *request_keys, *response_keys;
const struct port *port;
const struct portal_group *pg;
const struct target *targ;
const char *send_targets;
pg = conn->conn_portal->p_portal_group;
@ -284,29 +293,23 @@ discovery(struct connection *conn)
response_keys = keys_new();
if (strcmp(send_targets, "All") == 0) {
TAILQ_FOREACH(targ, &pg->pg_conf->conf_targets, t_next) {
if (targ->t_portal_group != pg) {
log_debugx("not returning target \"%s\"; "
"belongs to a different portal group",
targ->t_name);
continue;
}
if (discovery_target_filtered_out(conn, targ)) {
TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) {
if (discovery_target_filtered_out(conn, port)) {
/* Ignore this target. */
continue;
}
discovery_add_target(response_keys, targ);
discovery_add_target(response_keys, port->p_target);
}
} else {
targ = target_find(pg->pg_conf, send_targets);
if (targ == NULL) {
port = port_find_in_pg(pg, send_targets);
if (port == NULL) {
log_debugx("initiator requested information on unknown "
"target \"%s\"; returning nothing", send_targets);
} else {
if (discovery_target_filtered_out(conn, targ)) {
if (discovery_target_filtered_out(conn, port)) {
/* Ignore this target. */
} else {
discovery_add_target(response_keys, targ);
discovery_add_target(response_keys, port->p_target);
}
}
}

View File

@ -121,9 +121,10 @@ struct cctl_lun {
struct cctl_port {
uint32_t port_id;
int cfiscsi_status;
int cfiscsi_state;
char *cfiscsi_target;
uint16_t cfiscsi_portal_group_tag;
char *ctld_portal_group_name;
STAILQ_HEAD(,cctl_lun_nv) attr_list;
STAILQ_ENTRY(cctl_port) links;
};
@ -332,10 +333,13 @@ cctl_end_pelement(void *user_data, const char *name)
if (strcmp(name, "cfiscsi_target") == 0) {
cur_port->cfiscsi_target = str;
str = NULL;
} else if (strcmp(name, "cfiscsi_status") == 0) {
cur_port->cfiscsi_status = strtoul(str, NULL, 0);
} else if (strcmp(name, "cfiscsi_state") == 0) {
cur_port->cfiscsi_state = strtoul(str, NULL, 0);
} else if (strcmp(name, "cfiscsi_portal_group_tag") == 0) {
cur_port->cfiscsi_portal_group_tag = strtoul(str, NULL, 0);
} else if (strcmp(name, "ctld_portal_group_name") == 0) {
cur_port->ctld_portal_group_name = str;
str = NULL;
} else if (strcmp(name, "targ_port") == 0) {
devlist->cur_port = NULL;
} else if (strcmp(name, "ctlportlist") == 0) {
@ -373,6 +377,8 @@ conf_new_from_kernel(void)
{
struct conf *conf = NULL;
struct target *targ;
struct portal_group *pg;
struct port *cp;
struct lun *cl;
struct lun_option *lo;
struct ctl_lun_list list;
@ -496,9 +502,9 @@ conf_new_from_kernel(void)
"ignoring", (uintmax_t)port->port_id);
continue;
}
if (port->cfiscsi_status != 1) {
if (port->cfiscsi_state != 1) {
log_debugx("CTL port %ju is not active (%d); ignoring",
(uintmax_t)port->port_id, port->cfiscsi_status);
(uintmax_t)port->port_id, port->cfiscsi_state);
continue;
}
@ -514,6 +520,28 @@ conf_new_from_kernel(void)
continue;
}
}
if (port->ctld_portal_group_name == NULL)
continue;
pg = portal_group_find(conf, port->ctld_portal_group_name);
if (pg == NULL) {
#if 0
log_debugx("found new kernel portal group %s for CTL port %ld",
port->ctld_portal_group_name, port->port_id);
#endif
pg = portal_group_new(conf, port->ctld_portal_group_name);
if (pg == NULL) {
log_warnx("portal_group_new failed");
continue;
}
}
pg->pg_tag = port->cfiscsi_portal_group_tag;
cp = port_new(conf, targ, pg);
if (cp == NULL) {
log_warnx("port_new failed");
continue;
}
cp->p_ctl_port = port->port_id;
}
STAILQ_FOREACH(lun, &devlist.lun_list, links) {
@ -771,6 +799,10 @@ kernel_handoff(struct connection *conn)
sizeof(req.data.handoff.initiator_isid));
strlcpy(req.data.handoff.target_name,
conn->conn_target->t_name, sizeof(req.data.handoff.target_name));
if (conn->conn_target->t_offload != NULL) {
strlcpy(req.data.handoff.offload,
conn->conn_target->t_offload, sizeof(req.data.handoff.offload));
}
#ifdef ICL_KERNEL_PROXY
if (proxy_mode)
req.data.handoff.connection_id = conn->conn_socket;
@ -803,33 +835,68 @@ kernel_handoff(struct connection *conn)
}
}
void
kernel_limits(const char *offload, size_t *max_data_segment_length)
{
struct ctl_iscsi req;
bzero(&req, sizeof(req));
req.type = CTL_ISCSI_LIMITS;
if (offload != NULL) {
strlcpy(req.data.limits.offload, offload,
sizeof(req.data.limits.offload));
}
if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
log_err(1, "error issuing CTL_ISCSI ioctl; "
"dropping connection");
}
if (req.status != CTL_ISCSI_OK) {
log_errx(1, "error returned from CTL iSCSI limits request: "
"%s; dropping connection", req.error_str);
}
*max_data_segment_length = req.data.limits.data_segment_limit;
if (offload != NULL) {
log_debugx("MaxRecvDataSegment kernel limit for offload "
"\"%s\" is %zd", offload, *max_data_segment_length);
} else {
log_debugx("MaxRecvDataSegment kernel limit is %zd",
*max_data_segment_length);
}
}
int
kernel_port_add(struct target *targ)
kernel_port_add(struct port *port)
{
struct ctl_port_entry entry;
struct ctl_req req;
struct ctl_lun_map lm;
struct target *targ = port->p_target;
struct portal_group *pg = port->p_portal_group;
char tagstr[16];
int error, i;
int error, i, n;
/* Create iSCSI port. */
bzero(&req, sizeof(req));
strlcpy(req.driver, "iscsi", sizeof(req.driver));
req.reqtype = CTL_REQ_CREATE;
req.num_args = 4;
req.args = malloc(req.num_args * sizeof(*req.args));
req.args[0].namelen = sizeof("port_id");
req.args[0].name = __DECONST(char *, "port_id");
req.args[0].vallen = sizeof(targ->t_ctl_port);
req.args[0].value = &targ->t_ctl_port;
req.args[0].flags = CTL_BEARG_WR;
str_arg(&req.args[1], "cfiscsi_target", targ->t_name);
snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
str_arg(&req.args[2], "cfiscsi_portal_group_tag", tagstr);
n = 0;
req.args[n].namelen = sizeof("port_id");
req.args[n].name = __DECONST(char *, "port_id");
req.args[n].vallen = sizeof(port->p_ctl_port);
req.args[n].value = &port->p_ctl_port;
req.args[n++].flags = CTL_BEARG_WR;
str_arg(&req.args[n++], "cfiscsi_target", targ->t_name);
snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
str_arg(&req.args[n++], "cfiscsi_portal_group_tag", tagstr);
if (targ->t_alias)
str_arg(&req.args[3], "cfiscsi_target_alias", targ->t_alias);
else
req.num_args--;
str_arg(&req.args[n++], "cfiscsi_target_alias", targ->t_alias);
str_arg(&req.args[n++], "ctld_portal_group_name", pg->pg_name);
req.num_args = n;
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);
free(req.args);
if (error != 0) {
@ -848,7 +915,7 @@ kernel_port_add(struct target *targ)
}
/* Explicitly enable mapping to block any access except allowed. */
lm.port = targ->t_ctl_port;
lm.port = port->p_ctl_port;
lm.plun = UINT32_MAX;
lm.lun = 0;
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
@ -859,7 +926,7 @@ kernel_port_add(struct target *targ)
for (i = 0; i < MAX_LUNS; i++) {
if (targ->t_luns[i] == NULL)
continue;
lm.port = targ->t_ctl_port;
lm.port = port->p_ctl_port;
lm.plun = i;
lm.lun = targ->t_luns[i]->l_ctl_lun;
error = ioctl(ctl_fd, CTL_LUN_MAP, &lm);
@ -869,7 +936,7 @@ kernel_port_add(struct target *targ)
/* Enable port */
bzero(&entry, sizeof(entry));
entry.targ_port = targ->t_ctl_port;
entry.targ_port = port->p_ctl_port;
error = ioctl(ctl_fd, CTL_ENABLE_PORT, &entry);
if (error != 0) {
log_warn("CTL_ENABLE_PORT ioctl failed");
@ -880,14 +947,15 @@ kernel_port_add(struct target *targ)
}
int
kernel_port_update(struct target *targ)
kernel_port_update(struct port *port)
{
struct ctl_lun_map lm;
struct target *targ = port->p_target;
int error, i;
/* Map configured LUNs and unmap others */
for (i = 0; i < MAX_LUNS; i++) {
lm.port = targ->t_ctl_port;
lm.port = port->p_ctl_port;
lm.plun = i;
if (targ->t_luns[i] == NULL)
lm.lun = UINT32_MAX;
@ -901,10 +969,12 @@ kernel_port_update(struct target *targ)
}
int
kernel_port_remove(struct target *targ)
kernel_port_remove(struct port *port)
{
struct ctl_req req;
char tagstr[16];
struct target *targ = port->p_target;
struct portal_group *pg = port->p_portal_group;
int error;
bzero(&req, sizeof(req));
@ -913,7 +983,7 @@ kernel_port_remove(struct target *targ)
req.num_args = 2;
req.args = malloc(req.num_args * sizeof(*req.args));
str_arg(&req.args[0], "cfiscsi_target", targ->t_name);
snprintf(tagstr, sizeof(tagstr), "%d", targ->t_portal_group->pg_tag);
snprintf(tagstr, sizeof(tagstr), "%d", pg->pg_tag);
str_arg(&req.args[1], "cfiscsi_portal_group_tag", tagstr);
error = ioctl(ctl_fd, CTL_PORT_REQ, &req);

View File

@ -453,7 +453,8 @@ static void
login_negotiate_key(struct pdu *request, const char *name,
const char *value, bool skipped_security, struct keys *response_keys)
{
int which, tmp;
int which;
size_t tmp;
struct connection *conn;
conn = request->pdu_connection;
@ -552,13 +553,13 @@ login_negotiate_key(struct pdu *request, const char *name,
log_errx(1, "received invalid "
"MaxRecvDataSegmentLength");
}
if (tmp > MAX_DATA_SEGMENT_LENGTH) {
if (tmp > conn->conn_data_segment_limit) {
log_debugx("capping MaxRecvDataSegmentLength "
"from %d to %d", tmp, MAX_DATA_SEGMENT_LENGTH);
tmp = MAX_DATA_SEGMENT_LENGTH;
"from %zd to %zd", tmp, conn->conn_data_segment_limit);
tmp = conn->conn_data_segment_limit;
}
conn->conn_max_data_segment_length = tmp;
keys_add_int(response_keys, name, MAX_DATA_SEGMENT_LENGTH);
keys_add_int(response_keys, name, tmp);
} else if (strcmp(name, "MaxBurstLength") == 0) {
tmp = strtoul(value, NULL, 10);
if (tmp <= 0) {
@ -566,7 +567,7 @@ login_negotiate_key(struct pdu *request, const char *name,
log_errx(1, "received invalid MaxBurstLength");
}
if (tmp > MAX_BURST_LENGTH) {
log_debugx("capping MaxBurstLength from %d to %d",
log_debugx("capping MaxBurstLength from %zd to %d",
tmp, MAX_BURST_LENGTH);
tmp = MAX_BURST_LENGTH;
}
@ -579,10 +580,10 @@ login_negotiate_key(struct pdu *request, const char *name,
log_errx(1, "received invalid "
"FirstBurstLength");
}
if (tmp > MAX_DATA_SEGMENT_LENGTH) {
log_debugx("capping FirstBurstLength from %d to %d",
tmp, MAX_DATA_SEGMENT_LENGTH);
tmp = MAX_DATA_SEGMENT_LENGTH;
if (tmp > conn->conn_data_segment_limit) {
log_debugx("capping FirstBurstLength from %zd to %zd",
tmp, conn->conn_data_segment_limit);
tmp = conn->conn_data_segment_limit;
}
/*
* We don't pass the value to the kernel; it only enforces
@ -680,6 +681,18 @@ login_negotiate(struct connection *conn, struct pdu *request)
int i;
bool redirected, skipped_security;
if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
/*
* Query the kernel for MaxDataSegmentLength it can handle.
* In case of offload, it depends on hardware capabilities.
*/
assert(conn->conn_target != NULL);
kernel_limits(conn->conn_target->t_offload,
&conn->conn_data_segment_limit);
} else {
conn->conn_data_segment_limit = MAX_DATA_SEGMENT_LENGTH;
}
if (request == NULL) {
log_debugx("beginning operational parameter negotiation; "
"waiting for Login PDU");
@ -827,19 +840,22 @@ login(struct connection *conn)
log_errx(1, "received Login PDU without TargetName");
}
conn->conn_target = target_find(pg->pg_conf, target_name);
if (conn->conn_target == NULL) {
conn->conn_port = port_find_in_pg(pg, target_name);
if (conn->conn_port == NULL) {
login_send_error(request, 0x02, 0x03);
log_errx(1, "requested target \"%s\" not found",
target_name);
}
conn->conn_target = conn->conn_port->p_target;
}
/*
* At this point we know what kind of authentication we need.
*/
if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
ag = conn->conn_target->t_auth_group;
ag = conn->conn_port->p_auth_group;
if (ag == NULL)
ag = conn->conn_target->t_auth_group;
if (ag->ag_name != NULL) {
log_debugx("initiator requests to connect "
"to target \"%s\"; auth-group \"%s\"",

View File

@ -60,7 +60,7 @@ extern void yyrestart(FILE *);
%token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
%token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP DISCOVERY_FILTER
%token INITIATOR_NAME INITIATOR_PORTAL ISNS_SERVER ISNS_PERIOD ISNS_TIMEOUT
%token LISTEN LISTEN_ISER LUN MAXPROC OPENING_BRACKET OPTION
%token LISTEN LISTEN_ISER LUN MAXPROC OFFLOAD OPENING_BRACKET OPTION
%token PATH PIDFILE PORTAL_GROUP REDIRECT SEMICOLON SERIAL SIZE STR
%token TARGET TIMEOUT
@ -463,6 +463,8 @@ target_entry:
|
target_initiator_portal
|
target_offload
|
target_portal_group
|
target_redirect
@ -652,21 +654,69 @@ target_initiator_portal: INITIATOR_PORTAL STR
}
;
target_portal_group: PORTAL_GROUP STR
target_offload: OFFLOAD STR
{
if (target->t_portal_group != NULL) {
log_warnx("portal-group for target \"%s\" "
"specified more than once", target->t_name);
int error;
error = target_set_offload(target, $2);
free($2);
if (error != 0)
return (1);
}
;
target_portal_group: PORTAL_GROUP STR STR
{
struct portal_group *tpg;
struct auth_group *tag;
struct port *tp;
tpg = portal_group_find(conf, $2);
if (tpg == NULL) {
log_warnx("unknown portal-group \"%s\" for target "
"\"%s\"", $2, target->t_name);
free($2);
free($3);
return (1);
}
tag = auth_group_find(conf, $3);
if (tag == NULL) {
log_warnx("unknown auth-group \"%s\" for target "
"\"%s\"", $3, target->t_name);
free($2);
free($3);
return (1);
}
tp = port_new(conf, target, tpg);
if (tp == NULL) {
log_warnx("can't link portal-group \"%s\" to target "
"\"%s\"", $2, target->t_name);
free($2);
return (1);
}
target->t_portal_group = portal_group_find(conf, $2);
if (target->t_portal_group == NULL) {
tp->p_auth_group = tag;
free($2);
free($3);
}
| PORTAL_GROUP STR
{
struct portal_group *tpg;
struct port *tp;
tpg = portal_group_find(conf, $2);
if (tpg == NULL) {
log_warnx("unknown portal-group \"%s\" for target "
"\"%s\"", $2, target->t_name);
free($2);
return (1);
}
tp = port_new(conf, target, tpg);
if (tp == NULL) {
log_warnx("can't link portal-group \"%s\" to target "
"\"%s\"", $2, target->t_name);
free($2);
return (1);
}
free($2);
}
;

View File

@ -65,6 +65,7 @@ listen { return LISTEN; }
listen-iser { return LISTEN_ISER; }
lun { return LUN; }
maxproc { return MAXPROC; }
offload { return OFFLOAD; }
option { return OPTION; }
path { return PATH; }
pidfile { return PIDFILE; }

9
usr.sbin/devctl/Makefile Normal file
View File

@ -0,0 +1,9 @@
# $FreeBSD$
PROG= devctl
MAN= devctl.8
MAN=
LIBADD= devctl
.include <bsd.prog.mk>

137
usr.sbin/devctl/devctl.8 Normal file
View File

@ -0,0 +1,137 @@
.\"
.\" Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd February 5, 2015
.Dt DEVCTL 8
.Os
.Sh NAME
.Nm devctl
.Nd device control utility
.Sh SYNOPSIS
.Nm
.Cm attach
.Ar device
.Nm
.Cm detach
.Op Fl f
.Ar device
.Nm
.Cm disable
.Op Fl f
.Ar device
.Nm
.Cm enable
.Ar device
.Nm
.Cm suspend
.Ar device
.Nm
.Cm resume
.Ar device
.Nm
.Cm set driver
.Op Fl f
.Ar device driver
.Sh DESCRIPTION
The
.Nm
utility adjusts the state of individual devices in the kernel's
internal device hierarchy.
Each invocation of
.Nm
consists of a single command followed by command-specific arguments.
Each command operates on a single device specified via the
.Ar device
argument.
The
.Ar device
may be specified either as the name of an existing device or as a
bus-specific address.
More details on supported address formats can be found in
.Xr devctl 3 .
.Pp
The following commands are supported:
.Bl -tag -width indent
.It Cm attach Ar device
Force the kernel to re-probe the device.
If a suitable driver is found,
it is attached to the device.
.It Xo Cm detach
.Op Fl f
.Ar device
.Xc
Detach the device from its current device driver.
If the
.Fl f
flag is specified,
the device driver will be detached even if the device is busy.
.It Xo Cm disable
.Op Fl f
.Ar device
.Xc
Disable a device.
If the device is currently attached to a device driver,
the device driver will be detached from the device,
but the device will retain its current name.
If the
.Fl f
flag is specified,
the device driver will be detached even if the device is busy.
.It Cm enable Ar device
Enable a device.
The device will probe and attach if a suitable device driver is found.
Note that this can re-enable a device disabled at boot time via a
loader tunable.
.It Cm suspend Ar device
Suspend a device.
This may include placing the device in a reduced power state.
.It Cm resume device
Resume a suspended device to a fully working state.
.It Xo Cm set driver
.Op Fl f
.Ar device driver
.Xc
Force the device to use a device driver named
.Ar driver .
If the device is already attached to a device driver and the
.Fl f
flag is specified,
the device will be detached from its current device driver before it is
attached to the new device driver.
If the device is already attached to a device driver and the
.Fl f
flag is not specified,
the device will not be changed.
.El
.Sh SEE ALSO
.Xr devctl 3 ,
.Xr devinfo 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Fx 11.0 .

282
usr.sbin/devctl/devctl.c Normal file
View File

@ -0,0 +1,282 @@
/*-
* Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/linker_set.h>
#include <devctl.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
struct devctl_command {
const char *name;
int (*handler)(int ac, char **av);
};
#define DEVCTL_DATASET(name) devctl_ ## name ## _table
#define DEVCTL_COMMAND(set, name, function) \
static struct devctl_command function ## _devctl_command = \
{ #name, function }; \
DATA_SET(DEVCTL_DATASET(set), function ## _devctl_command)
#define DEVCTL_TABLE(set, name) \
SET_DECLARE(DEVCTL_DATASET(name), struct devctl_command); \
\
static int \
devctl_ ## name ## _table_handler(int ac, char **av) \
{ \
return (devctl_table_handler(SET_BEGIN(DEVCTL_DATASET(name)), \
SET_LIMIT(DEVCTL_DATASET(name)), ac, av)); \
} \
DEVCTL_COMMAND(set, name, devctl_ ## name ## _table_handler)
static int devctl_table_handler(struct devctl_command **start,
struct devctl_command **end, int ac, char **av);
SET_DECLARE(DEVCTL_DATASET(top), struct devctl_command);
DEVCTL_TABLE(top, set);
static void
usage(void)
{
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: devctl attach device",
" devctl detach [-f] device",
" devctl disable [-f] device",
" devctl enable device",
" devctl suspend device",
" devctl resume device",
" devctl set driver [-f] device driver");
exit(1);
}
static int
devctl_table_handler(struct devctl_command **start,
struct devctl_command **end, int ac, char **av)
{
struct devctl_command **cmd;
if (ac < 2) {
warnx("The %s command requires a sub-command.", av[0]);
return (EINVAL);
}
for (cmd = start; cmd < end; cmd++) {
if (strcmp((*cmd)->name, av[1]) == 0)
return ((*cmd)->handler(ac - 1, av + 1));
}
warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
return (ENOENT);
}
static int
help(int ac __unused, char **av __unused)
{
usage();
return (0);
}
DEVCTL_COMMAND(top, help, help);
static int
attach(int ac, char **av)
{
if (ac != 2)
usage();
if (devctl_attach(av[1]) < 0)
err(1, "Failed to attach %s", av[1]);
return (0);
}
DEVCTL_COMMAND(top, attach, attach);
static void
detach_usage(void)
{
fprintf(stderr, "usage: devctl detach [-f] device\n");
exit(1);
}
static int
detach(int ac, char **av)
{
bool force;
int ch;
force = false;
while ((ch = getopt(ac, av, "f")) != -1)
switch (ch) {
case 'f':
force = true;
break;
default:
detach_usage();
}
ac -= optind;
av += optind;
if (ac != 1)
detach_usage();
if (devctl_detach(av[0], force) < 0)
err(1, "Failed to detach %s", av[0]);
return (0);
}
DEVCTL_COMMAND(top, detach, detach);
static void
disable_usage(void)
{
fprintf(stderr, "usage: devctl disable [-f] device\n");
exit(1);
}
static int
disable(int ac, char **av)
{
bool force;
int ch;
force = false;
while ((ch = getopt(ac, av, "f")) != -1)
switch (ch) {
case 'f':
force = true;
break;
default:
disable_usage();
}
ac -= optind;
av += optind;
if (ac != 1)
disable_usage();
if (devctl_disable(av[0], force) < 0)
err(1, "Failed to disable %s", av[0]);
return (0);
}
DEVCTL_COMMAND(top, disable, disable);
static int
enable(int ac, char **av)
{
if (ac != 2)
usage();
if (devctl_enable(av[1]) < 0)
err(1, "Failed to enable %s", av[1]);
return (0);
}
DEVCTL_COMMAND(top, enable, enable);
static int
suspend(int ac, char **av)
{
if (ac != 2)
usage();
if (devctl_suspend(av[1]) < 0)
err(1, "Failed to suspend %s", av[1]);
return (0);
}
DEVCTL_COMMAND(top, suspend, suspend);
static int
resume(int ac, char **av)
{
if (ac != 2)
usage();
if (devctl_resume(av[1]) < 0)
err(1, "Failed to resume %s", av[1]);
return (0);
}
DEVCTL_COMMAND(top, resume, resume);
static void
set_driver_usage(void)
{
fprintf(stderr, "usage: devctl set driver [-f] device driver\n");
exit(1);
}
static int
set_driver(int ac, char **av)
{
bool force;
int ch;
force = false;
while ((ch = getopt(ac, av, "f")) != -1)
switch (ch) {
case 'f':
force = true;
break;
default:
set_driver_usage();
}
ac -= optind;
av += optind;
if (ac != 2)
set_driver_usage();
if (devctl_set_driver(av[0], av[1], force) < 0)
err(1, "Failed to set %s driver to %s", av[0], av[1]);
return (0);
}
DEVCTL_COMMAND(set, driver, set_driver);
int
main(int ac, char *av[])
{
struct devctl_command **cmd;
if (ac == 1)
usage();
ac--;
av++;
SET_FOREACH(cmd, DEVCTL_DATASET(top)) {
if (strcmp((*cmd)->name, av[0]) == 0) {
if ((*cmd)->handler(ac, av) != 0)
return (1);
else
return (0);
}
}
warnx("Unknown command %s.", av[0]);
return (1);
}

View File

@ -146,6 +146,10 @@ print_device(struct devinfo_dev *dev, void *arg)
printf(" pnpinfo %s", dev->dd_pnpinfo);
if (vflag && *dev->dd_location)
printf(" at %s", dev->dd_location);
if (!(dev->dd_flags & DF_ENABLED))
printf(" (disabled)");
else if (dev->dd_flags & DF_SUSPENDED)
printf(" (suspended)");
printf("\n");
if (rflag) {
ia.indent = indent + 4;

View File

@ -2828,18 +2828,27 @@ Kernel updates have been installed. Please reboot and run
grep -E '^[^|]+\|d\|' > INDEX-NEW
install_from_index INDEX-NEW || return 1
# Install new runtime linker
grep -vE '^/boot/' $1/INDEX-NEW |
grep -vE '^[^|]+\|d\|' |
grep -E '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' > INDEX-NEW
install_from_index INDEX-NEW || return 1
# Install new shared libraries next
grep -vE '^/boot/' $1/INDEX-NEW |
grep -vE '^[^|]+\|d\|' |
grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' |
grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW
install_from_index INDEX-NEW || return 1
# Deal with everything else
grep -vE '^/boot/' $1/INDEX-OLD |
grep -vE '^[^|]+\|d\|' |
grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' |
grep -vE '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-OLD
grep -vE '^/boot/' $1/INDEX-NEW |
grep -vE '^[^|]+\|d\|' |
grep -vE '^/libexec/ld-elf[^|]*\.so\.[0-9]+\|' |
grep -vE '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW
install_from_index INDEX-NEW || return 1
install_delete INDEX-OLD INDEX-NEW || return 1

View File

@ -112,6 +112,12 @@ next_command(struct cfjail *j)
if (!bool_param(j->intparams[IP_MOUNT_FDESCFS]))
continue;
j->comstring = &dummystring;
break;
case IP_MOUNT_PROCFS:
if (!bool_param(j->intparams[IP_MOUNT_PROCFS]))
continue;
j->comstring = &dummystring;
break;
case IP__OP:
case IP_STOP_TIMEOUT:
j->comstring = &dummystring;
@ -528,6 +534,32 @@ run_command(struct cfjail *j)
}
break;
case IP_MOUNT_PROCFS:
argv = alloca(7 * sizeof(char *));
path = string_param(j->intparams[KP_PATH]);
if (path == NULL) {
jail_warnx(j, "mount.procfs: no path");
return -1;
}
devpath = alloca(strlen(path) + 6);
sprintf(devpath, "%s/proc", path);
if (check_path(j, "mount.procfs", devpath, 0,
down ? "procfs" : NULL) < 0)
return -1;
if (down) {
argv[0] = "/sbin/umount";
argv[1] = devpath;
argv[2] = NULL;
} else {
argv[0] = _PATH_MOUNT;
argv[1] = "-t";
argv[2] = "procfs";
argv[3] = ".";
argv[4] = devpath;
argv[5] = NULL;
}
break;
case IP_COMMAND:
if (j->name != NULL)
goto default_command;

View File

@ -84,6 +84,7 @@ static const struct ipspec intparams[] = {
[IP_MOUNT] = {"mount", PF_INTERNAL | PF_REV},
[IP_MOUNT_DEVFS] = {"mount.devfs", PF_INTERNAL | PF_BOOL},
[IP_MOUNT_FDESCFS] = {"mount.fdescfs", PF_INTERNAL | PF_BOOL},
[IP_MOUNT_PROCFS] = {"mount.procfs", PF_INTERNAL | PF_BOOL},
[IP_MOUNT_FSTAB] = {"mount.fstab", PF_INTERNAL},
[IP_STOP_TIMEOUT] = {"stop.timeout", PF_INTERNAL | PF_INT},
[IP_VNET_INTERFACE] = {"vnet.interface", PF_INTERNAL},

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 28, 2015
.Dd February 6, 2015
.Dt JAIL 8
.Os
.Sh NAME
@ -753,6 +753,12 @@ Mount a
filesystem on the chrooted
.Pa /dev/fd
directory.
.It Va mount.procfs
Mount a
.Xr procfs 5
filesystem on the chrooted
.Pa /proc
directory.
.It Va allow.dying
Allow making changes to a
.Va dying
@ -1207,6 +1213,7 @@ environment of the first jail.
.Xr jls 8 ,
.Xr mount 8 ,
.Xr named 8 ,
.Xr procfs 5 ,
.Xr reboot 8 ,
.Xr rpcbind 8 ,
.Xr sendmail 8 ,

View File

@ -93,6 +93,7 @@ static const enum intparam startcommands[] = {
IP__MOUNT_FROM_FSTAB,
IP_MOUNT_DEVFS,
IP_MOUNT_FDESCFS,
IP_MOUNT_PROCFS,
IP_EXEC_PRESTART,
IP__OP,
IP_VNET_INTERFACE,
@ -109,6 +110,7 @@ static const enum intparam stopcommands[] = {
IP_STOP_TIMEOUT,
IP__OP,
IP_EXEC_POSTSTOP,
IP_MOUNT_PROCFS,
IP_MOUNT_FDESCFS,
IP_MOUNT_DEVFS,
IP__MOUNT_FROM_FSTAB,

View File

@ -96,6 +96,7 @@ enum intparam {
IP_MOUNT, /* Mount points in fstab(5) form */
IP_MOUNT_DEVFS, /* Mount /dev under prison root */
IP_MOUNT_FDESCFS, /* Mount /dev/fd under prison root */
IP_MOUNT_PROCFS, /* Mount /proc under prison root */
IP_MOUNT_FSTAB, /* A standard fstab(5) file */
IP_STOP_TIMEOUT, /* Time to wait after sending SIGTERM */
IP_VNET_INTERFACE, /* Assign interface(s) to vnet jail */