diff options
author | dim <dim@FreeBSD.org> | 2010-10-19 21:02:05 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2010-10-19 21:02:05 +0000 |
commit | acc1b913a3297e19f9ffe7d2b7b8a3142926d3b4 (patch) | |
tree | 3ba42afae5a4abd129ca596650d0c27112d3953e | |
parent | ba43e0ffe7a883f062e502acf73190ce6534b0fe (diff) | |
parent | f0ce9e3f305fe6039937eade02551429beef30ac (diff) | |
download | FreeBSD-src-acc1b913a3297e19f9ffe7d2b7b8a3142926d3b4.zip FreeBSD-src-acc1b913a3297e19f9ffe7d2b7b8a3142926d3b4.tar.gz |
Sync: merge r213992 through r214076 from ^/head.
92 files changed, 1991 insertions, 912 deletions
diff --git a/contrib/bsnmp/lib/bsnmplib.3 b/contrib/bsnmp/lib/bsnmplib.3 index 4512b8c..dfbffc4 100644 --- a/contrib/bsnmp/lib/bsnmplib.3 +++ b/contrib/bsnmp/lib/bsnmplib.3 @@ -134,7 +134,6 @@ is not zero, .Fa v.octetstring.octets points to a string allocated by .Xr malloc 3 . -.Pp .Bd -literal -offset indent #define SNMP_COMMUNITY_MAXLEN 128 #define SNMP_MAX_BINDINGS 100 diff --git a/contrib/netcat/nc.1 b/contrib/netcat/nc.1 index 41f5f09..9a6e836 100644 --- a/contrib/netcat/nc.1 +++ b/contrib/netcat/nc.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nc.1,v 1.53 2010/02/23 23:00:52 schwarze Exp $ +.\" $OpenBSD: nc.1,v 1.55 2010/07/25 07:51:39 guenther Exp $ .\" .\" Copyright (c) 1996 David Sacerdote .\" All rights reserved. @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 3, 2010 +.Dd July 25, 2010 .Dt NC 1 .Os .Sh NAME @@ -46,7 +46,7 @@ .Op Fl p Ar source_port .Op Fl s Ar source_ip_address .Op Fl T Ar ToS -.Op Fl V Ar fib +.Op Fl V Ar rtable .Op Fl w Ar timeout .Op Fl X Ar proxy_protocol .Oo Xo @@ -158,7 +158,6 @@ TCP_NOOPT socket option. .It Fl O Ar length Specifies the size of the TCP send buffer. -When .It Fl P Ar proxy_username Specifies a username to present to a proxy server that requires authentication. If no username is specified then authentication will not be attempted. @@ -202,8 +201,10 @@ Specifies to use sockets. .It Fl u Use UDP instead of the default option of TCP. -.It Fl V Ar fib -Set the routing table (FIB). +.It Fl V Ar rtable +Set the routing table +.Pq Dq FIB +to be used. The default is 0. .It Fl v Have diff --git a/contrib/netcat/netcat.c b/contrib/netcat/netcat.c index 28a9823..fe87e96 100644 --- a/contrib/netcat/netcat.c +++ b/contrib/netcat/netcat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netcat.c,v 1.95 2010/02/27 00:58:56 nicm Exp $ */ +/* $OpenBSD: netcat.c,v 1.98 2010/07/03 04:44:51 guenther Exp $ */ /* * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> * @@ -93,7 +93,7 @@ int Iflag; /* TCP receive buffer size */ int Oflag; /* TCP send buffer size */ int Sflag; /* TCP MD5 signature option */ int Tflag = -1; /* IP Type of Service */ -u_int rdomain; +u_int rtableid; int timeout = -1; int family = AF_UNSPEC; @@ -139,7 +139,6 @@ main(int argc, char *argv[]) { NULL, 0, NULL, 0 } }; - rdomain = 0; ret = 1; ipsec_count = 0; s = 0; @@ -235,10 +234,10 @@ main(int argc, char *argv[]) case 'V': if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) errx(1, "Multiple FIBS not supported"); - rdomain = (unsigned int)strtonum(optarg, 0, + rtableid = (unsigned int)strtonum(optarg, 0, numfibs - 1, &errstr); if (errstr) - errx(1, "FIB %s: %s", errstr, optarg); + errx(1, "rtable %s: %s", errstr, optarg); break; case 'v': vflag = 1; @@ -371,11 +370,11 @@ main(int argc, char *argv[]) */ if (uflag) { int rv, plen; - char buf[8192]; + char buf[16384]; struct sockaddr_storage z; len = sizeof(z); - plen = jflag ? 8192 : 1024; + plen = jflag ? 16384 : 2048; rv = recvfrom(s, buf, plen, MSG_PEEK, (struct sockaddr *)&z, &len); if (rv < 0) @@ -561,8 +560,8 @@ remote_connect(const char *host, const char *port, struct addrinfo hints) add_ipsec_policy(s, ipsec_policy[1]); #endif - if (rdomain) { - if (setfib(rdomain) == -1) + if (rtableid) { + if (setfib(rtableid) == -1) err(1, "setfib"); } @@ -634,8 +633,8 @@ local_listen(char *host, char *port, struct addrinfo hints) res0->ai_protocol)) < 0) continue; - if (rdomain) { - if (setfib(rdomain) == -1) + if (rtableid) { + if (setfib(rtableid) == -1) err(1, "setfib"); } @@ -680,12 +679,12 @@ void readwrite(int nfd) { struct pollfd pfd[2]; - unsigned char buf[8192]; + unsigned char buf[16384]; int n, wfd = fileno(stdin); int lfd = fileno(stdout); int plen; - plen = jflag ? 8192 : 1024; + plen = jflag ? 16384 : 2048; /* Setup Network FD */ pfd[0].fd = nfd; @@ -827,10 +826,9 @@ build_ports(char *p) hi = strtonum(p, 1, PORT_MAX, &errstr); if (errstr) errx(1, "port number %s: %s", errstr, p); - portlist[0] = calloc(1, PORT_MAX_LEN); + portlist[0] = strdup(p); if (portlist[0] == NULL) err(1, NULL); - portlist[0] = p; } } @@ -947,7 +945,7 @@ help(void) \t-t Answer TELNET negotiation\n\ \t-U Use UNIX domain socket\n\ \t-u UDP mode\n\ - \t-V fib Specify alternate routing table (FIB)\n\ + \t-V rtable Specify alternate routing table\n\ \t-v Verbose\n\ \t-w secs\t Timeout for connects and final net reads\n\ \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ @@ -992,7 +990,7 @@ usage(int ret) "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n" #endif "\t [-P proxy_username] [-p source_port] [-s source_ip_address] [-T ToS]\n" - "\t [-V fib] [-w timeout] [-X proxy_protocol]\n" + "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" "\t [-x proxy_address[:port]] [hostname] [port]\n"); if (ret) exit(1); diff --git a/contrib/netcat/socks.c b/contrib/netcat/socks.c index da7bd0c..b38dff7 100644 --- a/contrib/netcat/socks.c +++ b/contrib/netcat/socks.c @@ -1,4 +1,4 @@ -/* $OpenBSD: socks.c,v 1.17 2006/09/25 04:51:20 ray Exp $ */ +/* $OpenBSD: socks.c,v 1.18 2010/04/20 07:26:35 nicm Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -167,11 +167,11 @@ socks_connect(const char *host, const char *port, buf[2] = SOCKS_NOAUTH; cnt = atomicio(vwrite, proxyfd, buf, 3); if (cnt != 3) - err(1, "write failed (%d/3)", cnt); + err(1, "write failed (%zu/3)", cnt); cnt = atomicio(read, proxyfd, buf, 2); if (cnt != 2) - err(1, "read failed (%d/3)", cnt); + err(1, "read failed (%zu/3)", cnt); if (buf[1] == SOCKS_NOMETHOD) errx(1, "authentication method negotiation failed"); @@ -220,11 +220,11 @@ socks_connect(const char *host, const char *port, cnt = atomicio(vwrite, proxyfd, buf, wlen); if (cnt != wlen) - err(1, "write failed (%d/%d)", cnt, wlen); + err(1, "write failed (%zu/%zu)", cnt, wlen); cnt = atomicio(read, proxyfd, buf, 10); if (cnt != 10) - err(1, "read failed (%d/10)", cnt); + err(1, "read failed (%zu/10)", cnt); if (buf[1] != 0) errx(1, "connection failed, SOCKS error %d", buf[1]); } else if (socksv == 4) { @@ -242,11 +242,11 @@ socks_connect(const char *host, const char *port, cnt = atomicio(vwrite, proxyfd, buf, wlen); if (cnt != wlen) - err(1, "write failed (%d/%d)", cnt, wlen); + err(1, "write failed (%zu/%zu)", cnt, wlen); cnt = atomicio(read, proxyfd, buf, 8); if (cnt != 8) - err(1, "read failed (%d/8)", cnt); + err(1, "read failed (%zu/8)", cnt); if (buf[1] != 90) errx(1, "connection failed, SOCKS error %d", buf[1]); } else if (socksv == -1) { @@ -272,7 +272,7 @@ socks_connect(const char *host, const char *port, cnt = atomicio(vwrite, proxyfd, buf, r); if (cnt != r) - err(1, "write failed (%d/%d)", cnt, r); + err(1, "write failed (%zu/%d)", cnt, r); if (authretry > 1) { char resp[1024]; @@ -290,7 +290,7 @@ socks_connect(const char *host, const char *port, errx(1, "Proxy auth response too long"); r = strlen(buf); if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r) - err(1, "write failed (%d/%d)", cnt, r); + err(1, "write failed (%zu/%d)", cnt, r); } /* Terminate headers */ diff --git a/include/pthread.h b/include/pthread.h index 56f6ef4..9a8e2ae 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -135,6 +135,15 @@ enum pthread_mutextype { #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_ERRORCHECK +enum pthread_rwlocktype_np +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_DEFAULT_NP = + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP +}; + struct _pthread_cleanup_info { __uintptr_t pthread_cleanup_pad[8]; }; @@ -233,11 +242,14 @@ int pthread_rwlock_tryrdlock(pthread_rwlock_t *); int pthread_rwlock_trywrlock(pthread_rwlock_t *); int pthread_rwlock_unlock(pthread_rwlock_t *); int pthread_rwlock_wrlock(pthread_rwlock_t *); -int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); +int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *, + int *); int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *); +int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int); int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int); -int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); pthread_t pthread_self(void); int pthread_setspecific(pthread_key_t, const void *); diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h index 6ba8bab..590eba7 100644 --- a/lib/libc/include/namespace.h +++ b/lib/libc/include/namespace.h @@ -177,8 +177,10 @@ #define pthread_rwlock_unlock _pthread_rwlock_unlock #define pthread_rwlock_wrlock _pthread_rwlock_wrlock #define pthread_rwlockattr_destroy _pthread_rwlockattr_destroy +#define pthread_rwlockattr_getkind_np _pthread_rwlockattr_getkind_np #define pthread_rwlockattr_getpshared _pthread_rwlockattr_getpshared #define pthread_rwlockattr_init _pthread_rwlockattr_init +#define pthread_rwlockattr_setkind_np _pthread_rwlockattr_setkind_np #define pthread_rwlockattr_setpshared _pthread_rwlockattr_setpshared #define pthread_self _pthread_self #define pthread_set_name_np _pthread_set_name_np diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h index 00f0df2..7a8f9d9 100644 --- a/lib/libc/include/un-namespace.h +++ b/lib/libc/include/un-namespace.h @@ -158,8 +158,10 @@ #undef pthread_rwlock_unlock #undef pthread_rwlock_wrlock #undef pthread_rwlockattr_destroy +#undef pthread_rwlockattr_getkind_np #undef pthread_rwlockattr_getpshared #undef pthread_rwlockattr_init +#undef pthread_rwlockattr_setkind_np #undef pthread_rwlockattr_setpshared #undef pthread_self #undef pthread_set_name_np diff --git a/lib/libradius/Makefile b/lib/libradius/Makefile index f49f65c..5723bf1 100644 --- a/lib/libradius/Makefile +++ b/lib/libradius/Makefile @@ -33,6 +33,39 @@ CFLAGS+= -Wall SHLIB_MAJOR= 4 MAN= libradius.3 radius.conf.5 +MLINKS+=libradius.3 rad_acct_open.3 \ + libradius.3 rad_add_server.3 \ + libradius.3 rad_auth_open.3 \ + libradius.3 rad_close.3 \ + libradius.3 rad_config.3 \ + libradius.3 rad_continue_send_request.3 \ + libradius.3 rad_create_request.3 \ + libradius.3 rad_create_response.3 \ + libradius.3 rad_cvt_addr.3 \ + libradius.3 rad_cvt_int.3 \ + libradius.3 rad_cvt_string.3 \ + libradius.3 rad_demangle.3 \ + libradius.3 rad_demangle_mppe_key.3 \ + libradius.3 rad_get_attr.3 \ + libradius.3 rad_get_vendor_attr.3 \ + libradius.3 rad_init_send_request.3 \ + libradius.3 rad_put_addr.3 \ + libradius.3 rad_put_attr.3 \ + libradius.3 rad_put_int.3 \ + libradius.3 rad_put_message_authentic.3 \ + libradius.3 rad_put_string.3 \ + libradius.3 rad_put_vendor_addr.3 \ + libradius.3 rad_put_vendor_attr.3 \ + libradius.3 rad_put_vendor_int.3 \ + libradius.3 rad_put_vendor_string.3 \ + libradius.3 rad_receive_request.3 \ + libradius.3 rad_request_authenticator.3 \ + libradius.3 rad_send_request.3 \ + libradius.3 rad_send_response.3 \ + libradius.3 rad_server_open.3 \ + libradius.3 rad_server_secret.3 \ + libradius.3 rad_strerror.3 + WARNS?= 3 .if ${MK_OPENSSL} == "no" diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index 5e36239..4094016 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -318,7 +318,9 @@ FBSDprivate_1.0 { _pthread_rwlock_wrlock; _pthread_rwlockattr_destroy; _pthread_rwlockattr_getpshared; + _pthread_rwlockattr_getkind_np; _pthread_rwlockattr_init; + _pthread_rwlockattr_setkind_np; _pthread_rwlockattr_setpshared; _pthread_self; _pthread_set_name_np; @@ -401,6 +403,8 @@ FBSD_1.1 { FBSD_1.2 { openat; + pthread_rwlockattr_getkind_np; + pthread_rwlockattr_setkind_np; setcontext; swapcontext; }; diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index aa9feef..5d0c301 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -285,11 +285,14 @@ struct pthread_prio { struct pthread_rwlockattr { int pshared; + int kind; }; struct pthread_rwlock { struct urwlock lock; struct pthread *owner; + int recurse; + int kind; }; /* diff --git a/lib/libthr/thread/thr_rwlock.c b/lib/libthr/thread/thr_rwlock.c index ebdeae7..20b9b79 100644 --- a/lib/libthr/thread/thr_rwlock.c +++ b/lib/libthr/thread/thr_rwlock.c @@ -63,13 +63,19 @@ __weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); */ static int -rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr __unused) +rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { pthread_rwlock_t prwlock; prwlock = (pthread_rwlock_t)calloc(1, sizeof(struct pthread_rwlock)); if (prwlock == NULL) return (ENOMEM); + if (attr != NULL) + prwlock->kind = (*attr)->kind; + else + prwlock->kind = PTHREAD_RWLOCK_DEFAULT_NP; + if (prwlock->kind == PTHREAD_RWLOCK_PREFER_READER_NP) + prwlock->lock.rw_flags |= URWLOCK_PREFER_READER; *rwlock = prwlock; return (0); } @@ -112,7 +118,7 @@ init_static(struct pthread *thread, pthread_rwlock_t *rwlock) } int -_pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) +_pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { *rwlock = NULL; return (rwlock_init(rwlock, attr)); @@ -260,6 +266,14 @@ rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) CHECK_AND_INIT_RWLOCK + if (__predict_false(prwlock->owner == curthread)) { + if (__predict_false( + prwlock->kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)) { + prwlock->recurse++; + return (0); + } + } + /* * POSIX said the validity of the abstimeout parameter need * not be checked if the lock can be immediately acquired. @@ -335,6 +349,13 @@ _pthread_rwlock_unlock (pthread_rwlock_t *rwlock) if (state & URWLOCK_WRITE_OWNER) { if (__predict_false(prwlock->owner != curthread)) return (EPERM); + if (__predict_false( + prwlock->kind == PTHREAD_RWLOCK_PREFER_WRITER_NP)) { + if (prwlock->recurse > 0) { + prwlock->recurse--; + return (0); + } + } prwlock->owner = NULL; } diff --git a/lib/libthr/thread/thr_rwlockattr.c b/lib/libthr/thread/thr_rwlockattr.c index b47d167..23ea73e 100644 --- a/lib/libthr/thread/thr_rwlockattr.c +++ b/lib/libthr/thread/thr_rwlockattr.c @@ -36,8 +36,10 @@ __weak_reference(_pthread_rwlockattr_destroy, pthread_rwlockattr_destroy); __weak_reference(_pthread_rwlockattr_getpshared, pthread_rwlockattr_getpshared); +__weak_reference(_pthread_rwlockattr_getkind_np, pthread_rwlockattr_getkind_np); __weak_reference(_pthread_rwlockattr_init, pthread_rwlockattr_init); __weak_reference(_pthread_rwlockattr_setpshared, pthread_rwlockattr_setpshared); +__weak_reference(_pthread_rwlockattr_setkind_np, pthread_rwlockattr_setkind_np); int _pthread_rwlockattr_destroy(pthread_rwlockattr_t *rwlockattr) @@ -81,6 +83,7 @@ _pthread_rwlockattr_init(pthread_rwlockattr_t *rwlockattr) return(ENOMEM); prwlockattr->pshared = PTHREAD_PROCESS_PRIVATE; + prwlockattr->kind = PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP; *rwlockattr = prwlockattr; return(0); @@ -98,3 +101,21 @@ _pthread_rwlockattr_setpshared(pthread_rwlockattr_t *rwlockattr, int pshared) return(0); } +int +_pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int kind) +{ + if (kind != PTHREAD_RWLOCK_PREFER_READER_NP && + kind != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP && + kind != PTHREAD_RWLOCK_PREFER_WRITER_NP) { + return (EINVAL); + } + (*attr)->kind = kind; + return (0); +} + +int +_pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *kind) +{ + *kind = (*attr)->kind; + return (0); +} diff --git a/libexec/bootpd/bootptab.5 b/libexec/bootpd/bootptab.5 index c10d26b..bfc535c 100644 --- a/libexec/bootpd/bootptab.5 +++ b/libexec/bootpd/bootptab.5 @@ -388,7 +388,6 @@ hardware address. An example .Pa /etc/bootptab file follows: -.Pp .Bd -literal -offset indent # Sample bootptab file (domain=andrew.cmu.edu) diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index f9c8eee..b85f81d 100644 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -207,9 +207,6 @@ A device identifier can take one of three forms: .Bl -tag -width 14n .It deviceUNIT Specify a device name and unit number combination, like "da5" or "cd3". -Note that character device node names (e.g.\& /dev/da0) are -.Em not -allowed here. .It bus:target Specify a bus number and target id. The bus number can be determined from diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 9f26906..b92cc4c1 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -4605,15 +4605,7 @@ main(int argc, char **argv) char name[30]; int rv; - /* - * First catch people who try to do things like: - * camcontrol tur /dev/da0 - * camcontrol doesn't take device nodes as arguments. - */ - if (argv[2][0] == '/') { - warnx("%s is not a valid device identifier", argv[2]); - errx(1, "please read the camcontrol(8) man page"); - } else if (isdigit(argv[2][0])) { + if (isdigit(argv[2][0])) { /* device specified as bus:target[:lun] */ rv = parse_btl(argv[2], &bus, &target, &lun, &arglist); if (rv < 2) diff --git a/sbin/routed/routed.8 b/sbin/routed/routed.8 index c285ef3..570e20b 100644 --- a/sbin/routed/routed.8 +++ b/sbin/routed/routed.8 @@ -440,7 +440,6 @@ The file is comprised of a series of lines, each in one of the following two formats or consist of parameters described later. Blank lines and lines starting with '#' are comments. -.Pp .Bd -ragged .Cm net .Ar Nname[/mask] diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8 index c66860f..7103e1f 100644 --- a/sbin/setkey/setkey.8 +++ b/sbin/setkey/setkey.8 @@ -565,7 +565,6 @@ There are small, but important, differences in the syntax. See .Xr ipsec_set_policy 3 for details. -.Pp .El .Pp .\" @@ -583,7 +582,6 @@ in the of the .Ar protocol parameter: -.Pp .Bd -literal -offset indent algorithm keylen (bits) comment hmac-md5 128 ah: rfc2403 @@ -616,7 +614,6 @@ in the of the .Ar protocol parameter: -.Pp .Bd -literal -offset indent algorithm keylen (bits) comment des-cbc 64 esp-old: rfc1829, esp: rfc2405 @@ -643,7 +640,6 @@ in the of the .Ar protocol parameter: -.Pp .Bd -literal -offset indent algorithm comment deflate rfc2394 diff --git a/sbin/sunlabel/sunlabel.8 b/sbin/sunlabel/sunlabel.8 index 7e3d3f2..5fc815d 100644 --- a/sbin/sunlabel/sunlabel.8 +++ b/sbin/sunlabel/sunlabel.8 @@ -120,7 +120,6 @@ Options are listed in alphabetical order here. Note that only those option combinations listed under .Sx SYNOPSIS are allowable. -.Pp .Bl -tag -width ".Fl b Ar bootpath" .It Fl b Ar bootpath Specify that diff --git a/share/man/man4/lagg.4 b/share/man/man4/lagg.4 index a8604ac..1dd5142 100644 --- a/share/man/man4/lagg.4 +++ b/share/man/man4/lagg.4 @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 8, 2010 +.Dd October 18, 2010 .Dt LAGG 4 .Os .Sh NAME @@ -73,14 +73,14 @@ The interface link state is used to validate if the port is active or not. .Bl -tag -width loadbalance .It Ic failover -Sends traffic only through the master port. +Sends traffic only through the active port. If the master port becomes unavailable, the next active port is used. The first interface added is the master port; any interfaces added after that are used as failover devices. .Pp By default, received traffic is only accepted when they are received -through the master port. +through the active port. This constraint can be relaxed by setting the .Va net.link.lagg.failover_rx_all .Xr sysctl 8 diff --git a/share/man/man4/man4.arm/mge.4 b/share/man/man4/man4.arm/mge.4 index adc90ca..a0f05bd 100644 --- a/share/man/man4/man4.arm/mge.4 +++ b/share/man/man4/man4.arm/mge.4 @@ -47,7 +47,6 @@ system-on-chip devices. The .Nm driver supports the following media types: -.Pp .Bl -tag -width xxxxxxxxxxxxxxxxxxxx .It autoselect Enable autoselection of the media type and options @@ -62,7 +61,6 @@ Set 1000baseT operation The .Nm driver supports the following media options: -.Pp .Bl -tag -width xxxxxxxxxxxxxxxxxxxx .It full-duplex Set full duplex operation diff --git a/share/man/man4/man4.i386/ep.4 b/share/man/man4/man4.i386/ep.4 index 3916754..446eb04 100644 --- a/share/man/man4/man4.i386/ep.4 +++ b/share/man/man4/man4.i386/ep.4 @@ -57,7 +57,6 @@ Parallel Tasking chipset. .Pp Various models of these cards come with a different assortment of connectors: -.Pp .Bl -tag -width xxxxxxxxxxxxxxxxxxxx .It AUI/DIX Standard 15 pin connector, also known as 10base5 (thick-net) @@ -74,7 +73,6 @@ To override this, use the following media options with or in your .Pa /etc/rc.conf file. -.Pp .Bl -tag -width xxxxxxxxxxxxxxxxxxxx .It 10base5/AUI Use the AUI port. diff --git a/share/man/man4/man4.i386/mse.4 b/share/man/man4/man4.i386/mse.4 index a5cb3f7..bea73e1 100644 --- a/share/man/man4/man4.i386/mse.4 +++ b/share/man/man4/man4.i386/mse.4 @@ -147,7 +147,6 @@ or in the User Configuration Menu at the boot time (see .Xr boot 8 ) . -.Pp .Bl -tag -width MOUSE .It bit 4..7 ACCELERATION This flag controls the amount of acceleration effect. diff --git a/share/man/man4/man4.powerpc/tsec.4 b/share/man/man4/man4.powerpc/tsec.4 index 6e535a5..84db70e 100644 --- a/share/man/man4/man4.powerpc/tsec.4 +++ b/share/man/man4/man4.powerpc/tsec.4 @@ -47,7 +47,6 @@ some of the Freescale system-on-chip devices. The .Nm driver supports the following media types: -.Pp .Bl -tag -width xxxxxxxxxxxxxxxxxxxx .It autoselect Enable autoselection of the media type and options @@ -62,7 +61,6 @@ Set 1000baseT operation The .Nm driver supports the following media options: -.Pp .Bl -tag -width xxxxxxxxxxxxxxxxxxxx .It full-duplex Set full duplex operation diff --git a/share/man/man4/nxge.4 b/share/man/man4/nxge.4 index 891ffad..4550535 100644 --- a/share/man/man4/nxge.4 +++ b/share/man/man4/nxge.4 @@ -49,7 +49,7 @@ The .Nm driver provides support for Neterion Xframe-I and Xframe-II adapters. The driver supports TCP Segmentation Offload (TSO/LSO), -Large Receive Offlaod (LRO), Jumbo Frames (5 buffer mode), +Large Receive Offload (LRO), Jumbo Frames (5 buffer mode), Header Separation (Rx 2 buffer mode), VLAN, and Promiscuous mode. .Pp For general information and support, please visit the Neterion support page diff --git a/share/man/man5/freebsd-update.conf.5 b/share/man/man5/freebsd-update.conf.5 index d372102..653b055 100644 --- a/share/man/man5/freebsd-update.conf.5 +++ b/share/man/man5/freebsd-update.conf.5 @@ -47,7 +47,6 @@ Unless stated otherwise, specifying an option multiple times is an error. .Pp The possible options and their meanings are as follows: -.Pp .Bl -tag -width ".Cm BackupKernelSymbolFiles" .It Cm KeyPrint The single parameter following this keyword is the SHA256 hash diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 2198a6f..261be4f 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1212,11 +1212,17 @@ MLINKS+=sysctl_ctx_init.9 sysctl_ctx_entry_add.9 \ sysctl_ctx_init.9 sysctl_ctx_free.9 MLINKS+=taskqueue.9 TASK_INIT.9 \ taskqueue.9 taskqueue_create.9 \ + taskqueue.9 taskqueue_create_fast.9 \ taskqueue.9 TASKQUEUE_DECLARE.9 \ taskqueue.9 TASKQUEUE_DEFINE.9 \ + taskqueue.9 TASKQUEUE_DEFINE_THREAD.9 \ + taskqueue.9 taskqueue_drain.9 \ taskqueue.9 taskqueue_enqueue.9 \ - taskqueue.9 taskqueue_find.9 \ + taskqueue.9 taskqueue_enqueue_fast.9 \ + taskqueue.9 TASKQUEUE_FAST_DEFINE.9 \ + taskqueue.9 TASKQUEUE_FAST_DEFINE_THREAD.9 \ taskqueue.9 taskqueue_free.9 \ + taskqueue.9 taskqueue_member.9 \ taskqueue.9 taskqueue_run.9 MLINKS+=time.9 boottime.9 \ time.9 time_second.9 \ diff --git a/share/man/man9/vrele.9 b/share/man/man9/vrele.9 index 8d28d5e..0b9b736 100644 --- a/share/man/man9/vrele.9 +++ b/share/man/man9/vrele.9 @@ -59,7 +59,7 @@ The .Fn vrele function takes an unlocked vnode and returns with the vnode unlocked. .Pp -.The +The .Fn vput function should be given a locked vnode as argument, the vnode is unlocked after the function returned. diff --git a/share/man/man9/zone.9 b/share/man/man9/zone.9 index 304b7f0..a2132b5 100644 --- a/share/man/man9/zone.9 +++ b/share/man/man9/zone.9 @@ -153,6 +153,13 @@ Items are released back to the zone from which they were allocated by calling .Fn uma_zfree with a pointer to the zone and a pointer to the item. +If +.Fa item +is +.Dv NULL , +then +.Fn uma_zfree +does nothing. .Pp The variations .Fn uma_zalloc_arg diff --git a/sys/arm/mv/mv_sata.c b/sys/arm/mv/mv_sata.c index 13ae1e0..277c837 100644 --- a/sys/arm/mv/mv_sata.c +++ b/sys/arm/mv/mv_sata.c @@ -710,7 +710,7 @@ sata_channel_status(device_t dev) if ((icr & SATA_ICR_DEV(ch->unit)) || iecr) { /* Disable EDMA before accessing SATA registers */ sata_edma_ctrl(dev, 0); - ata_sata_phy_check_events(dev); + ata_sata_phy_check_events(dev, -1); /* Ack device and error interrupt */ SATA_OUTL(sc, SATA_ICR, ~SATA_ICR_DEV(ch->unit)); diff --git a/sys/conf/files b/sys/conf/files index c1bc03a..75f16e5 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2453,6 +2453,7 @@ net80211/ieee80211_power.c optional wlan net80211/ieee80211_proto.c optional wlan net80211/ieee80211_radiotap.c optional wlan net80211/ieee80211_ratectl.c optional wlan +net80211/ieee80211_ratectl_none.c optional wlan net80211/ieee80211_regdomain.c optional wlan net80211/ieee80211_rssadapt.c optional wlan wlan_rssadapt net80211/ieee80211_scan.c optional wlan diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index f9b981b..24982fe 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -66,10 +66,6 @@ __FBSDID("$FreeBSD$"); #include <dev/acpica/acpivar.h> #include <dev/acpica/acpiio.h> -#include "pci_if.h" -#include <dev/pci/pcivar.h> -#include <dev/pci/pci_private.h> - #include <vm/vm_param.h> MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices"); @@ -133,8 +129,7 @@ static ACPI_STATUS acpi_device_scan_cb(ACPI_HANDLE h, UINT32 level, void *context, void **retval); static ACPI_STATUS acpi_device_scan_children(device_t bus, device_t dev, int max_depth, acpi_scan_cb_t user_fn, void *arg); -static int acpi_set_powerstate_method(device_t bus, device_t child, - int state); +static int acpi_set_powerstate(device_t child, int state); static int acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids); static void acpi_probe_children(device_t bus); @@ -205,9 +200,6 @@ static device_method_t acpi_methods[] = { DEVMETHOD(acpi_pwr_for_sleep, acpi_device_pwr_for_sleep), DEVMETHOD(acpi_scan_children, acpi_device_scan_children), - /* PCI emulation */ - DEVMETHOD(pci_set_powerstate, acpi_set_powerstate_method), - /* ISA emulation */ DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe), @@ -262,12 +254,6 @@ TUNABLE_INT("debug.acpi.interpreter_slack", &acpi_interpreter_slack); SYSCTL_INT(_debug_acpi, OID_AUTO, interpreter_slack, CTLFLAG_RDTUN, &acpi_interpreter_slack, 1, "Turn on interpreter slack mode."); -/* Power devices off and on in suspend and resume. XXX Remove once tested. */ -static int acpi_do_powerstate = 1; -TUNABLE_INT("debug.acpi.do_powerstate", &acpi_do_powerstate); -SYSCTL_INT(_debug_acpi, OID_AUTO, do_powerstate, CTLFLAG_RW, - &acpi_do_powerstate, 1, "Turn off devices when suspending."); - /* Reset system clock while resuming. XXX Remove once tested. */ static int acpi_reset_clock = 1; TUNABLE_INT("debug.acpi.reset_clock", &acpi_reset_clock); @@ -668,45 +654,43 @@ acpi_attach(device_t dev) return_VALUE (error); } +static void +acpi_set_power_children(device_t dev, int state) +{ + device_t child, parent; + device_t *devlist; + struct pci_devinfo *dinfo; + int dstate, i, numdevs; + + if (device_get_children(dev, &devlist, &numdevs) != 0) + return; + + /* + * Retrieve and set D-state for the sleep state if _SxD is present. + * Skip children who aren't attached since they are handled separately. + */ + parent = device_get_parent(dev); + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + dinfo = device_get_ivars(child); + dstate = state; + if (device_is_attached(child) && + acpi_device_pwr_for_sleep(parent, dev, &dstate) == 0) + acpi_set_powerstate(child, dstate); + } + free(devlist, M_TEMP); +} + static int acpi_suspend(device_t dev) { - device_t child, *devlist; - int error, i, numdevs, pstate; + int error; GIANT_REQUIRED; - /* First give child devices a chance to suspend. */ error = bus_generic_suspend(dev); - if (error) - return (error); - - /* - * Now, set them into the appropriate power state, usually D3. If the - * device has an _SxD method for the next sleep state, use that power - * state instead. - */ - error = device_get_children(dev, &devlist, &numdevs); - if (error) - return (error); - for (i = 0; i < numdevs; i++) { - /* If the device is not attached, we've powered it down elsewhere. */ - child = devlist[i]; - if (!device_is_attached(child)) - continue; - - /* - * Default to D3 for all sleep states. The _SxD method is optional - * so set the powerstate even if it's absent. - */ - pstate = PCI_POWERSTATE_D3; - error = acpi_device_pwr_for_sleep(device_get_parent(child), - child, &pstate); - if ((error == 0 || error == ESRCH) && acpi_do_powerstate) - pci_set_powerstate(child, pstate); - } - free(devlist, M_TEMP); - error = 0; + if (error == 0) + acpi_set_power_children(dev, ACPI_STATE_D3); return (error); } @@ -714,28 +698,10 @@ acpi_suspend(device_t dev) static int acpi_resume(device_t dev) { - ACPI_HANDLE handle; - int i, numdevs, error; - device_t child, *devlist; GIANT_REQUIRED; - /* - * Put all devices in D0 before resuming them. Call _S0D on each one - * since some systems expect this. - */ - error = device_get_children(dev, &devlist, &numdevs); - if (error) - return (error); - for (i = 0; i < numdevs; i++) { - child = devlist[i]; - handle = acpi_get_handle(child); - if (handle) - AcpiEvaluateObject(handle, "_S0D", NULL, NULL); - if (device_is_attached(child) && acpi_do_powerstate) - pci_set_powerstate(child, PCI_POWERSTATE_D0); - } - free(devlist, M_TEMP); + acpi_set_power_children(dev, ACPI_STATE_D0); return (bus_generic_resume(dev)); } @@ -811,7 +777,7 @@ static void acpi_probe_nomatch(device_t bus, device_t child) { #ifdef ACPI_ENABLE_POWERDOWN_NODRIVER - pci_set_powerstate(child, PCI_POWERSTATE_D3); + acpi_set_powerstate(child, ACPI_STATE_D3); #endif } @@ -833,9 +799,9 @@ acpi_driver_added(device_t dev, driver_t *driver) child = devlist[i]; if (device_get_state(child) == DS_NOTPRESENT) { #ifdef ACPI_ENABLE_POWERDOWN_NODRIVER - pci_set_powerstate(child, PCI_POWERSTATE_D0); + acpi_set_powerstate(child, ACPI_STATE_D0); if (device_probe_and_attach(child) != 0) - pci_set_powerstate(child, PCI_POWERSTATE_D3); + acpi_set_powerstate(child, ACPI_STATE_D3); #else device_probe_and_attach(child); #endif @@ -1401,9 +1367,7 @@ acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate) ACPI_HANDLE handle; ACPI_STATUS status; char sxd[8]; - int error; - sc = device_get_softc(bus); handle = acpi_get_handle(dev); /* @@ -1412,7 +1376,7 @@ acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate) * set to D3 and it appears that such legacy devices may * need special handling in their drivers. */ - if (handle == NULL || + if (dstate == NULL || handle == NULL || acpi_MatchHid(handle, "PNP0500") || acpi_MatchHid(handle, "PNP0501") || acpi_MatchHid(handle, "PNP0502") || @@ -1421,28 +1385,19 @@ acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate) return (ENXIO); /* - * Override next state with the value from _SxD, if present. If no - * dstate argument was provided, don't fetch the return value. + * Override next state with the value from _SxD, if present. + * Note illegal _S0D is evaluated because some systems expect this. */ + sc = device_get_softc(bus); snprintf(sxd, sizeof(sxd), "_S%dD", sc->acpi_sstate); - if (dstate) - status = acpi_GetInteger(handle, sxd, dstate); - else - status = AcpiEvaluateObject(handle, sxd, NULL, NULL); - - switch (status) { - case AE_OK: - error = 0; - break; - case AE_NOT_FOUND: - error = ESRCH; - break; - default: - error = ENXIO; - break; + status = acpi_GetInteger(handle, sxd, dstate); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + device_printf(dev, "failed to get %s on %s: %s\n", sxd, + acpi_name(handle), AcpiFormatException(status)); + return (ENXIO); } - return (error); + return (0); } /* Callback arg for our implementation of walking the namespace. */ @@ -1524,13 +1479,11 @@ acpi_device_scan_children(device_t bus, device_t dev, int max_depth, * device power states since it's close enough to ACPI. */ static int -acpi_set_powerstate_method(device_t bus, device_t child, int state) +acpi_set_powerstate(device_t child, int state) { ACPI_HANDLE h; ACPI_STATUS status; - int error; - error = 0; h = acpi_get_handle(child); if (state < ACPI_STATE_D0 || state > ACPI_D_STATES_MAX) return (EINVAL); @@ -1539,12 +1492,16 @@ acpi_set_powerstate_method(device_t bus, device_t child, int state) /* Ignore errors if the power methods aren't present. */ status = acpi_pwr_switch_consumer(h, state); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND - && status != AE_BAD_PARAMETER) - device_printf(bus, "failed to set ACPI power state D%d on %s: %s\n", - state, acpi_name(h), AcpiFormatException(status)); + if (ACPI_SUCCESS(status)) { + if (bootverbose) + device_printf(child, "set ACPI power state D%d on %s\n", + state, acpi_name(h)); + } else if (status != AE_NOT_FOUND) + device_printf(child, + "failed to set ACPI power state D%d on %s: %s\n", state, + acpi_name(h), AcpiFormatException(status)); - return (error); + return (0); } static int diff --git a/sys/dev/acpica/acpi_if.m b/sys/dev/acpica/acpi_if.m index 36fad85..f0a68e3 100644 --- a/sys/dev/acpica/acpi_if.m +++ b/sys/dev/acpica/acpi_if.m @@ -123,8 +123,7 @@ METHOD ACPI_STATUS evaluate_object { # # int *dstate: if successful, contains the highest valid sleep state # -# Returns: 0 on success, ESRCH if device has no special state, or -# some other error value. +# Returns: 0 on success or some other error value. # METHOD int pwr_for_sleep { device_t bus; diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c index 9cf064e..bf7cf2e 100644 --- a/sys/dev/acpica/acpi_pci.c +++ b/sys/dev/acpica/acpi_pci.c @@ -186,11 +186,15 @@ acpi_pci_set_powerstate_method(device_t dev, device_t child, int state) } h = acpi_get_handle(child); status = acpi_pwr_switch_consumer(h, state); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) + if (ACPI_SUCCESS(status)) { + if (bootverbose) + device_printf(dev, "set ACPI power state D%d on %s\n", + state, acpi_name(h)); + } else if (status != AE_NOT_FOUND) device_printf(dev, - "Failed to set ACPI power state D%d on %s: %s\n", + "failed to set ACPI power state D%d on %s: %s\n", state, acpi_name(h), AcpiFormatException(status)); - if (old_state > state) + if (old_state > state && pci_do_power_resume) error = pci_set_powerstate_method(dev, child, state); out: diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 8c0ea9d..f40dcc2 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -83,6 +83,7 @@ static void bswap(int8_t *, int); static void btrim(int8_t *, int); static void bpack(int8_t *, int8_t *, int); static void ata_interrupt_locked(void *data); +static void ata_periodic_poll(void *data); /* global vars */ MALLOC_DEFINE(M_ATA, "ata_generic", "ATA driver generic layer"); @@ -173,6 +174,7 @@ ata_attach(device_t dev) ch->curr[i] = ch->user[i]; } #endif + callout_init(&ch->poll_callout, 1); /* reset the controller HW, the channel and device(s) */ while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit) @@ -200,6 +202,8 @@ ata_attach(device_t dev) device_printf(dev, "unable to setup interrupt\n"); return error; } + if (ch->flags & ATA_PERIODIC_POLL) + callout_reset(&ch->poll_callout, hz, ata_periodic_poll, ch); #ifndef ATA_CAM /* probe and attach devices on this channel unless we are in early boot */ @@ -246,6 +250,8 @@ err2: err1: bus_release_resource(dev, SYS_RES_IRQ, rid, ch->r_irq); mtx_unlock(&ch->state_mtx); + if (ch->flags & ATA_PERIODIC_POLL) + callout_drain(&ch->poll_callout); return (error); #endif } @@ -267,6 +273,8 @@ ata_detach(device_t dev) mtx_lock(&ch->state_mtx); ch->state |= ATA_STALL_QUEUE; mtx_unlock(&ch->state_mtx); + if (ch->flags & ATA_PERIODIC_POLL) + callout_drain(&ch->poll_callout); #ifndef ATA_CAM /* detach & delete all children */ @@ -454,6 +462,8 @@ ata_suspend(device_t dev) if (!dev || !(ch = device_get_softc(dev))) return ENXIO; + if (ch->flags & ATA_PERIODIC_POLL) + callout_drain(&ch->poll_callout); #ifdef ATA_CAM mtx_lock(&ch->state_mtx); xpt_freeze_simq(ch->sim, 1); @@ -498,6 +508,8 @@ ata_resume(device_t dev) /* kick off requests on the queue */ ata_start(dev); #endif + if (ch->flags & ATA_PERIODIC_POLL) + callout_reset(&ch->poll_callout, hz, ata_periodic_poll, ch); return error; } @@ -564,6 +576,15 @@ ata_interrupt_locked(void *data) #endif } +static void +ata_periodic_poll(void *data) +{ + struct ata_channel *ch = (struct ata_channel *)data; + + callout_reset(&ch->poll_callout, hz, ata_periodic_poll, ch); + ata_interrupt(ch); +} + void ata_print_cable(device_t dev, u_int8_t *who) { diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 0f09a1f..17a28c0 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -114,13 +114,6 @@ #define ATA_SS_IPM_PARTIAL 0x00000200 #define ATA_SS_IPM_SLUMBER 0x00000600 -#define ATA_SS_CONWELL_MASK \ - (ATA_SS_DET_MASK|ATA_SS_SPD_MASK|ATA_SS_IPM_MASK) -#define ATA_SS_CONWELL_GEN1 \ - (ATA_SS_DET_PHY_ONLINE|ATA_SS_SPD_GEN1|ATA_SS_IPM_ACTIVE) -#define ATA_SS_CONWELL_GEN2 \ - (ATA_SS_DET_PHY_ONLINE|ATA_SS_SPD_GEN2|ATA_SS_IPM_ACTIVE) - #define ATA_SERROR 14 #define ATA_SE_DATA_CORRECTED 0x00000001 #define ATA_SE_COMM_CORRECTED 0x00000002 @@ -567,6 +560,7 @@ struct ata_channel { #define ATA_DMA_BEFORE_CMD 0x100 #define ATA_KNOWN_PRESENCE 0x200 #define ATA_STATUS_IS_LONG 0x400 +#define ATA_PERIODIC_POLL 0x800 int pm_level; /* power management level */ int devices; /* what is present */ @@ -593,6 +587,7 @@ struct ata_channel { struct ata_cam_device user[16]; /* User-specified settings */ struct ata_cam_device curr[16]; /* Current settings */ #endif + struct callout poll_callout; /* Periodic status poll. */ }; /* disk bay/enclosure related */ @@ -666,7 +661,7 @@ void ata_dmainit(device_t); void ata_dmafini(device_t dev); /* ata-sata.c: */ -void ata_sata_phy_check_events(device_t dev); +void ata_sata_phy_check_events(device_t dev, int port); int ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val); int ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val); int ata_sata_phy_reset(device_t dev, int port, int quick); diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index c847e90..cf579f8 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -615,6 +615,7 @@ ata_pcichannel_attach(device_t dev) return (0); ch->attached = 1; + ch->dev = dev; ch->unit = (intptr_t)device_get_ivars(dev); resource_int_value(device_get_name(dev), diff --git a/sys/dev/ata/ata-sata.c b/sys/dev/ata/ata-sata.c index d4c52fd..d3df7ce 100644 --- a/sys/dev/ata/ata-sata.c +++ b/sys/dev/ata/ata-sata.c @@ -48,20 +48,23 @@ __FBSDID("$FreeBSD$"); #include <ata_if.h> void -ata_sata_phy_check_events(device_t dev) +ata_sata_phy_check_events(device_t dev, int port) { struct ata_channel *ch = device_get_softc(dev); - u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR); + u_int32_t error, status; - /* clear error bits/interrupt */ - ATA_IDX_OUTL(ch, ATA_SERROR, error); + ata_sata_scr_read(ch, port, ATA_SERROR, &error); + /* Clear set error bits/interrupt. */ + if (error) + ata_sata_scr_write(ch, port, ATA_SERROR, error); /* if we have a connection event deal with it */ if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) { if (bootverbose) { - u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS); - if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) || - ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)) { + ata_sata_scr_read(ch, port, ATA_SSTATUS, &status); + if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) && + ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) && + ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) { device_printf(dev, "CONNECT requested\n"); } else device_printf(dev, "DISCONNECT requested\n"); @@ -73,69 +76,51 @@ ata_sata_phy_check_events(device_t dev) int ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val) { - int r; - if (port < 0) { + if (ch->hw.pm_read != NULL) + return (ch->hw.pm_read(ch->dev, port, reg, val)); + if (ch->r_io[reg].res) { *val = ATA_IDX_INL(ch, reg); return (0); - } else { - switch (reg) { - case ATA_SSTATUS: - r = 0; - break; - case ATA_SERROR: - r = 1; - break; - case ATA_SCONTROL: - r = 2; - break; - default: - return (EINVAL); - } - return (ch->hw.pm_read(ch->dev, port, r, val)); } + return (-1); } int ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val) { - int r; - if (port < 0) { + if (ch->hw.pm_write != NULL) + return (ch->hw.pm_write(ch->dev, port, reg, val)); + if (ch->r_io[reg].res) { ATA_IDX_OUTL(ch, reg, val); return (0); - } else { - switch (reg) { - case ATA_SERROR: - r = 1; - break; - case ATA_SCONTROL: - r = 2; - break; - default: - return (EINVAL); - } - return (ch->hw.pm_write(ch->dev, port, r, val)); } + return (-1); } static int -ata_sata_connect(struct ata_channel *ch, int port) +ata_sata_connect(struct ata_channel *ch, int port, int quick) { u_int32_t status; - int timeout; + int timeout, t; /* wait up to 1 second for "connect well" */ - for (timeout = 0; timeout < 100 ; timeout++) { + timeout = (quick == 2) ? 0 : 100; + t = 0; + while (1) { if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status)) return (0); - if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 || - (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2) + if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) && + ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) && + ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) + break; + if (++t > timeout) break; ata_udelay(10000); } - if (timeout >= 100) { - if (bootverbose) { + if (bootverbose) { + if (t > timeout) { if (port < 0) { device_printf(ch->dev, "SATA connect timeout status=%08x\n", status); @@ -143,23 +128,19 @@ ata_sata_connect(struct ata_channel *ch, int port) device_printf(ch->dev, "p%d: SATA connect timeout status=%08x\n", port, status); } - } - return 0; - } - if (bootverbose) { - if (port < 0) { + } else if (port < 0) { device_printf(ch->dev, "SATA connect time=%dms status=%08x\n", - timeout * 10, status); + t * 10, status); } else { device_printf(ch->dev, "p%d: SATA connect time=%dms status=%08x\n", - port, timeout * 10, status); + port, t * 10, status); } } /* clear SATA error register */ ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff); - return 1; + return ((t > timeout) ? 0 : 1); } int @@ -173,7 +154,7 @@ ata_sata_phy_reset(device_t dev, int port, int quick) if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val)) return (0); if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE) - return ata_sata_connect(ch, port); + return ata_sata_connect(ch, port, quick); } if (bootverbose) { @@ -203,7 +184,7 @@ ata_sata_phy_reset(device_t dev, int port, int quick) if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val)) return (0); if ((val & ATA_SC_DET_MASK) == 0) - return ata_sata_connect(ch, port); + return ata_sata_connect(ch, port, 0); } } return 0; diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c index 7496f6b..4a240d7 100644 --- a/sys/dev/ata/chipsets/ata-ahci.c +++ b/sys/dev/ata/chipsets/ata-ahci.c @@ -403,7 +403,7 @@ ata_ahci_status(device_t dev) /* do we have any PHY events ? */ if (istatus & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) - ata_sata_phy_check_events(dev); + ata_sata_phy_check_events(dev, -1); /* do we have a potentially hanging engine to take care of? */ /* XXX SOS what todo on NCQ */ @@ -623,6 +623,25 @@ ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result) (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40; + if (port < 0) { + *result = ATA_IDX_INL(ch, reg); + return (0); + } + if (port < ATA_PM) { + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SERROR: + reg = 1; + break; + case ATA_SCONTROL: + reg = 2; + break; + default: + return (EINVAL); + } + } bzero(ctp->cfis, 64); ctp->cfis[0] = 0x27; /* host to device */ ctp->cfis[1] = 0x8f; /* command FIS to PM port */ @@ -649,6 +668,25 @@ ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t value) (struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET); int offset = ch->unit << 7; + if (port < 0) { + ATA_IDX_OUTL(ch, reg, value); + return (0); + } + if (port < ATA_PM) { + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SERROR: + reg = 1; + break; + case ATA_SCONTROL: + reg = 2; + break; + default: + return (EINVAL); + } + } bzero(ctp->cfis, 64); ctp->cfis[0] = 0x27; /* host to device */ ctp->cfis[1] = 0x8f; /* command FIS to PM port */ diff --git a/sys/dev/ata/chipsets/ata-intel.c b/sys/dev/ata/chipsets/ata-intel.c index 0f47bc7..ba602aa 100644 --- a/sys/dev/ata/chipsets/ata-intel.c +++ b/sys/dev/ata/chipsets/ata-intel.c @@ -59,6 +59,15 @@ static int ata_intel_old_setmode(device_t dev, int target, int mode); static int ata_intel_new_setmode(device_t dev, int target, int mode); static int ata_intel_sch_setmode(device_t dev, int target, int mode); static int ata_intel_sata_getrev(device_t dev, int target); +static int ata_intel_sata_status(device_t dev); +static int ata_intel_sata_cscr_read(device_t dev, int port, + int reg, u_int32_t *result); +static int ata_intel_sata_sidpr_read(device_t dev, int port, + int reg, u_int32_t *result); +static int ata_intel_sata_cscr_write(device_t dev, int port, + int reg, u_int32_t result); +static int ata_intel_sata_sidpr_write(device_t dev, int port, + int reg, u_int32_t result); static int ata_intel_31244_ch_attach(device_t dev); static int ata_intel_31244_ch_detach(device_t dev); static int ata_intel_31244_status(device_t dev); @@ -67,7 +76,9 @@ static void ata_intel_31244_reset(device_t dev); /* misc defines */ #define INTEL_AHCI 1 - +#define INTEL_ICH5 2 +#define INTEL_6CH 4 +#define INTEL_6CH2 8 /* * Intel chipset support functions @@ -92,74 +103,74 @@ ata_intel_probe(device_t dev) { ATA_I82801DB, 0, 0, 2, ATA_UDMA5, "ICH4" }, { ATA_I82801DB_1, 0, 0, 2, ATA_UDMA5, "ICH4" }, { ATA_I82801EB, 0, 0, 2, ATA_UDMA5, "ICH5" }, - { ATA_I82801EB_S1, 0, 0, 2, ATA_SA150, "ICH5" }, - { ATA_I82801EB_R1, 0, 0, 2, ATA_SA150, "ICH5" }, + { ATA_I82801EB_S1, 0, INTEL_ICH5, 2, ATA_SA150, "ICH5" }, + { ATA_I82801EB_R1, 0, INTEL_ICH5, 2, ATA_SA150, "ICH5" }, { ATA_I6300ESB, 0, 0, 2, ATA_UDMA5, "6300ESB" }, - { ATA_I6300ESB_S1, 0, 0, 2, ATA_SA150, "6300ESB" }, - { ATA_I6300ESB_R1, 0, 0, 2, ATA_SA150, "6300ESB" }, + { ATA_I6300ESB_S1, 0, INTEL_ICH5, 2, ATA_SA150, "6300ESB" }, + { ATA_I6300ESB_R1, 0, INTEL_ICH5, 2, ATA_SA150, "6300ESB" }, { ATA_I82801FB, 0, 0, 2, ATA_UDMA5, "ICH6" }, { ATA_I82801FB_S1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH6" }, { ATA_I82801FB_R1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH6" }, { ATA_I82801FBM, 0, INTEL_AHCI, 0, ATA_SA150, "ICH6M" }, { ATA_I82801GB, 0, 0, 1, ATA_UDMA5, "ICH7" }, - { ATA_I82801GB_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH7" }, - { ATA_I82801GB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH7" }, + { ATA_I82801GB_S1, 0, 0, 0, ATA_SA300, "ICH7" }, + { ATA_I82801GB_R1, 0, 0, 0, ATA_SA300, "ICH7" }, { ATA_I82801GB_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH7" }, - { ATA_I82801GBM_S1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" }, - { ATA_I82801GBM_R1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" }, + { ATA_I82801GBM_S1, 0, 0, 0, ATA_SA150, "ICH7M" }, + { ATA_I82801GBM_R1, 0, 0, 0, ATA_SA150, "ICH7M" }, { ATA_I82801GBM_AH, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" }, { ATA_I63XXESB2, 0, 0, 1, ATA_UDMA5, "63XXESB2" }, - { ATA_I63XXESB2_S1, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" }, + { ATA_I63XXESB2_S1, 0, 0, 0, ATA_SA300, "63XXESB2" }, { ATA_I63XXESB2_S2, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" }, { ATA_I63XXESB2_R1, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" }, { ATA_I63XXESB2_R2, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" }, - { ATA_I82801HB_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" }, - { ATA_I82801HB_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" }, + { ATA_I82801HB_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH8" }, + { ATA_I82801HB_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH8" }, { ATA_I82801HB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" }, { ATA_I82801HB_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" }, { ATA_I82801HB_AH6, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" }, { ATA_I82801HBM, 0, 0, 1, ATA_UDMA5, "ICH8M" }, - { ATA_I82801HBM_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" }, + { ATA_I82801HBM_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH8M" }, { ATA_I82801HBM_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" }, { ATA_I82801HBM_S3, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" }, - { ATA_I82801IB_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, - { ATA_I82801IB_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, + { ATA_I82801IB_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH9" }, + { ATA_I82801IB_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH9" }, { ATA_I82801IB_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, { ATA_I82801IB_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, { ATA_I82801IB_AH6, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, { ATA_I82801IB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" }, - { ATA_I82801JIB_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JIB_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH10" }, { ATA_I82801JIB_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, { ATA_I82801JIB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JIB_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JD_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JIB_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JD_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH10" }, { ATA_I82801JD_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, { ATA_I82801JD_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JD_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JI_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JD_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH10" }, + { ATA_I82801JI_S1, 0, INTEL_6CH, 0, ATA_SA300, "ICH10" }, { ATA_I82801JI_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, { ATA_I82801JI_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_I82801JI_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" }, - { ATA_5Series_S1, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, - { ATA_5Series_S2, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, + { ATA_I82801JI_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH10" }, + { ATA_5Series_S1, 0, INTEL_6CH, 0, ATA_SA300, "5 Series/3400 Series PCH" }, + { ATA_5Series_S2, 0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" }, { ATA_5Series_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, { ATA_5Series_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, { ATA_5Series_R1, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, - { ATA_5Series_S3, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, - { ATA_5Series_S4, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, + { ATA_5Series_S3, 0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" }, + { ATA_5Series_S4, 0, INTEL_6CH, 0, ATA_SA300, "5 Series/3400 Series PCH" }, { ATA_5Series_AH3, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, { ATA_5Series_R2, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, - { ATA_5Series_S5, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, - { ATA_5Series_S6, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, + { ATA_5Series_S5, 0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" }, + { ATA_5Series_S6, 0, INTEL_6CH, 0, ATA_SA300, "5 Series/3400 Series PCH" }, { ATA_5Series_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" }, - { ATA_CPT_S1, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, - { ATA_CPT_S2, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, + { ATA_CPT_S1, 0, INTEL_6CH, 0, ATA_SA300, "Cougar Point" }, + { ATA_CPT_S2, 0, INTEL_6CH, 0, ATA_SA300, "Cougar Point" }, { ATA_CPT_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, { ATA_CPT_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, { ATA_CPT_R1, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, { ATA_CPT_R2, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, - { ATA_CPT_S3, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, - { ATA_CPT_S4, 0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" }, + { ATA_CPT_S3, 0, INTEL_6CH2, 0, ATA_SA300, "Cougar Point" }, + { ATA_CPT_S4, 0, INTEL_6CH2, 0, ATA_SA300, "Cougar Point" }, { ATA_I31244, 0, 0, 2, ATA_SA150, "31244" }, { ATA_ISCH, 0, 0, 1, ATA_UDMA5, "SCH" }, { 0, 0, 0, 0, 0, 0}}; @@ -183,6 +194,8 @@ ata_intel_chipinit(device_t dev) if (ata_setup_interrupt(dev, ata_generic_intr)) return ENXIO; + ctlr->chipset_data = NULL; + /* good old PIIX needs special treatment (not implemented) */ if (ctlr->chip->chipid == ATA_I82371FB) { ctlr->setmode = ata_intel_old_setmode; @@ -233,7 +246,7 @@ ata_intel_chipinit(device_t dev) * if we have AHCI capability and AHCI or RAID mode enabled * in BIOS we try for AHCI mode */ - if ((ctlr->chip->cfg1 == INTEL_AHCI) && + if ((ctlr->chip->cfg1 & INTEL_AHCI) && (pci_read_config(dev, 0x90, 1) & 0xc0) && (ata_ahci_chipinit(dev) != ENXIO)) return 0; @@ -242,7 +255,8 @@ ata_intel_chipinit(device_t dev) ctlr->r_type2 = SYS_RES_IOPORT; ctlr->r_rid2 = PCIR_BAR(5); if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, - &ctlr->r_rid2, RF_ACTIVE))) + &ctlr->r_rid2, RF_ACTIVE)) + || (ctlr->chip->cfg1 & INTEL_ICH5)) ctlr->getrev = ata_intel_sata_getrev; ctlr->setmode = ata_sata_setmode; } @@ -252,63 +266,142 @@ ata_intel_chipinit(device_t dev) static int ata_intel_ch_attach(device_t dev) { - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - /* setup the usual register normal pci style */ - if (ata_pci_ch_attach(dev)) - return ENXIO; - - /* if r_res2 is valid it points to SATA interface registers */ - if (ctlr->r_res2) { - ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2; - ch->r_io[ATA_IDX_ADDR].offset = 0x00; - ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2; - ch->r_io[ATA_IDX_DATA].offset = 0x04; - } + struct ata_pci_controller *ctlr; + struct ata_channel *ch; + u_char *smap; + u_int map; + + /* setup the usual register normal pci style */ + if (ata_pci_ch_attach(dev)) + return (ENXIO); + + ctlr = device_get_softc(device_get_parent(dev)); + ch = device_get_softc(dev); + + /* if r_res2 is valid it points to SATA interface registers */ + if (ctlr->r_res2) { + ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2; + ch->r_io[ATA_IDX_ADDR].offset = 0x00; + ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2; + ch->r_io[ATA_IDX_DATA].offset = 0x04; + } - ch->flags |= ATA_ALWAYS_DMASTAT; - if (ctlr->chip->max_dma >= ATA_SA150) { - if (ctlr->chip->cfg1 == 0 && - (pci_read_config(device_get_parent(dev), 0x90, 1) & 0x04) == 0) - ch->flags |= ATA_NO_SLAVE; - ch->flags |= ATA_SATA; - } else if (ctlr->chip->chipid != ATA_ISCH) - ch->flags |= ATA_CHECKS_CABLE; - return 0; + ch->flags |= ATA_ALWAYS_DMASTAT; + if (ctlr->chip->max_dma >= ATA_SA150) { + smap = (u_char *)&ctlr->chipset_data + ch->unit * 2; + map = pci_read_config(device_get_parent(dev), 0x90, 1); + if (ctlr->chip->cfg1 & INTEL_ICH5) { + map &= 0x07; + if ((map & 0x04) == 0) { + ch->flags |= ATA_SATA; + ch->flags |= ATA_NO_SLAVE; + smap[0] = (map & 0x01) ^ ch->unit; + smap[1] = 0; + } else if ((map & 0x02) == 0 && ch->unit == 0) { + ch->flags |= ATA_SATA; + smap[0] = (map & 0x01) ? 1 : 0; + smap[1] = (map & 0x01) ? 0 : 1; + } else if ((map & 0x02) != 0 && ch->unit == 1) { + ch->flags |= ATA_SATA; + smap[0] = (map & 0x01) ? 1 : 0; + smap[1] = (map & 0x01) ? 0 : 1; + } + } else if (ctlr->chip->cfg1 & INTEL_6CH2) { + ch->flags |= ATA_SATA; + ch->flags |= ATA_NO_SLAVE; + smap[0] = (ch->unit == 0) ? 4 : 5; + smap[1] = 0; + } else { + map &= 0x03; + if (map == 0x00) { + ch->flags |= ATA_SATA; + smap[ch->unit] = (ch->unit == 0) ? 0x20 : 0x31; + smap[0] = (ch->unit == 0) ? 0 : 1; + smap[1] = (ch->unit == 0) ? 2 : 3; + } else if (map == 0x02 && ch->unit == 0) { + ch->flags |= ATA_SATA; + smap[0] = 0; + smap[1] = 2; + } else if (map == 0x01 && ch->unit == 1) { + ch->flags |= ATA_SATA; + smap[0] = 1; + smap[1] = 3; + } + } + if (ch->flags & ATA_SATA) { + if ((ctlr->chip->cfg1 & INTEL_ICH5)) { + ch->flags |= ATA_PERIODIC_POLL; + ch->hw.status = ata_intel_sata_status; + ch->hw.pm_read = ata_intel_sata_cscr_read; + ch->hw.pm_write = ata_intel_sata_cscr_write; + } else if (ctlr->r_res2) { + ch->flags |= ATA_PERIODIC_POLL; + ch->hw.status = ata_intel_sata_status; + ch->hw.pm_read = ata_intel_sata_sidpr_read; + ch->hw.pm_write = ata_intel_sata_sidpr_write; + } + if (ch->hw.pm_write != NULL) { + ata_sata_scr_write(ch, 0, + ATA_SERROR, 0xffffffff); + if ((ch->flags & ATA_NO_SLAVE) == 0) { + ata_sata_scr_write(ch, 1, + ATA_SERROR, 0xffffffff); + } + } + } else + ctlr->setmode = ata_intel_new_setmode; + } else if (ctlr->chip->chipid != ATA_ISCH) + ch->flags |= ATA_CHECKS_CABLE; + return (0); } static void ata_intel_reset(device_t dev) { - device_t parent = device_get_parent(dev); - struct ata_pci_controller *ctlr = device_get_softc(parent); - struct ata_channel *ch = device_get_softc(dev); - int mask, timeout; + device_t parent = device_get_parent(dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + struct ata_channel *ch = device_get_softc(dev); + int mask, pmask, timeout, devs; + u_char *smap; + + /* In combined mode, skip SATA stuff for PATA channel. */ + if ((ch->flags & ATA_SATA) == 0) + return (ata_generic_reset(dev)); + + /* Do hard-reset on respective SATA ports. */ + smap = (u_char *)&ctlr->chipset_data + ch->unit * 2; + mask = 1 << smap[0]; + if ((ch->flags & ATA_NO_SLAVE) == 0) + mask |= (1 << smap[1]); + pci_write_config(parent, 0x92, + pci_read_config(parent, 0x92, 2) & ~mask, 2); + DELAY(10); + pci_write_config(parent, 0x92, + pci_read_config(parent, 0x92, 2) | mask, 2); + + /* Wait up to 1 sec for "connect well". */ + if (ctlr->chip->cfg1 & (INTEL_6CH | INTEL_6CH2)) + pmask = mask << 8; + else + pmask = mask << 4; + for (timeout = 0; timeout < 100 ; timeout++) { + if (((pci_read_config(parent, 0x92, 2) & pmask) == pmask) && + (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) + break; + ata_udelay(10000); + } - /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */ - if (ctlr->chip->cfg1) { - mask = (0x0005 << ch->unit); - } - else { - /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */ - if (pci_read_config(parent, 0x90, 1) & 0x04) - mask = 0x0003; + /* If any device found, do soft-reset. */ + if (ch->hw.pm_read != NULL) { + devs = ata_sata_phy_reset(dev, 0, 2); + if ((ch->flags & ATA_NO_SLAVE) == 0) + devs += ata_sata_phy_reset(dev, 1, 2); + } else + devs = 1; + if (devs) + ata_generic_reset(dev); else - mask = (0x0001 << ch->unit); - } - pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) & ~mask, 2); - DELAY(10); - pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) | mask, 2); - - /* wait up to 1 sec for "connect well" */ - for (timeout = 0; timeout < 100 ; timeout++) { - if (((pci_read_config(parent, 0x92, 2) & (mask << 4)) == (mask << 4)) && - (ATA_IDX_INB(ch, ATA_STATUS) != 0xff)) - break; - ata_udelay(10000); - } - ata_generic_reset(dev); + ch->devices = 0; } static int @@ -339,6 +432,10 @@ ata_intel_new_setmode(device_t dev, int target, int mode) u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x00, 0x21, 0x23 }; u_int8_t utimings[] = { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 }; + /* In combined mode, skip PATA stuff for SATA channel. */ + if (ch->flags & ATA_SATA) + return (ata_sata_setmode(dev, target, mode)); + mode = min(mode, ctlr->chip->max_dma); if (ata_dma_check_80pin && mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { @@ -421,12 +518,145 @@ static int ata_intel_sata_getrev(device_t dev, int target) { struct ata_channel *ch = device_get_softc(dev); - int devno = (ch->unit << 1) + target; + uint32_t status; - /* set ATA_SSTATUS register offset */ - ATA_IDX_OUTL(ch, ATA_IDX_ADDR, devno * 0x100); - /* query SATA STATUS for the speed */ - return ((ATA_IDX_INL(ch, ATA_IDX_DATA) & 0x0f0) >> 4); + if (ata_sata_scr_read(ch, target, ATA_SSTATUS, &status) == 0) + return ((status & 0x0f0) >> 4); + return (0xff); +} + +static int +ata_intel_sata_status(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + + ata_sata_phy_check_events(dev, 0); + if ((ch->flags & ATA_NO_SLAVE) == 0) + ata_sata_phy_check_events(dev, 1); + + return ata_pci_status(dev); +} + +static int +ata_intel_sata_cscr_read(device_t dev, int port, int reg, u_int32_t *result) +{ + struct ata_pci_controller *ctlr; + struct ata_channel *ch; + device_t parent; + u_char *smap; + + parent = device_get_parent(dev); + ctlr = device_get_softc(parent); + ch = device_get_softc(dev); + smap = (u_char *)&ctlr->chipset_data + ch->unit * 2; + port = (port == 1) ? 1 : 0; + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SERROR: + reg = 1; + break; + case ATA_SCONTROL: + reg = 2; + break; + default: + return (EINVAL); + } + pci_write_config(parent, 0xa0, + 0x50 + smap[port] * 0x10 + reg * 4, 4); + *result = pci_read_config(parent, 0xa4, 4); + return (0); +} + +static int +ata_intel_sata_sidpr_read(device_t dev, int port, int reg, u_int32_t *result) +{ + struct ata_pci_controller *ctlr; + struct ata_channel *ch; + device_t parent; + + parent = device_get_parent(dev); + ctlr = device_get_softc(parent); + ch = device_get_softc(dev); + port = (port == 1) ? 1 : 0; + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SCONTROL: + reg = 1; + break; + case ATA_SERROR: + reg = 2; + break; + default: + return (EINVAL); + } + ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg); + *result = ATA_IDX_INL(ch, ATA_IDX_DATA); + return (0); +} + +static int +ata_intel_sata_cscr_write(device_t dev, int port, int reg, u_int32_t value) +{ + struct ata_pci_controller *ctlr; + struct ata_channel *ch; + device_t parent; + u_char *smap; + + parent = device_get_parent(dev); + ctlr = device_get_softc(parent); + ch = device_get_softc(dev); + smap = (u_char *)&ctlr->chipset_data + ch->unit * 2; + port = (port == 1) ? 1 : 0; + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SERROR: + reg = 1; + break; + case ATA_SCONTROL: + reg = 2; + break; + default: + return (EINVAL); + } + pci_write_config(parent, 0xa0, + 0x50 + smap[port] * 0x10 + reg * 4, 4); + pci_write_config(parent, 0xa4, value, 4); + return (0); +} + +static int +ata_intel_sata_sidpr_write(device_t dev, int port, int reg, u_int32_t value) +{ + struct ata_pci_controller *ctlr; + struct ata_channel *ch; + device_t parent; + + parent = device_get_parent(dev); + ctlr = device_get_softc(parent); + ch = device_get_softc(dev); + port = (port == 1) ? 1 : 0; + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SCONTROL: + reg = 1; + break; + case ATA_SERROR: + reg = 2; + break; + default: + return (EINVAL); + } + ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg); + ATA_IDX_OUTL(ch, ATA_IDX_DATA, value); + return (0); } static int @@ -492,7 +722,7 @@ static int ata_intel_31244_status(device_t dev) { /* do we have any PHY events ? */ - ata_sata_phy_check_events(dev); + ata_sata_phy_check_events(dev, -1); /* any drive action to take care of ? */ return ata_pci_status(dev); diff --git a/sys/dev/ata/chipsets/ata-marvell.c b/sys/dev/ata/chipsets/ata-marvell.c index 371d951..eb6414e 100644 --- a/sys/dev/ata/chipsets/ata-marvell.c +++ b/sys/dev/ata/chipsets/ata-marvell.c @@ -374,7 +374,7 @@ ata_marvell_edma_status(device_t dev) ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0); /* do we have any PHY events ? */ - ata_sata_phy_check_events(dev); + ata_sata_phy_check_events(dev, -1); } /* do we have any device action ? */ diff --git a/sys/dev/ata/chipsets/ata-nvidia.c b/sys/dev/ata/chipsets/ata-nvidia.c index 344e5a4..b1da6f0 100644 --- a/sys/dev/ata/chipsets/ata-nvidia.c +++ b/sys/dev/ata/chipsets/ata-nvidia.c @@ -281,7 +281,7 @@ ata_nvidia_status(device_t dev) /* do we have any PHY events ? */ if (istatus & (0x0c << shift)) - ata_sata_phy_check_events(dev); + ata_sata_phy_check_events(dev, -1); /* clear interrupt(s) */ if (ctlr->chip->cfg1 & NVQ) diff --git a/sys/dev/ata/chipsets/ata-promise.c b/sys/dev/ata/chipsets/ata-promise.c index 8a7bceb..622352b 100644 --- a/sys/dev/ata/chipsets/ata-promise.c +++ b/sys/dev/ata/chipsets/ata-promise.c @@ -830,6 +830,25 @@ ata_promise_mio_pm_read(device_t dev, int port, int reg, u_int32_t *result) struct ata_channel *ch = device_get_softc(dev); int timeout = 0; + if (port < 0) { + *result = ATA_IDX_INL(ch, reg); + return (0); + } + if (port < ATA_PM) { + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SERROR: + reg = 1; + break; + case ATA_SCONTROL: + reg = 2; + break; + default: + return (EINVAL); + } + } /* set portmultiplier port */ ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f); @@ -862,6 +881,25 @@ ata_promise_mio_pm_write(device_t dev, int port, int reg, u_int32_t value) struct ata_channel *ch = device_get_softc(dev); int timeout = 0; + if (port < 0) { + ATA_IDX_OUTL(ch, reg, value); + return (0); + } + if (port < ATA_PM) { + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SERROR: + reg = 1; + break; + case ATA_SCONTROL: + reg = 2; + break; + default: + return (EINVAL); + } + } /* set portmultiplier port */ ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f); diff --git a/sys/dev/ata/chipsets/ata-siliconimage.c b/sys/dev/ata/chipsets/ata-siliconimage.c index f9b90f6..fa7619c 100644 --- a/sys/dev/ata/chipsets/ata-siliconimage.c +++ b/sys/dev/ata/chipsets/ata-siliconimage.c @@ -354,7 +354,7 @@ ata_sii_status(device_t dev) /* do we have any PHY events ? */ if (ctlr->chip->max_dma >= ATA_SA150 && (ATA_INL(ctlr->r_res2, 0x10 + offset0) & 0x00000010)) - ata_sata_phy_check_events(dev); + ata_sata_phy_check_events(dev, -1); if (ATA_INL(ctlr->r_res2, 0xa0 + offset1) & 0x00000800) return ata_pci_status(dev); @@ -510,7 +510,7 @@ ata_siiprb_status(device_t dev) u_int32_t istatus = ATA_INL(ctlr->r_res2, 0x1008 + offset); /* do we have any PHY events ? */ - ata_sata_phy_check_events(dev); + ata_sata_phy_check_events(dev, -1); /* clear interrupt(s) */ ATA_OUTL(ctlr->r_res2, 0x1008 + offset, istatus); @@ -700,6 +700,25 @@ ata_siiprb_pm_read(device_t dev, int port, int reg, u_int32_t *result) struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work; int offset = ch->unit * 0x2000; + if (port < 0) { + *result = ATA_IDX_INL(ch, reg); + return (0); + } + if (port < ATA_PM) { + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SERROR: + reg = 1; + break; + case ATA_SCONTROL: + reg = 2; + break; + default: + return (EINVAL); + } + } bzero(prb, sizeof(struct ata_siiprb_command)); prb->fis[0] = 0x27; /* host to device */ prb->fis[1] = 0x8f; /* command FIS to PM port */ @@ -724,6 +743,25 @@ ata_siiprb_pm_write(device_t dev, int port, int reg, u_int32_t value) struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work; int offset = ch->unit * 0x2000; + if (port < 0) { + ATA_IDX_OUTL(ch, reg, value); + return (0); + } + if (port < ATA_PM) { + switch (reg) { + case ATA_SSTATUS: + reg = 0; + break; + case ATA_SERROR: + reg = 1; + break; + case ATA_SCONTROL: + reg = 2; + break; + default: + return (EINVAL); + } + } bzero(prb, sizeof(struct ata_siiprb_command)); prb->fis[0] = 0x27; /* host to device */ prb->fis[1] = 0x8f; /* command FIS to PM port */ diff --git a/sys/dev/ata/chipsets/ata-via.c b/sys/dev/ata/chipsets/ata-via.c index 8d87f31..284a892 100644 --- a/sys/dev/ata/chipsets/ata-via.c +++ b/sys/dev/ata/chipsets/ata-via.c @@ -56,6 +56,7 @@ static int ata_via_chipinit(device_t dev); static int ata_via_ch_attach(device_t dev); static int ata_via_ch_detach(device_t dev); static void ata_via_reset(device_t dev); +static int ata_via_status(device_t dev); static int ata_via_old_setmode(device_t dev, int target, int mode); static void ata_via_southbridge_fixup(device_t dev); static int ata_via_new_setmode(device_t dev, int target, int mode); @@ -249,11 +250,13 @@ ata_via_ch_attach(device_t dev) ch->r_io[ATA_SERROR].offset = 0x04 + (ch->unit << ctlr->chip->cfg1); ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; ch->r_io[ATA_SCONTROL].offset = 0x08 + (ch->unit << ctlr->chip->cfg1); + ch->hw.status = ata_via_status; ch->flags |= ATA_NO_SLAVE; ch->flags |= ATA_SATA; + ch->flags |= ATA_PERIODIC_POLL; + + ata_sata_scr_write(ch, -1, ATA_SERROR, 0xffffffff); - /* XXX SOS PHY hotplug handling missing in VIA chip ?? */ - /* XXX SOS unknown how to enable PHY state change interrupt */ return 0; } @@ -299,6 +302,14 @@ ata_via_reset(device_t dev) } static int +ata_via_status(device_t dev) +{ + + ata_sata_phy_check_events(dev, -1); + return (ata_pci_status(dev)); +} + +static int ata_via_new_setmode(device_t dev, int target, int mode) { device_t parent = device_get_parent(dev); diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c index edfc047..07a1a42 100644 --- a/sys/dev/firewire/fwohci.c +++ b/sys/dev/firewire/fwohci.c @@ -1971,8 +1971,8 @@ fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat, int count) OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER); #endif OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); - device_printf(fc->dev, "too many cycle lost, " - "no cycle master presents?\n"); + device_printf(fc->dev, "too many cycles lost, " + "no cycle master present?\n"); } } if (stat & OHCI_INT_DMA_ATRQ) { diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index bde2d5b..763ed74 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -1644,10 +1644,6 @@ ndis_linksts_done(adapter) default: break; } - - /* Notify possible listners of interface change. */ - - rt_ifmsg(ifp); } static void diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 47aa751..6c3484e 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -909,18 +909,26 @@ mdcreate_vnode(struct md_s *sc, struct md_ioctl *mdio, struct thread *td) { struct vattr vattr; struct nameidata nd; + char *fname; int error, flags, vfslocked; - error = copyinstr(mdio->md_file, sc->file, sizeof(sc->file), NULL); - if (error != 0) - return (error); - flags = FREAD|FWRITE; /* - * If the user specified that this is a read only device, unset the - * FWRITE mask before trying to open the backing store. + * Kernel-originated requests must have the filename appended + * to the mdio structure to protect against malicious software. + */ + fname = mdio->md_file; + if ((void *)fname != (void *)(mdio + 1)) { + error = copyinstr(fname, sc->file, sizeof(sc->file), NULL); + if (error != 0) + return (error); + } else + strlcpy(sc->file, fname, sizeof(sc->file)); + + /* + * If the user specified that this is a read only device, don't + * set the FWRITE mask before trying to open the backing store. */ - if ((mdio->md_options & MD_READONLY) != 0) - flags &= ~FWRITE; + flags = FREAD | ((mdio->md_options & MD_READONLY) ? 0 : FWRITE); NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, sc->file, td); error = vn_open(&nd, &flags, 0, NULL); if (error != 0) diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index cf88d20..9f915df 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -280,6 +280,10 @@ brgphy_attach(device_t dev) brgphy_reset(sc); + /* Read the PHY's capabilities. */ + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + if (sc->mii_capabilities & BMSR_EXTSTAT) + sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); device_printf(dev, " "); #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 450cb3e..d1b211a 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -2911,15 +2911,12 @@ pci_set_power_children(device_t dev, device_t *devlist, int numdevs, struct pci_devinfo *dinfo; int dstate, i; - if (!pci_do_power_resume) - return; - /* * Set the device to the given state. If the firmware suggests * a different power state, use it instead. If power management * is not present, the firmware is responsible for managing * device power. Skip children who aren't attached since they - * are handled separately. Only manage type 0 devices for now. + * are handled separately. */ pcib = device_get_parent(dev); for (i = 0; i < numdevs; i++) { @@ -2927,8 +2924,6 @@ pci_set_power_children(device_t dev, device_t *devlist, int numdevs, dinfo = device_get_ivars(child); dstate = state; if (device_is_attached(child) && - (dinfo->cfg.hdrtype & PCIM_HDRTYPE) == - PCIM_HDRTYPE_NORMAL && PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0) pci_set_powerstate(child, dstate); } @@ -2976,7 +2971,9 @@ pci_resume(device_t dev) */ if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) return (error); - pci_set_power_children(dev, devlist, numdevs, PCI_POWERSTATE_D0); + if (pci_do_power_resume) + pci_set_power_children(dev, devlist, numdevs, + PCI_POWERSTATE_D0); /* Now the device is powered up, restore its config space. */ for (i = 0; i < numdevs; i++) { diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c index 999125d..51b6dc8 100644 --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -594,10 +594,15 @@ msdosfs_deget_dotdot(struct vnode *vp, u_long cluster, int blkoff, vfs_unbusy(mp); if (error == 0) *rvp = DETOV(rdp); - vn_lock(vp, ltype | LK_RETRY); + if (*rvp != vp) + vn_lock(vp, ltype | LK_RETRY); if (vp->v_iflag & VI_DOOMED) { - if (error == 0) - vput(*rvp); + if (error == 0) { + if (*rvp == vp) + vunref(*rvp); + else + vput(*rvp); + } error = ENOENT; } return (error); diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c index 7d76be0..8ca1c43 100644 --- a/sys/fs/nfsclient/nfs_clnode.c +++ b/sys/fs/nfsclient/nfs_clnode.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/fcntl.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mount.h> @@ -53,12 +54,13 @@ __FBSDID("$FreeBSD$"); #include <fs/nfsclient/nfsmount.h> #include <fs/nfsclient/nfs.h> +#include <nfs/nfs_lock.h> + extern struct vop_vector newnfs_vnodeops; extern struct buf_ops buf_ops_newnfs; MALLOC_DECLARE(M_NEWNFSREQ); uma_zone_t newnfsnode_zone; -vop_reclaim_t *ncl_reclaim_p = NULL; void ncl_nhinit(void) @@ -238,8 +240,8 @@ ncl_reclaim(struct vop_reclaim_args *ap) * If the NLM is running, give it a chance to abort pending * locks. */ - if (ncl_reclaim_p) - ncl_reclaim_p(ap); + if (nfs_reclaim_p != NULL) + nfs_reclaim_p(ap); /* * Destroy the vm object and flush associated pages. diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c index b2cd92b..d7245ee 100644 --- a/sys/fs/nfsclient/nfs_clvfsops.c +++ b/sys/fs/nfsclient/nfs_clvfsops.c @@ -96,10 +96,13 @@ SYSCTL_INT(_vfs_newnfs, NFS_TPRINTF_DELAY, static void nfs_sec_name(char *, int *); static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp, - struct nfs_args *argp, struct ucred *, struct thread *); + struct nfs_args *argp, const char *, struct ucred *, + struct thread *); static int mountnfs(struct nfs_args *, struct mount *, struct sockaddr *, char *, u_char *, u_char *, u_char *, struct vnode **, struct ucred *, struct thread *, int); +static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *, + struct sockaddr_storage *, int *, off_t *); static vfs_mount_t nfs_mount; static vfs_cmount_t nfs_cmount; static vfs_unmount_t nfs_unmount; @@ -518,10 +521,11 @@ nfs_sec_name(char *sec, int *flagsp) static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp, - struct ucred *cred, struct thread *td) + const char *hostname, struct ucred *cred, struct thread *td) { int s; int adjsock; + char *p; s = splnet(); @@ -659,6 +663,14 @@ nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp, nmp->nm_sotype = argp->sotype; nmp->nm_soproto = argp->proto; } + + if (hostname != NULL) { + strlcpy(nmp->nm_hostname, hostname, + sizeof(nmp->nm_hostname)); + p = strchr(nmp->nm_hostname, ':'); + if (p != NULL) + *p = '\0'; + } } static const char *nfs_opts[] = { "from", @@ -933,7 +945,7 @@ nfs_mount(struct mount *mp) NFSMNT_INTEGRITY | NFSMNT_PRIVACY | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)); - nfs_decode_args(mp, nmp, &args, td->td_ucred, td); + nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td); goto out; } @@ -1110,13 +1122,14 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, nmp->nm_sockreq.nr_cred = crhold(cred); mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF); mp->mnt_data = nmp; + nmp->nm_getinfo = nfs_getnlminfo; } vfs_getnewfsid(mp); nmp->nm_mountp = mp; mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK); nmp->nm_negnametimeo = negnametimeo; - nfs_decode_args(mp, nmp, argp, cred, td); + nfs_decode_args(mp, nmp, argp, hst, cred, td); /* * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too @@ -1447,3 +1460,26 @@ nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req) return (0); } +/* + * Extract the information needed by the nlm from the nfs vnode. + */ +static void +nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp, + struct sockaddr_storage *sp, int *is_v3p, off_t *sizep) +{ + struct nfsmount *nmp; + struct nfsnode *np = VTONFS(vp); + + nmp = VFSTONFS(vp->v_mount); + if (fhlenp != NULL) + *fhlenp = (size_t)np->n_fhp->nfh_len; + if (fhp != NULL) + bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len); + if (sp != NULL) + bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp))); + if (is_v3p != NULL) + *is_v3p = NFS_ISV3(vp); + if (sizep != NULL) + *sizep = np->n_size; +} + diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 8f1ec27..b02c4bf 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -84,7 +84,6 @@ __FBSDID("$FreeBSD$"); extern struct nfsstats newnfsstats; MALLOC_DECLARE(M_NEWNFSREQ); -vop_advlock_t *ncl_advlock_p = NULL; /* * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these @@ -2937,8 +2936,8 @@ nfs_advlock(struct vop_advlock_args *ap) VOP_UNLOCK(vp, 0); error = lf_advlock(ap, &(vp->v_lockf), size); } else { - if (ncl_advlock_p) - error = ncl_advlock_p(ap); + if (nfs_advlock_p != NULL) + error = nfs_advlock_p(ap); else { VOP_UNLOCK(vp, 0); error = ENOLCK; diff --git a/sys/fs/nfsclient/nfsmount.h b/sys/fs/nfsclient/nfsmount.h index 9fd9331..5bc69f8 100644 --- a/sys/fs/nfsclient/nfsmount.h +++ b/sys/fs/nfsclient/nfsmount.h @@ -35,22 +35,19 @@ #ifndef _NFSCLIENT_NFSMOUNT_H_ #define _NFSCLIENT_NFSMOUNT_H_ +#include <nfs/nfs_mountcommon.h> + /* * Mount structure. * One allocated on every NFS mount. * Holds NFS specific information for mount. */ struct nfsmount { - struct mtx nm_mtx; - int nm_flag; /* Flags for soft/hard... */ - int nm_state; /* Internal state flags */ - struct mount *nm_mountp; /* Vfs structure for this filesystem */ + struct nfsmount_common nm_com; /* Common fields for nlm */ int nm_numgrps; /* Max. size of groupslist */ u_char nm_fh[NFSX_FHMAX]; /* File handle of root dir */ int nm_fhsize; /* Size of root file handle */ struct nfssockreq nm_sockreq; /* Socket Info */ - int nm_timeo; /* Init timer for NFSMNT_DUMBTIMR */ - int nm_retry; /* Max retries */ int nm_timeouts; /* Request timeouts */ int nm_rsize; /* Max size of read rpc */ int nm_wsize; /* Max size of write rpc */ @@ -89,6 +86,14 @@ struct nfsmount { #define nm_soproto nm_sockreq.nr_soproto #define nm_client nm_sockreq.nr_client #define nm_krbname nm_name +#define nm_mtx nm_com.nmcom_mtx +#define nm_flag nm_com.nmcom_flag +#define nm_state nm_com.nmcom_state +#define nm_mountp nm_com.nmcom_mountp +#define nm_timeo nm_com.nmcom_timeo +#define nm_retry nm_com.nmcom_retry +#define nm_hostname nm_com.nmcom_hostname +#define nm_getinfo nm_com.nmcom_getinfo #define NFSMNT_DIRPATH(m) (&((m)->nm_name[(m)->nm_krbnamelen + 1])) #define NFSMNT_SRVKRBNAME(m) \ diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index 173e326..e4cbbe3 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -126,8 +126,16 @@ g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) error = g_attach(cp, pp); KASSERT(error == 0, ("g_dev_taste(%s) failed to g_attach, err=%d", pp->name, error)); - dev = make_dev(&g_dev_cdevsw, 0, - UID_ROOT, GID_OPERATOR, 0640, "%s", gp->name); + error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, &dev, + &g_dev_cdevsw, NULL, UID_ROOT, GID_OPERATOR, 0640, "%s", gp->name); + if (error != 0) { + printf("%s: make_dev_p() failed (gp->name=%s, error=%d)\n", + __func__, gp->name, error); + g_detach(cp); + g_destroy_consumer(cp); + g_destroy_geom(gp); + return (NULL); + } if (pp->flags & G_PF_CANDELETE) dev->si_flags |= SI_CANDELETE; dev->si_iosize_max = MAXPHYS; diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 09c8603..0da0075 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -699,8 +699,8 @@ kern_setrlimit(td, which, limp) if (limp->rlim_max > maxssiz) limp->rlim_max = maxssiz; oldssiz = *alimp; - if (td->td_proc->p_sysent->sv_fixlimit != NULL) - td->td_proc->p_sysent->sv_fixlimit(&oldssiz, + if (p->p_sysent->sv_fixlimit != NULL) + p->p_sysent->sv_fixlimit(&oldssiz, RLIMIT_STACK); break; @@ -722,8 +722,8 @@ kern_setrlimit(td, which, limp) limp->rlim_max = 1; break; } - if (td->td_proc->p_sysent->sv_fixlimit != NULL) - td->td_proc->p_sysent->sv_fixlimit(limp, which); + if (p->p_sysent->sv_fixlimit != NULL) + p->p_sysent->sv_fixlimit(limp, which); *alimp = *limp; p->p_limit = newlim; PROC_UNLOCK(p); diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index 0f14623..c20a1c6 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -133,7 +133,6 @@ static struct dumperinfo dumper; /* our selected dumper */ static struct pcb dumppcb; /* Registers. */ static lwpid_t dumptid; /* Thread ID. */ -static void boot(int) __dead2; static void poweroff_wait(void *, int); static void shutdown_halt(void *junk, int howto); static void shutdown_panic(void *junk, int howto); @@ -173,7 +172,7 @@ reboot(struct thread *td, struct reboot_args *uap) error = priv_check(td, PRIV_REBOOT); if (error == 0) { mtx_lock(&Giant); - boot(uap->opt); + kern_reboot(uap->opt); mtx_unlock(&Giant); } return (error); @@ -197,7 +196,7 @@ shutdown_nice(int howto) PROC_UNLOCK(initproc); } else { /* No init(8) running, so simply reboot */ - boot(RB_NOSYNC); + kern_reboot(RB_NOSYNC); } return; } @@ -269,8 +268,8 @@ isbufbusy(struct buf *bp) /* * Shutdown the system cleanly to prepare for reboot, halt, or power off. */ -static void -boot(int howto) +void +kern_reboot(int howto) { static int first_buf_printf = 1; @@ -283,7 +282,7 @@ boot(int howto) thread_lock(curthread); sched_bind(curthread, 0); thread_unlock(curthread); - KASSERT(PCPU_GET(cpuid) == 0, ("boot: not running on cpu 0")); + KASSERT(PCPU_GET(cpuid) == 0, ("%s: not running on cpu 0", __func__)); #endif /* We're in the process of rebooting. */ rebooting = 1; @@ -589,7 +588,7 @@ panic(const char *fmt, ...) if (!sync_on_panic) bootopt |= RB_NOSYNC; critical_exit(); - boot(bootopt); + kern_reboot(bootopt); } /* diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 5b0fd00..83cbc60 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1424,15 +1424,17 @@ vfs_filteropt(struct vfsoptlist *opts, const char **legal) continue; snprintf(errmsg, sizeof(errmsg), "mount option <%s> is unknown", p); - printf("%s\n", errmsg); ret = EINVAL; } if (ret != 0) { TAILQ_FOREACH(opt, opts, link) { if (strcmp(opt->name, "errmsg") == 0) { strncpy((char *)opt->value, errmsg, opt->len); + break; } } + if (opt == NULL) + printf("%s\n", errmsg); } return (ret); } diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c index 8685547..07c2988 100644 --- a/sys/kern/vfs_mountroot.c +++ b/sys/kern/vfs_mountroot.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2010 Marcel Moolenaar * Copyright (c) 1999-2004 Poul-Henning Kamp * Copyright (c) 1999 Michael Smith * Copyright (c) 1989, 1993 @@ -34,6 +35,8 @@ * SUCH DAMAGE. */ +#include "opt_rootdevname.h" + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -44,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/libkern.h> #include <sys/malloc.h> +#include <sys/mdioctl.h> #include <sys/mount.h> #include <sys/mutex.h> #include <sys/namei.h> @@ -51,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/filedesc.h> #include <sys/reboot.h> +#include <sys/stat.h> #include <sys/syscallsubr.h> #include <sys/sysproto.h> #include <sys/sx.h> @@ -58,25 +63,9 @@ __FBSDID("$FreeBSD$"); #include <sys/sysent.h> #include <sys/systm.h> #include <sys/vnode.h> -#include <vm/uma.h> #include <geom/geom.h> -#include <machine/stdarg.h> - -#include "opt_rootdevname.h" - -#define ROOTNAME "root_device" - -static int vfs_mountroot_ask(void); -static int vfs_mountroot_try(const char *mountfrom, const char *options); - -/* - * The vnode of the system's root (/ in the filesystem, without chroot - * active.) - */ -struct vnode *rootvnode; - /* * The root filesystem is detailed in the kernel environment variable * vfs.root.mountfrom, which is expected to be in the general format @@ -96,21 +85,16 @@ struct vnode *rootvnode; * by nmount() in the kernel. */ +static int parse_mount(char **); +static struct mntarg *parse_mountroot_options(struct mntarg *, const char *); + /* - * The root specifiers we will try if RB_CDROM is specified. + * The vnode of the system's root (/ in the filesystem, without chroot + * active.) */ -static char *cdrom_rootdevnames[] = { - "cd9660:cd0", - "cd9660:acd0", - NULL -}; +struct vnode *rootvnode; -/* legacy find-root code */ -char *rootdevnames[2] = {NULL, NULL}; -#ifndef ROOTDEVNAME -# define ROOTDEVNAME NULL -#endif -static const char *ctrootdevname = ROOTDEVNAME; +char *rootdevnames[2] = {NULL, NULL}; struct root_hold_token { const char *who; @@ -120,8 +104,21 @@ struct root_hold_token { static LIST_HEAD(, root_hold_token) root_holds = LIST_HEAD_INITIALIZER(root_holds); +enum action { + A_CONTINUE, + A_PANIC, + A_REBOOT, + A_RETRY +}; + +static enum action root_mount_onfail = A_CONTINUE; + +static int root_mount_mddev; static int root_mount_complete; +/* By default wait up to 3 seconds for devices to appear. */ +static int root_mount_timeout = 3; + struct root_hold_token * root_mount_hold(const char *identifier) { @@ -151,52 +148,6 @@ root_mount_rel(struct root_hold_token *h) free(h, M_DEVBUF); } -static void -root_mount_prepare(void) -{ - struct root_hold_token *h; - struct timeval lastfail; - int curfail = 0; - - for (;;) { - DROP_GIANT(); - g_waitidle(); - PICKUP_GIANT(); - mtx_lock(&mountlist_mtx); - if (LIST_EMPTY(&root_holds)) { - mtx_unlock(&mountlist_mtx); - break; - } - if (ppsratecheck(&lastfail, &curfail, 1)) { - printf("Root mount waiting for:"); - LIST_FOREACH(h, &root_holds, list) - printf(" %s", h->who); - printf("\n"); - } - msleep(&root_holds, &mountlist_mtx, PZERO | PDROP, "roothold", - hz); - } -} - -static void -root_mount_done(void) -{ - - /* Keep prison0's root in sync with the global rootvnode. */ - mtx_lock(&prison0.pr_mtx); - prison0.pr_root = rootvnode; - vref(prison0.pr_root); - mtx_unlock(&prison0.pr_mtx); - /* - * Use a mutex to prevent the wakeup being missed and waiting for - * an extra 1 second sleep. - */ - mtx_lock(&mountlist_mtx); - root_mount_complete = 1; - wakeup(&root_mount_complete); - mtx_unlock(&mountlist_mtx); -} - int root_mounted(void) { @@ -251,26 +202,27 @@ set_rootvnode(void) EVENTHANDLER_INVOKE(mountroot); } -static void -devfs_first(void) +static int +vfs_mountroot_devfs(struct thread *td, struct mount **mpp) { - struct thread *td = curthread; struct vfsoptlist *opts; struct vfsconf *vfsp; - struct mount *mp = NULL; + struct mount *mp; int error; + *mpp = NULL; + vfsp = vfs_byname("devfs"); KASSERT(vfsp != NULL, ("Could not find devfs by name")); if (vfsp == NULL) - return; + return (ENOENT); mp = vfs_mount_alloc(NULLVP, vfsp, "/dev", td->td_ucred); error = VFS_MOUNT(mp); KASSERT(error == 0, ("VFS_MOUNT(devfs) failed %d", error)); if (error) - return; + return (error); opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK); TAILQ_INIT(opts); @@ -280,170 +232,764 @@ devfs_first(void) TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list); mtx_unlock(&mountlist_mtx); + *mpp = mp; set_rootvnode(); error = kern_symlink(td, "/", "dev", UIO_SYSSPACE); if (error) printf("kern_symlink /dev -> / returns %d\n", error); + + return (error); } -static void -devfs_fixup(struct thread *td) +static int +vfs_mountroot_shuffle(struct thread *td, struct mount *mpdevfs) { struct nameidata nd; - struct vnode *vp, *dvp; - struct mount *mp; + struct mount *mporoot, *mpnroot; + struct vnode *vp, *vporoot, *vpdevfs; + char *fspath; int error; - /* Remove our devfs mount from the mountlist and purge the cache */ + mpnroot = TAILQ_NEXT(mpdevfs, mnt_list); + + /* Shuffle the mountlist. */ mtx_lock(&mountlist_mtx); - mp = TAILQ_FIRST(&mountlist); - TAILQ_REMOVE(&mountlist, mp, mnt_list); + mporoot = TAILQ_FIRST(&mountlist); + TAILQ_REMOVE(&mountlist, mpdevfs, mnt_list); + if (mporoot != mpdevfs) { + TAILQ_REMOVE(&mountlist, mpnroot, mnt_list); + TAILQ_INSERT_HEAD(&mountlist, mpnroot, mnt_list); + } + TAILQ_INSERT_TAIL(&mountlist, mpdevfs, mnt_list); mtx_unlock(&mountlist_mtx); - cache_purgevfs(mp); - VFS_ROOT(mp, LK_EXCLUSIVE, &dvp); - VI_LOCK(dvp); - dvp->v_iflag &= ~VI_MOUNT; - VI_UNLOCK(dvp); - dvp->v_mountedhere = NULL; + cache_purgevfs(mporoot); + if (mporoot != mpdevfs) + cache_purgevfs(mpdevfs); + + VFS_ROOT(mporoot, LK_EXCLUSIVE, &vporoot); - /* Set up the real rootvnode, and purge the cache */ - TAILQ_FIRST(&mountlist)->mnt_vnodecovered = NULL; + VI_LOCK(vporoot); + vporoot->v_iflag &= ~VI_MOUNT; + VI_UNLOCK(vporoot); + vporoot->v_mountedhere = NULL; + mporoot->mnt_flag &= ~MNT_ROOTFS; + mporoot->mnt_vnodecovered = NULL; + vput(vporoot); + + /* Set up the new rootvnode, and purge the cache */ + mpnroot->mnt_vnodecovered = NULL; set_rootvnode(); cache_purgevfs(rootvnode->v_mount); + if (mporoot != mpdevfs) { + /* Remount old root under /.mount or /mnt */ + fspath = "/.mount"; + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, + fspath, td); + error = namei(&nd); + if (error) { + NDFREE(&nd, NDF_ONLY_PNBUF); + fspath = "/mnt"; + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, + fspath, td); + error = namei(&nd); + } + if (!error) { + vp = nd.ni_vp; + error = (vp->v_type == VDIR) ? 0 : ENOTDIR; + if (!error) + error = vinvalbuf(vp, V_SAVE, 0, 0); + if (!error) { + cache_purge(vp); + mporoot->mnt_vnodecovered = vp; + vp->v_mountedhere = mporoot; + strlcpy(mporoot->mnt_stat.f_mntonname, + fspath, MNAMELEN); + VOP_UNLOCK(vp, 0); + } else + vput(vp); + } + NDFREE(&nd, NDF_ONLY_PNBUF); + + if (error && bootverbose) + printf("mountroot: unable to remount previous root " + "under /.mount or /mnt (error %d).\n", error); + } + + /* Remount devfs under /dev */ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev", td); error = namei(&nd); - if (error) { - printf("Lookup of /dev for devfs, error: %d\n", error); - vput(dvp); - vfs_unbusy(mp); - return; + if (!error) { + vp = nd.ni_vp; + error = (vp->v_type == VDIR) ? 0 : ENOTDIR; + if (!error) + error = vinvalbuf(vp, V_SAVE, 0, 0); + if (!error) { + vpdevfs = mpdevfs->mnt_vnodecovered; + if (vpdevfs != NULL) { + cache_purge(vpdevfs); + vpdevfs->v_mountedhere = NULL; + vrele(vpdevfs); + } + mpdevfs->mnt_vnodecovered = vp; + vp->v_mountedhere = mpdevfs; + VOP_UNLOCK(vp, 0); + } else + vput(vp); } + if (error && bootverbose) + printf("mountroot: unable to remount devfs under /dev " + "(error %d).\n", error); NDFREE(&nd, NDF_ONLY_PNBUF); - vp = nd.ni_vp; - if (vp->v_type != VDIR) { - printf("/dev is not a directory\n"); - vput(dvp); - vput(vp); - vfs_unbusy(mp); - return; + + if (mporoot == mpdevfs) { + vfs_unbusy(mpdevfs); + /* Unlink the no longer needed /dev/dev -> / symlink */ + error = kern_unlink(td, "/dev/dev", UIO_SYSSPACE); + if (error && bootverbose) + printf("mountroot: unable to unlink /dev/dev " + "(error %d)\n", error); } - error = vinvalbuf(vp, V_SAVE, 0, 0); - if (error) { - printf("vinvalbuf() of /dev failed, error: %d\n", error); - vput(dvp); - vput(vp); - vfs_unbusy(mp); - return; + + return (0); +} + +/* + * Configuration parser. + */ + +/* Parser character classes. */ +#define CC_WHITESPACE -1 +#define CC_NONWHITESPACE -2 + +/* Parse errors. */ +#define PE_EOF -1 +#define PE_EOL -2 + +static __inline int +parse_peek(char **conf) +{ + + return (**conf); +} + +static __inline void +parse_poke(char **conf, int c) +{ + + **conf = c; +} + +static __inline void +parse_advance(char **conf) +{ + + (*conf)++; +} + +static __inline int +parse_isspace(int c) +{ + + return ((c == ' ' || c == '\t' || c == '\n') ? 1 : 0); +} + +static int +parse_skipto(char **conf, int mc) +{ + int c, match; + + while (1) { + c = parse_peek(conf); + if (c == 0) + return (PE_EOF); + switch (mc) { + case CC_WHITESPACE: + match = (c == ' ' || c == '\t' || c == '\n') ? 1 : 0; + break; + case CC_NONWHITESPACE: + if (c == '\n') + return (PE_EOL); + match = (c != ' ' && c != '\t') ? 1 : 0; + break; + default: + match = (c == mc) ? 1 : 0; + break; + } + if (match) + break; + parse_advance(conf); } - cache_purge(vp); - mp->mnt_vnodecovered = vp; - vp->v_mountedhere = mp; - mtx_lock(&mountlist_mtx); - TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); - mtx_unlock(&mountlist_mtx); - VOP_UNLOCK(vp, 0); - vput(dvp); - vfs_unbusy(mp); + return (0); +} + +static int +parse_token(char **conf, char **tok) +{ + char *p; + size_t len; + int error; - /* Unlink the no longer needed /dev/dev -> / symlink */ - error = kern_unlink(td, "/dev/dev", UIO_SYSSPACE); + *tok = NULL; + error = parse_skipto(conf, CC_NONWHITESPACE); if (error) - printf("kern_unlink of /dev/dev failed, error: %d\n", error); + return (error); + p = *conf; + error = parse_skipto(conf, CC_WHITESPACE); + len = *conf - p; + *tok = malloc(len + 1, M_TEMP, M_WAITOK | M_ZERO); + bcopy(p, *tok, len); + return (0); } -void -vfs_mountroot(void) +static void +parse_dir_ask_printenv(const char *var) +{ + char *val; + + val = getenv(var); + if (val != NULL) { + printf(" %s=%s\n", var, val); + freeenv(val); + } +} + +static int +parse_dir_ask(char **conf) { - char *cp, *cpt, *options, *tmpdev; - int error, i, asked = 0; + char name[80]; + char *mnt; + int error; + + printf("\nLoader variables:\n"); + parse_dir_ask_printenv("vfs.root.mountfrom"); + parse_dir_ask_printenv("vfs.root.mountfrom.options"); + + printf("\nManual root filesystem specification:\n"); + printf(" <fstype>:<device> [options]\n"); + printf(" Mount <device> using filesystem <fstype>\n"); + printf(" and with the specified (optional) option list.\n"); + printf("\n"); + printf(" eg. ufs:/dev/da0s1a\n"); + printf(" zfs:tank\n"); + printf(" cd9660:/dev/acd0 ro\n"); + printf(" (which is equivalent to: "); + printf("mount -t cd9660 -o ro /dev/acd0 /)\n"); + printf("\n"); + printf(" ? List valid disk boot devices\n"); + printf(" . Yield 1 second (for background tasks)\n"); + printf(" <empty line> Abort manual input\n"); + + again: + printf("\nmountroot> "); + gets(name, sizeof(name), 1); + if (name[0] == '\0') + return (0); + if (name[0] == '?') { + printf("\nList of GEOM managed disk devices:\n "); + g_dev_print(); + goto again; + } + if (name[0] == '.') { + pause("rmask", hz); + goto again; + } + mnt = name; + error = parse_mount(&mnt); + if (error == -1) { + printf("Invalid specification.\n"); + goto again; + } + return (error); +} - options = NULL; +static int +parse_dir_md(char **conf) +{ + struct stat sb; + struct thread *td; + struct md_ioctl *mdio; + char *path, *tok; + int error, fd, len; - root_mount_prepare(); + td = curthread; - devfs_first(); + error = parse_token(conf, &tok); + if (error) + return (error); - /* - * We are booted with instructions to prompt for the root filesystem. - */ - if (boothowto & RB_ASKNAME) { - if (!vfs_mountroot_ask()) - goto mounted; - asked = 1; + len = strlen(tok); + mdio = malloc(sizeof(*mdio) + len + 1, M_TEMP, M_WAITOK | M_ZERO); + path = (void *)(mdio + 1); + bcopy(tok, path, len); + free(tok, M_TEMP); + + /* Get file status. */ + error = kern_stat(td, path, UIO_SYSSPACE, &sb); + if (error) + goto out; + + /* Open /dev/mdctl so that we can attach/detach. */ + error = kern_open(td, "/dev/" MDCTL_NAME, UIO_SYSSPACE, O_RDWR, 0); + if (error) + goto out; + + fd = td->td_retval[0]; + mdio->md_version = MDIOVERSION; + mdio->md_type = MD_VNODE; + + if (root_mount_mddev != -1) { + mdio->md_unit = root_mount_mddev; + DROP_GIANT(); + error = kern_ioctl(td, fd, MDIOCDETACH, (void *)mdio); + PICKUP_GIANT(); + /* Ignore errors. We don't care. */ + root_mount_mddev = -1; } - options = getenv("vfs.root.mountfrom.options"); + mdio->md_file = (void *)(mdio + 1); + mdio->md_options = MD_AUTOUNIT | MD_READONLY; + mdio->md_mediasize = sb.st_size; + mdio->md_unit = 0; + DROP_GIANT(); + error = kern_ioctl(td, fd, MDIOCATTACH, (void *)mdio); + PICKUP_GIANT(); + if (error) + goto out; - /* - * The root filesystem information is compiled in, and we are - * booted with instructions to use it. - */ - if (ctrootdevname != NULL && (boothowto & RB_DFLTROOT)) { - if (!vfs_mountroot_try(ctrootdevname, options)) - goto mounted; - ctrootdevname = NULL; + if (mdio->md_unit > 9) { + printf("rootmount: too many md units\n"); + mdio->md_file = NULL; + mdio->md_options = 0; + mdio->md_mediasize = 0; + DROP_GIANT(); + error = kern_ioctl(td, fd, MDIOCDETACH, (void *)mdio); + PICKUP_GIANT(); + /* Ignore errors. We don't care. */ + error = ERANGE; + goto out; + } + + root_mount_mddev = mdio->md_unit; + printf(MD_NAME "%u attached to %s\n", root_mount_mddev, mdio->md_file); + + error = kern_close(td, fd); + + out: + free(mdio, M_TEMP); + return (error); +} + +static int +parse_dir_onfail(char **conf) +{ + char *action; + int error; + + error = parse_token(conf, &action); + if (error) + return (error); + + if (!strcmp(action, "continue")) + root_mount_onfail = A_CONTINUE; + else if (!strcmp(action, "panic")) + root_mount_onfail = A_PANIC; + else if (!strcmp(action, "reboot")) + root_mount_onfail = A_REBOOT; + else if (!strcmp(action, "retry")) + root_mount_onfail = A_RETRY; + else { + printf("rootmount: %s: unknown action\n", action); + error = EINVAL; } + free(action, M_TEMP); + return (0); +} + +static int +parse_dir_timeout(char **conf) +{ + char *tok, *endtok; + long secs; + int error; + + error = parse_token(conf, &tok); + if (error) + return (error); + + secs = strtol(tok, &endtok, 0); + error = (secs < 0 || *endtok != '\0') ? EINVAL : 0; + if (!error) + root_mount_timeout = secs; + free(tok, M_TEMP); + return (error); +} + +static int +parse_directive(char **conf) +{ + char *dir; + int error; + + error = parse_token(conf, &dir); + if (error) + return (error); + + if (strcmp(dir, ".ask") == 0) + error = parse_dir_ask(conf); + else if (strcmp(dir, ".md") == 0) + error = parse_dir_md(conf); + else if (strcmp(dir, ".onfail") == 0) + error = parse_dir_onfail(conf); + else if (strcmp(dir, ".timeout") == 0) + error = parse_dir_timeout(conf); + else { + printf("mountroot: invalid directive `%s'\n", dir); + /* Ignore the rest of the line. */ + (void)parse_skipto(conf, '\n'); + error = EINVAL; + } + free(dir, M_TEMP); + return (error); +} + +static int +parse_mount_dev_present(const char *dev) +{ + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, dev, curthread); + error = namei(&nd); + if (!error) + vput(nd.ni_vp); + NDFREE(&nd, NDF_ONLY_PNBUF); + return (error != 0) ? 0 : 1; +} + +static int +parse_mount(char **conf) +{ + char errmsg[255]; + struct mntarg *ma; + char *dev, *fs, *opts, *tok; + int delay, error, timeout; + + error = parse_token(conf, &tok); + if (error) + return (error); + fs = tok; + error = parse_skipto(&tok, ':'); + if (error) { + free(fs, M_TEMP); + return (error); + } + parse_poke(&tok, '\0'); + parse_advance(&tok); + dev = tok; + + if (root_mount_mddev != -1) { + /* Handle substitution for the md unit number. */ + tok = strstr(dev, "md#"); + if (tok != NULL) + tok[2] = '0' + root_mount_mddev; + } + + /* Parse options. */ + error = parse_token(conf, &tok); + opts = (error == 0) ? tok : NULL; + + printf("Trying to mount root from %s:%s [%s]...\n", fs, dev, + (opts != NULL) ? opts : ""); + + bzero(errmsg, sizeof(errmsg)); + + if (vfs_byname(fs) == NULL) { + strlcpy(errmsg, "unknown file system", sizeof(errmsg)); + error = ENOENT; + goto out; + } + + if (strcmp(fs, "zfs") != 0 && dev[0] != '\0' && + !parse_mount_dev_present(dev)) { + printf("mountroot: waiting for device %s ...\n", dev); + delay = hz / 10; + timeout = root_mount_timeout * hz; + do { + pause("rmdev", delay); + timeout -= delay; + } while (timeout > 0 && !parse_mount_dev_present(dev)); + if (timeout <= 0) { + error = ENODEV; + goto out; + } + } + + ma = NULL; + ma = mount_arg(ma, "fstype", fs, -1); + ma = mount_arg(ma, "fspath", "/", -1); + ma = mount_arg(ma, "from", dev, -1); + ma = mount_arg(ma, "errmsg", errmsg, sizeof(errmsg)); + ma = mount_arg(ma, "ro", NULL, 0); + ma = parse_mountroot_options(ma, opts); + error = kernel_mount(ma, MNT_ROOTFS); + + out: + if (error) { + printf("Mounting from %s:%s failed with error %d", + fs, dev, error); + if (errmsg[0] != '\0') + printf(": %s", errmsg); + printf(".\n"); + } + free(fs, M_TEMP); + if (opts != NULL) + free(opts, M_TEMP); + /* kernel_mount can return -1 on error. */ + return ((error < 0) ? EDOOFUS : error); +} + +static int +vfs_mountroot_parse(struct sbuf *sb, struct mount *mpdevfs) +{ + struct mount *mp; + char *conf; + int error; + + root_mount_mddev = -1; + +retry: + conf = sbuf_data(sb); + mp = TAILQ_NEXT(mpdevfs, mnt_list); + error = (mp == NULL) ? 0 : EDOOFUS; + root_mount_onfail = A_CONTINUE; + while (mp == NULL) { + error = parse_skipto(&conf, CC_NONWHITESPACE); + if (error == PE_EOL) { + parse_advance(&conf); + continue; + } + if (error < 0) + break; + switch (parse_peek(&conf)) { + case '#': + error = parse_skipto(&conf, '\n'); + break; + case '.': + error = parse_directive(&conf); + break; + default: + error = parse_mount(&conf); + break; + } + if (error < 0) + break; + /* Ignore any trailing garbage on the line. */ + if (parse_peek(&conf) != '\n') { + printf("mountroot: advancing to next directive...\n"); + (void)parse_skipto(&conf, '\n'); + } + mp = TAILQ_NEXT(mpdevfs, mnt_list); + } + if (mp != NULL) + return (0); + /* - * We've been given the generic "use CDROM as root" flag. This is - * necessary because one media may be used in many different - * devices, so we need to search for them. + * We failed to mount (a new) root. */ + switch (root_mount_onfail) { + case A_CONTINUE: + break; + case A_PANIC: + panic("mountroot: unable to (re-)mount root."); + /* NOTREACHED */ + case A_RETRY: + goto retry; + case A_REBOOT: + kern_reboot(RB_NOSYNC); + /* NOTREACHED */ + } + + return (error); +} + +static void +vfs_mountroot_conf0(struct sbuf *sb) +{ + char *s, *tok, *mnt, *opt; + int error; + + sbuf_printf(sb, ".onfail panic\n"); + sbuf_printf(sb, ".timeout %d\n", root_mount_timeout); + if (boothowto & RB_ASKNAME) + sbuf_printf(sb, ".ask\n"); +#ifdef ROOTDEVNAME + if (boothowto & RB_DFLTROOT) + sbuf_printf(sb, "%s\n", ROOTDEVNAME); +#endif if (boothowto & RB_CDROM) { - for (i = 0; cdrom_rootdevnames[i] != NULL; i++) { - if (!vfs_mountroot_try(cdrom_rootdevnames[i], options)) - goto mounted; + sbuf_printf(sb, "cd9660:cd0\n"); + sbuf_printf(sb, ".timeout 0\n"); + sbuf_printf(sb, "cd9660:acd0\n"); + sbuf_printf(sb, ".timeout %d\n", root_mount_timeout); + } + s = getenv("vfs.root.mountfrom"); + if (s != NULL) { + opt = getenv("vfs.root.mountfrom.options"); + tok = s; + error = parse_token(&tok, &mnt); + while (!error) { + sbuf_printf(sb, "%s %s\n", mnt, + (opt != NULL) ? opt : ""); + free(mnt, M_TEMP); + error = parse_token(&tok, &mnt); } + if (opt != NULL) + freeenv(opt); + freeenv(s); } + if (rootdevnames[0] != NULL) + sbuf_printf(sb, "%s\n", rootdevnames[0]); + if (rootdevnames[1] != NULL) + sbuf_printf(sb, "%s\n", rootdevnames[1]); +#ifdef ROOTDEVNAME + if (!(boothowto & RB_DFLTROOT)) + sbuf_printf(sb, "%s\n", ROOTDEVNAME); +#endif + if (!(boothowto & RB_ASKNAME)) + sbuf_printf(sb, ".ask\n"); +} - /* - * Try to use the value read by the loader from /etc/fstab, or - * supplied via some other means. This is the preferred - * mechanism. - */ - cp = getenv("vfs.root.mountfrom"); - if (cp != NULL) { - cpt = cp; - while ((tmpdev = strsep(&cpt, " \t")) != NULL) { - error = vfs_mountroot_try(tmpdev, options); - if (error == 0) { - freeenv(cp); - goto mounted; +static int +vfs_mountroot_readconf(struct thread *td, struct sbuf *sb) +{ + static char buf[128]; + struct nameidata nd; + off_t ofs; + int error, flags; + int len, resid; + int vfslocked; + + NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, + "/.mount.conf", td); + flags = FREAD; + error = vn_open(&nd, &flags, 0, NULL); + if (error) + return (error); + + vfslocked = NDHASGIANT(&nd); + NDFREE(&nd, NDF_ONLY_PNBUF); + ofs = 0; + len = sizeof(buf) - 1; + while (1) { + error = vn_rdwr(UIO_READ, nd.ni_vp, buf, len, ofs, + UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, + NOCRED, &resid, td); + if (error) + break; + if (resid == len) + break; + buf[len - resid] = 0; + sbuf_printf(sb, "%s", buf); + ofs += len - resid; + } + + VOP_UNLOCK(nd.ni_vp, 0); + vn_close(nd.ni_vp, FREAD, td->td_ucred, td); + VFS_UNLOCK_GIANT(vfslocked); + return (error); +} + +static void +vfs_mountroot_wait(void) +{ + struct root_hold_token *h; + struct timeval lastfail; + int curfail; + + curfail = 0; + while (1) { + DROP_GIANT(); + g_waitidle(); + PICKUP_GIANT(); + mtx_lock(&mountlist_mtx); + if (LIST_EMPTY(&root_holds)) { + mtx_unlock(&mountlist_mtx); + break; + } + if (ppsratecheck(&lastfail, &curfail, 1)) { + printf("Root mount waiting for:"); + LIST_FOREACH(h, &root_holds, list) + printf(" %s", h->who); + printf("\n"); + } + msleep(&root_holds, &mountlist_mtx, PZERO | PDROP, "roothold", + hz); + } +} + +void +vfs_mountroot(void) +{ + struct mount *mp; + struct sbuf *sb; + struct thread *td; + time_t timebase; + int error; + + td = curthread; + + vfs_mountroot_wait(); + + sb = sbuf_new_auto(); + vfs_mountroot_conf0(sb); + sbuf_finish(sb); + + error = vfs_mountroot_devfs(td, &mp); + while (!error) { + error = vfs_mountroot_parse(sb, mp); + if (!error) { + error = vfs_mountroot_shuffle(td, mp); + if (!error) { + sbuf_clear(sb); + error = vfs_mountroot_readconf(td, sb); + sbuf_finish(sb); } } - freeenv(cp); } - /* - * Try values that may have been computed by code during boot - */ - if (!vfs_mountroot_try(rootdevnames[0], options)) - goto mounted; - if (!vfs_mountroot_try(rootdevnames[1], options)) - goto mounted; + sbuf_delete(sb); /* - * If we (still) have a compiled-in default, try it. + * Iterate over all currently mounted file systems and use + * the time stamp found to check and/or initialize the RTC. + * Call inittodr() only once and pass it the largest of the + * timestamps we encounter. */ - if (ctrootdevname != NULL) - if (!vfs_mountroot_try(ctrootdevname, options)) - goto mounted; - /* - * Everything so far has failed, prompt on the console if we haven't - * already tried that. - */ - if (!asked) - if (!vfs_mountroot_ask()) - goto mounted; + timebase = 0; + mtx_lock(&mountlist_mtx); + mp = TAILQ_FIRST(&mountlist); + while (mp != NULL) { + if (mp->mnt_time > timebase) + timebase = mp->mnt_time; + mp = TAILQ_NEXT(mp, mnt_list); + } + mtx_unlock(&mountlist_mtx); + inittodr(timebase); - panic("Root mount failed, startup aborted."); + /* Keep prison0's root in sync with the global rootvnode. */ + mtx_lock(&prison0.pr_mtx); + prison0.pr_root = rootvnode; + vref(prison0.pr_root); + mtx_unlock(&prison0.pr_mtx); -mounted: - root_mount_done(); - freeenv(options); + mtx_lock(&mountlist_mtx); + atomic_store_rel_int(&root_mount_complete, 1); + wakeup(&root_mount_complete); + mtx_unlock(&mountlist_mtx); } static struct mntarg * @@ -460,7 +1006,7 @@ parse_mountroot_options(struct mntarg *ma, const char *options) p = opts = strdup(options, M_MOUNT); if (opts == NULL) { return (ma); - } + } while((name = strsep(&p, ",")) != NULL) { if (name[0] == '\0') @@ -482,7 +1028,7 @@ parse_mountroot_options(struct mntarg *ma, const char *options) } name_arg = strdup(name, M_MOUNT); val_arg = NULL; - if (val != NULL) + if (val != NULL) val_arg = strdup(val, M_MOUNT); ma = mount_arg(ma, name_arg, val_arg, @@ -491,136 +1037,3 @@ parse_mountroot_options(struct mntarg *ma, const char *options) free(opts, M_MOUNT); return (ma); } - -/* - * Mount (mountfrom) as the root filesystem. - */ -static int -vfs_mountroot_try(const char *mountfrom, const char *options) -{ - struct mount *mp; - struct mntarg *ma; - char *vfsname, *path; - time_t timebase; - int error; - char patt[32]; - char errmsg[255]; - - vfsname = NULL; - path = NULL; - mp = NULL; - ma = NULL; - error = EINVAL; - bzero(errmsg, sizeof(errmsg)); - - if (mountfrom == NULL) - return (error); /* don't complain */ - printf("Trying to mount root from %s\n", mountfrom); - - /* parse vfs name and path */ - vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK); - path = malloc(MNAMELEN, M_MOUNT, M_WAITOK); - vfsname[0] = path[0] = 0; - sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN); - if (sscanf(mountfrom, patt, vfsname, path) < 1) - goto out; - - if (path[0] == '\0') - strcpy(path, ROOTNAME); - - ma = mount_arg(ma, "fstype", vfsname, -1); - ma = mount_arg(ma, "fspath", "/", -1); - ma = mount_arg(ma, "from", path, -1); - ma = mount_arg(ma, "errmsg", errmsg, sizeof(errmsg)); - ma = mount_arg(ma, "ro", NULL, 0); - ma = parse_mountroot_options(ma, options); - error = kernel_mount(ma, MNT_ROOTFS); - - if (error == 0) { - /* - * We mount devfs prior to mounting the / FS, so the first - * entry will typically be devfs. - */ - mp = TAILQ_FIRST(&mountlist); - KASSERT(mp != NULL, ("%s: mountlist is empty", __func__)); - - /* - * Iterate over all currently mounted file systems and use - * the time stamp found to check and/or initialize the RTC. - * Typically devfs has no time stamp and the only other FS - * is the actual / FS. - * Call inittodr() only once and pass it the largest of the - * timestamps we encounter. - */ - timebase = 0; - do { - if (mp->mnt_time > timebase) - timebase = mp->mnt_time; - mp = TAILQ_NEXT(mp, mnt_list); - } while (mp != NULL); - inittodr(timebase); - - devfs_fixup(curthread); - } - - if (error != 0 ) { - printf("ROOT MOUNT ERROR: %s\n", errmsg); - printf("If you have invalid mount options, reboot, and "); - printf("first try the following from\n"); - printf("the loader prompt:\n\n"); - printf(" set vfs.root.mountfrom.options=rw\n\n"); - printf("and then remove invalid mount options from "); - printf("/etc/fstab.\n\n"); - } -out: - free(path, M_MOUNT); - free(vfsname, M_MOUNT); - return (error); -} - -static int -vfs_mountroot_ask(void) -{ - char name[128]; - char *mountfrom; - char *options; - - for(;;) { - printf("Loader variables:\n"); - printf("vfs.root.mountfrom="); - mountfrom = getenv("vfs.root.mountfrom"); - if (mountfrom != NULL) { - printf("%s", mountfrom); - } - printf("\n"); - printf("vfs.root.mountfrom.options="); - options = getenv("vfs.root.mountfrom.options"); - if (options != NULL) { - printf("%s", options); - } - printf("\n"); - freeenv(mountfrom); - freeenv(options); - printf("\nManual root filesystem specification:\n"); - printf(" <fstype>:<device> Mount <device> using filesystem <fstype>\n"); - printf(" eg. zfs:tank\n"); - printf(" eg. ufs:/dev/da0s1a\n"); - printf(" eg. cd9660:/dev/acd0\n"); - printf(" This is equivalent to: "); - printf("mount -t cd9660 /dev/acd0 /\n"); - printf("\n"); - printf(" ? List valid disk boot devices\n"); - printf(" <empty line> Abort manual input\n"); - printf("\nmountroot> "); - gets(name, sizeof(name), 1); - if (name[0] == '\0') - return (1); - if (name[0] == '?') { - printf("\nList of GEOM managed disk devices:\n "); - g_dev_print(); - continue; - } - if (!vfs_mountroot_try(name, NULL)) - return (0); - } -} diff --git a/sys/modules/mps/Makefile b/sys/modules/mps/Makefile index 5e91084..49e65da 100644 --- a/sys/modules/mps/Makefile +++ b/sys/modules/mps/Makefile @@ -4,7 +4,7 @@ KMOD= mps SRCS= mps_pci.c mps.c mps_sas.c mps_table.c mps_user.c -SRCS+= opt_compat.h +SRCS+= opt_mps.h opt_cam.h opt_compat.h SRCS+= device_if.h bus_if.h pci_if.h #CFLAGS += -DMPS_DEBUG diff --git a/sys/modules/wlan/Makefile b/sys/modules/wlan/Makefile index 79d5e75..682aab3 100644 --- a/sys/modules/wlan/Makefile +++ b/sys/modules/wlan/Makefile @@ -3,13 +3,13 @@ .PATH: ${.CURDIR}/../../net80211 KMOD= wlan -SRCS= ieee80211.c ieee80211_action.c ieee80211_ageq.c ieee80211_amrr.c \ +SRCS= ieee80211.c ieee80211_action.c ieee80211_ageq.c \ ieee80211_crypto.c ieee80211_crypto_none.c ieee80211_dfs.c \ ieee80211_freebsd.c ieee80211_input.c ieee80211_ioctl.c \ ieee80211_mesh.c ieee80211_node.c ieee80211_output.c ieee80211_phy.c \ ieee80211_power.c ieee80211_proto.c ieee80211_scan.c \ ieee80211_scan_sta.c ieee80211_radiotap.c ieee80211_ratectl.c \ - ieee80211_regdomain.c ieee80211_rssadapt.c \ + ieee80211_ratectl_none.c ieee80211_regdomain.c \ ieee80211_ht.c ieee80211_hwmp.c ieee80211_adhoc.c ieee80211_hostap.c \ ieee80211_monitor.c ieee80211_sta.c ieee80211_wds.c ieee80211_ddb.c SRCS+= bus_if.h device_if.h opt_inet.h opt_inet6.h opt_ipx.h opt_wlan.h \ diff --git a/sys/net80211/ieee80211_ratectl.c b/sys/net80211/ieee80211_ratectl.c index 2e8eb7e..ea3d8d4 100644 --- a/sys/net80211/ieee80211_ratectl.c +++ b/sys/net80211/ieee80211_ratectl.c @@ -39,6 +39,14 @@ __FBSDID("$FreeBSD$"); static const struct ieee80211_ratectl *ratectls[IEEE80211_RATECTL_MAX]; +static const char *ratectl_modnames[IEEE80211_RATECTL_MAX] = { + [IEEE80211_RATECTL_AMRR] = "wlan_amrr", + [IEEE80211_RATECTL_RSSADAPT] = "wlan_rssadapt", + [IEEE80211_RATECTL_ONOE] = "wlan_onoe", + [IEEE80211_RATECTL_SAMPLE] = "wlan_sample", + [IEEE80211_RATECTL_NONE] = "wlan_none", +}; + MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control"); void @@ -62,5 +70,15 @@ ieee80211_ratectl_set(struct ieee80211vap *vap, int type) { if (type >= IEEE80211_RATECTL_MAX) return; + if (ratectls[type] == NULL) { + ieee80211_load_module(ratectl_modnames[type]); + if (ratectls[type] == NULL) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL, + "%s: unable to load algo %u, module %s\n", + __func__, type, ratectl_modnames[type]); + vap->iv_rate = ratectls[IEEE80211_RATECTL_NONE]; + return; + } + } vap->iv_rate = ratectls[type]; } diff --git a/sys/net80211/ieee80211_ratectl.h b/sys/net80211/ieee80211_ratectl.h index 73b4f32..87b2698 100644 --- a/sys/net80211/ieee80211_ratectl.h +++ b/sys/net80211/ieee80211_ratectl.h @@ -26,10 +26,11 @@ */ enum ieee80211_ratealgs { - IEEE80211_RATECTL_AMRR = 0, + IEEE80211_RATECTL_AMRR = 0, IEEE80211_RATECTL_RSSADAPT = 1, IEEE80211_RATECTL_ONOE = 2, IEEE80211_RATECTL_SAMPLE = 3, + IEEE80211_RATECTL_NONE = 4, IEEE80211_RATECTL_MAX }; diff --git a/sys/net80211/ieee80211_ratectl_none.c b/sys/net80211/ieee80211_ratectl_none.c new file mode 100644 index 0000000..0979e9d --- /dev/null +++ b/sys/net80211/ieee80211_ratectl_none.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2010 Bernhard Schmidt <bschmidt@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 "opt_wlan.h" + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/socket.h> +#include <sys/sysctl.h> + +#include <net/if.h> +#include <net/if_media.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_ether.h> +#endif + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_ratectl.h> + +static void +none_init(struct ieee80211vap *vap) +{ +} + +static void +none_deinit(struct ieee80211vap *vap) +{ + free(vap->iv_rs, M_80211_RATECTL); +} + +static void +none_node_init(struct ieee80211_node *ni) +{ +} + +static void +none_node_deinit(struct ieee80211_node *ni) +{ +} + +static int +none_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused) +{ + int rix = 0; + + ni->ni_txrate = ni->ni_rates.rs_rates[rix] & IEEE80211_RATE_VAL; + return rix; +} + +static void +none_tx_complete(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, int ok, + void *arg1, void *arg2 __unused) +{ +} + +static void +none_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni, + void *arg1, void *arg2, void *arg3) +{ +} + +static void +none_setinterval(const struct ieee80211vap *vap, int msecs) +{ +} + +/* number of references from net80211 layer */ +static int nrefs = 0; + +static const struct ieee80211_ratectl none = { + .ir_name = "none", + .ir_attach = NULL, + .ir_detach = NULL, + .ir_init = none_init, + .ir_deinit = none_deinit, + .ir_node_init = none_node_init, + .ir_node_deinit = none_node_deinit, + .ir_rate = none_rate, + .ir_tx_complete = none_tx_complete, + .ir_tx_update = none_tx_update, + .ir_setinterval = none_setinterval, +}; +IEEE80211_RATECTL_MODULE(ratectl_none, 1); +IEEE80211_RATECTL_ALG(none, IEEE80211_RATECTL_NONE, none); diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3 index 8f7d93f..31702e8 100644 --- a/sys/netinet/libalias/libalias.3 +++ b/sys/netinet/libalias/libalias.3 @@ -899,7 +899,6 @@ protocols (except for IP, TCP and UDP) to external modules. .Sh ACKNOWLEDGMENTS Listed below, in approximate chronological order, are individuals who have provided valuable comments and/or debugging assistance. -.Pp .Bd -ragged -offset indent .An -split .An Gary Roberts diff --git a/sys/nfs/nfs_lock.c b/sys/nfs/nfs_lock.c index 89ad654..4c220e2 100644 --- a/sys/nfs/nfs_lock.c +++ b/sys/nfs/nfs_lock.c @@ -62,6 +62,9 @@ __FBSDID("$FreeBSD$"); extern void (*nlminfo_release_p)(struct proc *p); +vop_advlock_t *nfs_advlock_p = nfs_dolock; +vop_reclaim_t *nfs_reclaim_p = NULL; + MALLOC_DEFINE(M_NFSLOCK, "nfsclient_lock", "NFS lock request"); MALLOC_DEFINE(M_NLMINFO, "nfsclient_nlminfo", "NFS lock process structure"); @@ -236,20 +239,19 @@ nfs_dolock(struct vop_advlock_args *ap) int error; struct flock *fl; struct proc *p; + struct nfsmount *nmp; td = curthread; p = td->td_proc; vp = ap->a_vp; fl = ap->a_fl; + nmp = VFSTONFS(vp->v_mount); ASSERT_VOP_LOCKED(vp, "nfs_dolock"); - bcopy(VFSTONFS(vp->v_mount)->nm_nam, &msg.lm_addr, - min(sizeof msg.lm_addr, VFSTONFS(vp->v_mount)->nm_nam->sa_len)); - msg.lm_fh_len = NFS_ISV3(vp) ? VTONFS(vp)->n_fhsize : NFSX_V2FH; - bcopy(VTONFS(vp)->n_fhp, msg.lm_fh, msg.lm_fh_len); - msg.lm_nfsv3 = NFS_ISV3(vp); + nmp->nm_getinfo(vp, msg.lm_fh, &msg.lm_fh_len, &msg.lm_addr, + &msg.lm_nfsv3, NULL); VOP_UNLOCK(vp, 0); /* diff --git a/sys/nfs/nfs_lock.h b/sys/nfs/nfs_lock.h index aa99996..ff5feb2 100644 --- a/sys/nfs/nfs_lock.h +++ b/sys/nfs/nfs_lock.h @@ -87,4 +87,6 @@ struct lockd_ans { #ifdef _KERNEL int nfs_dolock(struct vop_advlock_args *ap); +extern vop_advlock_t *nfs_advlock_p; +extern vop_reclaim_t *nfs_reclaim_p; #endif diff --git a/sys/nfs/nfs_mountcommon.h b/sys/nfs/nfs_mountcommon.h new file mode 100644 index 0000000..c004b9c --- /dev/null +++ b/sys/nfs/nfs_mountcommon.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2009 Rick Macklem, University of Guelph + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NFS_MOUNTCOMMON_H_ +#define _NFS_MOUNTCOMMON_H_ + +/* + * The common fields of the nfsmount structure for the two clients + * used by the nlm. It includes a function pointer that provides + * a mechanism for getting the client specific info for an nfs vnode. + */ +typedef void nfs_getinfofromvp_ftype(struct vnode *, uint8_t *, size_t *, + struct sockaddr_storage *, int *, off_t *); + +struct nfsmount_common { + struct mtx nmcom_mtx; + int nmcom_flag; /* Flags for soft/hard... */ + int nmcom_state; /* Internal state flags */ + struct mount *nmcom_mountp; /* Vfs structure for this filesystem */ + int nmcom_timeo; /* Init timer for NFSMNT_DUMBTIMR */ + int nmcom_retry; /* Max retries */ + char nmcom_hostname[MNAMELEN]; /* server's name */ + nfs_getinfofromvp_ftype *nmcom_getinfo; /* Get info from nfsnode */ +}; + +#endif /* _NFS_MOUNTCOMMON_H_ */ diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h index da61175..99b86f8 100644 --- a/sys/nfsclient/nfs.h +++ b/sys/nfsclient/nfs.h @@ -253,7 +253,7 @@ int nfs_writerpc(struct vnode *, struct uio *, struct ucred *, int *, int nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred, struct thread *td); int nfs_readdirrpc(struct vnode *, struct uio *, struct ucred *); -int nfs_nfsiodnew(int); +void nfs_nfsiodnew(void); void nfs_nfsiodnew_tq(__unused void *, int); int nfs_asyncio(struct nfsmount *, struct buf *, struct ucred *, struct thread *); int nfs_doio(struct vnode *, struct buf *, struct ucred *, struct thread *); diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index 2f40bb2..047df94 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -1375,13 +1375,9 @@ again: /* * Try to create one if none are free. */ - if (!gotiod) { - iod = nfs_nfsiodnew(1); - if (iod != -1) - gotiod = TRUE; - } - - if (gotiod) { + if (!gotiod) + nfs_nfsiodnew(); + else { /* * Found one, so wake it up and tell it which * mount to process. @@ -1401,7 +1397,7 @@ again: if (!gotiod) { if (nmp->nm_bufqiods > 0) { NFS_DPF(ASYNCIO, - ("nfs_asyncio: %d iods are already processing mount %p\n", + ("nfs_asyncio: %d iods are already processing mount %p\n", nmp->nm_bufqiods, nmp)); gotiod = TRUE; } @@ -1416,9 +1412,9 @@ again: * Ensure that the queue never grows too large. We still want * to asynchronize so we block rather then return EIO. */ - while (nmp->nm_bufqlen >= 2*nfs_numasync) { + while (nmp->nm_bufqlen >= 2 * nfs_numasync) { NFS_DPF(ASYNCIO, - ("nfs_asyncio: waiting for mount %p queue to drain\n", nmp)); + ("nfs_asyncio: waiting for mount %p queue to drain\n", nmp)); nmp->nm_bufqwant = TRUE; error = nfs_msleep(td, &nmp->nm_bufq, &nfs_iod_mtx, slpflag | PRIBIO, @@ -1426,7 +1422,7 @@ again: if (error) { error2 = nfs_sigintr(nmp, td); if (error2) { - mtx_unlock(&nfs_iod_mtx); + mtx_unlock(&nfs_iod_mtx); return (error2); } if (slpflag == NFS_PCATCH) { @@ -1438,17 +1434,13 @@ again: * We might have lost our iod while sleeping, * so check and loop if nescessary. */ - if (nmp->nm_bufqiods == 0) { - NFS_DPF(ASYNCIO, - ("nfs_asyncio: no iods after mount %p queue was drained, looping\n", nmp)); - goto again; - } + goto again; } /* We might have lost our nfsiod */ if (nmp->nm_bufqiods == 0) { NFS_DPF(ASYNCIO, - ("nfs_asyncio: no iods after mount %p queue was drained, looping\n", nmp)); +("nfs_asyncio: no iods after mount %p queue was drained, looping\n", nmp)); goto again; } diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c index 5e2fbcc..fcb987e 100644 --- a/sys/nfsclient/nfs_nfsiod.c +++ b/sys/nfsclient/nfs_nfsiod.c @@ -76,16 +76,6 @@ static MALLOC_DEFINE(M_NFSSVC, "nfsclient_srvsock", "Nfs server structure"); static void nfssvc_iod(void *); -struct nfsiod_str { - STAILQ_ENTRY(nfsiod_str) ni_links; - int *ni_inst; - int ni_iod; - int ni_error; - int ni_done; -}; -static STAILQ_HEAD(, nfsiod_str) nfsiodhead = - STAILQ_HEAD_INITIALIZER(nfsiodhead); - static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; SYSCTL_DECL(_vfs_nfs); @@ -101,6 +91,8 @@ unsigned int nfs_iodmax = 20; /* Minimum number of nfsiod kthreads to keep as spares */ static unsigned int nfs_iodmin = 0; +static int nfs_nfsiodnew_sync(void); + static int sysctl_iodmin(SYSCTL_HANDLER_ARGS) { @@ -124,7 +116,7 @@ sysctl_iodmin(SYSCTL_HANDLER_ARGS) * than the new minimum, create some more. */ for (i = nfs_iodmin - nfs_numasync; i > 0; i--) - nfs_nfsiodnew(0); + nfs_nfsiodnew_sync(); out: mtx_unlock(&nfs_iod_mtx); return (0); @@ -170,68 +162,55 @@ SYSCTL_PROC(_vfs_nfs, OID_AUTO, iodmax, CTLTYPE_UINT | CTLFLAG_RW, 0, sizeof (nfs_iodmax), sysctl_iodmax, "IU", "Max number of nfsiod kthreads"); +static int +nfs_nfsiodnew_sync(void) +{ + int error, i; + + mtx_assert(&nfs_iod_mtx, MA_OWNED); + for (i = 0; i < nfs_iodmax; i++) { + if (nfs_asyncdaemon[i] == 0) { + nfs_asyncdaemon[i] = 1; + break; + } + } + if (i == nfs_iodmax) + return (0); + mtx_unlock(&nfs_iod_mtx); + error = kproc_create(nfssvc_iod, nfs_asyncdaemon + i, NULL, + RFHIGHPID, 0, "nfsiod %d", i); + mtx_lock(&nfs_iod_mtx); + if (error == 0) { + nfs_numasync++; + nfs_iodwant[i] = NFSIOD_AVAILABLE; + } else + nfs_asyncdaemon[i] = 0; + return (error); +} + void nfs_nfsiodnew_tq(__unused void *arg, int pending) { - struct nfsiod_str *nip; mtx_lock(&nfs_iod_mtx); - while ((nip = STAILQ_FIRST(&nfsiodhead)) != NULL) { - STAILQ_REMOVE_HEAD(&nfsiodhead, ni_links); - mtx_unlock(&nfs_iod_mtx); - nip->ni_error = kproc_create(nfssvc_iod, nip->ni_inst, NULL, - RFHIGHPID, 0, "nfsiod %d", nip->ni_iod); - nip->ni_done = 1; - mtx_lock(&nfs_iod_mtx); - wakeup(nip); + while (pending > 0) { + pending--; + nfs_nfsiodnew_sync(); } mtx_unlock(&nfs_iod_mtx); } -int -nfs_nfsiodnew(int set_iodwant) +void +nfs_nfsiodnew(void) { - int error, i; - int newiod; - struct nfsiod_str *nip; - if (nfs_numasync >= nfs_iodmax) - return (-1); - newiod = -1; - for (i = 0; i < nfs_iodmax; i++) - if (nfs_asyncdaemon[i] == 0) { - nfs_asyncdaemon[i]++; - newiod = i; - break; - } - if (newiod == -1) - return (-1); - if (set_iodwant > 0) - nfs_iodwant[i] = NFSIOD_CREATED_FOR_NFS_ASYNCIO; - mtx_unlock(&nfs_iod_mtx); - nip = malloc(sizeof(*nip), M_TEMP, M_WAITOK | M_ZERO); - nip->ni_inst = nfs_asyncdaemon + i; - nip->ni_iod = newiod; - mtx_lock(&nfs_iod_mtx); - STAILQ_INSERT_TAIL(&nfsiodhead, nip, ni_links); + mtx_assert(&nfs_iod_mtx, MA_OWNED); taskqueue_enqueue(taskqueue_thread, &nfs_nfsiodnew_task); - while (!nip->ni_done) - mtx_sleep(nip, &nfs_iod_mtx, 0, "niwt", 0); - error = nip->ni_error; - free(nip, M_TEMP); - if (error) { - if (set_iodwant > 0) - nfs_iodwant[i] = NFSIOD_NOT_AVAILABLE; - return (-1); - } - nfs_numasync++; - return (newiod); } static void nfsiod_setup(void *dummy) { - int i; int error; TUNABLE_INT_FETCH("vfs.nfs.iodmin", &nfs_iodmin); @@ -240,8 +219,8 @@ nfsiod_setup(void *dummy) if (nfs_iodmin > NFS_MAXASYNCDAEMON) nfs_iodmin = NFS_MAXASYNCDAEMON; - for (i = 0; i < nfs_iodmin; i++) { - error = nfs_nfsiodnew(0); + while (nfs_numasync < nfs_iodmin) { + error = nfs_nfsiodnew_sync(); if (error == -1) panic("nfsiod_setup: nfs_nfsiodnew failed"); } diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c index 9e558f4..5b87bd7 100644 --- a/sys/nfsclient/nfs_node.c +++ b/sys/nfsclient/nfs_node.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/fcntl.h> #include <sys/fnv_hash.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -51,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <vm/uma.h> #include <nfs/nfsproto.h> +#include <nfs/nfs_lock.h> #include <nfsclient/nfs.h> #include <nfsclient/nfsnode.h> #include <nfsclient/nfsmount.h> diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index f07bf16..fd50ca8 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -115,6 +115,8 @@ static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp, static int mountnfs(struct nfs_args *, struct mount *, struct sockaddr *, char *, struct vnode **, struct ucred *cred, int); +static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *, + struct sockaddr_storage *, int *, off_t *); static vfs_mount_t nfs_mount; static vfs_cmount_t nfs_cmount; static vfs_unmount_t nfs_unmount; @@ -1202,6 +1204,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, bzero((caddr_t)nmp, sizeof (struct nfsmount)); TAILQ_INIT(&nmp->nm_bufq); mp->mnt_data = nmp; + nmp->nm_getinfo = nfs_getnlminfo; } vfs_getnewfsid(mp); nmp->nm_mountp = mp; @@ -1490,3 +1493,27 @@ nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req) } return (0); } + +/* + * Extract the information needed by the nlm from the nfs vnode. + */ +static void +nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp, + struct sockaddr_storage *sp, int *is_v3p, off_t *sizep) +{ + struct nfsmount *nmp; + struct nfsnode *np = VTONFS(vp); + + nmp = VFSTONFS(vp->v_mount); + if (fhlenp != NULL) + *fhlenp = (size_t)np->n_fhsize; + if (fhp != NULL) + bcopy(np->n_fhp, fhp, np->n_fhsize); + if (sp != NULL) + bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp))); + if (is_v3p != NULL) + *is_v3p = NFS_ISV3(vp); + if (sizep != NULL) + *sizep = np->n_size; +} + diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index 828a739..cb2a126 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -215,8 +215,6 @@ struct mtx nfs_iod_mtx; enum nfsiod_state nfs_iodwant[NFS_MAXASYNCDAEMON]; struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON]; int nfs_numasync = 0; -vop_advlock_t *nfs_advlock_p = nfs_dolock; -vop_reclaim_t *nfs_reclaim_p = NULL; #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) SYSCTL_DECL(_vfs_nfs); diff --git a/sys/nfsclient/nfsmount.h b/sys/nfsclient/nfsmount.h index d47957c..515c64e 100644 --- a/sys/nfsclient/nfsmount.h +++ b/sys/nfsclient/nfsmount.h @@ -36,6 +36,10 @@ #ifndef _NFSCLIENT_NFSMOUNT_H_ #define _NFSCLIENT_NFSMOUNT_H_ +#include <sys/socket.h> + +#include <nfs/nfs_mountcommon.h> + #include <rpc/types.h> #include <rpc/auth.h> #include <rpc/clnt.h> @@ -47,10 +51,7 @@ * Holds NFS specific information for mount. */ struct nfsmount { - struct mtx nm_mtx; - int nm_flag; /* Flags for soft/hard... */ - int nm_state; /* Internal state flags */ - struct mount *nm_mountp; /* Vfs structure for this filesystem */ + struct nfsmount_common nm_com; /* Common fields for nlm */ int nm_numgrps; /* Max. size of groupslist */ u_char nm_fh[NFSX_V4FH]; /* File handle of root dir */ int nm_fhsize; /* Size of root file handle */ @@ -58,8 +59,6 @@ struct nfsmount { int nm_soproto; /* and protocol */ int nm_soflags; /* pr_flags for socket protocol */ struct sockaddr *nm_nam; /* Addr of server */ - int nm_timeo; /* Init timer for NFSMNT_DUMBTIMR */ - int nm_retry; /* Max retries */ int nm_deadthresh; /* Threshold of timeouts-->dead server*/ int nm_rsize; /* Max size of read rpc */ int nm_wsize; /* Max size of write rpc */ @@ -79,7 +78,6 @@ struct nfsmount { struct nfs_rpcops *nm_rpcops; int nm_tprintf_initial_delay; /* initial delay */ int nm_tprintf_delay; /* interval for messages */ - char nm_hostname[MNAMELEN]; /* server's name */ int nm_secflavor; /* auth flavor to use for rpc */ struct __rpc_client *nm_client; struct rpc_timers nm_timers[NFS_MAX_TIMER]; /* RTT Timers for rpcs */ @@ -94,6 +92,15 @@ struct nfsmount { time_t nm_last_renewal; }; +#define nm_mtx nm_com.nmcom_mtx +#define nm_flag nm_com.nmcom_flag +#define nm_state nm_com.nmcom_state +#define nm_mountp nm_com.nmcom_mountp +#define nm_timeo nm_com.nmcom_timeo +#define nm_retry nm_com.nmcom_retry +#define nm_hostname nm_com.nmcom_hostname +#define nm_getinfo nm_com.nmcom_getinfo + #if defined(_KERNEL) /* * Convert mount ptr to nfsmount ptr. diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h index 5254689..19c1c47 100644 --- a/sys/nfsclient/nfsnode.h +++ b/sys/nfsclient/nfsnode.h @@ -165,16 +165,13 @@ struct nfsnode { #define NFS_TIMESPEC_COMPARE(T1, T2) (((T1)->tv_sec != (T2)->tv_sec) || ((T1)->tv_nsec != (T2)->tv_nsec)) /* - * NFS iod threads can be in one of these three states once spawned. + * NFS iod threads can be in one of these two states once spawned. * NFSIOD_NOT_AVAILABLE - Cannot be assigned an I/O operation at this time. * NFSIOD_AVAILABLE - Available to be assigned an I/O operation. - * NFSIOD_CREATED_FOR_NFS_ASYNCIO - Newly created for nfs_asyncio() and - * will be used by the thread that called nfs_asyncio(). */ enum nfsiod_state { NFSIOD_NOT_AVAILABLE = 0, NFSIOD_AVAILABLE = 1, - NFSIOD_CREATED_FOR_NFS_ASYNCIO = 2, }; /* @@ -190,9 +187,6 @@ extern struct vop_vector nfs_fifoops; extern struct vop_vector nfs_vnodeops; extern struct buf_ops buf_ops_nfs; -extern vop_advlock_t *nfs_advlock_p; -extern vop_reclaim_t *nfs_reclaim_p; - /* * Prototypes for NFS vnode operations */ diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c index 833bfc7..4a3876f 100644 --- a/sys/nfsserver/nfs_serv.c +++ b/sys/nfsserver/nfs_serv.c @@ -3036,7 +3036,7 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct iovec iv; struct vattr va, at, *vap = &va; struct nfs_fattr *fp; - int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; + int len, nlen, rem, xfer, tsiz, i, error = 0, error1, getret = 1; int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies; u_quad_t off, toff, verf; u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ @@ -3240,24 +3240,25 @@ again: } if (!VOP_ISLOCKED(vp)) vn_lock(vp, LK_SHARED | LK_RETRY); - if (VOP_LOOKUP(vp, &nvp, &cn) != 0) + if ((vp->v_vflag & VV_ROOT) != 0 && + (cn.cn_flags & ISDOTDOT) != 0) { + vref(vp); + nvp = vp; + } else if (VOP_LOOKUP(vp, &nvp, &cn) != 0) goto invalid; } bzero((caddr_t)nfhp, NFSX_V3FH); nfhp->fh_fsid = nvp->v_mount->mnt_stat.f_fsid; - if (VOP_VPTOFH(nvp, &nfhp->fh_fid)) { - vput(nvp); - nvp = NULL; - goto invalid; - } - if (VOP_GETATTR(nvp, vap, cred)) { + if ((error1 = VOP_VPTOFH(nvp, &nfhp->fh_fid)) == 0) + error1 = VOP_GETATTR(nvp, vap, cred); + if (vp == nvp) + vunref(nvp); + else vput(nvp); - nvp = NULL; - goto invalid; - } - vput(nvp); nvp = NULL; + if (error1 != 0) + goto invalid; /* * If either the dircount or maxcount will be diff --git a/sys/nlm/nlm_advlock.c b/sys/nlm/nlm_advlock.c index b179595..b4edb4d 100644 --- a/sys/nlm/nlm_advlock.c +++ b/sys/nlm/nlm_advlock.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mount.h> #include <sys/mutex.h> #include <sys/proc.h> +#include <sys/socket.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/unistd.h> @@ -47,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include <nfs/nfsproto.h> #include <nfsclient/nfs.h> -#include <nfsclient/nfsnode.h> #include <nfsclient/nfsmount.h> #include <nlm/nlm_prot.h> @@ -196,7 +196,6 @@ nlm_advlock_internal(struct vnode *vp, void *id, int op, struct flock *fl, { struct thread *td = curthread; struct nfsmount *nmp; - struct nfsnode *np; off_t size; size_t fhlen; union nfsfh fh; @@ -214,6 +213,7 @@ nlm_advlock_internal(struct vnode *vp, void *id, int op, struct flock *fl, struct nlm_file_svid *ns; int svid; int error; + int is_v3; ASSERT_VOP_LOCKED(vp, "nlm_advlock_1"); @@ -225,18 +225,13 @@ nlm_advlock_internal(struct vnode *vp, void *id, int op, struct flock *fl, if (op == F_SETLK || op == F_UNLCK) nfs_vinvalbuf(vp, V_SAVE, td, 1); - np = VTONFS(vp); nmp = VFSTONFS(vp->v_mount); - size = np->n_size; - sa = nmp->nm_nam; - memcpy(&ss, sa, sa->sa_len); - sa = (struct sockaddr *) &ss; strcpy(servername, nmp->nm_hostname); - fhlen = np->n_fhsize; - memcpy(&fh.fh_bytes, np->n_fhp, fhlen); + nmp->nm_getinfo(vp, fh.fh_bytes, &fhlen, &ss, &is_v3, &size); + sa = (struct sockaddr *) &ss; timo.tv_sec = nmp->nm_timeo / NFS_HZ; timo.tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ); - if (NFS_ISV3(vp)) + if (is_v3 != 0) vers = NLM_VERS4; else vers = NLM_VERS; diff --git a/sys/nlm/nlm_prot_impl.c b/sys/nlm/nlm_prot_impl.c index 5f7f8e1..ea4baca 100644 --- a/sys/nlm/nlm_prot_impl.c +++ b/sys/nlm/nlm_prot_impl.c @@ -55,8 +55,7 @@ __FBSDID("$FreeBSD$"); #include <sys/vnode.h> #include <nfs/nfsproto.h> -#include <nfsclient/nfs.h> -#include <nfsclient/nfsnode.h> +#include <nfs/nfs_lock.h> #include <nlm/nlm_prot.h> #include <nlm/sm_inter.h> @@ -2432,4 +2431,5 @@ DECLARE_MODULE(nfslockd, nfslockd_mod, SI_SUB_VFS, SI_ORDER_ANY); /* So that loader and kldload(2) can find us, wherever we are.. */ MODULE_DEPEND(nfslockd, krpc, 1, 1, 1); MODULE_DEPEND(nfslockd, nfs, 1, 1, 1); +MODULE_DEPEND(nfslockd, nfslock, 1, 1, 1); MODULE_VERSION(nfslockd, 1); diff --git a/sys/sparc64/include/tick.h b/sys/sparc64/include/tick.h index 979e93f..201a3e6 100644 --- a/sys/sparc64/include/tick.h +++ b/sys/sparc64/include/tick.h @@ -29,7 +29,7 @@ #ifndef _MACHINE_TICK_H_ #define _MACHINE_TICK_H_ -extern u_int hardclock_use_stick; +extern u_int tick_et_use_stick; void tick_clear(u_int cpu_impl); void tick_stop(u_int cpu_impl); diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c index 5a4bba6..588a0ca 100644 --- a/sys/sparc64/sparc64/mp_machdep.c +++ b/sys/sparc64/sparc64/mp_machdep.c @@ -318,7 +318,7 @@ ap_start(phandle_t node, u_int mid, u_int cpu_impl) if (OF_getprop(node, "clock-frequency", &clock, sizeof(clock)) <= 0) panic("%s: couldn't determine CPU frequency", __func__); if (clock != PCPU_GET(clock)) - hardclock_use_stick = 1; + tick_et_use_stick = 1; csa = &cpu_start_args; csa->csa_state = 0; diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c index 3291687..82c24a5 100644 --- a/sys/sparc64/sparc64/tick.c +++ b/sys/sparc64/sparc64/tick.c @@ -74,9 +74,9 @@ static int adjust_ticks = 0; SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_ticks, CTLFLAG_RD, &adjust_ticks, 0, "total number of tick interrupts with adjustment"); -u_int hardclock_use_stick = 0; -SYSCTL_INT(_machdep_tick, OID_AUTO, hardclock_use_stick, CTLFLAG_RD, - &hardclock_use_stick, 0, "hardclock uses STICK instead of TICK timer"); +u_int tick_et_use_stick = 0; +SYSCTL_INT(_machdep_tick, OID_AUTO, tick_et_use_stick, CTLFLAG_RD, + &tick_et_use_stick, 0, "tick event timer uses STICK instead of TICK"); static struct timecounter stick_tc; static struct timecounter tick_tc; @@ -96,9 +96,9 @@ static int tick_et_start(struct eventtimer *et, static int tick_et_stop(struct eventtimer *et); static void tick_intr(struct trapframe *tf); static void tick_intr_bbwar(struct trapframe *tf); -static inline void tick_hardclock_periodic(struct trapframe *tf, u_long tick, - u_long tick_increment, u_long adj); static inline void tick_process(struct trapframe *tf); +static inline void tick_process_periodic(struct trapframe *tf, u_long tick, + u_long tick_increment, u_long adj); static void stick_intr(struct trapframe *tf); static uint64_t @@ -127,7 +127,7 @@ cpu_initclocks(void) * Given that the STICK timers typically are driven at rather low * frequencies they shouldn't be used except when really necessary. */ - if (hardclock_use_stick != 0) { + if (tick_et_use_stick != 0) { intr_setup(PIL_TICK, stick_intr, -1, NULL, NULL); /* * We don't provide a CPU ticker as long as the frequency @@ -180,11 +180,11 @@ cpu_initclocks(void) #endif tc_init(&stick_tc); } - tick_et.et_name = hardclock_use_stick ? "stick" : "tick"; + tick_et.et_name = tick_et_use_stick ? "stick" : "tick"; tick_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU; tick_et.et_quality = 1000; - tick_et.et_frequency = hardclock_use_stick ? sclock : clock; + tick_et.et_frequency = tick_et_use_stick ? sclock : clock; tick_et.et_min_period.sec = 0; tick_et.et_min_period.frac = 0x00010000LLU << 32; /* To be safe. */ tick_et.et_max_period.sec = 3600 * 24; /* No practical limit. */ @@ -203,6 +203,7 @@ tick_process(struct trapframe *tf) struct trapframe *oldframe; struct thread *td; + critical_enter(); if (tick_et.et_active) { td = curthread; oldframe = td->td_intr_frame; @@ -210,13 +211,14 @@ tick_process(struct trapframe *tf) tick_et.et_event_cb(&tick_et, tick_et.et_arg); td->td_intr_frame = oldframe; } + critical_exit(); } /* * NB: the sequence of reading the (S)TICK register, calculating the value * of the next tick and writing it to the (S)TICK_COMPARE register must not * be interrupted, not even by an IPI, otherwise a value that is in the past - * could be written in the worst case, causing hardclock to stop. + * could be written in the worst case, causing the periodic timer to stop. */ static void @@ -232,7 +234,7 @@ tick_intr(struct trapframe *tf) tick = rd(tick); wr(tick_cmpr, tick + tick_increment - adj, 0); intr_restore(s); - tick_hardclock_periodic(tf, tick, tick_increment, adj); + tick_process_periodic(tf, tick, tick_increment, adj); } else { intr_restore(s); tick_process(tf); @@ -252,7 +254,7 @@ tick_intr_bbwar(struct trapframe *tf) tick = rd(tick); wrtickcmpr(tick + tick_increment - adj, 0); intr_restore(s); - tick_hardclock_periodic(tf, tick, tick_increment, adj); + tick_process_periodic(tf, tick, tick_increment, adj); } else { intr_restore(s); tick_process(tf); @@ -272,7 +274,7 @@ stick_intr(struct trapframe *tf) stick = rdstick(); wrstickcmpr(stick + tick_increment - adj, 0); intr_restore(s); - tick_hardclock_periodic(tf, stick, tick_increment, adj); + tick_process_periodic(tf, stick, tick_increment, adj); } else { intr_restore(s); tick_process(tf); @@ -280,7 +282,7 @@ stick_intr(struct trapframe *tf) } static inline void -tick_hardclock_periodic(struct trapframe *tf, u_long tick, +tick_process_periodic(struct trapframe *tf, u_long tick, u_long tick_increment, u_long adj) { u_long ref; @@ -385,7 +387,7 @@ tick_et_start(struct eventtimer *et, struct bintime *first, * out one tick to make sure that it is not missed. */ s = intr_disable(); - if (hardclock_use_stick != 0) + if (tick_et_use_stick != 0) base = rdstick(); else base = rd(tick); @@ -394,7 +396,7 @@ tick_et_start(struct eventtimer *et, struct bintime *first, base = roundup(base, div); } PCPU_SET(tickref, base); - if (hardclock_use_stick != 0) + if (tick_et_use_stick != 0) wrstickcmpr(base + fdiv, 0); else wrtickcmpr(base + fdiv, 0); diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 8e98ef4..39e9e8c 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -46,7 +46,7 @@ #include <sys/stdint.h> /* for people using printf mainly */ extern int cold; /* nonzero if we are doing a cold boot */ -extern int rebooting; /* boot() has been called. */ +extern int rebooting; /* kern_reboot() has been called. */ extern const char *panicstr; /* panic message */ extern char version[]; /* system version */ extern char copyright[]; /* system copyright */ @@ -291,6 +291,7 @@ void cpu_initclocks_ap(void); void usrinfoinit(void); /* Finalize the world */ +void kern_reboot(int) __dead2; void shutdown_nice(int); /* Timeouts */ diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index dfd4403..43e3703 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -2517,6 +2517,10 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata) CTR2(KTR_UMA, "uma_zfree_arg thread %x zone %s", curthread, zone->uz_name); + /* uma_zfree(..., NULL) does nothing, to match free(9). */ + if (item == NULL) + return; + if (zone->uz_dtor) zone->uz_dtor(item, zone->uz_size, udata); diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd index 416b5a2..4c553aa 100644 --- a/usr.bin/calendar/calendars/calendar.freebsd +++ b/usr.bin/calendar/calendars/calendar.freebsd @@ -302,7 +302,7 @@ 11/19 Konstantin Belousov <kib@FreeBSD.org> born in Kiev, USSR, 1972 11/20 Dmitry Morozovsky <marck@FreeBSD.org> born in Moscow, USSR, 1968 11/20 Gavin Atkinson <gavin@FreeBSD.org> born in Middlesbrough, United Kingdom, 1979 -11/22 Frederic Culot <culot@FreeBSD.org> born in Saint-Germain-En-Laye, France, 1976 +11/22 Frederic Culot <culot@FreeBSD.org> born in Saint-Germain-En-Laye, France, 1976 11/23 Josef Lawrence Karthauser <joe@FreeBSD.org> born in Pembury, Kent, United Kingdom, 1972 11/24 Andrey Zakhvatov <andy@FreeBSD.org> born in Chelyabinsk, Russian Federation, 1974 11/24 Daniel Gerzo <danger@FreeBSD.org> born in Bratislava, Slovakia, 1986 diff --git a/usr.bin/nc/Makefile b/usr.bin/nc/Makefile index 84d20d3..17cea06 100644 --- a/usr.bin/nc/Makefile +++ b/usr.bin/nc/Makefile @@ -9,6 +9,6 @@ CFLAGS+=-DIPSEC LDADD= -lipsec DPADD= ${LIBIPSEC} -WARNS?= 1 +WARNS?= 2 .include <bsd.prog.mk> diff --git a/usr.bin/uudecode/uudecode.c b/usr.bin/uudecode/uudecode.c index 093af7d..58c0878 100644 --- a/usr.bin/uudecode/uudecode.c +++ b/usr.bin/uudecode/uudecode.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/in.h> +#include <ctype.h> #include <err.h> #include <errno.h> #include <fcntl.h> @@ -87,7 +88,7 @@ main(int argc, char *argv[]) base64 = 1; while ((ch = getopt(argc, argv, "cimo:prs")) != -1) { - switch(ch) { + switch (ch) { case 'c': if (oflag || rflag) usage(); @@ -125,10 +126,10 @@ main(int argc, char *argv[]) usage(); } } - argc -= optind; - argv += optind; + argc -= optind; + argv += optind; - if (*argv) { + if (*argv != NULL) { rval = 0; do { infp = fopen(infile = *argv, "r"); @@ -184,7 +185,7 @@ decode2(void) void *handle; struct passwd *pw; struct stat st; - char buf[MAXPATHLEN+1]; + char buf[MAXPATHLEN + 1]; base64 = 0; /* search for header line */ @@ -259,7 +260,7 @@ decode2(void) if (pflag || strcmp(outfile, "/dev/stdout") == 0) outfp = stdout; else { - flags = O_WRONLY|O_CREAT|O_EXCL; + flags = O_WRONLY | O_CREAT | O_EXCL; if (lstat(outfile, &st) == 0) { if (iflag) { warnc(EEXIST, "%s: %s", infile, outfile); @@ -305,6 +306,7 @@ decode2(void) static int getline(char *buf, size_t size) { + if (fgets(buf, size, infp) != NULL) return (2); if (rflag) @@ -341,17 +343,19 @@ uu_decode(void) /* for each input line */ for (;;) { switch (getline(buf, sizeof(buf))) { - case 0: return (0); - case 1: return (1); + case 0: + return (0); + case 1: + return (1); } -#define DEC(c) (((c) - ' ') & 077) /* single character decode */ -#define IS_DEC(c) ( (((c) - ' ') >= 0) && (((c) - ' ') <= 077 + 1) ) +#define DEC(c) (((c) - ' ') & 077) /* single character decode */ +#define IS_DEC(c) ( (((c) - ' ') >= 0) && (((c) - ' ') <= 077 + 1) ) #define OUT_OF_RANGE do { \ warnx("%s: %s: character out of range: [%d-%d]", \ infile, outfile, 1 + ' ', 077 + ' ' + 1); \ - return (1); \ + return (1); \ } while (0) /* @@ -364,8 +368,8 @@ uu_decode(void) for (++p; i > 0; p += 4, i -= 3) if (i >= 3) { if (!(IS_DEC(*p) && IS_DEC(*(p + 1)) && - IS_DEC(*(p + 2)) && IS_DEC(*(p + 3)))) - OUT_OF_RANGE; + IS_DEC(*(p + 2)) && IS_DEC(*(p + 3)))) + OUT_OF_RANGE; ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; putc(ch, outfp); @@ -373,8 +377,7 @@ uu_decode(void) putc(ch, outfp); ch = DEC(p[2]) << 6 | DEC(p[3]); putc(ch, outfp); - } - else { + } else { if (i >= 1) { if (!(IS_DEC(*p) && IS_DEC(*(p + 1)))) OUT_OF_RANGE; @@ -383,56 +386,85 @@ uu_decode(void) } if (i >= 2) { if (!(IS_DEC(*(p + 1)) && - IS_DEC(*(p + 2)))) - OUT_OF_RANGE; + IS_DEC(*(p + 2)))) + OUT_OF_RANGE; ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; putc(ch, outfp); } if (i >= 3) { if (!(IS_DEC(*(p + 2)) && - IS_DEC(*(p + 3)))) - OUT_OF_RANGE; + IS_DEC(*(p + 3)))) + OUT_OF_RANGE; ch = DEC(p[2]) << 6 | DEC(p[3]); putc(ch, outfp); } } } switch (getline(buf, sizeof(buf))) { - case 0: return (0); - case 1: return (1); - default: return (checkend(buf, "end", "no \"end\" line")); + case 0: + return (0); + case 1: + return (1); + default: + return (checkend(buf, "end", "no \"end\" line")); } } static int base64_decode(void) { - int n; - char inbuf[MAXPATHLEN+1]; + int n, count, count4; + char inbuf[MAXPATHLEN + 1], *p; unsigned char outbuf[MAXPATHLEN * 4]; + char leftover[MAXPATHLEN + 1]; + leftover[0] = '\0'; for (;;) { - switch (getline(inbuf, sizeof(inbuf))) { - case 0: return (0); - case 1: return (1); + strcpy(inbuf, leftover); + switch (getline(inbuf + strlen(inbuf), + sizeof(inbuf) - strlen(inbuf))) { + case 0: + return (0); + case 1: + return (1); } + + count = 0; + count4 = -1; + p = inbuf; + while (*p != '\0') { + /* + * Base64 encoded strings have the following + * characters in them: A-Z, a-z, 0-9 and +, / and = + */ + if (isalnum(*p) || *p == '+' || *p == '/' || *p == '=') + count++; + if (count % 4 == 0) + count4 = p - inbuf; + p++; + } + + strcpy(leftover, inbuf + count4 + 1); + inbuf[count4 + 1] = 0; + n = b64_pton(inbuf, outbuf, sizeof(outbuf)); + if (n < 0) break; fwrite(outbuf, 1, n, outfp); } - return (checkend(inbuf, "====", - "error decoding base64 input stream")); + return (checkend(inbuf, "====", "error decoding base64 input stream")); } static void usage(void) { + (void)fprintf(stderr, -"usage: uudecode [-cimprs] [file ...]\n" -" uudecode [-i] -o output_file [file]\n" -" b64decode [-cimprs] [file ...]\n" -" b64decode [-i] -o output_file [file]\n"); + "usage: uudecode [-cimprs] [file ...]\n" + " uudecode [-i] -o output_file [file]\n" + " b64decode [-cimprs] [file ...]\n" + " b64decode [-i] -o output_file [file]\n"); exit(1); } diff --git a/usr.sbin/apmd/apmd.8 b/usr.sbin/apmd/apmd.8 index 892826c..4ca8aae 100644 --- a/usr.sbin/apmd/apmd.8 +++ b/usr.sbin/apmd/apmd.8 @@ -143,7 +143,6 @@ The structure of the .Nm configuration file is quite simple. For example: -.Pp .Bd -literal apm_event SUSPENDREQ { exec "sync && sync && sync"; @@ -161,7 +160,6 @@ to receive the APM event command 3 times and wait for a while, then execute .Nm zzz ( Ns Nm apm Fl z ) to put the system in the suspend state. -.Pp .Bl -bullet .It The apm_event keyword diff --git a/usr.sbin/gpioctl/gpioctl.8 b/usr.sbin/gpioctl/gpioctl.8 index 6747f8e..12bae3a 100644 --- a/usr.sbin/gpioctl/gpioctl.8 +++ b/usr.sbin/gpioctl/gpioctl.8 @@ -95,7 +95,6 @@ toggle value of provided pin number be verbose: for each listed pin print current configuration .El .Sh EXAMPLES -.Pp .Bl -bullet .It List pins available on GPIO controller defined by device /dev/gpioctl0 diff --git a/usr.sbin/pc-sysinstall/backend-query/list-tzones.sh b/usr.sbin/pc-sysinstall/backend-query/list-tzones.sh index 640272e..c7009b0 100755 --- a/usr.sbin/pc-sysinstall/backend-query/list-tzones.sh +++ b/usr.sbin/pc-sysinstall/backend-query/list-tzones.sh @@ -25,19 +25,10 @@ # # $FreeBSD$ -rm ${TMPDIR}/.tzonetmp >/dev/null 2>/dev/null - # Backend script which lists all the available timezones for front-ends to display -while read line -do - echo "$line" | grep "^#" >/dev/null 2>/dev/null - if [ "$?" != "0" ] - then - echo "$line" | tr -s "\t" ":" | cut -d ":" -f 3-4 >>${TMPDIR}/.tzonetmp - fi -done < /usr/share/zoneinfo/zone.tab - -sort ${TMPDIR}/.tzonetmp -rm -f ${TMPDIR}/.tzonetmp >/dev/null 2>/dev/null +egrep -v '^#' /usr/share/zoneinfo/zone.tab |\ + tr -s "\t" ":" |\ + cut -d ":" -f 3-4 |\ + sort exit 0 diff --git a/usr.sbin/pc-sysinstall/backend-query/sys-mem.sh b/usr.sbin/pc-sysinstall/backend-query/sys-mem.sh index d8555af..bc0e3a2 100755 --- a/usr.sbin/pc-sysinstall/backend-query/sys-mem.sh +++ b/usr.sbin/pc-sysinstall/backend-query/sys-mem.sh @@ -25,7 +25,4 @@ # # $FreeBSD$ -MEM=`sysctl hw.realmem | sed "s|hw.realmem: ||g"` -MEM=`expr $MEM / 1024` -MEM=`expr $MEM / 1024` -echo $MEM +expr $(sysctl -n hw.realmem) / 1048576 diff --git a/usr.sbin/ppp/ipcp.c b/usr.sbin/ppp/ipcp.c index 31aa07d..80b3a1b 100644 --- a/usr.sbin/ppp/ipcp.c +++ b/usr.sbin/ppp/ipcp.c @@ -319,8 +319,11 @@ ipcp_WriteDNS(struct ipcp *ipcp) strerror(errno)); return 0; } - } else + } else { umask(mask); + log_Printf(LogERROR,"fopen(\"%s\", \"w\") failed: %s\n", _PATH_RESCONF, + strerror(errno)); + } return 1; } |