IFC @ r245178
This commit is contained in:
commit
1b54fbe69d
@ -184,7 +184,10 @@ prn_octal(const char *s)
|
||||
for (i = 0; i < (int)clen; i++)
|
||||
putchar((unsigned char)s[i]);
|
||||
len += wcwidth(wc);
|
||||
} else if (goodchar && f_octal_escape && wc >= 0 &&
|
||||
} else if (goodchar && f_octal_escape &&
|
||||
#if WCHAR_MIN < 0
|
||||
wc >= 0 &&
|
||||
#endif
|
||||
wc <= (wchar_t)UCHAR_MAX &&
|
||||
(p = strchr(esc, (char)wc)) != NULL) {
|
||||
putchar('\\');
|
||||
|
@ -25,6 +25,22 @@ THIS SOFTWARE.
|
||||
This file lists all bug fixes, changes, etc., made since the AWK book
|
||||
was sent to the printers in August, 1987.
|
||||
|
||||
Dec 20, 2012:
|
||||
fiddled makefile to get correct yacc and bison flags. pick yacc
|
||||
(linux) or bison (mac) as necessary.
|
||||
|
||||
added __attribute__((__noreturn__)) to a couple of lines in
|
||||
proto.h, to silence someone's enthusiastic checker.
|
||||
|
||||
fixed obscure call by value bug in split(a[1],a) reported on
|
||||
9fans. the management of temporary values is just a mess; i
|
||||
took a shortcut by making an extra string copy. thanks
|
||||
to paul patience and arnold robbins for passing it on and for
|
||||
proposed patches.
|
||||
|
||||
tiny fiddle in setfval to eliminate -0 results in T.expr, which
|
||||
has irritated me for 20+ years.
|
||||
|
||||
Aug 10, 2011:
|
||||
another fix to avoid core dump with delete(ARGV); again, many thanks
|
||||
to ruslan ermilov.
|
||||
|
@ -25,7 +25,7 @@ THIS SOFTWARE.
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
const char *version = "version 20110810 (FreeBSD)";
|
||||
const char *version = "version 20121220 (FreeBSD)";
|
||||
|
||||
#define DEBUG
|
||||
#include <stdio.h>
|
||||
|
@ -26,15 +26,15 @@ CFLAGS = -g
|
||||
CFLAGS = -O2
|
||||
CFLAGS =
|
||||
|
||||
CC = gcc -Wall -g
|
||||
CC = cc
|
||||
CC = gcc -Wall -g -Wwrite-strings
|
||||
CC = gcc -fprofile-arcs -ftest-coverage # then gcov f1.c; cat f1.c.gcov
|
||||
CC = gcc -g -Wall -pedantic
|
||||
CC = gcc -O4 -Wall -pedantic -fno-strict-aliasing
|
||||
|
||||
YACC = bison -y
|
||||
YACC = yacc
|
||||
YFLAGS = -d
|
||||
YACC = bison -d -y
|
||||
YACC = yacc -d -S
|
||||
#YFLAGS = -d -S
|
||||
# -S uses sprintf in yacc parser instead of sprint
|
||||
|
||||
OFILES = b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o
|
||||
|
||||
|
@ -46,7 +46,7 @@ extern void freetr(Node *);
|
||||
extern int hexstr(uschar **);
|
||||
extern int quoted(uschar **);
|
||||
extern char *cclenter(const char *);
|
||||
extern void overflo(const char *);
|
||||
extern void overflo(const char *) __attribute__((__noreturn__));
|
||||
extern void cfoll(fa *, Node *);
|
||||
extern int first(Node *);
|
||||
extern void follow(Node *);
|
||||
@ -132,7 +132,7 @@ extern void fpecatch(int);
|
||||
extern void bracecheck(void);
|
||||
extern void bcheck2(int, int, int);
|
||||
extern void SYNTAX(const char *, ...);
|
||||
extern void FATAL(const char *, ...);
|
||||
extern void FATAL(const char *, ...) __attribute__((__noreturn__));
|
||||
extern void WARNING(const char *, ...);
|
||||
extern void error(void);
|
||||
extern void eprint(void);
|
||||
|
@ -1213,13 +1213,13 @@ Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
|
||||
Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
|
||||
{
|
||||
Cell *x = 0, *y, *ap;
|
||||
char *s;
|
||||
char *s, *origs;
|
||||
int sep;
|
||||
char *t, temp, num[50], *fs = 0;
|
||||
int n, tempstat, arg3type;
|
||||
|
||||
y = execute(a[0]); /* source string */
|
||||
s = getsval(y);
|
||||
origs = s = strdup(getsval(y));
|
||||
arg3type = ptoi(a[3]);
|
||||
if (a[2] == 0) /* fs string */
|
||||
fs = *FS;
|
||||
@ -1339,6 +1339,7 @@ Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
|
||||
}
|
||||
tempfree(ap);
|
||||
tempfree(y);
|
||||
free(origs);
|
||||
if (a[2] != 0 && arg3type == STRING) {
|
||||
tempfree(x);
|
||||
}
|
||||
|
@ -298,6 +298,8 @@ Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */
|
||||
xfree(vp->sval); /* free any previous string */
|
||||
vp->tval &= ~STR; /* mark string invalid */
|
||||
vp->tval |= NUM; /* mark number ok */
|
||||
if (f == -0) /* who would have thought this possible? */
|
||||
f = 0;
|
||||
dprintf( ("setfval %p: %s = %g, t=%o\n", (void*)vp, NN(vp->nval), f, vp->tval) );
|
||||
return vp->fval = f;
|
||||
}
|
||||
|
@ -7,14 +7,14 @@
|
||||
; (e.g. reference this file in the "cache . <file>"
|
||||
; configuration file of BIND domain name servers).
|
||||
;
|
||||
; This file is made available by InterNIC
|
||||
; This file is made available by InterNIC
|
||||
; under anonymous FTP as
|
||||
; file /domain/named.root
|
||||
; file /domain/named.cache
|
||||
; on server FTP.INTERNIC.NET
|
||||
; -OR- RS.INTERNIC.NET
|
||||
;
|
||||
; last update: Jun 8, 2011
|
||||
; related version of root zone: 2011060800
|
||||
; last update: Jan 3, 2013
|
||||
; related version of root zone: 2013010300
|
||||
;
|
||||
; formerly NS.INTERNIC.NET
|
||||
;
|
||||
@ -35,7 +35,7 @@ C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12
|
||||
; FORMERLY TERP.UMD.EDU
|
||||
;
|
||||
. 3600000 NS D.ROOT-SERVERS.NET.
|
||||
D.ROOT-SERVERS.NET. 3600000 A 128.8.10.90
|
||||
D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13
|
||||
D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2D::D
|
||||
;
|
||||
; FORMERLY NS.NASA.GOV
|
||||
|
@ -43,5 +43,5 @@ divert(0)dnl
|
||||
VERSIONID(`$FreeBSD$')
|
||||
|
||||
OSTYPE(freebsd6)
|
||||
FEATURE(nullclient, smarthost.ysv.$m)
|
||||
FEATURE(nullclient, smarthost.ysv.freebsd.org)
|
||||
MASQUERADE_AS(FreeBSD.org)
|
||||
|
@ -1,6 +1,7 @@
|
||||
# $FreeBSD$
|
||||
. ${srcdir}/emulparams/armelf.sh
|
||||
. ${srcdir}/emulparams/elf_fbsd.sh
|
||||
TARGET2_TYPE=got-rel
|
||||
MAXPAGESIZE=0x8000
|
||||
GENERATE_PIE_SCRIPT=yes
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#OUTPUT_FORMAT="elf32-bigarm"
|
||||
. ${srcdir}/emulparams/armelf.sh
|
||||
. ${srcdir}/emulparams/elf_fbsd.sh
|
||||
TARGET2_TYPE=got-rel
|
||||
MAXPAGESIZE=0x8000
|
||||
GENERATE_PIE_SCRIPT=yes
|
||||
|
||||
|
@ -61,9 +61,7 @@ _start(char **ap, void (*cleanup)(void))
|
||||
argc = *(long *)(void *)ap;
|
||||
argv = ap + 1;
|
||||
env = ap + 2 + argc;
|
||||
environ = env;
|
||||
if (argc > 0 && argv[0] != NULL)
|
||||
handle_progname(argv[0]);
|
||||
handle_argv(argc, argv, env);
|
||||
|
||||
if (&_DYNAMIC != NULL)
|
||||
atexit(cleanup);
|
||||
|
@ -98,10 +98,7 @@ __start(int argc, char **argv, char **env, struct ps_strings *ps_strings,
|
||||
const struct Struct_Obj_Entry *obj __unused, void (*cleanup)(void))
|
||||
{
|
||||
|
||||
environ = env;
|
||||
|
||||
if (argc > 0 && argv[0] != NULL)
|
||||
handle_progname(argv[0]);
|
||||
handle_argv(argc, argv, env);
|
||||
|
||||
if (ps_strings != (struct ps_strings *)0)
|
||||
__ps_strings = ps_strings;
|
||||
|
@ -87,14 +87,18 @@ handle_static_init(int argc, char **argv, char **env)
|
||||
}
|
||||
|
||||
static inline void
|
||||
handle_progname(const char *v)
|
||||
handle_argv(int argc, char *argv[], char **env)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
__progname = v;
|
||||
for (s = __progname; *s != '\0'; s++) {
|
||||
if (*s == '/')
|
||||
__progname = s + 1;
|
||||
if (environ == NULL)
|
||||
environ = env;
|
||||
if (argc > 0 && argv[0] != NULL) {
|
||||
__progname = argv[0];
|
||||
for (s = __progname; *s != '\0'; s++) {
|
||||
if (*s == '/')
|
||||
__progname = s + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,10 +61,7 @@ _start1(fptr cleanup, int argc, char *argv[])
|
||||
char **env;
|
||||
|
||||
env = argv + argc + 1;
|
||||
environ = env;
|
||||
if (argc > 0 && argv[0] != NULL)
|
||||
handle_progname(argv[0]);
|
||||
|
||||
handle_argv(argc, argv, env);
|
||||
if (&_DYNAMIC != NULL)
|
||||
atexit(cleanup);
|
||||
else
|
||||
|
@ -71,9 +71,7 @@ __start(char **ap,
|
||||
argc = * (long *) ap;
|
||||
argv = ap + 1;
|
||||
env = ap + 2 + argc;
|
||||
environ = env;
|
||||
if (argc > 0 && argv[0] != NULL)
|
||||
handle_progname(argv[0]);
|
||||
handle_argv(argc, argv, env);
|
||||
|
||||
if (&_DYNAMIC != NULL)
|
||||
atexit(cleanup);
|
||||
|
@ -81,10 +81,8 @@ _start(int argc, char **argv, char **env,
|
||||
struct ps_strings *ps_strings)
|
||||
{
|
||||
|
||||
environ = env;
|
||||
|
||||
if (argc > 0 && argv[0] != NULL)
|
||||
handle_progname(argv[0]);
|
||||
handle_argv(argc, argv, env);
|
||||
|
||||
if (ps_strings != (struct ps_strings *)0)
|
||||
__ps_strings = ps_strings;
|
||||
|
@ -81,10 +81,7 @@ _start(int argc, char **argv, char **env,
|
||||
struct ps_strings *ps_strings)
|
||||
{
|
||||
|
||||
environ = env;
|
||||
|
||||
if (argc > 0 && argv[0] != NULL)
|
||||
handle_progname(argv[0]);
|
||||
handle_argv(argc, argv, env);
|
||||
|
||||
if (ps_strings != (struct ps_strings *)0)
|
||||
__ps_strings = ps_strings;
|
||||
|
@ -85,9 +85,7 @@ _start(char **ap, void (*cleanup)(void), struct Struct_Obj_Entry *obj __unused,
|
||||
argc = *(long *)(void *)ap;
|
||||
argv = ap + 1;
|
||||
env = ap + 2 + argc;
|
||||
environ = env;
|
||||
if (argc > 0 && argv[0] != NULL)
|
||||
handle_progname(argv[0]);
|
||||
handle_argv(argc, argv, env);
|
||||
|
||||
if (&_DYNAMIC != NULL)
|
||||
atexit(cleanup);
|
||||
|
@ -95,7 +95,7 @@ what the endianness of the CPU. VFP is sane.
|
||||
#define FLOAT64_DEMANGLE(a) (a)
|
||||
#define FLOAT64_MANGLE(a) (a)
|
||||
#else
|
||||
#define FLOAT64_DEMANGLE(a) (((a) << 32) | ((a) >> 32))
|
||||
#define FLOAT64_DEMANGLE(a) ((((a) & 0xfffffffful) << 32) | ((a) >> 32))
|
||||
#define FLOAT64_MANGLE(a) FLOAT64_DEMANGLE(a)
|
||||
#endif
|
||||
#endif
|
||||
|
@ -36,9 +36,9 @@ if [ $# -lt 3 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LABEL=$1; shift
|
||||
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
|
||||
NAME=$1; shift
|
||||
|
||||
echo "/dev/iso9660/`echo $LABEL | tr '[:lower:]' '[:upper:]'` / cd9660 ro 0 0" > $1/etc/fstab
|
||||
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
|
||||
makefs -t cd9660 $bootable -o rockridge -o label=$LABEL $NAME $*
|
||||
rm $1/etc/fstab
|
||||
|
@ -36,9 +36,9 @@ if [ $# -lt 3 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LABEL=$1; shift
|
||||
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
|
||||
NAME=$1; shift
|
||||
|
||||
echo "/dev/iso9660/`echo $LABEL | tr '[:lower:]' '[:upper:]'` / cd9660 ro 0 0" > $1/etc/fstab
|
||||
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
|
||||
makefs -t cd9660 $bootable -o rockridge -o label=$LABEL $NAME $*
|
||||
rm $1/etc/fstab
|
||||
|
@ -37,7 +37,7 @@ if [ $# -lt 3 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LABEL=$1; shift
|
||||
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
|
||||
NAME=$1; shift
|
||||
BASE=$1; shift
|
||||
|
||||
|
@ -36,9 +36,9 @@ if [ $# -lt 3 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LABEL=$1; shift
|
||||
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
|
||||
NAME=$1; shift
|
||||
|
||||
echo "/dev/iso9660/`echo $LABEL | tr '[:lower:]' '[:upper:]'` / cd9660 ro 0 0" > $1/etc/fstab
|
||||
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
|
||||
makefs -t cd9660 $bootable -o rockridge -o label=$LABEL $NAME $*
|
||||
rm $1/etc/fstab
|
||||
|
@ -58,10 +58,10 @@ if [ $# -lt 3 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LABEL=$1; shift
|
||||
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
|
||||
NAME=$1; shift
|
||||
|
||||
echo "/dev/iso9660/`echo $LABEL | tr '[:lower:]' '[:upper:]'` / cd9660 ro 0 0" > $1/etc/fstab
|
||||
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
|
||||
makefs -t cd9660 $bootable -o rockridge -o label=$LABEL $NAME $*
|
||||
rm $1/etc/fstab
|
||||
rm /tmp/hfs-boot-block
|
||||
|
@ -63,7 +63,7 @@ if [ $? -ne 0 ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
LABEL=$1; shift
|
||||
LABEL=`echo $1 | tr '[:lower:]' '[:upper:]'`; shift
|
||||
NAME=$1; shift
|
||||
|
||||
echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > $1/etc/fstab
|
||||
|
@ -73,6 +73,6 @@ g_journal_ufs_using_last_sector(const char *prov)
|
||||
/* Provider size in 512 bytes blocks. */
|
||||
psize = g_get_mediasize(prov) / DEV_BSIZE;
|
||||
/* File system size in 512 bytes blocks. */
|
||||
fssize = fsbtodb(fs, dbtofsb(fs, psize));
|
||||
return (psize == fssize);
|
||||
fssize = fsbtodb(fs, fs->fs_size);
|
||||
return (psize <= fssize);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 19, 2012
|
||||
.Dd January 3, 2013
|
||||
.Dt GPART 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -453,8 +453,14 @@ about its use.
|
||||
.El
|
||||
.\" ==== SHOW ====
|
||||
.It Cm show
|
||||
Show the current partition information of the specified geoms
|
||||
or all geoms if none are specified.
|
||||
Show current partition information for the specified geoms, or all
|
||||
geoms if none are specified.
|
||||
The default output includes the logical starting block of each
|
||||
partition, the partition size in blocks, the partition index number,
|
||||
the partition type, and a human readable partition size.
|
||||
Block sizes and locations are based on the device's Sectorsize
|
||||
as shown by
|
||||
.Cm gpart list .
|
||||
Additional options include:
|
||||
.Bl -tag -width 10n
|
||||
.It Fl l
|
||||
@ -919,7 +925,7 @@ and
|
||||
.Cm list
|
||||
will report about corrupt tables.
|
||||
.Pp
|
||||
If the size of the device has changed (e.g.\& volume expansion) the
|
||||
If the size of the device has changed (e.g.,\& volume expansion) the
|
||||
secondary GPT header will no longer be located in the last sector.
|
||||
This is not a metadata corruption, but it is dangerous because any
|
||||
corruption of the primary GPT will lead to loss of the partition table.
|
||||
@ -979,14 +985,14 @@ This may break a mirrored volume and lead to data damage.
|
||||
Exit status is 0 on success, and 1 if the command fails.
|
||||
.Sh EXAMPLES
|
||||
Create a GPT scheme on
|
||||
.Pa ad0 :
|
||||
.Pa ada0 :
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart create -s GPT ad0
|
||||
/sbin/gpart create -s GPT ada0
|
||||
.Ed
|
||||
.Pp
|
||||
Embed GPT bootstrap code into a protective MBR:
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart bootcode -b /boot/pmbr ad0
|
||||
/sbin/gpart bootcode -b /boot/pmbr ada0
|
||||
.Ed
|
||||
.Pp
|
||||
Create a dedicated
|
||||
@ -1011,15 +1017,15 @@ aligned on a 64 kB boundary without the need to specify an explicit
|
||||
offset or alignment.
|
||||
The boot partition itself is aligned on a 4 kB boundary.
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart add -b 40 -s 88 -t freebsd-boot ad0
|
||||
/sbin/gpart bootcode -p /boot/gptboot -i 1 ad0
|
||||
/sbin/gpart add -b 40 -s 88 -t freebsd-boot ada0
|
||||
/sbin/gpart bootcode -p /boot/gptboot -i 1 ada0
|
||||
.Ed
|
||||
.Pp
|
||||
Create a 512MB-sized
|
||||
.Cm freebsd-ufs
|
||||
partition to contain a UFS filesystem from which the system can boot.
|
||||
.Bd -literal -offset indent
|
||||
/sbin/gpart add -s 512M -t freebsd-ufs ad0
|
||||
/sbin/gpart add -s 512M -t freebsd-ufs ada0
|
||||
.Ed
|
||||
.Pp
|
||||
Create an MBR scheme on
|
||||
|
@ -57,27 +57,35 @@ static const char rcsid[] =
|
||||
|
||||
#include "mntopts.h"
|
||||
|
||||
static struct mntopt mopts[] = {
|
||||
MOPT_STDOPTS,
|
||||
MOPT_END
|
||||
};
|
||||
|
||||
int subdir(const char *, const char *);
|
||||
static void usage(void) __dead2;
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct iovec iov[6];
|
||||
int ch, mntflags;
|
||||
struct iovec *iov;
|
||||
char *p, *val;
|
||||
char source[MAXPATHLEN];
|
||||
char target[MAXPATHLEN];
|
||||
char errmsg[255];
|
||||
int ch, mntflags, iovlen;
|
||||
char nullfs[] = "nullfs";
|
||||
|
||||
iov = NULL;
|
||||
iovlen = 0;
|
||||
mntflags = 0;
|
||||
errmsg[0] = '\0';
|
||||
while ((ch = getopt(argc, argv, "o:")) != -1)
|
||||
switch(ch) {
|
||||
case 'o':
|
||||
getmntopts(optarg, mopts, &mntflags, 0);
|
||||
val = strdup("");
|
||||
p = strchr(optarg, '=');
|
||||
if (p != NULL) {
|
||||
free(val);
|
||||
*p = '\0';
|
||||
val = p + 1;
|
||||
}
|
||||
build_iovec(&iov, &iovlen, optarg, val, (size_t)-1);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
@ -99,21 +107,16 @@ main(int argc, char *argv[])
|
||||
errx(EX_USAGE, "%s (%s) and %s are not distinct paths",
|
||||
argv[0], target, argv[1]);
|
||||
|
||||
iov[0].iov_base = strdup("fstype");
|
||||
iov[0].iov_len = sizeof("fstype");
|
||||
iov[1].iov_base = strdup("nullfs");
|
||||
iov[1].iov_len = strlen(iov[1].iov_base) + 1;
|
||||
iov[2].iov_base = strdup("fspath");
|
||||
iov[2].iov_len = sizeof("fspath");
|
||||
iov[3].iov_base = source;
|
||||
iov[3].iov_len = strlen(source) + 1;
|
||||
iov[4].iov_base = strdup("target");
|
||||
iov[4].iov_len = sizeof("target");
|
||||
iov[5].iov_base = target;
|
||||
iov[5].iov_len = strlen(target) + 1;
|
||||
|
||||
if (nmount(iov, 6, mntflags))
|
||||
err(1, NULL);
|
||||
build_iovec(&iov, &iovlen, "fstype", nullfs, (size_t)-1);
|
||||
build_iovec(&iov, &iovlen, "fspath", source, (size_t)-1);
|
||||
build_iovec(&iov, &iovlen, "target", target, (size_t)-1);
|
||||
build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
|
||||
if (nmount(iov, iovlen, mntflags) < 0) {
|
||||
if (errmsg[0] != 0)
|
||||
err(1, "%s: %s", source, errmsg);
|
||||
else
|
||||
err(1, "%s", source);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ typedef union sockunion *sup;
|
||||
int pid, rtm_addrs;
|
||||
int s;
|
||||
int forcehost, forcenet, doflush, nflag, af, qflag, tflag;
|
||||
int iflag, verbose, aflen = sizeof (struct sockaddr_in);
|
||||
int verbose, aflen = sizeof (struct sockaddr_in);
|
||||
int locking, lockrest, debugonly;
|
||||
struct rt_metrics rt_metrics;
|
||||
u_long rtm_inits;
|
||||
@ -107,7 +107,7 @@ static char *atalk_ntoa(struct at_addr);
|
||||
static void bprintf(FILE *, int, u_char *);
|
||||
static void flushroutes(int argc, char *argv[]);
|
||||
static int flushroutes_fib(int);
|
||||
static int getaddr(int, char *, struct hostent **);
|
||||
static int getaddr(int, char *, struct hostent **, int);
|
||||
static int keyword(const char *);
|
||||
static void inet_makenetandmask(u_long, struct sockaddr_in *, u_long);
|
||||
#ifdef INET6
|
||||
@ -833,34 +833,34 @@ newroute(int argc, char **argv)
|
||||
case K_IFA:
|
||||
if (!--argc)
|
||||
usage(NULL);
|
||||
(void) getaddr(RTA_IFA, *++argv, 0);
|
||||
getaddr(RTA_IFA, *++argv, 0, nrflags);
|
||||
break;
|
||||
case K_IFP:
|
||||
if (!--argc)
|
||||
usage(NULL);
|
||||
(void) getaddr(RTA_IFP, *++argv, 0);
|
||||
getaddr(RTA_IFP, *++argv, 0, nrflags);
|
||||
break;
|
||||
case K_GENMASK:
|
||||
if (!--argc)
|
||||
usage(NULL);
|
||||
(void) getaddr(RTA_GENMASK, *++argv, 0);
|
||||
getaddr(RTA_GENMASK, *++argv, 0, nrflags);
|
||||
break;
|
||||
case K_GATEWAY:
|
||||
if (!--argc)
|
||||
usage(NULL);
|
||||
(void) getaddr(RTA_GATEWAY, *++argv, 0);
|
||||
getaddr(RTA_GATEWAY, *++argv, 0, nrflags);
|
||||
break;
|
||||
case K_DST:
|
||||
if (!--argc)
|
||||
usage(NULL);
|
||||
if (getaddr(RTA_DST, *++argv, &hp))
|
||||
if (getaddr(RTA_DST, *++argv, &hp, nrflags))
|
||||
nrflags |= F_ISHOST;
|
||||
dest = *argv;
|
||||
break;
|
||||
case K_NETMASK:
|
||||
if (!--argc)
|
||||
usage(NULL);
|
||||
(void) getaddr(RTA_NETMASK, *++argv, 0);
|
||||
getaddr(RTA_NETMASK, *++argv, 0, nrflags);
|
||||
/* FALLTHROUGH */
|
||||
case K_NET:
|
||||
nrflags |= F_FORCENET;
|
||||
@ -895,13 +895,13 @@ newroute(int argc, char **argv)
|
||||
} else {
|
||||
if ((rtm_addrs & RTA_DST) == 0) {
|
||||
dest = *argv;
|
||||
if (getaddr(RTA_DST, *argv, &hp))
|
||||
if (getaddr(RTA_DST, *argv, &hp, nrflags))
|
||||
nrflags |= F_ISHOST;
|
||||
} else if ((rtm_addrs & RTA_GATEWAY) == 0) {
|
||||
gateway = *argv;
|
||||
(void) getaddr(RTA_GATEWAY, *argv, &hp);
|
||||
getaddr(RTA_GATEWAY, *argv, &hp, nrflags);
|
||||
} else {
|
||||
(void) getaddr(RTA_NETMASK, *argv, 0);
|
||||
getaddr(RTA_NETMASK, *argv, 0, nrflags);
|
||||
nrflags |= F_FORCENET;
|
||||
}
|
||||
}
|
||||
@ -1116,7 +1116,7 @@ inet6_makenetandmask(struct sockaddr_in6 *sin6, const char *plen)
|
||||
* returning 1 if a host address, 0 if a network address.
|
||||
*/
|
||||
static int
|
||||
getaddr(int which, char *str, struct hostent **hpp)
|
||||
getaddr(int which, char *str, struct hostent **hpp, int nrflags)
|
||||
{
|
||||
sup su;
|
||||
struct hostent *hp;
|
||||
@ -1137,7 +1137,7 @@ getaddr(int which, char *str, struct hostent **hpp)
|
||||
break;
|
||||
case RTA_GATEWAY:
|
||||
su = &so_gate;
|
||||
if (iflag) {
|
||||
if (nrflags & F_INTERFACE) {
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct sockaddr_dl *sdl = NULL;
|
||||
|
||||
@ -1197,7 +1197,7 @@ getaddr(int which, char *str, struct hostent **hpp)
|
||||
#if 0
|
||||
bzero(su, sizeof(*su)); /* for readability */
|
||||
#endif
|
||||
getaddr(RTA_NETMASK, str, 0);
|
||||
getaddr(RTA_NETMASK, str, 0, nrflags);
|
||||
break;
|
||||
#if 0
|
||||
case RTA_NETMASK:
|
||||
|
@ -52,7 +52,6 @@ XFILES= BSD_daemon/FreeBSD.pfa \
|
||||
csh/dot.cshrc \
|
||||
cvsup/README \
|
||||
cvsup/cvs-supfile \
|
||||
cvsup/gnats-supfile \
|
||||
cvsup/ports-supfile \
|
||||
cvsup/refuse \
|
||||
cvsup/refuse.README \
|
||||
|
@ -1,5 +1,15 @@
|
||||
# $FreeBSD$
|
||||
|
||||
BEWARE, CVS is deprecated and no longer supported by the FreeBSD project.
|
||||
|
||||
The primary development work happens in Subversion and is temporarily
|
||||
exported to the legacy CVS system with significant time delays.
|
||||
|
||||
You should NOT set up a new consumer of FreeBSD source code via CVS.
|
||||
Please see:
|
||||
http://www.freebsd.org/doc/handbook/svn.html
|
||||
http://www.freebsd.org/doc/handbook/svn-mirrors.html
|
||||
|
||||
This directory contains sample "supfiles" for obtaining and updating
|
||||
the FreeBSD sources via the Internet. These supfiles will work
|
||||
with CVSup version 14.0 or later. For general information on CVSup
|
||||
@ -20,10 +30,6 @@ FreeBSD, use:
|
||||
|
||||
cvs-supfile Main source tree and ports collection
|
||||
|
||||
To maintain a copy of the FreeBSD bug database, use the file:
|
||||
|
||||
gnats-supfile FreeBSD bug database
|
||||
|
||||
IMPORTANT: Before you use any of the supfiles in this directory,
|
||||
you will need to edit in an appropriate "host" setting. See:
|
||||
|
||||
|
@ -1,7 +1,14 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# This file contains all of the "CVSup collections" that make up the
|
||||
# CVS development tree of the FreeBSD system.
|
||||
# BEWARE, CVS is deprecated and no longer supported by the FreeBSD project.
|
||||
#
|
||||
# The primary development work happens in Subversion and is temporarily
|
||||
# exported to the legacy CVS system with significant time delays.
|
||||
#
|
||||
# You should NOT set up a new consumer of FreeBSD source code via CVS.
|
||||
# Please see:
|
||||
# http://www.freebsd.org/doc/handbook/svn.html
|
||||
# http://www.freebsd.org/doc/handbook/svn-mirrors.html
|
||||
#
|
||||
# csup (CVS Update Protocol) allows you to download the latest CVS
|
||||
# tree (or any branch of development therefrom) to your system easily
|
||||
@ -61,36 +68,6 @@
|
||||
# mega-collection. It includes all of the individual "src-*" collections.
|
||||
src-all
|
||||
|
||||
# These are the individual collections that make up "src-all". If you
|
||||
# use these, be sure to comment out "src-all" above.
|
||||
#src-base
|
||||
#src-bin
|
||||
#src-cddl
|
||||
#src-contrib
|
||||
#src-etc
|
||||
#src-games
|
||||
#src-gnu
|
||||
#src-include
|
||||
#src-kerberos5
|
||||
#src-kerberosIV
|
||||
#src-lib
|
||||
#src-libexec
|
||||
#src-release
|
||||
#src-rescue
|
||||
#src-sbin
|
||||
#src-share
|
||||
#src-sys
|
||||
#src-tools
|
||||
#src-usrbin
|
||||
#src-usrsbin
|
||||
# These are the individual collections that make up FreeBSD's crypto
|
||||
# collection. They are no longer export-restricted and are a part of
|
||||
# src-all
|
||||
#src-crypto
|
||||
#src-eBones
|
||||
#src-secure
|
||||
#src-sys-crypto
|
||||
|
||||
## Ports Collection.
|
||||
#
|
||||
# The easiest way to get the ports tree is to use the "ports-all"
|
||||
@ -98,77 +75,6 @@ src-all
|
||||
# collections,
|
||||
ports-all
|
||||
|
||||
# These are the individual collections that make up "ports-all". If you
|
||||
# use these, be sure to comment out "ports-all" above and always include
|
||||
# "ports-base" if you use any of the other individual collections below.
|
||||
# Your ports may not build correctly without an up-to-date "ports-base".
|
||||
#
|
||||
#ports-base
|
||||
#
|
||||
#ports-accessibility
|
||||
#ports-arabic
|
||||
#ports-archivers
|
||||
#ports-astro
|
||||
#ports-audio
|
||||
#ports-benchmarks
|
||||
#ports-biology
|
||||
#ports-cad
|
||||
#ports-chinese
|
||||
#ports-comms
|
||||
#ports-converters
|
||||
#ports-databases
|
||||
#ports-deskutils
|
||||
#ports-devel
|
||||
#ports-dns
|
||||
#ports-editors
|
||||
#ports-emulators
|
||||
#ports-finance
|
||||
#ports-french
|
||||
#ports-ftp
|
||||
#ports-games
|
||||
#ports-german
|
||||
#ports-graphics
|
||||
#ports-hebrew
|
||||
#ports-hungarian
|
||||
#ports-irc
|
||||
#ports-japanese
|
||||
#ports-java
|
||||
#ports-korean
|
||||
#ports-lang
|
||||
#ports-mail
|
||||
#ports-math
|
||||
#ports-misc
|
||||
#ports-multimedia
|
||||
#ports-net
|
||||
#ports-net-im
|
||||
#ports-net-mgmt
|
||||
#ports-net-p2p
|
||||
#ports-news
|
||||
#ports-palm
|
||||
#ports-picobsd
|
||||
#ports-polish
|
||||
#ports-ports-mgmt
|
||||
#ports-portuguese
|
||||
#ports-print
|
||||
#ports-russian
|
||||
#ports-science
|
||||
#ports-security
|
||||
#ports-shells
|
||||
#ports-sysutils
|
||||
#ports-textproc
|
||||
#ports-ukrainian
|
||||
#ports-vietnamese
|
||||
#ports-www
|
||||
#ports-x11
|
||||
#ports-x11-clocks
|
||||
#ports-x11-drivers
|
||||
#ports-x11-fm
|
||||
#ports-x11-fonts
|
||||
#ports-x11-servers
|
||||
#ports-x11-themes
|
||||
#ports-x11-toolkits
|
||||
#ports-x11-wm
|
||||
|
||||
## Projects
|
||||
#
|
||||
# This collection retrieves the projects tree of the FreeBSD
|
||||
@ -179,11 +85,3 @@ projects-all
|
||||
#
|
||||
# This is to get the control files that cvs(1) needs and the commit logs.
|
||||
cvsroot-all
|
||||
|
||||
# These are the individual collections that make up "cvsroot-all" If you
|
||||
# use these, be sure to comment out "cvsroot-all" above. "cvsroot-common"
|
||||
# is a synthetic CVSROOT that has all the modules from the other CVSROOT-*
|
||||
# directories merged into one, and merged commitlogs via symlinks.
|
||||
#cvsroot-common
|
||||
#cvsroot-src
|
||||
#cvsroot-ports
|
||||
|
@ -1,60 +0,0 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# This file contains all of the "CVSup collections" that make up the
|
||||
# FreeBSD GNATS bug report database.
|
||||
#
|
||||
# csup (CVS Update Protocol) allows you to download the latest CVS
|
||||
# tree (or any branch of development therefrom) to your system easily
|
||||
# and efficiently
|
||||
#
|
||||
# To keep your CVS tree up-to-date run:
|
||||
#
|
||||
# csup gnats-supfile
|
||||
#
|
||||
# Note that this only updates the tree contents and does not
|
||||
# update what is actually installed.
|
||||
#
|
||||
# You may wish to change some of the settings in this file to better
|
||||
# suit your system:
|
||||
#
|
||||
# host=CHANGE_THIS.FreeBSD.org
|
||||
# This specifies the server host which will supply the
|
||||
# file updates. You must change it to one of the CVSup
|
||||
# mirror sites listed in the FreeBSD Handbook at
|
||||
# http://www.freebsd.org/doc/handbook/cvsup.html#CVSUP-MIRRORS.
|
||||
# You can override this setting on the command line
|
||||
# with cvsup's "-h host" option.
|
||||
#
|
||||
# base=/var/db
|
||||
# This specifies the root where csup will store information
|
||||
# about the collections you have transferred to your system.
|
||||
# A setting of "/var/db" will generate this information in
|
||||
# /var/db/sup. You can override the "base" setting on the
|
||||
# command line with cvsup's "-b base" option. This directory
|
||||
# must exist in order to run CVSup.
|
||||
#
|
||||
# prefix=/usr
|
||||
# This specifies where to place the requested files. A
|
||||
# setting of "/usr" will place all of the files requested
|
||||
# in "/usr/gnats".
|
||||
# The prefix directory must exist in order to run CVSup.
|
||||
|
||||
# Defaults that apply to all the collections
|
||||
#
|
||||
# IMPORTANT: Change the next line to use one of the CVSup mirror sites
|
||||
# listed at http://www.freebsd.org/doc/handbook/cvsup.html#CVSUP-MIRRORS.
|
||||
*default host=CHANGE_THIS.FreeBSD.org
|
||||
*default base=/var/db
|
||||
*default prefix=/usr
|
||||
*default release=current
|
||||
*default delete use-rel-suffix
|
||||
|
||||
# If you seem to be limited by CPU rather than network or disk bandwidth, try
|
||||
# commenting out the following line. (Normally, today's CPUs are fast enough
|
||||
# that you want to run compression.)
|
||||
*default compress
|
||||
|
||||
## GNATS database
|
||||
#
|
||||
gnats
|
||||
|
@ -1,7 +1,14 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# This file contains all of the "CVSup collections" that make up the
|
||||
# ports collection.
|
||||
# BEWARE, CVS is deprecated and no longer supported by the FreeBSD project.
|
||||
#
|
||||
# The primary development work happens in Subversion and is temporarily
|
||||
# exported to the legacy CVS system with significant time delays.
|
||||
#
|
||||
# You should NOT set up a new consumer of FreeBSD source code via CVS.
|
||||
# Please see:
|
||||
# http://www.freebsd.org/doc/handbook/svn.html
|
||||
# http://www.freebsd.org/doc/handbook/svn-mirrors.html
|
||||
#
|
||||
# csup (CVS Update Protocol) allows you to download the latest CVS
|
||||
# tree (or any branch of development therefrom) to your system easily
|
||||
@ -65,76 +72,3 @@
|
||||
# mega-collection. It includes all of the individual "ports-*"
|
||||
# collections,
|
||||
ports-all
|
||||
|
||||
# These are the individual collections that make up "ports-all". If you
|
||||
# use these, be sure to comment out "ports-all" above.
|
||||
|
||||
# Be sure to ALWAYS cvsup the ports-base collection if you use any of the
|
||||
# other individual collections below. ports-base is a mandatory collection
|
||||
# for the ports collection, and your ports may not build correctly if it
|
||||
# is not kept up to date.
|
||||
#
|
||||
# Use of individual collections is not a supported configuration.
|
||||
#ports-base
|
||||
#ports-accessibility
|
||||
#ports-arabic
|
||||
#ports-archivers
|
||||
#ports-astro
|
||||
#ports-audio
|
||||
#ports-benchmarks
|
||||
#ports-biology
|
||||
#ports-cad
|
||||
#ports-chinese
|
||||
#ports-comms
|
||||
#ports-converters
|
||||
#ports-databases
|
||||
#ports-deskutils
|
||||
#ports-devel
|
||||
#ports-dns
|
||||
#ports-editors
|
||||
#ports-emulators
|
||||
#ports-finance
|
||||
#ports-french
|
||||
#ports-ftp
|
||||
#ports-games
|
||||
#ports-german
|
||||
#ports-graphics
|
||||
#ports-hebrew
|
||||
#ports-hungarian
|
||||
#ports-irc
|
||||
#ports-japanese
|
||||
#ports-java
|
||||
#ports-korean
|
||||
#ports-lang
|
||||
#ports-mail
|
||||
#ports-math
|
||||
#ports-misc
|
||||
#ports-multimedia
|
||||
#ports-net
|
||||
#ports-net-im
|
||||
#ports-net-mgmt
|
||||
#ports-net-p2p
|
||||
#ports-news
|
||||
#ports-palm
|
||||
#ports-polish
|
||||
#ports-ports-mgmt
|
||||
#ports-portuguese
|
||||
#ports-print
|
||||
#ports-russian
|
||||
#ports-science
|
||||
#ports-security
|
||||
#ports-shells
|
||||
#ports-sysutils
|
||||
#ports-textproc
|
||||
#ports-ukrainian
|
||||
#ports-vietnamese
|
||||
#ports-www
|
||||
#ports-x11
|
||||
#ports-x11-clocks
|
||||
#ports-x11-drivers
|
||||
#ports-x11-fm
|
||||
#ports-x11-fonts
|
||||
#ports-x11-servers
|
||||
#ports-x11-themes
|
||||
#ports-x11-toolkits
|
||||
#ports-x11-wm
|
||||
|
@ -1,7 +1,14 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# This file contains all of the "CVSup collections" that make up the
|
||||
# FreeBSD-stable source tree.
|
||||
# BEWARE, CVS is deprecated and no longer supported by the FreeBSD project.
|
||||
#
|
||||
# The primary development work happens in Subversion and is temporarily
|
||||
# exported to the legacy CVS system with significant time delays.
|
||||
#
|
||||
# You should NOT set up a new consumer of FreeBSD source code via CVS.
|
||||
# Please see:
|
||||
# http://www.freebsd.org/doc/handbook/svn.html
|
||||
# http://www.freebsd.org/doc/handbook/svn-mirrors.html
|
||||
#
|
||||
# csup (CVS Update Protocol) allows you to download the latest CVS
|
||||
# tree (or any branch of development therefrom) to your system easily
|
||||
@ -80,33 +87,3 @@
|
||||
# mega-collection. It includes all of the individual "src-*" collections.
|
||||
# Please note: If you want to track -STABLE, leave this uncommented.
|
||||
src-all
|
||||
|
||||
# These are the individual collections that make up "src-all". If you
|
||||
# use these, be sure to comment out "src-all" above.
|
||||
#src-base
|
||||
#src-bin
|
||||
#src-cddl
|
||||
#src-contrib
|
||||
#src-etc
|
||||
#src-games
|
||||
#src-gnu
|
||||
#src-include
|
||||
#src-kerberos5
|
||||
#src-kerberosIV
|
||||
#src-lib
|
||||
#src-libexec
|
||||
#src-release
|
||||
#src-rescue
|
||||
#src-sbin
|
||||
#src-share
|
||||
#src-sys
|
||||
#src-tools
|
||||
#src-usrbin
|
||||
#src-usrsbin
|
||||
# These are the individual collections that make up FreeBSD's crypto
|
||||
# collection. They are no longer export-restricted and are a part of
|
||||
# src-all
|
||||
#src-crypto
|
||||
#src-eBones
|
||||
#src-secure
|
||||
#src-sys-crypto
|
||||
|
@ -1,7 +1,14 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# This file contains all of the "CVSup collections" that make up the
|
||||
# FreeBSD-current source tree.
|
||||
# BEWARE, CVS is deprecated and no longer supported by the FreeBSD project.
|
||||
#
|
||||
# The primary development work happens in Subversion and is temporarily
|
||||
# exported to the legacy CVS system with significant time delays.
|
||||
#
|
||||
# You should NOT set up a new consumer of FreeBSD source code via CVS.
|
||||
# Please see:
|
||||
# http://www.freebsd.org/doc/handbook/svn.html
|
||||
# http://www.freebsd.org/doc/handbook/svn-mirrors.html
|
||||
#
|
||||
# csup (CVS Update Protocol) allows you to download the latest CVS
|
||||
# tree (or any branch of development therefrom) to your system easily
|
||||
@ -59,33 +66,3 @@
|
||||
# The easiest way to get the main source tree is to use the "src-all"
|
||||
# mega-collection. It includes all of the individual "src-*" collections.
|
||||
src-all
|
||||
|
||||
# These are the individual collections that make up "src-all". If you
|
||||
# use these, be sure to comment out "src-all" above.
|
||||
#src-base
|
||||
#src-bin
|
||||
#src-cddl
|
||||
#src-contrib
|
||||
#src-etc
|
||||
#src-games
|
||||
#src-gnu
|
||||
#src-include
|
||||
#src-kerberos5
|
||||
#src-kerberosIV
|
||||
#src-lib
|
||||
#src-libexec
|
||||
#src-release
|
||||
#src-rescue
|
||||
#src-sbin
|
||||
#src-share
|
||||
#src-sys
|
||||
#src-tools
|
||||
#src-usrbin
|
||||
#src-usrsbin
|
||||
# These are the individual collections that make up FreeBSD's crypto
|
||||
# collection. They are no longer export-restricted and are a part of
|
||||
# src-all
|
||||
#src-crypto
|
||||
#src-eBones
|
||||
#src-secure
|
||||
#src-sys-crypto
|
||||
|
@ -34,7 +34,7 @@
|
||||
.\" $Id: //depot/SpectraBSD/head/share/man/man4/mps.4#6 $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 30, 2012
|
||||
.Dd January 3, 2013
|
||||
.Dt MPS 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -62,7 +62,7 @@ controllers and WarpDrive solid state storage cards.
|
||||
.Sh HARDWARE
|
||||
The
|
||||
.Nm
|
||||
driver supports the following controllers:
|
||||
driver supports the following hardware:
|
||||
.Pp
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
@ -80,6 +80,19 @@ LSI Logic SAS2116 (16 Port
|
||||
.It
|
||||
LSI Logic SAS2208 (8 Port
|
||||
.Tn SAS )
|
||||
.It
|
||||
LSI Logic SAS2308 (8 Port
|
||||
.Tn SAS )
|
||||
.It
|
||||
LSI Logic SSS6200 Solid State Storage
|
||||
.It
|
||||
Intel Integrated RAID Module RMS25JB040
|
||||
.It
|
||||
Intel Integrated RAID Module RMS25JB080
|
||||
.It
|
||||
Intel Integrated RAID Module RMS25KB040
|
||||
.It
|
||||
Intel Integrated RAID Module RMS25KB080
|
||||
.El
|
||||
.Sh CONFIGURATION
|
||||
To disable MSI interrupts for all
|
||||
|
@ -102,12 +102,11 @@ If
|
||||
.Fa priority
|
||||
includes the
|
||||
.Dv PCATCH
|
||||
flag, pending
|
||||
signals are checked before and after sleeping, otherwise signals are
|
||||
not checked.
|
||||
flag, pending signals are allowed to interrupt the sleep, otherwise
|
||||
pending signals are ignored during the sleep.
|
||||
If
|
||||
.Dv PCATCH
|
||||
is set and a signal needs to be delivered,
|
||||
is set and a signal becomes pending,
|
||||
.Er ERESTART
|
||||
is returned if the current system call should be restarted if
|
||||
possible, and
|
||||
@ -119,9 +118,10 @@ If the
|
||||
.Dv PBDRY
|
||||
flag is specified in addition to
|
||||
.Dv PCATCH ,
|
||||
then the sleeping thread is not stopped upon delivery of
|
||||
then the sleeping thread is not stopped when
|
||||
.Dv SIGSTOP
|
||||
or other stop action while it is sleeping.
|
||||
becomes pending
|
||||
or some other stop action occurs while it is sleeping.
|
||||
Instead, it is woken up, with the assumption
|
||||
that the stop will occur on reaching a stop
|
||||
point when returning to usermode.
|
||||
|
@ -140,6 +140,7 @@ maho [label="Maho Nakata\nmaho@FreeBSD.org\n2002/10/17"]
|
||||
makc [label="Max Brazhnikov\nmakc@FreeBSD.org\n2008/08/25"]
|
||||
mandree [label="Matthias Andree\nmandree@FreeBSD.org\n2009/11/18"]
|
||||
marcus [label="Joe Marcus Clarke\nmarcus@FreeBSD.org\n2002/04/05"]
|
||||
marius [label="Marius Strobl\nmarius@FreeBSD.org\n2012/12/29"]
|
||||
markus [label="Markus Brueffer\nmarkus@FreeBSD.org\n2004/02/21"]
|
||||
martymac [label="Ganael Laplanche\nmartymac@FreeBSD.org\n2010/09/24"]
|
||||
mat [label="Mathieu Arnold\nmat@FreeBSD.org\n2003/08/15"]
|
||||
@ -235,8 +236,10 @@ avilla -> rakuco
|
||||
bapt -> bdrewery
|
||||
bapt -> eadler
|
||||
bapt -> jlaffaye
|
||||
bapt -> marius
|
||||
|
||||
beat -> decke
|
||||
beat -> marius
|
||||
beat -> sperber
|
||||
beat -> uqs
|
||||
|
||||
|
@ -97,13 +97,13 @@ _CPUCFLAGS = -march=${CPUTYPE}
|
||||
. if ${CPUTYPE} == "xscale"
|
||||
#XXX: gcc doesn't seem to like -mcpu=xscale, and dies while rebuilding itself
|
||||
#_CPUCFLAGS = -mcpu=xscale
|
||||
_CPUCFLAGS = -march=armv5te -D__XSCALE__ -DARM_WANT_TP_ADDRESS
|
||||
_CPUCFLAGS = -march=armv5te -D__XSCALE__
|
||||
. elif ${CPUTYPE} == "armv6"
|
||||
_CPUCFLAGS = -march=${CPUTYPE} -DARM_ARCH_6=1
|
||||
. elif ${CPUTYPE} == "cortexa"
|
||||
_CPUCFLAGS = -march=armv6 -DARM_ARCH_6=1 -mfpu=vfp
|
||||
_CPUCFLAGS = -DARM_ARCH_6=1 -mfpu=vfp
|
||||
. else
|
||||
_CPUCFLAGS = -mcpu=${CPUTYPE} -DARM_WANT_TP_ADDRESS
|
||||
_CPUCFLAGS = -mcpu=${CPUTYPE}
|
||||
. endif
|
||||
. elif ${MACHINE_ARCH} == "powerpc"
|
||||
. if ${CPUTYPE} == "e500"
|
||||
|
@ -35,6 +35,7 @@ options SOFTUPDATES # Enable FFS soft updates support
|
||||
options UFS_ACL # Support for access control lists
|
||||
options UFS_DIRHASH # Improve performance on big directories
|
||||
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
|
||||
options QUOTA # Enable disk quotas for UFS
|
||||
options MD_ROOT # MD is a potential root device
|
||||
options NFSCL # New Network Filesystem Client
|
||||
options NFSD # New Network Filesystem Server
|
||||
@ -317,15 +318,6 @@ device usb # USB Bus (required)
|
||||
device ukbd # Keyboard
|
||||
device umass # Disks/Mass storage - Requires scbus and da
|
||||
|
||||
# FireWire support
|
||||
device firewire # FireWire bus code
|
||||
# sbp(4) works for some systems but causes boot failure on others
|
||||
#device sbp # SCSI over FireWire (Requires scbus and da)
|
||||
device fwe # Ethernet over FireWire (non-standard!)
|
||||
device fwip # IP over FireWire (RFC 2734,3146)
|
||||
device dcons # Dumb console driver
|
||||
device dcons_crom # Configuration ROM for dcons
|
||||
|
||||
# Sound support
|
||||
device sound # Generic sound driver (required)
|
||||
device snd_cmi # CMedia CMI8338/CMI8738
|
||||
|
@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/uio.h>
|
||||
@ -162,8 +163,6 @@ const struct pmap_devmap *pmap_devmap_bootstrap_table;
|
||||
|
||||
uint32_t board_id;
|
||||
struct arm_lbabi_tag *atag_list;
|
||||
uint32_t revision;
|
||||
uint64_t serial;
|
||||
char linux_command_line[LBABI_MAX_COMMAND_LINE + 1];
|
||||
char atags[LBABI_MAX_COMMAND_LINE * 2];
|
||||
uint32_t memstart[LBABI_MAX_BANKS];
|
||||
@ -171,6 +170,31 @@ uint32_t memsize[LBABI_MAX_BANKS];
|
||||
uint32_t membanks;
|
||||
#endif
|
||||
|
||||
static uint32_t board_revision;
|
||||
/* hex representation of uint64_t */
|
||||
static char board_serial[32];
|
||||
|
||||
SYSCTL_NODE(_hw, OID_AUTO, board, CTLFLAG_RD, 0, "Board attributes");
|
||||
SYSCTL_UINT(_hw_board, OID_AUTO, revision, CTLFLAG_RD,
|
||||
&board_revision, 0, "Board revision");
|
||||
SYSCTL_STRING(_hw_board, OID_AUTO, serial, CTLFLAG_RD,
|
||||
board_serial, 0, "Board serial");
|
||||
|
||||
void
|
||||
board_set_serial(uint64_t serial)
|
||||
{
|
||||
|
||||
snprintf(board_serial, sizeof(board_serial)-1,
|
||||
"%016jx", serial);
|
||||
}
|
||||
|
||||
void
|
||||
board_set_revision(uint32_t revision)
|
||||
{
|
||||
|
||||
board_revision = revision;
|
||||
}
|
||||
|
||||
void
|
||||
sendsig(catcher, ksi, mask)
|
||||
sig_t catcher;
|
||||
@ -849,6 +873,8 @@ vm_offset_t
|
||||
linux_parse_boot_param(struct arm_boot_params *abp)
|
||||
{
|
||||
struct arm_lbabi_tag *walker;
|
||||
uint32_t revision;
|
||||
uint64_t serial;
|
||||
|
||||
/*
|
||||
* Linux boot ABI: r0 = 0, r1 is the board type (!= 0) and r2
|
||||
@ -883,9 +909,11 @@ linux_parse_boot_param(struct arm_boot_params *abp)
|
||||
case ATAG_SERIAL:
|
||||
serial = walker->u.tag_sn.low |
|
||||
((uint64_t)walker->u.tag_sn.high << 32);
|
||||
board_set_serial(serial);
|
||||
break;
|
||||
case ATAG_REVISION:
|
||||
revision = walker->u.tag_rev.rev;
|
||||
board_set_revision(revision);
|
||||
break;
|
||||
case ATAG_CMDLINE:
|
||||
/* XXX open question: Parse this for boothowto? */
|
||||
|
@ -135,11 +135,12 @@ pl310_cache_sync(void)
|
||||
return;
|
||||
|
||||
#ifdef PL310_ERRATA_753970
|
||||
/* Write uncached PL310 register */
|
||||
pl310_write4(pl310_softc, 0x740, 0xffffffff);
|
||||
#else
|
||||
pl310_write4(pl310_softc, PL310_CACHE_SYNC, 0xffffffff);
|
||||
if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
|
||||
/* Write uncached PL310 register */
|
||||
pl310_write4(pl310_softc, 0x740, 0xffffffff);
|
||||
else
|
||||
#endif
|
||||
pl310_write4(pl310_softc, PL310_CACHE_SYNC, 0xffffffff);
|
||||
}
|
||||
|
||||
|
||||
@ -152,13 +153,17 @@ pl310_wbinv_all(void)
|
||||
|
||||
PL310_LOCK(pl310_softc);
|
||||
#ifdef PL310_ERRATA_727915
|
||||
platform_pl310_write_debug(pl310_softc, 3);
|
||||
if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r2p0 ||
|
||||
pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
|
||||
platform_pl310_write_debug(pl310_softc, 3);
|
||||
#endif
|
||||
pl310_write4(pl310_softc, PL310_CLEAN_INV_WAY, g_l2cache_way_mask);
|
||||
pl310_wait_background_op(PL310_CLEAN_INV_WAY, g_l2cache_way_mask);
|
||||
pl310_cache_sync();
|
||||
#ifdef PL310_ERRATA_727915
|
||||
platform_pl310_write_debug(pl310_softc, 0);
|
||||
if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r2p0 ||
|
||||
pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
|
||||
platform_pl310_write_debug(pl310_softc, 0);
|
||||
#endif
|
||||
PL310_UNLOCK(pl310_softc);
|
||||
}
|
||||
@ -186,18 +191,19 @@ pl310_wbinv_range(vm_paddr_t start, vm_size_t size)
|
||||
#endif
|
||||
while (size > 0) {
|
||||
#ifdef PL310_ERRATA_588369
|
||||
/*
|
||||
* Errata 588369 says that clean + inv may keep the
|
||||
* cache line if it was clean, the recommanded workaround
|
||||
* is to clean then invalidate the cache line, with
|
||||
* write-back and cache linefill disabled
|
||||
*/
|
||||
|
||||
pl310_write4(pl310_softc, PL310_CLEAN_LINE_PA, start);
|
||||
pl310_write4(pl310_softc, PL310_INV_LINE_PA, start);
|
||||
#else
|
||||
pl310_write4(pl310_softc, PL310_CLEAN_INV_LINE_PA, start);
|
||||
if (pl310_softc->sc_rtl_revision <= CACHE_ID_RELEASE_r1p0) {
|
||||
/*
|
||||
* Errata 588369 says that clean + inv may keep the
|
||||
* cache line if it was clean, the recommanded
|
||||
* workaround is to clean then invalidate the cache
|
||||
* line, with write-back and cache linefill disabled.
|
||||
*/
|
||||
pl310_write4(pl310_softc, PL310_CLEAN_LINE_PA, start);
|
||||
pl310_write4(pl310_softc, PL310_INV_LINE_PA, start);
|
||||
} else
|
||||
#endif
|
||||
pl310_write4(pl310_softc, PL310_CLEAN_INV_LINE_PA,
|
||||
start);
|
||||
start += g_l2cache_line_size;
|
||||
size -= g_l2cache_line_size;
|
||||
}
|
||||
@ -307,6 +313,8 @@ pl310_attach(device_t dev)
|
||||
pl310_filter, NULL, sc, &sc->sc_irq_h);
|
||||
|
||||
cache_id = pl310_read4(sc, PL310_CACHE_ID);
|
||||
sc->sc_rtl_revision = (cache_id >> CACHE_ID_RELEASE_SHIFT) &
|
||||
CACHE_ID_RELEASE_MASK;
|
||||
device_printf(dev, "Part number: 0x%x, release: 0x%x\n",
|
||||
(cache_id >> CACHE_ID_PARTNUM_SHIFT) & CACHE_ID_PARTNUM_MASK,
|
||||
(cache_id >> CACHE_ID_RELEASE_SHIFT) & CACHE_ID_RELEASE_MASK);
|
||||
|
@ -193,6 +193,14 @@ int pmap_debug_level = 0;
|
||||
#define PMAP_INLINE __inline
|
||||
#endif /* PMAP_DEBUG */
|
||||
|
||||
#ifdef ARM_L2_PIPT
|
||||
#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((pa), (size))
|
||||
#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((pa), (size))
|
||||
#else
|
||||
#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((va), (size))
|
||||
#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((va), (size))
|
||||
#endif
|
||||
|
||||
extern struct pv_addr systempage;
|
||||
|
||||
/*
|
||||
@ -786,11 +794,7 @@ pmap_l2ptp_ctor(void *mem, int size, void *arg, int flags)
|
||||
pte = *ptep;
|
||||
|
||||
cpu_idcache_wbinv_range(va, PAGE_SIZE);
|
||||
#ifdef ARM_L2_PIPT
|
||||
cpu_l2cache_wbinv_range(pte & L2_S_FRAME, PAGE_SIZE);
|
||||
#else
|
||||
cpu_l2cache_wbinv_range(va, PAGE_SIZE);
|
||||
#endif
|
||||
pmap_l2cache_wbinv_range(va, pte & L2_S_FRAME, PAGE_SIZE);
|
||||
if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
|
||||
/*
|
||||
* Page tables must have the cache-mode set to
|
||||
@ -2121,6 +2125,7 @@ pmap_kremove(vm_offset_t va)
|
||||
cpu_tlb_flushD_SE(va);
|
||||
cpu_cpwait();
|
||||
*pte = 0;
|
||||
PTE_SYNC(pte);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2387,11 +2392,7 @@ pmap_change_attr(vm_offset_t sva, vm_size_t len, int mode)
|
||||
|
||||
pte = *ptep &~ L2_S_CACHE_MASK;
|
||||
cpu_idcache_wbinv_range(tmpva, PAGE_SIZE);
|
||||
#ifdef ARM_L2_PIPT
|
||||
cpu_l2cache_wbinv_range(pte & L2_S_FRAME, PAGE_SIZE);
|
||||
#else
|
||||
cpu_l2cache_wbinv_range(tmpva, PAGE_SIZE);
|
||||
#endif
|
||||
pmap_l2cache_wbinv_range(tmpva, pte & L2_S_FRAME, PAGE_SIZE);
|
||||
*ptep = pte;
|
||||
cpu_tlb_flushID_SE(tmpva);
|
||||
|
||||
@ -2754,6 +2755,9 @@ do_l2b_alloc:
|
||||
else if (PV_BEEN_REFD(oflags))
|
||||
cpu_tlb_flushD_SE(va);
|
||||
}
|
||||
|
||||
if ((pmap != pmap_kernel()) && (pmap == &curproc->p_vmspace->vm_pmap))
|
||||
cpu_icache_sync_range(va, PAGE_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3197,6 +3201,16 @@ pmap_zero_page_gen(vm_page_t pg, int off, int size)
|
||||
else
|
||||
bzero_page(cdstp);
|
||||
|
||||
/*
|
||||
* Although aliasing is not possible if we use
|
||||
* cdstp temporary mappings with memory that
|
||||
* will be mapped later as non-cached or with write-through
|
||||
* caches we might end up overwriting it when calling wbinv_all
|
||||
* So make sure caches are clean after copy operation
|
||||
*/
|
||||
cpu_idcache_wbinv_range(cdstp, size);
|
||||
pmap_l2cache_wbinv_range(cdstp, phys, size);
|
||||
|
||||
mtx_unlock(&cmtx);
|
||||
}
|
||||
|
||||
@ -3276,12 +3290,23 @@ pmap_copy_page_generic(vm_paddr_t src, vm_paddr_t dst)
|
||||
*cdst_pte = L2_S_PROTO | dst | pte_l2_s_cache_mode;
|
||||
pmap_set_prot(cdst_pte, VM_PROT_READ | VM_PROT_WRITE, 0);
|
||||
PTE_SYNC(cdst_pte);
|
||||
|
||||
cpu_tlb_flushD_SE(csrcp);
|
||||
cpu_tlb_flushD_SE(cdstp);
|
||||
cpu_cpwait();
|
||||
|
||||
/*
|
||||
* Although aliasing is not possible if we use
|
||||
* cdstp temporary mappings with memory that
|
||||
* will be mapped later as non-cached or with write-through
|
||||
* caches we might end up overwriting it when calling wbinv_all
|
||||
* So make sure caches are clean after copy operation
|
||||
*/
|
||||
bcopy_page(csrcp, cdstp);
|
||||
|
||||
cpu_idcache_wbinv_range(cdstp, PAGE_SIZE);
|
||||
pmap_l2cache_wbinv_range(cdstp, dst, PAGE_SIZE);
|
||||
|
||||
mtx_unlock(&cmtx);
|
||||
}
|
||||
|
||||
|
@ -891,7 +891,7 @@ bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
|
||||
+ (sc->depth/8) * (col + sc->xmargin);
|
||||
|
||||
fg = a & 0xf ;
|
||||
bg = (a >> 8) & 0xf;
|
||||
bg = (a >> 4) & 0xf;
|
||||
|
||||
for (i = 0; i < BCMFB_FONT_HEIGHT; i++) {
|
||||
for (j = 0, k = 7; j < 8; j++, k--) {
|
||||
|
@ -78,6 +78,25 @@ initarm_gpio_init(void)
|
||||
void
|
||||
initarm_late_init(void)
|
||||
{
|
||||
phandle_t system;
|
||||
pcell_t cells[2];
|
||||
int len;
|
||||
|
||||
/*
|
||||
* It seems there is no way to let syscons framework know
|
||||
* that framebuffer resolution has changed. So just try
|
||||
* to fetch data from FDT and go with defaults if failed
|
||||
*/
|
||||
system = OF_finddevice("/system");
|
||||
if (system != 0) {
|
||||
len = OF_getprop(system, "linux,serial", &cells, sizeof(cells));
|
||||
if (len > 0)
|
||||
board_set_serial(fdt64_to_cpu(*((uint64_t *)cells)));
|
||||
|
||||
len = OF_getprop(system, "linux,revision", &cells, sizeof(cells));
|
||||
if (len > 0)
|
||||
board_set_revision(fdt32_to_cpu(*((uint32_t *)cells)));
|
||||
}
|
||||
}
|
||||
|
||||
#define FDT_DEVMAP_MAX (2) // FIXME
|
||||
|
@ -62,11 +62,11 @@ options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
|
||||
|
||||
# NFS support
|
||||
#options NFSCL
|
||||
#options NFSSERVER #Network Filesystem Server
|
||||
#options NFSCLIENT #Network Filesystem Client
|
||||
#options NFSD
|
||||
#options NFSLOCKD
|
||||
|
||||
# Uncomment this for NFS root
|
||||
#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
|
||||
#options NFS_ROOT #NFS usable as /, requires NFSCL
|
||||
#options BOOTP_NFSROOT
|
||||
#options BOOTP_COMPAT
|
||||
#options BOOTP
|
||||
|
@ -47,9 +47,25 @@
|
||||
#include <machine/cpuconf.h>
|
||||
#endif
|
||||
|
||||
#define mb()
|
||||
#define wmb()
|
||||
#define rmb()
|
||||
#if defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
|
||||
#define isb() __asm __volatile("isb" : : : "memory")
|
||||
#define dsb() __asm __volatile("dsb" : : : "memory")
|
||||
#define dmb() __asm __volatile("dmb" : : : "memory")
|
||||
#elif defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) || \
|
||||
defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6Z__) || \
|
||||
defined (__ARM_ARCH_6ZK__)
|
||||
#define isb() __asm __volatile("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory")
|
||||
#define dsb() __asm __volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory")
|
||||
#define dmb() __asm __volatile("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory")
|
||||
#else
|
||||
#define isb()
|
||||
#define dsb()
|
||||
#define dmb()
|
||||
#endif
|
||||
|
||||
#define mb() dmb()
|
||||
#define wmb() dmb()
|
||||
#define rmb() dmb()
|
||||
|
||||
#ifndef I32_bit
|
||||
#define I32_bit (1 << 7) /* IRQ disable */
|
||||
|
@ -37,6 +37,10 @@ void initarm_gpio_init(void);
|
||||
void initarm_late_init(void);
|
||||
int platform_devmap_init(void);
|
||||
|
||||
/* Board-specific attributes */
|
||||
void board_set_serial(uint64_t);
|
||||
void board_set_revision(uint32_t);
|
||||
|
||||
/* Needs to be initialised by platform_devmap_init */
|
||||
extern const struct pmap_devmap *pmap_devmap_bootstrap_table;
|
||||
|
||||
|
@ -131,6 +131,7 @@ struct pl310_softc {
|
||||
void* sc_irq_h;
|
||||
int sc_enabled;
|
||||
struct mtx sc_mtx;
|
||||
u_int sc_rtl_revision;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -61,7 +61,7 @@
|
||||
#else
|
||||
#define PTE_NOCACHE 1
|
||||
#endif
|
||||
#define PTE_CACHE 4
|
||||
#define PTE_CACHE 6
|
||||
#define PTE_DEVICE 2
|
||||
#define PTE_PAGETABLE 4
|
||||
#else
|
||||
|
@ -98,7 +98,7 @@ static int cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data);
|
||||
static int cpsw_init_slot_lists(struct cpsw_softc *sc);
|
||||
static void cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot);
|
||||
static void cpsw_fill_rx_queue_locked(struct cpsw_softc *sc);
|
||||
static void cpsw_watchdog(struct cpsw_softc *sc);
|
||||
static void cpsw_tx_watchdog(struct cpsw_softc *sc);
|
||||
|
||||
static void cpsw_intr_rx_thresh(void *arg);
|
||||
static void cpsw_intr_rx(void *arg);
|
||||
@ -716,34 +716,24 @@ cpsw_start_locked(struct ifnet *ifp)
|
||||
if (STAILQ_EMPTY(&newslots))
|
||||
return;
|
||||
|
||||
/* Attach new segments to the hardware TX queue. */
|
||||
/* Attach the list of new buffers to the hardware TX queue. */
|
||||
prev_slot = STAILQ_LAST(&sc->tx_active, cpsw_slot, next);
|
||||
first_new_slot = STAILQ_FIRST(&newslots);
|
||||
STAILQ_CONCAT(&sc->tx_active, &newslots);
|
||||
if (prev_slot == NULL) {
|
||||
/* Start the TX queue fresh. */
|
||||
cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
|
||||
cpsw_cpdma_txbd_paddr(first_new_slot->index));
|
||||
cpsw_cpdma_txbd_paddr(first_new_slot->index));
|
||||
} else {
|
||||
/* Add packets to current queue. */
|
||||
/* Race: The hardware might have sent the last packet
|
||||
* on the queue and stopped the transmitter just
|
||||
* before we got here. In that case, this is a no-op,
|
||||
* but it also means there's a TX interrupt waiting
|
||||
* to be processed as soon as we release the lock here.
|
||||
* That TX interrupt can detect and recover from this
|
||||
* situation; see cpsw_intr_tx_locked.
|
||||
*/
|
||||
/* Add buffers to end of current queue. */
|
||||
cpsw_cpdma_write_txbd_next(prev_slot->index,
|
||||
cpsw_cpdma_txbd_paddr(first_new_slot->index));
|
||||
/* If underrun, restart queue. */
|
||||
if (cpsw_cpdma_read_txbd_flags(prev_slot->index) & CPDMA_BD_EOQ)
|
||||
cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
|
||||
cpsw_cpdma_txbd_paddr(first_new_slot->index));
|
||||
}
|
||||
/* If tx_retires hasn't changed, then we may have
|
||||
lost a TX interrupt, so let the timer tick. */
|
||||
sc->tx_enqueues += enqueued;
|
||||
if (sc->tx_retires_at_wd_reset != sc->tx_retires) {
|
||||
sc->tx_retires_at_wd_reset = sc->tx_retires;
|
||||
sc->wd_timer = 5;
|
||||
}
|
||||
sc->tx_queued += enqueued;
|
||||
if (sc->tx_queued > sc->tx_max_queued) {
|
||||
sc->tx_max_queued = sc->tx_queued;
|
||||
@ -771,7 +761,6 @@ cpsw_stop_locked(struct cpsw_softc *sc)
|
||||
|
||||
/* Stop tick engine */
|
||||
callout_stop(&sc->wd_callout);
|
||||
sc->wd_timer = 0;
|
||||
|
||||
/* Wait for hardware to clear pending ops. */
|
||||
CPSW_GLOBAL_UNLOCK(sc);
|
||||
@ -1098,14 +1087,10 @@ cpsw_fill_rx_queue_locked(struct cpsw_softc *sc)
|
||||
cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
|
||||
cpsw_cpdma_rxbd_paddr(next_slot->index));
|
||||
} else {
|
||||
/* Extend an existing RX queue. */
|
||||
/* Add buffers to end of current queue. */
|
||||
cpsw_cpdma_write_rxbd_next(prev_slot->index,
|
||||
cpsw_cpdma_rxbd_paddr(next_slot->index));
|
||||
/* XXX Order matters: Previous write must complete
|
||||
before next read begins in order to avoid an
|
||||
end-of-queue race. I think bus_write and bus_read have
|
||||
sufficient barriers built-in to ensure this. XXX */
|
||||
/* If old RX queue was stopped, restart it. */
|
||||
/* If underrun, restart queue. */
|
||||
if (cpsw_cpdma_read_rxbd_flags(prev_slot->index) & CPDMA_BD_EOQ) {
|
||||
cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
|
||||
cpsw_cpdma_rxbd_paddr(next_slot->index));
|
||||
@ -1177,15 +1162,8 @@ cpsw_intr_tx_locked(void *arg)
|
||||
/* Tell hardware the last item we dequeued. */
|
||||
cpsw_write_4(CPSW_CPDMA_TX_CP(0),
|
||||
cpsw_cpdma_txbd_paddr(last_slot->index));
|
||||
/* If transmitter stopped and there's more, restart it. */
|
||||
/* This resolves the race described in tx_start above. */
|
||||
if ((last_flags & CPDMA_BD_EOQ) && (slot != NULL)) {
|
||||
cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
|
||||
cpsw_cpdma_txbd_paddr(slot->index));
|
||||
}
|
||||
sc->tx_retires += retires;
|
||||
sc->tx_queued -= retires;
|
||||
sc->wd_timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1206,7 +1184,7 @@ cpsw_tick(void *msc)
|
||||
struct cpsw_softc *sc = msc;
|
||||
|
||||
/* Check for TX timeout */
|
||||
cpsw_watchdog(sc);
|
||||
cpsw_tx_watchdog(sc);
|
||||
|
||||
mii_tick(sc->mii);
|
||||
|
||||
@ -1222,21 +1200,28 @@ cpsw_tick(void *msc)
|
||||
}
|
||||
|
||||
static void
|
||||
cpsw_watchdog(struct cpsw_softc *sc)
|
||||
cpsw_tx_watchdog(struct cpsw_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
struct ifnet *ifp = sc->ifp;
|
||||
|
||||
ifp = sc->ifp;
|
||||
CPSW_GLOBAL_LOCK(sc);
|
||||
if (sc->wd_timer == 0 || --sc->wd_timer) {
|
||||
CPSW_GLOBAL_UNLOCK(sc);
|
||||
return;
|
||||
if (sc->tx_retires > sc->tx_retires_at_last_tick) {
|
||||
sc->tx_wd_timer = 0; /* Stuff got sent. */
|
||||
} else if (sc->tx_queued == 0) {
|
||||
sc->tx_wd_timer = 0; /* Nothing to send. */
|
||||
} else {
|
||||
/* There was something to send but we didn't. */
|
||||
++sc->tx_wd_timer;
|
||||
if (sc->tx_wd_timer > 3) {
|
||||
sc->tx_wd_timer = 0;
|
||||
ifp->if_oerrors++;
|
||||
if_printf(ifp, "watchdog timeout\n");
|
||||
cpsw_stop_locked(sc);
|
||||
cpsw_init_locked(sc);
|
||||
CPSW_DEBUGF(("watchdog reset completed\n"));
|
||||
}
|
||||
}
|
||||
|
||||
ifp->if_oerrors++;
|
||||
if_printf(ifp, "watchdog timeout\n");
|
||||
cpsw_stop_locked(sc);
|
||||
cpsw_init_locked(sc);
|
||||
sc->tx_retires_at_last_tick = sc->tx_retires;
|
||||
CPSW_GLOBAL_UNLOCK(sc);
|
||||
}
|
||||
|
||||
@ -1381,7 +1366,7 @@ cpsw_init_locked(void *arg)
|
||||
/* Activate network interface */
|
||||
sc->rx_running = 1;
|
||||
sc->tx_running = 1;
|
||||
sc->wd_timer = 0;
|
||||
sc->tx_wd_timer = 0;
|
||||
callout_reset(&sc->wd_callout, hz, cpsw_tick, sc);
|
||||
sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
@ -63,7 +63,7 @@ struct cpsw_softc {
|
||||
int cpsw_media_status;
|
||||
|
||||
struct callout wd_callout;
|
||||
int wd_timer;
|
||||
int tx_wd_timer;
|
||||
|
||||
bus_dma_tag_t mbuf_dtag;
|
||||
|
||||
@ -82,7 +82,7 @@ struct cpsw_softc {
|
||||
/* Statistics */
|
||||
uint32_t tx_enqueues; /* total TX bufs added to queue */
|
||||
uint32_t tx_retires; /* total TX bufs removed from queue */
|
||||
uint32_t tx_retires_at_wd_reset; /* used for watchdog */
|
||||
uint32_t tx_retires_at_last_tick; /* used for watchdog */
|
||||
/* Note: tx_queued != tx_enqueues - tx_retires
|
||||
At driver reset, packets can be discarded
|
||||
from TX queue without being retired. */
|
||||
|
@ -129,27 +129,75 @@ omap4_get_revision(void)
|
||||
|
||||
switch (hawkeye) {
|
||||
case 0xB852:
|
||||
if (revision == 0)
|
||||
switch (revision) {
|
||||
case 0:
|
||||
chip_revision = OMAP4430_REV_ES1_0;
|
||||
else
|
||||
chip_revision = OMAP4430_REV_ES2_0;
|
||||
break;
|
||||
case 0xB95C:
|
||||
if (revision == 3)
|
||||
break;
|
||||
case 1:
|
||||
chip_revision = OMAP4430_REV_ES2_1;
|
||||
else if (revision == 4)
|
||||
chip_revision = OMAP4430_REV_ES2_2;
|
||||
else
|
||||
chip_revision = OMAP4430_REV_ES2_3;
|
||||
break;
|
||||
default:
|
||||
chip_revision = OMAP4430_REV_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB95C:
|
||||
switch (revision) {
|
||||
case 3:
|
||||
chip_revision = OMAP4430_REV_ES2_1;
|
||||
break;
|
||||
case 4:
|
||||
chip_revision = OMAP4430_REV_ES2_2;
|
||||
break;
|
||||
case 6:
|
||||
chip_revision = OMAP4430_REV_ES2_3;
|
||||
break;
|
||||
default:
|
||||
chip_revision = OMAP4430_REV_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB94E:
|
||||
switch (revision) {
|
||||
case 0:
|
||||
chip_revision = OMAP4460_REV_ES1_0;
|
||||
break;
|
||||
case 2:
|
||||
chip_revision = OMAP4460_REV_ES1_1;
|
||||
break;
|
||||
default:
|
||||
chip_revision = OMAP4460_REV_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB975:
|
||||
switch (revision) {
|
||||
case 0:
|
||||
chip_revision = OMAP4470_REV_ES1_0;
|
||||
break;
|
||||
default:
|
||||
chip_revision = OMAP4470_REV_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Default to the latest revision if we can't determine type */
|
||||
chip_revision = OMAP4430_REV_ES2_3;
|
||||
chip_revision = OMAP_UNKNOWN_DEV;
|
||||
break;
|
||||
}
|
||||
printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n",
|
||||
OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision),
|
||||
OMAP_REV_MINOR(chip_revision));
|
||||
if (chip_revision != OMAP_UNKNOWN_DEV) {
|
||||
printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n",
|
||||
OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision),
|
||||
OMAP_REV_MINOR(chip_revision));
|
||||
}
|
||||
else {
|
||||
printf("Texas Instruments unknown OMAP chip: %04x, rev %d\n",
|
||||
hawkeye, revision);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,34 +30,46 @@
|
||||
#ifndef _TI_CPUID_H_
|
||||
#define _TI_CPUID_H_
|
||||
|
||||
#define OMAP_MAKEREV(d, a, b, c) \
|
||||
#define OMAP_MAKEREV(d, a, b, c) \
|
||||
(uint32_t)(((d) << 16) | (((a) & 0xf) << 8) | (((b) & 0xf) << 4) | ((c) & 0xf))
|
||||
|
||||
#define OMAP_REV_DEVICE(x) (((x) >> 16) & 0xffff)
|
||||
#define OMAP_REV_MAJOR(x) (((x) >> 8) & 0xf)
|
||||
#define OMAP_REV_MINOR(x) (((x) >> 4) & 0xf)
|
||||
#define OMAP_REV_MINOR_MINOR(x) (((x) >> 0) & 0xf)
|
||||
#define OMAP_REV_DEVICE(x) (((x) >> 16) & 0xffff)
|
||||
#define OMAP_REV_MAJOR(x) (((x) >> 8) & 0xf)
|
||||
#define OMAP_REV_MINOR(x) (((x) >> 4) & 0xf)
|
||||
#define OMAP_REV_MINOR_MINOR(x) (((x) >> 0) & 0xf)
|
||||
|
||||
#define OMAP3350_DEV 0x3530
|
||||
#define OMAP3350_REV_ES1_0 OMAP_MAKEREV(OMAP3350_DEV, 1, 0, 0)
|
||||
#define OMAP3530_REV_ES2_0 OMAP_MAKEREV(OMAP3350_DEV, 2, 0, 0)
|
||||
#define OMAP3530_REV_ES2_1 OMAP_MAKEREV(OMAP3350_DEV, 2, 1, 0)
|
||||
#define OMAP3530_REV_ES3_0 OMAP_MAKEREV(OMAP3350_DEV, 3, 0, 0)
|
||||
#define OMAP3530_REV_ES3_1 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 0)
|
||||
#define OMAP3530_REV_ES3_1_2 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 2)
|
||||
#define OMAP3350_REV_ES1_0 OMAP_MAKEREV(OMAP3350_DEV, 1, 0, 0)
|
||||
#define OMAP3530_REV_ES2_0 OMAP_MAKEREV(OMAP3350_DEV, 2, 0, 0)
|
||||
#define OMAP3530_REV_ES2_1 OMAP_MAKEREV(OMAP3350_DEV, 2, 1, 0)
|
||||
#define OMAP3530_REV_ES3_0 OMAP_MAKEREV(OMAP3350_DEV, 3, 0, 0)
|
||||
#define OMAP3530_REV_ES3_1 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 0)
|
||||
#define OMAP3530_REV_ES3_1_2 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 2)
|
||||
|
||||
#define OMAP4430_DEV 0x4430
|
||||
#define OMAP4430_REV_ES1_0 OMAP_MAKEREV(OMAP4430_DEV, 1, 0, 0)
|
||||
#define OMAP4430_REV_ES2_0 OMAP_MAKEREV(OMAP4430_DEV, 2, 0, 0)
|
||||
#define OMAP4430_REV_ES2_1 OMAP_MAKEREV(OMAP4430_DEV, 2, 1, 0)
|
||||
#define OMAP4430_REV_ES2_2 OMAP_MAKEREV(OMAP4430_DEV, 2, 2, 0)
|
||||
#define OMAP4430_REV_ES2_3 OMAP_MAKEREV(OMAP4430_DEV, 2, 3, 0)
|
||||
#define OMAP4430_REV_ES1_0 OMAP_MAKEREV(OMAP4430_DEV, 1, 0, 0)
|
||||
#define OMAP4430_REV_ES2_0 OMAP_MAKEREV(OMAP4430_DEV, 2, 0, 0)
|
||||
#define OMAP4430_REV_ES2_1 OMAP_MAKEREV(OMAP4430_DEV, 2, 1, 0)
|
||||
#define OMAP4430_REV_ES2_2 OMAP_MAKEREV(OMAP4430_DEV, 2, 2, 0)
|
||||
#define OMAP4430_REV_ES2_3 OMAP_MAKEREV(OMAP4430_DEV, 2, 3, 0)
|
||||
#define OMAP4430_REV_UNKNOWN OMAP_MAKEREV(OMAP4430_DEV, 9, 9, 9)
|
||||
|
||||
#define AM335X_DEVREV(x) ((x) >> 28)
|
||||
#define OMAP4460_DEV 0x4460
|
||||
#define OMAP4460_REV_ES1_0 OMAP_MAKEREV(OMAP4460_DEV, 1, 0, 0)
|
||||
#define OMAP4460_REV_ES1_1 OMAP_MAKEREV(OMAP4460_DEV, 1, 1, 0)
|
||||
#define OMAP4460_REV_UNKNOWN OMAP_MAKEREV(OMAP4460_DEV, 9, 9, 9)
|
||||
|
||||
#define CHIP_OMAP_3 0
|
||||
#define CHIP_OMAP_4 1
|
||||
#define CHIP_AM335X 2
|
||||
#define OMAP4470_DEV 0x4470
|
||||
#define OMAP4470_REV_ES1_0 OMAP_MAKEREV(OMAP4470_DEV, 1, 0, 0)
|
||||
#define OMAP4470_REV_UNKNOWN OMAP_MAKEREV(OMAP4470_DEV, 9, 9, 9)
|
||||
|
||||
#define OMAP_UNKNOWN_DEV OMAP_MAKEREV(0x9999, 9, 9, 9)
|
||||
|
||||
#define AM335X_DEVREV(x) ((x) >> 28)
|
||||
|
||||
#define CHIP_OMAP_3 0
|
||||
#define CHIP_OMAP_4 1
|
||||
#define CHIP_AM335X 2
|
||||
|
||||
static __inline int ti_chip(void)
|
||||
{
|
||||
|
@ -892,7 +892,7 @@ versatilefb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
|
||||
+ (sc->depth/8) * (col + sc->xmargin);
|
||||
|
||||
fg = a & 0xf ;
|
||||
bg = (a >> 8) & 0xf;
|
||||
bg = (a >> 4) & 0xf;
|
||||
|
||||
for (i = 0; i < VERSATILE_FONT_HEIGHT; i++) {
|
||||
for (j = 0, k = 7; j < 8; j++, k--) {
|
||||
|
@ -53,8 +53,8 @@ extern char bootprog_rev[];
|
||||
/*
|
||||
* FreeBSD loader default dictionary cells
|
||||
*/
|
||||
#ifndef BF_DICTSIZE
|
||||
#define BF_DICTSIZE 10000
|
||||
#ifndef BF_DICTSIZE
|
||||
#define BF_DICTSIZE 10000
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -247,6 +247,7 @@ bf_init(void)
|
||||
char create_buf[41]; /* 31 characters-long builtins */
|
||||
int fd;
|
||||
|
||||
|
||||
bf_sys = ficlInitSystem(BF_DICTSIZE);
|
||||
bf_vm = ficlNewVM(bf_sys);
|
||||
|
||||
|
@ -73,6 +73,7 @@ MAXMEM opt_global.h
|
||||
#
|
||||
OCTEON_MODEL opt_cvmx.h
|
||||
OCTEON_VENDOR_LANNER opt_cvmx.h
|
||||
OCTEON_VENDOR_UBIQUITI opt_cvmx.h
|
||||
OCTEON_VENDOR_RADISYS opt_cvmx.h
|
||||
OCTEON_BOARD_CAPK_0100ND opt_cvmx.h
|
||||
|
||||
|
@ -299,6 +299,9 @@ enum cvmx_board_types_enum {
|
||||
CVMX_BOARD_TYPE_CUST_LANNER_MR320= 20002,
|
||||
CVMX_BOARD_TYPE_CUST_LANNER_MR321X=20007,
|
||||
#endif
|
||||
#if defined(OCTEON_VENDOR_UBIQUITI)
|
||||
CVMX_BOARD_TYPE_CUST_UBIQUITI_E100=20002,
|
||||
#endif
|
||||
#if defined(OCTEON_VENDOR_RADISYS)
|
||||
CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE=20002,
|
||||
#endif
|
||||
@ -426,6 +429,9 @@ static inline const char *cvmx_board_type_to_string(enum cvmx_board_types_enum t
|
||||
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_LANNER_MR320)
|
||||
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_LANNER_MR321X)
|
||||
#endif
|
||||
#if defined(OCTEON_VENDOR_UBIQUITI)
|
||||
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_UBIQUITI_E100)
|
||||
#endif
|
||||
#if defined(OCTEON_VENDOR_RADISYS)
|
||||
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE)
|
||||
#endif
|
||||
|
@ -592,6 +592,12 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if defined(OCTEON_VENDOR_UBIQUITI)
|
||||
case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100:
|
||||
if (ipd_port > 2)
|
||||
return -1;
|
||||
return (7 - ipd_port);
|
||||
#endif
|
||||
#if defined(OCTEON_VENDOR_RADISYS)
|
||||
case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE:
|
||||
/* No MII. */
|
||||
@ -1463,6 +1469,9 @@ cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void)
|
||||
case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
|
||||
case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
|
||||
#endif
|
||||
#if defined(OCTEON_VENDOR_UBIQUITI)
|
||||
case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100:
|
||||
#endif
|
||||
#if defined(OCTEON_BOARD_CAPK_0100ND)
|
||||
case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
|
||||
#endif
|
||||
|
@ -423,7 +423,21 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
|
||||
sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags;
|
||||
#ifdef AH_SUPPORT_AR5416
|
||||
sc->sc_rx_th.wr_chan_flags &= ~CHAN_HT;
|
||||
if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
|
||||
if (rs->rs_status & HAL_RXERR_PHY) {
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
/*
|
||||
* PHY error - make sure the channel flags
|
||||
* reflect the actual channel configuration,
|
||||
* not the received frame.
|
||||
*/
|
||||
if (IEEE80211_IS_CHAN_HT40U(ic->ic_curchan))
|
||||
sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U;
|
||||
else if (IEEE80211_IS_CHAN_HT40D(ic->ic_curchan))
|
||||
sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D;
|
||||
else if (IEEE80211_IS_CHAN_HT20(ic->ic_curchan))
|
||||
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
|
||||
} else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
if ((rs->rs_flags & HAL_RX_2040) == 0)
|
||||
@ -435,6 +449,7 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
|
||||
if ((rs->rs_flags & HAL_RX_GI) == 0)
|
||||
sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
|
||||
}
|
||||
|
||||
#endif
|
||||
sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(sc, rs->rs_tstamp, tsf));
|
||||
if (rs->rs_status & HAL_RXERR_CRC)
|
||||
|
@ -82,13 +82,20 @@ struct ath_spectral_state {
|
||||
*/
|
||||
|
||||
/*
|
||||
* Attach DFS to the given interface
|
||||
* Attach spectral to the given interface
|
||||
*/
|
||||
int
|
||||
ath_spectral_attach(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_spectral_state *ss;
|
||||
|
||||
/*
|
||||
* If spectral isn't supported, don't error - just
|
||||
* quietly complete.
|
||||
*/
|
||||
if (! ath_hal_spectral_supported(sc->sc_ah))
|
||||
return (0);
|
||||
|
||||
ss = malloc(sizeof(struct ath_spectral_state),
|
||||
M_TEMP, M_WAITOK | M_ZERO);
|
||||
|
||||
@ -106,11 +113,15 @@ ath_spectral_attach(struct ath_softc *sc)
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach DFS from the given interface
|
||||
* Detach spectral from the given interface
|
||||
*/
|
||||
int
|
||||
ath_spectral_detach(struct ath_softc *sc)
|
||||
{
|
||||
|
||||
if (! ath_hal_spectral_supported(sc->sc_ah))
|
||||
return (0);
|
||||
|
||||
if (sc->sc_spectral != NULL) {
|
||||
free(sc->sc_spectral, M_TEMP);
|
||||
}
|
||||
@ -148,6 +159,9 @@ ath_ioctl_spectral(struct ath_softc *sc, struct ath_diag *ad)
|
||||
HAL_SPECTRAL_PARAM *pe;
|
||||
struct ath_spectral_state *ss = sc->sc_spectral;
|
||||
|
||||
if (! ath_hal_spectral_supported(sc->sc_ah))
|
||||
return (EINVAL);
|
||||
|
||||
if (ad->ad_id & ATH_DIAG_IN) {
|
||||
/*
|
||||
* Copy in data.
|
||||
|
@ -1303,6 +1303,8 @@ void ath_intr(void *);
|
||||
#define ath_hal_get_chan_ext_busy(_ah) \
|
||||
((*(_ah)->ah_get11nExtBusy)((_ah)))
|
||||
|
||||
#define ath_hal_spectral_supported(_ah) \
|
||||
(ath_hal_getcapability(_ah, HAL_CAP_SPECTRAL_SCAN, 0, NULL) == HAL_OK)
|
||||
#define ath_hal_spectral_get_config(_ah, _p) \
|
||||
((*(_ah)->ah_spectralGetConfig)((_ah), (_p)))
|
||||
#define ath_hal_spectral_configure(_ah, _p) \
|
||||
|
@ -287,10 +287,10 @@ nvme_ns_test(struct nvme_namespace *ns, u_long cmd, caddr_t arg)
|
||||
for (i = 0; i < io_test->num_threads; i++)
|
||||
#if __FreeBSD_version >= 800004
|
||||
kthread_add(fn, io_test_internal,
|
||||
curproc, NULL, 0, 0, "nvme_io_test[%d]", i);
|
||||
NULL, NULL, 0, 0, "nvme_io_test[%d]", i);
|
||||
#else
|
||||
kthread_create(fn, io_test_internal,
|
||||
curproc, 0, 0, "nvme_io_test[%d]", i);
|
||||
NULL, 0, 0, "nvme_io_test[%d]", i);
|
||||
#endif
|
||||
|
||||
tsleep(io_test_internal, 0, "nvme_test", io_test->time * 2 * hz);
|
||||
|
@ -244,7 +244,7 @@ static const struct pci_quirk pci_quirks[] = {
|
||||
* but support MSI just fine. QEMU uses the Intel 82440.
|
||||
*/
|
||||
{ 0x12378086, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 },
|
||||
{ 0x12751275, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 }, /* BHyVe */
|
||||
{ 0x12751275, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 }, /* bhyve */
|
||||
|
||||
/*
|
||||
* HPET MMIO base address may appear in Bar1 for AMD SB600 SMBus
|
||||
|
@ -1440,26 +1440,37 @@ void
|
||||
xhci_interrupt(struct xhci_softc *sc)
|
||||
{
|
||||
uint32_t status;
|
||||
uint32_t temp;
|
||||
uint32_t iman;
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
|
||||
status = XREAD4(sc, oper, XHCI_USBSTS);
|
||||
if (status == 0)
|
||||
goto done;
|
||||
|
||||
/* acknowledge interrupts */
|
||||
|
||||
XWRITE4(sc, oper, XHCI_USBSTS, status);
|
||||
|
||||
temp = XREAD4(sc, runt, XHCI_IMAN(0));
|
||||
DPRINTFN(16, "real interrupt (status=0x%08x)\n", status);
|
||||
|
||||
if (status & XHCI_STS_EINT) {
|
||||
|
||||
/* acknowledge pending event */
|
||||
/* acknowledge pending event */
|
||||
iman = XREAD4(sc, runt, XHCI_IMAN(0));
|
||||
|
||||
XWRITE4(sc, runt, XHCI_IMAN(0), temp);
|
||||
/* reset interrupt */
|
||||
XWRITE4(sc, runt, XHCI_IMAN(0), iman);
|
||||
|
||||
DPRINTFN(16, "real interrupt (iman=0x%08x)\n", iman);
|
||||
|
||||
/* check for event(s) */
|
||||
xhci_interrupt_poll(sc);
|
||||
}
|
||||
|
||||
DPRINTFN(16, "real interrupt (sts=0x%08x, "
|
||||
"iman=0x%08x)\n", status, temp);
|
||||
if (status & (XHCI_STS_PCD | XHCI_STS_HCH |
|
||||
XHCI_STS_HSE | XHCI_STS_HCE)) {
|
||||
|
||||
if (status != 0) {
|
||||
if (status & XHCI_STS_PCD) {
|
||||
xhci_root_intr(sc);
|
||||
}
|
||||
@ -1479,9 +1490,7 @@ xhci_interrupt(struct xhci_softc *sc)
|
||||
__FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
xhci_interrupt_poll(sc);
|
||||
|
||||
done:
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
|
@ -2019,7 +2019,8 @@ run_key_set_cb(void *arg)
|
||||
wcid = 0; /* NB: update WCID0 for group keys */
|
||||
base = RT2860_SKEY(RUN_VAP(vap)->rvp_id, k->wk_keyix);
|
||||
} else {
|
||||
wcid = RUN_AID2WCID(associd);
|
||||
wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
|
||||
1 : RUN_AID2WCID(associd);
|
||||
base = RT2860_PKEY(wcid);
|
||||
}
|
||||
|
||||
@ -2374,9 +2375,12 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint8_t rate;
|
||||
uint8_t ridx;
|
||||
uint8_t wcid = RUN_AID2WCID(ni->ni_associd);
|
||||
uint8_t wcid;
|
||||
int i, j;
|
||||
|
||||
wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
|
||||
1 : RUN_AID2WCID(ni->ni_associd);
|
||||
|
||||
if (wcid > RT2870_WCID_MAX) {
|
||||
device_printf(sc->sc_dev, "wcid=%d out of range\n", wcid);
|
||||
return;
|
||||
@ -3044,8 +3048,12 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
||||
txd->flags = qflags;
|
||||
txwi = (struct rt2860_txwi *)(txd + 1);
|
||||
txwi->xflags = xflags;
|
||||
txwi->wcid = IEEE80211_IS_MULTICAST(wh->i_addr1) ?
|
||||
0 : RUN_AID2WCID(ni->ni_associd);
|
||||
if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
|
||||
txwi->wcid = 0;
|
||||
} else {
|
||||
txwi->wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
|
||||
1 : RUN_AID2WCID(ni->ni_associd);
|
||||
}
|
||||
/* clear leftover garbage bits */
|
||||
txwi->flags = 0;
|
||||
txwi->txop = 0;
|
||||
|
@ -125,7 +125,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/smp.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <geom/geom.h>
|
||||
|
||||
#include <machine/_inttypes.h>
|
||||
@ -145,8 +144,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <xen/xenbus/xenbusvar.h>
|
||||
|
||||
#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*(x)))
|
||||
|
||||
/*--------------------------- Forward Declarations --------------------------*/
|
||||
/** Function signature for shutdown event handlers. */
|
||||
typedef void (xctrl_shutdown_handler_t)(void);
|
||||
@ -165,7 +162,7 @@ struct xctrl_shutdown_reason {
|
||||
};
|
||||
|
||||
/** Lookup table for shutdown event name to handler. */
|
||||
static struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = {
|
||||
static const struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = {
|
||||
{ "poweroff", xctrl_poweroff },
|
||||
{ "reboot", xctrl_reboot },
|
||||
{ "suspend", xctrl_suspend },
|
||||
@ -198,7 +195,6 @@ extern void xencons_resume(void);
|
||||
static void
|
||||
xctrl_suspend()
|
||||
{
|
||||
u_int cpuid;
|
||||
int i, j, k, fpp;
|
||||
unsigned long max_pfn, start_info_mfn;
|
||||
|
||||
@ -207,6 +203,8 @@ xctrl_suspend()
|
||||
#ifdef SMP
|
||||
struct thread *td;
|
||||
cpuset_t map;
|
||||
u_int cpuid;
|
||||
|
||||
/*
|
||||
* Bind us to CPU 0 and stop any other VCPUs.
|
||||
*/
|
||||
@ -231,7 +229,7 @@ xctrl_suspend()
|
||||
mtx_lock(&Giant);
|
||||
if (DEVICE_SUSPEND(root_bus) != 0) {
|
||||
mtx_unlock(&Giant);
|
||||
printf("xen_suspend: device_suspend failed\n");
|
||||
printf("%s: device_suspend failed\n", __func__);
|
||||
#ifdef SMP
|
||||
if (!CPU_EMPTY(&map))
|
||||
restart_cpus(map);
|
||||
@ -343,9 +341,9 @@ xctrl_suspend()
|
||||
* drivers need this.
|
||||
*/
|
||||
mtx_lock(&Giant);
|
||||
if (DEVICE_SUSPEND(root_bus)) {
|
||||
if (DEVICE_SUSPEND(root_bus) != 0) {
|
||||
mtx_unlock(&Giant);
|
||||
printf("xen_suspend: device_suspend failed\n");
|
||||
printf("%s: device_suspend failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
@ -396,8 +394,8 @@ xctrl_halt()
|
||||
static void
|
||||
xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len)
|
||||
{
|
||||
struct xctrl_shutdown_reason *reason;
|
||||
struct xctrl_shutdown_reason *last_reason;
|
||||
const struct xctrl_shutdown_reason *reason;
|
||||
const struct xctrl_shutdown_reason *last_reason;
|
||||
char *result;
|
||||
int error;
|
||||
int result_len;
|
||||
@ -408,7 +406,7 @@ xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len)
|
||||
return;
|
||||
|
||||
reason = xctrl_shutdown_reasons;
|
||||
last_reason = reason + NUM_ELEMENTS(xctrl_shutdown_reasons);
|
||||
last_reason = reason + nitems(xctrl_shutdown_reasons);
|
||||
while (reason < last_reason) {
|
||||
|
||||
if (!strcmp(result, reason->name)) {
|
||||
@ -511,10 +509,10 @@ static device_method_t xctrl_methods[] = {
|
||||
DEVMETHOD(device_attach, xctrl_attach),
|
||||
DEVMETHOD(device_detach, xctrl_detach),
|
||||
|
||||
{ 0, 0 }
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(xctrl, xctrl_driver, xctrl_methods, sizeof(struct xctrl_softc));
|
||||
devclass_t xctrl_devclass;
|
||||
|
||||
DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, 0, 0);
|
||||
DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, NULL, NULL);
|
||||
|
@ -1,394 +0,0 @@
|
||||
/******************************************************************************
|
||||
* evtchn.c
|
||||
*
|
||||
* Xenolinux driver for receiving and demuxing event-channel signals.
|
||||
*
|
||||
* Copyright (c) 2004, K A Fraser
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/ioccom.h>
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/xen-os.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/synch_bitops.h>
|
||||
|
||||
#include <xen/hypervisor.h>
|
||||
|
||||
|
||||
typedef struct evtchn_sotfc {
|
||||
|
||||
struct selinfo ev_rsel;
|
||||
} evtchn_softc_t;
|
||||
|
||||
|
||||
#ifdef linuxcrap
|
||||
/* NB. This must be shared amongst drivers if more things go in /dev/xen */
|
||||
static devfs_handle_t xen_dev_dir;
|
||||
#endif
|
||||
|
||||
/* Only one process may open /dev/xen/evtchn at any time. */
|
||||
static unsigned long evtchn_dev_inuse;
|
||||
|
||||
/* Notification ring, accessed via /dev/xen/evtchn. */
|
||||
|
||||
#define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
|
||||
|
||||
#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
|
||||
static uint16_t *ring;
|
||||
static unsigned int ring_cons, ring_prod, ring_overflow;
|
||||
|
||||
/* Which ports is user-space bound to? */
|
||||
static uint32_t bound_ports[32];
|
||||
|
||||
/* Unique address for processes to sleep on */
|
||||
static void *evtchn_waddr = ˚
|
||||
|
||||
static struct mtx lock, upcall_lock;
|
||||
|
||||
static d_read_t evtchn_read;
|
||||
static d_write_t evtchn_write;
|
||||
static d_ioctl_t evtchn_ioctl;
|
||||
static d_poll_t evtchn_poll;
|
||||
static d_open_t evtchn_open;
|
||||
static d_close_t evtchn_close;
|
||||
|
||||
|
||||
void
|
||||
evtchn_device_upcall(int port)
|
||||
{
|
||||
mtx_lock(&upcall_lock);
|
||||
|
||||
mask_evtchn(port);
|
||||
clear_evtchn(port);
|
||||
|
||||
if ( ring != NULL ) {
|
||||
if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) {
|
||||
ring[EVTCHN_RING_MASK(ring_prod)] = (uint16_t)port;
|
||||
if ( ring_cons == ring_prod++ ) {
|
||||
wakeup(evtchn_waddr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ring_overflow = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mtx_unlock(&upcall_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
__evtchn_reset_buffer_ring(void)
|
||||
{
|
||||
/* Initialise the ring to empty. Clear errors. */
|
||||
ring_cons = ring_prod = ring_overflow = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int rc;
|
||||
unsigned int count, c, p, sst = 0, bytes1 = 0, bytes2 = 0;
|
||||
count = uio->uio_resid;
|
||||
|
||||
count &= ~1; /* even number of bytes */
|
||||
|
||||
if ( count == 0 )
|
||||
{
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( count > PAGE_SIZE )
|
||||
count = PAGE_SIZE;
|
||||
|
||||
for ( ; ; ) {
|
||||
if ( (c = ring_cons) != (p = ring_prod) )
|
||||
break;
|
||||
|
||||
if ( ring_overflow ) {
|
||||
rc = EFBIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sst != 0) {
|
||||
rc = EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* PCATCH == check for signals before and after sleeping
|
||||
* PWAIT == priority of waiting on resource
|
||||
*/
|
||||
sst = tsleep(evtchn_waddr, PWAIT|PCATCH, "evchwt", 10);
|
||||
}
|
||||
|
||||
/* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
|
||||
if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 ) {
|
||||
bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(uint16_t);
|
||||
bytes2 = EVTCHN_RING_MASK(p) * sizeof(uint16_t);
|
||||
}
|
||||
else {
|
||||
bytes1 = (p - c) * sizeof(uint16_t);
|
||||
bytes2 = 0;
|
||||
}
|
||||
|
||||
/* Truncate chunks according to caller's maximum byte count. */
|
||||
if ( bytes1 > count ) {
|
||||
bytes1 = count;
|
||||
bytes2 = 0;
|
||||
}
|
||||
else if ( (bytes1 + bytes2) > count ) {
|
||||
bytes2 = count - bytes1;
|
||||
}
|
||||
|
||||
if ( uiomove(&ring[EVTCHN_RING_MASK(c)], bytes1, uio) ||
|
||||
((bytes2 != 0) && uiomove(&ring[0], bytes2, uio)))
|
||||
/* keeping this around as its replacement is not equivalent
|
||||
* copyout(&ring[0], &buf[bytes1], bytes2)
|
||||
*/
|
||||
{
|
||||
rc = EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ring_cons += (bytes1 + bytes2) / sizeof(uint16_t);
|
||||
|
||||
rc = bytes1 + bytes2;
|
||||
|
||||
out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int rc, i, count;
|
||||
|
||||
count = uio->uio_resid;
|
||||
|
||||
uint16_t *kbuf = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
|
||||
|
||||
|
||||
if ( kbuf == NULL )
|
||||
return ENOMEM;
|
||||
|
||||
count &= ~1; /* even number of bytes */
|
||||
|
||||
if ( count == 0 ) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( count > PAGE_SIZE )
|
||||
count = PAGE_SIZE;
|
||||
|
||||
if ( uiomove(kbuf, count, uio) != 0 ) {
|
||||
rc = EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mtx_lock_spin(&lock);
|
||||
for ( i = 0; i < (count/2); i++ )
|
||||
if ( test_bit(kbuf[i], &bound_ports[0]) )
|
||||
unmask_evtchn(kbuf[i]);
|
||||
mtx_unlock_spin(&lock);
|
||||
|
||||
rc = count;
|
||||
|
||||
out:
|
||||
free(kbuf, M_DEVBUF);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
|
||||
int mode, struct thread *td __unused)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
mtx_lock_spin(&lock);
|
||||
|
||||
switch ( cmd )
|
||||
{
|
||||
case EVTCHN_RESET:
|
||||
__evtchn_reset_buffer_ring();
|
||||
break;
|
||||
case EVTCHN_BIND:
|
||||
if ( !synch_test_and_set_bit((int)arg, &bound_ports[0]) )
|
||||
unmask_evtchn((int)arg);
|
||||
else
|
||||
rc = EINVAL;
|
||||
break;
|
||||
case EVTCHN_UNBIND:
|
||||
if ( synch_test_and_clear_bit((int)arg, &bound_ports[0]) )
|
||||
mask_evtchn((int)arg);
|
||||
else
|
||||
rc = EINVAL;
|
||||
break;
|
||||
default:
|
||||
rc = ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_unlock_spin(&lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
evtchn_poll(struct cdev *dev, int poll_events, struct thread *td)
|
||||
{
|
||||
|
||||
evtchn_softc_t *sc;
|
||||
unsigned int mask = POLLOUT | POLLWRNORM;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
|
||||
if ( ring_cons != ring_prod )
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
else if ( ring_overflow )
|
||||
mask = POLLERR;
|
||||
else
|
||||
selrecord(td, &sc->ev_rsel);
|
||||
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td)
|
||||
{
|
||||
uint16_t *_ring;
|
||||
|
||||
if (flag & O_NONBLOCK)
|
||||
return EBUSY;
|
||||
|
||||
if ( synch_test_and_set_bit(0, &evtchn_dev_inuse) )
|
||||
return EBUSY;
|
||||
|
||||
if ( (_ring = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK)) == NULL )
|
||||
return ENOMEM;
|
||||
|
||||
mtx_lock_spin(&lock);
|
||||
ring = _ring;
|
||||
__evtchn_reset_buffer_ring();
|
||||
mtx_unlock_spin(&lock);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evtchn_close(struct cdev *dev, int flag, int otyp, struct thread *td __unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
mtx_lock_spin(&lock);
|
||||
if (ring != NULL) {
|
||||
free(ring, M_DEVBUF);
|
||||
ring = NULL;
|
||||
}
|
||||
for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
|
||||
if ( synch_test_and_clear_bit(i, &bound_ports[0]) )
|
||||
mask_evtchn(i);
|
||||
mtx_unlock_spin(&lock);
|
||||
|
||||
evtchn_dev_inuse = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cdevsw evtchn_devsw = {
|
||||
d_version: D_VERSION,
|
||||
d_open: evtchn_open,
|
||||
d_close: evtchn_close,
|
||||
d_read: evtchn_read,
|
||||
d_write: evtchn_write,
|
||||
d_ioctl: evtchn_ioctl,
|
||||
d_poll: evtchn_poll,
|
||||
d_name: "evtchn",
|
||||
d_flags: 0,
|
||||
};
|
||||
|
||||
|
||||
/* XXX - if this device is ever supposed to support use by more than one process
|
||||
* this global static will have to go away
|
||||
*/
|
||||
static struct cdev *evtchn_dev;
|
||||
|
||||
|
||||
|
||||
static int
|
||||
evtchn_init(void *dummy __unused)
|
||||
{
|
||||
/* XXX I believe we don't need these leaving them here for now until we
|
||||
* have some semblance of it working
|
||||
*/
|
||||
mtx_init(&upcall_lock, "evtchup", NULL, MTX_DEF);
|
||||
|
||||
/* (DEVFS) create '/dev/misc/evtchn'. */
|
||||
evtchn_dev = make_dev(&evtchn_devsw, 0, UID_ROOT, GID_WHEEL, 0600, "xen/evtchn");
|
||||
|
||||
mtx_init(&lock, "evch", NULL, MTX_SPIN | MTX_NOWITNESS);
|
||||
|
||||
evtchn_dev->si_drv1 = malloc(sizeof(evtchn_softc_t), M_DEVBUF, M_WAITOK);
|
||||
bzero(evtchn_dev->si_drv1, sizeof(evtchn_softc_t));
|
||||
|
||||
/* XXX I don't think we need any of this rubbish */
|
||||
#if 0
|
||||
if ( err != 0 )
|
||||
{
|
||||
printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* (DEVFS) create directory '/dev/xen'. */
|
||||
xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
|
||||
|
||||
/* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
|
||||
pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
|
||||
&link_dest[3],
|
||||
sizeof(link_dest) - 3);
|
||||
if ( pos >= 0 )
|
||||
strncpy(&link_dest[pos], "../", 3);
|
||||
/* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
|
||||
(void)devfs_mk_symlink(xen_dev_dir,
|
||||
"evtchn",
|
||||
DEVFS_FL_DEFAULT,
|
||||
&link_dest[pos],
|
||||
&symlink_handle,
|
||||
NULL);
|
||||
|
||||
/* (DEVFS) automatically destroy the symlink with its destination. */
|
||||
devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
|
||||
#endif
|
||||
printk("Event-channel device installed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SYSINIT(evtchn_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_init, NULL);
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
@ -208,8 +207,6 @@ struct xn_chain_data {
|
||||
struct mbuf *xn_rx_chain[NET_RX_RING_SIZE+1];
|
||||
};
|
||||
|
||||
#define NUM_ELEMENTS(x) (sizeof(x)/sizeof(*x))
|
||||
|
||||
struct net_device_stats
|
||||
{
|
||||
u_long rx_packets; /* total packets received */
|
||||
@ -244,7 +241,6 @@ struct net_device_stats
|
||||
};
|
||||
|
||||
struct netfront_info {
|
||||
|
||||
struct ifnet *xn_ifp;
|
||||
#if __FreeBSD_version >= 700000
|
||||
struct lro_ctrl xn_lro;
|
||||
@ -329,12 +325,6 @@ struct netfront_rx_info {
|
||||
|
||||
/* Access macros for acquiring freeing slots in xn_free_{tx,rx}_idxs[]. */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Access macros for acquiring freeing slots in tx_skbs[].
|
||||
*/
|
||||
|
||||
static inline void
|
||||
add_id_to_freelist(struct mbuf **list, uintptr_t id)
|
||||
{
|
||||
@ -517,7 +507,6 @@ netfront_resume(device_t dev)
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* Common code used when first setting up, and when resuming. */
|
||||
static int
|
||||
talk_to_backend(device_t dev, struct netfront_info *info)
|
||||
@ -605,7 +594,6 @@ talk_to_backend(device_t dev, struct netfront_info *info)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
setup_device(device_t dev, struct netfront_info *info)
|
||||
{
|
||||
@ -794,7 +782,7 @@ netif_release_tx_bufs(struct netfront_info *np)
|
||||
add_id_to_freelist(np->tx_mbufs, i);
|
||||
np->xn_cdata.xn_tx_chain_cnt--;
|
||||
if (np->xn_cdata.xn_tx_chain_cnt < 0) {
|
||||
panic("netif_release_tx_bufs: tx_chain_cnt must be >= 0");
|
||||
panic("%s: tx_chain_cnt must be >= 0", __func__);
|
||||
}
|
||||
m_free(m);
|
||||
}
|
||||
@ -946,7 +934,6 @@ refill:
|
||||
reservation.domid = DOMID_SELF;
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
|
||||
|
||||
/* After all PTEs have been zapped, flush the TLB. */
|
||||
sc->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
|
||||
UVMF_TLB_FLUSH|UVMF_ALL;
|
||||
@ -958,15 +945,11 @@ refill:
|
||||
/* Zap PTEs and give away pages in one big multicall. */
|
||||
(void)HYPERVISOR_multicall(sc->rx_mcl, i+1);
|
||||
|
||||
/* Check return status of HYPERVISOR_dom_mem_op(). */
|
||||
if (unlikely(sc->rx_mcl[i].result != i))
|
||||
panic("Unable to reduce memory reservation\n");
|
||||
} else {
|
||||
if (HYPERVISOR_memory_op(
|
||||
XENMEM_decrease_reservation, &reservation)
|
||||
!= i)
|
||||
panic("Unable to reduce memory "
|
||||
"reservation\n");
|
||||
if (unlikely(sc->rx_mcl[i].result != i ||
|
||||
HYPERVISOR_memory_op(XENMEM_decrease_reservation,
|
||||
&reservation) != i))
|
||||
panic("%s: unable to reduce memory "
|
||||
"reservation\n", __func__);
|
||||
}
|
||||
} else {
|
||||
wmb();
|
||||
@ -1169,8 +1152,8 @@ xn_txeof(struct netfront_info *np)
|
||||
ifp->if_opackets++;
|
||||
if (unlikely(gnttab_query_foreign_access(
|
||||
np->grant_tx_ref[id]) != 0)) {
|
||||
panic("grant id %u still in use by the backend",
|
||||
id);
|
||||
panic("%s: grant id %u still in use by the "
|
||||
"backend", __func__, id);
|
||||
}
|
||||
gnttab_end_foreign_access_ref(
|
||||
np->grant_tx_ref[id]);
|
||||
@ -1210,7 +1193,6 @@ xn_txeof(struct netfront_info *np)
|
||||
netif_wake_queue(dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1240,7 +1222,6 @@ xn_intr(void *xsc)
|
||||
xn_start(ifp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xennet_move_rx_slot(struct netfront_info *np, struct mbuf *m,
|
||||
grant_ref_t ref)
|
||||
@ -1319,17 +1300,15 @@ xennet_get_responses(struct netfront_info *np,
|
||||
|
||||
m0 = m = m_prev = xennet_get_rx_mbuf(np, *cons);
|
||||
|
||||
|
||||
if (rx->flags & NETRXF_extra_info) {
|
||||
err = xennet_get_extras(np, extras, rp, cons);
|
||||
}
|
||||
|
||||
|
||||
if (m0 != NULL) {
|
||||
m0->m_pkthdr.len = 0;
|
||||
m0->m_next = NULL;
|
||||
}
|
||||
|
||||
|
||||
for (;;) {
|
||||
u_long mfn;
|
||||
|
||||
@ -1468,10 +1447,8 @@ xn_tick_locked(struct netfront_info *sc)
|
||||
callout_reset(&sc->xn_stat_ch, hz, xn_tick, sc);
|
||||
|
||||
/* XXX placeholder for printing debug information */
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xn_tick(void *xsc)
|
||||
{
|
||||
@ -1481,7 +1458,6 @@ xn_tick(void *xsc)
|
||||
XN_RX_LOCK(sc);
|
||||
xn_tick_locked(sc);
|
||||
XN_RX_UNLOCK(sc);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1595,10 +1571,12 @@ xn_assemble_tx_request(struct netfront_info *sc, struct mbuf *m_head)
|
||||
tx = RING_GET_REQUEST(&sc->tx, sc->tx.req_prod_pvt);
|
||||
id = get_id_from_freelist(sc->tx_mbufs);
|
||||
if (id == 0)
|
||||
panic("xn_start_locked: was allocated the freelist head!\n");
|
||||
panic("%s: was allocated the freelist head!\n",
|
||||
__func__);
|
||||
sc->xn_cdata.xn_tx_chain_cnt++;
|
||||
if (sc->xn_cdata.xn_tx_chain_cnt > NET_TX_RING_SIZE)
|
||||
panic("xn_start_locked: tx_chain_cnt must be <= NET_TX_RING_SIZE\n");
|
||||
panic("%s: tx_chain_cnt must be <= NET_TX_RING_SIZE\n",
|
||||
__func__);
|
||||
sc->tx_mbufs[id] = m;
|
||||
tx->id = id;
|
||||
ref = gnttab_claim_grant_reference(&sc->gref_tx_head);
|
||||
@ -1710,7 +1688,6 @@ xn_start_locked(struct ifnet *ifp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xn_start(struct ifnet *ifp)
|
||||
{
|
||||
@ -1744,10 +1721,8 @@ xn_ifinit_locked(struct netfront_info *sc)
|
||||
if_link_state_change(ifp, LINK_STATE_UP);
|
||||
|
||||
callout_reset(&sc->xn_stat_ch, hz, xn_tick, sc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xn_ifinit(void *xsc)
|
||||
{
|
||||
@ -1756,10 +1731,8 @@ xn_ifinit(void *xsc)
|
||||
XN_LOCK(sc);
|
||||
xn_ifinit_locked(sc);
|
||||
XN_UNLOCK(sc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
@ -2261,7 +2234,7 @@ static device_method_t netfront_methods[] = {
|
||||
/* Xenbus interface */
|
||||
DEVMETHOD(xenbus_otherend_changed, netfront_backend_changed),
|
||||
|
||||
{ 0, 0 }
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t netfront_driver = {
|
||||
@ -2271,4 +2244,5 @@ static driver_t netfront_driver = {
|
||||
};
|
||||
devclass_t netfront_devclass;
|
||||
|
||||
DRIVER_MODULE(xe, xenbusb_front, netfront_driver, netfront_devclass, 0, 0);
|
||||
DRIVER_MODULE(xe, xenbusb_front, netfront_driver, netfront_devclass, NULL,
|
||||
NULL);
|
||||
|
@ -1,80 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 Citrix Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/interrupt.h>
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/xen_intr.h>
|
||||
|
||||
#include <dev/xen/xenpci/xenpcivar.h>
|
||||
|
||||
void
|
||||
xen_suspend()
|
||||
{
|
||||
int suspend_cancelled;
|
||||
|
||||
if (DEVICE_SUSPEND(root_bus)) {
|
||||
printf("xen_suspend: device_suspend failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we don't change cpus or switch to some other
|
||||
* thread. for the duration.
|
||||
*/
|
||||
critical_enter();
|
||||
|
||||
/*
|
||||
* Prevent any races with evtchn_interrupt() handler.
|
||||
*/
|
||||
irq_suspend();
|
||||
disable_intr();
|
||||
|
||||
suspend_cancelled = HYPERVISOR_suspend(0);
|
||||
if (!suspend_cancelled)
|
||||
xenpci_resume();
|
||||
|
||||
/*
|
||||
* Re-enable interrupts and put the scheduler back to normal.
|
||||
*/
|
||||
enable_intr();
|
||||
critical_exit();
|
||||
|
||||
/*
|
||||
* FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or
|
||||
* similar.
|
||||
*/
|
||||
if (!suspend_cancelled)
|
||||
DEVICE_RESUME(root_bus);
|
||||
}
|
@ -29,8 +29,6 @@
|
||||
#ifndef _FS_EXT2FS_EXT2_DINODE_H_
|
||||
#define _FS_EXT2FS_EXT2_DINODE_H_
|
||||
|
||||
#define e2di_size_high e2di_dacl
|
||||
|
||||
/*
|
||||
* Special inode numbers
|
||||
* The root inode is the root of the file system. Inode 0 can't be used for
|
||||
@ -87,11 +85,11 @@
|
||||
struct ext2fs_dinode {
|
||||
uint16_t e2di_mode; /* 0: IFMT, permissions; see below. */
|
||||
uint16_t e2di_uid; /* 2: Owner UID */
|
||||
uint32_t e2di_size; /* 4: Size (in bytes) */
|
||||
uint32_t e2di_atime; /* 8: Access time */
|
||||
uint32_t e2di_ctime; /* 12: Change time */
|
||||
uint32_t e2di_mtime; /* 16: Modification time */
|
||||
uint32_t e2di_dtime; /* 20: Deletion time */
|
||||
uint32_t e2di_size; /* 4: Size (in bytes) */
|
||||
uint32_t e2di_atime; /* 8: Access time */
|
||||
uint32_t e2di_ctime; /* 12: Change time */
|
||||
uint32_t e2di_mtime; /* 16: Modification time */
|
||||
uint32_t e2di_dtime; /* 20: Deletion time */
|
||||
uint16_t e2di_gid; /* 24: Owner GID */
|
||||
uint16_t e2di_nlink; /* 26: File link count */
|
||||
uint32_t e2di_nblock; /* 28: Blocks count */
|
||||
@ -99,22 +97,23 @@ struct ext2fs_dinode {
|
||||
uint32_t e2di_version; /* 36: Low 32 bits inode version */
|
||||
uint32_t e2di_blocks[EXT2_N_BLOCKS]; /* 40: disk blocks */
|
||||
uint32_t e2di_gen; /* 100: generation number */
|
||||
uint32_t e2di_facl; /* 104: file ACL (not implemented) */
|
||||
uint32_t e2di_dacl; /* 108: dir ACL (not implemented) */
|
||||
uint32_t e2di_faddr; /* 112: fragment address */
|
||||
uint32_t e2di_facl; /* 104: Low EA block */
|
||||
uint32_t e2di_size_high; /* 108: Upper bits of file size */
|
||||
uint32_t e2di_faddr; /* 112: Fragment address (obsolete) */
|
||||
uint16_t e2di_nblock_high; /* 116: Blocks count bits 47:32 */
|
||||
uint16_t e2di_facl_high; /* 118: file ACL bits 47:32 */
|
||||
uint16_t e2di_facl_high; /* 118: File EA bits 47:32 */
|
||||
uint16_t e2di_uid_high; /* 120: Owner UID top 16 bits */
|
||||
uint16_t e2di_gid_high; /* 122: Owner GID top 16 bits */
|
||||
uint32_t e2di_linux_reserved3; /* 124 */
|
||||
uint16_t e2di_extra_isize;
|
||||
uint16_t e2di_pad1;
|
||||
uint32_t e2di_ctime_extra; /* Extra change time */
|
||||
uint32_t e2di_mtime_extra; /* Extra modification time */
|
||||
uint32_t e2di_atime_extra; /* Extra access time */
|
||||
uint32_t e2di_crtime; /* Creation (birth)time */
|
||||
uint32_t e2di_crtime_extra; /* Extra creation (birth)time */
|
||||
uint32_t e2di_version_hi; /* High 30 bits of inode version */
|
||||
uint16_t e2di_chksum_lo; /* 124: Lower inode checksum */
|
||||
uint16_t e2di_lx_reserved; /* 126: Unused */
|
||||
uint16_t e2di_extra_isize; /* 128: Size of this inode */
|
||||
uint16_t e2di_chksum_hi; /* 130: High inode checksum */
|
||||
uint32_t e2di_ctime_extra; /* 132: Extra change time */
|
||||
uint32_t e2di_mtime_extra; /* 136: Extra modification time */
|
||||
uint32_t e2di_atime_extra; /* 140: Extra access time */
|
||||
uint32_t e2di_crtime; /* 144: Creation (birth)time */
|
||||
uint32_t e2di_crtime_extra; /* 148: Extra creation (birth)time */
|
||||
uint32_t e2di_version_hi; /* 152: High bits of inode version */
|
||||
};
|
||||
|
||||
#endif /* !_FS_EXT2FS_EXT2_DINODE_H_ */
|
||||
|
@ -113,7 +113,7 @@ fuse_write_directbackend(struct vnode *vp, struct uio *uio,
|
||||
struct ucred *cred, struct fuse_filehandle *fufh);
|
||||
static int
|
||||
fuse_write_biobackend(struct vnode *vp, struct uio *uio,
|
||||
struct ucred *cred, struct fuse_filehandle *fufh);
|
||||
struct ucred *cred, struct fuse_filehandle *fufh, int ioflag);
|
||||
|
||||
int
|
||||
fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
|
||||
@ -162,7 +162,7 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
|
||||
} else {
|
||||
FS_DEBUG("buffered write of vnode %ju\n",
|
||||
(uintmax_t)VTOILLU(vp));
|
||||
err = fuse_write_biobackend(vp, uio, cred, fufh);
|
||||
err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -371,7 +371,7 @@ fuse_write_directbackend(struct vnode *vp, struct uio *uio,
|
||||
|
||||
static int
|
||||
fuse_write_biobackend(struct vnode *vp, struct uio *uio,
|
||||
struct ucred *cred, struct fuse_filehandle *fufh)
|
||||
struct ucred *cred, struct fuse_filehandle *fufh, int ioflag)
|
||||
{
|
||||
struct fuse_vnode_data *fvdat = VTOFUD(vp);
|
||||
struct buf *bp;
|
||||
@ -390,6 +390,8 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio,
|
||||
return (EINVAL);
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
if (ioflag & IO_APPEND)
|
||||
uio_setoffset(uio, fvdat->filesize);
|
||||
|
||||
/*
|
||||
* Find all of this file's B_NEEDCOMMIT buffers. If our writes
|
||||
|
@ -478,39 +478,19 @@ nandfs_iterate_dirty_vnodes(struct mount *mp, struct nandfs_seginfo *seginfo)
|
||||
struct nandfs_node *nandfs_node;
|
||||
struct vnode *vp, *mvp;
|
||||
struct thread *td;
|
||||
int error, lockreq, update;
|
||||
int error, update;
|
||||
|
||||
td = curthread;
|
||||
lockreq = LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY;
|
||||
|
||||
MNT_ILOCK(mp);
|
||||
|
||||
MNT_VNODE_FOREACH(vp, mp, mvp) {
|
||||
MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) {
|
||||
update = 0;
|
||||
|
||||
if (mp->mnt_syncer == vp)
|
||||
continue;
|
||||
if (VOP_ISLOCKED(vp))
|
||||
continue;
|
||||
|
||||
VI_LOCK(vp);
|
||||
MNT_IUNLOCK(mp);
|
||||
if (vp->v_iflag & VI_DOOMED) {
|
||||
if (mp->mnt_syncer == vp || VOP_ISLOCKED(vp)) {
|
||||
VI_UNLOCK(vp);
|
||||
MNT_ILOCK(mp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((error = vget(vp, lockreq, td)) != 0) {
|
||||
MNT_ILOCK(mp);
|
||||
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_NOWAIT, td) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vp->v_iflag & VI_DOOMED) {
|
||||
vput(vp);
|
||||
MNT_ILOCK(mp);
|
||||
continue;
|
||||
}
|
||||
|
||||
nandfs_node = VTON(vp);
|
||||
if (nandfs_node->nn_flags & IN_MODIFIED) {
|
||||
@ -532,12 +512,8 @@ nandfs_iterate_dirty_vnodes(struct mount *mp, struct nandfs_seginfo *seginfo)
|
||||
|
||||
if (update)
|
||||
nandfs_node_update(nandfs_node);
|
||||
|
||||
MNT_ILOCK(mp);
|
||||
}
|
||||
|
||||
MNT_IUNLOCK(mp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -34,9 +34,15 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef FS_NULL_H
|
||||
#define FS_NULL_H
|
||||
|
||||
#define NULLM_CACHE 0x0001
|
||||
|
||||
struct null_mount {
|
||||
struct mount *nullm_vfs;
|
||||
struct vnode *nullm_rootvp; /* Reference to root null_node */
|
||||
uint64_t nullm_flags;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
@ -80,3 +86,5 @@ MALLOC_DECLARE(M_NULLFSNODE);
|
||||
#endif /* NULLFS_DEBUG */
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif
|
||||
|
@ -224,6 +224,9 @@ null_nodeget(mp, lowervp, vpp)
|
||||
* provide ready to use vnode.
|
||||
*/
|
||||
if (VOP_ISLOCKED(lowervp) != LK_EXCLUSIVE) {
|
||||
KASSERT((MOUNTTONULLMOUNT(mp)->nullm_flags & NULLM_CACHE) != 0,
|
||||
("lowervp %p is not excl locked and cache is disabled",
|
||||
lowervp));
|
||||
vn_lock(lowervp, LK_UPGRADE | LK_RETRY);
|
||||
if ((lowervp->v_iflag & VI_DOOMED) != 0) {
|
||||
vput(lowervp);
|
||||
|
@ -67,6 +67,15 @@ static vfs_vget_t nullfs_vget;
|
||||
static vfs_extattrctl_t nullfs_extattrctl;
|
||||
static vfs_reclaim_lowervp_t nullfs_reclaim_lowervp;
|
||||
|
||||
/* Mount options that we support. */
|
||||
static const char *nullfs_opts[] = {
|
||||
"cache",
|
||||
"export",
|
||||
"from",
|
||||
"target",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Mount null layer
|
||||
*/
|
||||
@ -86,9 +95,11 @@ nullfs_mount(struct mount *mp)
|
||||
|
||||
if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_NULLFS))
|
||||
return (EPERM);
|
||||
|
||||
if (mp->mnt_flag & MNT_ROOTFS)
|
||||
return (EOPNOTSUPP);
|
||||
if (vfs_filteropt(mp->mnt_optnew, nullfs_opts))
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Update is a no-op
|
||||
*/
|
||||
@ -149,7 +160,7 @@ nullfs_mount(struct mount *mp)
|
||||
}
|
||||
|
||||
xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
|
||||
M_NULLFSMNT, M_WAITOK);
|
||||
M_NULLFSMNT, M_WAITOK | M_ZERO);
|
||||
|
||||
/*
|
||||
* Save reference to underlying FS
|
||||
@ -187,16 +198,27 @@ nullfs_mount(struct mount *mp)
|
||||
mp->mnt_flag |= MNT_LOCAL;
|
||||
MNT_IUNLOCK(mp);
|
||||
}
|
||||
|
||||
xmp->nullm_flags |= NULLM_CACHE;
|
||||
if (vfs_getopt(mp->mnt_optnew, "nocache", NULL, NULL) == 0)
|
||||
xmp->nullm_flags &= ~NULLM_CACHE;
|
||||
|
||||
MNT_ILOCK(mp);
|
||||
mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag &
|
||||
(MNTK_SHARED_WRITES | MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED);
|
||||
if ((xmp->nullm_flags & NULLM_CACHE) != 0) {
|
||||
mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag &
|
||||
(MNTK_SHARED_WRITES | MNTK_LOOKUP_SHARED |
|
||||
MNTK_EXTENDED_SHARED);
|
||||
}
|
||||
mp->mnt_kern_flag |= MNTK_LOOKUP_EXCL_DOTDOT;
|
||||
MNT_IUNLOCK(mp);
|
||||
mp->mnt_data = xmp;
|
||||
vfs_getnewfsid(mp);
|
||||
MNT_ILOCK(xmp->nullm_vfs);
|
||||
TAILQ_INSERT_TAIL(&xmp->nullm_vfs->mnt_uppers, mp, mnt_upper_link);
|
||||
MNT_IUNLOCK(xmp->nullm_vfs);
|
||||
if ((xmp->nullm_flags & NULLM_CACHE) != 0) {
|
||||
MNT_ILOCK(xmp->nullm_vfs);
|
||||
TAILQ_INSERT_TAIL(&xmp->nullm_vfs->mnt_uppers, mp,
|
||||
mnt_upper_link);
|
||||
MNT_IUNLOCK(xmp->nullm_vfs);
|
||||
}
|
||||
|
||||
vfs_mountedfrom(mp, target);
|
||||
|
||||
@ -234,13 +256,15 @@ nullfs_unmount(mp, mntflags)
|
||||
*/
|
||||
mntdata = mp->mnt_data;
|
||||
ump = mntdata->nullm_vfs;
|
||||
MNT_ILOCK(ump);
|
||||
while ((ump->mnt_kern_flag & MNTK_VGONE_UPPER) != 0) {
|
||||
ump->mnt_kern_flag |= MNTK_VGONE_WAITER;
|
||||
msleep(&ump->mnt_uppers, &ump->mnt_mtx, 0, "vgnupw", 0);
|
||||
if ((mntdata->nullm_flags & NULLM_CACHE) != 0) {
|
||||
MNT_ILOCK(ump);
|
||||
while ((ump->mnt_kern_flag & MNTK_VGONE_UPPER) != 0) {
|
||||
ump->mnt_kern_flag |= MNTK_VGONE_WAITER;
|
||||
msleep(&ump->mnt_uppers, &ump->mnt_mtx, 0, "vgnupw", 0);
|
||||
}
|
||||
TAILQ_REMOVE(&ump->mnt_uppers, mp, mnt_upper_link);
|
||||
MNT_IUNLOCK(ump);
|
||||
}
|
||||
TAILQ_REMOVE(&ump->mnt_uppers, mp, mnt_upper_link);
|
||||
MNT_IUNLOCK(ump);
|
||||
mp->mnt_data = NULL;
|
||||
free(mntdata, M_NULLFSMNT);
|
||||
return (0);
|
||||
|
@ -692,7 +692,22 @@ null_unlock(struct vop_unlock_args *ap)
|
||||
static int
|
||||
null_inactive(struct vop_inactive_args *ap __unused)
|
||||
{
|
||||
struct vnode *vp;
|
||||
struct mount *mp;
|
||||
struct null_mount *xmp;
|
||||
|
||||
vp = ap->a_vp;
|
||||
mp = vp->v_mount;
|
||||
xmp = MOUNTTONULLMOUNT(mp);
|
||||
if ((xmp->nullm_flags & NULLM_CACHE) == 0) {
|
||||
/*
|
||||
* If this is the last reference and caching of the
|
||||
* nullfs vnodes is not enabled, then free up the
|
||||
* vnode so as not to tie up the lower vnodes.
|
||||
*/
|
||||
vp->v_object = NULL;
|
||||
vrecycle(vp);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
/* --------------------------------------------------------------------- */
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/tree.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#include <vm/swap_pager.h>
|
||||
|
||||
@ -60,104 +61,81 @@ MALLOC_DECLARE(M_TMPFSNAME);
|
||||
/*
|
||||
* Internal representation of a tmpfs directory entry.
|
||||
*/
|
||||
|
||||
LIST_HEAD(tmpfs_dir_duphead, tmpfs_dirent);
|
||||
|
||||
struct tmpfs_dirent {
|
||||
TAILQ_ENTRY(tmpfs_dirent) td_entries;
|
||||
/*
|
||||
* Depending on td_cookie flag entry can be of 3 types:
|
||||
* - regular -- no hash collisions, stored in RB-Tree
|
||||
* - duphead -- synthetic linked list head for dup entries
|
||||
* - dup -- stored in linked list instead of RB-Tree
|
||||
*/
|
||||
union {
|
||||
/* regular and duphead entry types */
|
||||
RB_ENTRY(tmpfs_dirent) td_entries;
|
||||
|
||||
/* Length of the name stored in this directory entry. This avoids
|
||||
* the need to recalculate it every time the name is used. */
|
||||
uint16_t td_namelen;
|
||||
/* dup entry type */
|
||||
struct {
|
||||
LIST_ENTRY(tmpfs_dirent) entries;
|
||||
LIST_ENTRY(tmpfs_dirent) index_entries;
|
||||
} td_dup;
|
||||
} uh;
|
||||
|
||||
/* The name of the entry, allocated from a string pool. This
|
||||
* string is not required to be zero-terminated; therefore, the
|
||||
* td_namelen field must always be used when accessing its value. */
|
||||
char * td_name;
|
||||
uint32_t td_cookie;
|
||||
uint32_t td_hash;
|
||||
u_int td_namelen;
|
||||
|
||||
/* Pointer to the node this entry refers to. In case this field
|
||||
* is NULL, the node is a whiteout. */
|
||||
struct tmpfs_node * td_node;
|
||||
|
||||
union {
|
||||
/*
|
||||
* The name of the entry, allocated from a string pool. This
|
||||
* string is not required to be zero-terminated.
|
||||
*/
|
||||
char * td_name; /* regular, dup */
|
||||
struct tmpfs_dir_duphead td_duphead; /* duphead */
|
||||
} ud;
|
||||
};
|
||||
|
||||
/* A directory in tmpfs holds a sorted list of directory entries, which in
|
||||
/* A directory in tmpfs holds a list of directory entries, which in
|
||||
* turn point to other files (which can be directories themselves).
|
||||
*
|
||||
* In tmpfs, this list is managed by a tail queue, whose head is defined by
|
||||
* In tmpfs, this list is managed by a RB-Tree, whose head is defined by
|
||||
* the struct tmpfs_dir type.
|
||||
*
|
||||
* It is imporant to notice that directories do not have entries for . and
|
||||
* It is important to notice that directories do not have entries for . and
|
||||
* .. as other file systems do. These can be generated when requested
|
||||
* based on information available by other means, such as the pointer to
|
||||
* the node itself in the former case or the pointer to the parent directory
|
||||
* in the latter case. This is done to simplify tmpfs's code and, more
|
||||
* importantly, to remove redundancy. */
|
||||
TAILQ_HEAD(tmpfs_dir, tmpfs_dirent);
|
||||
RB_HEAD(tmpfs_dir, tmpfs_dirent);
|
||||
|
||||
/* Each entry in a directory has a cookie that identifies it. Cookies
|
||||
* supersede offsets within directories because, given how tmpfs stores
|
||||
* directories in memory, there is no such thing as an offset. (Emulating
|
||||
* a real offset could be very difficult.)
|
||||
*
|
||||
* directories in memory, there is no such thing as an offset.
|
||||
*
|
||||
* The '.', '..' and the end of directory markers have fixed cookies which
|
||||
* cannot collide with the cookies generated by other entries. The cookies
|
||||
* fot the other entries are generated based on the memory address on which
|
||||
* stores their information is stored.
|
||||
* for the other entries are generated based on the file name hash value or
|
||||
* unique number in case of name hash collision.
|
||||
*
|
||||
* Ideally, using the entry's memory pointer as the cookie would be enough
|
||||
* to represent it and it wouldn't cause collisions in any system.
|
||||
* Unfortunately, this results in "offsets" with very large values which
|
||||
* later raise problems in the Linux compatibility layer (and maybe in other
|
||||
* places) as described in PR kern/32034. Hence we need to workaround this
|
||||
* with a rather ugly hack.
|
||||
*
|
||||
* Linux 32-bit binaries, unless built with _FILE_OFFSET_BITS=64, have off_t
|
||||
* set to 'long', which is a 32-bit *signed* long integer. Regardless of
|
||||
* the macro value, GLIBC (2.3 at least) always uses the getdents64
|
||||
* system call (when calling readdir) which internally returns off64_t
|
||||
* offsets. In order to make 32-bit binaries work, *GLIBC* converts the
|
||||
* 64-bit values returned by the kernel to 32-bit ones and aborts with
|
||||
* EOVERFLOW if the conversion results in values that won't fit in 32-bit
|
||||
* integers (which it assumes is because the directory is extremely large).
|
||||
* This wouldn't cause problems if we were dealing with unsigned integers,
|
||||
* but as we have signed integers, this check fails due to sign expansion.
|
||||
*
|
||||
* For example, consider that the kernel returns the 0xc1234567 cookie to
|
||||
* userspace in a off64_t integer. Later on, GLIBC casts this value to
|
||||
* off_t (remember, signed) with code similar to:
|
||||
* system call returns the offset in kernel_value;
|
||||
* off_t casted_value = kernel_value;
|
||||
* if (sizeof(off_t) != sizeof(off64_t) &&
|
||||
* kernel_value != casted_value)
|
||||
* error!
|
||||
* In this case, casted_value still has 0xc1234567, but when it is compared
|
||||
* for equality against kernel_value, it is promoted to a 64-bit integer and
|
||||
* becomes 0xffffffffc1234567, which is different than 0x00000000c1234567.
|
||||
* Then, GLIBC assumes this is because the directory is very large.
|
||||
*
|
||||
* Given that all the above happens in user-space, we have no control over
|
||||
* it; therefore we must workaround the issue here. We do this by
|
||||
* truncating the pointer value to a 32-bit integer and hope that there
|
||||
* won't be collisions. In fact, this will not cause any problems in
|
||||
* 32-bit platforms but some might arise in 64-bit machines (I'm not sure
|
||||
* if they can happen at all in practice).
|
||||
*
|
||||
* XXX A nicer solution shall be attempted. */
|
||||
#ifdef _KERNEL
|
||||
#define TMPFS_DIRCOOKIE_DOT 0
|
||||
#define TMPFS_DIRCOOKIE_DOTDOT 1
|
||||
#define TMPFS_DIRCOOKIE_EOF 2
|
||||
static __inline
|
||||
off_t
|
||||
tmpfs_dircookie(struct tmpfs_dirent *de)
|
||||
{
|
||||
off_t cookie;
|
||||
* To preserve compatibility cookies are limited to 31 bits.
|
||||
*/
|
||||
|
||||
cookie = ((off_t)(uintptr_t)de >> 1) & 0x7FFFFFFF;
|
||||
MPASS(cookie != TMPFS_DIRCOOKIE_DOT);
|
||||
MPASS(cookie != TMPFS_DIRCOOKIE_DOTDOT);
|
||||
MPASS(cookie != TMPFS_DIRCOOKIE_EOF);
|
||||
|
||||
return cookie;
|
||||
}
|
||||
#endif
|
||||
#define TMPFS_DIRCOOKIE_DOT 0
|
||||
#define TMPFS_DIRCOOKIE_DOTDOT 1
|
||||
#define TMPFS_DIRCOOKIE_EOF 2
|
||||
#define TMPFS_DIRCOOKIE_MASK ((off_t)0x3fffffffU)
|
||||
#define TMPFS_DIRCOOKIE_MIN ((off_t)0x00000004U)
|
||||
#define TMPFS_DIRCOOKIE_DUP ((off_t)0x40000000U)
|
||||
#define TMPFS_DIRCOOKIE_DUPHEAD ((off_t)0x80000000U)
|
||||
#define TMPFS_DIRCOOKIE_DUP_MIN TMPFS_DIRCOOKIE_DUP
|
||||
#define TMPFS_DIRCOOKIE_DUP_MAX \
|
||||
(TMPFS_DIRCOOKIE_DUP | TMPFS_DIRCOOKIE_MASK)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
@ -243,29 +221,31 @@ struct tmpfs_node {
|
||||
dev_t tn_rdev;
|
||||
|
||||
/* Valid when tn_type == VDIR. */
|
||||
struct tn_dir{
|
||||
struct tn_dir {
|
||||
/* Pointer to the parent directory. The root
|
||||
* directory has a pointer to itself in this field;
|
||||
* this property identifies the root node. */
|
||||
struct tmpfs_node * tn_parent;
|
||||
|
||||
/* Head of a tail-queue that links the contents of
|
||||
* the directory together. See above for a
|
||||
* description of its contents. */
|
||||
/* Head of a tree that links the contents of
|
||||
* the directory together. */
|
||||
struct tmpfs_dir tn_dirhead;
|
||||
|
||||
/* Head of a list the contains fake directory entries
|
||||
* heads, i.e. entries with TMPFS_DIRCOOKIE_DUPHEAD
|
||||
* flag. */
|
||||
struct tmpfs_dir_duphead tn_dupindex;
|
||||
|
||||
/* Number and pointer of the first directory entry
|
||||
* returned by the readdir operation if it were
|
||||
* called again to continue reading data from the
|
||||
* same directory as before. This is used to speed
|
||||
* up reads of long directories, assuming that no
|
||||
* more than one read is in progress at a given time.
|
||||
* Otherwise, these values are discarded and a linear
|
||||
* scan is performed from the beginning up to the
|
||||
* point where readdir starts returning values. */
|
||||
* Otherwise, these values are discarded. */
|
||||
off_t tn_readdir_lastn;
|
||||
struct tmpfs_dirent * tn_readdir_lastp;
|
||||
}tn_dir;
|
||||
} tn_dir;
|
||||
|
||||
/* Valid when tn_type == VLNK. */
|
||||
/* The link's target, allocated from a string pool. */
|
||||
@ -419,9 +399,9 @@ int tmpfs_alloc_node(struct tmpfs_mount *, enum vtype,
|
||||
char *, dev_t, struct tmpfs_node **);
|
||||
void tmpfs_free_node(struct tmpfs_mount *, struct tmpfs_node *);
|
||||
int tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
|
||||
const char *, uint16_t, struct tmpfs_dirent **);
|
||||
void tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *,
|
||||
boolean_t);
|
||||
const char *, u_int, struct tmpfs_dirent **);
|
||||
void tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *);
|
||||
void tmpfs_dirent_init(struct tmpfs_dirent *, const char *, u_int);
|
||||
int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, int,
|
||||
struct vnode **);
|
||||
void tmpfs_free_vp(struct vnode *);
|
||||
@ -429,13 +409,12 @@ int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
|
||||
struct componentname *, char *);
|
||||
void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
|
||||
void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
|
||||
void tmpfs_dir_destroy(struct tmpfs_mount *, struct tmpfs_node *);
|
||||
struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node,
|
||||
struct tmpfs_node *f,
|
||||
struct componentname *cnp);
|
||||
int tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *);
|
||||
int tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *);
|
||||
struct tmpfs_dirent * tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t);
|
||||
int tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *);
|
||||
int tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, int,
|
||||
u_long *, int *);
|
||||
int tmpfs_dir_whiteout_add(struct vnode *, struct componentname *);
|
||||
void tmpfs_dir_whiteout_remove(struct vnode *, struct componentname *);
|
||||
int tmpfs_reg_resize(struct vnode *, off_t, boolean_t);
|
||||
@ -467,8 +446,8 @@ int tmpfs_truncate(struct vnode *, off_t);
|
||||
* with a length of 'len'.
|
||||
*/
|
||||
#define TMPFS_DIRENT_MATCHES(de, name, len) \
|
||||
(de->td_namelen == (uint16_t)len && \
|
||||
bcmp((de)->td_name, (name), (de)->td_namelen) == 0)
|
||||
(de->td_namelen == len && \
|
||||
bcmp((de)->ud.td_name, (name), (de)->td_namelen) == 0)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
@ -476,11 +455,10 @@ int tmpfs_truncate(struct vnode *, off_t);
|
||||
* Ensures that the node pointed by 'node' is a directory and that its
|
||||
* contents are consistent with respect to directories.
|
||||
*/
|
||||
#define TMPFS_VALIDATE_DIR(node) \
|
||||
MPASS((node)->tn_type == VDIR); \
|
||||
MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
|
||||
MPASS((node)->tn_dir.tn_readdir_lastp == NULL || \
|
||||
tmpfs_dircookie((node)->tn_dir.tn_readdir_lastp) == (node)->tn_dir.tn_readdir_lastn);
|
||||
#define TMPFS_VALIDATE_DIR(node) do { \
|
||||
MPASS((node)->tn_type == VDIR); \
|
||||
MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
|
||||
} while (0)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/fnv_hash.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
@ -58,6 +59,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <fs/tmpfs/tmpfs_fifoops.h>
|
||||
#include <fs/tmpfs/tmpfs_vnops.h>
|
||||
|
||||
struct tmpfs_dir_cursor {
|
||||
struct tmpfs_dirent *tdc_current;
|
||||
struct tmpfs_dirent *tdc_tree;
|
||||
};
|
||||
|
||||
SYSCTL_NODE(_vfs, OID_AUTO, tmpfs, CTLFLAG_RW, 0, "tmpfs file system");
|
||||
|
||||
static long tmpfs_pages_reserved = TMPFS_PAGES_MINRESERVED;
|
||||
@ -87,6 +93,10 @@ SYSCTL_PROC(_vfs_tmpfs, OID_AUTO, memory_reserved, CTLTYPE_LONG|CTLFLAG_RW,
|
||||
&tmpfs_pages_reserved, 0, sysctl_mem_reserved, "L",
|
||||
"Amount of available memory and swap below which tmpfs growth stops");
|
||||
|
||||
static __inline int tmpfs_dirtree_cmp(struct tmpfs_dirent *a,
|
||||
struct tmpfs_dirent *b);
|
||||
RB_PROTOTYPE_STATIC(tmpfs_dir, tmpfs_dirent, uh.td_entries, tmpfs_dirtree_cmp);
|
||||
|
||||
size_t
|
||||
tmpfs_mem_avail(void)
|
||||
{
|
||||
@ -188,7 +198,8 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp, enum vtype type,
|
||||
break;
|
||||
|
||||
case VDIR:
|
||||
TAILQ_INIT(&nnode->tn_dir.tn_dirhead);
|
||||
RB_INIT(&nnode->tn_dir.tn_dirhead);
|
||||
LIST_INIT(&nnode->tn_dir.tn_dupindex);
|
||||
MPASS(parent != nnode);
|
||||
MPASS(IMPLIES(parent == NULL, tmp->tm_root == NULL));
|
||||
nnode->tn_dir.tn_parent = (parent == NULL) ? nnode : parent;
|
||||
@ -309,6 +320,49 @@ tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static __inline uint32_t
|
||||
tmpfs_dirent_hash(const char *name, u_int len)
|
||||
{
|
||||
uint32_t hash;
|
||||
|
||||
hash = fnv_32_buf(name, len, FNV1_32_INIT + len) & TMPFS_DIRCOOKIE_MASK;
|
||||
#ifdef TMPFS_DEBUG_DIRCOOKIE_DUP
|
||||
hash &= 0xf;
|
||||
#endif
|
||||
if (hash < TMPFS_DIRCOOKIE_MIN)
|
||||
hash += TMPFS_DIRCOOKIE_MIN;
|
||||
|
||||
return (hash);
|
||||
}
|
||||
|
||||
static __inline off_t
|
||||
tmpfs_dirent_cookie(struct tmpfs_dirent *de)
|
||||
{
|
||||
MPASS(de->td_cookie >= TMPFS_DIRCOOKIE_MIN);
|
||||
|
||||
return (de->td_cookie);
|
||||
}
|
||||
|
||||
static __inline boolean_t
|
||||
tmpfs_dirent_dup(struct tmpfs_dirent *de)
|
||||
{
|
||||
return ((de->td_cookie & TMPFS_DIRCOOKIE_DUP) != 0);
|
||||
}
|
||||
|
||||
static __inline boolean_t
|
||||
tmpfs_dirent_duphead(struct tmpfs_dirent *de)
|
||||
{
|
||||
return ((de->td_cookie & TMPFS_DIRCOOKIE_DUPHEAD) != 0);
|
||||
}
|
||||
|
||||
void
|
||||
tmpfs_dirent_init(struct tmpfs_dirent *de, const char *name, u_int namelen)
|
||||
{
|
||||
de->td_hash = de->td_cookie = tmpfs_dirent_hash(name, namelen);
|
||||
memcpy(de->ud.td_name, name, namelen);
|
||||
de->td_namelen = namelen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocates a new directory entry for the node node with a name of name.
|
||||
* The new directory entry is returned in *de.
|
||||
@ -320,17 +374,17 @@ tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node)
|
||||
*/
|
||||
int
|
||||
tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node,
|
||||
const char *name, uint16_t len, struct tmpfs_dirent **de)
|
||||
const char *name, u_int len, struct tmpfs_dirent **de)
|
||||
{
|
||||
struct tmpfs_dirent *nde;
|
||||
|
||||
nde = (struct tmpfs_dirent *)uma_zalloc(
|
||||
tmp->tm_dirent_pool, M_WAITOK);
|
||||
nde->td_name = malloc(len, M_TMPFSNAME, M_WAITOK);
|
||||
nde->td_namelen = len;
|
||||
memcpy(nde->td_name, name, len);
|
||||
|
||||
nde = uma_zalloc(tmp->tm_dirent_pool, M_WAITOK);
|
||||
nde->td_node = node;
|
||||
if (name != NULL) {
|
||||
nde->ud.td_name = malloc(len, M_TMPFSNAME, M_WAITOK);
|
||||
tmpfs_dirent_init(nde, name, len);
|
||||
} else
|
||||
nde->td_namelen = 0;
|
||||
if (node != NULL)
|
||||
node->tn_links++;
|
||||
|
||||
@ -351,20 +405,17 @@ tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node,
|
||||
* directory entry, as it may already have been released from the outside.
|
||||
*/
|
||||
void
|
||||
tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de,
|
||||
boolean_t node_exists)
|
||||
tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de)
|
||||
{
|
||||
if (node_exists) {
|
||||
struct tmpfs_node *node;
|
||||
struct tmpfs_node *node;
|
||||
|
||||
node = de->td_node;
|
||||
if (node != NULL) {
|
||||
MPASS(node->tn_links > 0);
|
||||
node->tn_links--;
|
||||
}
|
||||
node = de->td_node;
|
||||
if (node != NULL) {
|
||||
MPASS(node->tn_links > 0);
|
||||
node->tn_links--;
|
||||
}
|
||||
|
||||
free(de->td_name, M_TMPFSNAME);
|
||||
if (!tmpfs_dirent_duphead(de) && de->ud.td_name != NULL)
|
||||
free(de->ud.td_name, M_TMPFSNAME);
|
||||
uma_zfree(tmp->tm_dirent_pool, de);
|
||||
}
|
||||
|
||||
@ -586,7 +637,7 @@ tmpfs_alloc_file(struct vnode *dvp, struct vnode **vpp, struct vattr *vap,
|
||||
/* Allocate a vnode for the new file. */
|
||||
error = tmpfs_alloc_vp(dvp->v_mount, node, LK_EXCLUSIVE, vpp);
|
||||
if (error != 0) {
|
||||
tmpfs_free_dirent(tmp, de, TRUE);
|
||||
tmpfs_free_dirent(tmp, de);
|
||||
tmpfs_free_node(tmp, node);
|
||||
goto out;
|
||||
}
|
||||
@ -605,6 +656,215 @@ out:
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static struct tmpfs_dirent *
|
||||
tmpfs_dir_first(struct tmpfs_node *dnode, struct tmpfs_dir_cursor *dc)
|
||||
{
|
||||
struct tmpfs_dirent *de;
|
||||
|
||||
de = RB_MIN(tmpfs_dir, &dnode->tn_dir.tn_dirhead);
|
||||
dc->tdc_tree = de;
|
||||
if (de != NULL && tmpfs_dirent_duphead(de))
|
||||
de = LIST_FIRST(&de->ud.td_duphead);
|
||||
dc->tdc_current = de;
|
||||
|
||||
return (dc->tdc_current);
|
||||
}
|
||||
|
||||
static struct tmpfs_dirent *
|
||||
tmpfs_dir_next(struct tmpfs_node *dnode, struct tmpfs_dir_cursor *dc)
|
||||
{
|
||||
struct tmpfs_dirent *de;
|
||||
|
||||
MPASS(dc->tdc_tree != NULL);
|
||||
if (tmpfs_dirent_dup(dc->tdc_current)) {
|
||||
dc->tdc_current = LIST_NEXT(dc->tdc_current, uh.td_dup.entries);
|
||||
if (dc->tdc_current != NULL)
|
||||
return (dc->tdc_current);
|
||||
}
|
||||
dc->tdc_tree = dc->tdc_current = RB_NEXT(tmpfs_dir,
|
||||
&dnode->tn_dir.tn_dirhead, dc->tdc_tree);
|
||||
if ((de = dc->tdc_current) != NULL && tmpfs_dirent_duphead(de)) {
|
||||
dc->tdc_current = LIST_FIRST(&de->ud.td_duphead);
|
||||
MPASS(dc->tdc_current != NULL);
|
||||
}
|
||||
|
||||
return (dc->tdc_current);
|
||||
}
|
||||
|
||||
/* Lookup directory entry in RB-Tree. Function may return duphead entry. */
|
||||
static struct tmpfs_dirent *
|
||||
tmpfs_dir_xlookup_hash(struct tmpfs_node *dnode, uint32_t hash)
|
||||
{
|
||||
struct tmpfs_dirent *de, dekey;
|
||||
|
||||
dekey.td_hash = hash;
|
||||
de = RB_FIND(tmpfs_dir, &dnode->tn_dir.tn_dirhead, &dekey);
|
||||
return (de);
|
||||
}
|
||||
|
||||
/* Lookup directory entry by cookie, initialize directory cursor accordingly. */
|
||||
static struct tmpfs_dirent *
|
||||
tmpfs_dir_lookup_cookie(struct tmpfs_node *node, off_t cookie,
|
||||
struct tmpfs_dir_cursor *dc)
|
||||
{
|
||||
struct tmpfs_dir *dirhead = &node->tn_dir.tn_dirhead;
|
||||
struct tmpfs_dirent *de, dekey;
|
||||
|
||||
MPASS(cookie >= TMPFS_DIRCOOKIE_MIN);
|
||||
|
||||
if (cookie == node->tn_dir.tn_readdir_lastn &&
|
||||
(de = node->tn_dir.tn_readdir_lastp) != NULL) {
|
||||
/* Protect against possible race, tn_readdir_last[pn]
|
||||
* may be updated with only shared vnode lock held. */
|
||||
if (cookie == tmpfs_dirent_cookie(de))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((cookie & TMPFS_DIRCOOKIE_DUP) != 0) {
|
||||
LIST_FOREACH(de, &node->tn_dir.tn_dupindex,
|
||||
uh.td_dup.index_entries) {
|
||||
MPASS(tmpfs_dirent_dup(de));
|
||||
if (de->td_cookie == cookie)
|
||||
goto out;
|
||||
/* dupindex list is sorted. */
|
||||
if (de->td_cookie < cookie) {
|
||||
de = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
MPASS(de == NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
MPASS((cookie & TMPFS_DIRCOOKIE_MASK) == cookie);
|
||||
dekey.td_hash = cookie;
|
||||
/* Recover if direntry for cookie was removed */
|
||||
de = RB_NFIND(tmpfs_dir, dirhead, &dekey);
|
||||
dc->tdc_tree = de;
|
||||
dc->tdc_current = de;
|
||||
if (de != NULL && tmpfs_dirent_duphead(de)) {
|
||||
dc->tdc_current = LIST_FIRST(&de->ud.td_duphead);
|
||||
MPASS(dc->tdc_current != NULL);
|
||||
}
|
||||
return (dc->tdc_current);
|
||||
|
||||
out:
|
||||
dc->tdc_tree = de;
|
||||
dc->tdc_current = de;
|
||||
if (de != NULL && tmpfs_dirent_dup(de))
|
||||
dc->tdc_tree = tmpfs_dir_xlookup_hash(node,
|
||||
de->td_hash);
|
||||
return (dc->tdc_current);
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks for a directory entry in the directory represented by node.
|
||||
* 'cnp' describes the name of the entry to look for. Note that the .
|
||||
* and .. components are not allowed as they do not physically exist
|
||||
* within directories.
|
||||
*
|
||||
* Returns a pointer to the entry when found, otherwise NULL.
|
||||
*/
|
||||
struct tmpfs_dirent *
|
||||
tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f,
|
||||
struct componentname *cnp)
|
||||
{
|
||||
struct tmpfs_dir_duphead *duphead;
|
||||
struct tmpfs_dirent *de;
|
||||
uint32_t hash;
|
||||
|
||||
MPASS(IMPLIES(cnp->cn_namelen == 1, cnp->cn_nameptr[0] != '.'));
|
||||
MPASS(IMPLIES(cnp->cn_namelen == 2, !(cnp->cn_nameptr[0] == '.' &&
|
||||
cnp->cn_nameptr[1] == '.')));
|
||||
TMPFS_VALIDATE_DIR(node);
|
||||
|
||||
hash = tmpfs_dirent_hash(cnp->cn_nameptr, cnp->cn_namelen);
|
||||
de = tmpfs_dir_xlookup_hash(node, hash);
|
||||
if (de != NULL && tmpfs_dirent_duphead(de)) {
|
||||
duphead = &de->ud.td_duphead;
|
||||
LIST_FOREACH(de, duphead, uh.td_dup.entries) {
|
||||
if (TMPFS_DIRENT_MATCHES(de, cnp->cn_nameptr,
|
||||
cnp->cn_namelen))
|
||||
break;
|
||||
}
|
||||
} else if (de != NULL) {
|
||||
if (!TMPFS_DIRENT_MATCHES(de, cnp->cn_nameptr,
|
||||
cnp->cn_namelen))
|
||||
de = NULL;
|
||||
}
|
||||
if (de != NULL && f != NULL && de->td_node != f)
|
||||
de = NULL;
|
||||
|
||||
return (de);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach duplicate-cookie directory entry nde to dnode and insert to dupindex
|
||||
* list, allocate new cookie value.
|
||||
*/
|
||||
static void
|
||||
tmpfs_dir_attach_dup(struct tmpfs_node *dnode,
|
||||
struct tmpfs_dir_duphead *duphead, struct tmpfs_dirent *nde)
|
||||
{
|
||||
struct tmpfs_dir_duphead *dupindex;
|
||||
struct tmpfs_dirent *de, *pde;
|
||||
|
||||
dupindex = &dnode->tn_dir.tn_dupindex;
|
||||
de = LIST_FIRST(dupindex);
|
||||
if (de == NULL || de->td_cookie < TMPFS_DIRCOOKIE_DUP_MAX) {
|
||||
if (de == NULL)
|
||||
nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MIN;
|
||||
else
|
||||
nde->td_cookie = de->td_cookie + 1;
|
||||
MPASS(tmpfs_dirent_dup(nde));
|
||||
LIST_INSERT_HEAD(dupindex, nde, uh.td_dup.index_entries);
|
||||
LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cookie numbers are near exhaustion. Scan dupindex list for unused
|
||||
* numbers. dupindex list is sorted in descending order. Keep it so
|
||||
* after inserting nde.
|
||||
*/
|
||||
while (1) {
|
||||
pde = de;
|
||||
de = LIST_NEXT(de, uh.td_dup.index_entries);
|
||||
if (de == NULL && pde->td_cookie != TMPFS_DIRCOOKIE_DUP_MIN) {
|
||||
/*
|
||||
* Last element of the index doesn't have minimal cookie
|
||||
* value, use it.
|
||||
*/
|
||||
nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MIN;
|
||||
LIST_INSERT_AFTER(pde, nde, uh.td_dup.index_entries);
|
||||
LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries);
|
||||
return;
|
||||
} else if (de == NULL) {
|
||||
/*
|
||||
* We are so lucky have 2^30 hash duplicates in single
|
||||
* directory :) Return largest possible cookie value.
|
||||
* It should be fine except possible issues with
|
||||
* VOP_READDIR restart.
|
||||
*/
|
||||
nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MAX;
|
||||
LIST_INSERT_HEAD(dupindex, nde,
|
||||
uh.td_dup.index_entries);
|
||||
LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries);
|
||||
return;
|
||||
}
|
||||
if (de->td_cookie + 1 == pde->td_cookie ||
|
||||
de->td_cookie >= TMPFS_DIRCOOKIE_DUP_MAX)
|
||||
continue; /* No hole or invalid cookie. */
|
||||
nde->td_cookie = de->td_cookie + 1;
|
||||
MPASS(tmpfs_dirent_dup(nde));
|
||||
MPASS(pde->td_cookie > nde->td_cookie);
|
||||
MPASS(nde->td_cookie > de->td_cookie);
|
||||
LIST_INSERT_BEFORE(de, nde, uh.td_dup.index_entries);
|
||||
LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries);
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Attaches the directory entry de to the directory represented by vp.
|
||||
* Note that this does not change the link count of the node pointed by
|
||||
@ -614,10 +874,38 @@ void
|
||||
tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de)
|
||||
{
|
||||
struct tmpfs_node *dnode;
|
||||
struct tmpfs_dirent *xde, *nde;
|
||||
|
||||
ASSERT_VOP_ELOCKED(vp, __func__);
|
||||
MPASS(de->td_namelen > 0);
|
||||
MPASS(de->td_hash >= TMPFS_DIRCOOKIE_MIN);
|
||||
MPASS(de->td_cookie == de->td_hash);
|
||||
|
||||
dnode = VP_TO_TMPFS_DIR(vp);
|
||||
TAILQ_INSERT_TAIL(&dnode->tn_dir.tn_dirhead, de, td_entries);
|
||||
dnode->tn_dir.tn_readdir_lastn = 0;
|
||||
dnode->tn_dir.tn_readdir_lastp = NULL;
|
||||
|
||||
MPASS(!tmpfs_dirent_dup(de));
|
||||
xde = RB_INSERT(tmpfs_dir, &dnode->tn_dir.tn_dirhead, de);
|
||||
if (xde != NULL && tmpfs_dirent_duphead(xde))
|
||||
tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, de);
|
||||
else if (xde != NULL) {
|
||||
/*
|
||||
* Allocate new duphead. Swap xde with duphead to avoid
|
||||
* adding/removing elements with the same hash.
|
||||
*/
|
||||
MPASS(!tmpfs_dirent_dup(xde));
|
||||
tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), NULL, NULL, 0,
|
||||
&nde);
|
||||
/* *nde = *xde; XXX gcc 4.2.1 may generate invalid code. */
|
||||
memcpy(nde, xde, sizeof(*xde));
|
||||
xde->td_cookie |= TMPFS_DIRCOOKIE_DUPHEAD;
|
||||
LIST_INIT(&xde->ud.td_duphead);
|
||||
xde->td_namelen = 0;
|
||||
xde->td_node = NULL;
|
||||
tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, nde);
|
||||
tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, de);
|
||||
}
|
||||
dnode->tn_size += sizeof(struct tmpfs_dirent);
|
||||
dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
|
||||
TMPFS_NODE_MODIFIED;
|
||||
@ -633,58 +921,61 @@ tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de)
|
||||
void
|
||||
tmpfs_dir_detach(struct vnode *vp, struct tmpfs_dirent *de)
|
||||
{
|
||||
struct tmpfs_mount *tmp;
|
||||
struct tmpfs_dir *head;
|
||||
struct tmpfs_node *dnode;
|
||||
struct tmpfs_dirent *xde;
|
||||
|
||||
ASSERT_VOP_ELOCKED(vp, __func__);
|
||||
|
||||
dnode = VP_TO_TMPFS_DIR(vp);
|
||||
head = &dnode->tn_dir.tn_dirhead;
|
||||
dnode->tn_dir.tn_readdir_lastn = 0;
|
||||
dnode->tn_dir.tn_readdir_lastp = NULL;
|
||||
|
||||
if (dnode->tn_dir.tn_readdir_lastp == de) {
|
||||
dnode->tn_dir.tn_readdir_lastn = 0;
|
||||
dnode->tn_dir.tn_readdir_lastp = NULL;
|
||||
}
|
||||
if (tmpfs_dirent_dup(de)) {
|
||||
/* Remove duphead if de was last entry. */
|
||||
if (LIST_NEXT(de, uh.td_dup.entries) == NULL) {
|
||||
xde = tmpfs_dir_xlookup_hash(dnode, de->td_hash);
|
||||
MPASS(tmpfs_dirent_duphead(xde));
|
||||
} else
|
||||
xde = NULL;
|
||||
LIST_REMOVE(de, uh.td_dup.entries);
|
||||
LIST_REMOVE(de, uh.td_dup.index_entries);
|
||||
if (xde != NULL) {
|
||||
if (LIST_EMPTY(&xde->ud.td_duphead)) {
|
||||
RB_REMOVE(tmpfs_dir, head, xde);
|
||||
tmp = VFS_TO_TMPFS(vp->v_mount);
|
||||
MPASS(xde->td_node == NULL);
|
||||
tmpfs_free_dirent(tmp, xde);
|
||||
}
|
||||
}
|
||||
} else
|
||||
RB_REMOVE(tmpfs_dir, head, de);
|
||||
|
||||
TAILQ_REMOVE(&dnode->tn_dir.tn_dirhead, de, td_entries);
|
||||
dnode->tn_size -= sizeof(struct tmpfs_dirent);
|
||||
dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
|
||||
TMPFS_NODE_MODIFIED;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Looks for a directory entry in the directory represented by node.
|
||||
* 'cnp' describes the name of the entry to look for. Note that the .
|
||||
* and .. components are not allowed as they do not physically exist
|
||||
* within directories.
|
||||
*
|
||||
* Returns a pointer to the entry when found, otherwise NULL.
|
||||
*/
|
||||
struct tmpfs_dirent *
|
||||
tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f,
|
||||
struct componentname *cnp)
|
||||
void
|
||||
tmpfs_dir_destroy(struct tmpfs_mount *tmp, struct tmpfs_node *dnode)
|
||||
{
|
||||
boolean_t found;
|
||||
struct tmpfs_dirent *de;
|
||||
struct tmpfs_dirent *de, *dde, *nde;
|
||||
|
||||
MPASS(IMPLIES(cnp->cn_namelen == 1, cnp->cn_nameptr[0] != '.'));
|
||||
MPASS(IMPLIES(cnp->cn_namelen == 2, !(cnp->cn_nameptr[0] == '.' &&
|
||||
cnp->cn_nameptr[1] == '.')));
|
||||
TMPFS_VALIDATE_DIR(node);
|
||||
|
||||
found = 0;
|
||||
TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) {
|
||||
if (f != NULL && de->td_node != f)
|
||||
continue;
|
||||
MPASS(cnp->cn_namelen < 0xffff);
|
||||
if (de->td_namelen == (uint16_t)cnp->cn_namelen &&
|
||||
bcmp(de->td_name, cnp->cn_nameptr, de->td_namelen) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
RB_FOREACH_SAFE(de, tmpfs_dir, &dnode->tn_dir.tn_dirhead, nde) {
|
||||
RB_REMOVE(tmpfs_dir, &dnode->tn_dir.tn_dirhead, de);
|
||||
/* Node may already be destroyed. */
|
||||
de->td_node = NULL;
|
||||
if (tmpfs_dirent_duphead(de)) {
|
||||
while ((dde = LIST_FIRST(&de->ud.td_duphead)) != NULL) {
|
||||
LIST_REMOVE(dde, uh.td_dup.entries);
|
||||
dde->td_node = NULL;
|
||||
tmpfs_free_dirent(tmp, dde);
|
||||
}
|
||||
}
|
||||
tmpfs_free_dirent(tmp, de);
|
||||
}
|
||||
node->tn_status |= TMPFS_NODE_ACCESSED;
|
||||
|
||||
return found ? de : NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -696,7 +987,7 @@ tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f,
|
||||
* hold the directory entry or an appropriate error code if another
|
||||
* error happens.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
tmpfs_dir_getdotdent(struct tmpfs_node *node, struct uio *uio)
|
||||
{
|
||||
int error;
|
||||
@ -713,12 +1004,9 @@ tmpfs_dir_getdotdent(struct tmpfs_node *node, struct uio *uio)
|
||||
dent.d_reclen = GENERIC_DIRSIZ(&dent);
|
||||
|
||||
if (dent.d_reclen > uio->uio_resid)
|
||||
error = -1;
|
||||
else {
|
||||
error = EJUSTRETURN;
|
||||
else
|
||||
error = uiomove(&dent, dent.d_reclen, uio);
|
||||
if (error == 0)
|
||||
uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT;
|
||||
}
|
||||
|
||||
node->tn_status |= TMPFS_NODE_ACCESSED;
|
||||
|
||||
@ -734,7 +1022,7 @@ tmpfs_dir_getdotdent(struct tmpfs_node *node, struct uio *uio)
|
||||
* hold the directory entry or an appropriate error code if another
|
||||
* error happens.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio)
|
||||
{
|
||||
int error;
|
||||
@ -763,19 +1051,9 @@ tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio)
|
||||
dent.d_reclen = GENERIC_DIRSIZ(&dent);
|
||||
|
||||
if (dent.d_reclen > uio->uio_resid)
|
||||
error = -1;
|
||||
else {
|
||||
error = EJUSTRETURN;
|
||||
else
|
||||
error = uiomove(&dent, dent.d_reclen, uio);
|
||||
if (error == 0) {
|
||||
struct tmpfs_dirent *de;
|
||||
|
||||
de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
|
||||
if (de == NULL)
|
||||
uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
|
||||
else
|
||||
uio->uio_offset = tmpfs_dircookie(de);
|
||||
}
|
||||
}
|
||||
|
||||
node->tn_status |= TMPFS_NODE_ACCESSED;
|
||||
|
||||
@ -784,30 +1062,6 @@ tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Lookup a directory entry by its associated cookie.
|
||||
*/
|
||||
struct tmpfs_dirent *
|
||||
tmpfs_dir_lookupbycookie(struct tmpfs_node *node, off_t cookie)
|
||||
{
|
||||
struct tmpfs_dirent *de;
|
||||
|
||||
if (cookie == node->tn_dir.tn_readdir_lastn &&
|
||||
node->tn_dir.tn_readdir_lastp != NULL) {
|
||||
return node->tn_dir.tn_readdir_lastp;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) {
|
||||
if (tmpfs_dircookie(de) == cookie) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return de;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Helper function for tmpfs_readdir. Returns as much directory entries
|
||||
* as can fit in the uio space. The read starts at uio->uio_offset.
|
||||
@ -816,27 +1070,47 @@ tmpfs_dir_lookupbycookie(struct tmpfs_node *node, off_t cookie)
|
||||
* error code if another error happens.
|
||||
*/
|
||||
int
|
||||
tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp)
|
||||
tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt,
|
||||
u_long *cookies, int *ncookies)
|
||||
{
|
||||
int error;
|
||||
off_t startcookie;
|
||||
struct tmpfs_dir_cursor dc;
|
||||
struct tmpfs_dirent *de;
|
||||
off_t off;
|
||||
int error;
|
||||
|
||||
TMPFS_VALIDATE_DIR(node);
|
||||
|
||||
/* Locate the first directory entry we have to return. We have cached
|
||||
* the last readdir in the node, so use those values if appropriate.
|
||||
* Otherwise do a linear scan to find the requested entry. */
|
||||
startcookie = uio->uio_offset;
|
||||
MPASS(startcookie != TMPFS_DIRCOOKIE_DOT);
|
||||
MPASS(startcookie != TMPFS_DIRCOOKIE_DOTDOT);
|
||||
if (startcookie == TMPFS_DIRCOOKIE_EOF) {
|
||||
return 0;
|
||||
} else {
|
||||
de = tmpfs_dir_lookupbycookie(node, startcookie);
|
||||
}
|
||||
if (de == NULL) {
|
||||
return EINVAL;
|
||||
off = 0;
|
||||
switch (uio->uio_offset) {
|
||||
case TMPFS_DIRCOOKIE_DOT:
|
||||
error = tmpfs_dir_getdotdent(node, uio);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT;
|
||||
if (cnt != 0)
|
||||
cookies[(*ncookies)++] = off = uio->uio_offset;
|
||||
case TMPFS_DIRCOOKIE_DOTDOT:
|
||||
error = tmpfs_dir_getdotdotdent(node, uio);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
de = tmpfs_dir_first(node, &dc);
|
||||
if (de == NULL)
|
||||
uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
|
||||
else
|
||||
uio->uio_offset = tmpfs_dirent_cookie(de);
|
||||
if (cnt != 0)
|
||||
cookies[(*ncookies)++] = off = uio->uio_offset;
|
||||
if (de == NULL)
|
||||
return (0);
|
||||
break;
|
||||
case TMPFS_DIRCOOKIE_EOF:
|
||||
return (0);
|
||||
default:
|
||||
de = tmpfs_dir_lookup_cookie(node, uio->uio_offset, &dc);
|
||||
if (de == NULL)
|
||||
return (EINVAL);
|
||||
if (cnt != 0)
|
||||
off = tmpfs_dirent_cookie(de);
|
||||
}
|
||||
|
||||
/* Read as much entries as possible; i.e., until we reach the end of
|
||||
@ -887,14 +1161,14 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp)
|
||||
}
|
||||
d.d_namlen = de->td_namelen;
|
||||
MPASS(de->td_namelen < sizeof(d.d_name));
|
||||
(void)memcpy(d.d_name, de->td_name, de->td_namelen);
|
||||
(void)memcpy(d.d_name, de->ud.td_name, de->td_namelen);
|
||||
d.d_name[de->td_namelen] = '\0';
|
||||
d.d_reclen = GENERIC_DIRSIZ(&d);
|
||||
|
||||
/* Stop reading if the directory entry we are treating is
|
||||
* bigger than the amount of data that can be returned. */
|
||||
if (d.d_reclen > uio->uio_resid) {
|
||||
error = -1;
|
||||
error = EJUSTRETURN;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -902,21 +1176,30 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp)
|
||||
* advance pointers. */
|
||||
error = uiomove(&d, d.d_reclen, uio);
|
||||
if (error == 0) {
|
||||
(*cntp)++;
|
||||
de = TAILQ_NEXT(de, td_entries);
|
||||
de = tmpfs_dir_next(node, &dc);
|
||||
if (cnt != 0) {
|
||||
if (de == NULL)
|
||||
off = TMPFS_DIRCOOKIE_EOF;
|
||||
else
|
||||
off = tmpfs_dirent_cookie(de);
|
||||
MPASS(*ncookies < cnt);
|
||||
cookies[(*ncookies)++] = off;
|
||||
}
|
||||
}
|
||||
} while (error == 0 && uio->uio_resid > 0 && de != NULL);
|
||||
|
||||
/* Update the offset and cache. */
|
||||
if (de == NULL) {
|
||||
uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
|
||||
node->tn_dir.tn_readdir_lastn = 0;
|
||||
node->tn_dir.tn_readdir_lastp = NULL;
|
||||
} else {
|
||||
node->tn_dir.tn_readdir_lastn = uio->uio_offset = tmpfs_dircookie(de);
|
||||
node->tn_dir.tn_readdir_lastp = de;
|
||||
if (cnt == 0) {
|
||||
if (de == NULL)
|
||||
off = TMPFS_DIRCOOKIE_EOF;
|
||||
else
|
||||
off = tmpfs_dirent_cookie(de);
|
||||
}
|
||||
|
||||
uio->uio_offset = off;
|
||||
node->tn_dir.tn_readdir_lastn = off;
|
||||
node->tn_dir.tn_readdir_lastp = de;
|
||||
|
||||
node->tn_status |= TMPFS_NODE_ACCESSED;
|
||||
return error;
|
||||
}
|
||||
@ -943,7 +1226,7 @@ tmpfs_dir_whiteout_remove(struct vnode *dvp, struct componentname *cnp)
|
||||
de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(dvp), NULL, cnp);
|
||||
MPASS(de != NULL && de->td_node == NULL);
|
||||
tmpfs_dir_detach(dvp, de);
|
||||
tmpfs_free_dirent(VFS_TO_TMPFS(dvp->v_mount), de, TRUE);
|
||||
tmpfs_free_dirent(VFS_TO_TMPFS(dvp->v_mount), de);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
@ -1436,3 +1719,15 @@ out:
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
tmpfs_dirtree_cmp(struct tmpfs_dirent *a, struct tmpfs_dirent *b)
|
||||
{
|
||||
if (a->td_hash > b->td_hash)
|
||||
return (1);
|
||||
else if (a->td_hash < b->td_hash)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
RB_GENERATE_STATIC(tmpfs_dir, tmpfs_dirent, uh.td_entries, tmpfs_dirtree_cmp);
|
||||
|
@ -294,19 +294,8 @@ tmpfs_unmount(struct mount *mp, int mntflags)
|
||||
while (node != NULL) {
|
||||
struct tmpfs_node *next;
|
||||
|
||||
if (node->tn_type == VDIR) {
|
||||
struct tmpfs_dirent *de;
|
||||
|
||||
de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
|
||||
while (de != NULL) {
|
||||
struct tmpfs_dirent *nde;
|
||||
|
||||
nde = TAILQ_NEXT(de, td_entries);
|
||||
tmpfs_free_dirent(tmp, de, FALSE);
|
||||
de = nde;
|
||||
node->tn_size -= sizeof(struct tmpfs_dirent);
|
||||
}
|
||||
}
|
||||
if (node->tn_type == VDIR)
|
||||
tmpfs_dir_destroy(tmp, node);
|
||||
|
||||
next = LIST_NEXT(node, tn_entries);
|
||||
tmpfs_free_node(tmp, node);
|
||||
|
@ -847,7 +847,7 @@ tmpfs_remove(struct vop_remove_args *v)
|
||||
/* Free the directory entry we just deleted. Note that the node
|
||||
* referred by it will not be removed until the vnode is really
|
||||
* reclaimed. */
|
||||
tmpfs_free_dirent(tmp, de, TRUE);
|
||||
tmpfs_free_dirent(tmp, de);
|
||||
|
||||
node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED;
|
||||
error = 0;
|
||||
@ -1263,26 +1263,25 @@ tmpfs_rename(struct vop_rename_args *v)
|
||||
fdnode->tn_links--;
|
||||
TMPFS_NODE_UNLOCK(fdnode);
|
||||
}
|
||||
|
||||
/* Do the move: just remove the entry from the source directory
|
||||
* and insert it into the target one. */
|
||||
tmpfs_dir_detach(fdvp, de);
|
||||
if (fcnp->cn_flags & DOWHITEOUT)
|
||||
tmpfs_dir_whiteout_add(fdvp, fcnp);
|
||||
if (tcnp->cn_flags & ISWHITEOUT)
|
||||
tmpfs_dir_whiteout_remove(tdvp, tcnp);
|
||||
tmpfs_dir_attach(tdvp, de);
|
||||
}
|
||||
|
||||
/* Do the move: just remove the entry from the source directory
|
||||
* and insert it into the target one. */
|
||||
tmpfs_dir_detach(fdvp, de);
|
||||
|
||||
if (fcnp->cn_flags & DOWHITEOUT)
|
||||
tmpfs_dir_whiteout_add(fdvp, fcnp);
|
||||
if (tcnp->cn_flags & ISWHITEOUT)
|
||||
tmpfs_dir_whiteout_remove(tdvp, tcnp);
|
||||
|
||||
/* If the name has changed, we need to make it effective by changing
|
||||
* it in the directory entry. */
|
||||
if (newname != NULL) {
|
||||
MPASS(tcnp->cn_namelen <= MAXNAMLEN);
|
||||
|
||||
free(de->td_name, M_TMPFSNAME);
|
||||
de->td_namelen = (uint16_t)tcnp->cn_namelen;
|
||||
memcpy(newname, tcnp->cn_nameptr, tcnp->cn_namelen);
|
||||
de->td_name = newname;
|
||||
free(de->ud.td_name, M_TMPFSNAME);
|
||||
de->ud.td_name = newname;
|
||||
tmpfs_dirent_init(de, tcnp->cn_nameptr, tcnp->cn_namelen);
|
||||
|
||||
fnode->tn_status |= TMPFS_NODE_CHANGED;
|
||||
tdnode->tn_status |= TMPFS_NODE_MODIFIED;
|
||||
@ -1291,15 +1290,20 @@ tmpfs_rename(struct vop_rename_args *v)
|
||||
/* If we are overwriting an entry, we have to remove the old one
|
||||
* from the target directory. */
|
||||
if (tvp != NULL) {
|
||||
struct tmpfs_dirent *tde;
|
||||
|
||||
/* Remove the old entry from the target directory. */
|
||||
de = tmpfs_dir_lookup(tdnode, tnode, tcnp);
|
||||
tmpfs_dir_detach(tdvp, de);
|
||||
tde = tmpfs_dir_lookup(tdnode, tnode, tcnp);
|
||||
tmpfs_dir_detach(tdvp, tde);
|
||||
|
||||
/* Free the directory entry we just deleted. Note that the
|
||||
* node referred by it will not be removed until the vnode is
|
||||
* really reclaimed. */
|
||||
tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), de, TRUE);
|
||||
tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), tde);
|
||||
}
|
||||
|
||||
tmpfs_dir_attach(tdvp, de);
|
||||
|
||||
cache_purge(fvp);
|
||||
if (tvp != NULL)
|
||||
cache_purge(tvp);
|
||||
@ -1427,7 +1431,7 @@ tmpfs_rmdir(struct vop_rmdir_args *v)
|
||||
/* Free the directory entry we just deleted. Note that the node
|
||||
* referred by it will not be removed until the vnode is really
|
||||
* reclaimed. */
|
||||
tmpfs_free_dirent(tmp, de, TRUE);
|
||||
tmpfs_free_dirent(tmp, de);
|
||||
|
||||
/* Release the deleted vnode (will destroy the node, notify
|
||||
* interested parties and clean it from the cache). */
|
||||
@ -1473,8 +1477,8 @@ tmpfs_readdir(struct vop_readdir_args *v)
|
||||
int *ncookies = v->a_ncookies;
|
||||
|
||||
int error;
|
||||
off_t startoff;
|
||||
off_t cnt = 0;
|
||||
ssize_t startresid;
|
||||
int cnt = 0;
|
||||
struct tmpfs_node *node;
|
||||
|
||||
/* This operation only makes sense on directory nodes. */
|
||||
@ -1483,69 +1487,29 @@ tmpfs_readdir(struct vop_readdir_args *v)
|
||||
|
||||
node = VP_TO_TMPFS_DIR(vp);
|
||||
|
||||
startoff = uio->uio_offset;
|
||||
startresid = uio->uio_resid;
|
||||
|
||||
if (uio->uio_offset == TMPFS_DIRCOOKIE_DOT) {
|
||||
error = tmpfs_dir_getdotdent(node, uio);
|
||||
if (error != 0)
|
||||
goto outok;
|
||||
cnt++;
|
||||
if (cookies != NULL && ncookies != NULL) {
|
||||
cnt = howmany(node->tn_size, sizeof(struct tmpfs_dirent)) + 2;
|
||||
*cookies = malloc(cnt * sizeof(**cookies), M_TEMP, M_WAITOK);
|
||||
*ncookies = 0;
|
||||
}
|
||||
|
||||
if (uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT) {
|
||||
error = tmpfs_dir_getdotdotdent(node, uio);
|
||||
if (error != 0)
|
||||
goto outok;
|
||||
cnt++;
|
||||
}
|
||||
if (cnt == 0)
|
||||
error = tmpfs_dir_getdents(node, uio, 0, NULL, NULL);
|
||||
else
|
||||
error = tmpfs_dir_getdents(node, uio, cnt, *cookies, ncookies);
|
||||
|
||||
error = tmpfs_dir_getdents(node, uio, &cnt);
|
||||
if (error == EJUSTRETURN)
|
||||
error = (uio->uio_resid != startresid) ? 0 : EINVAL;
|
||||
|
||||
outok:
|
||||
MPASS(error >= -1);
|
||||
|
||||
if (error == -1)
|
||||
error = (cnt != 0) ? 0 : EINVAL;
|
||||
if (error != 0 && cnt != 0)
|
||||
free(*cookies, M_TEMP);
|
||||
|
||||
if (eofflag != NULL)
|
||||
*eofflag =
|
||||
(error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF);
|
||||
|
||||
/* Update NFS-related variables. */
|
||||
if (error == 0 && cookies != NULL && ncookies != NULL) {
|
||||
off_t i;
|
||||
off_t off = startoff;
|
||||
struct tmpfs_dirent *de = NULL;
|
||||
|
||||
*ncookies = cnt;
|
||||
*cookies = malloc(cnt * sizeof(off_t), M_TEMP, M_WAITOK);
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
MPASS(off != TMPFS_DIRCOOKIE_EOF);
|
||||
if (off == TMPFS_DIRCOOKIE_DOT) {
|
||||
off = TMPFS_DIRCOOKIE_DOTDOT;
|
||||
} else {
|
||||
if (off == TMPFS_DIRCOOKIE_DOTDOT) {
|
||||
de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
|
||||
} else if (de != NULL) {
|
||||
de = TAILQ_NEXT(de, td_entries);
|
||||
} else {
|
||||
de = tmpfs_dir_lookupbycookie(node,
|
||||
off);
|
||||
MPASS(de != NULL);
|
||||
de = TAILQ_NEXT(de, td_entries);
|
||||
}
|
||||
if (de == NULL)
|
||||
off = TMPFS_DIRCOOKIE_EOF;
|
||||
else
|
||||
off = tmpfs_dircookie(de);
|
||||
}
|
||||
|
||||
(*cookies)[i] = off;
|
||||
}
|
||||
MPASS(uio->uio_offset == off);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ options SOFTUPDATES # Enable FFS soft updates support
|
||||
options UFS_ACL # Support for access control lists
|
||||
options UFS_DIRHASH # Improve performance on big directories
|
||||
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
|
||||
options QUOTA # Enable disk quotas for UFS
|
||||
options MD_ROOT # MD is a potential root device
|
||||
options NFSCL # New Network Filesystem Client
|
||||
options NFSD # New Network Filesystem Server
|
||||
@ -331,15 +332,6 @@ device usb # USB Bus (required)
|
||||
device ukbd # Keyboard
|
||||
device umass # Disks/Mass storage - Requires scbus and da
|
||||
|
||||
# FireWire support
|
||||
device firewire # FireWire bus code
|
||||
# sbp(4) works for some systems but causes boot failure on others
|
||||
#device sbp # SCSI over FireWire (Requires scbus and da)
|
||||
device fwe # Ethernet over FireWire (non-standard!)
|
||||
device fwip # IP over FireWire (RFC 2734,3146)
|
||||
device dcons # Dumb console driver
|
||||
device dcons_crom # Configuration ROM for dcons
|
||||
|
||||
# Sound support
|
||||
device sound # Generic sound driver (required)
|
||||
device snd_cmi # CMedia CMI8338/CMI8738
|
||||
|
@ -216,7 +216,9 @@ static mmu_update_t xpq_queue[MAX_VIRT_CPUS][XPQUEUE_SIZE];
|
||||
#else
|
||||
|
||||
static mmu_update_t xpq_queue[XPQUEUE_SIZE];
|
||||
#ifdef INVARIANTS
|
||||
static struct mmu_log xpq_queue_log[XPQUEUE_SIZE];
|
||||
#endif
|
||||
static int xpq_idx = 0;
|
||||
|
||||
#define XPQ_QUEUE_LOG xpq_queue_log
|
||||
|
@ -60,6 +60,7 @@ options SYSVSHM # SYSV-style shared memory
|
||||
options UFS_ACL # Support for access control lists
|
||||
options UFS_DIRHASH # Hash-based directory lookup scheme
|
||||
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
|
||||
options QUOTA # Enable disk quotas for UFS
|
||||
options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B RT extensions
|
||||
|
||||
# Debugging support. Always need this:
|
||||
@ -77,7 +78,6 @@ options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
|
||||
options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
|
||||
|
||||
# Various "busses"
|
||||
device firewire # FireWire bus code
|
||||
device miibus # MII bus support (Ethernet)
|
||||
device pci # PCI bus support
|
||||
device scbus # SCSI bus (required for ATA/SCSI)
|
||||
@ -190,11 +190,6 @@ options IEEE80211_SUPPORT_MESH
|
||||
# builds everything including AR5416 (and later 11n NIC) support.
|
||||
options AH_SUPPORT_AR5416
|
||||
|
||||
# FireWire support
|
||||
device fwip # IP over FireWire (RFC 2734,3146)
|
||||
# sbp(4) works for some systems but causes boot failure on others
|
||||
#device sbp # SCSI over FireWire (need scbus & da)
|
||||
|
||||
# Various (pseudo) devices
|
||||
device ether # Ethernet support
|
||||
device faith # IPv6-to-IPv4 relaying (translation)
|
||||
|
@ -1074,7 +1074,9 @@ kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
|
||||
q = td->td_proc;
|
||||
|
||||
if ((pid_t)id == WAIT_MYPGRP && (idtype == P_PID || idtype == P_PGID)) {
|
||||
PROC_LOCK(q);
|
||||
id = (id_t)q->p_pgid;
|
||||
PROC_UNLOCK(q);
|
||||
idtype = P_PGID;
|
||||
}
|
||||
|
||||
|
@ -498,6 +498,8 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
|
||||
case LK_DOWNGRADE:
|
||||
_lockmgr_assert(lk, KA_XLOCKED | KA_NOTRECURSED,
|
||||
file, line);
|
||||
if (flags & LK_INTERLOCK)
|
||||
class->lc_unlock(ilk);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
@ -133,10 +133,10 @@ sleepinit(void)
|
||||
* General sleep call. Suspends the current thread until a wakeup is
|
||||
* performed on the specified identifier. The thread will then be made
|
||||
* runnable with the specified priority. Sleeps at most timo/hz seconds
|
||||
* (0 means no timeout). If pri includes PCATCH flag, signals are checked
|
||||
* before and after sleeping, else signals are not checked. Returns 0 if
|
||||
* (0 means no timeout). If pri includes the PCATCH flag, let signals
|
||||
* interrupt the sleep, otherwise ignore them while sleeping. Returns 0 if
|
||||
* awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a
|
||||
* signal needs to be delivered, ERESTART is returned if the current system
|
||||
* signal becomes pending, ERESTART is returned if the current system
|
||||
* call should be restarted if possible, and EINTR is returned if the system
|
||||
* call should be interrupted by the signal (return EINTR).
|
||||
*
|
||||
|
@ -160,7 +160,7 @@ static const char *const vm_bnames[] = {
|
||||
"Plex86", /* Plex86 */
|
||||
"Bochs", /* Bochs */
|
||||
"Xen", /* Xen */
|
||||
"BHYVE", /* BHyVe */
|
||||
"BHYVE", /* bhyve */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -559,7 +559,7 @@ vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
|
||||
if (error || fstype[fstypelen - 1] != '\0') {
|
||||
error = EINVAL;
|
||||
if (errmsg != NULL)
|
||||
strlcpy(errmsg, "Invalid fstype", errmsg_len);
|
||||
strncpy(errmsg, "Invalid fstype", errmsg_len);
|
||||
goto bail;
|
||||
}
|
||||
fspathlen = 0;
|
||||
@ -567,7 +567,7 @@ vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
|
||||
if (error || fspath[fspathlen - 1] != '\0') {
|
||||
error = EINVAL;
|
||||
if (errmsg != NULL)
|
||||
strlcpy(errmsg, "Invalid fspath", errmsg_len);
|
||||
strncpy(errmsg, "Invalid fspath", errmsg_len);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
@ -1447,7 +1447,7 @@ vfs_filteropt(struct vfsoptlist *opts, const char **legal)
|
||||
if (ret != 0) {
|
||||
TAILQ_FOREACH(opt, opts, link) {
|
||||
if (strcmp(opt->name, "errmsg") == 0) {
|
||||
strlcpy((char *)opt->value, errmsg, opt->len);
|
||||
strncpy((char *)opt->value, errmsg, opt->len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1705,103 +1705,6 @@ vfs_copyopt(opts, name, dest, len)
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* These are helper functions for filesystems to traverse all
|
||||
* their vnodes. See MNT_VNODE_FOREACH() in sys/mount.h.
|
||||
*
|
||||
* This interface has been deprecated in favor of MNT_VNODE_FOREACH_ALL.
|
||||
*/
|
||||
|
||||
MALLOC_DECLARE(M_VNODE_MARKER);
|
||||
|
||||
struct vnode *
|
||||
__mnt_vnode_next(struct vnode **mvp, struct mount *mp)
|
||||
{
|
||||
struct vnode *vp;
|
||||
|
||||
mtx_assert(MNT_MTX(mp), MA_OWNED);
|
||||
|
||||
KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
|
||||
if (should_yield()) {
|
||||
MNT_IUNLOCK(mp);
|
||||
kern_yield(PRI_USER);
|
||||
MNT_ILOCK(mp);
|
||||
}
|
||||
vp = TAILQ_NEXT(*mvp, v_nmntvnodes);
|
||||
while (vp != NULL && vp->v_type == VMARKER)
|
||||
vp = TAILQ_NEXT(vp, v_nmntvnodes);
|
||||
|
||||
/* Check if we are done */
|
||||
if (vp == NULL) {
|
||||
__mnt_vnode_markerfree(mvp, mp);
|
||||
return (NULL);
|
||||
}
|
||||
TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
|
||||
TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
|
||||
return (vp);
|
||||
}
|
||||
|
||||
struct vnode *
|
||||
__mnt_vnode_first(struct vnode **mvp, struct mount *mp)
|
||||
{
|
||||
struct vnode *vp;
|
||||
|
||||
mtx_assert(MNT_MTX(mp), MA_OWNED);
|
||||
|
||||
vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
|
||||
while (vp != NULL && vp->v_type == VMARKER)
|
||||
vp = TAILQ_NEXT(vp, v_nmntvnodes);
|
||||
|
||||
/* Check if we are done */
|
||||
if (vp == NULL) {
|
||||
*mvp = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
MNT_REF(mp);
|
||||
MNT_IUNLOCK(mp);
|
||||
*mvp = (struct vnode *) malloc(sizeof(struct vnode),
|
||||
M_VNODE_MARKER,
|
||||
M_WAITOK | M_ZERO);
|
||||
MNT_ILOCK(mp);
|
||||
(*mvp)->v_type = VMARKER;
|
||||
|
||||
vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
|
||||
while (vp != NULL && vp->v_type == VMARKER)
|
||||
vp = TAILQ_NEXT(vp, v_nmntvnodes);
|
||||
|
||||
/* Check if we are done */
|
||||
if (vp == NULL) {
|
||||
MNT_IUNLOCK(mp);
|
||||
free(*mvp, M_VNODE_MARKER);
|
||||
MNT_ILOCK(mp);
|
||||
*mvp = NULL;
|
||||
MNT_REL(mp);
|
||||
return (NULL);
|
||||
}
|
||||
(*mvp)->v_mount = mp;
|
||||
TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
|
||||
return (vp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp)
|
||||
{
|
||||
|
||||
if (*mvp == NULL)
|
||||
return;
|
||||
|
||||
mtx_assert(MNT_MTX(mp), MA_OWNED);
|
||||
|
||||
KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
|
||||
TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
|
||||
MNT_IUNLOCK(mp);
|
||||
free(*mvp, M_VNODE_MARKER);
|
||||
MNT_ILOCK(mp);
|
||||
*mvp = NULL;
|
||||
MNT_REL(mp);
|
||||
}
|
||||
|
||||
int
|
||||
__vfs_statfs(struct mount *mp, struct statfs *sbp)
|
||||
{
|
||||
|
@ -81,6 +81,7 @@ struct ar71xx_pci_softc {
|
||||
device_t sc_dev;
|
||||
|
||||
int sc_busno;
|
||||
int sc_baseslot;
|
||||
struct rman sc_mem_rman;
|
||||
struct rman sc_irq_rman;
|
||||
|
||||
@ -395,6 +396,16 @@ ar71xx_pci_attach(device_t dev)
|
||||
AR71XX_PCI_IRQ_END) != 0)
|
||||
panic("ar71xx_pci_attach: failed to set up IRQ rman");
|
||||
|
||||
/*
|
||||
* Check if there is a base slot hint. Otherwise use default value.
|
||||
*/
|
||||
if (resource_int_value(device_get_name(dev),
|
||||
device_get_unit(dev), "baseslot", &sc->sc_baseslot) != 0) {
|
||||
device_printf(dev,
|
||||
"%s: missing hint '%s', default to AR71XX_PCI_BASE_SLOT\n",
|
||||
__func__, "baseslot");
|
||||
sc->sc_baseslot = AR71XX_PCI_BASE_SLOT;
|
||||
}
|
||||
|
||||
ATH_WRITE_REG(AR71XX_PCI_INTR_STATUS, 0);
|
||||
ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, 0);
|
||||
@ -648,11 +659,13 @@ ar71xx_pci_maxslots(device_t dev)
|
||||
static int
|
||||
ar71xx_pci_route_interrupt(device_t pcib, device_t device, int pin)
|
||||
{
|
||||
if (pci_get_slot(device) < AR71XX_PCI_BASE_SLOT)
|
||||
struct ar71xx_pci_softc *sc = device_get_softc(pcib);
|
||||
|
||||
if (pci_get_slot(device) < sc->sc_baseslot)
|
||||
panic("%s: PCI slot %d is less then AR71XX_PCI_BASE_SLOT",
|
||||
__func__, pci_get_slot(device));
|
||||
|
||||
return (pci_get_slot(device) - AR71XX_PCI_BASE_SLOT);
|
||||
return (pci_get_slot(device) - sc->sc_baseslot);
|
||||
}
|
||||
|
||||
static device_method_t ar71xx_pci_methods[] = {
|
||||
|
@ -39,6 +39,7 @@ makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
|
||||
# Board-specific support that cannot be auto-detected at runtime.
|
||||
#options OCTEON_VENDOR_LANNER # Support for Lanner boards.
|
||||
#options OCTEON_VENDOR_RADISYS # Support for Radisys boards.
|
||||
#options OCTEON_VENDOR_UBIQUITI # Support for Ubiquiti boards.
|
||||
#options OCTEON_BOARD_CAPK_0100ND # Support for CAPK-0100nd.
|
||||
|
||||
# Compile for a specified Octeon model. If not specified, support for
|
||||
|
@ -1,6 +1,4 @@
|
||||
/* $OpenBSD: if_pfsync.h,v 1.35 2008/06/29 08:42:15 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2001 Michael Shalayeff
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -26,7 +24,7 @@
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*-
|
||||
* Copyright (c) 2008 David Gwynne <dlg@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -42,6 +40,12 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $OpenBSD: if_pfsync.h,v 1.35 2008/06/29 08:42:15 mcbride Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NET_IF_PFSYNC_H_
|
||||
#define _NET_IF_PFSYNC_H_
|
||||
|
||||
@ -63,20 +67,6 @@
|
||||
#define PFSYNC_ACT_EOF 12 /* end of frame */
|
||||
#define PFSYNC_ACT_MAX 13
|
||||
|
||||
#define PFSYNC_ACTIONS "CLR ST", \
|
||||
"INS ST", \
|
||||
"INS ST ACK", \
|
||||
"UPD ST", \
|
||||
"UPD ST COMP", \
|
||||
"UPD ST REQ", \
|
||||
"DEL ST", \
|
||||
"DEL ST COMP", \
|
||||
"INS FR", \
|
||||
"DEL FR", \
|
||||
"BULK UPD STAT", \
|
||||
"TDB UPD", \
|
||||
"EOF"
|
||||
|
||||
#define PFSYNC_HMAC_LEN 20
|
||||
|
||||
/*
|
||||
|
@ -25,7 +25,14 @@
|
||||
#define MY_ZCALLOC
|
||||
|
||||
#if defined(__FreeBSD__) && defined(_KERNEL)
|
||||
#define inflate inflate_ppp /* FreeBSD already has an inflate :-( */
|
||||
#define _tr_init _zlib104_tr_init
|
||||
#define _tr_align _zlib104_tr_align
|
||||
#define _tr_tally _zlib104_tr_tally
|
||||
#define _tr_flush_block _zlib104_tr_flush_block
|
||||
#define _tr_stored_block _zlib104_tr_stored_block
|
||||
#define inflate_fast _zlib104_inflate_fast
|
||||
#define inflate _zlib104_inflate
|
||||
#define zlibVersion _zlib104_Version
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -511,7 +511,7 @@ extern int EXPORT inflateInit OF((z_streamp strm));
|
||||
*/
|
||||
|
||||
#if defined(__FreeBSD__) && defined(_KERNEL)
|
||||
#define inflate inflate_ppp /* FreeBSD already has an inflate :-( */
|
||||
#define inflate _zlib104_inflate /* FreeBSD already has an inflate :-( */
|
||||
#endif
|
||||
|
||||
extern int EXPORT inflate OF((z_streamp strm, int flush));
|
||||
|
@ -2324,5 +2324,19 @@ ieee80211_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m0)
|
||||
ifp = vap->iv_ic->ic_ifp;
|
||||
else
|
||||
ifp = vap->iv_ifp;
|
||||
(void) ifp->if_transmit(ifp, m);
|
||||
|
||||
/*
|
||||
* Free any node ref which this mbuf may have.
|
||||
*
|
||||
* Much like psq_mfree(), we assume that M_ENCAP nodes have
|
||||
* node references.
|
||||
*/
|
||||
if (ifp->if_transmit(ifp, m) != 0) {
|
||||
/*
|
||||
* XXX m is invalid (freed) at this point, determine M_ENCAP
|
||||
* an alternate way.
|
||||
*/
|
||||
if (ifp == vap->iv_ic->ic_ifp)
|
||||
ieee80211_free_node(ni);
|
||||
}
|
||||
}
|
||||
|
@ -1227,6 +1227,8 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
struct mbuf *m, *next;
|
||||
uint32_t metric = 0;
|
||||
const uint8_t *addr;
|
||||
int is_encap;
|
||||
struct ieee80211_node *ni_encap;
|
||||
|
||||
if (ni == vap->iv_bss ||
|
||||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
|
||||
@ -1403,11 +1405,21 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
(struct ieee80211_node *)(uintptr_t)
|
||||
ieee80211_mac_hash(ic, addr)); /* either dest or ext_dest */
|
||||
for (; m != NULL; m = next) {
|
||||
is_encap = !! (m->m_flags & M_ENCAP);
|
||||
ni_encap = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
next = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||
"flush queued frame %p len %d", m, m->m_pkthdr.len);
|
||||
ifp->if_transmit(ifp, m);
|
||||
|
||||
/*
|
||||
* If the mbuf has M_ENCAP set, ensure we free it.
|
||||
* Note that after if_transmit() is called, m is invalid.
|
||||
*/
|
||||
if (ifp->if_transmit(ifp, m) != 0) {
|
||||
if (is_encap)
|
||||
ieee80211_free_node(ni_encap);
|
||||
}
|
||||
}
|
||||
#undef IS_PROXY
|
||||
#undef PROXIED_BY_US
|
||||
|
@ -194,9 +194,20 @@ enum ieee80211_radiotap_type {
|
||||
IEEE80211_RADIOTAP_ANTENNA = 11,
|
||||
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
|
||||
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
|
||||
/* NB: gap for netbsd definitions */
|
||||
/*
|
||||
* 14-17 are from Linux, they overlap the netbsd-specific
|
||||
* fields.
|
||||
*/
|
||||
IEEE80211_RADIOTAP_RX_FLAGS = 14,
|
||||
IEEE80211_RADIOTAP_TX_FLAGS = 15,
|
||||
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
|
||||
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
|
||||
|
||||
IEEE80211_RADIOTAP_XCHANNEL = 18,
|
||||
IEEE80211_RADIOTAP_MCS = 19,
|
||||
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
|
||||
|
||||
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
|
||||
IEEE80211_RADIOTAP_VENDOREXT = 30,
|
||||
IEEE80211_RADIOTAP_EXT = 31,
|
||||
};
|
||||
|
@ -819,19 +819,14 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Give the interface a chance to initialize if this is its first
|
||||
* address, and to validate the address if necessary.
|
||||
*
|
||||
* Historically, drivers managed IFF_UP flag theirselves, so we
|
||||
* need to check whether driver did that.
|
||||
* Give the interface a chance to initialize
|
||||
* if this is its first address,
|
||||
* and to validate the address if necessary.
|
||||
*/
|
||||
flags = ifp->if_flags;
|
||||
if (ifp->if_ioctl != NULL &&
|
||||
(error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) != 0)
|
||||
/* LIST_REMOVE(ia, ia_hash) is done in in_control */
|
||||
return (error);
|
||||
if ((ifp->if_flags & IFF_UP) && (flags & IFF_UP) == 0)
|
||||
if_up(ifp);
|
||||
|
||||
/*
|
||||
* Be compatible with network classes, if netmask isn't supplied,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user