Merge ^/head r340368 through r340426.

This commit is contained in:
Dimitry Andric 2018-11-14 06:46:44 +00:00
commit 6149ed01a1
105 changed files with 2362 additions and 1689 deletions

View File

@ -1287,7 +1287,7 @@ ITOOLS+=makewhatis
#
# Non-base distributions produced by the base system
EXTRA_DISTRIBUTIONS= doc
EXTRA_DISTRIBUTIONS=
.if defined(LIBCOMPAT)
EXTRA_DISTRIBUTIONS+= lib${libcompat}
.endif
@ -1297,7 +1297,7 @@ EXTRA_DISTRIBUTIONS+= tests
DEBUG_DISTRIBUTIONS=
.if ${MK_DEBUG_FILES} != "no"
DEBUG_DISTRIBUTIONS+= base ${EXTRA_DISTRIBUTIONS:S,doc,,:S,tests,,}
DEBUG_DISTRIBUTIONS+= base ${EXTRA_DISTRIBUTIONS:S,tests,,}
.endif
MTREE_MAGIC?= mtree 2.0

View File

@ -17,7 +17,7 @@ LIB32CPUFLAGS= -march=${TARGET_CPUTYPE}
.if ${WANT_COMPILER_TYPE} == gcc || \
(defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc)
.else
LIB32CPUFLAGS+= -target x86_64-unknown-freebsd12.0
LIB32CPUFLAGS+= -target x86_64-unknown-freebsd13.0
.endif
LIB32CPUFLAGS+= -m32
LIB32WMAKEENV= MACHINE=i386 MACHINE_ARCH=i386 \
@ -49,9 +49,9 @@ LIB32CPUFLAGS= -march=${TARGET_CPUTYPE}
.endif
.else
.if ${TARGET_ARCH:Mmips64el*} != ""
LIB32CPUFLAGS= -target mipsel-unknown-freebsd12.0
LIB32CPUFLAGS= -target mipsel-unknown-freebsd13.0
.else
LIB32CPUFLAGS= -target mips-unknown-freebsd12.0
LIB32CPUFLAGS= -target mips-unknown-freebsd13.0
.endif
.endif
LIB32CPUFLAGS+= -mabi=32

View File

@ -42,7 +42,7 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \
libdevctl \
libdevinfo \
libdevstat \
${_libdl} \
libdl \
libdwarf \
libedit \
libelftc \
@ -193,10 +193,6 @@ _libproc= libproc
_librtld_db= librtld_db
.endif
.if defined(LINKER_FEATURES) && ${LINKER_FEATURES:Mfilter}
_libdl= libdl
.endif
SUBDIR.${MK_OPENSSL}+= libmp
SUBDIR.${MK_PMC}+= libpmc libpmcstat
SUBDIR.${MK_RADIUS_SUPPORT}+= libradius

View File

@ -32,10 +32,27 @@ typedef void (*crt_func)(void);
extern void *__dso_handle __hidden;
#ifdef SHARED
void *__dso_handle = &__dso_handle;
#else
#ifndef SHARED
void *__dso_handle = 0;
#else
void *__dso_handle = &__dso_handle;
void __cxa_finalize(void *) __weak_symbol;
/*
* Call __cxa_finalize with the dso handle in shared objects.
* When we have ctors/dtors call from the dtor handler before calling
* any dtors, otherwise use a destructor.
*/
#ifndef HAVE_CTORS
__attribute__((destructor))
#endif
static void
run_cxa_finalize(void)
{
if (__cxa_finalize != NULL)
__cxa_finalize(__dso_handle);
}
#endif
/*
@ -58,6 +75,10 @@ __do_global_dtors_aux(void)
crt_func fn;
int n;
#ifdef SHARED
run_cxa_finalize();
#endif
for (n = 1;; n++) {
fn = __DTOR_LIST__[n];
if (fn == (crt_func)0 || fn == (crt_func)-1)

View File

@ -31,6 +31,9 @@ FBSD_1.4 {
FBSD_1.5 {
} FBSD_1.4;
# This version was first added to 13.0-current.
FBSD_1.6 {
} FBSD_1.5;
# This is our private namespace. Any global interfaces that are
# strictly for use only by other FreeBSD applications and libraries
@ -39,4 +42,4 @@ FBSD_1.5 {
#
# Please do NOT increment the version of this namespace.
FBSDprivate_1.0 {
} FBSD_1.5;
} FBSD_1.6;

View File

@ -3,6 +3,7 @@
.include <src.opts.mk>
SUBDIR= cap_dns
SUBDIR+= cap_fileargs
SUBDIR+= cap_grp
SUBDIR+= cap_pwd
SUBDIR+= cap_random

View File

@ -0,0 +1,35 @@
# $FreeBSD$
SHLIBDIR?= /lib/casper
.include <src.opts.mk>
PACKAGE=libcasper
SHLIB_MAJOR= 1
INCSDIR?= ${INCLUDEDIR}/casper
.if ${MK_CASPER} != "no"
SHLIB= cap_fileargs
SRCS= cap_fileargs.c
.endif
INCS= cap_fileargs.h
LIBADD= nv
CFLAGS+=-I${.CURDIR}
MAN+= cap_fileargs.3
MLINKS+=cap_fileargs.3 libcap_fileargs.3
MLINKS+=cap_fileargs.3 fileargs_cinit.3
MLINKS+=cap_fileargs.3 fileargs_cinitnv.3
MLINKS+=cap_fileargs.3 fileargs_fopen.3
MLINKS+=cap_fileargs.3 fileargs_free.3
MLINKS+=cap_fileargs.3 fileargs_init.3
MLINKS+=cap_fileargs.3 fileargs_initnv.3
MLINKS+=cap_fileargs.3 fileargs_open.3
.include <bsd.lib.mk>

View File

@ -0,0 +1,241 @@
.\" Copyright (c) 2018 Mariusz Zaborski <oshogbo@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 AUTHORS 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 AUTHORS 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 November 12, 2018
.Dt CAP_FILEARGS 3
.Os
.Sh NAME
.Nm fileargs_cinit ,
.Nm fileargs_cinitnv ,
.Nm fileargs_init ,
.Nm fileargs_initnv ,
.Nm fileargs_free ,
.Nm fileargs_open ,
.Nm fileargs_fopen
.Nd "library for handling files in capability mode"
.Sh LIBRARY
.Lb libcap_fileargs
.Sh SYNOPSIS
.In sys/nv.h
.In libcasper.h
.In casper/cap_fileargs.h
.Ft "fileargs_t *"
.Fn fileargs_init "int argc" "char *argv[]" "int flags" "mode_t mode" "cap_rights_t *rightsp"
.Ft "fileargs_t *"
.Fn fileargs_cinit "cap_channel_t *cas" "int argc" "char *argv[]" "int flags" "mode_t mode" "cap_rights_t *rightsp"
.Ft "fileargs_t *"
.Fn fileargs_cinitnv "cap_channel_t *cas" "nvlist_t *limits"
.Ft "fileargs_t *"
.Fn fileargs_initnv "nvlist_t *limits"
.Ft "void"
.Fn fileargs_free "fileargs_t *fa"
.Ft "int"
.Fn fileargs_open "fileargs_t *fa" "const char *name"
.Ft "FILE *"
.Fn fileargs_fopen "fileargs_t *fa" "const char *name" "const char *mode"
.Sh DESCRIPTION
The library is used to simplify Capsicumizing a tools that are using file system.
Idea behind the library is that we are passing a remaining
.Fa argc
and
.Fa argv
which contains a list of files that should be open for this program.
The library will create a service that will serve those files.
.Pp
The function
.Fn fileargs_init
create a service to the
.Nm system.fileargs .
The
.Fa argv
contains a list of files that should be opened.
The argument can be set to
.Dv NULL
which will not create a service and all files will be prohibited to be opened.
The
.Fa argc
argument contains a number of passed files.
The
.Fa flags
argument limits opened files for either execution or reading and/or writing.
The
.Fa mode
argument tells which what mode file should be created if the
.Dv O_CREATE
flag is present .
For more details of the
.Fa flags
and
.Fa mode
arguments see
.Xr open 2 .
The
.Fa rightsp
argument contains a list of the capability rights which file should be limited to.
For more details of the capability rights see
.Xr cap_rights_init 3 .
.Pp
The function
.Fn fileargs_cinit
is equivalent to
.Fn fileargs_init
except that the connection to the Casper needs to be provided.
.Pp
The functions
.Fn fileargs_ininv
and
.Fn fileargs_cininv
are respectively equivalent to
.Fn fileargs_init
and
.Fn fileargs_cinit
expect that all arguments all provided as
.Xr nvlist 9 .
For details see
.Sx LIMITS .
.Pp
The
.Fa fileargs_free
close connection to the
.Nm system.filerags
service and free are structures.
The function handle
.Dv NULL
argument.
.Pp
The functions
.Fn fileargs_open
and
.Fn fileargs_fopen
are respectively equivalent to
.Xr open 2
and
.Xr fopen 3
expect that all arguments are fetched from the
.Va fileargs_t
structure.
.Sh LIMITS
This section describe which values and types should be used to pass arguments to the
.Fa system.filerags
through the
.Fn fileargs_ininv
and
.Fn fileargs_cinit
functions.
The
.Xr nvlist 9
for that functions must contain the following values and types:
.Bl -ohang -offset indent
.It flags ( NV_TYPE_NUMBER )
The
.Va flags
limits opened files for either execution or reading and/or writing.
.It mode (NV_TYPE_NUMBER)
If in the
.Va flags
argument the
.Dv O_CREATE
flag was defined the
.Xr nvlist 9
must contain the
.Va mode .
The
.Va mode
argument tells which what mode file should be created.
.El
.Pp
The
.Xr nvlist 9
for that functions may contain the following values and types:
.Bl -ohang -offset indent
.It cap_rights ( NV_TYPE_BINARY )
The
.Va cap_rights
argument contains a list of the capability rights which file should be limited to.
.It ( NV_TYPE_NULL )
Any number of
.Dv NV_TYPE_NULL
where the name of the element is name of the file which can be opened.
.Sh EXAMPLES
The following example first parse some options and then create the
.Nm system.filerags
service with remaining arguments.
.Bd -literal
int ch, fd, i;
cap_rights_t rights;
fileargs_t *fa;
while ((ch = getopt(argc, argv, "h")) != -1) {
switch (ch) {
case 'h':
default:
usage();
}
}
argc -= optind;
argv += optind;
/* Create capability to the system.fileargs service. */
fa = fileargs_init(argc, argv, O_RDONLY, 0,
cap_rights_init(&rights, CAP_READ));
if (fa == NULL)
err(1, "unable to open system.fileargs service");
/* Enter capability mode sandbox. */
if (cap_enter() < 0 && errno != ENOSYS)
err(1, "unable to enter capability mode");
/* Open files. */
for (i = 0; i < argc; i++) {
fd = fileargs_open(fa, argv[i]);
if (fd < 0)
err(1, "unable to open file %s", argv[i]);
printf("File %s opened in capability mode\n", argv[i]);
close(fd);
}
fileargs_free(fa);
.Ed
.Sh SEE ALSO
.Xr cap_enter 2 ,
.Xr open 2 ,
.Xr cap_rights_init 3 ,
.Xr err 3 ,
.Xr fopen 3,
.Xr getopt 3,
.Xr capsicum 4 ,
.Xr nv 9
.Sh BUGS
The
.Lb cap_fileargs
included in
.Fx
is considered experimental, and should not be deployed in production
environments without careful consideration of the risks associated with
the use of experimental operating system features.
.Sh AUTHORS
.An Mariusz Zaborski Aq Mt oshogbo@FreeBSD.org

View File

@ -0,0 +1,505 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2018 Mariusz Zaborski <oshogbo@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 AUTHORS 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 AUTHORS 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/capsicum.h>
#include <sys/sysctl.h>
#include <sys/cnv.h>
#include <sys/dnv.h>
#include <sys/nv.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libcasper.h>
#include <libcasper_service.h>
#include "cap_fileargs.h"
#define CACHE_SIZE 128
#define FILEARGS_MAGIC 0xFA00FA00
struct fileargs {
uint32_t fa_magic;
nvlist_t *fa_cache;
cap_channel_t *fa_chann;
int fa_fdflags;
};
static int
fileargs_get_cache(fileargs_t *fa, const char *name)
{
int fd;
const nvlist_t *nvl;
nvlist_t *tnvl;
assert(fa != NULL);
assert(fa->fa_magic == FILEARGS_MAGIC);
assert(name != NULL);
if (fa->fa_cache == NULL)
return (-1);
if ((fa->fa_fdflags & O_CREAT) != 0)
return (-1);
nvl = dnvlist_get_nvlist(fa->fa_cache, name, NULL);
if (nvl == NULL)
return (-1);
tnvl = nvlist_take_nvlist(fa->fa_cache, name);
fd = nvlist_take_descriptor(tnvl, "fd");
nvlist_destroy(tnvl);
if ((fa->fa_fdflags & O_CLOEXEC) != O_CLOEXEC) {
if (fcntl(fd, F_SETFD, fa->fa_fdflags) == -1) {
close(fd);
return (-1);
}
}
return (fd);
}
static void
fileargs_set_cache(fileargs_t *fa, nvlist_t *nvl)
{
nvlist_destroy(fa->fa_cache);
fa->fa_cache = nvl;
}
static nvlist_t*
fileargs_fetch(fileargs_t *fa, const char *name)
{
nvlist_t *nvl;
int serrno;
assert(fa != NULL);
assert(name != NULL);
nvl = nvlist_create(NV_FLAG_NO_UNIQUE);
nvlist_add_string(nvl, "cmd", "open");
nvlist_add_string(nvl, "name", name);
nvl = cap_xfer_nvlist(fa->fa_chann, nvl);
if (nvl == NULL)
return (NULL);
if (nvlist_get_number(nvl, "error") != 0) {
serrno = (int)nvlist_get_number(nvl, "error");
nvlist_destroy(nvl);
errno = serrno;
return (NULL);
}
return (nvl);
}
static nvlist_t *
fileargs_create_limit(int argc, const char * const *argv, int flags,
mode_t mode, cap_rights_t *rightsp)
{
nvlist_t *limits;
int i;
limits = nvlist_create(NV_FLAG_NO_UNIQUE);
if (limits == NULL)
return (NULL);
nvlist_add_number(limits, "flags", flags);
if (rightsp != NULL) {
nvlist_add_binary(limits, "cap_rights", rightsp,
sizeof(*rightsp));
}
if ((flags & O_CREAT) != 0)
nvlist_add_number(limits, "mode", (uint64_t)mode);
for (i = 0; i < argc; i++) {
nvlist_add_null(limits, argv[i]);
}
return (limits);
}
static fileargs_t *
fileargs_create(cap_channel_t *chan, int fdflags)
{
fileargs_t *fa;
fa = malloc(sizeof(*fa));
if (fa != NULL) {
fa->fa_cache = NULL;
fa->fa_chann = chan;
fa->fa_fdflags = fdflags;
fa->fa_magic = FILEARGS_MAGIC;
}
return (fa);
}
fileargs_t *
fileargs_init(int argc, char *argv[], int flags, mode_t mode,
cap_rights_t *rightsp)
{
nvlist_t *limits;
if (argc <= 0 || argv == NULL) {
return (fileargs_create(NULL, 0));
}
limits = fileargs_create_limit(argc, (const char * const *)argv, flags,
mode, rightsp);
if (limits == NULL)
return (NULL);
return (fileargs_initnv(limits));
}
fileargs_t *
fileargs_cinit(cap_channel_t *cas, int argc, char *argv[], int flags,
mode_t mode, cap_rights_t *rightsp)
{
nvlist_t *limits;
if (argc <= 0 || argv == NULL) {
return (fileargs_create(NULL, 0));
}
limits = fileargs_create_limit(argc, (const char * const *)argv, flags,
mode, rightsp);
if (limits == NULL)
return (NULL);
return (fileargs_cinitnv(cas, limits));
}
fileargs_t *
fileargs_initnv(nvlist_t *limits)
{
cap_channel_t *cas;
fileargs_t *fa;
if (limits == NULL) {
return (fileargs_create(NULL, 0));
}
cas = cap_init();
if (cas == NULL) {
nvlist_destroy(limits);
return (NULL);
}
fa = fileargs_cinitnv(cas, limits);
cap_close(cas);
return (fa);
}
fileargs_t *
fileargs_cinitnv(cap_channel_t *cas, nvlist_t *limits)
{
cap_channel_t *chann;
fileargs_t *fa;
int serrno, ret;
int flags;
assert(cas != NULL);
if (limits == NULL) {
return (fileargs_create(NULL, 0));
}
chann = NULL;
fa = NULL;
chann = cap_service_open(cas, "system.fileargs");
if (chann == NULL) {
nvlist_destroy(limits);
return (NULL);
}
flags = nvlist_get_number(limits, "flags");
/* Limits are consumed no need to free them. */
ret = cap_limit_set(chann, limits);
if (ret < 0)
goto out;
fa = fileargs_create(chann, flags);
if (fa == NULL)
goto out;
return (fa);
out:
serrno = errno;
if (chann != NULL)
cap_close(chann);
errno = serrno;
return (NULL);
}
int
fileargs_open(fileargs_t *fa, const char *name)
{
int fd;
nvlist_t *nvl;
char *cmd;
assert(fa != NULL);
assert(fa->fa_magic == FILEARGS_MAGIC);
if (name == NULL) {
errno = EINVAL;
return (-1);
}
if (fa->fa_chann == NULL) {
errno = ENOTCAPABLE;
return (-1);
}
fd = fileargs_get_cache(fa, name);
if (fd != -1)
return (fd);
nvl = fileargs_fetch(fa, name);
if (nvl == NULL)
return (-1);
fd = nvlist_take_descriptor(nvl, "fd");
cmd = nvlist_take_string(nvl, "cmd");
if (strcmp(cmd, "cache") == 0)
fileargs_set_cache(fa, nvl);
else
nvlist_destroy(nvl);
free(cmd);
return (fd);
}
FILE *
fileargs_fopen(fileargs_t *fa, const char *name, const char *mode)
{
int fd;
if ((fd = fileargs_open(fa, name)) < 0) {
return (NULL);
}
return (fdopen(fd, mode));
}
void
fileargs_free(fileargs_t *fa)
{
if (fa == NULL)
return;
assert(fa->fa_magic == FILEARGS_MAGIC);
nvlist_destroy(fa->fa_cache);
if (fa->fa_chann != NULL) {
cap_close(fa->fa_chann);
}
explicit_bzero(&fa->fa_magic, sizeof(fa->fa_magic));
free(fa);
}
/*
* Service functions.
*/
static const char *lastname;
static void *cacheposition;
static bool allcached;
static const cap_rights_t *caprightsp;
static int capflags;
static mode_t capmode;
static int
open_file(const char *name)
{
int fd, serrno;
if ((capflags & O_CREAT) == 0)
fd = open(name, capflags);
else
fd = open(name, capflags, capmode);
if (fd < 0)
return (-1);
if (caprightsp != NULL) {
if (cap_rights_limit(fd, caprightsp) < 0) {
serrno = errno;
close(fd);
errno = serrno;
return (-1);
}
}
return (fd);
}
static void
fileargs_add_cache(nvlist_t *nvlout, const nvlist_t *limits,
const char *curent_name)
{
int type, i, fd;
void *cookie;
nvlist_t *new;
const char *fname;
if ((capflags & O_CREAT) != 0) {
allcached = true;
return;
}
cookie = cacheposition;
for (i = 0; i < CACHE_SIZE + 1; i++) {
fname = nvlist_next(limits, &type, &cookie);
if (fname == NULL) {
cacheposition = NULL;
lastname = NULL;
allcached = true;
return;
}
/* We doing that to catch next element name. */
if (i == CACHE_SIZE) {
break;
}
if (type != NV_TYPE_NULL ||
(curent_name != NULL && strcmp(fname, curent_name) == 0)) {
curent_name = NULL;
i--;
continue;
}
fd = open_file(fname);
if (fd < 0) {
i--;
continue;
}
new = nvlist_create(NV_FLAG_NO_UNIQUE);
nvlist_move_descriptor(new, "fd", fd);
nvlist_add_nvlist(nvlout, fname, new);
}
cacheposition = cookie;
lastname = fname;
}
static bool
fileargs_allowed(const nvlist_t *limits, const nvlist_t *request)
{
const char *name;
name = dnvlist_get_string(request, "name", NULL);
if (name == NULL)
return (false);
/* Fast path. */
if (lastname != NULL && strcmp(name, lastname) == 0)
return (true);
if (!nvlist_exists_null(limits, name))
return (false);
return (true);
}
static int
fileargs_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits)
{
if (oldlimits != NULL)
return (ENOTCAPABLE);
capflags = (int)dnvlist_get_number(newlimits, "flags", 0);
if ((capflags & O_CREAT) != 0)
capmode = (mode_t)nvlist_get_number(newlimits, "mode");
else
capmode = 0;
caprightsp = dnvlist_get_binary(newlimits, "cap_rights", NULL, NULL, 0);
return (0);
}
static int
fileargs_command_open(const nvlist_t *limits, nvlist_t *nvlin,
nvlist_t *nvlout)
{
int fd;
const char *name;
if (limits == NULL)
return (ENOTCAPABLE);
if (!fileargs_allowed(limits, nvlin))
return (ENOTCAPABLE);
name = nvlist_get_string(nvlin, "name");
fd = open_file(name);
if (fd < 0)
return (errno);
if (!allcached && (lastname == NULL ||
strcmp(name, lastname) == 0)) {
nvlist_add_string(nvlout, "cmd", "cache");
fileargs_add_cache(nvlout, limits, name);
} else {
nvlist_add_string(nvlout, "cmd", "open");
}
nvlist_move_descriptor(nvlout, "fd", fd);
return (0);
}
static int
fileargs_command(const char *cmd, const nvlist_t *limits,
nvlist_t *nvlin, nvlist_t *nvlout)
{
if (strcmp(cmd, "open") == 0)
return (fileargs_command_open(limits, nvlin, nvlout));
return (EINVAL);
}
CREATE_SERVICE("system.fileargs", fileargs_limit, fileargs_command,
CASPER_SERVICE_FD | CASPER_SERVICE_STDIO | CASPER_SERVICE_NO_UNIQ_LIMITS);

View File

@ -0,0 +1,108 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2018 Mariusz Zaborski <oshogbo@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 AUTHORS 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 AUTHORS 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 _FILEARGS_H_
#define _FILEARGS_H_
#include <sys/dnv.h>
#include <sys/nv.h>
#include <stdbool.h>
#ifdef WITH_CASPER
struct fileargs;
typedef struct fileargs fileargs_t;
fileargs_t *fileargs_init(int argc, char *argv[], int flags, mode_t mode,
cap_rights_t *rightsp);
fileargs_t *fileargs_cinit(cap_channel_t *cas, int argc, char *argv[],
int flags, mode_t mode, cap_rights_t *rightsp);
fileargs_t *fileargs_initnv(nvlist_t *limits);
fileargs_t *fileargs_cinitnv(cap_channel_t *cas, nvlist_t *limits);
int fileargs_open(fileargs_t *fa, const char *name);
void fileargs_free(fileargs_t *fa);
FILE *fileargs_fopen(fileargs_t *fa, const char *name, const char *mode);
#else
typedef struct fileargs {
int fa_flags;
mode_t fa_mode;
} fileargs_t;
static inline fileargs_t *
fileargs_init(int argc __unused, char *argv[] __unused, int flags, mode_t mode,
cap_rights_t *rightsp __unused) {
fileargs_t *fa;
fa = malloc(sizeof(*fa));
if (fa != NULL) {
fa->fa_flags = flags;
fa->fa_mode = mode;
}
return (fa);
}
static inline fileargs_t *
fileargs_cinit(cap_channel_t *cas __unused, int argc, char *argv[], int flags,
mode_t mode, cap_rights_t *rightsp)
{
return (fileargs_init(argc, argv, flags, mode, rightsp));
}
static inline fileargs_t *
fileargs_initnv(nvlist_t *limits)
{
fileargs_t *fa;
fa = fileargs_init(0, NULL,
nvlist_get_number(limits, "flags"),
dnvlist_get_number(limits, "mode", 0),
NULL);
nvlist_destroy(limits);
return (fa);
}
static inline fileargs_t *
fileargs_cinitnv(cap_channel_t *cas __unused, nvlist_t *limits)
{
return (fileargs_initnv(limits));
}
#define fileargs_open(fa, name) \
open(name, fa->fa_flags, fa->fa_mode)
#define fileargs_fopen(fa, name, mode) \
fopen(name, mode)
#define fileargs_free(fa) (free(fa))
#endif
#endif /* !_FILEARGS_H_ */

View File

@ -34,6 +34,15 @@
#ifndef _COMMON_IMPL_H_
#define _COMMON_IMPL_H_
#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF)
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
static inline bool
fd_is_valid(int fd)
{
return (fcntl(fd, F_GETFD) != -1 || errno != EBADF);
}
#endif /* !_COMMON_IMPL_H_ */

View File

@ -66,11 +66,6 @@ msghdr_add_fd(struct cmsghdr *cmsg, int fd)
PJDLOG_ASSERT(fd >= 0);
if (!fd_is_valid(fd)) {
errno = EBADF;
return (-1);
}
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));

View File

@ -306,15 +306,12 @@ parent(int sock)
CHECK(name == NULL);
}
int
main(void)
static void
send_nvlist(void)
{
int status, socks[2];
pid_t pid;
printf("1..134\n");
fflush(stdout);
if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0)
err(1, "socketpair() failed");
pid = fork();
@ -326,7 +323,7 @@ main(void)
/* Child. */
close(socks[0]);
child(socks[1]);
return (0);
_exit(0);
default:
/* Parent. */
close(socks[1]);
@ -336,6 +333,35 @@ main(void)
if (waitpid(pid, &status, 0) < 0)
err(1, "waitpid() failed");
}
static void
send_closed_fd(void)
{
nvlist_t *nvl;
int error, socks[2];
if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0)
err(1, "socketpair() failed");
nvl = nvlist_create(0);
nvlist_add_descriptor(nvl, "fd", 12345);
error = nvlist_error(nvl);
CHECK(error == EBADF);
error = nvlist_send(socks[1], nvl);
CHECK(error != 0 && errno == EBADF);
}
int
main(void)
{
printf("1..136\n");
fflush(stdout);
send_nvlist();
send_closed_fd();
return (0);
}

View File

@ -3,12 +3,12 @@
PACKAGE=lib${LIB}
LIB= ufs
SHLIBDIR?= /lib
SHLIB_MAJOR= 6
SHLIB_MAJOR= 7
SRCS= block.c cgroup.c crc32.c inode.c sblock.c type.c ffs_subr.c ffs_tables.c
INCS= libufs.h
MAN= bread.3 cgread.3 libufs.3 sbread.3 ufs_disk_close.3
MAN= bread.3 cgread.3 getinode.3 libufs.3 sbread.3 ufs_disk_close.3
MLINKS+= bread.3 bwrite.3
MLINKS+= bread.3 berase.3
MLINKS+= cgread.3 cgread1.3
@ -16,6 +16,7 @@ MLINKS+= cgread.3 cgget.3
MLINKS+= cgread.3 cgwrite.3
MLINKS+= cgread.3 cgwrite1.3
MLINKS+= cgread.3 cgput.3
MLINKS+= getinode.3 putinode.3
MLINKS+= sbread.3 sbwrite.3
MLINKS+= sbread.3 sbget.3
MLINKS+= sbread.3 sbput.3

131
lib/libufs/getinode.3 Normal file
View File

@ -0,0 +1,131 @@
.\" Author: Marshall Kirk McKusick <mckusick@freebsd.org>
.\" Date: January 19, 2018
.\" Description:
.\" Manual page for libufs functions:
.\" getinode(3)
.\" putinode(3)
.\"
.\" This file is in the public domain.
.\"
.\" $FreeBSD$
.\"
.Dd November 10, 2018
.Dt GETINODE 3
.Os
.Sh NAME
.Nm getinode , putinode
.Nd fetch and store inodes on a UFS file system
.Sh LIBRARY
.Lb libufs
.Sh SYNOPSIS
.In ufs/ufs/dinode.h
.In ufs/ffs/fs.h
.In libufs.h
.Ft int
.Fn getinode "struct uufsd *disk" "union dinodep *dp" "ino_t inumber"
.Ft int
.Fn putinode "struct uufsd *disk"
.Sh DESCRIPTION
The
.Fn getinode
and
.Fn putinode
functions provide an inode fetch and store API for
.Xr libufs 3
consumers.
They operate on a userland UFS disk structure.
The
.Fn getinode
function fetches the specified inode from the filesystem.
The
.Fn putinode
function stores the most recently fetched inode to the filesystem.
.Pp
The
.Va dinodep
union is defined as:
.Bd -literal -offset indent
union dinodep {
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
};
.Ed
.Pp
Sample code to clear write permissions for inode number
.Fa inumber
stored on the filesystem described by
.Fa diskp .
.Bd -literal -offset indent
#include <sys/stat.h>
#include <err.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <libufs.h>
void
clearwrite(struct uufsd *diskp, ino_t inumber)
{
union dinodep dp;
if (getinode(diskp, &dp, inumber) == -1)
err(1, "getinode: %s", diskp->d_error);
switch (diskp->d_ufs) {
case 1: /* UFS 1 filesystem */
dp.dp1->di_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
break;
case 2: /* UFS 2 filesystem */
dp.dp2->di_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
break;
default:
errx(1, "unknown filesystem type");
}
if (putinode(diskp) == -1)
err(1, "putinode: %s", diskp->d_error);
}
.Ed
.Sh RETURN VALUES
The
.Fn getinode
and
.Fn putinode
functions return 0 on success, or \-1 in case of any error.
A string describing the error is stored in
.Fa diskp->d_error .
The global
.Fa errno
often provides additional information.
.Sh ERRORS
The function
.Fn getinode
may fail and set
.Va errno
for any of the errors specified for the library function
.Xr pread 2 .
It can also fail if the inode number is out of the range of inodes
in the filesystem.
.Pp
The function
.Fn putinode
may fail and set
.Va errno
for any of the errors specified for the library functions
.Xr ufs_disk_write 3
or
.Xr pwrite 2 .
.Pp
Additionally both functions may follow the
.Xr libufs 3
error methodologies in case of a device error.
.Sh SEE ALSO
.Xr pread 2 ,
.Xr pwrite 2 ,
.Xr libufs 3 ,
.Xr ufs_disk_write 3
.Sh HISTORY
These functions first appeared as part of
.Xr libufs 3
in
.Fx 13.0 .
.Sh AUTHORS
.An Marshall Kirk McKusick Aq Mt mckusick@freebsd.org

View File

@ -49,18 +49,16 @@ __FBSDID("$FreeBSD$");
#include <libufs.h>
int
getino(struct uufsd *disk, void **dino, ino_t inode, int *mode)
getinode(struct uufsd *disk, union dinodep *dp, ino_t inum)
{
ino_t min, max;
caddr_t inoblock;
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
struct fs *fs;
ERROR(disk, NULL);
fs = &disk->d_fs;
if (inode >= (ino_t)fs->fs_ipg * fs->fs_ncg) {
if (inum >= (ino_t)fs->fs_ipg * fs->fs_ncg) {
ERROR(disk, "inode number out of range");
return (-1);
}
@ -76,26 +74,22 @@ getino(struct uufsd *disk, void **dino, ino_t inode, int *mode)
}
disk->d_inoblock = inoblock;
}
if (inode >= min && inode < max)
if (inum >= min && inum < max)
goto gotit;
bread(disk, fsbtodb(fs, ino_to_fsba(fs, inode)), inoblock,
bread(disk, fsbtodb(fs, ino_to_fsba(fs, inum)), inoblock,
fs->fs_bsize);
disk->d_inomin = min = inode - (inode % INOPB(fs));
disk->d_inomin = min = inum - (inum % INOPB(fs));
disk->d_inomax = max = min + INOPB(fs);
gotit: switch (disk->d_ufs) {
case 1:
dp1 = &((struct ufs1_dinode *)inoblock)[inode - min];
if (mode != NULL)
*mode = dp1->di_mode & IFMT;
if (dino != NULL)
*dino = dp1;
disk->d_dp.dp1 = &((struct ufs1_dinode *)inoblock)[inum - min];
if (dp != NULL)
*dp = disk->d_dp;
return (0);
case 2:
dp2 = &((struct ufs2_dinode *)inoblock)[inode - min];
if (mode != NULL)
*mode = dp2->di_mode & IFMT;
if (dino != NULL)
*dino = dp2;
disk->d_dp.dp2 = &((struct ufs2_dinode *)inoblock)[inum - min];
if (dp != NULL)
*dp = disk->d_dp;
return (0);
default:
break;
@ -105,7 +99,7 @@ gotit: switch (disk->d_ufs) {
}
int
putino(struct uufsd *disk)
putinode(struct uufsd *disk)
{
struct fs *fs;

View File

@ -35,6 +35,10 @@
/*
* libufs structures.
*/
union dinodep {
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
};
/*
* userland ufs disk.
@ -49,6 +53,7 @@ struct uufsd {
caddr_t d_inoblock; /* inode block */
uint32_t d_inomin; /* low inode (not ino_t for ABI compat) */
uint32_t d_inomax; /* high inode (not ino_t for ABI compat) */
union dinodep d_dp; /* pointer to currently active inode */
union {
struct fs d_fs; /* filesystem information */
char d_sb[MAXBSIZE];
@ -135,8 +140,8 @@ int cgwrite1(struct uufsd *, int);
/*
* inode.c
*/
int getino(struct uufsd *, void **, ino_t, int *);
int putino(struct uufsd *);
int getinode(struct uufsd *, union dinodep *, ino_t);
int putinode(struct uufsd *);
/*
* sblock.c

View File

@ -10,7 +10,6 @@
# $FreeBSD$
base="Base system"
doc="Additional Documentation"
kernel="Kernel"
ports="Ports tree"
src="System source tree"
@ -19,7 +18,6 @@ tests="Test suite"
desc_base="${base} (MANDATORY)"
desc_base_dbg="${base} (Debugging)"
desc_doc="${doc}"
desc_kernel="${kernel} (MANDATORY)"
desc_kernel_dbg="${kernel} (Debugging)"
desc_kernel_alt="Alternate ${kernel}"
@ -30,7 +28,6 @@ desc_ports="${ports}"
desc_src="${src}"
desc_tests="${tests}"
default_doc=off
default_src=off
default_ports=off
default_tests=off
@ -51,6 +48,9 @@ for i in ${*}; do
desc="$(eval echo \"\${desc_${distname}}\")"
case ${i} in
doc.txz)
continue
;;
kernel-dbg.txz)
desc="${desc_kernel_dbg}"
;;

View File

@ -62,11 +62,6 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <unistd.h>
union dinodep {
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
};
static void
usage(void)
{
@ -104,8 +99,8 @@ main(int argc, char *argv[])
}
(void)printf("clearing %d\n", inonum);
if (getino(&disk, (void **)&dp, inonum, NULL) == -1) {
printf("getino: %s\n", disk.d_error);
if (getinode(&disk, &dp, inonum) == -1) {
printf("getinode: %s\n", disk.d_error);
exitval = 1;
continue;
}
@ -119,7 +114,7 @@ main(int argc, char *argv[])
memset(dp.dp2, 0, sizeof(*dp.dp2));
dp.dp2->di_gen = generation;
}
putino(&disk);
putinode(&disk);
(void)fsync(disk.d_fd);
}
(void)ufs_disk_close(&disk);

View File

@ -126,7 +126,7 @@ void dumpabort(int signo) __dead2;
void dump_getfstab(void);
char *rawname(char *cp);
union dinode *getinode(ino_t inum, int *mode);
union dinode *getino(ino_t inum, int *mode);
/* rdump routines */
#ifdef RDUMP

View File

@ -549,7 +549,7 @@ main(int argc, char *argv[])
/*
* Skip directory inodes deleted and maybe reallocated
*/
dp = getinode(ino, &mode);
dp = getino(ino, &mode);
if (mode != IFDIR)
continue;
(void)dumpino(dp, ino);
@ -568,7 +568,7 @@ main(int argc, char *argv[])
/*
* Skip inodes deleted and reallocated as directories.
*/
dp = getinode(ino, &mode);
dp = getino(ino, &mode);
if (mode == IFDIR)
continue;
(void)dumpino(dp, ino);

View File

@ -195,7 +195,7 @@ mapfiles(ino_t maxino, long *tapesize)
}
for (i = 0; i < inosused; i++, ino++) {
if (ino < UFS_ROOTINO ||
(dp = getinode(ino, &mode)) == NULL ||
(dp = getino(ino, &mode)) == NULL ||
(mode & IFMT) == 0)
continue;
if (ino >= maxino) {
@ -277,7 +277,7 @@ mapdirs(ino_t maxino, long *tapesize)
nodump = !nonodump && (TSTINO(ino, usedinomap) == 0);
if ((isdir & 1) == 0 || (TSTINO(ino, dumpinomap) && !nodump))
continue;
dp = getinode(ino, &i);
dp = getino(ino, &i);
/*
* inode buf may change in searchdir().
*/
@ -421,7 +421,7 @@ searchdir(
continue;
}
if (nodump) {
ip = getinode(dp->d_ino, &mode);
ip = getino(dp->d_ino, &mode);
if (TSTINO(dp->d_ino, dumpinomap)) {
CLRINO(dp->d_ino, dumpinomap);
*tapesize -= blockest(ip);
@ -875,7 +875,7 @@ writeheader(ino_t ino)
}
union dinode *
getinode(ino_t inum, int *modep)
getino(ino_t inum, int *modep)
{
static ino_t minino, maxino;
static caddr_t inoblock;

View File

@ -262,7 +262,7 @@ main(int argc, char **argv)
dbg_csp = fscs;
/* ... and dump it */
for(dbg_csc=0; dbg_csc<sblock.fs_ncg; dbg_csc++) {
for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) {
snprintf(dbg_line, sizeof(dbg_line),
"%d. csum in fscs", dbg_csc);
DBG_DUMP_CSUM(&sblock,
@ -342,8 +342,8 @@ void
dump_whole_ufs1_inode(ino_t inode, int level)
{
DBG_FUNC("dump_whole_ufs1_inode")
struct ufs1_dinode *ino;
int rb, mode;
union dinodep dp;
int rb;
unsigned int ind2ctr, ind3ctr;
ufs1_daddr_t *ind2ptr, *ind3ptr;
char comment[80];
@ -353,10 +353,10 @@ dump_whole_ufs1_inode(ino_t inode, int level)
/*
* Read the inode from disk/cache.
*/
if (getino(&disk, (void **)&ino, inode, &mode) == -1)
err(1, "getino: %s", disk.d_error);
if (getinode(&disk, &dp, inode) == -1)
err(1, "getinode: %s", disk.d_error);
if(ino->di_nlink==0) {
if (dp.dp1->di_nlink == 0) {
DBG_LEAVE;
return; /* inode not in use */
}
@ -368,7 +368,7 @@ dump_whole_ufs1_inode(ino_t inode, int level)
if (level & 0x100) {
DBG_DUMP_INO(&sblock,
comment,
ino);
dp.dp1);
}
if (!(level & 0x200)) {
@ -379,13 +379,13 @@ dump_whole_ufs1_inode(ino_t inode, int level)
/*
* Ok, now prepare for dumping all direct and indirect pointers.
*/
rb = howmany(ino->di_size, sblock.fs_bsize) - UFS_NDADDR;
if(rb>0) {
rb = howmany(dp.dp1->di_size, sblock.fs_bsize) - UFS_NDADDR;
if (rb > 0) {
/*
* Dump single indirect block.
*/
if (bread(&disk, fsbtodb(&sblock, ino->di_ib[0]), (void *)&i1blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, dp.dp1->di_ib[0]),
(void *)&i1blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 0",
@ -394,14 +394,14 @@ dump_whole_ufs1_inode(ino_t inode, int level)
comment,
i1blk,
(size_t)rb);
rb-=howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t));
rb -= howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t));
}
if(rb>0) {
if (rb > 0) {
/*
* Dump double indirect blocks.
*/
if (bread(&disk, fsbtodb(&sblock, ino->di_ib[1]), (void *)&i2blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, dp.dp1->di_ib[1]),
(void *)&i2blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 1",
@ -410,12 +410,12 @@ dump_whole_ufs1_inode(ino_t inode, int level)
comment,
i2blk,
howmany(rb, howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t))));
for(ind2ctr=0; ((ind2ctr < howmany(sblock.fs_bsize,
sizeof(ufs1_daddr_t))) && (rb>0)); ind2ctr++) {
ind2ptr=&((ufs1_daddr_t *)(void *)&i2blk)[ind2ctr];
for (ind2ctr = 0; ((ind2ctr < howmany(sblock.fs_bsize,
sizeof(ufs1_daddr_t))) && (rb > 0)); ind2ctr++) {
ind2ptr = &((ufs1_daddr_t *)(void *)&i2blk)[ind2ctr];
if (bread(&disk, fsbtodb(&sblock, *ind2ptr), (void *)&i1blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, *ind2ptr),
(void *)&i1blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment),
@ -425,15 +425,15 @@ dump_whole_ufs1_inode(ino_t inode, int level)
comment,
i1blk,
(size_t)rb);
rb-=howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t));
rb -= howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t));
}
}
if(rb>0) {
if (rb > 0) {
/*
* Dump triple indirect blocks.
*/
if (bread(&disk, fsbtodb(&sblock, ino->di_ib[2]), (void *)&i3blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, dp.dp1->di_ib[2]),
(void *)&i3blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2",
@ -445,12 +445,12 @@ dump_whole_ufs1_inode(ino_t inode, int level)
howmany(rb,
SQUARE(howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t)))));
#undef SQUARE
for(ind3ctr=0; ((ind3ctr<howmany(sblock.fs_bsize,
sizeof(ufs1_daddr_t)))&&(rb>0)); ind3ctr++) {
ind3ptr=&((ufs1_daddr_t *)(void *)&i3blk)[ind3ctr];
for (ind3ctr = 0; ((ind3ctr < howmany(sblock.fs_bsize,
sizeof(ufs1_daddr_t))) && (rb > 0)); ind3ctr++) {
ind3ptr = &((ufs1_daddr_t *)(void *)&i3blk)[ind3ctr];
if (bread(&disk, fsbtodb(&sblock, *ind3ptr), (void *)&i2blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, *ind3ptr),
(void *)&i2blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment),
@ -461,8 +461,8 @@ dump_whole_ufs1_inode(ino_t inode, int level)
i2blk,
howmany(rb,
howmany(sblock.fs_bsize, sizeof(ufs1_daddr_t))));
for(ind2ctr=0; ((ind2ctr < howmany(sblock.fs_bsize,
sizeof(ufs1_daddr_t)))&&(rb>0)); ind2ctr++) {
for (ind2ctr = 0; ((ind2ctr < howmany(sblock.fs_bsize,
sizeof(ufs1_daddr_t))) && (rb > 0)); ind2ctr++) {
ind2ptr=&((ufs1_daddr_t *)(void *)&i2blk)
[ind2ctr];
if (bread(&disk, fsbtodb(&sblock, *ind2ptr),
@ -477,7 +477,7 @@ dump_whole_ufs1_inode(ino_t inode, int level)
comment,
i1blk,
(size_t)rb);
rb-=howmany(sblock.fs_bsize,
rb -= howmany(sblock.fs_bsize,
sizeof(ufs1_daddr_t));
}
}
@ -496,8 +496,8 @@ void
dump_whole_ufs2_inode(ino_t inode, int level)
{
DBG_FUNC("dump_whole_ufs2_inode")
struct ufs2_dinode *ino;
int rb, mode;
union dinodep dp;
int rb;
unsigned int ind2ctr, ind3ctr;
ufs2_daddr_t *ind2ptr, *ind3ptr;
char comment[80];
@ -507,10 +507,10 @@ dump_whole_ufs2_inode(ino_t inode, int level)
/*
* Read the inode from disk/cache.
*/
if (getino(&disk, (void **)&ino, inode, &mode) == -1)
err(1, "getino: %s", disk.d_error);
if (getinode(&disk, &dp, inode) == -1)
err(1, "getinode: %s", disk.d_error);
if (ino->di_nlink == 0) {
if (dp.dp2->di_nlink == 0) {
DBG_LEAVE;
return; /* inode not in use */
}
@ -520,7 +520,7 @@ dump_whole_ufs2_inode(ino_t inode, int level)
*/
snprintf(comment, sizeof(comment), "Inode 0x%08jx", (uintmax_t)inode);
if (level & 0x100) {
DBG_DUMP_INO(&sblock, comment, ino);
DBG_DUMP_INO(&sblock, comment, dp.dp2);
}
if (!(level & 0x200)) {
@ -531,13 +531,13 @@ dump_whole_ufs2_inode(ino_t inode, int level)
/*
* Ok, now prepare for dumping all direct and indirect pointers.
*/
rb = howmany(ino->di_size, sblock.fs_bsize) - UFS_NDADDR;
rb = howmany(dp.dp2->di_size, sblock.fs_bsize) - UFS_NDADDR;
if (rb > 0) {
/*
* Dump single indirect block.
*/
if (bread(&disk, fsbtodb(&sblock, ino->di_ib[0]), (void *)&i1blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, dp.dp2->di_ib[0]),
(void *)&i1blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 0",
@ -549,8 +549,8 @@ dump_whole_ufs2_inode(ino_t inode, int level)
/*
* Dump double indirect blocks.
*/
if (bread(&disk, fsbtodb(&sblock, ino->di_ib[1]), (void *)&i2blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, dp.dp2->di_ib[1]),
(void *)&i2blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 1",
@ -563,8 +563,8 @@ dump_whole_ufs2_inode(ino_t inode, int level)
sizeof(ufs2_daddr_t))) && (rb>0)); ind2ctr++) {
ind2ptr = &((ufs2_daddr_t *)(void *)&i2blk)[ind2ctr];
if (bread(&disk, fsbtodb(&sblock, *ind2ptr), (void *)&i1blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, *ind2ptr),
(void *)&i1blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment),
@ -578,8 +578,8 @@ dump_whole_ufs2_inode(ino_t inode, int level)
/*
* Dump triple indirect blocks.
*/
if (bread(&disk, fsbtodb(&sblock, ino->di_ib[2]), (void *)&i3blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, dp.dp2->di_ib[2]),
(void *)&i3blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment), "Inode 0x%08jx: indirect 2",
@ -595,8 +595,8 @@ dump_whole_ufs2_inode(ino_t inode, int level)
sizeof(ufs2_daddr_t))) && (rb > 0)); ind3ctr++) {
ind3ptr = &((ufs2_daddr_t *)(void *)&i3blk)[ind3ctr];
if (bread(&disk, fsbtodb(&sblock, *ind3ptr), (void *)&i2blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, *ind3ptr),
(void *)&i2blk, (size_t)sblock.fs_bsize) == -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment),
@ -610,8 +610,9 @@ dump_whole_ufs2_inode(ino_t inode, int level)
for (ind2ctr = 0; ((ind2ctr < howmany(sblock.fs_bsize,
sizeof(ufs2_daddr_t))) && (rb > 0)); ind2ctr++) {
ind2ptr = &((ufs2_daddr_t *)(void *)&i2blk) [ind2ctr];
if (bread(&disk, fsbtodb(&sblock, *ind2ptr), (void *)&i1blk,
(size_t)sblock.fs_bsize) == -1) {
if (bread(&disk, fsbtodb(&sblock, *ind2ptr),
(void *)&i1blk, (size_t)sblock.fs_bsize)
== -1) {
err(1, "bread: %s", disk.d_error);
}
snprintf(comment, sizeof(comment),

View File

@ -254,14 +254,14 @@ fileerror(ino_t cwd, ino_t ino, const char *errmesg)
char pathbuf[MAXPATHLEN + 1];
pwarn("%s ", errmesg);
pinode(ino);
printf("\n");
getpathname(pathbuf, cwd, ino);
if (ino < UFS_ROOTINO || ino > maxino) {
pfatal("NAME=%s\n", pathbuf);
pfatal("out-of-range inode number %ju", (uintmax_t)ino);
return;
}
dp = ginode(ino);
prtinode(ino, dp);
printf("\n");
getpathname(pathbuf, cwd, ino);
if (ftypeok(dp))
pfatal("%s=%s\n",
(DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE",
@ -309,7 +309,7 @@ adjust(struct inodesc *idesc, int lcnt)
if (lcnt != 0) {
pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
((DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE"));
pinode(idesc->id_number);
prtinode(idesc->id_number, dp);
printf(" COUNT %d SHOULD BE %d",
DIP(dp, di_nlink), DIP(dp, di_nlink) - lcnt);
if (preen || usedsoftdep) {
@ -390,7 +390,8 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
dp = ginode(orphan);
lostdir = (DIP(dp, di_mode) & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
prtinode(orphan, dp);
printf("\n");
if (preen && DIP(dp, di_size) == 0)
return (0);
if (cursnapshot != 0) {

View File

@ -463,8 +463,8 @@ void pass4(void);
int pass4check(struct inodesc *);
void pass5(void);
void pfatal(const char *fmt, ...) __printflike(1, 2);
void pinode(ino_t ino);
void propagate(void);
void prtinode(ino_t ino, union dinode *dp);
void pwarn(const char *fmt, ...) __printflike(1, 2);
int readsb(int listerr);
int reply(const char *question);

View File

@ -392,13 +392,12 @@ clear_inode(struct ufs2_dinode *dino)
void
gjournal_check(const char *filesys)
{
struct ufs2_dinode *dino;
void *p;
union dinodep dp;
struct cgchain *cgc;
struct cg *cgp;
uint8_t *inosused;
ino_t cino, ino;
int cg, mode;
int cg;
devnam = filesys;
opendisk();
@ -444,19 +443,20 @@ gjournal_check(const char *filesys)
/* Unallocated? Skip it. */
if (isclr(inosused, cino))
continue;
if (getino(diskp, &p, ino, &mode) == -1)
err(1, "getino(cg=%d ino=%ju)",
cg, (uintmax_t)ino);
dino = p;
if (getinode(diskp, &dp, ino) == -1)
err(1, "getinode (cg=%d ino=%ju) %s",
cg, (uintmax_t)ino, diskp->d_error);
/* Not a regular file nor directory? Skip it. */
if (!S_ISREG(dino->di_mode) && !S_ISDIR(dino->di_mode))
if (!S_ISREG(dp.dp2->di_mode) &&
!S_ISDIR(dp.dp2->di_mode))
continue;
/* Has reference(s)? Skip it. */
if (dino->di_nlink > 0)
if (dp.dp2->di_nlink > 0)
continue;
//printf("Clearing inode=%d (size=%jd)\n", ino, (intmax_t)dino->di_size);
/* printf("Clearing inode=%d (size=%jd)\n", ino,
(intmax_t)dp.dp2->di_size); */
/* Free inode's blocks. */
clear_inode(dino);
clear_inode(dp.dp2);
/* Deallocate it. */
clrbit(inosused, cino);
/* Update position of last used inode. */
@ -469,17 +469,17 @@ gjournal_check(const char *filesys)
cgp->cg_unrefs--;
fs->fs_unrefs--;
/* If this is directory, update related statistics. */
if (S_ISDIR(dino->di_mode)) {
if (S_ISDIR(dp.dp2->di_mode)) {
cgp->cg_cs.cs_ndir--;
fs->fs_cs(fs, cg).cs_ndir--;
fs->fs_cstotal.cs_ndir--;
}
/* Zero-fill the inode. */
*dino = ufs2_zino;
*dp.dp2 = ufs2_zino;
/* Write the inode back. */
if (putino(diskp) == -1)
err(1, "putino(cg=%d ino=%ju)",
cg, (uintmax_t)ino);
if (putinode(diskp) == -1)
err(1, "putinode (cg=%d ino=%ju) %s",
cg, (uintmax_t)ino, diskp->d_error);
if (cgp->cg_unrefs == 0) {
//printf("No more unreferenced inodes in cg=%d.\n", cg);
break;

View File

@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <pwd.h>
#include <string.h>
#include <time.h>
#include <libufs.h>
#include "fsck.h"
@ -342,7 +343,11 @@ getnextinode(ino_t inumber, int rebuildcg)
nextinop = inobuf.b_un.b_buf;
}
dp = (union dinode *)nextinop;
if (rebuildcg && nextinop == inobuf.b_un.b_buf) {
if (sblock.fs_magic == FS_UFS1_MAGIC)
nextinop += sizeof(struct ufs1_dinode);
else
nextinop += sizeof(struct ufs2_dinode);
if (rebuildcg && (char *)dp == inobuf.b_un.b_buf) {
/*
* Try to determine if we have reached the end of the
* allocated inodes.
@ -355,7 +360,7 @@ getnextinode(ino_t inumber, int rebuildcg)
UFS_NIADDR * sizeof(ufs2_daddr_t)) ||
dp->dp2.di_mode || dp->dp2.di_size)
return (NULL);
goto inodegood;
return (dp);
}
if (!ftypeok(dp))
return (NULL);
@ -389,11 +394,6 @@ getnextinode(ino_t inumber, int rebuildcg)
if (DIP(dp, di_ib[j]) != 0)
return (NULL);
}
inodegood:
if (sblock.fs_magic == FS_UFS1_MAGIC)
nextinop += sizeof(struct ufs1_dinode);
else
nextinop += sizeof(struct ufs2_dinode);
return (dp);
}
@ -534,7 +534,8 @@ clri(struct inodesc *idesc, const char *type, int flag)
if (flag == 1) {
pwarn("%s %s", type,
(DIP(dp, di_mode) & IFMT) == IFDIR ? "DIR" : "FILE");
pinode(idesc->id_number);
prtinode(idesc->id_number, dp);
printf("\n");
}
if (preen || reply("CLEAR") == 1) {
if (preen)
@ -600,9 +601,8 @@ clearentry(struct inodesc *idesc)
}
void
pinode(ino_t ino)
prtinode(ino_t ino, union dinode *dp)
{
union dinode *dp;
char *p;
struct passwd *pw;
time_t t;
@ -610,7 +610,6 @@ pinode(ino_t ino)
printf(" I=%lu ", (u_long)ino);
if (ino < UFS_ROOTINO || ino > maxino)
return;
dp = ginode(ino);
printf(" OWNER=");
if ((pw = getpwuid((int)DIP(dp, di_uid))) != NULL)
printf("%s ", pw->pw_name);

View File

@ -458,30 +458,40 @@ checkfilesys(char *filesys)
if (preen == 0 && yflag == 0 && sblock.fs_magic != FS_UFS1_MAGIC &&
fswritefd != -1 && getosreldate() >= P_OSREL_CK_CYLGRP) {
if ((sblock.fs_metackhash & CK_CYLGRP) == 0 &&
reply("ADD CYLINDER GROUP CHECK-HASH PROTECTION") != 0)
reply("ADD CYLINDER GROUP CHECK-HASH PROTECTION") != 0) {
ckhashadd |= CK_CYLGRP;
sblock.fs_metackhash |= CK_CYLGRP;
}
if ((sblock.fs_metackhash & CK_SUPERBLOCK) == 0 &&
getosreldate() >= P_OSREL_CK_SUPERBLOCK &&
reply("ADD SUPERBLOCK CHECK-HASH PROTECTION") != 0) {
ckhashadd |= CK_SUPERBLOCK;
sblock.fs_metackhash |= CK_SUPERBLOCK;
sbdirty();
}
#ifdef notyet
if ((sblock.fs_metackhash & CK_INODE) == 0 &&
getosreldate() >= P_OSREL_CK_INODE &&
reply("ADD INODE CHECK-HASH PROTECTION") != 0)
reply("ADD INODE CHECK-HASH PROTECTION") != 0) {
ckhashadd |= CK_INODE;
sblock.fs_metackhash |= CK_INODE;
}
if ((sblock.fs_metackhash & CK_INDIR) == 0 &&
getosreldate() >= P_OSREL_CK_INDIR &&
reply("ADD INDIRECT BLOCK CHECK-HASH PROTECTION") != 0)
reply("ADD INDIRECT BLOCK CHECK-HASH PROTECTION") != 0) {
ckhashadd |= CK_INDIR;
sblock.fs_metackhash |= CK_INDIR;
}
if ((sblock.fs_metackhash & CK_DIR) == 0 &&
getosreldate() >= P_OSREL_CK_DIR &&
reply("ADD DIRECTORY CHECK-HASH PROTECTION") != 0)
reply("ADD DIRECTORY CHECK-HASH PROTECTION") != 0) {
ckhashadd |= CK_DIR;
sblock.fs_metackhash |= CK_DIR;
}
#endif /* notyet */
if (ckhashadd != 0)
if (ckhashadd != 0) {
sblock.fs_flags |= FS_METACKHASH;
sbdirty();
}
}
/*
* Cleared if any questions answered no. Used to decide if

View File

@ -74,11 +74,8 @@ pass5(void)
memset(newcg, 0, (size_t)fs->fs_cgsize);
newcg->cg_niblk = fs->fs_ipg;
/* check to see if we are to add a cylinder group check hash */
if ((ckhashadd & CK_CYLGRP) != 0) {
fs->fs_metackhash |= CK_CYLGRP;
if ((ckhashadd & CK_CYLGRP) != 0)
rewritecg = 1;
sbdirty();
}
if (cvtlevel >= 3) {
if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
if (preen)

View File

@ -175,7 +175,7 @@ fsirand(char *device)
}
/* For each cylinder group, randomize inodes and update backup sblock */
for (cg = 0, inumber = 0; cg < (int)sblock->fs_ncg; cg++) {
for (cg = 0, inumber = UFS_ROOTINO; cg < (int)sblock->fs_ncg; cg++) {
/* Read in inodes, then print or randomize generation nums */
dblk = fsbtodb(sblock, ino_to_fsba(sblock, inumber));
if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) {
@ -187,21 +187,22 @@ fsirand(char *device)
return (1);
}
for (n = 0; n < (int)sblock->fs_ipg; n++, inumber++) {
if (sblock->fs_magic == FS_UFS1_MAGIC)
dp1 = &((struct ufs1_dinode *)inodebuf)[n];
else
dp2 = &((struct ufs2_dinode *)inodebuf)[n];
if (inumber >= UFS_ROOTINO) {
if (printonly)
(void)printf("ino %ju gen %08x\n",
(uintmax_t)inumber,
sblock->fs_magic == FS_UFS1_MAGIC ?
dp1->di_gen : dp2->di_gen);
else if (sblock->fs_magic == FS_UFS1_MAGIC)
dp1->di_gen = random();
else
dp2->di_gen = random();
dp1 = (struct ufs1_dinode *)(void *)inodebuf;
dp2 = (struct ufs2_dinode *)(void *)inodebuf;
for (n = cg > 0 ? 0 : UFS_ROOTINO;
n < (int)sblock->fs_ipg;
n++, inumber++) {
if (printonly) {
(void)printf("ino %ju gen %08x\n",
(uintmax_t)inumber,
sblock->fs_magic == FS_UFS1_MAGIC ?
dp1->di_gen : dp2->di_gen);
} else if (sblock->fs_magic == FS_UFS1_MAGIC) {
dp1->di_gen = arc4random();
dp1++;
} else {
dp2->di_gen = arc4random();
dp2++;
}
}

View File

@ -301,16 +301,21 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag)
{
DBG_FUNC("initcg")
static caddr_t iobuf;
static long iobufsize;
long blkno, start;
ino_t ino;
ufs2_daddr_t i, cbase, dmax;
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
struct csum *cs;
uint j, d, dupper, dlower;
if (iobuf == NULL && (iobuf = malloc(sblock.fs_bsize * 3)) == NULL)
errx(37, "panic: cannot allocate I/O buffer");
if (iobuf == NULL) {
iobufsize = 2 * sblock.fs_bsize;
if ((iobuf = malloc(iobufsize)) == NULL)
errx(37, "panic: cannot allocate I/O buffer");
memset(iobuf, '\0', iobufsize);
}
/*
* Determine block bounds for cylinder group.
* Allow space for super block summary information in first
@ -374,13 +379,30 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag)
setbit(cg_inosused(&acg), ino);
acg.cg_cs.cs_nifree--;
}
/*
* Initialize the initial inode blocks.
*/
dp1 = (struct ufs1_dinode *)(void *)iobuf;
dp2 = (struct ufs2_dinode *)(void *)iobuf;
for (i = 0; i < acg.cg_initediblk; i++) {
if (sblock.fs_magic == FS_UFS1_MAGIC) {
dp1->di_gen = arc4random();
dp1++;
} else {
dp2->di_gen = arc4random();
dp2++;
}
}
wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno)), iobufsize, iobuf,
fso, Nflag);
/*
* For the old file system, we have to initialize all the inodes.
*/
if (sblock.fs_magic == FS_UFS1_MAGIC) {
bzero(iobuf, sblock.fs_bsize);
for (i = 0; i < sblock.fs_ipg / INOPF(&sblock);
i += sblock.fs_frag) {
if (sblock.fs_magic == FS_UFS1_MAGIC &&
sblock.fs_ipg > 2 * INOPB(&sblock)) {
for (i = 2 * sblock.fs_frag;
i < sblock.fs_ipg / INOPF(&sblock);
i += sblock.fs_frag) {
dp1 = (struct ufs1_dinode *)(void *)iobuf;
for (j = 0; j < INOPB(&sblock); j++) {
dp1->di_gen = arc4random();
@ -463,12 +485,8 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag)
*cs = acg.cg_cs;
cgckhash(&acg);
memcpy(iobuf, &acg, sblock.fs_cgsize);
memset(iobuf + sblock.fs_cgsize, '\0',
sblock.fs_bsize * 3 - sblock.fs_cgsize);
wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
sblock.fs_bsize * 3, iobuf, fso, Nflag);
wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), sblock.fs_cgsize, &acg,
fso, Nflag);
DBG_DUMP_CG(&sblock, "new cg", &acg);
DBG_LEAVE;

View File

@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd November 12, 2018
.Dd November 13, 2018
.Dt IPFW 8
.Os
.Sh NAME
@ -105,16 +105,6 @@ in-kernel NAT.
.Ar number
.Cm config
.Ar config-options
.Pp
.Nm
.Op Fl cfnNqS
.Oo
.Fl p Ar preproc
.Oo
.Ar preproc-flags
.Oc
.Oc
.Ar pathname
.Ss STATEFUL IPv6/IPv4 NETWORK ADDRESS AND PROTOCOL TRANSLATION
.Nm
.Oo Cm set Ar N Oc Cm nat64lsn Ar name Cm create Ar create-options
@ -166,6 +156,16 @@ in-kernel NAT.
.Cm internal talist
.Nm
.Cm internal vlist
.Ss LIST OF RULES AND PREPROCESSING
.Nm
.Op Fl cfnNqS
.Oo
.Fl p Ar preproc
.Oo
.Ar preproc-flags
.Oc
.Oc
.Ar pathname
.Sh DESCRIPTION
The
.Nm

View File

@ -1029,7 +1029,7 @@ goth:
void
iput(union dinode *ip, ino_t ino)
{
ufs2_daddr_t d;
union dinodep dp;
bread(&disk, part_ofs + fsbtodb(&sblock, cgtod(&sblock, 0)), (char *)&acg,
sblock.fs_cgsize);
@ -1043,20 +1043,15 @@ iput(union dinode *ip, ino_t ino)
err(1, "iput: cgput: %s", disk.d_error);
sblock.fs_cstotal.cs_nifree--;
fscs[0].cs_nifree--;
if (ino >= (unsigned long)sblock.fs_ipg * sblock.fs_ncg) {
printf("fsinit: inode value out of range (%ju).\n",
(uintmax_t)ino);
if (getinode(&disk, &dp, ino) == -1) {
printf("iput: %s\n", disk.d_error);
exit(32);
}
d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino));
bread(&disk, part_ofs + d, (char *)iobuf, sblock.fs_bsize);
if (sblock.fs_magic == FS_UFS1_MAGIC)
((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
ip->dp1;
*dp.dp1 = ip->dp1;
else
((struct ufs2_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
ip->dp2;
wtfs(d, sblock.fs_bsize, (char *)iobuf);
*dp.dp2 = ip->dp2;
putinode(&disk);
}
/*

View File

@ -679,41 +679,36 @@ dir_search(ufs2_daddr_t blk, int bytes)
static ino_t
journal_findfile(void)
{
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
union dinodep dp;
ino_t ino;
int mode;
void *ip;
int i;
if (getino(&disk, &ip, UFS_ROOTINO, &mode) != 0) {
warn("Failed to get root inode");
if (getinode(&disk, &dp, UFS_ROOTINO) != 0) {
warn("Failed to get root inode: %s", disk.d_error);
return (-1);
}
dp2 = ip;
dp1 = ip;
if (sblock.fs_magic == FS_UFS1_MAGIC) {
if ((off_t)dp1->di_size >= lblktosize(&sblock, UFS_NDADDR)) {
if ((off_t)dp.dp1->di_size >= lblktosize(&sblock, UFS_NDADDR)) {
warnx("UFS_ROOTINO extends beyond direct blocks.");
return (-1);
}
for (i = 0; i < UFS_NDADDR; i++) {
if (dp1->di_db[i] == 0)
if (dp.dp1->di_db[i] == 0)
break;
if ((ino = dir_search(dp1->di_db[i],
sblksize(&sblock, (off_t)dp1->di_size, i))) != 0)
if ((ino = dir_search(dp.dp1->di_db[i],
sblksize(&sblock, (off_t)dp.dp1->di_size, i))) != 0)
return (ino);
}
} else {
if ((off_t)dp2->di_size >= lblktosize(&sblock, UFS_NDADDR)) {
if ((off_t)dp.dp2->di_size >= lblktosize(&sblock, UFS_NDADDR)) {
warnx("UFS_ROOTINO extends beyond direct blocks.");
return (-1);
}
for (i = 0; i < UFS_NDADDR; i++) {
if (dp2->di_db[i] == 0)
if (dp.dp2->di_db[i] == 0)
break;
if ((ino = dir_search(dp2->di_db[i],
sblksize(&sblock, (off_t)dp2->di_size, i))) != 0)
if ((ino = dir_search(dp.dp2->di_db[i],
sblksize(&sblock, (off_t)dp.dp2->di_size, i))) != 0)
return (ino);
}
}
@ -795,23 +790,18 @@ dir_extend(ufs2_daddr_t blk, ufs2_daddr_t nblk, off_t size, ino_t ino)
static int
journal_insertfile(ino_t ino)
{
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
void *ip;
union dinodep dp;
ufs2_daddr_t nblk;
ufs2_daddr_t blk;
ufs_lbn_t lbn;
int size;
int mode;
int off;
if (getino(&disk, &ip, UFS_ROOTINO, &mode) != 0) {
warn("Failed to get root inode");
if (getinode(&disk, &dp, UFS_ROOTINO) != 0) {
warn("Failed to get root inode: %s", disk.d_error);
sbdirty();
return (-1);
}
dp2 = ip;
dp1 = ip;
blk = 0;
size = 0;
nblk = journal_balloc();
@ -824,15 +814,15 @@ journal_insertfile(ino_t ino)
* have to free them and extend the block.
*/
if (sblock.fs_magic == FS_UFS1_MAGIC) {
lbn = lblkno(&sblock, dp1->di_size);
off = blkoff(&sblock, dp1->di_size);
blk = dp1->di_db[lbn];
size = sblksize(&sblock, (off_t)dp1->di_size, lbn);
lbn = lblkno(&sblock, dp.dp1->di_size);
off = blkoff(&sblock, dp.dp1->di_size);
blk = dp.dp1->di_db[lbn];
size = sblksize(&sblock, (off_t)dp.dp1->di_size, lbn);
} else {
lbn = lblkno(&sblock, dp2->di_size);
off = blkoff(&sblock, dp2->di_size);
blk = dp2->di_db[lbn];
size = sblksize(&sblock, (off_t)dp2->di_size, lbn);
lbn = lblkno(&sblock, dp.dp2->di_size);
off = blkoff(&sblock, dp.dp2->di_size);
blk = dp.dp2->di_db[lbn];
size = sblksize(&sblock, (off_t)dp.dp2->di_size, lbn);
}
if (off != 0) {
if (dir_extend(blk, nblk, off, ino) == -1)
@ -843,16 +833,16 @@ journal_insertfile(ino_t ino)
return (-1);
}
if (sblock.fs_magic == FS_UFS1_MAGIC) {
dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE;
dp1->di_db[lbn] = nblk;
dp1->di_size = lblktosize(&sblock, lbn+1);
dp.dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE;
dp.dp1->di_db[lbn] = nblk;
dp.dp1->di_size = lblktosize(&sblock, lbn+1);
} else {
dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE;
dp2->di_db[lbn] = nblk;
dp2->di_size = lblktosize(&sblock, lbn+1);
dp.dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE;
dp.dp2->di_db[lbn] = nblk;
dp.dp2->di_size = lblktosize(&sblock, lbn+1);
}
if (putino(&disk) < 0) {
warn("Failed to write root inode");
if (putinode(&disk) < 0) {
warn("Failed to write root inode: %s", disk.d_error);
return (-1);
}
if (cgwrite(&disk) < 0) {
@ -916,11 +906,8 @@ indir_fill(ufs2_daddr_t blk, int level, int *resid)
static void
journal_clear(void)
{
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
union dinodep dp;
ino_t ino;
int mode;
void *ip;
ino = journal_findfile();
if (ino == (ino_t)-1 || ino == 0) {
@ -928,18 +915,16 @@ journal_clear(void)
return;
}
printf("Clearing journal flags from inode %ju\n", (uintmax_t)ino);
if (getino(&disk, &ip, ino, &mode) != 0) {
warn("Failed to get journal inode");
if (getinode(&disk, &dp, ino) != 0) {
warn("Failed to get journal inode: %s", disk.d_error);
return;
}
dp2 = ip;
dp1 = ip;
if (sblock.fs_magic == FS_UFS1_MAGIC)
dp1->di_flags = 0;
dp.dp1->di_flags = 0;
else
dp2->di_flags = 0;
if (putino(&disk) < 0) {
warn("Failed to write journal inode");
dp.dp2->di_flags = 0;
if (putinode(&disk) < 0) {
warn("Failed to write journal inode: %s", disk.d_error);
return;
}
}
@ -947,15 +932,12 @@ journal_clear(void)
static int
journal_alloc(int64_t size)
{
struct ufs1_dinode *dp1;
struct ufs2_dinode *dp2;
union dinodep dp;
ufs2_daddr_t blk;
void *ip;
struct cg *cgp;
int resid;
ino_t ino;
int blks;
int mode;
time_t utime;
int i;
@ -1007,8 +989,8 @@ journal_alloc(int64_t size)
break;
printf("Using inode %ju in cg %d for %jd byte journal\n",
(uintmax_t)ino, cgp->cg_cgx, size);
if (getino(&disk, &ip, ino, &mode) != 0) {
warn("Failed to get allocated inode");
if (getinode(&disk, &dp, ino) != 0) {
warn("Failed to get allocated inode: %s", disk.d_error);
sbdirty();
goto out;
}
@ -1017,39 +999,39 @@ journal_alloc(int64_t size)
* blocks and size uninitialized. This causes legacy
* fsck implementations to clear the inode.
*/
dp2 = ip;
dp1 = ip;
time(&utime);
if (sblock.fs_magic == FS_UFS1_MAGIC) {
bzero(dp1, sizeof(*dp1));
dp1->di_size = size;
dp1->di_mode = IFREG | IREAD;
dp1->di_nlink = 1;
dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP;
dp1->di_atime = utime;
dp1->di_mtime = utime;
dp1->di_ctime = utime;
bzero(dp.dp1, sizeof(*dp.dp1));
dp.dp1->di_size = size;
dp.dp1->di_mode = IFREG | IREAD;
dp.dp1->di_nlink = 1;
dp.dp1->di_flags =
SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP;
dp.dp1->di_atime = utime;
dp.dp1->di_mtime = utime;
dp.dp1->di_ctime = utime;
} else {
bzero(dp2, sizeof(*dp2));
dp2->di_size = size;
dp2->di_mode = IFREG | IREAD;
dp2->di_nlink = 1;
dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP;
dp2->di_atime = utime;
dp2->di_mtime = utime;
dp2->di_ctime = utime;
dp2->di_birthtime = utime;
bzero(dp.dp2, sizeof(*dp.dp2));
dp.dp2->di_size = size;
dp.dp2->di_mode = IFREG | IREAD;
dp.dp2->di_nlink = 1;
dp.dp2->di_flags =
SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP;
dp.dp2->di_atime = utime;
dp.dp2->di_mtime = utime;
dp.dp2->di_ctime = utime;
dp.dp2->di_birthtime = utime;
}
for (i = 0; i < UFS_NDADDR && resid; i++, resid--) {
blk = journal_balloc();
if (blk <= 0)
goto out;
if (sblock.fs_magic == FS_UFS1_MAGIC) {
dp1->di_db[i] = blk;
dp1->di_blocks++;
dp.dp1->di_db[i] = blk;
dp.dp1->di_blocks++;
} else {
dp2->di_db[i] = blk;
dp2->di_blocks++;
dp.dp2->di_db[i] = blk;
dp.dp2->di_blocks++;
}
}
for (i = 0; i < UFS_NIADDR && resid; i++) {
@ -1062,19 +1044,20 @@ journal_alloc(int64_t size)
goto out;
}
if (sblock.fs_magic == FS_UFS1_MAGIC) {
dp1->di_ib[i] = blk;
dp1->di_blocks += blks;
dp.dp1->di_ib[i] = blk;
dp.dp1->di_blocks += blks;
} else {
dp2->di_ib[i] = blk;
dp2->di_blocks += blks;
dp.dp2->di_ib[i] = blk;
dp.dp2->di_blocks += blks;
}
}
if (sblock.fs_magic == FS_UFS1_MAGIC)
dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize;
dp.dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize;
else
dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize;
if (putino(&disk) < 0) {
warn("Failed to write inode");
dp.dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize;
if (putinode(&disk) < 0) {
warn("Failed to write allocated inode: %s",
disk.d_error);
sbdirty();
return (-1);
}

View File

@ -86,9 +86,6 @@ ${X_}LINKER_FEATURES=
${X_}LINKER_FEATURES+= build-id
${X_}LINKER_FEATURES+= ifunc
.endif
.if ${${X_}LINKER_TYPE} != "lld" || ${${X_}LINKER_VERSION} >= 50000
${X_}LINKER_FEATURES+= filter
.endif
.if ${${X_}LINKER_TYPE} == "lld" && ${${X_}LINKER_VERSION} >= 60000
${X_}LINKER_FEATURES+= retpoline
.endif

View File

@ -75,6 +75,7 @@ _LIBRARIES= \
cam \
casper \
cap_dns \
cap_fileargs \
cap_grp \
cap_pwd \
cap_random \
@ -238,6 +239,7 @@ _DP_cam= sbuf
_DP_kvm= elf
_DP_casper= nv
_DP_cap_dns= nv
_DP_cap_fileargs= nv
_DP_cap_grp= nv
_DP_cap_pwd= nv
_DP_cap_random= nv

View File

@ -1581,6 +1581,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
identify_cpu1();
identify_hypervisor();
identify_cpu_fixup_bsp();
identify_cpu2();
initializecpucache();

View File

@ -372,3 +372,8 @@ device vmx # VMware VMXNET3 Ethernet
# Netmap provides direct access to TX/RX rings on supported NICs
device netmap # netmap(4) support
# evdev interface
options EVDEV_SUPPORT # evdev support in legacy drivers
device evdev # input event device support
device uinput # install /dev/uinput cdev

View File

@ -147,3 +147,8 @@ device bpf # Berkeley packet filter
# NOTE: XENHVM depends on xenpci. They must be added or removed together.
options XENHVM # Xen HVM kernel infrastructure
device xenpci # Xen HVM Hypervisor services driver
# evdev interface
options EVDEV_SUPPORT # evdev support in legacy drivers
device evdev # input event device support
device uinput # install /dev/uinput cdev

View File

@ -641,6 +641,11 @@ options LINPROCFS
# and PSEUDOFS)
options LINSYSFS
#####################################################################
# ZFS support
options ZFS
#####################################################################
# VM OPTIONS

View File

@ -11,7 +11,7 @@ all:
sysent: freebsd32_sysent.c freebsd32_syscall.h freebsd32_proto.h freebsd32_systrace_args.c
freebsd32_sysent.c freebsd32_syscalls.c freebsd32_syscall.h freebsd32_proto.h freebsd32_systrace_args.c : \
../../kern/makesyscalls.sh syscalls.master syscalls.conf capabilities.conf
../../kern/makesyscalls.sh syscalls.master syscalls.conf ../../kern/capabilities.conf
sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
clean:

View File

@ -1,298 +0,0 @@
##
## Copyright (c) 2008-2010 Robert N. M. Watson
## Copyright (c) 2016 The FreeBSD Foundation
## All rights reserved.
##
## This software was developed at the University of Cambridge Computer
## Laboratory with support from a grant from Google, Inc.
##
## Portions of this software were developed by Konstantin Belousov
## under sponsorship from the FreeBSD Foundation.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
##
## THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
## ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
## List of system calls enabled in freebsd32 capability mode, one name
## per line. See the original list in the sys/kern/capabilities.conf.
## Position of the compat syscall in this file must be identical to
## the master, to facilitate comparision and diagnostic.
##
## $FreeBSD$
##
__acl_aclcheck_fd
__acl_delete_fd
__acl_get_fd
__acl_set_fd
__mac_get_fd
#__mac_get_pid
__mac_get_proc
__mac_set_fd
__mac_set_proc
freebsd32___sysctl
freebsd32__umtx_op
abort2
accept
accept4
aio_cancel
freebsd32_aio_error
freebsd32_aio_fsync
freebsd32_aio_read
freebsd32_aio_return
freebsd32_aio_suspend
freebsd32_aio_waitcomplete
freebsd32_aio_write
#audit
bindat
cap_enter
cap_fcntls_get
cap_fcntls_limit
cap_getmode
freebsd32_cap_ioctls_get
freebsd32_cap_ioctls_limit
__cap_rights_get
cap_rights_limit
freebsd32_clock_getres
freebsd32_clock_gettime
close
closefrom
connectat
#cpuset
freebsd32_cpuset_getaffinity
#freebsd32_cpuset_getid
freebsd32_cpuset_setaffinity
#freebsd32_cpuset_setid
dup
dup2
extattr_delete_fd
extattr_get_fd
extattr_list_fd
extattr_set_fd
fchflags
fchmod
fchown
freebsd32_fcntl
freebsd32_fexecve
flock
fork
fpathconf
freebsd32_fstat
freebsd32_fstatat
freebsd32_getdirentries
freebsd32_fstatfs
freebsd32_mknodat
freebsd32_ftruncate
freebsd32_lseek
freebsd32_mmap
mmap
freebsd32_pread
freebsd32_pwrite
freebsd32_fstat
fstatfs
fsync
ftruncate
freebsd32_ftruncate
freebsd32_futimens
freebsd32_futimes
getaudit
getaudit_addr
getauid
freebsd32_getcontext
freebsd32_getdents
freebsd32_getdirentries
getdirentries
getdomainname
getdtablesize
getegid
geteuid
gethostid
gethostname
freebsd32_getitimer
getgid
getgroups
getlogin
freebsd32_getpagesize
getpeername
getpgid
getpgrp
getpid
getppid
getpriority
getrandom
getresgid
getresuid
getrlimit
freebsd32_getrusage
getsid
getsockname
getsockopt
freebsd32_gettimeofday
getuid
freebsd32_ioctl
issetugid
freebsd32_kevent
kill
freebsd32_kmq_notify
freebsd32_kmq_setattr
freebsd32_kmq_timedreceive
freebsd32_kmq_timedsend
kqueue
freebsd32_ktimer_create
ktimer_delete
ktimer_getoverrun
freebsd32_ktimer_gettime
freebsd32_ktimer_settime
#ktrace
freebsd32_lio_listio
listen
freebsd32_lseek
madvise
mincore
minherit
mlock
mlockall
freebsd32_mmap
freebsd32_mprotect
msync
munlock
munlockall
munmap
freebsd32_nanosleep
ntp_gettime
freebsd6_freebsd32_aio_read
freebsd6_freebsd32_aio_write
break
freebsd6_freebsd32_lio_listio
chflagsat
faccessat
fchmodat
fchownat
freebsd32_fstatat
freebsd32_futimesat
linkat
mkdirat
mkfifoat
mknodat
openat
readlinkat
renameat
symlinkat
unlinkat
freebsd32_utimensat
pdfork
pdgetpid
pdkill
#pdwait4 # not yet implemented
freebsd32_pipe
pipe2
poll
freebsd32_ppoll
freebsd32_posix_fallocate
freebsd32_pread
freebsd32_preadv
profil
#ptrace
freebsd32_pwrite
freebsd32_pwritev
read
freebsd32_readv
freebsd6_freebsd32_recv
freebsd32_recvfrom
freebsd32_recvmsg
rtprio
rtprio_thread
sbrk
sched_get_priority_max
sched_get_priority_min
sched_getparam
sched_getscheduler
freebsd32_sched_rr_get_interval
sched_setparam
sched_setscheduler
sched_yield
sctp_generic_recvmsg
sctp_generic_sendmsg
sctp_generic_sendmsg_iov
sctp_peeloff
freebsd32_pselect
freebsd32_select
freebsd6_freebsd32_send
freebsd32_sendfile
freebsd32_sendmsg
sendto
setaudit
setaudit_addr
setauid
freebsd32_setcontext
setegid
seteuid
setgid
freebsd32_setitimer
setpriority
setregid
setresgid
setresuid
setreuid
setrlimit
setsid
setsockopt
setuid
shm_open
shutdown
freebsd32_sigaction
freebsd32_sigaltstack
freebsd32_sigblock
freebsd32_sigpending
sigpending
freebsd32_sigprocmask
sigprocmask
freebsd32_sigqueue
sigqueue
freebsd32_sigreturn
freebsd32_sigsetmask
freebsd32_sigstack
freebsd32_sigsuspend
sigsuspend
freebsd32_sigtimedwait
freebsd32_sigvec
freebsd32_sigwaitinfo
sigwait
socket
socketpair
sstk
sync
sys_exit
freebsd32_sysarch
thr_create
thr_exit
thr_kill
#thr_kill2
freebsd32_thr_new
thr_self
thr_set_name
freebsd32_thr_suspend
thr_wake
umask
utrace
uuidgen
write
freebsd32_writev
yield

View File

@ -9,3 +9,5 @@ syscallprefix="FREEBSD32_SYS_"
switchname="freebsd32_sysent"
namesname="freebsd32_syscallnames"
systrace="freebsd32_systrace_args.c"
abi_func_prefix="freebsd32_"
capabilities_conf="../../kern/capabilities.conf"

View File

@ -55,21 +55,21 @@ DTBO=${DTSO:R:S/$/.dtbo/}
all: ${DTB} ${DTBO}
.if defined(DTS)
.export DTC
.export DTC ECHO
.for _dts in ${DTS}
${_dts:R:S/$/.dtb/}: ${_dts} ${OP_META}
@${ECHO} Generating ${.TARGET} from ${_dts}
@env ECHO=${ECHO} ${SYSDIR}/tools/fdt/make_dtb.sh ${SYSDIR} ${_dts} ${.OBJDIR}
@${SYSDIR}/tools/fdt/make_dtb.sh ${SYSDIR} ${_dts} ${.OBJDIR}
CLEANFILES+=${_dts:R:S/$/.dtb/}
.endfor
.endif
.if defined(DTSO)
.export DTC
.export DTC ECHO
.for _dtso in ${DTSO}
${_dtso:R:S/$/.dtbo/}: ${_dtso} ${OP_META}
@${ECHO} Generating ${.TARGET} from ${_dtso}
@env ECHO=${ECHO} ${SYSDIR}/tools/fdt/make_dtbo.sh ${SYSDIR} overlays/${_dtso} ${.OBJDIR}
@${SYSDIR}/tools/fdt/make_dtbo.sh ${SYSDIR} overlays/${_dtso} ${.OBJDIR}
CLEANFILES+=${_dtso:R:S/$/.dtbo/}
.endfor
.endif

View File

@ -1276,11 +1276,6 @@ nvpair_create_descriptor(const char *name, int value)
{
nvpair_t *nvp;
if (value < 0 || !fd_is_valid(value)) {
ERRNO_SET(EBADF);
return (NULL);
}
value = fcntl(value, F_DUPFD_CLOEXEC, 0);
if (value < 0)
return (NULL);
@ -1517,11 +1512,6 @@ nvpair_create_descriptor_array(const char *name, const int *value,
if (value[ii] == -1) {
fds[ii] = -1;
} else {
if (!fd_is_valid(value[ii])) {
ERRNO_SET(EBADF);
goto fail;
}
fds[ii] = fcntl(value[ii], F_DUPFD_CLOEXEC, 0);
if (fds[ii] == -1)
goto fail;
@ -2035,10 +2025,6 @@ nvpair_append_descriptor_array(nvpair_t *nvp, const int value)
NVPAIR_ASSERT(nvp);
PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR_ARRAY);
if (value < 0 || !fd_is_valid(value)) {
ERRNO_SET(EBADF);
return -1;
}
fd = fcntl(value, F_DUPFD_CLOEXEC, 0);
if (fd == -1) {
return (-1);

View File

@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <machine/cpufunc.h>
#include <machine/cputypes.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
@ -53,14 +54,21 @@ __FBSDID("$FreeBSD$");
#define SMN_ADDR_REG 0x60
#define SMN_DATA_REG 0x64
#define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450
#define PCI_DEVICE_ID_AMD_17H_ROOT_DF_F3 0x1463
#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT 0x15d0
#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT_DF_F3 0x15eb
struct amdsmn_softc {
struct mtx smn_lock;
};
static struct pciid {
uint32_t device_id;
uint16_t amdsmn_vendorid;
uint16_t amdsmn_deviceid;
} amdsmn_ids[] = {
{ 0x14501022 },
{ CPU_VENDOR_AMD, PCI_DEVICE_ID_AMD_17H_ROOT },
{ CPU_VENDOR_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT },
};
/*
@ -89,18 +97,21 @@ static driver_t amdsmn_driver = {
static devclass_t amdsmn_devclass;
DRIVER_MODULE(amdsmn, hostb, amdsmn_driver, amdsmn_devclass, NULL, NULL);
MODULE_VERSION(amdsmn, 1);
MODULE_PNP_INFO("W32:vendor/device", pci, amdsmn, amdsmn_ids,
MODULE_PNP_INFO("U16:vendor;U16:device", pci, amdsmn, amdsmn_ids,
nitems(amdsmn_ids));
static bool
amdsmn_match(device_t parent)
{
uint32_t devid;
uint16_t vendor, device;
size_t i;
devid = pci_get_devid(parent);
vendor = pci_get_vendor(parent);
device = pci_get_device(parent);
for (i = 0; i < nitems(amdsmn_ids); i++)
if (amdsmn_ids[i].device_id == devid)
if (vendor == amdsmn_ids[i].amdsmn_vendorid &&
device == amdsmn_ids[i].amdsmn_deviceid)
return (true);
return (false);
}

View File

@ -86,7 +86,10 @@ struct amdtemp_softc {
#define DEVICEID_AMD_MISC16 0x1533
#define DEVICEID_AMD_MISC16_M30H 0x1583
#define DEVICEID_AMD_MISC17 0x141d
#define DEVICEID_AMD_HOSTB17H 0x1450
#define DEVICEID_AMD_HOSTB17H_ROOT 0x1450
#define DEVICEID_AMD_HOSTB17H_DF_F3 0x1463
#define DEVICEID_AMD_HOSTB17H_M10H_ROOT 0x15d0
#define DEVICEID_AMD_HOSTB17H_M10H_DF_F3 0x15eb
static struct amdtemp_product {
uint16_t amdtemp_vendorid;
@ -101,7 +104,8 @@ static struct amdtemp_product {
{ VENDORID_AMD, DEVICEID_AMD_MISC16 },
{ VENDORID_AMD, DEVICEID_AMD_MISC16_M30H },
{ VENDORID_AMD, DEVICEID_AMD_MISC17 },
{ VENDORID_AMD, DEVICEID_AMD_HOSTB17H },
{ VENDORID_AMD, DEVICEID_AMD_HOSTB17H_ROOT },
{ VENDORID_AMD, DEVICEID_AMD_HOSTB17H_M10H_ROOT },
};
/*
@ -111,8 +115,15 @@ static struct amdtemp_product {
/*
* Reported Temperature, Family 17h
*
* According to AMD OSRR for 17H, section 4.2.1, bits 31-21 of this register
* provide the current temp. bit 19, when clear, means the temp is reported in
* a range 0.."225C" (probable typo for 255C), and when set changes the range
* to -49..206C.
*/
#define AMDTEMP_17H_CUR_TMP 0x59800
#define AMDTEMP_17H_CUR_TMP 0x59800
#define AMDTEMP_17H_CUR_TMP_RANGE_SEL (1 << 19)
#define AMDTEMP_17H_CUR_TMP_RANGE_OFF 490
/*
* Thermaltrip Status Register (Family 0Fh only)
@ -591,13 +602,15 @@ static int32_t
amdtemp_gettemp17h(device_t dev, amdsensor_t sensor)
{
struct amdtemp_softc *sc = device_get_softc(dev);
uint32_t temp;
uint32_t temp, val;
int error;
error = amdsmn_read(sc->sc_smn, AMDTEMP_17H_CUR_TMP, &temp);
error = amdsmn_read(sc->sc_smn, AMDTEMP_17H_CUR_TMP, &val);
KASSERT(error == 0, ("amdsmn_read"));
temp = ((temp >> 21) & 0x7ff) * 5 / 4;
temp = ((val >> 21) & 0x7ff) * 5 / 4;
if ((val & AMDTEMP_17H_CUR_TMP_RANGE_SEL) != 0)
temp -= AMDTEMP_17H_CUR_TMP_RANGE_OFF;
temp += AMDTEMP_ZERO_C_TO_K + sc->sc_offset * 10;
return (temp);

View File

@ -492,6 +492,9 @@ cxgbe_netmap_off(struct adapter *sc, struct vi_info *vi, struct ifnet *ifp,
ASSERT_SYNCHRONIZED_OP(sc);
if (!nm_netmap_on(na))
return (0);
if ((vi->flags & VI_INIT_DONE) == 0)
return (0);

View File

@ -535,11 +535,11 @@ nvme_ns_construct(struct nvme_namespace *ns, uint32_t id,
if (!mtx_initialized(&ns->lock))
mtx_init(&ns->lock, "nvme ns lock", NULL, MTX_DEF);
status.done = FALSE;
status.done = 0;
nvme_ctrlr_cmd_identify_namespace(ctrlr, id, &ns->data,
nvme_completion_poll_cb, &status);
while (status.done == FALSE)
DELAY(5);
while (!atomic_load_acq_int(&status.done))
pause("nvme", 1);
if (nvme_completion_is_error(&status.cpl)) {
nvme_printf(ctrlr, "nvme_identify_namespace failed\n");
return (ENXIO);

View File

@ -445,9 +445,7 @@ tws_setup_intr(struct tws_softc *sc, int irqs)
if (!(sc->intr_handle[i])) {
if ((error = bus_setup_intr(sc->tws_dev, sc->irq_res[i],
INTR_TYPE_CAM | INTR_MPSAFE,
#if (__FreeBSD_version >= 700000)
NULL,
#endif
tws_intr, sc, &sc->intr_handle[i]))) {
tws_log(sc, SETUP_INTR_RES);
return(FAILURE);

View File

@ -160,9 +160,7 @@ tws_cam_attach(struct tws_softc *sc)
*/
sc->sim = cam_sim_alloc(tws_action, tws_poll, "tws", sc,
device_get_unit(sc->tws_dev),
#if (__FreeBSD_version >= 700000)
&sc->sim_lock,
#endif
tws_cam_depth, 1, devq);
/* 1, 1, devq); */
if (sc->sim == NULL) {
@ -172,9 +170,7 @@ tws_cam_attach(struct tws_softc *sc)
/* Register the bus. */
mtx_lock(&sc->sim_lock);
if (xpt_bus_register(sc->sim,
#if (__FreeBSD_version >= 700000)
sc->tws_dev,
#endif
0) != CAM_SUCCESS) {
cam_sim_free(sc->sim, TRUE); /* passing true will free the devq */
sc->sim = NULL; /* so cam_detach will not try to free it */
@ -269,7 +265,6 @@ tws_action(struct cam_sim *sim, union ccb *ccb)
{
TWS_TRACE_DEBUG(sc, "get tran settings", sim, ccb);
#if (__FreeBSD_version >= 700000 )
ccb->cts.protocol = PROTO_SCSI;
ccb->cts.protocol_version = SCSI_REV_2;
ccb->cts.transport = XPORT_SPI;
@ -279,10 +274,6 @@ tws_action(struct cam_sim *sim, union ccb *ccb)
ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB;
ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
#else
ccb->cts.valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
ccb->cts.flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
#endif
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
@ -314,13 +305,11 @@ tws_action(struct cam_sim *sim, union ccb *ccb)
strlcpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN);
strlcpy(ccb->cpi.hba_vid, "3ware", HBA_IDLEN);
strlcpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN);
#if (__FreeBSD_version >= 700000 )
ccb->cpi.transport = XPORT_SPI;
ccb->cpi.transport_version = 2;
ccb->cpi.protocol = PROTO_SCSI;
ccb->cpi.protocol_version = SCSI_REV_2;
ccb->cpi.maxio = TWS_MAX_IO_SIZE;
#endif
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);

View File

@ -131,12 +131,5 @@ struct error_desc {
/* ------------------------ */
#if (__FreeBSD_version >= 700000)
#include <sys/clock.h>
#define TWS_LOCAL_TIME (time_second - utc_offset())
#else
#include <machine/clock.h>
#define TWS_LOCAL_TIME (time_second - (tz_minuteswest * 60) - \
(wall_cmos_clock ? adjkerntz : 0))
#endif

View File

@ -5,9 +5,9 @@ SYSDIR?=${SRCTOP}/sys
test-dts:
.for dts in ${DTS}
@env MACHINE=`basename ${.CURDIR}` ${SYSDIR}/tools/fdt/make_dtb.sh ${SYSDIR} ${dts} /tmp
.endfor
test-dtso:
.for dtso in ${DTSO}
@env MACHINE=`basename ${.CURDIR}` ${SYSDIR}/tools/fdt/make_dtbo.sh ${SYSDIR} ${dtso} /tmp
.endfor

View File

@ -1,6 +1,6 @@
# $FreeBSD$
DTS!=ls *.dts
DTS!=ls ${.CURDIR}/*.dts
all: test-dts

3
sys/dts/arm/Makefile.inc Normal file
View File

@ -0,0 +1,3 @@
# $FreeBSD$
.include "../Makefile.inc"

View File

@ -1,6 +1,6 @@
# $FreeBSD$
DTSO!=ls *.dtso
DTSO!=ls ${.CURDIR}/*.dtso
all: test-dtso

View File

@ -1,6 +1,6 @@
# $FreeBSD$
DTS!=ls *.dts
DTS!=ls ${.CURDIR}/*.dts
all: test-dts

View File

@ -0,0 +1,3 @@
# $FreeBSD$
.include "../Makefile.inc"

View File

@ -1,6 +1,6 @@
# $FreeBSD$
DTSO!=ls *.dtso
DTSO!=ls ${.CURDIR}/*.dtso
all: test-dtso

View File

@ -1,6 +1,6 @@
# $FreeBSD$
DTS!=ls *.dts
DTS!=ls ${.CURDIR}/*.dts
all: test-dts

View File

@ -1,6 +1,6 @@
# $FreeBSD$
DTS!=ls *.dts
DTS!=ls ${.CURDIR}/*.dts
all: test-dts

View File

@ -366,3 +366,8 @@ device xenpci # Xen HVM Hypervisor services driver
# VMware support
device vmx # VMware VMXNET3 Ethernet
# evdev interface
options EVDEV_SUPPORT # evdev support in legacy drivers
device evdev # input event device support
device uinput # install /dev/uinput cdev

View File

@ -148,3 +148,8 @@ device bpf # Berkeley packet filter
# NOTE: XENHVM depends on xenpci. They must be added or removed together.
options XENHVM # Xen HVM kernel infrastructure
device xenpci # Xen HVM Hypervisor services driver
# evdev interface
options EVDEV_SUPPORT # evdev support in legacy drivers
device evdev # input event device support
device uinput # install /dev/uinput cdev

View File

@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <sys/assym.h>
#include <sys/proc.h>
OFFSYM(td_pre_epoch_prio, thread, u_char);
OFFSYM(td_priority, thread, u_char);
OFFSYM(td_epochnest, thread, u_char);
OFFSYM(td_critnest, thread, u_int);

View File

@ -249,6 +249,7 @@ init_static_kenv(char *buf, size_t len)
{
char *eval;
KASSERT(!dynamic_kenv, ("kenv: dynamic_kenv already initialized"));
/*
* Give the static environment a chance to disable the loader(8)
* environment first. This is done with loader_env.disabled=1.

View File

@ -486,7 +486,7 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t v)
int64_t all_time = 0;
#endif
#if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING)
int doing_lockprof;
int doing_lockprof = 0;
#endif
td = curthread;
@ -690,7 +690,7 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t v)
int64_t spin_time = 0;
#endif
#if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING)
int doing_lockprof;
int doing_lockprof = 0;
#endif
tid = (uintptr_t)curthread;

View File

@ -742,7 +742,7 @@ _rm_assert(const struct rmlock *rm, int what, const char *file, int line)
{
int count;
if (panicstr != NULL)
if (SCHEDULER_STOPPED())
return;
switch (what) {
case RA_LOCKED:

View File

@ -445,7 +445,7 @@ __rw_rlock_hard(struct rwlock *rw, struct thread *td, uintptr_t v
int64_t all_time = 0;
#endif
#if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING)
uintptr_t state;
uintptr_t state = 0;
int doing_lockprof = 0;
#endif
@ -913,7 +913,7 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t v LOCK_FILE_LINE_ARG_DEF)
int64_t all_time = 0;
#endif
#if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING)
uintptr_t state;
uintptr_t state = 0;
int doing_lockprof = 0;
#endif
int extra_work = 0;
@ -1439,7 +1439,7 @@ __rw_assert(const volatile uintptr_t *c, int what, const char *file, int line)
{
const struct rwlock *rw;
if (panicstr != NULL)
if (SCHEDULER_STOPPED())
return;
rw = rwlock2rw(c);

View File

@ -1416,7 +1416,7 @@ _sx_assert(const struct sx *sx, int what, const char *file, int line)
int slocked = 0;
#endif
if (panicstr != NULL)
if (SCHEDULER_STOPPED())
return;
switch (what) {
case SA_SLOCKED:

View File

@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/epoch.h>
#include <sys/rangelock.h>
#include <sys/resourcevar.h>
#include <sys/sdt.h>
@ -272,6 +273,7 @@ thread_init(void *mem, int size, int flags)
td->td_rlqe = NULL;
EVENTHANDLER_DIRECT_INVOKE(thread_init, td);
umtx_thread_init(td);
epoch_thread_init(td);
td->td_kstack = 0;
td->td_sel = NULL;
return (0);
@ -291,6 +293,7 @@ thread_fini(void *mem, int size)
turnstile_free(td->td_turnstile);
sleepq_free(td->td_sleepqueue);
umtx_thread_fini(td);
epoch_thread_fini(td);
seltdfini(td);
}

View File

@ -45,13 +45,7 @@ sysarg="sysarg.switch.$$"
sysprotoend="sysprotoend.$$"
systracetmp="systrace.$$"
systraceret="systraceret.$$"
if [ -r capabilities.conf ]; then
capenabled=`egrep -v '^#|^$' capabilities.conf`
capenabled=`echo $capenabled | sed 's/ /,/g'`
else
capenabled=""
fi
capabilities_conf="capabilities.conf"
trap "rm $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4 $syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl $syscompat10 $syscompat10dcl $syscompat11 $syscompat11dcl $sysent $sysinc $sysarg $sysprotoend $systracetmp $systraceret" 0
@ -67,6 +61,13 @@ if [ -n "$2" ]; then
. $2
fi
if [ -r $capabilities_conf ]; then
capenabled=`egrep -v '^#|^$' $capabilities_conf`
capenabled=`echo $capenabled | sed 's/ /,/g'`
else
capenabled=""
fi
sed -e '
# FreeBSD ID, includes, comments, and blank lines
/.*\$FreeBSD/b done_joining
@ -137,6 +138,7 @@ sed -e '
switchname = \"$switchname\"
namesname = \"$namesname\"
infile = \"$1\"
abi_func_prefix = \"$abi_func_prefix\"
capenabled_string = \"$capenabled\"
"'
@ -381,7 +383,8 @@ sed -e '
# from it.
#
for (cap in capenabled) {
if (funcname == capenabled[cap]) {
if (funcname == capenabled[cap] ||
funcname == abi_func_prefix capenabled[cap]) {
flags = "SYF_CAPENABLED";
break;
}

View File

@ -46,11 +46,11 @@
* upper bound on a potential allocation, but not necessarily a tight upper
* bound.
*
* The radix tree also implements two collapsed states for meta nodes:
* the ALL-ALLOCATED state and the ALL-FREE state. If a meta node is
* in either of these two states, all information contained underneath
* the node is considered stale. These states are used to optimize
* allocation and freeing operations.
* The bitmap field in each node directs the search for available blocks.
* For a leaf node, a bit is set if the corresponding block is free. For a
* meta node, a bit is set if the corresponding subtree contains a free
* block somewhere within it. The search at a meta node considers only
* children of that node that represent a range that includes a free block.
*
* The hinting greatly increases code efficiency for allocations while
* the general radix structure optimizes both allocations and frees. The
@ -59,19 +59,19 @@
*
* The blist code wires all necessary memory at creation time. Neither
* allocations nor frees require interaction with the memory subsystem.
* The non-blocking features of the blist code are used in the swap code
* (vm/swap_pager.c).
* The non-blocking nature of allocations and frees is required by swap
* code (vm/swap_pager.c).
*
* LAYOUT: The radix tree is laid out recursively using a
* linear array. Each meta node is immediately followed (laid out
* sequentially in memory) by BLIST_META_RADIX lower level nodes. This
* is a recursive structure but one that can be easily scanned through
* a very simple 'skip' calculation. In order to support large radixes,
* portions of the tree may reside outside our memory allocation. We
* handle this with an early-termination optimization (when bighint is
* set to -1) on the scan. The memory allocation is only large enough
* to cover the number of blocks requested at creation time even if it
* must be encompassed in larger root-node radix.
* LAYOUT: The radix tree is laid out recursively using a linear array.
* Each meta node is immediately followed (laid out sequentially in
* memory) by BLIST_META_RADIX lower level nodes. This is a recursive
* structure but one that can be easily scanned through a very simple
* 'skip' calculation. The memory allocation is only large enough to
* cover the number of blocks requested at creation time. Nodes that
* represent blocks beyond that limit, nodes that would never be read
* or written, are not allocated, so that the last of the
* BLIST_META_RADIX lower level nodes of a some nodes may not be
* allocated.
*
* NOTE: the allocator cannot currently allocate more than
* BLIST_BMAP_RADIX blocks per call. It will panic with 'allocation too
@ -105,6 +105,7 @@ __FBSDID("$FreeBSD$");
#define BLIST_DEBUG
#endif
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/malloc.h>
#include <sys/sbuf.h>
@ -118,7 +119,7 @@ __FBSDID("$FreeBSD$");
#define bitcount64(x) __bitcount64((uint64_t)(x))
#define malloc(a,b,c) calloc(a, 1)
#define free(a,b) free(a)
static __inline int imax(int a, int b) { return (a > b ? a : b); }
#define ummin(a,b) ((a) < (b) ? (a) : (b))
#include <sys/blist.h>
@ -178,6 +179,18 @@ radix_to_skip(daddr_t radix)
((BLIST_BMAP_RADIX / BLIST_META_RADIX) * BLIST_META_MASK));
}
/*
* Provide a mask with count bits set, starting as position n.
*/
static inline u_daddr_t
bitrange(int n, int count)
{
return (((u_daddr_t)-1 << n) &
((u_daddr_t)-1 >> (BLIST_BMAP_RADIX - (n + count))));
}
/*
* Use binary search, or a faster method, to find the 1 bit in a u_daddr_t.
* Assumes that the argument has only one bit set.
@ -220,9 +233,7 @@ blist_t
blist_create(daddr_t blocks, int flags)
{
blist_t bl;
daddr_t i, last_block;
u_daddr_t nodes, radix, skip;
int digit;
u_daddr_t nodes, radix;
if (blocks == 0)
panic("invalid block count");
@ -230,30 +241,13 @@ blist_create(daddr_t blocks, int flags)
/*
* Calculate the radix and node count used for scanning.
*/
last_block = blocks - 1;
nodes = 1;
radix = BLIST_BMAP_RADIX;
while (radix < blocks) {
if (((last_block / radix + 1) & BLIST_META_MASK) != 0)
/*
* We must widen the blist to avoid partially
* filled nodes.
*/
last_block |= radix - 1;
while (radix <= blocks) {
nodes += 1 + (blocks - 1) / radix;
radix *= BLIST_META_RADIX;
}
/*
* Count the meta-nodes in the expanded tree, including the final
* terminator, from the bottom level up to the root.
*/
nodes = 1;
if (radix - blocks >= BLIST_BMAP_RADIX)
nodes++;
last_block /= BLIST_BMAP_RADIX;
while (last_block > 0) {
nodes += last_block + 1;
last_block /= BLIST_META_RADIX;
}
bl = malloc(offsetof(struct blist, bl_root[nodes]), M_SWAP, flags |
M_ZERO);
if (bl == NULL)
@ -261,33 +255,6 @@ blist_create(daddr_t blocks, int flags)
bl->bl_blocks = blocks;
bl->bl_radix = radix;
bl->bl_cursor = 0;
/*
* Initialize the empty tree by filling in root values, then initialize
* just the terminators in the rest of the tree.
*/
bl->bl_root[0].bm_bighint = 0;
if (radix == BLIST_BMAP_RADIX)
bl->bl_root[0].u.bmu_bitmap = 0;
else
bl->bl_root[0].u.bmu_avail = 0;
last_block = blocks - 1;
i = 0;
while (radix > BLIST_BMAP_RADIX) {
radix /= BLIST_META_RADIX;
skip = radix_to_skip(radix);
digit = last_block / radix;
i += 1 + digit * skip;
if (digit != BLIST_META_MASK) {
/*
* Add a terminator.
*/
bl->bl_root[i + skip].bm_bighint = (daddr_t)-1;
bl->bl_root[i + skip].u.bmu_bitmap = 0;
}
last_block %= radix;
}
#if defined(BLIST_DEBUG)
printf(
@ -321,6 +288,9 @@ blist_alloc(blist_t bl, daddr_t count)
{
daddr_t blk;
if (count > BLIST_MAX_ALLOC)
panic("allocation too large");
/*
* This loop iterates at most twice. An allocation failure in the
* first iteration leads to a second iteration only if the cursor was
@ -331,12 +301,13 @@ blist_alloc(blist_t bl, daddr_t count)
blk = blst_meta_alloc(bl->bl_root, bl->bl_cursor, count,
bl->bl_radix);
if (blk != SWAPBLK_NONE) {
bl->bl_avail -= count;
bl->bl_cursor = blk + count;
if (bl->bl_cursor == bl->bl_blocks)
bl->bl_cursor = 0;
return (blk);
} else if (bl->bl_cursor != 0)
bl->bl_cursor = 0;
}
bl->bl_cursor = 0;
}
return (SWAPBLK_NONE);
}
@ -348,10 +319,7 @@ daddr_t
blist_avail(blist_t bl)
{
if (bl->bl_radix == BLIST_BMAP_RADIX)
return (bitcount64(bl->bl_root->u.bmu_bitmap));
else
return (bl->bl_root->u.bmu_avail);
return (bl->bl_avail);
}
/*
@ -363,7 +331,10 @@ void
blist_free(blist_t bl, daddr_t blkno, daddr_t count)
{
if (blkno < 0 || blkno + count > bl->bl_blocks)
panic("freeing invalid range");
blst_meta_free(bl->bl_root, blkno, count, bl->bl_radix);
bl->bl_avail += count;
}
/*
@ -375,8 +346,13 @@ blist_free(blist_t bl, daddr_t blkno, daddr_t count)
daddr_t
blist_fill(blist_t bl, daddr_t blkno, daddr_t count)
{
daddr_t filled;
return (blst_meta_fill(bl->bl_root, blkno, count, bl->bl_radix));
if (blkno < 0 || blkno + count > bl->bl_blocks)
panic("filling invalid range");
filled = blst_meta_fill(bl->bl_root, blkno, count, bl->bl_radix);
bl->bl_avail -= filled;
return (filled);
}
/*
@ -414,8 +390,11 @@ blist_resize(blist_t *pbl, daddr_t count, int freenew, int flags)
void
blist_print(blist_t bl)
{
printf("BLIST cursor = %08jx {\n", (uintmax_t)bl->bl_cursor);
blst_radix_print(bl->bl_root, 0, bl->bl_radix, 4);
printf("BLIST avail = %jd, cursor = %08jx {\n",
(uintmax_t)bl->bl_avail, (uintmax_t)bl->bl_cursor);
if (bl->bl_root->bm_bitmap != 0)
blst_radix_print(bl->bl_root, 0, bl->bl_radix, 4);
printf("}\n");
}
@ -569,16 +548,11 @@ blist_stats(blist_t bl, struct sbuf *s)
* Check for skippable subtrees starting at i.
*/
while (radix > BLIST_BMAP_RADIX) {
if (bl->bl_root[nodes].u.bmu_avail == 0) {
if (bl->bl_root[nodes].bm_bitmap == 0) {
if (gap_stats_counting(stats))
update_gap_stats(stats, i);
break;
}
if (bl->bl_root[nodes].u.bmu_avail == radix) {
if (!gap_stats_counting(stats))
update_gap_stats(stats, i);
break;
}
/*
* Skip subtree root.
@ -590,7 +564,7 @@ blist_stats(blist_t bl, struct sbuf *s)
/*
* Scan leaf.
*/
mask = bl->bl_root[nodes].u.bmu_bitmap;
mask = bl->bl_root[nodes].bm_bitmap;
diff = mask ^ (mask << 1);
if (gap_stats_counting(stats))
diff ^= 1;
@ -618,7 +592,57 @@ blist_stats(blist_t bl, struct sbuf *s)
*/
/*
* blist_leaf_alloc() - allocate at a leaf in the radix tree (a bitmap).
* BLST_NEXT_LEAF_ALLOC() - allocate the first few blocks in the next leaf.
*
* 'scan' is a leaf node, associated with a block containing 'blk'.
* The next leaf node could be adjacent, or several nodes away if the
* least common ancestor of 'scan' and its neighbor is several levels
* up. Use 'blk' to determine how many meta-nodes lie between the
* leaves. If the next leaf has enough initial bits set, clear them
* and clear the bits in the meta nodes on the path up to the least
* common ancestor to mark any subtrees made completely empty.
*/
static int
blst_next_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
{
blmeta_t *next;
daddr_t skip;
u_daddr_t radix;
int digit;
next = scan + 1;
blk += BLIST_BMAP_RADIX;
radix = BLIST_BMAP_RADIX;
while ((digit = ((blk / radix) & BLIST_META_MASK)) == 0 &&
(next->bm_bitmap & 1) == 1) {
next++;
radix *= BLIST_META_RADIX;
}
if (((next->bm_bitmap + 1) & ~((u_daddr_t)-1 << count)) != 0) {
/*
* The next leaf doesn't have enough free blocks at the
* beginning to complete the spanning allocation.
*/
return (ENOMEM);
}
/* Clear the first 'count' bits in the next leaf to allocate. */
next->bm_bitmap &= (u_daddr_t)-1 << count;
/*
* Update bitmaps of next-ancestors, up to least common ancestor.
*/
skip = radix_to_skip(radix);
while (radix != BLIST_BMAP_RADIX && next->bm_bitmap == 0) {
(--next)->bm_bitmap ^= 1;
radix /= BLIST_META_RADIX;
}
if (next->bm_bitmap == 0)
scan[-digit * skip].bm_bitmap ^= (u_daddr_t)1 << digit;
return (0);
}
/*
* BLST_LEAF_ALLOC() - allocate at a leaf in the radix tree (a bitmap).
*
* This is the core of the allocator and is optimized for the
* BLIST_BMAP_RADIX block allocation case. Otherwise, execution
@ -633,15 +657,15 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
range1 = 0;
count1 = count - 1;
num_shifts = fls(count1);
mask = scan->u.bmu_bitmap;
mask = scan->bm_bitmap;
while ((-mask & ~mask) != 0 && num_shifts > 0) {
/*
* If bit i is set in mask, then bits in [i, i+range1] are set
* in scan->u.bmu_bitmap. The value of range1 is equal to
* in scan->bm_bitmap. The value of range1 is equal to
* count1 >> num_shifts. Grow range and reduce num_shifts to 0,
* while preserving these invariants. The updates to mask leave
* fewer bits set, but each bit that remains set represents a
* longer string of consecutive bits set in scan->u.bmu_bitmap.
* longer string of consecutive bits set in scan->bm_bitmap.
* If more updates to mask cannot clear more bits, because mask
* is partitioned with all 0 bits preceding all 1 bits, the loop
* terminates immediately.
@ -685,31 +709,14 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
* An allocation within this leaf is impossible, so a successful
* allocation depends on the next leaf providing some of the blocks.
*/
if (((blk / BLIST_BMAP_RADIX + 1) & BLIST_META_MASK) == 0) {
if (blst_next_leaf_alloc(scan, blk, hi - BLIST_BMAP_RADIX) != 0)
/*
* The next leaf has a different meta-node parent, so it
* is not necessarily initialized. Update bighint,
* comparing the range found at the end of mask to the
* largest earlier range that could have been made to
* vanish in the initial processing of mask.
*/
scan->bm_bighint = imax(BLIST_BMAP_RADIX - lo, range1);
return (SWAPBLK_NONE);
}
hi -= BLIST_BMAP_RADIX;
if (((scan[1].u.bmu_bitmap + 1) & ~((u_daddr_t)-1 << hi)) != 0) {
/*
* The next leaf doesn't have enough free blocks at the
* beginning to complete the spanning allocation. The
* hint cannot be updated, because the same allocation
* request could be satisfied later, by this leaf, if
* the state of the next leaf changes, and without any
* changes to this leaf.
* The hint cannot be updated, because the same
* allocation request could be satisfied later, by this
* leaf, if the state of the next leaf changes, and
* without any changes to this leaf.
*/
return (SWAPBLK_NONE);
}
/* Clear the first 'hi' bits in the next leaf, allocating them. */
scan[1].u.bmu_bitmap &= (u_daddr_t)-1 << hi;
hi = BLIST_BMAP_RADIX;
}
@ -724,12 +731,9 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
} else {
/* Clear the bits of mask at position 'hi' and higher. */
mask &= (u_daddr_t)-1 >> (BLIST_BMAP_RADIX - hi);
/* If this allocation uses all the bits, clear the hint. */
if (mask == scan->u.bmu_bitmap)
scan->bm_bighint = 0;
}
/* Clear the allocated bits from this leaf. */
scan->u.bmu_bitmap &= ~mask;
scan->bm_bitmap &= ~mask;
return ((blk & ~BLIST_BMAP_MASK) + lo);
}
@ -744,81 +748,61 @@ blst_leaf_alloc(blmeta_t *scan, daddr_t blk, int count)
static daddr_t
blst_meta_alloc(blmeta_t *scan, daddr_t cursor, daddr_t count, u_daddr_t radix)
{
daddr_t blk, i, next_skip, r, skip;
int child;
daddr_t blk, i, r, skip;
u_daddr_t bit, mask;
bool scan_from_start;
int digit;
if (radix == BLIST_BMAP_RADIX)
return (blst_leaf_alloc(scan, cursor, count));
if (scan->u.bmu_avail < count) {
/*
* The meta node's hint must be too large if the allocation
* exceeds the number of free blocks. Reduce the hint, and
* return failure.
*/
scan->bm_bighint = scan->u.bmu_avail;
return (SWAPBLK_NONE);
}
blk = cursor & -radix;
scan_from_start = (cursor == blk);
radix /= BLIST_META_RADIX;
skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
mask = scan->bm_bitmap;
/* Discard any candidates that appear before cursor. */
digit = (cursor / radix) & BLIST_META_MASK;
mask &= (u_daddr_t)-1 << digit;
/*
* An ALL-FREE meta node requires special handling before allocating
* any of its blocks.
* If the first try is for a block that includes the cursor, pre-undo
* the digit * radix offset in the first call; otherwise, ignore the
* cursor entirely.
*/
if (scan->u.bmu_avail == radix) {
radix /= BLIST_META_RADIX;
if (((mask >> digit) & 1) == 1)
cursor -= digit * radix;
else
cursor = blk;
/*
* Reinitialize each of the meta node's children. An ALL-FREE
* meta node cannot have a terminator in any subtree.
*/
for (i = 1; i < skip; i += next_skip) {
if (next_skip == 1)
scan[i].u.bmu_bitmap = (u_daddr_t)-1;
else
scan[i].u.bmu_avail = radix;
scan[i].bm_bighint = radix;
}
} else {
radix /= BLIST_META_RADIX;
}
if (count > radix) {
/*
* The allocation exceeds the number of blocks that are
* managed by a subtree of this meta node.
*/
panic("allocation too large");
}
scan_from_start = cursor == blk;
child = (cursor - blk) / radix;
blk += child * radix;
for (i = 1 + child * next_skip; i < skip; i += next_skip) {
/*
* Examine the nonempty subtree associated with each bit set in mask.
*/
do {
bit = mask & -mask;
digit = bitpos(bit);
i = 1 + digit * skip;
if (count <= scan[i].bm_bighint) {
/*
* The allocation might fit beginning in the i'th subtree.
*/
r = blst_meta_alloc(&scan[i],
cursor > blk ? cursor : blk, count, radix);
r = blst_meta_alloc(&scan[i], cursor + digit * radix,
count, radix);
if (r != SWAPBLK_NONE) {
scan->u.bmu_avail -= count;
if (scan[i].bm_bitmap == 0)
scan->bm_bitmap ^= bit;
return (r);
}
} else if (scan[i].bm_bighint == (daddr_t)-1) {
/*
* Terminator
*/
break;
}
blk += radix;
}
cursor = blk;
} while ((mask ^= bit) != 0);
/*
* We couldn't allocate count in this subtree, update bighint.
* We couldn't allocate count in this subtree. If the whole tree was
* scanned, and the last tree node is allocated, update bighint.
*/
if (scan_from_start && scan->bm_bighint >= count)
if (scan_from_start && !(digit == BLIST_META_RADIX - 1 &&
scan[i].bm_bighint == BLIST_MAX_ALLOC))
scan->bm_bighint = count - 1;
return (SWAPBLK_NONE);
@ -832,7 +816,6 @@ static void
blst_leaf_free(blmeta_t *scan, daddr_t blk, int count)
{
u_daddr_t mask;
int n;
/*
* free some data in this bitmap
@ -840,20 +823,10 @@ blst_leaf_free(blmeta_t *scan, daddr_t blk, int count)
* \_________/\__/
* count n
*/
n = blk & BLIST_BMAP_MASK;
mask = ((u_daddr_t)-1 << n) &
((u_daddr_t)-1 >> (BLIST_BMAP_RADIX - count - n));
if (scan->u.bmu_bitmap & mask)
mask = bitrange(blk & BLIST_BMAP_MASK, count);
if (scan->bm_bitmap & mask)
panic("freeing free block");
scan->u.bmu_bitmap |= mask;
/*
* We could probably do a better job here. We are required to make
* bighint at least as large as the biggest contiguous block of
* data. If we just shoehorn it, a little extra overhead will
* be incured on the next allocation (but only that one typically).
*/
scan->bm_bighint = BLIST_BMAP_RADIX;
scan->bm_bitmap |= mask;
}
/*
@ -869,79 +842,37 @@ blst_leaf_free(blmeta_t *scan, daddr_t blk, int count)
static void
blst_meta_free(blmeta_t *scan, daddr_t freeBlk, daddr_t count, u_daddr_t radix)
{
daddr_t blk, i, next_skip, skip, v;
int child;
daddr_t blk, endBlk, i, skip;
int digit, endDigit;
/*
* We could probably do a better job here. We are required to make
* bighint at least as large as the biggest allocable block of data.
* If we just shoehorn it, a little extra overhead will be incurred
* on the next allocation (but only that one typically).
*/
scan->bm_bighint = BLIST_MAX_ALLOC;
if (scan->bm_bighint == (daddr_t)-1)
panic("freeing invalid range");
if (radix == BLIST_BMAP_RADIX)
return (blst_leaf_free(scan, freeBlk, count));
skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
if (scan->u.bmu_avail == 0) {
/*
* ALL-ALLOCATED special case, with possible
* shortcut to ALL-FREE special case.
*/
scan->u.bmu_avail = count;
scan->bm_bighint = count;
if (count != radix) {
for (i = 1; i < skip; i += next_skip) {
if (scan[i].bm_bighint == (daddr_t)-1)
break;
scan[i].bm_bighint = 0;
if (next_skip == 1) {
scan[i].u.bmu_bitmap = 0;
} else {
scan[i].u.bmu_avail = 0;
}
}
/* fall through */
}
} else {
scan->u.bmu_avail += count;
/* scan->bm_bighint = radix; */
}
/*
* ALL-FREE special case.
*/
if (scan->u.bmu_avail == radix)
return;
if (scan->u.bmu_avail > radix)
panic("blst_meta_free: freeing already free blocks (%lld) %lld/%lld",
(long long)count, (long long)scan->u.bmu_avail,
(long long)radix);
/*
* Break the free down into its components
*/
blk = freeBlk & -radix;
endBlk = ummin(freeBlk + count, (freeBlk + radix) & -radix);
radix /= BLIST_META_RADIX;
child = (freeBlk - blk) / radix;
blk += child * radix;
i = 1 + child * next_skip;
while (i < skip && blk < freeBlk + count) {
v = blk + radix - freeBlk;
if (v > count)
v = count;
blst_meta_free(&scan[i], freeBlk, v, radix);
if (scan->bm_bighint < scan[i].bm_bighint)
scan->bm_bighint = scan[i].bm_bighint;
count -= v;
freeBlk += v;
skip = radix_to_skip(radix);
blk = freeBlk & -radix;
digit = (blk / radix) & BLIST_META_MASK;
endDigit = 1 + (((endBlk - 1) / radix) & BLIST_META_MASK);
scan->bm_bitmap |= bitrange(digit, endDigit - digit);
for (i = 1 + digit * skip; blk < endBlk; i += skip) {
blk += radix;
i += next_skip;
count = ummin(blk, endBlk) - freeBlk;
blst_meta_free(&scan[i], freeBlk, count, radix);
freeBlk = blk;
}
}
/*
* BLIST_RADIX_COPY() - copy one radix tree to another
* BLST_COPY() - copy one radix tree to another
*
* Locates free space in the source tree and frees it in the destination
* tree. The space may not already be free in the destination.
@ -950,21 +881,21 @@ static void
blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix, blist_t dest,
daddr_t count)
{
daddr_t i, next_skip, skip;
daddr_t endBlk, i, skip;
/*
* Leaf node
*/
if (radix == BLIST_BMAP_RADIX) {
u_daddr_t v = scan->u.bmu_bitmap;
u_daddr_t v = scan->bm_bitmap;
if (v == (u_daddr_t)-1) {
blist_free(dest, blk, count);
} else if (v != 0) {
int i;
for (i = 0; i < BLIST_BMAP_RADIX && i < count; ++i) {
for (i = 0; i < count; ++i) {
if (v & ((u_daddr_t)1 << i))
blist_free(dest, blk + i, 1);
}
@ -976,42 +907,22 @@ blst_copy(blmeta_t *scan, daddr_t blk, daddr_t radix, blist_t dest,
* Meta node
*/
if (scan->u.bmu_avail == 0) {
if (scan->bm_bitmap == 0) {
/*
* Source all allocated, leave dest allocated
*/
return;
}
if (scan->u.bmu_avail == radix) {
/*
* Source all free, free entire dest
*/
if (count < radix)
blist_free(dest, blk, count);
else
blist_free(dest, blk, radix);
return;
}
skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
endBlk = blk + count;
radix /= BLIST_META_RADIX;
for (i = 1; count && i < skip; i += next_skip) {
if (scan[i].bm_bighint == (daddr_t)-1)
break;
if (count >= radix) {
blst_copy(&scan[i], blk, radix, dest, radix);
count -= radix;
} else {
if (count) {
blst_copy(&scan[i], blk, radix, dest, count);
}
count = 0;
}
skip = radix_to_skip(radix);
for (i = 1; blk < endBlk; i += skip) {
blk += radix;
count = radix;
if (blk >= endBlk)
count -= blk - endBlk;
blst_copy(&scan[i], blk - radix, radix, dest, count);
}
}
@ -1027,16 +938,13 @@ blst_leaf_fill(blmeta_t *scan, daddr_t blk, int count)
{
daddr_t nblks;
u_daddr_t mask;
int n;
n = blk & BLIST_BMAP_MASK;
mask = ((u_daddr_t)-1 << n) &
((u_daddr_t)-1 >> (BLIST_BMAP_RADIX - count - n));
mask = bitrange(blk & BLIST_BMAP_MASK, count);
/* Count the number of blocks that we are allocating. */
nblks = bitcount64(scan->u.bmu_bitmap & mask);
nblks = bitcount64(scan->bm_bitmap & mask);
scan->u.bmu_bitmap &= ~mask;
scan->bm_bitmap &= ~mask;
return (nblks);
}
@ -1051,70 +959,27 @@ blst_leaf_fill(blmeta_t *scan, daddr_t blk, int count)
static daddr_t
blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, u_daddr_t radix)
{
daddr_t blk, i, nblks, next_skip, skip, v;
int child;
daddr_t blk, endBlk, i, nblks, skip;
int digit;
if (scan->bm_bighint == (daddr_t)-1)
panic("filling invalid range");
if (count > radix) {
/*
* The allocation exceeds the number of blocks that are
* managed by this node.
*/
panic("fill too large");
}
if (radix == BLIST_BMAP_RADIX)
return (blst_leaf_fill(scan, allocBlk, count));
if (count == radix || scan->u.bmu_avail == 0) {
/*
* ALL-ALLOCATED special case
*/
nblks = scan->u.bmu_avail;
scan->u.bmu_avail = 0;
scan->bm_bighint = 0;
return (nblks);
}
endBlk = ummin(allocBlk + count, (allocBlk + radix) & -radix);
radix /= BLIST_META_RADIX;
skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
blk = allocBlk & -radix;
/*
* An ALL-FREE meta node requires special handling before allocating
* any of its blocks.
*/
if (scan->u.bmu_avail == radix) {
radix /= BLIST_META_RADIX;
/*
* Reinitialize each of the meta node's children. An ALL-FREE
* meta node cannot have a terminator in any subtree.
*/
for (i = 1; i < skip; i += next_skip) {
if (next_skip == 1)
scan[i].u.bmu_bitmap = (u_daddr_t)-1;
else
scan[i].u.bmu_avail = radix;
scan[i].bm_bighint = radix;
}
} else {
radix /= BLIST_META_RADIX;
}
nblks = 0;
child = (allocBlk - blk) / radix;
blk += child * radix;
i = 1 + child * next_skip;
while (i < skip && blk < allocBlk + count) {
v = blk + radix - allocBlk;
if (v > count)
v = count;
nblks += blst_meta_fill(&scan[i], allocBlk, v, radix);
count -= v;
allocBlk += v;
while (blk < endBlk) {
digit = (blk / radix) & BLIST_META_MASK;
i = 1 + digit * skip;
blk += radix;
i += next_skip;
count = ummin(blk, endBlk) - allocBlk;
nblks += blst_meta_fill(&scan[i], allocBlk, count, radix);
if (scan[i].bm_bitmap == 0)
scan->bm_bitmap &= ~((u_daddr_t)1 << digit);
allocBlk = blk;
}
scan->u.bmu_avail -= nblks;
return (nblks);
}
@ -1123,64 +988,44 @@ blst_meta_fill(blmeta_t *scan, daddr_t allocBlk, daddr_t count, u_daddr_t radix)
static void
blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, int tab)
{
daddr_t i, next_skip, skip;
daddr_t skip;
u_daddr_t bit, mask;
int digit;
if (radix == BLIST_BMAP_RADIX) {
printf(
"%*.*s(%08llx,%lld): bitmap %016llx big=%lld\n",
"%*.*s(%08llx,%lld): bitmap %0*llx big=%lld\n",
tab, tab, "",
(long long)blk, (long long)radix,
(long long)scan->u.bmu_bitmap,
1 + (BLIST_BMAP_RADIX - 1) / 4,
(long long)scan->bm_bitmap,
(long long)scan->bm_bighint
);
return;
}
if (scan->u.bmu_avail == 0) {
printf(
"%*.*s(%08llx,%lld) ALL ALLOCATED\n",
tab, tab, "",
(long long)blk,
(long long)radix
);
return;
}
if (scan->u.bmu_avail == radix) {
printf(
"%*.*s(%08llx,%lld) ALL FREE\n",
tab, tab, "",
(long long)blk,
(long long)radix
);
return;
}
printf(
"%*.*s(%08llx,%lld): subtree (%lld/%lld) big=%lld {\n",
"%*.*s(%08llx): subtree (%lld/%lld) bitmap %0*llx big=%lld {\n",
tab, tab, "",
(long long)blk, (long long)radix,
(long long)scan->u.bmu_avail,
(long long)radix,
1 + (BLIST_META_RADIX - 1) / 4,
(long long)scan->bm_bitmap,
(long long)scan->bm_bighint
);
skip = radix_to_skip(radix);
next_skip = skip / BLIST_META_RADIX;
radix /= BLIST_META_RADIX;
skip = radix_to_skip(radix);
tab += 4;
for (i = 1; i < skip; i += next_skip) {
if (scan[i].bm_bighint == (daddr_t)-1) {
printf(
"%*.*s(%08llx,%lld): Terminator\n",
tab, tab, "",
(long long)blk, (long long)radix
);
break;
}
blst_radix_print(&scan[i], blk, radix, tab);
blk += radix;
}
mask = scan->bm_bitmap;
/* Examine the nonempty subtree associated with each bit set in mask */
do {
bit = mask & -mask;
digit = bitpos(bit);
blst_radix_print(&scan[1 + digit * skip], blk + digit * radix,
radix, tab);
} while ((mask ^= bit) != 0);
tab -= 4;
printf(
@ -1196,7 +1041,7 @@ blst_radix_print(blmeta_t *scan, daddr_t blk, daddr_t radix, int tab)
int
main(int ac, char **av)
{
int size = 1024;
int size = BLIST_META_RADIX * BLIST_BMAP_RADIX;
int i;
blist_t bl;
struct sbuf *s;

View File

@ -55,6 +55,27 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_EPOCH, "epoch", "epoch based reclamation");
#ifdef __amd64__
#define EPOCH_ALIGN CACHE_LINE_SIZE*2
#else
#define EPOCH_ALIGN CACHE_LINE_SIZE
#endif
TAILQ_HEAD (epoch_tdlist, epoch_tracker);
typedef struct epoch_record {
ck_epoch_record_t er_record;
volatile struct epoch_tdlist er_tdlist;
volatile uint32_t er_gen;
uint32_t er_cpuid;
} __aligned(EPOCH_ALIGN) *epoch_record_t;
struct epoch {
struct ck_epoch e_epoch __aligned(EPOCH_ALIGN);
epoch_record_t e_pcpu_record;
int e_idx;
int e_flags;
};
/* arbitrary --- needs benchmarking */
#define MAX_ADAPTIVE_SPIN 100
#define MAX_EPOCHS 64
@ -119,11 +140,15 @@ epoch_init(void *arg __unused)
epoch_call_count = counter_u64_alloc(M_WAITOK);
epoch_call_task_count = counter_u64_alloc(M_WAITOK);
pcpu_zone_record = uma_zcreate("epoch_record pcpu", sizeof(struct epoch_record),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_PCPU);
pcpu_zone_record = uma_zcreate("epoch_record pcpu",
sizeof(struct epoch_record), NULL, NULL, NULL, NULL,
UMA_ALIGN_PTR, UMA_ZONE_PCPU);
CPU_FOREACH(cpu) {
GROUPTASK_INIT(DPCPU_ID_PTR(cpu, epoch_cb_task), 0, epoch_call_task, NULL);
taskqgroup_attach_cpu(qgroup_softirq, DPCPU_ID_PTR(cpu, epoch_cb_task), NULL, cpu, -1, "epoch call task");
GROUPTASK_INIT(DPCPU_ID_PTR(cpu, epoch_cb_task), 0,
epoch_call_task, NULL);
taskqgroup_attach_cpu(qgroup_softirq,
DPCPU_ID_PTR(cpu, epoch_cb_task), NULL, cpu, -1,
"epoch call task");
}
inited = 1;
global_epoch = epoch_alloc(0);
@ -150,13 +175,21 @@ epoch_ctor(epoch_t epoch)
CPU_FOREACH(cpu) {
er = zpcpu_get_cpu(epoch->e_pcpu_record, cpu);
bzero(er, sizeof(*er));
ck_epoch_register(&epoch->e_epoch, &er->er_read_record, NULL);
ck_epoch_register(&epoch->e_epoch, &er->er_write_record, NULL);
ck_epoch_register(&epoch->e_epoch, &er->er_record, NULL);
TAILQ_INIT((struct threadlist *)(uintptr_t)&er->er_tdlist);
er->er_cpuid = cpu;
}
}
static void
epoch_adjust_prio(struct thread *td, u_char prio)
{
thread_lock(td);
sched_prio(td, prio);
thread_unlock(td);
}
epoch_t
epoch_alloc(int flags)
{
@ -192,51 +225,126 @@ epoch_free(epoch_t epoch)
free(epoch, M_EPOCH);
}
void
epoch_enter_preempt_KBI(epoch_t epoch, epoch_tracker_t et)
static epoch_record_t
epoch_currecord(epoch_t epoch)
{
epoch_enter_preempt(epoch, et);
return (zpcpu_get_cpu(epoch->e_pcpu_record, curcpu));
}
#define INIT_CHECK(epoch) \
do { \
if (__predict_false((epoch) == NULL)) \
return; \
} while (0)
void
epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et)
{
struct epoch_record *er;
struct thread *td;
MPASS(cold || epoch != NULL);
INIT_CHECK(epoch);
MPASS(epoch->e_flags & EPOCH_PREEMPT);
#ifdef EPOCH_TRACKER_DEBUG
et->et_magic_pre = EPOCH_MAGIC0;
et->et_magic_post = EPOCH_MAGIC1;
#endif
td = curthread;
et->et_td = td;
td->td_epochnest++;
critical_enter();
sched_pin();
td->td_pre_epoch_prio = td->td_priority;
er = epoch_currecord(epoch);
TAILQ_INSERT_TAIL(&er->er_tdlist, et, et_link);
ck_epoch_begin(&er->er_record, &et->et_section);
critical_exit();
}
void
epoch_exit_preempt_KBI(epoch_t epoch, epoch_tracker_t et)
epoch_enter(epoch_t epoch)
{
struct thread *td;
epoch_record_t er;
epoch_exit_preempt(epoch, et);
MPASS(cold || epoch != NULL);
INIT_CHECK(epoch);
td = curthread;
td->td_epochnest++;
critical_enter();
er = epoch_currecord(epoch);
ck_epoch_begin(&er->er_record, NULL);
}
void
epoch_enter_KBI(epoch_t epoch)
epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et)
{
struct epoch_record *er;
struct thread *td;
epoch_enter(epoch);
INIT_CHECK(epoch);
td = curthread;
critical_enter();
sched_unpin();
MPASS(td->td_epochnest);
td->td_epochnest--;
er = epoch_currecord(epoch);
MPASS(epoch->e_flags & EPOCH_PREEMPT);
MPASS(et != NULL);
MPASS(et->et_td == td);
#ifdef EPOCH_TRACKER_DEBUG
MPASS(et->et_magic_pre == EPOCH_MAGIC0);
MPASS(et->et_magic_post == EPOCH_MAGIC1);
et->et_magic_pre = 0;
et->et_magic_post = 0;
#endif
#ifdef INVARIANTS
et->et_td = (void*)0xDEADBEEF;
#endif
ck_epoch_end(&er->er_record, &et->et_section);
TAILQ_REMOVE(&er->er_tdlist, et, et_link);
er->er_gen++;
if (__predict_false(td->td_pre_epoch_prio != td->td_priority))
epoch_adjust_prio(td, td->td_pre_epoch_prio);
critical_exit();
}
void
epoch_exit_KBI(epoch_t epoch)
epoch_exit(epoch_t epoch)
{
struct thread *td;
epoch_record_t er;
epoch_exit(epoch);
INIT_CHECK(epoch);
td = curthread;
MPASS(td->td_epochnest);
td->td_epochnest--;
er = epoch_currecord(epoch);
ck_epoch_end(&er->er_record, NULL);
critical_exit();
}
/*
* epoch_block_handler_preempt is a callback from the ck code when another thread is
* currently in an epoch section.
* epoch_block_handler_preempt() is a callback from the CK code when another
* thread is currently in an epoch section.
*/
static void
epoch_block_handler_preempt(struct ck_epoch *global __unused, ck_epoch_record_t *cr,
void *arg __unused)
epoch_block_handler_preempt(struct ck_epoch *global __unused,
ck_epoch_record_t *cr, void *arg __unused)
{
epoch_record_t record;
struct thread *td, *owner, *curwaittd;
struct epoch_thread *tdwait;
struct epoch_tracker *tdwait;
struct turnstile *ts;
struct lock_object *lock;
int spincount, gen;
int locksheld __unused;
record = __containerof(cr, struct epoch_record, er_read_record);
record = __containerof(cr, struct epoch_record, er_record);
td = curthread;
locksheld = td->td_locks;
spincount = 0;
@ -318,25 +426,27 @@ epoch_block_handler_preempt(struct ck_epoch *global __unused, ck_epoch_record_t
if (TD_IS_INHIBITED(curwaittd) && TD_ON_LOCK(curwaittd) &&
((ts = curwaittd->td_blocked) != NULL)) {
/*
* We unlock td to allow turnstile_wait to reacquire the
* the thread lock. Before unlocking it we enter a critical
* section to prevent preemption after we reenable interrupts
* by dropping the thread lock in order to prevent curwaittd
* from getting to run.
* We unlock td to allow turnstile_wait to reacquire
* the thread lock. Before unlocking it we enter a
* critical section to prevent preemption after we
* reenable interrupts by dropping the thread lock in
* order to prevent curwaittd from getting to run.
*/
critical_enter();
thread_unlock(td);
owner = turnstile_lock(ts, &lock);
/*
* The owner pointer indicates that the lock succeeded. Only
* in case we hold the lock and the turnstile we locked is still
* the one that curwaittd is blocked on can we continue. Otherwise
* The turnstile pointer has been changed out from underneath
* us, as in the case where the lock holder has signalled curwaittd,
* The owner pointer indicates that the lock succeeded.
* Only in case we hold the lock and the turnstile we
* locked is still the one that curwaittd is blocked on
* can we continue. Otherwise the turnstile pointer has
* been changed out from underneath us, as in the case
* where the lock holder has signalled curwaittd,
* and we need to continue.
*/
if (owner != NULL && ts == curwaittd->td_blocked) {
MPASS(TD_IS_INHIBITED(curwaittd) && TD_ON_LOCK(curwaittd));
MPASS(TD_IS_INHIBITED(curwaittd) &&
TD_ON_LOCK(curwaittd));
critical_exit();
turnstile_wait(ts, owner, curwaittd->td_tsqueue);
counter_u64_add(turnstile_count, 1);
@ -386,9 +496,8 @@ epoch_wait_preempt(epoch_t epoch)
if ((epoch->e_flags & EPOCH_LOCKED) == 0)
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
"epoch_wait() can be long running");
KASSERT(!in_epoch(epoch),
("epoch_wait_preempt() called in the middle "
"of an epoch section of the same epoch"));
KASSERT(!in_epoch(epoch), ("epoch_wait_preempt() called in the middle "
"of an epoch section of the same epoch"));
#endif
thread_lock(td);
DROP_GIANT();
@ -401,7 +510,8 @@ epoch_wait_preempt(epoch_t epoch)
td->td_pinned = 0;
sched_bind(td, old_cpu);
ck_epoch_synchronize_wait(&epoch->e_epoch, epoch_block_handler_preempt, NULL);
ck_epoch_synchronize_wait(&epoch->e_epoch, epoch_block_handler_preempt,
NULL);
/* restore CPU binding, if any */
if (was_bound != 0) {
@ -462,7 +572,7 @@ epoch_call(epoch_t epoch, epoch_context_t ctx, void (*callback) (epoch_context_t
critical_enter();
*DPCPU_PTR(epoch_cb_count) += 1;
er = epoch_currecord(epoch);
ck_epoch_call(&er->er_write_record, cb, (ck_epoch_cb_t *)callback);
ck_epoch_call(&er->er_record, cb, (ck_epoch_cb_t *)callback);
critical_exit();
return;
boottime:
@ -486,7 +596,7 @@ epoch_call_task(void *arg __unused)
if (__predict_false((epoch = allepochs[i]) == NULL))
continue;
er = epoch_currecord(epoch);
record = &er->er_write_record;
record = &er->er_record;
if ((npending = record->n_pending) == 0)
continue;
ck_epoch_poll_deferred(record, &cb_stack);
@ -502,7 +612,7 @@ epoch_call_task(void *arg __unused)
head = ck_stack_batch_pop_npsc(&cb_stack);
for (cursor = head; cursor != NULL; cursor = next) {
struct ck_epoch_entry *entry =
ck_epoch_entry_container(cursor);
ck_epoch_entry_container(cursor);
next = CK_STACK_NEXT(cursor);
entry->function(entry);
@ -512,7 +622,7 @@ epoch_call_task(void *arg __unused)
int
in_epoch_verbose(epoch_t epoch, int dump_onfail)
{
struct epoch_thread *tdwait;
struct epoch_tracker *tdwait;
struct thread *td;
epoch_record_t er;
@ -548,9 +658,15 @@ in_epoch(epoch_t epoch)
}
void
epoch_adjust_prio(struct thread *td, u_char prio)
epoch_thread_init(struct thread *td)
{
thread_lock(td);
sched_prio(td, prio);
thread_unlock(td);
td->td_et = malloc(sizeof(struct epoch_tracker), M_EPOCH, M_WAITOK);
}
void
epoch_thread_fini(struct thread *td)
{
free(td->td_et, M_EPOCH);
}

View File

@ -1767,35 +1767,29 @@ if_data_copy(struct ifnet *ifp, struct if_data *ifd)
void
if_addr_rlock(struct ifnet *ifp)
{
MPASS(*(uint64_t *)&ifp->if_addr_et == 0);
epoch_enter_preempt(net_epoch_preempt, &ifp->if_addr_et);
epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_addr_runlock(struct ifnet *ifp)
{
epoch_exit_preempt(net_epoch_preempt, &ifp->if_addr_et);
#ifdef INVARIANTS
bzero(&ifp->if_addr_et, sizeof(struct epoch_tracker));
#endif
epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_maddr_rlock(if_t ifp)
{
MPASS(*(uint64_t *)&ifp->if_maddr_et == 0);
epoch_enter_preempt(net_epoch_preempt, &ifp->if_maddr_et);
epoch_enter_preempt(net_epoch_preempt, curthread->td_et);
}
void
if_maddr_runlock(if_t ifp)
{
epoch_exit_preempt(net_epoch_preempt, &ifp->if_maddr_et);
#ifdef INVARIANTS
bzero(&ifp->if_maddr_et, sizeof(struct epoch_tracker));
#endif
epoch_exit_preempt(net_epoch_preempt, curthread->td_et);
}
/*

View File

@ -381,8 +381,6 @@ struct ifnet {
*/
struct netdump_methods *if_netdump_methods;
struct epoch_context if_epoch_ctx;
struct epoch_tracker if_addr_et;
struct epoch_tracker if_maddr_et;
/*
* Spare fields to be added before branching a stable branch, so

View File

@ -39,6 +39,10 @@ options PREEMPTION #Enable kernel thread preemption
options VIMAGE # Subsystem virtualization, e.g. VNET
options INET #InterNETworking
options INET6 #IPv6 communications protocols
options IPSEC # IP (v4/v6) security
options IPSEC_SUPPORT # Allow kldload of ipsec and tcpmd5
options TCP_OFFLOAD # TCP offload
options TCP_BLACKBOX # Enhanced TCP event logging
options TCP_HHOOK # hhook(9) framework for TCP
options TCP_RFC7413 # TCP Fast Open
options SCTP #Stream Control Transmission Protocol
@ -83,6 +87,9 @@ options MAC # TrustedBSD MAC Framework
options KDTRACE_HOOKS # Kernel DTrace hooks
options DDB_CTF # Kernel ELF linker loads CTF data
options INCLUDE_CONFIG_FILE # Include this file in kernel
options RACCT # Resource accounting framework
options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
options RCTL # Resource limits
# Debugging support. Always need this:
options KDB # Enable kernel debugger support.
@ -136,10 +143,12 @@ device sym # NCR/Symbios/LSI Logic 53C8XX/53C1010/53C1510D
# ATA/SCSI peripherals
device scbus # SCSI bus (required for ATA/SCSI)
device ch # SCSI media changers
device da # Direct Access (disks)
device sa # Sequential Access (tape etc)
device cd # CD
device pass # Passthrough device (direct ATA/SCSI access)
device ses # Enclosure Service (SES and SAF-TE)
# vt is the default console driver, resembling an SCO console
device vt # Core console driver
@ -168,6 +177,7 @@ device re # RealTek 8139C+/8169/8169S/8110S
device rl # RealTek 8129/8139
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
device random # Entropy device
device ether # Ethernet support
@ -193,10 +203,8 @@ device usb # USB Bus (required)
device uhid # "Human Interface Devices"
device ukbd # Keyboard
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
device ulpt # Printer
device umass # Disks/Mass storage - Requires scbus and da0
device ums # Mouse
device urio # Diamond Rio 500 MP3 player
# USB Ethernet
device aue # ADMtek USB Ethernet
device axe # ASIX Electronics USB Ethernet
@ -236,3 +244,5 @@ device sound # Generic sound driver (required)
device snd_ai2s # Apple I2S audio
device snd_uaudio # USB Audio
# Netmap provides direct access to TX/RX rings on supported NICs
device netmap # netmap(4) support

View File

@ -38,6 +38,7 @@
#define _MACHINE_CPU_H_
#include <machine/atomic.h>
#include <machine/cpufunc.h>
#include <machine/frame.h>
#define TRAPF_PC(tfp) ((tfp)->tf_ra)
@ -86,8 +87,7 @@ static __inline uint64_t
get_cyclecount(void)
{
/* TODO: This is bogus */
return (1);
return (rdcycle());
}
#endif

View File

@ -104,6 +104,11 @@ sfence_vma_page(uintptr_t addr)
__asm __volatile("sfence.vma %0" :: "r" (addr) : "memory");
}
#define rdcycle() csr_read64(cycle)
#define rdtime() csr_read64(time)
#define rdinstret() csr_read64(instret)
#define rdhpmcounter(n) csr_read64(hpmcounter##n)
#define cpufunc_nullop() riscv_nullop()
void riscv_nullop(void);

View File

@ -223,4 +223,23 @@
val; \
})
#if __riscv_xlen == 32
#define csr_read64(csr) \
({ uint64_t val; \
uint32_t high, low; \
__asm __volatile("1: " \
"csrr t0, " #csr "h\n" \
"csrr %0, " #csr "\n" \
"csrr %1, " #csr "h\n" \
"bne t0, %1, 1b" \
: "=r" (low), "=r" (high) \
: \
: "t0"); \
val = (low | ((uint64_t)high << 32)); \
val; \
})
#else
#define csr_read64(csr) ((uint64_t)csr_read(csr))
#endif
#endif /* !_MACHINE_RISCVREG_H_ */

View File

@ -73,22 +73,20 @@ typedef uint64_t u_daddr_t; /* unsigned disk address */
*/
typedef struct blmeta {
union {
daddr_t bmu_avail; /* space available under us */
u_daddr_t bmu_bitmap; /* bitmap if we are a leaf */
} u;
u_daddr_t bm_bitmap; /* bitmap if we are a leaf */
daddr_t bm_bighint; /* biggest contiguous block hint*/
} blmeta_t;
typedef struct blist {
daddr_t bl_blocks; /* area of coverage */
daddr_t bl_avail; /* # available blocks */
u_daddr_t bl_radix; /* coverage radix */
daddr_t bl_cursor; /* next-fit search starts at */
blmeta_t bl_root[1]; /* root of radix tree */
} *blist_t;
#define BLIST_META_RADIX 16
#define BLIST_BMAP_RADIX (sizeof(u_daddr_t)*8)
#define BLIST_META_RADIX BLIST_BMAP_RADIX
#define BLIST_MAX_ALLOC BLIST_BMAP_RADIX

View File

@ -29,10 +29,17 @@
#ifndef _SYS_EPOCH_H_
#define _SYS_EPOCH_H_
struct epoch_context {
void *data[2];
} __aligned(sizeof(void *));
typedef struct epoch_context *epoch_context_t;
#ifdef _KERNEL
#include <sys/lock.h>
#include <sys/pcpu.h>
#endif
#include <ck_epoch.h>
struct epoch;
typedef struct epoch *epoch_t;
@ -43,22 +50,19 @@ typedef struct epoch *epoch_t;
extern epoch_t global_epoch;
extern epoch_t global_epoch_preempt;
struct epoch_context {
void *data[2];
} __aligned(sizeof(void *));
typedef struct epoch_context *epoch_context_t;
struct epoch_tracker {
void *datap[3];
#ifdef EPOCH_TRACKER_DEBUG
int datai[5];
#else
int datai[1];
#ifdef EPOCH_TRACKER_DEBUG
#define EPOCH_MAGIC0 0xFADECAFEF00DD00D
#define EPOCH_MAGIC1 0xBADDBABEDEEDFEED
uint64_t et_magic_pre;
#endif
TAILQ_ENTRY(epoch_tracker) et_link;
struct thread *et_td;
ck_epoch_section_t et_section;
#ifdef EPOCH_TRACKER_DEBUG
uint64_t et_magic_post;
#endif
} __aligned(sizeof(void *));
typedef struct epoch_tracker *epoch_tracker_t;
epoch_t epoch_alloc(int flags);
@ -68,26 +72,18 @@ void epoch_wait_preempt(epoch_t epoch);
void epoch_call(epoch_t epoch, epoch_context_t ctx, void (*callback) (epoch_context_t));
int in_epoch(epoch_t epoch);
int in_epoch_verbose(epoch_t epoch, int dump_onfail);
#ifdef _KERNEL
DPCPU_DECLARE(int, epoch_cb_count);
DPCPU_DECLARE(struct grouptask, epoch_cb_task);
#define EPOCH_MAGIC0 0xFADECAFEF00DD00D
#define EPOCH_MAGIC1 0xBADDBABEDEEDFEED
void epoch_enter_preempt_KBI(epoch_t epoch, epoch_tracker_t et);
void epoch_exit_preempt_KBI(epoch_t epoch, epoch_tracker_t et);
void epoch_enter_KBI(epoch_t epoch);
void epoch_exit_KBI(epoch_t epoch);
void epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et);
void epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et);
void epoch_enter(epoch_t epoch);
void epoch_exit(epoch_t epoch);
void epoch_thread_init(struct thread *);
void epoch_thread_fini(struct thread *);
#if defined(KLD_MODULE) && !defined(KLD_TIED)
#define epoch_enter_preempt(e, t) epoch_enter_preempt_KBI((e), (t))
#define epoch_exit_preempt(e, t) epoch_exit_preempt_KBI((e), (t))
#define epoch_enter(e) epoch_enter_KBI((e))
#define epoch_exit(e) epoch_exit_KBI((e))
#else
#include <sys/epoch_private.h>
#endif /* KLD_MODULE */
#endif /* _KERNEL */
#endif
#endif /* _KERNEL */
#endif /* _SYS_EPOCH_H_ */

View File

@ -1,211 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2018, Matthew Macy <mmacy@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.
*
* $FreeBSD$
*/
#ifndef _SYS_EPOCH_PRIVATE_H_
#define _SYS_EPOCH_PRIVATE_H_
#ifndef _KERNEL
#error "no user serviceable parts"
#else
#include <ck_epoch.h>
#include <sys/kpilite.h>
#include <sys/mutex.h>
extern void epoch_adjust_prio(struct thread *td, u_char prio);
#ifndef _SYS_SYSTM_H_
extern void critical_exit_preempt(void);
#endif
#ifdef __amd64__
#define EPOCH_ALIGN CACHE_LINE_SIZE*2
#else
#define EPOCH_ALIGN CACHE_LINE_SIZE
#endif
/*
* Standalone (_sa) routines for thread state manipulation
*/
static __inline void
critical_enter_sa(void *tdarg)
{
struct thread_lite *td;
td = tdarg;
td->td_critnest++;
__compiler_membar();
}
static __inline void
critical_exit_sa(void *tdarg)
{
struct thread_lite *td;
td = tdarg;
MPASS(td->td_critnest > 0);
__compiler_membar();
td->td_critnest--;
__compiler_membar();
if (__predict_false(td->td_owepreempt != 0))
critical_exit_preempt();
}
typedef struct epoch_thread {
#ifdef EPOCH_TRACKER_DEBUG
uint64_t et_magic_pre;
#endif
TAILQ_ENTRY(epoch_thread) et_link; /* Epoch queue. */
struct thread *et_td; /* pointer to thread in section */
ck_epoch_section_t et_section; /* epoch section object */
#ifdef EPOCH_TRACKER_DEBUG
uint64_t et_magic_post;
#endif
} *epoch_thread_t;
TAILQ_HEAD (epoch_tdlist, epoch_thread);
typedef struct epoch_record {
ck_epoch_record_t er_read_record;
ck_epoch_record_t er_write_record;
volatile struct epoch_tdlist er_tdlist;
volatile uint32_t er_gen;
uint32_t er_cpuid;
} __aligned(EPOCH_ALIGN) *epoch_record_t;
struct epoch {
struct ck_epoch e_epoch __aligned(EPOCH_ALIGN);
epoch_record_t e_pcpu_record;
int e_idx;
int e_flags;
};
static epoch_record_t
epoch_currecord(epoch_t epoch)
{
return zpcpu_get_cpu(epoch->e_pcpu_record, curcpu);
}
#define INIT_CHECK(epoch) \
do { \
if (__predict_false((epoch) == NULL)) \
return; \
} while (0)
static __inline void
epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et)
{
struct epoch_record *er;
struct epoch_thread *etd;
struct thread_lite *td;
MPASS(cold || epoch != NULL);
INIT_CHECK(epoch);
etd = (void *)et;
MPASS(epoch->e_flags & EPOCH_PREEMPT);
#ifdef EPOCH_TRACKER_DEBUG
etd->et_magic_pre = EPOCH_MAGIC0;
etd->et_magic_post = EPOCH_MAGIC1;
#endif
td = (struct thread_lite *)curthread;
etd->et_td = (void*)td;
td->td_epochnest++;
critical_enter_sa(td);
sched_pin_lite(td);
td->td_pre_epoch_prio = td->td_priority;
er = epoch_currecord(epoch);
TAILQ_INSERT_TAIL(&er->er_tdlist, etd, et_link);
ck_epoch_begin(&er->er_read_record, (ck_epoch_section_t *)&etd->et_section);
critical_exit_sa(td);
}
static __inline void
epoch_enter(epoch_t epoch)
{
struct thread_lite *td;
epoch_record_t er;
MPASS(cold || epoch != NULL);
INIT_CHECK(epoch);
td = (struct thread_lite *)curthread;
td->td_epochnest++;
critical_enter_sa(td);
er = epoch_currecord(epoch);
ck_epoch_begin(&er->er_read_record, NULL);
}
static __inline void
epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et)
{
struct epoch_record *er;
struct epoch_thread *etd;
struct thread_lite *td;
INIT_CHECK(epoch);
td = (struct thread_lite *)curthread;
critical_enter_sa(td);
sched_unpin_lite(td);
MPASS(td->td_epochnest);
td->td_epochnest--;
er = epoch_currecord(epoch);
MPASS(epoch->e_flags & EPOCH_PREEMPT);
etd = (void *)et;
MPASS(etd != NULL);
MPASS(etd->et_td == (struct thread *)td);
#ifdef EPOCH_TRACKER_DEBUG
MPASS(etd->et_magic_pre == EPOCH_MAGIC0);
MPASS(etd->et_magic_post == EPOCH_MAGIC1);
etd->et_magic_pre = 0;
etd->et_magic_post = 0;
#endif
etd->et_td = (void*)0xDEADBEEF;
ck_epoch_end(&er->er_read_record,
(ck_epoch_section_t *)&etd->et_section);
TAILQ_REMOVE(&er->er_tdlist, etd, et_link);
er->er_gen++;
if (__predict_false(td->td_pre_epoch_prio != td->td_priority))
epoch_adjust_prio((struct thread *)td, td->td_pre_epoch_prio);
critical_exit_sa(td);
}
static __inline void
epoch_exit(epoch_t epoch)
{
struct thread_lite *td;
epoch_record_t er;
INIT_CHECK(epoch);
td = (struct thread_lite *)curthread;
MPASS(td->td_epochnest);
td->td_epochnest--;
er = epoch_currecord(epoch);
ck_epoch_end(&er->er_read_record, NULL);
critical_exit_sa(td);
}
#endif /* _KERNEL */
#endif /* _SYS_EPOCH_PRIVATE_H_ */

View File

@ -193,6 +193,7 @@ struct trapframe;
struct turnstile;
struct vm_map;
struct vm_map_entry;
struct epoch_tracker;
/*
* XXX: Does this belong in resource.h or resourcevar.h instead?
@ -360,6 +361,7 @@ struct thread {
int td_lastcpu; /* (t) Last cpu we were on. */
int td_oncpu; /* (t) Which cpu we are on. */
void *td_lkpi_task; /* LinuxKPI task struct pointer */
struct epoch_tracker *td_et; /* (k) compat KPI spare tracker */
int td_pmcpend;
};

View File

@ -82,7 +82,7 @@ int ffs_getcg(struct fs *, struct vnode *, u_int, struct buf **,
struct cg **);
int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
int ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
int ffs_own_mount(const struct mount *mp);
int ffs_reallocblks(struct vop_reallocblks_args *);

View File

@ -148,12 +148,18 @@ loop:
if (I_IS_UFS1(ip)) {
*((struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
/* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
/*
* XXX: FIX? The entropy here is desirable,
* but the harvesting may be expensive
*/
random_harvest_queue(&(ip->i_din1), sizeof(ip->i_din1), RANDOM_FS_ATIME);
} else {
*((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
/* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */
/*
* XXX: FIX? The entropy here is desirable,
* but the harvesting may be expensive
*/
random_harvest_queue(&(ip->i_din2), sizeof(ip->i_din2), RANDOM_FS_ATIME);
}
if (waitfor)

View File

@ -1333,12 +1333,12 @@ expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype, clearmode)
*/
dip = (struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, cancelip->i_number);
if (clearmode || cancelip->i_effnlink == 0)
dip->di_mode = 0;
dip->di_size = 0;
dip->di_blocks = 0;
dip->di_flags &= ~SF_SNAPSHOT;
bzero(&dip->di_db[0], (UFS_NDADDR + UFS_NIADDR) * sizeof(ufs2_daddr_t));
if (clearmode || cancelip->i_effnlink == 0)
dip->di_mode = 0;
bdwrite(bp);
/*
* Now go through and expunge all the blocks in the file

View File

@ -6698,12 +6698,13 @@ softdep_journal_freeblocks(ip, cred, length, flags)
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
softdep_update_inodeblock(ip, bp, 0);
if (ump->um_fstype == UFS1)
if (ump->um_fstype == UFS1) {
*((struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din1;
else
} else {
*((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = *ip->i_din2;
}
ACQUIRE_LOCK(ump);
(void) inodedep_lookup(mp, ip->i_number, DEPALLOC, &inodedep);
if ((inodedep->id_state & IOSTARTED) != 0)
@ -9640,6 +9641,7 @@ static void
clear_unlinked_inodedep(inodedep)
struct inodedep *inodedep;
{
struct ufs2_dinode *dip;
struct ufsmount *ump;
struct inodedep *idp;
struct inodedep *idn;
@ -9743,12 +9745,14 @@ clear_unlinked_inodedep(inodedep)
ffs_oldfscompat_write((struct fs *)bp->b_data, ump);
softdep_setup_sbupdate(ump, (struct fs *)bp->b_data,
bp);
} else if (fs->fs_magic == FS_UFS1_MAGIC)
} else if (fs->fs_magic == FS_UFS1_MAGIC) {
((struct ufs1_dinode *)bp->b_data +
ino_to_fsbo(fs, pino))->di_freelink = nino;
else
((struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, pino))->di_freelink = nino;
} else {
dip = (struct ufs2_dinode *)bp->b_data +
ino_to_fsbo(fs, pino);
dip->di_freelink = nino;
}
/*
* If the bwrite fails we have no recourse to recover. The
* filesystem is corrupted already.

View File

@ -108,31 +108,35 @@ ffs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp)
* Load up the contents of an inode and copy the appropriate pieces
* to the incore copy.
*/
void
int
ffs_load_inode(struct buf *bp, struct inode *ip, struct fs *fs, ino_t ino)
{
struct ufs1_dinode *dip1;
struct ufs2_dinode *dip2;
if (I_IS_UFS1(ip)) {
*ip->i_din1 =
dip1 = ip->i_din1;
*dip1 =
*((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
ip->i_mode = ip->i_din1->di_mode;
ip->i_nlink = ip->i_din1->di_nlink;
ip->i_size = ip->i_din1->di_size;
ip->i_flags = ip->i_din1->di_flags;
ip->i_gen = ip->i_din1->di_gen;
ip->i_uid = ip->i_din1->di_uid;
ip->i_gid = ip->i_din1->di_gid;
} else {
*ip->i_din2 =
*((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
ip->i_mode = ip->i_din2->di_mode;
ip->i_nlink = ip->i_din2->di_nlink;
ip->i_size = ip->i_din2->di_size;
ip->i_flags = ip->i_din2->di_flags;
ip->i_gen = ip->i_din2->di_gen;
ip->i_uid = ip->i_din2->di_uid;
ip->i_gid = ip->i_din2->di_gid;
ip->i_mode = dip1->di_mode;
ip->i_nlink = dip1->di_nlink;
ip->i_size = dip1->di_size;
ip->i_flags = dip1->di_flags;
ip->i_gen = dip1->di_gen;
ip->i_uid = dip1->di_uid;
ip->i_gid = dip1->di_gid;
return (0);
}
dip2 = ip->i_din2;
*dip2 = *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
ip->i_mode = dip2->di_mode;
ip->i_nlink = dip2->di_nlink;
ip->i_size = dip2->di_size;
ip->i_flags = dip2->di_flags;
ip->i_gen = dip2->di_gen;
ip->i_uid = dip2->di_uid;
ip->i_gid = dip2->di_gid;
return (0);
}
#endif /* KERNEL */

View File

@ -740,16 +740,19 @@ loop:
bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
(int)fs->fs_bsize, NOCRED, &bp);
if (error) {
VOP_UNLOCK(vp, 0);
vrele(vp);
vput(vp);
MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
return (error);
}
if ((error = ffs_load_inode(bp, ip, fs, ip->i_number)) != 0) {
brelse(bp);
vput(vp);
MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
return (error);
}
ffs_load_inode(bp, ip, fs, ip->i_number);
ip->i_effnlink = ip->i_nlink;
brelse(bp);
VOP_UNLOCK(vp, 0);
vrele(vp);
vput(vp);
}
return (0);
}
@ -1729,7 +1732,12 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
ip->i_din1 = uma_zalloc(uma_ufs1, M_WAITOK);
else
ip->i_din2 = uma_zalloc(uma_ufs2, M_WAITOK);
ffs_load_inode(bp, ip, fs, ino);
if ((error = ffs_load_inode(bp, ip, fs, ino)) != 0) {
bqrelse(bp);
vput(vp);
*vpp = NULL;
return (error);
}
if (DOINGSOFTDEP(vp))
softdep_load_inodeblock(ip);
else

View File

@ -459,6 +459,36 @@ bucket_zone_drain(void)
zone_drain(ubz->ubz_zone);
}
static uma_bucket_t
zone_try_fetch_bucket(uma_zone_t zone, uma_zone_domain_t zdom, const bool ws)
{
uma_bucket_t bucket;
ZONE_LOCK_ASSERT(zone);
if ((bucket = LIST_FIRST(&zdom->uzd_buckets)) != NULL) {
MPASS(zdom->uzd_nitems >= bucket->ub_cnt);
LIST_REMOVE(bucket, ub_link);
zdom->uzd_nitems -= bucket->ub_cnt;
if (ws && zdom->uzd_imin > zdom->uzd_nitems)
zdom->uzd_imin = zdom->uzd_nitems;
}
return (bucket);
}
static void
zone_put_bucket(uma_zone_t zone, uma_zone_domain_t zdom, uma_bucket_t bucket,
const bool ws)
{
ZONE_LOCK_ASSERT(zone);
LIST_INSERT_HEAD(&zdom->uzd_buckets, bucket, ub_link);
zdom->uzd_nitems += bucket->ub_cnt;
if (ws && zdom->uzd_imax < zdom->uzd_nitems)
zdom->uzd_imax = zdom->uzd_nitems;
}
static void
zone_log_warning(uma_zone_t zone)
{
@ -508,6 +538,23 @@ uma_timeout(void *unused)
callout_reset(&uma_callout, UMA_TIMEOUT * hz, uma_timeout, NULL);
}
/*
* Update the working set size estimate for the zone's bucket cache.
* The constants chosen here are somewhat arbitrary. With an update period of
* 20s (UMA_TIMEOUT), this estimate is dominated by zone activity over the
* last 100s.
*/
static void
zone_domain_update_wss(uma_zone_domain_t zdom)
{
long wss;
MPASS(zdom->uzd_imax >= zdom->uzd_imin);
wss = zdom->uzd_imax - zdom->uzd_imin;
zdom->uzd_imax = zdom->uzd_imin = zdom->uzd_nitems;
zdom->uzd_wss = (3 * wss + 2 * zdom->uzd_wss) / 5;
}
/*
* Routine to perform timeout driven calculations. This expands the
* hashes and does per cpu statistics aggregation.
@ -560,8 +607,14 @@ keg_timeout(uma_keg_t keg)
static void
zone_timeout(uma_zone_t zone)
{
int i;
zone_foreach_keg(zone, &keg_timeout);
ZONE_LOCK(zone);
for (i = 0; i < vm_ndomains; i++)
zone_domain_update_wss(&zone->uz_domain[i]);
ZONE_UNLOCK(zone);
}
/*
@ -772,16 +825,16 @@ cache_drain_safe_cpu(uma_zone_t zone)
cache = &zone->uz_cpu[curcpu];
if (cache->uc_allocbucket) {
if (cache->uc_allocbucket->ub_cnt != 0)
LIST_INSERT_HEAD(&zone->uz_domain[domain].uzd_buckets,
cache->uc_allocbucket, ub_link);
zone_put_bucket(zone, &zone->uz_domain[domain],
cache->uc_allocbucket, false);
else
b1 = cache->uc_allocbucket;
cache->uc_allocbucket = NULL;
}
if (cache->uc_freebucket) {
if (cache->uc_freebucket->ub_cnt != 0)
LIST_INSERT_HEAD(&zone->uz_domain[domain].uzd_buckets,
cache->uc_freebucket, ub_link);
zone_put_bucket(zone, &zone->uz_domain[domain],
cache->uc_freebucket, false);
else
b2 = cache->uc_freebucket;
cache->uc_freebucket = NULL;
@ -844,8 +897,8 @@ bucket_cache_drain(uma_zone_t zone)
*/
for (i = 0; i < vm_ndomains; i++) {
zdom = &zone->uz_domain[i];
while ((bucket = LIST_FIRST(&zdom->uzd_buckets)) != NULL) {
LIST_REMOVE(bucket, ub_link);
while ((bucket = zone_try_fetch_bucket(zone, zdom, false)) !=
NULL) {
ZONE_UNLOCK(zone);
bucket_drain(zone, bucket);
bucket_free(zone, bucket, NULL);
@ -2523,11 +2576,9 @@ zalloc_start:
zdom = &zone->uz_domain[0];
else
zdom = &zone->uz_domain[domain];
if ((bucket = LIST_FIRST(&zdom->uzd_buckets)) != NULL) {
if ((bucket = zone_try_fetch_bucket(zone, zdom, true)) != NULL) {
KASSERT(bucket->ub_cnt != 0,
("uma_zalloc_arg: Returning an empty bucket."));
LIST_REMOVE(bucket, ub_link);
cache->uc_allocbucket = bucket;
ZONE_UNLOCK(zone);
goto zalloc_start;
@ -2556,6 +2607,7 @@ zalloc_start:
critical_enter();
cpu = curcpu;
cache = &zone->uz_cpu[cpu];
/*
* See if we lost the race or were migrated. Cache the
* initialized bucket to make this less likely or claim
@ -2565,6 +2617,7 @@ zalloc_start:
((zone->uz_flags & UMA_ZONE_NUMA) == 0 ||
domain == PCPU_GET(domain))) {
cache->uc_allocbucket = bucket;
zdom->uzd_imax += bucket->ub_cnt;
} else if ((zone->uz_flags & UMA_ZONE_NOBUCKETCACHE) != 0) {
critical_exit();
ZONE_UNLOCK(zone);
@ -2572,7 +2625,7 @@ zalloc_start:
bucket_free(zone, bucket, udata);
goto zalloc_restart;
} else
LIST_INSERT_HEAD(&zdom->uzd_buckets, bucket, ub_link);
zone_put_bucket(zone, zdom, bucket, false);
ZONE_UNLOCK(zone);
goto zalloc_start;
}
@ -3200,7 +3253,7 @@ zfree_start:
bucket_free(zone, bucket, udata);
goto zfree_restart;
} else
LIST_INSERT_HEAD(&zdom->uzd_buckets, bucket, ub_link);
zone_put_bucket(zone, zdom, bucket, true);
}
/*
@ -3649,6 +3702,7 @@ uma_reclaim_locked(bool kmem_danger)
cache_drain_safe(NULL);
zone_foreach(zone_drain);
}
/*
* Some slabs may have been freed but this zone will be visited early
* we visit again so that we can free pages that are empty once other
@ -3882,7 +3936,7 @@ uma_print_zone(uma_zone_t zone)
* directly so that we don't have to.
*/
static void
uma_zone_sumstat(uma_zone_t z, int *cachefreep, uint64_t *allocsp,
uma_zone_sumstat(uma_zone_t z, long *cachefreep, uint64_t *allocsp,
uint64_t *freesp, uint64_t *sleepsp)
{
uma_cache_t cache;
@ -3937,7 +3991,6 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS)
struct uma_stream_header ush;
struct uma_type_header uth;
struct uma_percpu_stat *ups;
uma_bucket_t bucket;
uma_zone_domain_t zdom;
struct sbuf sbuf;
uma_cache_t cache;
@ -3997,9 +4050,7 @@ sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS)
for (i = 0; i < vm_ndomains; i++) {
zdom = &z->uz_domain[i];
LIST_FOREACH(bucket, &zdom->uzd_buckets,
ub_link)
uth.uth_zone_free += bucket->ub_cnt;
uth.uth_zone_free += zdom->uzd_nitems;
}
uth.uth_allocs = z->uz_allocs;
uth.uth_frees = z->uz_frees;
@ -4199,12 +4250,11 @@ uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item)
#ifdef DDB
DB_SHOW_COMMAND(uma, db_show_uma)
{
uma_bucket_t bucket;
uma_keg_t kz;
uma_zone_t z;
uma_zone_domain_t zdom;
uint64_t allocs, frees, sleeps;
int cachefree, i;
long cachefree;
int i;
db_printf("%18s %8s %8s %8s %12s %8s %8s\n", "Zone", "Size", "Used",
"Free", "Requests", "Sleeps", "Bucket");
@ -4221,13 +4271,10 @@ DB_SHOW_COMMAND(uma, db_show_uma)
if (!((z->uz_flags & UMA_ZONE_SECONDARY) &&
(LIST_FIRST(&kz->uk_zones) != z)))
cachefree += kz->uk_free;
for (i = 0; i < vm_ndomains; i++) {
zdom = &z->uz_domain[i];
LIST_FOREACH(bucket, &zdom->uzd_buckets,
ub_link)
cachefree += bucket->ub_cnt;
}
db_printf("%18s %8ju %8jd %8d %12ju %8ju %8u\n",
for (i = 0; i < vm_ndomains; i++)
cachefree += z->uz_domain[i].uzd_nitems;
db_printf("%18s %8ju %8jd %8ld %12ju %8ju %8u\n",
z->uz_name, (uintmax_t)kz->uk_size,
(intmax_t)(allocs - frees), cachefree,
(uintmax_t)allocs, sleeps, z->uz_count);
@ -4239,22 +4286,18 @@ DB_SHOW_COMMAND(uma, db_show_uma)
DB_SHOW_COMMAND(umacache, db_show_umacache)
{
uma_bucket_t bucket;
uma_zone_t z;
uma_zone_domain_t zdom;
uint64_t allocs, frees;
int cachefree, i;
long cachefree;
int i;
db_printf("%18s %8s %8s %8s %12s %8s\n", "Zone", "Size", "Used", "Free",
"Requests", "Bucket");
LIST_FOREACH(z, &uma_cachezones, uz_link) {
uma_zone_sumstat(z, &cachefree, &allocs, &frees, NULL);
for (i = 0; i < vm_ndomains; i++) {
zdom = &z->uz_domain[i];
LIST_FOREACH(bucket, &zdom->uzd_buckets, ub_link)
cachefree += bucket->ub_cnt;
}
db_printf("%18s %8ju %8jd %8d %12ju %8u\n",
for (i = 0; i < vm_ndomains; i++)
cachefree += z->uz_domain[i].uzd_nitems;
db_printf("%18s %8ju %8jd %8ld %12ju %8u\n",
z->uz_name, (uintmax_t)z->uz_size,
(intmax_t)(allocs - frees), cachefree,
(uintmax_t)allocs, z->uz_count);

View File

@ -304,6 +304,10 @@ typedef struct uma_klink *uma_klink_t;
struct uma_zone_domain {
LIST_HEAD(,uma_bucket) uzd_buckets; /* full buckets */
long uzd_nitems; /* total item count */
long uzd_imax; /* maximum item count this period */
long uzd_imin; /* minimum item count this period */
long uzd_wss; /* working set size estimate */
};
typedef struct uma_zone_domain * uma_zone_domain_t;
@ -423,11 +427,12 @@ void uma_large_free(uma_slab_t slab);
mtx_init(&(z)->uz_lock, (z)->uz_name, \
"UMA zone", MTX_DEF | MTX_DUPOK); \
} while (0)
#define ZONE_LOCK(z) mtx_lock((z)->uz_lockptr)
#define ZONE_TRYLOCK(z) mtx_trylock((z)->uz_lockptr)
#define ZONE_UNLOCK(z) mtx_unlock((z)->uz_lockptr)
#define ZONE_LOCK_FINI(z) mtx_destroy(&(z)->uz_lock)
#define ZONE_LOCK_ASSERT(z) mtx_assert((z)->uz_lockptr, MA_OWNED)
/*
* Find a slab within a hash table. This is used for OFFPAGE zones to lookup

View File

@ -129,6 +129,7 @@ void dump_drop_page(vm_paddr_t);
void finishidentcpu(void);
void identify_cpu1(void);
void identify_cpu2(void);
void identify_cpu_fixup_bsp(void);
void identify_hypervisor(void);
void initializecpu(void);
void initializecpucache(void);

View File

@ -1467,6 +1467,19 @@ identify_cpu2(void)
}
}
void
identify_cpu_fixup_bsp(void)
{
u_int regs[4];
cpu_vendor_id = find_cpu_vendor_id();
if (fix_cpuid()) {
do_cpuid(0, regs);
cpu_high = regs[0];
}
}
/*
* Final stage of CPU identification.
*/
@ -1478,12 +1491,7 @@ finishidentcpu(void)
u_char ccr3;
#endif
cpu_vendor_id = find_cpu_vendor_id();
if (fix_cpuid()) {
do_cpuid(0, regs);
cpu_high = regs[0];
}
identify_cpu_fixup_bsp();
if (cpu_high >= 5 && (cpu_feature2 & CPUID2_MON) != 0) {
do_cpuid(5, regs);

View File

@ -60,6 +60,7 @@ DIRDEPS = \
lib/libdevdctl \
lib/libdevinfo \
lib/libdevstat \
lib/libdl \
lib/libdwarf \
lib/libedit/edit/readline \
lib/libelf \
@ -214,10 +215,6 @@ DIRDEPS+= \
DIRDEPS+= stand/libsa32
.endif
.if defined(LINKER_FEATURES) && ${LINKER_FEATURES:Mfilter}
DIRDEPS+= lib/libdl
.endif
.if ${MK_NAND} != "no"
DIRDEPS+= lib/libnandfs
.endif

View File

@ -47,7 +47,7 @@ main(argc, argv)
char *argv[];
{
struct uufsd disk;
union dinode *dp;
union dinodep dp;
struct fs *fs;
struct stat sb;
struct statfs sfb;
@ -98,11 +98,11 @@ main(argc, argv)
(void)printf("%s (inode #%jd): ", filename,
(intmax_t)inonum);
if ((error = getino(&disk, (void **)&dp, inonum, NULL)) < 0)
warn("Read of inode %jd on %s failed",
(intmax_t)inonum, fsname);
if ((error = getinode(&disk, &dp, inonum)) < 0)
warn("Read of inode %jd on %s failed: %s",
(intmax_t)inonum, fsname, disk.d_error);
prtblknos(&disk, dp);
prtblknos(&disk, (union dinode *)dp.dp1);
}
exit(0);
}

View File

@ -8,4 +8,10 @@ PROG= head
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
.if ${MK_CASPER} != "no" && !defined(RESCUE)
LIBADD+= casper
LIBADD+= cap_fileargs
CFLAGS+=-DWITH_CASPER
.endif
.include <bsd.prog.mk>

View File

@ -43,10 +43,13 @@ static char sccsid[] = "@(#)head.c 8.2 (Berkeley) 5/4/95";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/capsicum.h>
#include <sys/types.h>
#include <capsicum_helpers.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
@ -54,6 +57,9 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
#include <libcasper.h>
#include <casper/cap_fileargs.h>
/*
* head - give the first few lines of a stream or of each of a set of files
*
@ -75,14 +81,19 @@ static const struct option long_opts[] =
int
main(int argc, char *argv[])
{
int ch;
FILE *fp;
int first, linecnt = -1, eval = 0;
off_t bytecnt = -1;
char *ep;
off_t bytecnt;
int ch, first, linecnt, eval;
fileargs_t *fa;
cap_rights_t rights;
linecnt = -1;
eval = 0;
bytecnt = -1;
obsolete(argv);
while ((ch = getopt_long(argc, argv, "+n:c:", long_opts, NULL)) != -1)
while ((ch = getopt_long(argc, argv, "+n:c:", long_opts, NULL)) != -1) {
switch(ch) {
case 'c':
bytecnt = strtoimax(optarg, &ep, 10);
@ -97,17 +108,28 @@ main(int argc, char *argv[])
case '?':
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
fa = fileargs_init(argc, argv, O_RDONLY, 0,
cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL));
if (fa == NULL)
errx(1, "unable to init casper");
caph_cache_catpages();
if (caph_limit_stdio() < 0 || caph_enter_casper() < 0)
err(1, "unable to enter capability mode");
if (linecnt != -1 && bytecnt != -1)
errx(1, "can't combine line and byte counts");
if (linecnt == -1 )
if (linecnt == -1)
linecnt = 10;
if (*argv) {
for (first = 1; *argv; ++argv) {
if ((fp = fopen(*argv, "r")) == NULL) {
if (*argv != NULL) {
for (first = 1; *argv != NULL; ++argv) {
if ((fp = fileargs_fopen(fa, *argv, "r")) == NULL) {
warn("%s", *argv);
eval = 1;
continue;
@ -128,6 +150,7 @@ main(int argc, char *argv[])
else
head_bytes(stdin, bytecnt);
fileargs_free(fa);
exit(eval);
}
@ -137,7 +160,7 @@ head(FILE *fp, int cnt)
char *cp;
size_t error, readlen;
while (cnt && (cp = fgetln(fp, &readlen)) != NULL) {
while (cnt != 0 && (cp = fgetln(fp, &readlen)) != NULL) {
error = fwrite(cp, sizeof(char), readlen, stdout);
if (error != readlen)
err(1, "stdout");

View File

@ -1,7 +1,15 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
.include <src.opts.mk>
PROG= wc
LIBADD= xo
.if ${MK_CASPER} != "no"
LIBADD+= casper
LIBADD+= cap_fileargs
CFLAGS+=-DWITH_CASPER
.endif
.include <bsd.prog.mk>

View File

@ -44,9 +44,11 @@ static char sccsid[] = "@(#)wc.c 8.1 (Berkeley) 6/6/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/capsicum.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <capsicum_helpers.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@ -61,6 +63,10 @@ __FBSDID("$FreeBSD$");
#include <wctype.h>
#include <libxo/xo.h>
#include <libcasper.h>
#include <casper/cap_fileargs.h>
static fileargs_t *fa;
static uintmax_t tlinect, twordct, tcharct, tlongline;
static int doline, doword, dochar, domulti, dolongline;
static volatile sig_atomic_t siginfo;
@ -90,6 +96,7 @@ int
main(int argc, char *argv[])
{
int ch, errors, total;
cap_rights_t rights;
(void) setlocale(LC_CTYPE, "");
@ -125,6 +132,26 @@ main(int argc, char *argv[])
(void)signal(SIGINFO, siginfo_handler);
fa = fileargs_init(argc, argv, O_RDONLY, 0,
cap_rights_init(&rights, CAP_READ, CAP_FSTAT));
if (fa == NULL) {
xo_warn("Unable to init casper");
exit(1);
}
caph_cache_catpages();
if (caph_limit_stdio() < 0) {
xo_warn("Unable to limit stdio");
fileargs_free(fa);
exit(1);
}
if (caph_enter_casper() < 0) {
xo_warn("Unable to enter capability mode");
fileargs_free(fa);
exit(1);
}
/* Wc's flags are on by default. */
if (doline + doword + dochar + domulti + dolongline == 0)
doline = doword = dochar = 1;
@ -158,6 +185,7 @@ main(int argc, char *argv[])
xo_close_container("total");
}
fileargs_free(fa);
xo_close_container("wc");
xo_finish();
exit(errors == 0 ? 0 : 1);
@ -206,7 +234,7 @@ cnt(const char *file)
linect = wordct = charct = llct = tmpll = 0;
if (file == NULL)
fd = STDIN_FILENO;
else if ((fd = open(file, O_RDONLY, 0)) < 0) {
else if ((fd = fileargs_open(fa, file)) < 0) {
xo_warn("%s: open", file);
return (1);
}

View File

@ -73,16 +73,16 @@ amd_probe(int fd)
}
void
amd_update(const char *dev, const char *path)
amd_update(const struct ucode_update_params *params)
{
int fd, devfd;
int devfd;
unsigned int i;
struct stat st;
uint32_t *fw_image;
amd_fw_header_t *fw_header;
const char *dev, *path;
const uint32_t *fw_image;
const amd_fw_header_t *fw_header;
uint32_t sum;
uint32_t signature;
uint32_t *fw_data;
const uint32_t *fw_data;
size_t fw_size;
cpuctl_cpuid_args_t idargs = {
.level = 1, /* Request signature. */
@ -90,16 +90,14 @@ amd_update(const char *dev, const char *path)
cpuctl_update_args_t args;
int error;
dev = params->dev_path;
path = params->fw_path;
devfd = params->devfd;
fw_image = params->fwimage;
assert(path);
assert(dev);
fd = -1;
fw_image = MAP_FAILED;
devfd = open(dev, O_RDWR);
if (devfd < 0) {
WARN(0, "could not open %s for writing", dev);
return;
}
error = ioctl(devfd, CPUCTL_CPUID, &idargs);
if (error < 0) {
WARN(0, "ioctl()");
@ -115,37 +113,18 @@ amd_update(const char *dev, const char *path)
/*
* Open the firmware file.
*/
fd = open(path, O_RDONLY, 0);
if (fd < 0) {
WARN(0, "open(%s)", path);
goto fail;
}
error = fstat(fd, &st);
if (error != 0) {
WARN(0, "fstat(%s)", path);
goto fail;
}
if (st.st_size < 0 || (unsigned)st.st_size < sizeof(*fw_header)) {
if (params->fwsize < sizeof(*fw_header)) {
WARNX(2, "file too short: %s", path);
goto fail;
}
/*
* mmap the whole image.
*/
fw_image = (uint32_t *)mmap(NULL, st.st_size, PROT_READ,
MAP_PRIVATE, fd, 0);
if (fw_image == MAP_FAILED) {
WARN(0, "mmap(%s)", path);
goto fail;
}
fw_header = (amd_fw_header_t *)fw_image;
fw_header = (const amd_fw_header_t *)fw_image;
if ((fw_header->magic >> 8) != AMD_MAGIC) {
WARNX(2, "%s is not a valid amd firmware: version mismatch",
path);
goto fail;
}
fw_data = (uint32_t *)(fw_header + 1);
fw_size = (st.st_size - sizeof(*fw_header)) / sizeof(uint32_t);
fw_data = (const uint32_t *)(fw_header + 1);
fw_size = (params->fwsize - sizeof(*fw_header)) / sizeof(uint32_t);
/*
* Check the primary checksum.
@ -160,8 +139,8 @@ amd_update(const char *dev, const char *path)
if (signature == fw_header->signature) {
fprintf(stderr, "%s: updating cpu %s... ", path, dev);
args.data = fw_image;
args.size = st.st_size;
args.data = __DECONST(void *, fw_image);
args.size = params->fwsize;
error = ioctl(devfd, CPUCTL_UPDATE, &args);
if (error < 0) {
fprintf(stderr, "failed.\n");
@ -172,12 +151,5 @@ amd_update(const char *dev, const char *path)
}
fail:
if (fd >= 0)
close(fd);
if (devfd >= 0)
close(devfd);
if (fw_image != MAP_FAILED)
if(munmap(fw_image, st.st_size) != 0)
warn("munmap(%s)", path);
return;
}

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