From mav at FreeBSD.org Sun Feb 1 02:13:19 2009 From: mav at FreeBSD.org (Alexander Motin) Date: Sun Feb 1 02:13:30 2009 Subject: svn commit: r187982 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netgraph Message-ID: <200902011013.n11ADIVU050834@svn.freebsd.org> Author: mav Date: Sun Feb 1 10:13:18 2009 New Revision: 187982 URL: http://svn.freebsd.org/changeset/base/187982 Log: MFC rev. 187387 Remove strict limitation on minimal multilink MRRU. RFC claims that MRRU of 1500 must be supported, but allows smaller values to be negotiated. Enforce specified MRRU for outgoing frames. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netgraph/ng_ppp.c Modified: stable/7/sys/netgraph/ng_ppp.c ============================================================================== --- stable/7/sys/netgraph/ng_ppp.c Sun Feb 1 09:59:10 2009 (r187981) +++ stable/7/sys/netgraph/ng_ppp.c Sun Feb 1 10:13:18 2009 (r187982) @@ -128,7 +128,6 @@ MALLOC_DEFINE(M_NETGRAPH_PPP, "netgraph_ #define PROT_VJUNCOMP 0x002f /* Multilink PPP definitions */ -#define MP_MIN_MRRU 1500 /* per RFC 1990 */ #define MP_INITIAL_SEQ 0 /* per RFC 1990 */ #define MP_MIN_LINK_MRU 32 @@ -1985,6 +1984,12 @@ ng_ppp_mp_xmit(node_p node, item_p item, priv->activeLinks[0], plen)); } + /* Check peer's MRRU for this bundle. */ + if (plen > priv->conf.mrru) { + NG_FREE_ITEM(item); + return (EMSGSIZE); + } + /* Extract mbuf. */ NGI_GET_M(item, m); @@ -2540,10 +2545,6 @@ ng_ppp_config_valid(node_p node, const s return (0); } - /* Check bundle parameters */ - if (newConf->bund.enableMultilink && newConf->bund.mrru < MP_MIN_MRRU) - return (0); - /* Disallow changes to multi-link configuration while MP is active */ if (priv->numActiveLinks > 0 && newNumLinksActive > 0) { if (!priv->conf.enableMultilink From rwatson at FreeBSD.org Sun Feb 1 11:20:46 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Sun Feb 1 11:20:58 2009 Subject: svn commit: r187987 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netinet Message-ID: <200902011920.n11JKj0J064397@svn.freebsd.org> Author: rwatson Date: Sun Feb 1 19:20:45 2009 New Revision: 187987 URL: http://svn.freebsd.org/changeset/base/187987 Log: Merge r186717 from head to stable/7: Allow the IP_MINTTL socket option to be set to 0 so that it can be disabled entirely, which is its default state before set to a non-zero value. PR: 128790 Submitted by: Nick Hilliard Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netinet/ip_output.c Modified: stable/7/sys/netinet/ip_output.c ============================================================================== --- stable/7/sys/netinet/ip_output.c Sun Feb 1 18:10:06 2009 (r187986) +++ stable/7/sys/netinet/ip_output.c Sun Feb 1 19:20:45 2009 (r187987) @@ -875,7 +875,7 @@ ip_ctloutput(struct socket *so, struct s break; case IP_MINTTL: - if (optval > 0 && optval <= MAXTTL) + if (optval >= 0 && optval <= MAXTTL) inp->inp_ip_minttl = optval; else error = EINVAL; From keramida at FreeBSD.org Sun Feb 1 20:48:33 2009 From: keramida at FreeBSD.org (Giorgos Keramidas) Date: Sun Feb 1 20:48:44 2009 Subject: svn commit: r187997 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/sound/pci Message-ID: <200902020448.n124mWwn081229@svn.freebsd.org> Author: keramida (doc committer) Date: Mon Feb 2 04:48:32 2009 New Revision: 187997 URL: http://svn.freebsd.org/changeset/base/187997 Log: MFC 187375 from /head Add support for CMedia CMI120. PR: kern/123640 Approved by: ariff Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/sound/pci/cmi.c Modified: stable/7/sys/dev/sound/pci/cmi.c ============================================================================== --- stable/7/sys/dev/sound/pci/cmi.c Mon Feb 2 03:34:40 2009 (r187996) +++ stable/7/sys/dev/sound/pci/cmi.c Mon Feb 2 04:48:32 2009 (r187997) @@ -60,6 +60,7 @@ SND_DECLARE_FILE("$FreeBSD$"); #define CMI8338B_PCI_ID 0x010113f6 #define CMI8738_PCI_ID 0x011113f6 #define CMI8738B_PCI_ID 0x011213f6 +#define CMI120_USB_ID 0x01030d8c /* Buffer size max is 64k for permitted DMA boundaries */ #define CMI_DEFAULT_BUFSZ 16384 @@ -916,6 +917,9 @@ cmi_probe(device_t dev) case CMI8738B_PCI_ID: device_set_desc(dev, "CMedia CMI8738B"); return BUS_PROBE_DEFAULT; + case CMI120_USB_ID: + device_set_desc(dev, "CMedia CMI120"); + return BUS_PROBE_DEFAULT; default: return ENXIO; } From keramida at FreeBSD.org Sun Feb 1 20:57:38 2009 From: keramida at FreeBSD.org (Giorgos Keramidas) Date: Sun Feb 1 20:58:04 2009 Subject: svn commit: r187999 - stable/7/share/man/man4 Message-ID: <200902020457.n124vaUK081556@svn.freebsd.org> Author: keramida (doc committer) Date: Mon Feb 2 04:57:36 2009 New Revision: 187999 URL: http://svn.freebsd.org/changeset/base/187999 Log: MFC 187935 from /head Sometimes, depending on the bpf filter rules used in $PATTERN, the example script of the manpage feeds awk(1) with values larger than UINT32_MAX. Then awk prints a negative value, and this messes up $BPFPROG. Trying to load the resulting bpf byte codes with ngctl then fails. For example, the output for PATTERN="udp and dst net 255.255.0.0/16" should be (all in one line): bpf_prog_len=10 bpf_prog=[ { code=40 jt=0 jf=0 k=12 } { code=21 jt=7 jf=0 k=34525 } { code=21 jt=0 jf=6 k=2048 } { code=48 jt=0 jf=0 k=23 } { code=21 jt=0 jf=4 k=17 } { code=32 jt=0 jf=0 k=30 } { code=84 jt=0 jf=0 k=4294901760 } { code=21 jt=0 jf=1 k=4294901760 } { code=6 jt=0 jf=0 k=8192 } { code=6 jt=0 jf=0 k=0 } ] The two k=4294901760 values are displayed as k=-2147483648 by awk. Replace the awk script of the manpage example with a slower but safer version, that doesn't really attempt to convert the byte code printed by tcpdump from string to number and back. PR: docs/123255 Submitted by: Eugenio Maffione, eugenio.maffione at telecomitalia.it Modified: stable/7/share/man/man4/ (props changed) stable/7/share/man/man4/igb.4 (props changed) stable/7/share/man/man4/ng_bpf.4 Modified: stable/7/share/man/man4/ng_bpf.4 ============================================================================== --- stable/7/share/man/man4/ng_bpf.4 Mon Feb 2 04:53:39 2009 (r187998) +++ stable/7/share/man/man4/ng_bpf.4 Mon Feb 2 04:57:36 2009 (r187999) @@ -156,21 +156,14 @@ INHOOK="hook1" MATCHHOOK="hook2" NOTMATCHHOOK="hook3" -cat > /tmp/bpf.awk << xxENDxx -{ - if (!init) { - printf "bpf_prog_len=%d bpf_prog=[", \\$1; - init=1; - } else { - printf " { code=%d jt=%d jf=%d k=%d }", \\$1, \\$2, \\$3, \\$4; - } -} -END { - print " ]" -} -xxENDxx - -BPFPROG=`tcpdump -s 8192 -ddd ${PATTERN} | awk -f /tmp/bpf.awk` +BPFPROG=$( tcpdump -s 8192 -ddd ${PATTERN} | \\ + ( read len ; \\ + echo -n "bpf_prog_len=$len" ; \\ + echo -n "bpf_prog=[" ; \\ + while read code jt jf k ; do \\ + echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \\ + done ; \\ + echo " ]" ) ) ngctl msg ${NODEPATH} setprogram { thisHook=\\"${INHOOK}\\" \\ ifMatch=\\"${MATCHHOOK}\\" \\ From dds at FreeBSD.org Tue Feb 3 04:56:07 2009 From: dds at FreeBSD.org (Diomidis Spinellis) Date: Tue Feb 3 04:56:18 2009 Subject: svn commit: r188068 - stable/7/usr.bin/sed Message-ID: <200902031256.n13Cu5q1030739@svn.freebsd.org> Author: dds Date: Tue Feb 3 12:56:05 2009 New Revision: 188068 URL: http://svn.freebsd.org/changeset/base/188068 Log: MFC 184854 from head to stable/7 Fix the code to conform to the "or more" part of the following POSIX specification and regression test regress:25. "A function can be preceded by one or more '!' characters, in which case the function shall be applied if the addresses do not select the pattern space." _M 7/usr.bin/sed M 7/usr.bin/sed/compile.c Modified: stable/7/usr.bin/sed/ (props changed) stable/7/usr.bin/sed/compile.c Modified: stable/7/usr.bin/sed/compile.c ============================================================================== --- stable/7/usr.bin/sed/compile.c Tue Feb 3 11:04:03 2009 (r188067) +++ stable/7/usr.bin/sed/compile.c Tue Feb 3 12:56:05 2009 (r188068) @@ -224,7 +224,7 @@ nonsel: /* Now parse the command */ case NONSEL: /* ! */ p++; EATSPACE(); - cmd->nonsel = ! cmd->nonsel; + cmd->nonsel = 1; goto nonsel; case GROUP: /* { */ p++; From dds at FreeBSD.org Tue Feb 3 05:07:35 2009 From: dds at FreeBSD.org (Diomidis Spinellis) Date: Tue Feb 3 05:07:42 2009 Subject: svn commit: r188069 - stable/7/bin/cp Message-ID: <200902031307.n13D7Y8l030992@svn.freebsd.org> Author: dds Date: Tue Feb 3 13:07:34 2009 New Revision: 188069 URL: http://svn.freebsd.org/changeset/base/188069 Log: MFC r184342 from head to stable/7 Add fallback when mmap fails on regular files. Some filesystems, like smbnetfs, do not support mmap. Reported by: Harti Brandt _M cp M cp/utils.c Modified: stable/7/bin/cp/ (props changed) stable/7/bin/cp/utils.c Modified: stable/7/bin/cp/utils.c ============================================================================== --- stable/7/bin/cp/utils.c Tue Feb 3 12:56:05 2009 (r188068) +++ stable/7/bin/cp/utils.c Tue Feb 3 13:07:34 2009 (r188069) @@ -137,41 +137,39 @@ copy_file(const FTSENT *entp, int dne) * Mmap and write if less than 8M (the limit is so we don't totally * trash memory on big files. This is really a minor hack, but it * wins some CPU back. + * Some filesystems, such as smbnetfs, don't support mmap, + * so this is a best-effort attempt. */ #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED if (S_ISREG(fs->st_mode) && fs->st_size > 0 && - fs->st_size <= 8 * 1048576) { - if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ, - MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) { + fs->st_size <= 8 * 1024 * 1024 && + (p = mmap(NULL, (size_t)fs->st_size, PROT_READ, + MAP_SHARED, from_fd, (off_t)0)) != MAP_FAILED) { + wtotal = 0; + for (bufp = p, wresid = fs->st_size; ; + bufp += wcount, wresid -= (size_t)wcount) { + wcount = write(to_fd, bufp, wresid); + if (wcount <= 0) + break; + wtotal += wcount; + if (info) { + info = 0; + (void)fprintf(stderr, + "%s -> %s %3d%%\n", + entp->fts_path, to.p_path, + cp_pct(wtotal, fs->st_size)); + } + if (wcount >= (ssize_t)wresid) + break; + } + if (wcount != (ssize_t)wresid) { + warn("%s", to.p_path); + rval = 1; + } + /* Some systems don't unmap on close(2). */ + if (munmap(p, fs->st_size) < 0) { warn("%s", entp->fts_path); rval = 1; - } else { - wtotal = 0; - for (bufp = p, wresid = fs->st_size; ; - bufp += wcount, wresid -= (size_t)wcount) { - wcount = write(to_fd, bufp, wresid); - if (wcount <= 0) - break; - wtotal += wcount; - if (info) { - info = 0; - (void)fprintf(stderr, - "%s -> %s %3d%%\n", - entp->fts_path, to.p_path, - cp_pct(wtotal, fs->st_size)); - } - if (wcount >= (ssize_t)wresid) - break; - } - if (wcount != (ssize_t)wresid) { - warn("%s", to.p_path); - rval = 1; - } - /* Some systems don't unmap on close(2). */ - if (munmap(p, fs->st_size) < 0) { - warn("%s", entp->fts_path); - rval = 1; - } } } else #endif From rwatson at FreeBSD.org Tue Feb 3 05:45:58 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Tue Feb 3 05:46:10 2009 Subject: svn commit: r188069 - stable/7/bin/cp In-Reply-To: <200902031307.n13D7Y8l030992@svn.freebsd.org> References: <200902031307.n13D7Y8l030992@svn.freebsd.org> Message-ID: On Tue, 3 Feb 2009, Diomidis Spinellis wrote: > Author: dds > Date: Tue Feb 3 13:07:34 2009 > New Revision: 188069 > URL: http://svn.freebsd.org/changeset/base/188069 > > Log: > MFC r184342 from head to stable/7 > > Add fallback when mmap fails on regular files. Some filesystems, > like smbnetfs, do not support mmap. You mean smbfs? Robert N M Watson Computer Laboratory University of Cambridge > > Reported by: Harti Brandt > > _M cp > M cp/utils.c > > Modified: > stable/7/bin/cp/ (props changed) > stable/7/bin/cp/utils.c > > Modified: stable/7/bin/cp/utils.c > ============================================================================== > --- stable/7/bin/cp/utils.c Tue Feb 3 12:56:05 2009 (r188068) > +++ stable/7/bin/cp/utils.c Tue Feb 3 13:07:34 2009 (r188069) > @@ -137,41 +137,39 @@ copy_file(const FTSENT *entp, int dne) > * Mmap and write if less than 8M (the limit is so we don't totally > * trash memory on big files. This is really a minor hack, but it > * wins some CPU back. > + * Some filesystems, such as smbnetfs, don't support mmap, > + * so this is a best-effort attempt. > */ > #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED > if (S_ISREG(fs->st_mode) && fs->st_size > 0 && > - fs->st_size <= 8 * 1048576) { > - if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ, > - MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) { > + fs->st_size <= 8 * 1024 * 1024 && > + (p = mmap(NULL, (size_t)fs->st_size, PROT_READ, > + MAP_SHARED, from_fd, (off_t)0)) != MAP_FAILED) { > + wtotal = 0; > + for (bufp = p, wresid = fs->st_size; ; > + bufp += wcount, wresid -= (size_t)wcount) { > + wcount = write(to_fd, bufp, wresid); > + if (wcount <= 0) > + break; > + wtotal += wcount; > + if (info) { > + info = 0; > + (void)fprintf(stderr, > + "%s -> %s %3d%%\n", > + entp->fts_path, to.p_path, > + cp_pct(wtotal, fs->st_size)); > + } > + if (wcount >= (ssize_t)wresid) > + break; > + } > + if (wcount != (ssize_t)wresid) { > + warn("%s", to.p_path); > + rval = 1; > + } > + /* Some systems don't unmap on close(2). */ > + if (munmap(p, fs->st_size) < 0) { > warn("%s", entp->fts_path); > rval = 1; > - } else { > - wtotal = 0; > - for (bufp = p, wresid = fs->st_size; ; > - bufp += wcount, wresid -= (size_t)wcount) { > - wcount = write(to_fd, bufp, wresid); > - if (wcount <= 0) > - break; > - wtotal += wcount; > - if (info) { > - info = 0; > - (void)fprintf(stderr, > - "%s -> %s %3d%%\n", > - entp->fts_path, to.p_path, > - cp_pct(wtotal, fs->st_size)); > - } > - if (wcount >= (ssize_t)wresid) > - break; > - } > - if (wcount != (ssize_t)wresid) { > - warn("%s", to.p_path); > - rval = 1; > - } > - /* Some systems don't unmap on close(2). */ > - if (munmap(p, fs->st_size) < 0) { > - warn("%s", entp->fts_path); > - rval = 1; > - } > } > } else > #endif > From gabor at FreeBSD.org Tue Feb 3 06:26:00 2009 From: gabor at FreeBSD.org (Gabor Kovesdan) Date: Tue Feb 3 06:26:06 2009 Subject: svn commit: r188070 - stable/7/contrib/opie Message-ID: <200902031425.n13EPwtR032576@svn.freebsd.org> Author: gabor (doc,ports committer) Date: Tue Feb 3 14:25:58 2009 New Revision: 188070 URL: http://svn.freebsd.org/changeset/base/188070 Log: MFC: r187920 - Remove non-existing reference - Fix trailing comma PR: docs/85118 Submitted by: vs Modified: stable/7/contrib/opie/opiekey.1 Modified: stable/7/contrib/opie/opiekey.1 ============================================================================== --- stable/7/contrib/opie/opiekey.1 Tue Feb 3 13:07:34 2009 (r188069) +++ stable/7/contrib/opie/opiekey.1 Tue Feb 3 14:25:58 2009 (r188070) @@ -157,8 +157,7 @@ this mistake. Better checks are needed. .BR opieinfo (1), .BR opiekeys (5), .BR opieaccess (5), -.BR opiegen (1) -.BR su (1), +.BR su (1) .SH AUTHOR Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden From gabor at FreeBSD.org Tue Feb 3 06:31:00 2009 From: gabor at FreeBSD.org (Gabor Kovesdan) Date: Tue Feb 3 06:31:17 2009 Subject: svn commit: r188072 - in stable/7/share/man: man7 man8 Message-ID: <200902031430.n13EUx4e032785@svn.freebsd.org> Author: gabor (doc,ports committer) Date: Tue Feb 3 14:30:59 2009 New Revision: 188072 URL: http://svn.freebsd.org/changeset/base/188072 Log: MFC: r187916 - Rename adding_user(8) to adding_user(7). There's no adding_user utility, but the man page describes conceptual information about the process of adding a user, thus it should belong to section 7. - Remove HISTORY and BUGS sections because of the aforementioned reason. PR: docs/130151 Submitted by: Marian Cerny Added: stable/7/share/man/man7/adding_user.7 - copied, changed from r188071, stable/7/share/man/man8/adding_user.8 Deleted: stable/7/share/man/man8/adding_user.8 Modified: stable/7/share/man/man7/Makefile stable/7/share/man/man8/Makefile Modified: stable/7/share/man/man7/Makefile ============================================================================== --- stable/7/share/man/man7/Makefile Tue Feb 3 14:26:55 2009 (r188071) +++ stable/7/share/man/man7/Makefile Tue Feb 3 14:30:59 2009 (r188072) @@ -2,7 +2,8 @@ # $FreeBSD$ #MISSING: eqnchar.7 ms.7 term.7 -MAN= ascii.7 \ +MAN= adding_user.7 \ + ascii.7 \ bsd.snmpmod.mk.7 \ build.7 \ clocks.7 \ Copied and modified: stable/7/share/man/man7/adding_user.7 (from r188071, stable/7/share/man/man8/adding_user.8) ============================================================================== --- stable/7/share/man/man8/adding_user.8 Tue Feb 3 14:26:55 2009 (r188071, copy source) +++ stable/7/share/man/man7/adding_user.7 Tue Feb 3 14:30:59 2009 (r188072) @@ -32,7 +32,7 @@ .\" @(#)adduser.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd June 5, 1993 +.Dd Jan 30, 2009 .Dt ADDING_USER 8 .Os .Sh NAME @@ -108,10 +108,3 @@ skeletal login directory .Xr adduser 8 , .Xr pwd_mkdb 8 , .Xr vipw 8 -.Sh HISTORY -The -.Nm -utility appeared in -.Bx 3.0 . -.Sh BUGS -User information should (and eventually will) be stored elsewhere. Modified: stable/7/share/man/man8/Makefile ============================================================================== --- stable/7/share/man/man8/Makefile Tue Feb 3 14:26:55 2009 (r188071) +++ stable/7/share/man/man8/Makefile Tue Feb 3 14:30:59 2009 (r188072) @@ -1,8 +1,7 @@ # @(#)Makefile 8.1 (Berkeley) 6/5/93 # $FreeBSD$ -MAN= adding_user.8 \ - crash.8 \ +MAN= crash.8 \ diskless.8 \ intro.8 \ MAKEDEV.8 \ From dds at aueb.gr Tue Feb 3 06:33:20 2009 From: dds at aueb.gr (Diomidis Spinellis) Date: Tue Feb 3 06:33:27 2009 Subject: svn commit: r188069 - stable/7/bin/cp In-Reply-To: References: <200902031307.n13D7Y8l030992@svn.freebsd.org> Message-ID: <49885049.8040505@aueb.gr> Robert Watson wrote: > On Tue, 3 Feb 2009, Diomidis Spinellis wrote: > >> Author: dds >> Date: Tue Feb 3 13:07:34 2009 >> New Revision: 188069 >> URL: http://svn.freebsd.org/changeset/base/188069 >> >> Log: >> MFC r184342 from head to stable/7 >> >> Add fallback when mmap fails on regular files. Some filesystems, >> like smbnetfs, do not support mmap. > > You mean smbfs? The original report of the problem concerned SMBNetFS - a user-space implementation of SMB . Diomidis Spinellis - http://www.dmst.aueb.gr/dds From kostikbel at gmail.com Tue Feb 3 07:33:35 2009 From: kostikbel at gmail.com (Kostik Belousov) Date: Tue Feb 3 07:33:47 2009 Subject: svn commit: r188072 - in stable/7/share/man: man7 man8 In-Reply-To: <200902031430.n13EUx4e032785@svn.freebsd.org> References: <200902031430.n13EUx4e032785@svn.freebsd.org> Message-ID: <20090203144013.GM52415@deviant.kiev.zoral.com.ua> On Tue, Feb 03, 2009 at 02:30:59PM +0000, Gabor Kovesdan wrote: > Author: gabor (doc,ports committer) > Date: Tue Feb 3 14:30:59 2009 > New Revision: 188072 > URL: http://svn.freebsd.org/changeset/base/188072 > > Log: > MFC: r187916 > - Rename adding_user(8) to adding_user(7). There's no adding_user utility, > but the man page describes conceptual information about the process of > adding a user, thus it should belong to section 7. > - Remove HISTORY and BUGS sections because of the aforementioned reason. > > PR: docs/130151 > Submitted by: Marian Cerny > > Added: > stable/7/share/man/man7/adding_user.7 > - copied, changed from r188071, stable/7/share/man/man8/adding_user.8 > Deleted: > stable/7/share/man/man8/adding_user.8 The ObsoleteFiles.inc should be updated, then ? -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 195 bytes Desc: not available Url : http://lists.freebsd.org/pipermail/svn-src-stable-7/attachments/20090203/7b4037d6/attachment.pgp From rwatson at FreeBSD.org Tue Feb 3 08:08:49 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Tue Feb 3 08:09:00 2009 Subject: svn commit: r188069 - stable/7/bin/cp In-Reply-To: <49885049.8040505@aueb.gr> References: <200902031307.n13D7Y8l030992@svn.freebsd.org> <49885049.8040505@aueb.gr> Message-ID: On Tue, 3 Feb 2009, Diomidis Spinellis wrote: > Robert Watson wrote: >> On Tue, 3 Feb 2009, Diomidis Spinellis wrote: >> >>> Author: dds Date: Tue Feb 3 13:07:34 2009 New Revision: 188069 URL: >>> http://svn.freebsd.org/changeset/base/188069 >>> >>> Log: >>> MFC r184342 from head to stable/7 >>> >>> Add fallback when mmap fails on regular files. Some filesystems, >>> like smbnetfs, do not support mmap. >> >> You mean smbfs? > > The original report of the problem > > concerned SMBNetFS - a user-space implementation of SMB > . Ah, OK. Be aware that it's not possible to execve(2) from a file system that doesn't support memory mapping... Robert N M Watson Computer Laboratory University of Cambridge From gabor at FreeBSD.org Tue Feb 3 12:48:00 2009 From: gabor at FreeBSD.org (Gabor Kovesdan) Date: Tue Feb 3 12:48:16 2009 Subject: svn commit: r188103 - stable/7 Message-ID: <200902032047.n13Klwt8041607@svn.freebsd.org> Author: gabor (doc,ports committer) Date: Tue Feb 3 20:47:58 2009 New Revision: 188103 URL: http://svn.freebsd.org/changeset/base/188103 Log: MFC: Reflect adding_user.8 -> adding_user.7 rename Modified: stable/7/ObsoleteFiles.inc Modified: stable/7/ObsoleteFiles.inc ============================================================================== --- stable/7/ObsoleteFiles.inc Tue Feb 3 20:46:05 2009 (r188102) +++ stable/7/ObsoleteFiles.inc Tue Feb 3 20:47:58 2009 (r188103) @@ -14,6 +14,8 @@ # The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last. # +# 20090203: adding_user.8 moved to adding_user.7 +OLD_FILES+=usr/share/man/man8/adding_user.8.gz # 20080407: pkg_sign has been removed OLD_FILES+=usr/sbin/pkg_check OLD_FILES+=usr/sbin/pkg_sign From gabor at FreeBSD.org Tue Feb 3 13:01:40 2009 From: gabor at FreeBSD.org (=?ISO-8859-1?Q?G=E1bor_K=F6vesd=E1n?=) Date: Tue Feb 3 13:01:47 2009 Subject: svn commit: r188072 - in stable/7/share/man: man7 man8 In-Reply-To: <20090203144013.GM52415@deviant.kiev.zoral.com.ua> References: <200902031430.n13EUx4e032785@svn.freebsd.org> <20090203144013.GM52415@deviant.kiev.zoral.com.ua> Message-ID: <4988ADBD.4060502@FreeBSD.org> > The ObsoleteFiles.inc should be updated, then ? > Fixed, thanks for the reminder! -- Gabor Kovesdan EMAIL: gabor@FreeBSD.org WWW: http://www.kovesdan.org From mav at FreeBSD.org Wed Feb 4 07:02:58 2009 From: mav at FreeBSD.org (Alexander Motin) Date: Wed Feb 4 07:03:17 2009 Subject: svn commit: r188114 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/sound/pci/hda Message-ID: <200902041502.n14F2vsM079579@svn.freebsd.org> Author: mav Date: Wed Feb 4 15:02:57 2009 New Revision: 188114 URL: http://svn.freebsd.org/changeset/base/188114 Log: MFC rev. 187445, 187721, 187944 Add two more nVidia HDMI codec IDs. Specify analog beep pin widget for several AD codecs. It gives working speaker control for that systems. Fix bug in hint.hdac.X.config parsing. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/sound/pci/hda/hdac.c Modified: stable/7/sys/dev/sound/pci/hda/hdac.c ============================================================================== --- stable/7/sys/dev/sound/pci/hda/hdac.c Wed Feb 4 10:35:27 2009 (r188113) +++ stable/7/sys/dev/sound/pci/hda/hdac.c Wed Feb 4 15:02:57 2009 (r188114) @@ -83,7 +83,7 @@ #include "mixer_if.h" -#define HDA_DRV_TEST_REV "20090113_0125" +#define HDA_DRV_TEST_REV "20090131_0127" SND_DECLARE_FILE("$FreeBSD$"); @@ -761,8 +761,10 @@ static const struct { /* NVIDIA */ #define HDA_CODEC_NVIDIAMCP78 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0002) +#define HDA_CODEC_NVIDIAMCP78_2 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0006) #define HDA_CODEC_NVIDIAMCP7A HDA_CODEC_CONSTRUCT(NVIDIA, 0x0007) #define HDA_CODEC_NVIDIAMCP67 HDA_CODEC_CONSTRUCT(NVIDIA, 0x0067) +#define HDA_CODEC_NVIDIAMCP73 HDA_CODEC_CONSTRUCT(NVIDIA, 0x8001) #define HDA_CODEC_NVIDIAXXXX HDA_CODEC_CONSTRUCT(NVIDIA, 0xffff) /* INTEL */ @@ -905,7 +907,9 @@ static const struct { { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" }, { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" }, { HDA_CODEC_NVIDIAMCP67, "NVidia MCP67 HDMI" }, + { HDA_CODEC_NVIDIAMCP73, "NVidia MCP73 HDMI" }, { HDA_CODEC_NVIDIAMCP78, "NVidia MCP78 HDMI" }, + { HDA_CODEC_NVIDIAMCP78_2, "NVidia MCP78 HDMI" }, { HDA_CODEC_NVIDIAMCP7A, "NVidia MCP7A HDMI" }, { HDA_CODEC_INTELG45_1, "Intel G45 HDMI" }, { HDA_CODEC_INTELG45_2, "Intel G45 HDMI" }, @@ -2581,8 +2585,15 @@ hdac_widget_getcaps(struct hdac_widget * Change beeper pin node type to beeper to help parser. */ *waspin = 0; switch (id) { + case HDA_CODEC_AD1882: + case HDA_CODEC_AD1883: + case HDA_CODEC_AD1984: + case HDA_CODEC_AD1984A: + case HDA_CODEC_AD1984B: + case HDA_CODEC_AD1987: case HDA_CODEC_AD1988: case HDA_CODEC_AD1988B: + case HDA_CODEC_AD1989B: beeper = 26; break; case HDA_CODEC_ALC260: @@ -7095,7 +7106,7 @@ hdac_config_fetch(struct hdac_softc *sc, hdac_quirks_tab[k].key, len - inv) != 0) continue; if (len - inv != strlen(hdac_quirks_tab[k].key)) - break; + continue; HDA_BOOTVERBOSE( printf(" %s%s", (inv != 0) ? "no" : "", hdac_quirks_tab[k].key); From lulf at FreeBSD.org Wed Feb 4 09:35:22 2009 From: lulf at FreeBSD.org (Ulf Lilleengen) Date: Wed Feb 4 09:35:38 2009 Subject: svn commit: r188116 - in stable/7/sbin/geom: . class/part core misc Message-ID: <200902041735.n14HZLDE082816@svn.freebsd.org> Author: lulf Date: Wed Feb 4 17:35:21 2009 New Revision: 188116 URL: http://svn.freebsd.org/changeset/base/188116 Log: MFC r188017: - Use a separate pointer to the allocated memory for freeing, as strsep may modify the pointer argument passed to it. This triggered an assert in malloc when a geom command being run under the livefs environment. PR: bin/130632 Submitted by: Dimitry Andric Modified: stable/7/sbin/geom/ (props changed) stable/7/sbin/geom/class/part/ (props changed) stable/7/sbin/geom/core/geom.c stable/7/sbin/geom/misc/ (props changed) Modified: stable/7/sbin/geom/core/geom.c ============================================================================== --- stable/7/sbin/geom/core/geom.c Wed Feb 4 17:10:01 2009 (r188115) +++ stable/7/sbin/geom/core/geom.c Wed Feb 4 17:35:21 2009 (r188116) @@ -480,13 +480,13 @@ library_path(void) static void load_library(void) { - char *curpath, path[MAXPATHLEN], *totalpath; + char *curpath, path[MAXPATHLEN], *tofree, *totalpath; uint32_t *lib_version; void *dlh; int ret; ret = 0; - totalpath = strdup(library_path()); + tofree = totalpath = strdup(library_path()); if (totalpath == NULL) err(EXIT_FAILURE, "Not enough memory for library path"); @@ -512,7 +512,7 @@ load_library(void) } break; } - free(totalpath); + free(tofree); /* No library was found, but standard commands can still be used */ if (ret == -1) return; From rwatson at FreeBSD.org Fri Feb 6 03:03:52 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 03:04:08 2009 Subject: svn commit: r188222 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902061103.n16B3pXX059294@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 11:03:51 2009 New Revision: 188222 URL: http://svn.freebsd.org/changeset/base/188222 Log: Merge r184904 from head to stable/7: The audit queue limit variables are size_t, so use size_t for the audit queue length variables as well, avoiding storing the limit in a larger type than the length. Submitted by: sson Sponsored by: Apple Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit.c stable/7/sys/security/audit/audit_private.h Modified: stable/7/sys/security/audit/audit.c ============================================================================== --- stable/7/sys/security/audit/audit.c Fri Feb 6 10:30:46 2009 (r188221) +++ stable/7/sys/security/audit/audit.c Fri Feb 6 11:03:51 2009 (r188222) @@ -129,8 +129,8 @@ struct mtx audit_mtx; * outstanding in the system. */ struct kaudit_queue audit_q; -int audit_q_len; -int audit_pre_q_len; +size_t audit_q_len; +size_t audit_pre_q_len; /* * Audit queue control settings (minimum free, low/high water marks, etc.) Modified: stable/7/sys/security/audit/audit_private.h ============================================================================== --- stable/7/sys/security/audit/audit_private.h Fri Feb 6 10:30:46 2009 (r188221) +++ stable/7/sys/security/audit/audit_private.h Fri Feb 6 11:03:51 2009 (r188222) @@ -274,8 +274,8 @@ extern struct mtx audit_mtx; extern struct cv audit_watermark_cv; extern struct cv audit_worker_cv; extern struct kaudit_queue audit_q; -extern int audit_q_len; -extern int audit_pre_q_len; +extern size_t audit_q_len; +extern size_t audit_pre_q_len; extern int audit_in_failure; /* From rwatson at FreeBSD.org Fri Feb 6 04:06:55 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:07:15 2009 Subject: svn commit: r188223 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902061206.n16C6d7D060414@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:06:39 2009 New Revision: 188223 URL: http://svn.freebsd.org/changeset/base/188223 Log: Merge r184482 from head to stable/7: Protect the event->class lookup database using an rwlock instead of a mutex, as it's rarely changed but frequently accessed read-only from multiple threads, so a potentially significant source of contention. Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_bsm_klib.c Modified: stable/7/sys/security/audit/audit_bsm_klib.c ============================================================================== --- stable/7/sys/security/audit/audit_bsm_klib.c Fri Feb 6 11:03:51 2009 (r188222) +++ stable/7/sys/security/audit/audit_bsm_klib.c Fri Feb 6 12:06:39 2009 (r188223) @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Apple Inc. + * Copyright (c) 1999-2008 Apple Inc. * Copyright (c) 2005 Robert N. M. Watson * All rights reserved. * @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -64,9 +65,15 @@ struct evclass_list { }; static MALLOC_DEFINE(M_AUDITEVCLASS, "audit_evclass", "Audit event class"); -static struct mtx evclass_mtx; +static struct rwlock evclass_lock; static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE]; +#define EVCLASS_LOCK_INIT() rw_init(&evclass_lock, "evclass_lock") +#define EVCLASS_RLOCK() rw_rlock(&evclass_lock) +#define EVCLASS_RUNLOCK() rw_runlock(&evclass_lock) +#define EVCLASS_WLOCK() rw_wlock(&evclass_lock) +#define EVCLASS_WUNLOCK() rw_wunlock(&evclass_lock) + /* * Look up the class for an audit event in the class mapping table. */ @@ -77,7 +84,7 @@ au_event_class(au_event_t event) struct evclass_elem *evc; au_class_t class; - mtx_lock(&evclass_mtx); + EVCLASS_RLOCK(); evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE]; class = 0; LIST_FOREACH(evc, &evcl->head, entry) { @@ -87,7 +94,7 @@ au_event_class(au_event_t event) } } out: - mtx_unlock(&evclass_mtx); + EVCLASS_RUNLOCK(); return (class); } @@ -110,12 +117,12 @@ au_evclassmap_insert(au_event_t event, a */ evc_new = malloc(sizeof(*evc), M_AUDITEVCLASS, M_WAITOK); - mtx_lock(&evclass_mtx); + EVCLASS_WLOCK(); evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE]; LIST_FOREACH(evc, &evcl->head, entry) { if (evc->event == event) { evc->class = class; - mtx_unlock(&evclass_mtx); + EVCLASS_WUNLOCK(); free(evc_new, M_AUDITEVCLASS); return; } @@ -124,7 +131,7 @@ au_evclassmap_insert(au_event_t event, a evc->event = event; evc->class = class; LIST_INSERT_HEAD(&evcl->head, evc, entry); - mtx_unlock(&evclass_mtx); + EVCLASS_WUNLOCK(); } void @@ -132,7 +139,7 @@ au_evclassmap_init(void) { int i; - mtx_init(&evclass_mtx, "evclass_mtx", NULL, MTX_DEF); + EVCLASS_LOCK_INIT(); for (i = 0; i < EVCLASSMAP_HASH_TABLE_SIZE; i++) LIST_INIT(&evclass_hash[i].head); From rwatson at FreeBSD.org Fri Feb 6 04:10:35 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:10:52 2009 Subject: svn commit: r188224 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902061210.n16CAT22060548@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:10:28 2009 New Revision: 188224 URL: http://svn.freebsd.org/changeset/base/188224 Log: Merge r184948 from head to stable/7: When repeatedly accessing a thread credential, cache the credential pointer in a local thread. While this is unlikely to significantly improve performance given modern compiler behavior, it makes the code more readable and reduces diffs to the Mac OS X version of the same code (which stores things in creds in the same way, but where the cred for a thread is reached quite differently). Discussed with: sson Sponsored by: Apple Inc. Obtained from: TrustedBSD Project Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit.c stable/7/sys/security/audit/audit_arg.c stable/7/sys/security/audit/audit_syscalls.c Modified: stable/7/sys/security/audit/audit.c ============================================================================== --- stable/7/sys/security/audit/audit.c Fri Feb 6 12:06:39 2009 (r188223) +++ stable/7/sys/security/audit/audit.c Fri Feb 6 12:10:28 2009 (r188224) @@ -165,6 +165,7 @@ audit_record_ctor(void *mem, int size, v { struct kaudit_record *ar; struct thread *td; + struct ucred *cred; KASSERT(sizeof(*ar) == size, ("audit_record_ctor: wrong size")); @@ -177,15 +178,16 @@ audit_record_ctor(void *mem, int size, v /* * Export the subject credential. */ - cru2x(td->td_ucred, &ar->k_ar.ar_subj_cred); - ar->k_ar.ar_subj_ruid = td->td_ucred->cr_ruid; - ar->k_ar.ar_subj_rgid = td->td_ucred->cr_rgid; - ar->k_ar.ar_subj_egid = td->td_ucred->cr_groups[0]; - ar->k_ar.ar_subj_auid = td->td_ucred->cr_audit.ai_auid; - ar->k_ar.ar_subj_asid = td->td_ucred->cr_audit.ai_asid; + cred = td->td_ucred; + cru2x(cred, &ar->k_ar.ar_subj_cred); + ar->k_ar.ar_subj_ruid = cred->cr_ruid; + ar->k_ar.ar_subj_rgid = cred->cr_rgid; + ar->k_ar.ar_subj_egid = cred->cr_groups[0]; + ar->k_ar.ar_subj_auid = cred->cr_audit.ai_auid; + ar->k_ar.ar_subj_asid = cred->cr_audit.ai_asid; ar->k_ar.ar_subj_pid = td->td_proc->p_pid; - ar->k_ar.ar_subj_amask = td->td_ucred->cr_audit.ai_mask; - ar->k_ar.ar_subj_term_addr = td->td_ucred->cr_audit.ai_termid; + ar->k_ar.ar_subj_amask = cred->cr_audit.ai_mask; + ar->k_ar.ar_subj_term_addr = cred->cr_audit.ai_termid; return (0); } @@ -585,6 +587,7 @@ audit_proc_coredump(struct thread *td, c { struct kaudit_record *ar; struct au_mask *aumask; + struct ucred *cred; au_class_t class; int ret, sorf; char **pathp; @@ -595,11 +598,12 @@ audit_proc_coredump(struct thread *td, c /* * Make sure we are using the correct preselection mask. */ - auid = td->td_ucred->cr_audit.ai_auid; + cred = td->td_ucred; + auid = cred->cr_audit.ai_auid; if (auid == AU_DEFAUDITID) aumask = &audit_nae_mask; else - aumask = &td->td_ucred->cr_audit.ai_mask; + aumask = &cred->cr_audit.ai_mask; /* * It's possible for coredump(9) generation to fail. Make sure that * we handle this case correctly for preselection. @@ -612,6 +616,7 @@ audit_proc_coredump(struct thread *td, c if (au_preselect(AUE_CORE, class, aumask, sorf) == 0 && audit_pipe_preselect(auid, AUE_CORE, class, sorf, 0) == 0) return; + /* * If we are interested in seeing this audit record, allocate it. * Where possible coredump records should contain a pathname and arg32 Modified: stable/7/sys/security/audit/audit_arg.c ============================================================================== --- stable/7/sys/security/audit/audit_arg.c Fri Feb 6 12:06:39 2009 (r188223) +++ stable/7/sys/security/audit/audit_arg.c Fri Feb 6 12:10:28 2009 (r188224) @@ -356,6 +356,7 @@ void audit_arg_process(struct proc *p) { struct kaudit_record *ar; + struct ucred *cred; KASSERT(p != NULL, ("audit_arg_process: p == NULL")); @@ -365,13 +366,14 @@ audit_arg_process(struct proc *p) if (ar == NULL) return; - ar->k_ar.ar_arg_auid = p->p_ucred->cr_audit.ai_auid; - ar->k_ar.ar_arg_euid = p->p_ucred->cr_uid; - ar->k_ar.ar_arg_egid = p->p_ucred->cr_groups[0]; - ar->k_ar.ar_arg_ruid = p->p_ucred->cr_ruid; - ar->k_ar.ar_arg_rgid = p->p_ucred->cr_rgid; - ar->k_ar.ar_arg_asid = p->p_ucred->cr_audit.ai_asid; - ar->k_ar.ar_arg_termid_addr = p->p_ucred->cr_audit.ai_termid; + cred = p->p_ucred; + ar->k_ar.ar_arg_auid = cred->cr_audit.ai_auid; + ar->k_ar.ar_arg_euid = cred->cr_uid; + ar->k_ar.ar_arg_egid = cred->cr_groups[0]; + ar->k_ar.ar_arg_ruid = cred->cr_ruid; + ar->k_ar.ar_arg_rgid = cred->cr_rgid; + ar->k_ar.ar_arg_asid = cred->cr_audit.ai_asid; + ar->k_ar.ar_arg_termid_addr = cred->cr_audit.ai_termid; ar->k_ar.ar_arg_pid = p->p_pid; ARG_SET_VALID(ar, ARG_AUID | ARG_EUID | ARG_EGID | ARG_RUID | ARG_RGID | ARG_ASID | ARG_TERMID_ADDR | ARG_PID | ARG_PROCESS); Modified: stable/7/sys/security/audit/audit_syscalls.c ============================================================================== --- stable/7/sys/security/audit/audit_syscalls.c Fri Feb 6 12:06:39 2009 (r188223) +++ stable/7/sys/security/audit/audit_syscalls.c Fri Feb 6 12:10:28 2009 (r188224) @@ -157,7 +157,7 @@ free_out: int auditon(struct thread *td, struct auditon_args *uap) { - struct ucred *newcred, *oldcred; + struct ucred *cred, *newcred, *oldcred; int error; union auditon_udata udata; struct proc *tp; @@ -321,22 +321,21 @@ auditon(struct thread *td, struct audito PROC_UNLOCK(tp); return (EINVAL); } - if (tp->p_ucred->cr_audit.ai_termid.at_type == AU_IPv6) { + cred = tp->p_ucred; + if (cred->cr_audit.ai_termid.at_type == AU_IPv6) { PROC_UNLOCK(tp); return (EINVAL); } - udata.au_aupinfo.ap_auid = - tp->p_ucred->cr_audit.ai_auid; + udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid; udata.au_aupinfo.ap_mask.am_success = - tp->p_ucred->cr_audit.ai_mask.am_success; + cred->cr_audit.ai_mask.am_success; udata.au_aupinfo.ap_mask.am_failure = - tp->p_ucred->cr_audit.ai_mask.am_failure; + cred->cr_audit.ai_mask.am_failure; udata.au_aupinfo.ap_termid.machine = - tp->p_ucred->cr_audit.ai_termid.at_addr[0]; + cred->cr_audit.ai_termid.at_addr[0]; udata.au_aupinfo.ap_termid.port = - (dev_t)tp->p_ucred->cr_audit.ai_termid.at_port; - udata.au_aupinfo.ap_asid = - tp->p_ucred->cr_audit.ai_asid; + (dev_t)cred->cr_audit.ai_termid.at_port; + udata.au_aupinfo.ap_asid = cred->cr_audit.ai_asid; PROC_UNLOCK(tp); break; @@ -381,16 +380,14 @@ auditon(struct thread *td, struct audito return (EINVAL); if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL) return (EINVAL); - udata.au_aupinfo_addr.ap_auid = - tp->p_ucred->cr_audit.ai_auid; + cred = tp->p_ucred; + udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid; udata.au_aupinfo_addr.ap_mask.am_success = - tp->p_ucred->cr_audit.ai_mask.am_success; + cred->cr_audit.ai_mask.am_success; udata.au_aupinfo_addr.ap_mask.am_failure = - tp->p_ucred->cr_audit.ai_mask.am_failure; - udata.au_aupinfo_addr.ap_termid = - tp->p_ucred->cr_audit.ai_termid; - udata.au_aupinfo_addr.ap_asid = - tp->p_ucred->cr_audit.ai_asid; + cred->cr_audit.ai_mask.am_failure; + udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid; + udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid; PROC_UNLOCK(tp); break; @@ -500,21 +497,23 @@ int getaudit(struct thread *td, struct getaudit_args *uap) { struct auditinfo ai; + struct ucred *cred; int error; - if (jailed(td->td_ucred)) + cred = td->td_ucred; + if (jailed(cred)) return (ENOSYS); error = priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); - if (td->td_ucred->cr_audit.ai_termid.at_type == AU_IPv6) + if (cred->cr_audit.ai_termid.at_type == AU_IPv6) return (E2BIG); bzero(&ai, sizeof(ai)); - ai.ai_auid = td->td_ucred->cr_audit.ai_auid; - ai.ai_mask = td->td_ucred->cr_audit.ai_mask; - ai.ai_asid = td->td_ucred->cr_audit.ai_asid; - ai.ai_termid.machine = td->td_ucred->cr_audit.ai_termid.at_addr[0]; - ai.ai_termid.port = td->td_ucred->cr_audit.ai_termid.at_port; + ai.ai_auid = cred->cr_audit.ai_auid; + ai.ai_mask = cred->cr_audit.ai_mask; + ai.ai_asid = cred->cr_audit.ai_asid; + ai.ai_termid.machine = cred->cr_audit.ai_termid.at_addr[0]; + ai.ai_termid.port = cred->cr_audit.ai_termid.at_port; return (copyout(&ai, uap->auditinfo, sizeof(ai))); } From rwatson at FreeBSD.org Fri Feb 6 04:14:59 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:15:10 2009 Subject: svn commit: r188225 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902061214.n16CEvjs060690@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:14:57 2009 New Revision: 188225 URL: http://svn.freebsd.org/changeset/base/188225 Log: Merge r185293 from head to stable/7: Regularize /* FALLTHROUGH */ comments in the BSM event type switch, and add one that was missing. Coverity ID: 3960 Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_bsm.c Modified: stable/7/sys/security/audit/audit_bsm.c ============================================================================== --- stable/7/sys/security/audit/audit_bsm.c Fri Feb 6 12:10:28 2009 (r188224) +++ stable/7/sys/security/audit/audit_bsm.c Fri Feb 6 12:14:57 2009 (r188225) @@ -568,7 +568,7 @@ kaudit_to_bsm(struct kaudit_record *kar, tok = au_to_arg32(1, "cmd", ar->ar_arg_cmd); kau_write(rec, tok); } - /* fall thru */ + /* FALLTHROUGH */ case AUE_AUDITON_GETCAR: case AUE_AUDITON_GETCLASS: @@ -641,7 +641,8 @@ kaudit_to_bsm(struct kaudit_record *kar, tok = au_to_arg32(2, "mode", ar->ar_arg_mode); kau_write(rec, tok); } - /* fall through */ + /* FALLTHROUGH */ + case AUE_ACCESS: case AUE_CHDIR: case AUE_CHROOT: @@ -849,7 +850,8 @@ kaudit_to_bsm(struct kaudit_record *kar, tok = au_to_arg32(1, "flags", ar->ar_arg_fflags); kau_write(rec, tok); } - /* fall through */ + /* FALLTHROUGH */ + case AUE_FORK: case AUE_VFORK: if (ARG_IS_VALID(kar, ARG_PID)) { @@ -985,7 +987,7 @@ kaudit_to_bsm(struct kaudit_record *kar, tok = au_to_text(ar->ar_arg_text); kau_write(rec, tok); } - /* fall through */ + /* FALLTHROUGH */ case AUE_UMOUNT: UPATH1_VNODE1_TOKENS; @@ -1034,7 +1036,7 @@ kaudit_to_bsm(struct kaudit_record *kar, tok = au_to_arg32(3, "mode", ar->ar_arg_mode); kau_write(rec, tok); } - /* fall through */ + /* FALLTHROUGH */ case AUE_OPEN_R: case AUE_OPEN_RT: @@ -1311,6 +1313,8 @@ kaudit_to_bsm(struct kaudit_record *kar, tok = au_to_arg32(3, "mode", ar->ar_arg_mode); kau_write(rec, tok); } + /* FALLTHROUGH */ + case AUE_SHMUNLINK: if (ARG_IS_VALID(kar, ARG_TEXT)) { tok = au_to_text(ar->ar_arg_text); @@ -1344,7 +1348,7 @@ kaudit_to_bsm(struct kaudit_record *kar, tok = au_to_arg32(4, "value", ar->ar_arg_value); kau_write(rec, tok); } - /* fall through */ + /* FALLTHROUGH */ case AUE_SEMUNLINK: if (ARG_IS_VALID(kar, ARG_TEXT)) { From rwatson at FreeBSD.org Fri Feb 6 04:20:09 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:20:20 2009 Subject: svn commit: r188226 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netipx Message-ID: <200902061220.n16CK8og060901@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:20:08 2009 New Revision: 188226 URL: http://svn.freebsd.org/changeset/base/188226 Log: Merge r185928 from head to stable/7: Add missing "goto set_head" for SO_IPX_CHECKSUM; otherwise we fall through to the SO_HEADERS_ON_OUTPUT case and set that instead. Found with: Coverity Prevent(tm) Coverity ID: 3988 Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netipx/ipx_usrreq.c Modified: stable/7/sys/netipx/ipx_usrreq.c ============================================================================== --- stable/7/sys/netipx/ipx_usrreq.c Fri Feb 6 12:14:57 2009 (r188225) +++ stable/7/sys/netipx/ipx_usrreq.c Fri Feb 6 12:20:08 2009 (r188226) @@ -412,6 +412,7 @@ ipx_ctloutput(struct socket *so, struct case SO_IPX_CHECKSUM: mask = IPXP_CHECKSUM; + goto set_head; case SO_HEADERS_ON_OUTPUT: mask = IPXP_RAWOUT; From rwatson at FreeBSD.org Fri Feb 6 04:22:02 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:22:13 2009 Subject: svn commit: r188227 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902061222.n16CM0OH060994@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:22:00 2009 New Revision: 188227 URL: http://svn.freebsd.org/changeset/base/188227 Log: Merge r184489 from head to stable/7: When we drop an audit record going to and audit pipe because the audit pipe has overflowed, drop the newest, rather than oldest, record. This makes overflow drop behavior consistent with memory allocation failure leading to drop, avoids touching the consumer end of the queue from a producer, and lowers the CPU overhead of dropping a record by dropping before memory allocation and copying. Obtained from: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Fri Feb 6 12:20:08 2009 (r188226) +++ stable/7/sys/security/audit/audit_pipe.c Fri Feb 6 12:22:00 2009 (r188227) @@ -396,17 +396,22 @@ audit_pipe_preselect(au_id_t auid, au_ev /* * Append individual record to a queue -- allocate queue-local buffer, and - * add to the queue. We try to drop from the head of the queue so that more - * recent events take precedence over older ones, but if allocation fails we - * do drop the new event. + * add to the queue. If the queue is full or we can't allocate memory, drop + * the newest record. */ static void audit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len) { - struct audit_pipe_entry *ape, *ape_remove; + struct audit_pipe_entry *ape; mtx_assert(&audit_pipe_mtx, MA_OWNED); + if (ap->ap_qlen >= ap->ap_qlimit) { + ap->ap_drops++; + audit_pipe_drops++; + return; + } + ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO); if (ape == NULL) { ap->ap_drops++; @@ -425,15 +430,6 @@ audit_pipe_append(struct audit_pipe *ap, bcopy(record, ape->ape_record, record_len); ape->ape_record_len = record_len; - if (ap->ap_qlen >= ap->ap_qlimit) { - ape_remove = TAILQ_FIRST(&ap->ap_queue); - TAILQ_REMOVE(&ap->ap_queue, ape_remove, ape_queue); - audit_pipe_entry_free(ape_remove); - ap->ap_qlen--; - ap->ap_drops++; - audit_pipe_drops++; - } - TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); ap->ap_inserts++; ap->ap_qlen++; From rwatson at FreeBSD.org Fri Feb 6 04:24:32 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:24:43 2009 Subject: svn commit: r188228 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902061224.n16COUb5061110@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:24:30 2009 New Revision: 188228 URL: http://svn.freebsd.org/changeset/base/188228 Log: Merge r184488 from head to stable/7: Break out single audit_pipe_mtx into two types of locks: a global rwlock protecting the list of audit pipes, and a per-pipe mutex protecting the queue. Likewise, replace the single global condition variable used to signal delivery of a record to one or more pipes, and add a per-pipe condition variable to avoid spurious wakeups when event subscriptions differ across multiple pipes. This slightly increases the cost of delivering to audit pipes, but should reduce lock contention in the presence of multiple readers as only the per-pipe lock is required to read from a pipe, as well as avoid overheading when different pipes are used in different ways. Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Fri Feb 6 12:22:00 2009 (r188227) +++ stable/7/sys/security/audit/audit_pipe.c Fri Feb 6 12:24:30 2009 (r188228) @@ -1,5 +1,6 @@ /*- * Copyright (c) 2006 Robert N. M. Watson + * Copyright (c) 2008 Apple, Inc. * All rights reserved. * * This software was developed by Robert Watson for the TrustedBSD Project. @@ -41,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -115,6 +117,17 @@ struct audit_pipe { struct selinfo ap_selinfo; struct sigio *ap_sigio; + /* + * Per-pipe mutex protecting most fields in this data structure. + */ + struct mtx ap_lock; + + /* + * Condition variable to signal when data has been delivered to a + * pipe. + */ + struct cv ap_cv; + u_int ap_qlen; u_int ap_qlimit; @@ -144,19 +157,31 @@ struct audit_pipe { TAILQ_ENTRY(audit_pipe) ap_list; }; +#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_lock) +#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_lock, MA_OWNED) +#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_lock) +#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_lock, \ + "audit_pipe_lock", NULL, MTX_DEF) +#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_lock) +#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_lock) + /* - * Global list of audit pipes, mutex to protect it and the pipes. Finer - * grained locking may be desirable at some point. + * Global list of audit pipes, rwlock to protect it. Individual record + * queues on pipes are protected by per-pipe locks; these locks synchronize + * between threads walking the list to deliver to individual pipes and add/ + * remove of pipes, and are mostly acquired for read. */ static TAILQ_HEAD(, audit_pipe) audit_pipe_list; -static struct mtx audit_pipe_mtx; +static struct rwlock audit_pipe_lock; -/* - * This CV is used to wakeup on an audit record write. Eventually, it might - * be per-pipe to avoid unnecessary wakeups when several pipes with different - * preselection masks are present. - */ -static struct cv audit_pipe_cv; +#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \ + "audit_pipe_list_lock") +#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock) +#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock) +#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock) +#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \ + RA_WLOCKED) +#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock) /* * Cloning related variables and constants. @@ -224,7 +249,7 @@ audit_pipe_preselect_find(struct audit_p { struct audit_pipe_preselect *app; - mtx_assert(&audit_pipe_mtx, MA_OWNED); + AUDIT_PIPE_LOCK_ASSERT(ap); TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) { if (app->app_auid == auid) @@ -243,14 +268,14 @@ audit_pipe_preselect_get(struct audit_pi struct audit_pipe_preselect *app; int error; - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); app = audit_pipe_preselect_find(ap, auid); if (app != NULL) { *maskp = app->app_mask; error = 0; } else error = ENOENT; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); return (error); } @@ -268,7 +293,7 @@ audit_pipe_preselect_set(struct audit_pi * set, and allocate. We will free it if it is unneeded. */ app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK); - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); app = audit_pipe_preselect_find(ap, auid); if (app == NULL) { app = app_new; @@ -277,7 +302,7 @@ audit_pipe_preselect_set(struct audit_pi TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list); } app->app_mask = mask; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); if (app_new != NULL) free(app_new, M_AUDIT_PIPE_PRESELECT); } @@ -291,14 +316,14 @@ audit_pipe_preselect_delete(struct audit struct audit_pipe_preselect *app; int error; - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); app = audit_pipe_preselect_find(ap, auid); if (app != NULL) { TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); error = 0; } else error = ENOENT; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); if (app != NULL) free(app, M_AUDIT_PIPE_PRESELECT); return (error); @@ -312,7 +337,7 @@ audit_pipe_preselect_flush_locked(struct { struct audit_pipe_preselect *app; - mtx_assert(&audit_pipe_mtx, MA_OWNED); + AUDIT_PIPE_LOCK_ASSERT(ap); while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) { TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list); @@ -324,9 +349,9 @@ static void audit_pipe_preselect_flush(struct audit_pipe *ap) { - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); audit_pipe_preselect_flush_locked(ap); - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); } /*- @@ -345,7 +370,7 @@ audit_pipe_preselect_check(struct audit_ { struct audit_pipe_preselect *app; - mtx_assert(&audit_pipe_mtx, MA_OWNED); + AUDIT_PIPE_LOCK_ASSERT(ap); switch (ap->ap_preselect_mode) { case AUDITPIPE_PRESELECT_MODE_TRAIL: @@ -382,15 +407,18 @@ audit_pipe_preselect(au_id_t auid, au_ev { struct audit_pipe *ap; - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LIST_RLOCK(); TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { + AUDIT_PIPE_LOCK(ap); if (audit_pipe_preselect_check(ap, auid, event, class, sorf, trail_preselect)) { - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_LIST_RUNLOCK(); return (1); } + AUDIT_PIPE_UNLOCK(ap); } - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_LIST_RUNLOCK(); return (0); } @@ -404,7 +432,7 @@ audit_pipe_append(struct audit_pipe *ap, { struct audit_pipe_entry *ape; - mtx_assert(&audit_pipe_mtx, MA_OWNED); + AUDIT_PIPE_LOCK_ASSERT(ap); if (ap->ap_qlen >= ap->ap_qlimit) { ap->ap_drops++; @@ -437,6 +465,7 @@ audit_pipe_append(struct audit_pipe *ap, KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); if (ap->ap_flags & AUDIT_PIPE_ASYNC) pgsigio(&ap->ap_sigio, SIGIO, 0); + cv_broadcast(&ap->ap_cv); } /* @@ -450,20 +479,23 @@ audit_pipe_submit(au_id_t auid, au_event struct audit_pipe *ap; /* - * Lockless read to avoid mutex overhead if pipes are not in use. + * Lockless read to avoid lock overhead if pipes are not in use. */ if (TAILQ_FIRST(&audit_pipe_list) == NULL) return; - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LIST_RLOCK(); TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { + AUDIT_PIPE_LOCK(ap); if (audit_pipe_preselect_check(ap, auid, event, class, sorf, trail_select)) audit_pipe_append(ap, record, record_len); + AUDIT_PIPE_UNLOCK(ap); } + AUDIT_PIPE_LIST_RUNLOCK(); + + /* Unlocked increment. */ audit_pipe_records++; - mtx_unlock(&audit_pipe_mtx); - cv_broadcastpri(&audit_pipe_cv, PSOCK); } /* @@ -480,17 +512,21 @@ audit_pipe_submit_user(void *record, u_i struct audit_pipe *ap; /* - * Lockless read to avoid mutex overhead if pipes are not in use. + * Lockless read to avoid lock overhead if pipes are not in use. */ if (TAILQ_FIRST(&audit_pipe_list) == NULL) return; - mtx_lock(&audit_pipe_mtx); - TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) + AUDIT_PIPE_LIST_RLOCK(); + TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { + AUDIT_PIPE_LOCK(ap); audit_pipe_append(ap, record, record_len); + AUDIT_PIPE_UNLOCK(ap); + } + AUDIT_PIPE_LIST_RUNLOCK(); + + /* Unlocked increment. */ audit_pipe_records++; - mtx_unlock(&audit_pipe_mtx); - cv_broadcastpri(&audit_pipe_cv, PSOCK); } /* @@ -501,7 +537,7 @@ audit_pipe_pop(struct audit_pipe *ap) { struct audit_pipe_entry *ape; - mtx_assert(&audit_pipe_mtx, MA_OWNED); + AUDIT_PIPE_LOCK_ASSERT(ap); ape = TAILQ_FIRST(&ap->ap_queue); KASSERT((ape == NULL && ap->ap_qlen == 0) || @@ -522,15 +558,17 @@ audit_pipe_alloc(void) { struct audit_pipe *ap; - mtx_assert(&audit_pipe_mtx, MA_OWNED); + AUDIT_PIPE_LIST_WLOCK_ASSERT(); ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO); if (ap == NULL) return (NULL); ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT; TAILQ_INIT(&ap->ap_queue); - knlist_init(&ap->ap_selinfo.si_note, &audit_pipe_mtx, NULL, NULL, + knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL, NULL); + AUDIT_PIPE_LOCK_INIT(ap); + cv_init(&ap->ap_cv, "audit_pipe"); /* * Default flags, naflags, and auid-specific preselection settings to @@ -562,7 +600,7 @@ audit_pipe_flush(struct audit_pipe *ap) { struct audit_pipe_entry *ape; - mtx_assert(&audit_pipe_mtx, MA_OWNED); + AUDIT_PIPE_LOCK_ASSERT(ap); while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); @@ -574,18 +612,21 @@ audit_pipe_flush(struct audit_pipe *ap) /* * Free an audit pipe; this means freeing all preselection state and all - * records in the pipe. Assumes mutex is held to prevent any new records - * from being inserted during the free, and that the audit pipe is still on - * the global list. + * records in the pipe. Assumes global write lock and pipe mutex are held to + * prevent any new records from being inserted during the free, and that the + * audit pipe is still on the global list. */ static void audit_pipe_free(struct audit_pipe *ap) { - mtx_assert(&audit_pipe_mtx, MA_OWNED); + AUDIT_PIPE_LIST_WLOCK_ASSERT(); + AUDIT_PIPE_LOCK_ASSERT(ap); audit_pipe_preselect_flush_locked(ap); audit_pipe_flush(ap); + cv_destroy(&ap->ap_cv); + AUDIT_PIPE_LOCK_DESTROY(ap); knlist_destroy(&ap->ap_selinfo.si_note); TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); free(ap, M_AUDIT_PIPE); @@ -631,22 +672,22 @@ audit_pipe_open(struct cdev *dev, int of { struct audit_pipe *ap; - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LIST_WLOCK(); ap = dev->si_drv1; if (ap == NULL) { ap = audit_pipe_alloc(); if (ap == NULL) { - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_LIST_WUNLOCK(); return (ENOMEM); } dev->si_drv1 = ap; } else { KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open")); - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_LIST_WUNLOCK(); return (EBUSY); } - ap->ap_open = 1; - mtx_unlock(&audit_pipe_mtx); + ap->ap_open = 1; /* No lock required yet. */ + AUDIT_PIPE_LIST_WUNLOCK(); fsetown(td->td_proc->p_pid, &ap->ap_sigio); return (0); } @@ -662,12 +703,14 @@ audit_pipe_close(struct cdev *dev, int f ap = dev->si_drv1; KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL")); KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open")); + funsetown(&ap->ap_sigio); - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LIST_WLOCK(); + AUDIT_PIPE_LOCK(ap); ap->ap_open = 0; audit_pipe_free(ap); dev->si_drv1 = NULL; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_LIST_WUNLOCK(); return (0); } @@ -698,33 +741,33 @@ audit_pipe_ioctl(struct cdev *dev, u_lon */ switch (cmd) { case FIONBIO: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); if (*(int *)data) ap->ap_flags |= AUDIT_PIPE_NBIO; else ap->ap_flags &= ~AUDIT_PIPE_NBIO; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; case FIONREAD: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); if (TAILQ_FIRST(&ap->ap_queue) != NULL) *(int *)data = TAILQ_FIRST(&ap->ap_queue)->ape_record_len; else *(int *)data = 0; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; case FIOASYNC: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); if (*(int *)data) ap->ap_flags |= AUDIT_PIPE_ASYNC; else ap->ap_flags &= ~AUDIT_PIPE_ASYNC; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; @@ -768,34 +811,34 @@ audit_pipe_ioctl(struct cdev *dev, u_lon break; case AUDITPIPE_GET_PRESELECT_FLAGS: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); maskp = (au_mask_t *)data; *maskp = ap->ap_preselect_flags; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; case AUDITPIPE_SET_PRESELECT_FLAGS: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); maskp = (au_mask_t *)data; ap->ap_preselect_flags = *maskp; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; case AUDITPIPE_GET_PRESELECT_NAFLAGS: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); maskp = (au_mask_t *)data; *maskp = ap->ap_preselect_naflags; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; case AUDITPIPE_SET_PRESELECT_NAFLAGS: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); maskp = (au_mask_t *)data; ap->ap_preselect_naflags = *maskp; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; @@ -822,9 +865,9 @@ audit_pipe_ioctl(struct cdev *dev, u_lon break; case AUDITPIPE_GET_PRESELECT_MODE: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); *(int *)data = ap->ap_preselect_mode; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; @@ -833,9 +876,9 @@ audit_pipe_ioctl(struct cdev *dev, u_lon switch (mode) { case AUDITPIPE_PRESELECT_MODE_TRAIL: case AUDITPIPE_PRESELECT_MODE_LOCAL: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); ap->ap_preselect_mode = mode; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; @@ -845,9 +888,9 @@ audit_pipe_ioctl(struct cdev *dev, u_lon break; case AUDITPIPE_FLUSH: - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); audit_pipe_flush(ap); - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); error = 0; break; @@ -906,7 +949,8 @@ audit_pipe_read(struct cdev *dev, struct ap = dev->si_drv1; KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); - mtx_lock(&audit_pipe_mtx); + + AUDIT_PIPE_LOCK(ap); do { /* * Wait for a record that fits into the read buffer, dropping @@ -916,12 +960,12 @@ audit_pipe_read(struct cdev *dev, struct */ while ((ape = audit_pipe_pop(ap)) == NULL) { if (ap->ap_flags & AUDIT_PIPE_NBIO) { - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); return (EAGAIN); } - error = cv_wait_sig(&audit_pipe_cv, &audit_pipe_mtx); + error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); if (error) { - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); return (error); } } @@ -931,7 +975,7 @@ audit_pipe_read(struct cdev *dev, struct ap->ap_truncates++; } while (1); ap->ap_reads++; - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); /* * Now read record to user space memory. Even if the read is short, @@ -955,13 +999,14 @@ audit_pipe_poll(struct cdev *dev, int ev revents = 0; ap = dev->si_drv1; KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL")); + if (events & (POLLIN | POLLRDNORM)) { - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); if (TAILQ_FIRST(&ap->ap_queue) != NULL) revents |= events & (POLLIN | POLLRDNORM); else selrecord(td, &ap->ap_selinfo); - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); } return (revents); } @@ -983,9 +1028,9 @@ audit_pipe_kqfilter(struct cdev *dev, st kn->kn_fop = &audit_pipe_read_filterops; kn->kn_hook = ap; - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); knlist_add(&ap->ap_selinfo.si_note, kn, 1); - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); return (0); } @@ -998,11 +1043,11 @@ audit_pipe_kqread(struct knote *kn, long struct audit_pipe_entry *ape; struct audit_pipe *ap; - mtx_assert(&audit_pipe_mtx, MA_OWNED); - ap = (struct audit_pipe *)kn->kn_hook; KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); + AUDIT_PIPE_LOCK_ASSERT(ap); + if (ap->ap_qlen != 0) { ape = TAILQ_FIRST(&ap->ap_queue); KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); @@ -1026,9 +1071,9 @@ audit_pipe_kqdetach(struct knote *kn) ap = (struct audit_pipe *)kn->kn_hook; KASSERT(ap != NULL, ("audit_pipe_kqdetach: ap == NULL")); - mtx_lock(&audit_pipe_mtx); + AUDIT_PIPE_LOCK(ap); knlist_remove(&ap->ap_selinfo.si_note, kn, 1); - mtx_unlock(&audit_pipe_mtx); + AUDIT_PIPE_UNLOCK(ap); } /* @@ -1039,8 +1084,7 @@ audit_pipe_init(void *unused) { TAILQ_INIT(&audit_pipe_list); - mtx_init(&audit_pipe_mtx, "audit_pipe_mtx", NULL, MTX_DEF); - cv_init(&audit_pipe_cv, "audit_pipe_cv"); + AUDIT_PIPE_LIST_LOCK_INIT(); clone_setup(&audit_pipe_clones); audit_pipe_eh_tag = EVENTHANDLER_REGISTER(dev_clone, From rwatson at FreeBSD.org Fri Feb 6 04:27:27 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:27:38 2009 Subject: svn commit: r188229 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902061227.n16CRPQh061220@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:27:25 2009 New Revision: 188229 URL: http://svn.freebsd.org/changeset/base/188229 Log: Merge r186603 from head to stabl/7: Rename mbcnt to mbcnt_delta in uipc_send() -- unlike other local variables named mbcnt in uipc_usrreq.c, this instance is a delta rather than a cache of sb_mbcnt. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/uipc_usrreq.c Modified: stable/7/sys/kern/uipc_usrreq.c ============================================================================== --- stable/7/sys/kern/uipc_usrreq.c Fri Feb 6 12:24:30 2009 (r188228) +++ stable/7/sys/kern/uipc_usrreq.c Fri Feb 6 12:27:25 2009 (r188229) @@ -751,7 +751,7 @@ uipc_send(struct socket *so, int flags, { struct unpcb *unp, *unp2; struct socket *so2; - u_int mbcnt, sbcc; + u_int mbcnt_delta, sbcc; u_long newhiwat; int error = 0; @@ -881,7 +881,7 @@ uipc_send(struct socket *so, int flags, control = NULL; } else sbappend_locked(&so2->so_rcv, m); - mbcnt = so2->so_rcv.sb_mbcnt - unp2->unp_mbcnt; + mbcnt_delta = so2->so_rcv.sb_mbcnt - unp2->unp_mbcnt; unp2->unp_mbcnt = so2->so_rcv.sb_mbcnt; sbcc = so2->so_rcv.sb_cc; sorwakeup_locked(so2); @@ -890,7 +890,7 @@ uipc_send(struct socket *so, int flags, newhiwat = so->so_snd.sb_hiwat - (sbcc - unp2->unp_cc); (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat, newhiwat, RLIM_INFINITY); - so->so_snd.sb_mbmax -= mbcnt; + so->so_snd.sb_mbmax -= mbcnt_delta; SOCKBUF_UNLOCK(&so->so_snd); unp2->unp_cc = sbcc; UNP_PCB_UNLOCK(unp2); From rwatson at FreeBSD.org Fri Feb 6 04:33:40 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:33:57 2009 Subject: svn commit: r188230 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902061233.n16CXd1s061422@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:33:39 2009 New Revision: 188230 URL: http://svn.freebsd.org/changeset/base/188230 Log: Merge r187881 from head to stable/7: If a process is a zombie and we couldn't identify another useful state, print out the state as "zombine" in preference to "unknown" when ^T is pressed. Sponsored by: Google, Inc. (Note that this change appears in tty.c in 7.x vs tty_info.c in 8.x) Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/tty.c Modified: stable/7/sys/kern/tty.c ============================================================================== --- stable/7/sys/kern/tty.c Fri Feb 6 12:27:25 2009 (r188229) +++ stable/7/sys/kern/tty.c Fri Feb 6 12:33:39 2009 (r188230) @@ -2608,6 +2608,8 @@ ttyinfo(struct tty *tp) state = "suspended"; else if (TD_AWAITING_INTR(td)) state = "intrwait"; + else if (pick->p_state == PRS_ZOMBIE) + state = "zombie"; else state = "unknown"; pctcpu = (sched_pctcpu(td) * 10000 + FSCALE / 2) >> FSHIFT; From rwatson at FreeBSD.org Fri Feb 6 04:39:43 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 04:40:01 2009 Subject: svn commit: r188231 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb ufs/ffs Message-ID: <200902061239.n16CdgsN061589@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 12:39:42 2009 New Revision: 188231 URL: http://svn.freebsd.org/changeset/base/188231 Log: Merge r187790 from head to stable/7: Following a fair amount of real world experience with ACLs and extended attributes since FreeBSD 5, make the following semantic changes: - Don't update the inode modification time (mtime) when extended attributes (and hence also ACLs) are added, modified, or removed. - Don't update the inode access tie (atime) when extended attributes (and hence also ACLs) are queried. This means that rsync (and related tools) won't improperly think that the data in the file has changed when only the ACL has changed. Note that ffs_reallocblks() has not been changed to not update on an IO_EXT transaction, but currently EAs don't use the cluster write routines so this shouldn't be a problem. If EAs grow support for clustering, then VOP_REALLOCBLKS() will need to grow a flag argument to carry down IO_EXT to UFS. PR: ports/125739 Reported by: Alexander Zagrebin Tested by: pluknet , Greg Byshenk Discussed with: kib, kientzle, timur, Alexander Bokovoy Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/ufs/ffs/ffs_alloc.c stable/7/sys/ufs/ffs/ffs_balloc.c stable/7/sys/ufs/ffs/ffs_extern.h stable/7/sys/ufs/ffs/ffs_inode.c stable/7/sys/ufs/ffs/ffs_vnops.c Modified: stable/7/sys/ufs/ffs/ffs_alloc.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_alloc.c Fri Feb 6 12:33:39 2009 (r188230) +++ stable/7/sys/ufs/ffs/ffs_alloc.c Fri Feb 6 12:39:42 2009 (r188231) @@ -130,10 +130,10 @@ static int ffs_reallocblks_ufs2(struct v * available block is located. */ int -ffs_alloc(ip, lbn, bpref, size, cred, bnp) +ffs_alloc(ip, lbn, bpref, size, flags, cred, bnp) struct inode *ip; ufs2_daddr_t lbn, bpref; - int size; + int size, flags; struct ucred *cred; ufs2_daddr_t *bnp; { @@ -191,7 +191,10 @@ retry: UFS_UNLOCK(ump); } DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (flags & IO_EXT) + ip->i_flag |= IN_CHANGE; + else + ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; return (0); } @@ -227,12 +230,12 @@ nospace: * invoked to get an appropriate block. */ int -ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, cred, bpp) +ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp) struct inode *ip; ufs2_daddr_t lbprev; ufs2_daddr_t bprev; ufs2_daddr_t bpref; - int osize, nsize; + int osize, nsize, flags; struct ucred *cred; struct buf **bpp; { @@ -317,7 +320,10 @@ retry: UFS_UNLOCK(ump); } DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (flags & IO_EXT) + ip->i_flag |= IN_CHANGE; + else + ip->i_flag |= IN_CHANGE | IN_UPDATE; allocbuf(bp, nsize); bp->b_flags |= B_DONE; if ((bp->b_flags & (B_MALLOC | B_VMIO)) != B_VMIO) @@ -392,7 +398,10 @@ retry: UFS_UNLOCK(ump); } DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (flags & IO_EXT) + ip->i_flag |= IN_CHANGE; + else + ip->i_flag |= IN_CHANGE | IN_UPDATE; allocbuf(bp, nsize); bp->b_flags |= B_DONE; if ((bp->b_flags & (B_MALLOC | B_VMIO)) != B_VMIO) Modified: stable/7/sys/ufs/ffs/ffs_balloc.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_balloc.c Fri Feb 6 12:33:39 2009 (r188230) +++ stable/7/sys/ufs/ffs/ffs_balloc.c Fri Feb 6 12:39:42 2009 (r188231) @@ -133,7 +133,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t UFS_LOCK(ump); error = ffs_realloccg(ip, nb, dp->di_db[nb], ffs_blkpref_ufs1(ip, lastlbn, (int)nb, - &dp->di_db[0]), osize, (int)fs->fs_bsize, cred, &bp); + &dp->di_db[0]), osize, (int)fs->fs_bsize, flags, + cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -184,7 +185,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t UFS_LOCK(ump); error = ffs_realloccg(ip, lbn, dp->di_db[lbn], ffs_blkpref_ufs1(ip, lbn, (int)lbn, - &dp->di_db[0]), osize, nsize, cred, &bp); + &dp->di_db[0]), osize, nsize, flags, + cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -200,7 +202,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t UFS_LOCK(ump); error = ffs_alloc(ip, lbn, ffs_blkpref_ufs1(ip, lbn, (int)lbn, &dp->di_db[0]), - nsize, cred, &newb); + nsize, flags, cred, &newb); if (error) return (error); bp = getblk(vp, lbn, nsize, 0, 0, 0); @@ -241,7 +243,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t UFS_LOCK(ump); pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0); if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, - cred, &newb)) != 0) { + flags, cred, &newb)) != 0) { curthread->td_pflags &= saved_inbdflush; return (error); } @@ -291,8 +293,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t UFS_LOCK(ump); if (pref == 0) pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0); - if ((error = - ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) { + if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, + flags, cred, &newb)) != 0) { brelse(bp); goto fail; } @@ -346,7 +348,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t UFS_LOCK(ump); pref = ffs_blkpref_ufs1(ip, lbn, indirs[i].in_off, &bap[0]); error = ffs_alloc(ip, - lbn, pref, (int)fs->fs_bsize, cred, &newb); + lbn, pref, (int)fs->fs_bsize, flags, cred, &newb); if (error) { brelse(bp); goto fail; @@ -534,7 +536,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t dp->di_extb[nb], ffs_blkpref_ufs2(ip, lastlbn, (int)nb, &dp->di_extb[0]), osize, - (int)fs->fs_bsize, cred, &bp); + (int)fs->fs_bsize, flags, cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -545,7 +547,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t dp->di_extsize = smalllblktosize(fs, nb + 1); dp->di_extb[nb] = dbtofsb(fs, bp->b_blkno); bp->b_xflags |= BX_ALTDATA; - ip->i_flag |= IN_CHANGE | IN_UPDATE; + ip->i_flag |= IN_CHANGE; if (flags & IO_SYNC) bwrite(bp); else @@ -588,7 +590,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t error = ffs_realloccg(ip, -1 - lbn, dp->di_extb[lbn], ffs_blkpref_ufs2(ip, lbn, (int)lbn, - &dp->di_extb[0]), osize, nsize, cred, &bp); + &dp->di_extb[0]), osize, nsize, flags, + cred, &bp); if (error) return (error); bp->b_xflags |= BX_ALTDATA; @@ -605,7 +608,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t UFS_LOCK(ump); error = ffs_alloc(ip, lbn, ffs_blkpref_ufs2(ip, lbn, (int)lbn, &dp->di_extb[0]), - nsize, cred, &newb); + nsize, flags, cred, &newb); if (error) return (error); bp = getblk(vp, -1 - lbn, nsize, 0, 0, 0); @@ -618,7 +621,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t nsize, 0, bp); } dp->di_extb[lbn] = dbtofsb(fs, bp->b_blkno); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + ip->i_flag |= IN_CHANGE; *bpp = bp; return (0); } @@ -636,7 +639,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t error = ffs_realloccg(ip, nb, dp->di_db[nb], ffs_blkpref_ufs2(ip, lastlbn, (int)nb, &dp->di_db[0]), osize, (int)fs->fs_bsize, - cred, &bp); + flags, cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -688,7 +691,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t UFS_LOCK(ump); error = ffs_realloccg(ip, lbn, dp->di_db[lbn], ffs_blkpref_ufs2(ip, lbn, (int)lbn, - &dp->di_db[0]), osize, nsize, cred, &bp); + &dp->di_db[0]), osize, nsize, flags, + cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -704,7 +708,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t UFS_LOCK(ump); error = ffs_alloc(ip, lbn, ffs_blkpref_ufs2(ip, lbn, (int)lbn, - &dp->di_db[0]), nsize, cred, &newb); + &dp->di_db[0]), nsize, flags, cred, &newb); if (error) return (error); bp = getblk(vp, lbn, nsize, 0, 0, 0); @@ -745,7 +749,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t UFS_LOCK(ump); pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0); if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, - cred, &newb)) != 0) { + flags, cred, &newb)) != 0) { curthread->td_pflags &= saved_inbdflush; return (error); } @@ -795,8 +799,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t UFS_LOCK(ump); if (pref == 0) pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0); - if ((error = - ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) { + if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, + flags, cred, &newb)) != 0) { brelse(bp); goto fail; } @@ -850,7 +854,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t UFS_LOCK(ump); pref = ffs_blkpref_ufs2(ip, lbn, indirs[i].in_off, &bap[0]); error = ffs_alloc(ip, - lbn, pref, (int)fs->fs_bsize, cred, &newb); + lbn, pref, (int)fs->fs_bsize, flags, cred, &newb); if (error) { brelse(bp); goto fail; Modified: stable/7/sys/ufs/ffs/ffs_extern.h ============================================================================== --- stable/7/sys/ufs/ffs/ffs_extern.h Fri Feb 6 12:33:39 2009 (r188230) +++ stable/7/sys/ufs/ffs/ffs_extern.h Fri Feb 6 12:39:42 2009 (r188231) @@ -48,8 +48,8 @@ struct vnode; struct vop_fsync_args; struct vop_reallocblks_args; -int ffs_alloc(struct inode *, - ufs2_daddr_t, ufs2_daddr_t, int, struct ucred *, ufs2_daddr_t *); +int ffs_alloc(struct inode *, ufs2_daddr_t, ufs2_daddr_t, int, int, + struct ucred *, ufs2_daddr_t *); int ffs_balloc_ufs1(struct vnode *a_vp, off_t a_startoffset, int a_size, struct ucred *a_cred, int a_flags, struct buf **a_bpp); int ffs_balloc_ufs2(struct vnode *a_vp, off_t a_startoffset, int a_size, @@ -72,7 +72,7 @@ void ffs_load_inode(struct buf *, struct int ffs_mountroot(void); int ffs_reallocblks(struct vop_reallocblks_args *); int ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t, - ufs2_daddr_t, int, int, struct ucred *, struct buf **); + ufs2_daddr_t, int, int, int, struct ucred *, struct buf **); int ffs_sbupdate(struct ufsmount *, int, int); void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t); int ffs_snapblkfree(struct fs *, struct vnode *, ufs2_daddr_t, long, ino_t); Modified: stable/7/sys/ufs/ffs/ffs_inode.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_inode.c Fri Feb 6 12:33:39 2009 (r188230) +++ stable/7/sys/ufs/ffs/ffs_inode.c Fri Feb 6 12:39:42 2009 (r188231) @@ -208,7 +208,7 @@ ffs_truncate(vp, length, flags, cred, td oldblks[i] = ip->i_din2->di_extb[i]; ip->i_din2->di_extb[i] = 0; } - ip->i_flag |= IN_CHANGE | IN_UPDATE; + ip->i_flag |= IN_CHANGE; if ((error = ffs_update(vp, 1))) return (error); for (i = 0; i < NXADDR; i++) { Modified: stable/7/sys/ufs/ffs/ffs_vnops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vnops.c Fri Feb 6 12:33:39 2009 (r188230) +++ stable/7/sys/ufs/ffs/ffs_vnops.c Fri Feb 6 12:39:42 2009 (r188231) @@ -1004,13 +1004,6 @@ ffs_extread(struct vnode *vp, struct uio bqrelse(bp); } } - - if ((error == 0 || uio->uio_resid != orig_resid) && - (vp->v_mount->mnt_flag & MNT_NOATIME) == 0) { - VI_LOCK(vp); - ip->i_flag |= IN_ACCESS; - VI_UNLOCK(vp); - } return (error); } @@ -1116,7 +1109,7 @@ ffs_extwrite(struct vnode *vp, struct ui bdwrite(bp); if (error || xfersize == 0) break; - ip->i_flag |= IN_CHANGE | IN_UPDATE; + ip->i_flag |= IN_CHANGE; } /* * If we successfully wrote any data, and we are not the superuser From jhb at FreeBSD.org Fri Feb 6 07:28:10 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Fri Feb 6 07:28:27 2009 Subject: svn commit: r188238 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb net Message-ID: <200902061528.n16FS8cu065036@svn.freebsd.org> Author: jhb Date: Fri Feb 6 15:28:08 2009 New Revision: 188238 URL: http://svn.freebsd.org/changeset/base/188238 Log: MFC: Only start the if_slowtimo timer if it is needed. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/net/if.c Modified: stable/7/sys/net/if.c ============================================================================== --- stable/7/sys/net/if.c Fri Feb 6 15:27:40 2009 (r188237) +++ stable/7/sys/net/if.c Fri Feb 6 15:28:08 2009 (r188238) @@ -84,6 +84,8 @@ #include +static int slowtimo_started; + SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); @@ -399,7 +401,13 @@ if_check(void *dummy __unused) } IFNET_RUNLOCK(); splx(s); - if_slowtimo(0); + + /* + * If at least one interface added during boot uses + * if_watchdog then start the timer. + */ + if (slowtimo_started) + if_slowtimo(0); } /* @@ -602,9 +610,17 @@ if_attach(struct ifnet *ifp) /* Announce the interface. */ rt_ifannouncemsg(ifp, IFAN_ARRIVAL); - if (ifp->if_watchdog != NULL) + if (ifp->if_watchdog != NULL) { if_printf(ifp, "WARNING: using obsoleted if_watchdog interface\n"); + + /* + * Note that we need if_slowtimo(). If this happens after + * boot, then call if_slowtimo() directly. + */ + if (atomic_cmpset_int(&slowtimo_started, 0, 1) && !cold) + if_slowtimo(0); + } if (ifp->if_flags & IFF_NEEDSGIANT) if_printf(ifp, "WARNING: using obsoleted IFF_NEEDSGIANT flag\n"); From jhb at FreeBSD.org Fri Feb 6 08:05:03 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Fri Feb 6 08:05:19 2009 Subject: svn commit: r188239 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902061605.n16G50pb065704@svn.freebsd.org> Author: jhb Date: Fri Feb 6 16:05:00 2009 New Revision: 188239 URL: http://svn.freebsd.org/changeset/base/188239 Log: MFC: Push down Giant in the vlnru kproc main loop so that it is only acquired around calls to vlrureclaim() on non-MPSAFE filesystems. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/vfs_subr.c Modified: stable/7/sys/kern/vfs_subr.c ============================================================================== --- stable/7/sys/kern/vfs_subr.c Fri Feb 6 15:28:08 2009 (r188238) +++ stable/7/sys/kern/vfs_subr.c Fri Feb 6 16:05:00 2009 (r188239) @@ -717,15 +717,13 @@ static void vnlru_proc(void) { struct mount *mp, *nmp; - int done; + int done, vfslocked; struct proc *p = vnlruproc; struct thread *td = curthread; EVENTHANDLER_REGISTER(shutdown_pre_sync, kproc_shutdown, p, SHUTDOWN_PRI_FIRST); - mtx_lock(&Giant); - for (;;) { kthread_suspend_check(p); mtx_lock(&vnode_free_list_mtx); @@ -742,19 +740,13 @@ vnlru_proc(void) done = 0; mtx_lock(&mountlist_mtx); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { - int vfsunlocked; if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { nmp = TAILQ_NEXT(mp, mnt_list); continue; } - if (!VFS_NEEDSGIANT(mp)) { - mtx_unlock(&Giant); - vfsunlocked = 1; - } else - vfsunlocked = 0; + vfslocked = VFS_LOCK_GIANT(mp); done += vlrureclaim(mp); - if (vfsunlocked) - mtx_lock(&Giant); + VFS_UNLOCK_GIANT(vfslocked); mtx_lock(&mountlist_mtx); nmp = TAILQ_NEXT(mp, mnt_list); vfs_unbusy(mp, td); From tabthorpe at FreeBSD.org Fri Feb 6 09:19:04 2009 From: tabthorpe at FreeBSD.org (Thomas Abthorpe) Date: Fri Feb 6 09:19:16 2009 Subject: svn commit: r188241 - stable/7/share/man/man5 Message-ID: <200902061719.n16HJ26o067119@svn.freebsd.org> Author: tabthorpe (ports committer) Date: Fri Feb 6 17:19:02 2009 New Revision: 188241 URL: http://svn.freebsd.org/changeset/base/188241 Log: - MFC the portindex(5) manual page PR: docs/70652 Approved by: trhodes Added: stable/7/share/man/man5/portindex.5 - copied, changed from r187825, head/share/man/man5/portindex.5 Modified: stable/7/share/man/man5/Makefile Modified: stable/7/share/man/man5/Makefile ============================================================================== --- stable/7/share/man/man5/Makefile Fri Feb 6 17:14:07 2009 (r188240) +++ stable/7/share/man/man5/Makefile Fri Feb 6 17:19:02 2009 (r188241) @@ -51,6 +51,7 @@ MAN= acct.5 \ pbm.5 \ periodic.conf.5 \ phones.5 \ + portindex.5 \ portsnap.conf.5 \ procfs.5 \ protocols.5 \ Copied and modified: stable/7/share/man/man5/portindex.5 (from r187825, head/share/man/man5/portindex.5) ============================================================================== --- head/share/man/man5/portindex.5 Wed Jan 28 15:22:44 2009 (r187825, copy source) +++ stable/7/share/man/man5/portindex.5 Fri Feb 6 17:19:02 2009 (r188241) @@ -90,8 +90,8 @@ branch. vim-6.3.15|/usr/ports/editors/vim|/usr/local|Vi "workalike", with many additional features|/usr/ports/editors/vim/pkg-descr|obrien@FreeBSD.org|editors|libiconv-1.9.2_1|libiconv-1.9.2_1|http://www.vim.org/||| .Ed .Sh SEE ALSO -.Xr csup 1 , .Xr build 1 , +.Xr csup 1 , .Xr ports 7 .Sh AUTHORS .An -nosplit From rwatson at FreeBSD.org Fri Feb 6 15:56:03 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 15:56:09 2009 Subject: svn commit: r188253 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902062356.n16Nu2PK074799@svn.freebsd.org> Author: rwatson Date: Fri Feb 6 23:56:02 2009 New Revision: 188253 URL: http://svn.freebsd.org/changeset/base/188253 Log: Merge r186684 from head to stable/7: White space and comment tweaks. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/uipc_usrreq.c Modified: stable/7/sys/kern/uipc_usrreq.c ============================================================================== --- stable/7/sys/kern/uipc_usrreq.c Fri Feb 6 22:40:15 2009 (r188252) +++ stable/7/sys/kern/uipc_usrreq.c Fri Feb 6 23:56:02 2009 (r188253) @@ -1204,14 +1204,14 @@ unp_connect(struct socket *so, struct so unp3->unp_addr = (struct sockaddr_un *) sa; sa = NULL; } + /* - * unp_peercred management: - * * The connecter's (client's) credentials are copied from its * process structure at the time of connect() (which is now). */ cru2x(td->td_ucred, &unp3->unp_peercred); unp3->unp_flags |= UNP_HAVEPC; + /* * The receiver's (server's) credentials are copied from the * unp_peercred member of socket on which the former called From rwatson at FreeBSD.org Fri Feb 6 16:05:11 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 6 16:05:23 2009 Subject: svn commit: r188255 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/mac Message-ID: <200902070005.n1705Abs075088@svn.freebsd.org> Author: rwatson Date: Sat Feb 7 00:05:10 2009 New Revision: 188255 URL: http://svn.freebsd.org/changeset/base/188255 Log: Merge r187667 from head to stable/7: Use __FBSDID() for $FreeBSD$ version strings in .c files. Obtained from: TrustedBSD Project Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/mac/mac_audit.c stable/7/sys/security/mac/mac_priv.c Modified: stable/7/sys/security/mac/mac_audit.c ============================================================================== --- stable/7/sys/security/mac/mac_audit.c Sat Feb 7 00:01:10 2009 (r188254) +++ stable/7/sys/security/mac/mac_audit.c Sat Feb 7 00:05:10 2009 (r188255) @@ -31,10 +31,11 @@ * 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$ */ +#include +__FBSDID("$FreeBSD$"); + #include #include #include Modified: stable/7/sys/security/mac/mac_priv.c ============================================================================== --- stable/7/sys/security/mac/mac_priv.c Sat Feb 7 00:01:10 2009 (r188254) +++ stable/7/sys/security/mac/mac_priv.c Sat Feb 7 00:05:10 2009 (r188255) @@ -25,14 +25,15 @@ * 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$ */ /* * MAC checks for system privileges. */ +#include "sys/cdefs.h" +__FBSDID("$FreeBSD$"); + #include "opt_mac.h" #include From thompsa at FreeBSD.org Fri Feb 6 17:43:05 2009 From: thompsa at FreeBSD.org (Andrew Thompson) Date: Fri Feb 6 17:43:18 2009 Subject: svn commit: r188260 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/usb Message-ID: <200902070143.n171h4VH077147@svn.freebsd.org> Author: thompsa Date: Sat Feb 7 01:43:04 2009 New Revision: 188260 URL: http://svn.freebsd.org/changeset/base/188260 Log: MFC r173522, r176910, r178975 - Add private tx/rx buffer management to support large frame sizes and update the rx code to handle multiple frames in a single usb transfer. AX772 parts (at least) exhibit many input errors when operated with a 2K rx buffer and no errors w/ a 4K rx buffer (it's unclear what the cause of the errors is for 2K so this may just be covering up the real issue). Larger rx buffer sizes show no significant performance improvement for AX772. Bypassing the common buffer management routines also eliminates an extra context switch on every packet which noticeably improves performance (TCP netperf rx goes from 45 Mb/s to 85 MB/s). - Apply le*toh() or htole*() to the variables of which we use the address as the buffer pointer in the call to axe_cmd(). This is needed to make the code work on big-endian machines. - Add support for the Apple USB Ethernet adapter. Work around the "latch in at the first working PHY address hack", that fails for this adapter because it returns 0xffff when reading from lower PHY addresses. Also add more debugging printfs Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/usb/if_axe.c stable/7/sys/dev/usb/if_axereg.h stable/7/sys/dev/usb/usbdevs Modified: stable/7/sys/dev/usb/if_axe.c ============================================================================== --- stable/7/sys/dev/usb/if_axe.c Sat Feb 7 01:15:13 2009 (r188259) +++ stable/7/sys/dev/usb/if_axe.c Sat Feb 7 01:43:04 2009 (r188260) @@ -104,6 +104,21 @@ __FBSDID("$FreeBSD$"); /* "device miibus" required. See GENERIC if you get errors here. */ #include "miibus_if.h" +/* + * AXE_178_MAX_FRAME_BURST + * max frame burst size for Ax88178 and Ax88772 + * 0 2048 bytes + * 1 4096 bytes + * 2 8192 bytes + * 3 16384 bytes + * use the largest your system can handle without usb stalling. + * + * NB: 88772 parts appear to generate lots of input errors with + * a 2K rx buffer and 8K is only slightly faster than 4K on an + * EHCI port on a T42 so change at your own risk. + */ +#define AXE_178_MAX_FRAME_BURST 1 + #include /* @@ -112,6 +127,7 @@ __FBSDID("$FreeBSD$"); const struct axe_type axe_devs[] = { { { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UF200}, 0 }, { { USB_VENDOR_ACERCM, USB_PRODUCT_ACERCM_EP1427X2}, 0 }, + { { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_ETHERNET}, AX772 }, { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172}, 0 }, { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772}, AX772 }, { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178}, AX178 }, @@ -151,7 +167,6 @@ static void axe_rxeof(usbd_xfer_handle, static void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); static void axe_tick(void *); static void axe_tick_task(void *); -static void axe_rxstart(struct ifnet *); static void axe_start(struct ifnet *); static int axe_ioctl(struct ifnet *, u_long, caddr_t); static void axe_init(void *); @@ -259,10 +274,10 @@ axe_miibus_readreg(device_t dev, int phy return(-1); } - if (val) + if (val && val != 0xffff) sc->axe_phyaddrs[0] = phy; - return (val); + return (le16toh(val)); } static int @@ -277,6 +292,7 @@ axe_miibus_writereg(device_t dev, int ph AXE_SLEEPLOCKASSERT(sc); AXE_LOCK(sc); axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); + val = htole32(val); err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, (void *)&val); axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); AXE_UNLOCK(sc); @@ -367,6 +383,7 @@ axe_setmulti(struct axe_softc *sc) AXE_LOCK(sc); axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, (void *)&rxmode); + rxmode = le16toh(rxmode); if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { rxmode |= AXE_RXCMD_ALLMULTI; @@ -403,6 +420,7 @@ axe_ax88178_init(struct axe_softc *sc) axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL); /* XXX magic */ axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom); + eeprom = le16toh(eeprom); axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL); /* if EEPROM is invalid we have to use to GPIO0 */ @@ -548,7 +566,6 @@ axe_attach(device_t self) } sc->axe_boundary = 64; -#if 0 if (sc->axe_flags & (AX178|AX772)) { if (sc->axe_udev->speed == USB_SPEED_HIGH) { sc->axe_bufsz = AXE_178_MAX_BUFSZ; @@ -556,10 +573,7 @@ axe_attach(device_t self) } else sc->axe_bufsz = AXE_178_MIN_BUFSZ; } else - sc->axe_bufsz = AXE_172_BUFSZ -#else - sc->axe_bufsz = AXE_172_BUFSZ; -#endif + sc->axe_bufsz = AXE_172_BUFSZ; { /* XXX debug */ device_printf(sc->axe_dev, "%s, bufsz %d, boundary %d\n", sc->axe_flags & AX178 ? "AX88178" : @@ -643,9 +657,6 @@ device_printf(sc->axe_dev, "%s, bufsz %d ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; IFQ_SET_READY(&ifp->if_snd); - sc->axe_qdat.ifp = ifp; - sc->axe_qdat.if_rxstart = axe_rxstart; - if (mii_phy_probe(self, &sc->axe_miibus, axe_ifmedia_upd, axe_ifmedia_sts)) { device_printf(sc->axe_dev, "MII without any PHY!\n"); @@ -704,33 +715,97 @@ axe_detach(device_t dev) return(0); } +static int +axe_rx_list_init(struct axe_softc *sc) +{ + struct axe_cdata *cd; + struct axe_chain *c; + int i; + + cd = &sc->axe_cdata; + for (i = 0; i < AXE_RX_LIST_CNT; i++) { + c = &cd->axe_rx_chain[i]; + c->axe_sc = sc; + c->axe_idx = i; + c->axe_mbuf = NULL; + if (c->axe_xfer == NULL) { + c->axe_xfer = usbd_alloc_xfer(sc->axe_udev); + if (c->axe_xfer == NULL) + return (ENOBUFS); + c->axe_buf = usbd_alloc_buffer(c->axe_xfer, + sc->axe_bufsz); + if (c->axe_buf == NULL) { + usbd_free_xfer(c->axe_xfer); + return (ENOBUFS); + } + } + } + + return (0); +} + static void -axe_rxstart(struct ifnet *ifp) +axe_rx_list_free(struct axe_softc *sc) { - struct axe_softc *sc; - struct ue_chain *c; + int i; - sc = ifp->if_softc; - AXE_LOCK(sc); - c = &sc->axe_cdata.ue_rx_chain[sc->axe_cdata.ue_rx_prod]; + for (i = 0; i < AXE_RX_LIST_CNT; i++) { + if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL) { + m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf); + sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL; + } + if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) { + usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer); + sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL; + } + } +} - c->ue_mbuf = usb_ether_newbuf(); - if (c->ue_mbuf == NULL) { - device_printf(sc->axe_dev, "no memory for rx list " - "-- packet dropped!\n"); - ifp->if_ierrors++; - AXE_UNLOCK(sc); - return; +static int +axe_tx_list_init(struct axe_softc *sc) +{ + struct axe_cdata *cd; + struct axe_chain *c; + int i; + + cd = &sc->axe_cdata; + for (i = 0; i < AXE_TX_LIST_CNT; i++) { + c = &cd->axe_tx_chain[i]; + c->axe_sc = sc; + c->axe_idx = i; + c->axe_mbuf = NULL; + if (c->axe_xfer == NULL) { + c->axe_xfer = usbd_alloc_xfer(sc->axe_udev); + if (c->axe_xfer == NULL) + return (ENOBUFS); + c->axe_buf = usbd_alloc_buffer(c->axe_xfer, + sc->axe_bufsz); + if (c->axe_buf == NULL) { + usbd_free_xfer(c->axe_xfer); + return (ENOBUFS); + } + } } - /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->axe_ep[AXE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, axe_rxeof); - usbd_transfer(c->ue_xfer); - AXE_UNLOCK(sc); + return (0); +} - return; +static void +axe_tx_list_free(struct axe_softc *sc) +{ + int i; + + /* Free TX resources. */ + for (i = 0; i < AXE_TX_LIST_CNT; i++) { + if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL) { + m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf); + sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL; + } + if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) { + usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer); + sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL; + } + } } /* @@ -741,14 +816,15 @@ static void axe_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) { struct axe_softc *sc; - struct ue_chain *c; + struct axe_chain *c = (struct axe_chain *) priv; struct mbuf *m; + u_char *buf; struct ifnet *ifp; - struct axe_sframe_hdr hdr; - int total_len = 0, pktlen; + struct axe_sframe_hdr *hdr; + int total_len = 0; + int pktlen = 0; - c = priv; - sc = c->ue_sc; + sc = c->axe_sc; AXE_LOCK(sc); ifp = sc->axe_ifp; @@ -772,49 +848,61 @@ axe_rxeof(usbd_xfer_handle xfer, usbd_pr usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); - m = c->ue_mbuf; - /* XXX don't handle multiple packets in one transfer */ - if (sc->axe_flags & (AX178|AX772)) { - if (total_len < sizeof(hdr)) { - ifp->if_ierrors++; - goto done; - } - m_copydata(m, 0, sizeof(hdr), (caddr_t) &hdr); - total_len -= sizeof(hdr); + buf = c->axe_buf; - if ((hdr.len ^ hdr.ilen) != 0xffff) { - ifp->if_ierrors++; - goto done; + do { + if (sc->axe_flags & (AX178|AX772)) { + if (total_len < sizeof(struct axe_sframe_hdr)) { + ifp->if_ierrors++; + goto done; + } + if ((pktlen % 2) != 0) + pktlen++; + buf += pktlen; + + hdr = (struct axe_sframe_hdr *) buf; + total_len -= sizeof(struct axe_sframe_hdr); + if ((hdr->len ^ hdr->ilen) != 0xffff) { + ifp->if_ierrors++; + goto done; + } + pktlen = le16toh(hdr->len); + if (pktlen > total_len) { + ifp->if_ierrors++; + goto done; + } + + buf += sizeof(struct axe_sframe_hdr); + total_len -= pktlen + (pktlen % 2); + } else { + pktlen = total_len; + total_len = 0; } - pktlen = le16toh(hdr.len); - if (pktlen > total_len) { + + if (pktlen < sizeof(struct ether_header)) { ifp->if_ierrors++; goto done; } - m_adj(m, sizeof(hdr)); - } else { - if (total_len < sizeof(struct ether_header)) { + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) { ifp->if_ierrors++; goto done; } - pktlen = total_len; - } - - ifp->if_ipackets++; - m->m_pkthdr.rcvif = (void *)&sc->axe_qdat; - m->m_pkthdr.len = m->m_len = pktlen; - - /* Put the packet on the special USB input queue. */ - usb_ether_input(m); - AXE_UNLOCK(sc); - - return; + m->m_data += ETHER_ALIGN; + memcpy(mtod(m, void *), buf, pktlen); + m->m_pkthdr.len = m->m_len = pktlen; + m->m_pkthdr.rcvif = ifp; + + ifp->if_input(ifp, m); + ifp->if_ipackets++; + } while (total_len > 0); + /* fall thru... */ done: /* Setup new transfer. */ - usbd_setup_xfer(c->ue_xfer, sc->axe_ep[AXE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK, + usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX], + c, c->axe_buf, sc->axe_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, axe_rxeof); - usbd_transfer(c->ue_xfer); + usbd_transfer(xfer); AXE_UNLOCK(sc); return; @@ -829,12 +917,12 @@ static void axe_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) { struct axe_softc *sc; - struct ue_chain *c; + struct axe_chain *c; struct ifnet *ifp; usbd_status err; c = priv; - sc = c->ue_sc; + sc = c->axe_sc; AXE_LOCK(sc); ifp = sc->axe_ifp; @@ -853,12 +941,11 @@ axe_txeof(usbd_xfer_handle xfer, usbd_pr ifp->if_timer = 0; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err); + usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &err); - if (c->ue_mbuf != NULL) { - c->ue_mbuf->m_pkthdr.rcvif = ifp; - usb_tx_done(c->ue_mbuf); - c->ue_mbuf = NULL; + if (c->axe_mbuf != NULL) { + m_freem(c->axe_mbuf); + c->axe_mbuf = NULL; } if (err) @@ -868,6 +955,9 @@ axe_txeof(usbd_xfer_handle xfer, usbd_pr AXE_UNLOCK(sc); + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + axe_start(ifp); + return; } @@ -927,12 +1017,12 @@ axe_tick_task(void *xsc) static int axe_encap(struct axe_softc *sc, struct mbuf *m, int idx) { - struct ue_chain *c; + struct axe_chain *c; usbd_status err; struct axe_sframe_hdr hdr; int length; - c = &sc->axe_cdata.ue_tx_chain[idx]; + c = &sc->axe_cdata.axe_tx_chain[idx]; /* * Copy the mbuf data into a contiguous buffer, leaving two @@ -942,29 +1032,29 @@ axe_encap(struct axe_softc *sc, struct m hdr.len = htole16(m->m_pkthdr.len); hdr.ilen = ~hdr.len; - memcpy(c->ue_buf, &hdr, sizeof(hdr)); + memcpy(c->axe_buf, &hdr, sizeof(hdr)); length = sizeof(hdr); - m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf + sizeof(hdr)); + m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf + length); length += m->m_pkthdr.len; if ((length % sc->axe_boundary) == 0) { hdr.len = 0; hdr.ilen = 0xffff; - memcpy(c->ue_buf + length, &hdr, sizeof(hdr)); + memcpy(c->axe_buf + length, &hdr, sizeof(hdr)); length += sizeof(hdr); } } else { - m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf); + m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf); length = m->m_pkthdr.len; } - c->ue_mbuf = m; + c->axe_mbuf = m; - usbd_setup_xfer(c->ue_xfer, sc->axe_ep[AXE_ENDPT_TX], - c, c->ue_buf, length, USBD_FORCE_SHORT_XFER, 10000, axe_txeof); + usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX], + c, c->axe_buf, length, USBD_FORCE_SHORT_XFER, 10000, axe_txeof); /* Transmit */ - err = usbd_transfer(c->ue_xfer); + err = usbd_transfer(c->axe_xfer); if (err != USBD_IN_PROGRESS) { /* XXX probably don't want to sleep here */ AXE_SLEEPLOCK(sc); @@ -973,7 +1063,7 @@ axe_encap(struct axe_softc *sc, struct m return(EIO); } - sc->axe_cdata.ue_tx_cnt++; + sc->axe_cdata.axe_tx_cnt++; return(0); } @@ -1032,7 +1122,7 @@ axe_init(void *xsc) { struct axe_softc *sc = xsc; struct ifnet *ifp = sc->axe_ifp; - struct ue_chain *c; + struct axe_chain *c; usbd_status err; int i; int rxmode; @@ -1057,8 +1147,7 @@ axe_init(void *xsc) /* Enable RX logic. */ /* Init TX ring. */ - if (usb_ether_tx_list_init(sc, &sc->axe_cdata, - sc->axe_udev) == ENOBUFS) { + if (axe_tx_list_init(sc) == ENOBUFS) { device_printf(sc->axe_dev, "tx list init failed\n"); AXE_UNLOCK(sc); AXE_SLEEPUNLOCK(sc); @@ -1066,8 +1155,7 @@ axe_init(void *xsc) } /* Init RX ring. */ - if (usb_ether_rx_list_init(sc, &sc->axe_cdata, - sc->axe_udev) == ENOBUFS) { + if (axe_rx_list_init(sc) == ENOBUFS) { device_printf(sc->axe_dev, "rx list init failed\n"); AXE_UNLOCK(sc); AXE_SLEEPUNLOCK(sc); @@ -1088,7 +1176,7 @@ axe_init(void *xsc) rxmode = AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE; if (sc->axe_flags & (AX178|AX772)) { if (sc->axe_bufsz == AXE_178_MAX_BUFSZ) - rxmode |= AXE_178_RXCMD_MFB_16384; + rxmode |= AXE_178_RXCMD_MFB; } else rxmode |= AXE_172_RXCMD_UNICAST; @@ -1126,12 +1214,13 @@ axe_init(void *xsc) } /* Start up the receive pipe. */ - for (i = 0; i < UE_RX_LIST_CNT; i++) { - c = &sc->axe_cdata.ue_rx_chain[i]; - usbd_setup_xfer(c->ue_xfer, sc->axe_ep[AXE_ENDPT_RX], - c, mtod(c->ue_mbuf, char *), UE_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof); - usbd_transfer(c->ue_xfer); + for (i = 0; i < AXE_RX_LIST_CNT; i++) { + c = &sc->axe_cdata.axe_rx_chain[i]; + usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX], + c, c->axe_buf, sc->axe_bufsz, + USBD_SHORT_XFER_OK | USBD_NO_COPY, + USBD_NO_TIMEOUT, axe_rxeof); + usbd_transfer(c->axe_xfer); } ifp->if_drv_flags |= IFF_DRV_RUNNING; @@ -1164,6 +1253,7 @@ axe_ioctl(struct ifnet *ifp, u_long comm AXE_LOCK(sc); axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, (void *)&rxmode); + rxmode = le16toh(rxmode); rxmode |= AXE_RXCMD_PROMISC; axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); @@ -1177,6 +1267,7 @@ axe_ioctl(struct ifnet *ifp, u_long comm AXE_LOCK(sc); axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, (void *)&rxmode); + rxmode = le16toh(rxmode); rxmode &= ~AXE_RXCMD_PROMISC; axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); @@ -1222,7 +1313,7 @@ static void axe_watchdog(struct ifnet *ifp) { struct axe_softc *sc; - struct ue_chain *c; + struct axe_chain *c; usbd_status stat; sc = ifp->if_softc; @@ -1231,9 +1322,9 @@ axe_watchdog(struct ifnet *ifp) ifp->if_oerrors++; device_printf(sc->axe_dev, "watchdog timeout\n"); - c = &sc->axe_cdata.ue_tx_chain[0]; - usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat); - axe_txeof(c->ue_xfer, c, stat); + c = &sc->axe_cdata.axe_tx_chain[0]; + usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat); + axe_txeof(c->axe_xfer, c, stat); AXE_UNLOCK(sc); @@ -1307,9 +1398,9 @@ axe_stop(struct axe_softc *sc) axe_reset(sc); /* Free RX resources. */ - usb_ether_rx_list_free(&sc->axe_cdata); + axe_rx_list_free(sc); /* Free TX resources. */ - usb_ether_tx_list_free(&sc->axe_cdata); + axe_tx_list_free(sc); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); sc->axe_link = 0; Modified: stable/7/sys/dev/usb/if_axereg.h ============================================================================== --- stable/7/sys/dev/usb/if_axereg.h Sat Feb 7 01:15:13 2009 (r188259) +++ stable/7/sys/dev/usb/if_axereg.h Sat Feb 7 01:43:04 2009 (r188260) @@ -129,11 +129,10 @@ #define AXE_RXCMD_MULTICAST 0x0010 #define AXE_178_RXCMD_AP 0x0020 #define AXE_RXCMD_ENABLE 0x0080 -#define AXE_178_RXCMD_MFB 0x0300 /* Max Frame Burst */ -#define AXE_178_RXCMD_MFB_2048 0x0000 -#define AXE_178_RXCMD_MFB_4096 0x0100 -#define AXE_178_RXCMD_MFB_8192 0x0200 -#define AXE_178_RXCMD_MFB_16384 0x0300 +#define AXE_178_RXCMD_MFB_2048 0x0000 /* 2K max frame burst */ +#define AXE_178_RXCMD_MFB_4096 0x0100 /* 4K max frame burst */ +#define AXE_178_RXCMD_MFB_8192 0x0200 /* 8K max frame burst */ +#define AXE_178_RXCMD_MFB_16384 0x0300 /* 16K max frame burst*/ #define AXE_NOPHY 0xE0 #define AXE_INTPHY 0x10 @@ -141,14 +140,45 @@ #define AXE_TIMEOUT 1000 #define AXE_172_BUFSZ 1536 #define AXE_178_MIN_BUFSZ 2048 -#define AXE_178_MAX_BUFSZ 16384 #define AXE_MIN_FRAMELEN 60 #define AXE_RX_FRAMES 1 #define AXE_TX_FRAMES 1 +#if AXE_178_MAX_FRAME_BURST == 0 +#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_2048 +#define AXE_178_MAX_BUFSZ 2048 +#elif AXE_178_MAX_FRAME_BURST == 1 +#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_4096 +#define AXE_178_MAX_BUFSZ 4096 +#elif AXE_178_MAX_FRAME_BURST == 2 +#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_8192 +#define AXE_178_MAX_BUFSZ 8192 +#else +#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_16384 +#define AXE_178_MAX_BUFSZ 16384 +#endif + #define AXE_RX_LIST_CNT 1 #define AXE_TX_LIST_CNT 1 +struct axe_chain { + struct axe_softc *axe_sc; + usbd_xfer_handle axe_xfer; + char *axe_buf; + struct mbuf *axe_mbuf; + int axe_accum; + int axe_idx; +}; + +struct axe_cdata { + struct axe_chain axe_tx_chain[AXE_TX_LIST_CNT]; + struct axe_chain axe_rx_chain[AXE_RX_LIST_CNT]; + int axe_tx_prod; + int axe_tx_cons; + int axe_tx_cnt; + int axe_rx_prod; +}; + #define AXE_CTL_READ 0x01 #define AXE_CTL_WRITE 0x02 @@ -198,7 +228,7 @@ struct axe_softc { int axe_ed[AXE_ENDPT_MAX]; usbd_pipe_handle axe_ep[AXE_ENDPT_MAX]; int axe_if_flags; - struct ue_cdata axe_cdata; + struct axe_cdata axe_cdata; struct callout_handle axe_stat_ch; struct mtx axe_mtx; struct sx axe_sleeplock; @@ -207,7 +237,6 @@ struct axe_softc { unsigned char axe_ipgs[3]; unsigned char axe_phyaddrs[2]; struct timeval axe_rx_notice; - struct usb_qdat axe_qdat; struct usb_task axe_tick_task; int axe_bufsz; int axe_boundary; Modified: stable/7/sys/dev/usb/usbdevs ============================================================================== --- stable/7/sys/dev/usb/usbdevs Sat Feb 7 01:15:13 2009 (r188259) +++ stable/7/sys/dev/usb/usbdevs Sat Feb 7 01:43:04 2009 (r188260) @@ -856,6 +856,7 @@ product APPLE IPODVIDEO 0x1209 iPod Vid product APPLE IPODNANO 0x120a iPod Nano product APPLE IPHONE 0x1290 iPhone product APPLE IPHONE_3G 0x1292 iPhone 3G +product APPLE ETHERNET 0x1402 Ethernet A1277 /* Arkmicro Technologies */ product ARKMICRO ARK3116 0x0232 ARK3116 Serial From bz at FreeBSD.org Sat Feb 7 02:17:31 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 02:17:44 2009 Subject: svn commit: r188275 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netinet Message-ID: <200902071017.n17AHUB9087636@svn.freebsd.org> Author: bz Date: Sat Feb 7 10:17:29 2009 New Revision: 188275 URL: http://svn.freebsd.org/changeset/base/188275 Log: MFC: r183571: Implement IPv4 source address selection for unbound sockets. This also changes the semantics of selecting the IP for processes within a jail as it now uses the same logic as outside the jail (with additional checks) but no longer is on a mutually exclusive code path. r186086: With the special check for FreeBSD before 8 a destination route via a loopback interface is treated as a valid and reachable thing for IPv4 source address selection, even though nothing of that network is ever directly reachable, but it is more like a blackhole route. With this the source address will be selected and IPsec can grab the packets before we would discard them at a later point, encapsulate them and send them out from a different tunnel endpoint IP. This is needed to not change the expected behaviour on a stable branch. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netinet/in_pcb.c Modified: stable/7/sys/netinet/in_pcb.c ============================================================================== --- stable/7/sys/netinet/in_pcb.c Sat Feb 7 09:57:14 2009 (r188274) +++ stable/7/sys/netinet/in_pcb.c Sat Feb 7 10:17:29 2009 (r188275) @@ -545,6 +545,209 @@ in_pcbconnect(struct inpcb *inp, struct } /* + * Do proper source address selection on an unbound socket in case + * of connect. Take jails into account as well. + */ +static int +in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr, + struct ucred *cred) +{ + struct in_ifaddr *ia; + struct ifaddr *ifa; + struct sockaddr *sa; + struct sockaddr_in *sin; + struct route sro; + int error; + + KASSERT(laddr != NULL, ("%s: null laddr", __func__)); + + error = 0; + ia = NULL; + bzero(&sro, sizeof(sro)); + + sin = (struct sockaddr_in *)&sro.ro_dst; + sin->sin_family = AF_INET; + sin->sin_len = sizeof(struct sockaddr_in); + sin->sin_addr.s_addr = faddr->s_addr; + + /* + * If route is known our src addr is taken from the i/f, + * else punt. + * + * Find out route to destination. + */ + if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0) + in_rtalloc_ign(&sro, RTF_CLONING, inp->inp_inc.inc_fibnum); + + /* + * If we found a route, use the address corresponding to + * the outgoing interface. + * + * Otherwise assume faddr is reachable on a directly connected + * network and try to find a corresponding interface to take + * the source address from. + */ + if (sro.ro_rt == NULL || sro.ro_rt->rt_ifp == NULL) { + struct ifnet *ifp; + + ia = ifatoia(ifa_ifwithdstaddr((struct sockaddr *)sin)); + if (ia == NULL) + ia = ifatoia(ifa_ifwithnet((struct sockaddr *)sin)); + if (ia == NULL) { + error = ENETUNREACH; + goto done; + } + + if (cred == NULL || !jailed(cred)) { + laddr->s_addr = ia->ia_addr.sin_addr.s_addr; + goto done; + } + + ifp = ia->ia_ifp; + ia = NULL; + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + + sa = ifa->ifa_addr; + if (sa->sa_family != AF_INET) + continue; + sin = (struct sockaddr_in *)sa; + if (htonl(prison_getip(cred)) == sin->sin_addr.s_addr) { + ia = (struct in_ifaddr *)ifa; + break; + } + } + if (ia != NULL) { + laddr->s_addr = ia->ia_addr.sin_addr.s_addr; + goto done; + } + + /* 3. As a last resort return the 'default' jail address. */ + laddr->s_addr = htonl(prison_getip(cred)); + goto done; + } + + /* + * If the outgoing interface on the route found is not + * a loopback interface, use the address from that interface. + * In case of jails do those three steps: + * 1. check if the interface address belongs to the jail. If so use it. + * 2. check if we have any address on the outgoing interface + * belonging to this jail. If so use it. + * 3. as a last resort return the 'default' jail address. + */ + if ((sro.ro_rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) { + + /* If not jailed, use the default returned. */ + if (cred == NULL || !jailed(cred)) { + ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; + laddr->s_addr = ia->ia_addr.sin_addr.s_addr; + goto done; + } + + /* Jailed. */ + /* 1. Check if the iface address belongs to the jail. */ + sin = (struct sockaddr_in *)sro.ro_rt->rt_ifa->ifa_addr; + if (htonl(prison_getip(cred)) == sin->sin_addr.s_addr) { + ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; + laddr->s_addr = ia->ia_addr.sin_addr.s_addr; + goto done; + } + + /* + * 2. Check if we have any address on the outgoing interface + * belonging to this jail. + */ + TAILQ_FOREACH(ifa, &sro.ro_rt->rt_ifp->if_addrhead, ifa_link) { + + sa = ifa->ifa_addr; + if (sa->sa_family != AF_INET) + continue; + sin = (struct sockaddr_in *)sa; + if (htonl(prison_getip(cred)) == sin->sin_addr.s_addr) { + ia = (struct in_ifaddr *)ifa; + break; + } + } + if (ia != NULL) { + laddr->s_addr = ia->ia_addr.sin_addr.s_addr; + goto done; + } + + /* 3. As a last resort return the 'default' jail address. */ + laddr->s_addr = htonl(prison_getip(cred)); + goto done; + } + + /* + * The outgoing interface is marked with 'loopback net', so a route + * to ourselves is here. + * Try to find the interface of the destination address and then + * take the address from there. That interface is not necessarily + * a loopback interface. + * In case of jails, check that it is an address of the jail + * and if we cannot find, fall back to the 'default' jail address. + */ + if ((sro.ro_rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) { + struct sockaddr_in sain; + + bzero(&sain, sizeof(struct sockaddr_in)); + sain.sin_family = AF_INET; + sain.sin_len = sizeof(struct sockaddr_in); + sain.sin_addr.s_addr = faddr->s_addr; + + ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sain))); + if (ia == NULL) + ia = ifatoia(ifa_ifwithnet(sintosa(&sain))); + + if (cred == NULL || !jailed(cred)) { +#if __FreeBSD_version < 800000 + if (ia == NULL) + ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; +#endif + if (ia == NULL) { + error = ENETUNREACH; + goto done; + } + laddr->s_addr = ia->ia_addr.sin_addr.s_addr; + goto done; + } + + /* Jailed. */ + if (ia != NULL) { + struct ifnet *ifp; + + ifp = ia->ia_ifp; + ia = NULL; + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + + sa = ifa->ifa_addr; + if (sa->sa_family != AF_INET) + continue; + sin = (struct sockaddr_in *)sa; + if (htonl(prison_getip(cred)) == + sin->sin_addr.s_addr) { + ia = (struct in_ifaddr *)ifa; + break; + } + } + if (ia != NULL) { + laddr->s_addr = ia->ia_addr.sin_addr.s_addr; + goto done; + } + } + + /* 3. As a last resort return the 'default' jail address. */ + laddr->s_addr = htonl(prison_getip(cred)); + goto done; + } + +done: + if (sro.ro_rt != NULL) + RTFREE(sro.ro_rt); + return (error); +} + +/* * Set up for a connect from a socket to the specified address. * On entry, *laddrp and *lportp should contain the current local * address and port for the PCB; these are updated to the values @@ -566,8 +769,6 @@ in_pcbconnect_setup(struct inpcb *inp, s { struct sockaddr_in *sin = (struct sockaddr_in *)nam; struct in_ifaddr *ia; - struct sockaddr_in sa; - struct ucred *socred; struct inpcb *oinp; struct in_addr laddr, faddr; u_short lport, fport; @@ -592,17 +793,7 @@ in_pcbconnect_setup(struct inpcb *inp, s lport = *lportp; faddr = sin->sin_addr; fport = sin->sin_port; - socred = inp->inp_socket->so_cred; - if (laddr.s_addr == INADDR_ANY && jailed(socred)) { - bzero(&sa, sizeof(sa)); - sa.sin_addr.s_addr = htonl(prison_getip(socred)); - sa.sin_len = sizeof(sa); - sa.sin_family = AF_INET; - error = in_pcbbind_setup(inp, (struct sockaddr *)&sa, - &laddr.s_addr, &lport, cred); - if (error) - return (error); - } + if (!TAILQ_EMPTY(&in_ifaddrhead)) { /* * If the destination address is INADDR_ANY, @@ -620,35 +811,10 @@ in_pcbconnect_setup(struct inpcb *inp, s &in_ifaddrhead)->ia_broadaddr)->sin_addr; } if (laddr.s_addr == INADDR_ANY) { - ia = NULL; - /* - * If route is known our src addr is taken from the i/f, - * else punt. - * - * Find out route to destination - */ - if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0) - ia = ip_rtaddr(faddr, inp->inp_inc.inc_fibnum); - /* - * If we found a route, use the address corresponding to - * the outgoing interface. - * - * Otherwise assume faddr is reachable on a directly connected - * network and try to find a corresponding interface to take - * the source address from. - */ - if (ia == NULL) { - bzero(&sa, sizeof(sa)); - sa.sin_addr = faddr; - sa.sin_len = sizeof(sa); - sa.sin_family = AF_INET; + error = in_pcbladdr(inp, &faddr, &laddr, cred); + if (error) + return (error); - ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sa))); - if (ia == NULL) - ia = ifatoia(ifa_ifwithnet(sintosa(&sa))); - if (ia == NULL) - return (ENETUNREACH); - } /* * If the destination address is multicast and an outgoing * interface has been set as a multicast option, use the @@ -667,9 +833,9 @@ in_pcbconnect_setup(struct inpcb *inp, s break; if (ia == NULL) return (EADDRNOTAVAIL); + laddr = ia->ia_addr.sin_addr; } } - laddr = ia->ia_addr.sin_addr; } oinp = in_pcblookup_hash(inp->inp_pcbinfo, faddr, fport, laddr, lport, From bz at FreeBSD.org Sat Feb 7 02:29:08 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 02:29:20 2009 Subject: svn commit: r188276 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902071029.n17AT7SX089156@svn.freebsd.org> Author: bz Date: Sat Feb 7 10:29:07 2009 New Revision: 188276 URL: http://svn.freebsd.org/changeset/base/188276 Log: MFC: r185404 With the permissions of phk@ change the license on kern_jail.c to a 2 clause BSD license. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_jail.c Modified: stable/7/sys/kern/kern_jail.c ============================================================================== --- stable/7/sys/kern/kern_jail.c Sat Feb 7 10:17:29 2009 (r188275) +++ stable/7/sys/kern/kern_jail.c Sat Feb 7 10:29:07 2009 (r188276) @@ -1,10 +1,26 @@ /*- - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- + * Copyright (c) 1999 Poul-Henning Kamp. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include From rwatson at FreeBSD.org Sat Feb 7 03:15:54 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Sat Feb 7 03:16:12 2009 Subject: svn commit: r188278 - stable/7/sbin/dumpfs Message-ID: <200902071115.n17BFr5N090260@svn.freebsd.org> Author: rwatson Date: Sat Feb 7 11:15:53 2009 New Revision: 188278 URL: http://svn.freebsd.org/changeset/base/188278 Log: Merge r187814, r187820 from head to stable/7: Add a new flag to dumpfs(8), -f, which causes dumpfs to list all free fragments in the file system by fragment (block) number. This new mode does the necessary arithmetic to generate absolute fragment numbers rather than than the cg-relative numbers printed in the default mode. If -f is passed once, contiguous fragment ranges are collapsed into an X-Y format as free block lists are currently printed in regular dumpfs output, but if specified twice, all block numbers are printed individually, allowing both compact and more script-friendly representation. This proves quite handy when attempting to recover deleted data, as it allows exclusion of non-deleted data from blocks searched. Discussed with: jeff, Richard Clayton Sponsored by: Google, Inc. Print disk offets as %jd rather than %lld; I fixed one before committing but missed the other, which breaks 64-bit builds. Reported by: bf Reviewed by: mckusick Modified: stable/7/sbin/dumpfs/ (props changed) stable/7/sbin/dumpfs/dumpfs.8 stable/7/sbin/dumpfs/dumpfs.c Modified: stable/7/sbin/dumpfs/dumpfs.8 ============================================================================== --- stable/7/sbin/dumpfs/dumpfs.8 Sat Feb 7 11:12:30 2009 (r188277) +++ stable/7/sbin/dumpfs/dumpfs.8 Sat Feb 7 11:15:53 2009 (r188278) @@ -36,15 +36,18 @@ .Nd dump file system information .Sh SYNOPSIS .Nm +.Op Fl f .Op Fl m .Ar filesys | device .Sh DESCRIPTION The .Nm utility prints out the super block and cylinder group information -for the file system or special device specified, unless +for the file system or special device specified, unless the +.Fl f +or .Fl m -is specified. +flag is specified. The listing is very long and detailed. This command is useful mostly for finding out certain file system @@ -52,6 +55,15 @@ information such as the file system bloc free space percentage. .Pp If +.Fl f +is specified, a sorted list of all free fragments and free fragment ranges, +as represented in cylinder group block free lists, is printed. +If the flag is specified twice, contiguous free fragments are not collapsed +into ranges and instead printed in a simple list. +Fragment numbers may be converted to raw byte offsets by multiplying by the +fragment size, which may be useful when recovering deleted data. +.Pp +If .Fl m is specified, a .Xr newfs 8 Modified: stable/7/sbin/dumpfs/dumpfs.c ============================================================================== --- stable/7/sbin/dumpfs/dumpfs.c Sat Feb 7 11:12:30 2009 (r188277) +++ stable/7/sbin/dumpfs/dumpfs.c Sat Feb 7 11:15:53 2009 (r188278) @@ -1,4 +1,10 @@ /* + * Copyright (c) 2009 Robert N. M. Watson + * All rights reserved. + * + * This software was developed at the University of Cambridge Computer + * Laboratory with support from a grant from Google, Inc. + * * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * @@ -74,8 +80,11 @@ struct uufsd disk; int dumpfs(const char *); int dumpcg(void); +int dumpfreespace(const char *, int); +void dumpfreespacecg(int); int marshal(const char *); void pbits(void *, int); +void pblklist(void *, int, off_t, int); void ufserr(const char *); void usage(void) __dead2; @@ -83,12 +92,15 @@ int main(int argc, char *argv[]) { const char *name; - int ch, domarshal, eval; + int ch, dofreespace, domarshal, eval; - domarshal = eval = 0; + dofreespace = domarshal = eval = 0; - while ((ch = getopt(argc, argv, "m")) != -1) { + while ((ch = getopt(argc, argv, "fm")) != -1) { switch (ch) { + case 'f': + dofreespace++; + break; case 'm': domarshal = 1; break; @@ -102,6 +114,10 @@ main(int argc, char *argv[]) if (argc < 1) usage(); + if (dofreespace && domarshal) + usage(); + if (dofreespace > 2) + usage(); while ((name = *argv++) != NULL) { if (ufs_disk_fillout(&disk, name) == -1) { @@ -109,7 +125,9 @@ main(int argc, char *argv[]) eval |= 1; continue; } - if (domarshal) + if (dofreespace) + eval |= dumpfreespace(name, dofreespace); + else if (domarshal) eval |= marshal(name); else eval |= dumpfs(name); @@ -333,6 +351,30 @@ dumpcg(void) } int +dumpfreespace(const char *name, int fflag) +{ + int i; + + while ((i = cgread(&disk)) != 0) { + if (i == -1) + goto err; + dumpfreespacecg(fflag); + } + return (0); +err: + ufserr(name); + return (1); +} + +void +dumpfreespacecg(int fflag) +{ + + pblklist(cg_blksfree(&acg), afs.fs_fpg, disk.d_lcg * afs.fs_fpg, + fflag); +} + +int marshal(const char *name) { struct fs *fs; @@ -401,6 +443,27 @@ pbits(void *vp, int max) } void +pblklist(void *vp, int max, off_t offset, int fflag) +{ + int i, j; + char *p; + + for (i = 0, p = vp; i < max; i++) { + if (isset(p, i)) { + printf("%jd", (intmax_t)(i + offset)); + if (fflag < 2) { + j = i; + while ((i+1) Author: rwatson Date: Sat Feb 7 11:27:35 2009 New Revision: 188279 URL: http://svn.freebsd.org/changeset/base/188279 Log: Merge r188006 from head to stable/7: Alow dirname(1) to accept multiple arguments in the same way that basename(1) does. (Two different PRs contained identical patches, both cited below) PR: 121520, 86148 Submitted by: Ighighi Submitted by: Leif Neland Modified: stable/7/usr.bin/basename/ (props changed) stable/7/usr.bin/basename/basename.1 stable/7/usr.bin/dirname/ (props changed) stable/7/usr.bin/dirname/dirname.c Modified: stable/7/usr.bin/basename/basename.1 ============================================================================== --- stable/7/usr.bin/basename/basename.1 Sat Feb 7 11:15:53 2009 (r188278) +++ stable/7/usr.bin/basename/basename.1 Sat Feb 7 11:27:35 2009 (r188279) @@ -52,6 +52,7 @@ .Op Ar ... .Nm dirname .Ar string +.Op Ar ... .Sh DESCRIPTION The .Nm Modified: stable/7/usr.bin/dirname/dirname.c ============================================================================== --- stable/7/usr.bin/dirname/dirname.c Sat Feb 7 11:15:53 2009 (r188278) +++ stable/7/usr.bin/dirname/dirname.c Sat Feb 7 11:27:35 2009 (r188279) @@ -66,12 +66,15 @@ main(int argc, char **argv) argc -= optind; argv += optind; - if (argc != 1) + if (argc < 1) usage(); - if ((p = dirname(*argv)) == NULL) - err(1, "%s", *argv); - (void)printf("%s\n", p); + while (argc--) { + if ((p = dirname(*argv)) == NULL) + err(1, "%s", *argv); + argv++; + (void)printf("%s\n", p); + } exit(0); } @@ -79,6 +82,6 @@ void usage(void) { - (void)fprintf(stderr, "usage: dirname string\n"); + (void)fprintf(stderr, "usage: dirname string [...]\n"); exit(1); } From bz at FreeBSD.org Sat Feb 7 05:19:10 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 05:19:29 2009 Subject: svn commit: r188281 - in stable/7: . etc etc/defaults etc/periodic/weekly lib/libc lib/libc/string lib/libc/sys lib/libkvm share/man/man4 sys sys/compat/freebsd32 sys/contrib/pf sys/dev/ath/ath_hal... Message-ID: <200902071319.n17DJ8Wd092736@svn.freebsd.org> Author: bz Date: Sat Feb 7 13:19:08 2009 New Revision: 188281 URL: http://svn.freebsd.org/changeset/base/188281 Log: MFC: r185435: This enhances the current jail implementation to permit multiple addresses per jail. In addtion to IPv4, IPv6 is supported as well. Due to updated checks it is even possible to have jails without an IP address at all, which basically gives one a chroot with restricted process view, no networking,.. SCTP support was updated and supports IPv6 in jails as well. Cpuset support permits jails to be bound to specific processor sets after creation. Jails can have an unrestricted (no duplicate protection, etc.) name in addition to the hostname. The jail name cannot be changed from within a jail and is considered to be used for management purposes or as audit-token in the future. DDB 'show jails' command was added to aid debugging. Proper compat support permits 32bit jail binaries to be used on 64bit systems to manage jails. Also backward compatibility was preserved where possible: for jail v1 syscalls, as well as with user space management utilities. Both jail as well as prison version were updated for the new features. A gap was intentionally left as the intermediate versions had been used by various patches floating around the last years. Bump __FreeBSD_version for the afore mentioned and in kernel changes. r185441: Unbreak the no-networks (no INET/6) build. r185899: Correctly check the number of prison states to not access anything outside the prison_states array. When checking if there is a name configured for the prison, check the first character to not be '\0' instead of checking if the char array is present, which it always is. Note, that this is different for the *jailname in the syscall. Found with: Coverity Prevent(tm) CID: 4156, 4155 r186085: Make sure that the direct jls invocations prints something reasonable close to and in the same format as it had always. r186606: Make sure that unused j->ip[46] are cleared. r186834: Document the special loopback address behaviour of jails. PR: kern/103464 r186841: Put the devfs ruleset next to devfs enable, add a comment about the suggested ruleset[1]. While here use an IP from the 'test-net' prefix for docs. PR: kern/130102 r187059: Add a short section talking about jails and file systems; mention the mountand jail-aware file systems as well as quota. PR: kern/68192 r187092: Sort .Xr. r187365: s,unmount 8,umount 8, it is unmount(2) which I did not mean. r187669: Update the description of the '-h' option wrt to primary addresses per address family and add a reference to the ip-addresses option. r187670: New sentence starts on a new line. Modified: stable/7/UPDATING stable/7/etc/ (props changed) stable/7/etc/defaults/rc.conf stable/7/etc/periodic/weekly/ (props changed) stable/7/lib/libc/ (props changed) stable/7/lib/libc/string/ffsll.c (props changed) stable/7/lib/libc/string/flsll.c (props changed) stable/7/lib/libc/sys/cpuset_getaffinity.2 stable/7/lib/libc/sys/jail.2 stable/7/lib/libkvm/ (props changed) stable/7/lib/libkvm/kvm_proc.c stable/7/share/man/man4/ (props changed) stable/7/share/man/man4/ddb.4 stable/7/share/man/man4/igb.4 (props changed) stable/7/sys/ (props changed) stable/7/sys/compat/freebsd32/freebsd32.h stable/7/sys/compat/freebsd32/freebsd32_misc.c stable/7/sys/compat/freebsd32/syscalls.master stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_cpuset.c stable/7/sys/kern/kern_exit.c stable/7/sys/kern/kern_fork.c stable/7/sys/kern/kern_jail.c stable/7/sys/kern/uipc_socket.c stable/7/sys/net/if.c stable/7/sys/net/rtsock.c stable/7/sys/netinet/in_pcb.c stable/7/sys/netinet/raw_ip.c stable/7/sys/netinet/sctp_pcb.c stable/7/sys/netinet/sctp_usrreq.c stable/7/sys/netinet/tcp_usrreq.c stable/7/sys/netinet/udp_usrreq.c stable/7/sys/netinet6/in6_pcb.c stable/7/sys/netinet6/in6_src.c stable/7/sys/netinet6/raw_ip6.c stable/7/sys/netinet6/udp6_usrreq.c stable/7/sys/security/mac_bsdextended/mac_bsdextended.c stable/7/sys/sys/cpuset.h stable/7/sys/sys/jail.h stable/7/sys/sys/param.h stable/7/usr.bin/cpuset/ (props changed) stable/7/usr.bin/cpuset/cpuset.1 stable/7/usr.bin/cpuset/cpuset.c stable/7/usr.sbin/jail/ (props changed) stable/7/usr.sbin/jail/Makefile stable/7/usr.sbin/jail/jail.8 stable/7/usr.sbin/jail/jail.c stable/7/usr.sbin/jexec/ (props changed) stable/7/usr.sbin/jexec/Makefile stable/7/usr.sbin/jexec/jexec.8 stable/7/usr.sbin/jexec/jexec.c stable/7/usr.sbin/jls/ (props changed) stable/7/usr.sbin/jls/Makefile stable/7/usr.sbin/jls/jls.8 stable/7/usr.sbin/jls/jls.c Modified: stable/7/UPDATING ============================================================================== --- stable/7/UPDATING Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/UPDATING Sat Feb 7 13:19:08 2009 (r188281) @@ -8,6 +8,12 @@ Items affecting the ports and packages s /usr/ports/UPDATING. Please read that file before running portupgrade. +20090207: + Multi-IPv4/v6/no-IP jail support was merged to STABLE. + You need to rebuild jls(8) and to use the new features + jail(8), jexec(8) and cpuset(1) with a new kernel. + __FreeBSD_version was bumped to 701103. + 20090119: NTFS has been removed from GENERIC kernel on amd64 to match GENERIC on i386. Should not cause any issues since mount_ntfs(8) Modified: stable/7/etc/defaults/rc.conf ============================================================================== --- stable/7/etc/defaults/rc.conf Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/etc/defaults/rc.conf Sat Feb 7 13:19:08 2009 (r188281) @@ -620,7 +620,7 @@ jail_sysvipc_allow="NO" # Allow SystemV # #jail_example_rootdir="/usr/jail/default" # Jail's root directory #jail_example_hostname="default.domain.com" # Jail's hostname -#jail_example_ip="192.168.0.10" # Jail's IP number +#jail_example_ip="192.0.2.10" # Jail's IP number #jail_example_interface="" # Interface to create the IP alias on #jail_example_fib="0" # routing table for setfib(1) #jail_example_exec_start="/bin/sh /etc/rc" # command to execute in jail for starting @@ -629,10 +629,11 @@ jail_sysvipc_allow="NO" # Allow SystemV # specified using a trailing number #jail_example_exec_stop="/bin/sh /etc/rc.shutdown" # command to execute in jail for stopping #jail_example_devfs_enable="NO" # mount devfs in the jail +#jail_example_devfs_ruleset="ruleset_name" # devfs ruleset to apply to jail - + # usually you want "devfsrules_jail". #jail_example_fdescfs_enable="NO" # mount fdescfs in the jail #jail_example_procfs_enable="NO" # mount procfs in jail #jail_example_mount_enable="NO" # mount/umount jail's fs -#jail_example_devfs_ruleset="ruleset_name" # devfs ruleset to apply to jail #jail_example_fstab="" # fstab(5) for mount/umount #jail_example_flags="-l -U root" # flags for jail(8) Modified: stable/7/lib/libc/sys/cpuset_getaffinity.2 ============================================================================== --- stable/7/lib/libc/sys/cpuset_getaffinity.2 Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/lib/libc/sys/cpuset_getaffinity.2 Sat Feb 7 13:19:08 2009 (r188281) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 29, 2008 +.Dd November 29, 2008 .Dt CPUSET 2 .Os .Sh NAME @@ -46,7 +46,7 @@ and .Fn cpuset_setaffinity allow the manipulation of sets of CPUs available to processes, threads, -interrupts and other resources. +interrupts, jails and other resources. These functions may manipulate sets of CPUs that contain many processes or per-object anonymous masks that effect only a single object. .Pp Modified: stable/7/lib/libc/sys/jail.2 ============================================================================== --- stable/7/lib/libc/sys/jail.2 Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/lib/libc/sys/jail.2 Sat Feb 7 13:19:08 2009 (r188281) @@ -8,7 +8,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 8, 2003 +.Dd January 6, 2009 .Dt JAIL 2 .Os .Sh NAME @@ -32,15 +32,20 @@ The argument is a pointer to a structure .Bd -literal -offset indent struct jail { u_int32_t version; - char *path; - char *hostname; - u_int32_t ip_number; + char *path; + char *hostname; + char *jailname; + unsigned int ip4s; + unsigned int ip6s; + struct in_addr *ip4; + struct in6_addr *ip6; }; .Ed .Pp .Dq Li version defines the version of the API in use. -It should be set to zero at this time. +.Dv JAIL_API_VERSION +is defined for the current version. .Pp The .Dq Li path @@ -54,8 +59,24 @@ This can be changed from the inside of the prison. .Pp The -.Dq Li ip_number -can be set to the IP number assigned to the prison. +.Dq Li jailname +pointer is an optional name that can be assigned to the jail +for example for managment purposes. +.Pp +The +.Dq Li ip4s +and +.Dq Li ip6s +give the numbers of IPv4 and IPv6 addresses that will be passed +via their respective pointers. +.Pp +The +.Dq Li ip4 +and +.Dq Li ip6 +pointers can be set to an arrays of IPv4 and IPv6 addresses to be assigned to +the prison, or NULL if none. +IPv4 addresses must be in network byte order. .Pp The .Fn jail_attach @@ -97,6 +118,12 @@ or, if present, the per-jail .Pp All IP activity will be forced to happen to/from the IP number specified, which should be an alias on one of the network interfaces. +All connections to/from the loopback address +.Pf ( Li 127.0.0.1 +for IPv4, +.Li ::1 +for IPv6) will be changed to be to/from the primary address +of the jail for the given address family. .Pp It is possible to identify a process as jailed by examining .Dq Li /proc//status : Modified: stable/7/lib/libkvm/kvm_proc.c ============================================================================== --- stable/7/lib/libkvm/kvm_proc.c Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/lib/libkvm/kvm_proc.c Sat Feb 7 13:19:08 2009 (r188281) @@ -54,10 +54,11 @@ __FBSDID("$FreeBSD$"); #include #include #include -#define _WANT_PRISON /* make jail.h give us 'struct prison' */ -#include +#include #include #include +#define _WANT_PRISON /* make jail.h give us 'struct prison' */ +#include #include #include #include Modified: stable/7/share/man/man4/ddb.4 ============================================================================== --- stable/7/share/man/man4/ddb.4 Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/share/man/man4/ddb.4 Sat Feb 7 13:19:08 2009 (r188281) @@ -60,7 +60,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 26, 2007 +.Dd November 29, 2008 .Dt DDB 4 .Os .Sh NAME @@ -539,6 +539,16 @@ If the .Ar addr is given, displays details about the given GEOM object (class, geom, provider or consumer). +.\" +.Pp +.It Ic show Cm jails +Show the list of +.Xr jail 8 +instances. +In addition to what +.Xr jls 8 +shows, also list kernel internal details. +.\" .Pp .It Ic show Cm map Ns Oo Li / Ns Cm f Oc Ar addr Prints the VM map at Modified: stable/7/sys/compat/freebsd32/freebsd32.h ============================================================================== --- stable/7/sys/compat/freebsd32/freebsd32.h Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/sys/compat/freebsd32/freebsd32.h Sat Feb 7 13:19:08 2009 (r188281) @@ -153,6 +153,24 @@ struct stat32 { unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32)); }; +struct jail32_v0 { + u_int32_t version; + uint32_t path; + uint32_t hostname; + u_int32_t ip_number; +}; + +struct jail32 { + uint32_t version; + uint32_t path; + uint32_t hostname; + uint32_t jailname; + uint32_t ip4s; + uint32_t ip6s; + uint32_t ip4; + uint32_t ip6; +}; + struct sigaction32 { u_int32_t sa_u; int sa_flags; Modified: stable/7/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- stable/7/sys/compat/freebsd32/freebsd32_misc.c Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/sys/compat/freebsd32/freebsd32_misc.c Sat Feb 7 13:19:08 2009 (r188281) @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1983,6 +1984,66 @@ done2: } int +freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap) +{ + uint32_t version; + int error; + struct jail j; + + error = copyin(uap->jail, &version, sizeof(uint32_t)); + if (error) + return (error); + switch (version) { + case 0: + { + /* FreeBSD single IPv4 jails. */ + struct jail32_v0 j32_v0; + + bzero(&j, sizeof(struct jail)); + error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0)); + if (error) + return (error); + CP(j32_v0, j, version); + PTRIN_CP(j32_v0, j, path); + PTRIN_CP(j32_v0, j, hostname); + j.ip4s = j32_v0.ip_number; + break; + } + + case 1: + /* + * Version 1 was used by multi-IPv4 jail implementations + * that never made it into the official kernel. + */ + return (EINVAL); + + case 2: /* JAIL_API_VERSION */ + { + /* FreeBSD multi-IPv4/IPv6,noIP jails. */ + struct jail32 j32; + + error = copyin(uap->jail, &j32, sizeof(struct jail32)); + if (error) + return (error); + CP(j32, j, version); + PTRIN_CP(j32, j, path); + PTRIN_CP(j32, j, hostname); + PTRIN_CP(j32, j, jailname); + CP(j32, j, ip4s); + CP(j32, j, ip6s); + PTRIN_CP(j32, j, ip4); + PTRIN_CP(j32, j, ip6); + break; + } + + default: + /* Sci-Fi jails are not supported, sorry. */ + return (EINVAL); + } + return (kern_jail(td, &j)); +} + +int freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap) { struct sigaction32 s32; Modified: stable/7/sys/compat/freebsd32/syscalls.master ============================================================================== --- stable/7/sys/compat/freebsd32/syscalls.master Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/sys/compat/freebsd32/syscalls.master Sat Feb 7 13:19:08 2009 (r188281) @@ -587,7 +587,7 @@ off_t *sbytes, int flags); } 337 AUE_NULL NOPROTO { int kldsym(int fileid, int cmd, \ void *data); } -338 AUE_JAIL NOPROTO { int jail(struct jail *jail); } +338 AUE_JAIL STD { int freebsd32_jail(struct jail32 *jail); } 339 AUE_NULL UNIMPL pioctl 340 AUE_SIGPROCMASK NOPROTO { int sigprocmask(int how, \ const sigset_t *set, sigset_t *oset); } Modified: stable/7/sys/kern/kern_cpuset.c ============================================================================== --- stable/7/sys/kern/kern_cpuset.c Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/sys/kern/kern_cpuset.c Sat Feb 7 13:19:08 2009 (r188281) @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include /* Must come after sys/proc.h */ #include @@ -208,7 +209,7 @@ cpuset_rel_complete(struct cpuset *set) * Find a set based on an id. Returns it with a ref. */ static struct cpuset * -cpuset_lookup(cpusetid_t setid) +cpuset_lookup(cpusetid_t setid, struct thread *td) { struct cpuset *set; @@ -221,6 +222,28 @@ cpuset_lookup(cpusetid_t setid) if (set) cpuset_ref(set); mtx_unlock_spin(&cpuset_lock); + + KASSERT(td != NULL, ("[%s:%d] td is NULL", __func__, __LINE__)); + if (set != NULL && jailed(td->td_ucred)) { + struct cpuset *rset, *jset; + struct prison *pr; + + rset = cpuset_refroot(set); + + pr = td->td_ucred->cr_prison; + mtx_lock(&pr->pr_mtx); + cpuset_ref(pr->pr_cpuset); + jset = pr->pr_cpuset; + mtx_unlock(&pr->pr_mtx); + + if (jset->cs_id != rset->cs_id) { + cpuset_rel(set); + set = NULL; + } + cpuset_rel(jset); + cpuset_rel(rset); + } + return (set); } @@ -414,12 +437,38 @@ cpuset_which(cpuwhich_t which, id_t id, set = cpuset_refbase(curthread->td_cpuset); thread_unlock(curthread); } else - set = cpuset_lookup(id); + set = cpuset_lookup(id, curthread); if (set) { *setp = set; return (0); } return (ESRCH); + case CPU_WHICH_JAIL: + { + /* Find `set' for prison with given id. */ + struct prison *pr; + + sx_slock(&allprison_lock); + pr = prison_find(id); + sx_sunlock(&allprison_lock); + if (pr == NULL) + return (ESRCH); + if (jailed(curthread->td_ucred)) { + if (curthread->td_ucred->cr_prison == pr) { + cpuset_ref(pr->pr_cpuset); + set = pr->pr_cpuset; + } + } else { + cpuset_ref(pr->pr_cpuset); + set = pr->pr_cpuset; + } + mtx_unlock(&pr->pr_mtx); + if (set) { + *setp = set; + return (0); + } + return (ESRCH); + } default: return (EINVAL); } @@ -668,6 +717,59 @@ cpuset_thread0(void) } /* + * Create a cpuset, which would be cpuset_create() but + * mark the new 'set' as root. + * + * We are not going to reparent the td to it. Use cpuset_reparentproc() for that. + * + * In case of no error, returns the set in *setp locked with a reference. + */ +int +cpuset_create_root(struct thread *td, struct cpuset **setp) +{ + struct cpuset *root; + struct cpuset *set; + int error; + + KASSERT(td != NULL, ("[%s:%d] invalid td", __func__, __LINE__)); + KASSERT(setp != NULL, ("[%s:%d] invalid setp", __func__, __LINE__)); + + thread_lock(td); + root = cpuset_refroot(td->td_cpuset); + thread_unlock(td); + + error = cpuset_create(setp, td->td_cpuset, &root->cs_mask); + cpuset_rel(root); + if (error) + return (error); + + KASSERT(*setp != NULL, ("[%s:%d] cpuset_create returned invalid data", + __func__, __LINE__)); + + /* Mark the set as root. */ + set = *setp; + set->cs_flags |= CPU_SET_ROOT; + + return (0); +} + +int +cpuset_setproc_update_set(struct proc *p, struct cpuset *set) +{ + int error; + + KASSERT(p != NULL, ("[%s:%d] invalid proc", __func__, __LINE__)); + KASSERT(set != NULL, ("[%s:%d] invalid set", __func__, __LINE__)); + + cpuset_ref(set); + error = cpuset_setproc(p->p_pid, set, NULL); + if (error) + return (error); + cpuset_rel(set); + return (0); +} + +/* * This is called once the final set of system cpus is known. Modifies * the root set and all children and mark the root readonly. */ @@ -732,7 +834,7 @@ cpuset_setid(struct thread *td, struct c */ if (uap->which != CPU_WHICH_PID) return (EINVAL); - set = cpuset_lookup(uap->setid); + set = cpuset_lookup(uap->setid, td); if (set == NULL) return (ESRCH); error = cpuset_setproc(uap->id, set, NULL); @@ -771,6 +873,7 @@ cpuset_getid(struct thread *td, struct c PROC_UNLOCK(p); break; case CPU_WHICH_CPUSET: + case CPU_WHICH_JAIL: break; } switch (uap->level) { @@ -831,6 +934,7 @@ cpuset_getaffinity(struct thread *td, st thread_unlock(ttd); break; case CPU_WHICH_CPUSET: + case CPU_WHICH_JAIL: break; } if (uap->level == CPU_LEVEL_ROOT) @@ -857,6 +961,7 @@ cpuset_getaffinity(struct thread *td, st PROC_SUNLOCK(p); break; case CPU_WHICH_CPUSET: + case CPU_WHICH_JAIL: CPU_COPY(&set->cs_mask, mask); break; } @@ -934,6 +1039,7 @@ cpuset_setaffinity(struct thread *td, st PROC_UNLOCK(p); break; case CPU_WHICH_CPUSET: + case CPU_WHICH_JAIL: break; } if (uap->level == CPU_LEVEL_ROOT) @@ -953,7 +1059,8 @@ cpuset_setaffinity(struct thread *td, st error = cpuset_setproc(uap->id, NULL, mask); break; case CPU_WHICH_CPUSET: - error = cpuset_which(CPU_WHICH_CPUSET, uap->id, &p, + case CPU_WHICH_JAIL: + error = cpuset_which(uap->which, uap->id, &p, &ttd, &set); if (error == 0) { error = cpuset_modify(set, mask); Modified: stable/7/sys/kern/kern_exit.c ============================================================================== --- stable/7/sys/kern/kern_exit.c Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/sys/kern/kern_exit.c Sat Feb 7 13:19:08 2009 (r188281) @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -461,6 +462,10 @@ retry: p->p_xstat = rv; p->p_xthread = td; + /* In case we are jailed tell the prison that we are gone. */ + if (jailed(p->p_ucred)) + prison_proc_free(p->p_ucred->cr_prison); + #ifdef KDTRACE_HOOKS /* * Tell the DTrace fasttrap provider about the exit if it Modified: stable/7/sys/kern/kern_fork.c ============================================================================== --- stable/7/sys/kern/kern_fork.c Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/sys/kern/kern_fork.c Sat Feb 7 13:19:08 2009 (r188281) @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -442,6 +443,11 @@ again: __rangeof(struct proc, p_startzero, p_endzero)); p2->p_ucred = crhold(td->td_ucred); + + /* In case we are jailed tell the prison that we exist. */ + if (jailed(p2->p_ucred)) + prison_proc_hold(p2->p_ucred->cr_prison); + PROC_UNLOCK(p2); /* Modified: stable/7/sys/kern/kern_jail.c ============================================================================== --- stable/7/sys/kern/kern_jail.c Sat Feb 7 11:40:47 2009 (r188280) +++ stable/7/sys/kern/kern_jail.c Sat Feb 7 13:19:08 2009 (r188281) @@ -1,5 +1,7 @@ /*- - * Copyright (c) 1999 Poul-Henning Kamp. All rights reserved. + * Copyright (c) 1999 Poul-Henning Kamp. + * Copyright (c) 2008 Bjoern A. Zeeb. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,6 +28,9 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_ddb.h" +#include "opt_inet.h" +#include "opt_inet6.h" #include "opt_mac.h" #include @@ -51,6 +56,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef DDB +#include +#ifdef INET6 +#include +#endif /* INET6 */ +#endif /* DDB */ #include @@ -67,7 +78,7 @@ SYSCTL_INT(_security_jail, OID_AUTO, set int jail_socket_unixiproute_only = 1; SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, &jail_socket_unixiproute_only, 0, - "Processes in jail are limited to creating UNIX/IPv4/route sockets only"); + "Processes in jail are limited to creating UNIX/IP/route sockets only"); int jail_sysvipc_allowed = 0; SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, @@ -94,6 +105,11 @@ SYSCTL_INT(_security_jail, OID_AUTO, mou &jail_mount_allowed, 0, "Processes in jail can mount/unmount jail-friendly file systems"); +int jail_max_af_ips = 255; +SYSCTL_INT(_security_jail, OID_AUTO, jail_max_af_ips, CTLFLAG_RW, + &jail_max_af_ips, 0, + "Number of IP addresses a jail may have at most per address family"); + /* allprison, lastprid, and prisoncount are protected by allprison_lock. */ struct prisonlist allprison; struct sx allprison_lock; @@ -119,6 +135,12 @@ struct prison_service { static void init_prison(void *); static void prison_complete(void *context, int pending); static int sysctl_jail_list(SYSCTL_HANDLER_ARGS); +#ifdef INET +static int _prison_check_ip4(struct prison *, struct in_addr *); +#endif +#ifdef INET6 +static int _prison_check_ip6(struct prison *, struct in6_addr *); +#endif static void init_prison(void *data __unused) @@ -130,6 +152,278 @@ init_prison(void *data __unused) SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL); +#ifdef INET +static int +qcmp_v4(const void *ip1, const void *ip2) +{ + in_addr_t iaa, iab; + + /* + * We need to compare in HBO here to get the list sorted as expected + * by the result of the code. Sorting NBO addresses gives you + * interesting results. If you do not understand, do not try. + */ + iaa = ntohl(((const struct in_addr *)ip1)->s_addr); + iab = ntohl(((const struct in_addr *)ip2)->s_addr); + + /* + * Do not simply return the difference of the two numbers, the int is + * not wide enough. + */ + if (iaa > iab) + return (1); + else if (iaa < iab) + return (-1); + else + return (0); +} +#endif + +#ifdef INET6 +static int +qcmp_v6(const void *ip1, const void *ip2) +{ + const struct in6_addr *ia6a, *ia6b; + int i, rc; + + ia6a = (const struct in6_addr *)ip1; + ia6b = (const struct in6_addr *)ip2; + + rc = 0; + for (i=0; rc == 0 && i < sizeof(struct in6_addr); i++) { + if (ia6a->s6_addr[i] > ia6b->s6_addr[i]) + rc = 1; + else if (ia6a->s6_addr[i] < ia6b->s6_addr[i]) + rc = -1; + } + return (rc); +} +#endif + +#if defined(INET) || defined(INET6) +static int +prison_check_conflicting_ips(struct prison *p) +{ + struct prison *pr; + int i; + + sx_assert(&allprison_lock, SX_LOCKED); + + if (p->pr_ip4s == 0 && p->pr_ip6s == 0) + return (0); + + LIST_FOREACH(pr, &allprison, pr_list) { + /* + * Skip 'dying' prisons to avoid problems when + * restarting multi-IP jails. + */ + if (pr->pr_state == PRISON_STATE_DYING) + continue; + + /* + * We permit conflicting IPs if there is no + * more than 1 IP on eeach jail. + * In case there is one duplicate on a jail with + * more than one IP stop checking and return error. + */ +#ifdef INET + if ((p->pr_ip4s >= 1 && pr->pr_ip4s > 1) || + (p->pr_ip4s > 1 && pr->pr_ip4s >= 1)) { + for (i = 0; i < p->pr_ip4s; i++) { + if (_prison_check_ip4(pr, &p->pr_ip4[i])) + return (EINVAL); + } + } +#endif +#ifdef INET6 + if ((p->pr_ip6s >= 1 && pr->pr_ip6s > 1) || + (p->pr_ip6s > 1 && pr->pr_ip6s >= 1)) { + for (i = 0; i < p->pr_ip6s; i++) { + if (_prison_check_ip6(pr, &p->pr_ip6[i])) + return (EINVAL); + } + } +#endif + } + + return (0); +} + +static int +jail_copyin_ips(struct jail *j) +{ +#ifdef INET + struct in_addr *ip4; +#endif +#ifdef INET6 + struct in6_addr *ip6; +#endif + int error, i; + + /* + * Copy in addresses, check for duplicate addresses and do some + * simple 0 and broadcast checks. If users give other bogus addresses + * it is their problem. + * + * IP addresses are all sorted but ip[0] to preserve the primary IP + * address as given from userland. This special IP is used for + * unbound outgoing connections as well for "loopback" traffic. + */ +#ifdef INET + ip4 = NULL; +#endif +#ifdef INET6 + ip6 = NULL; +#endif +#ifdef INET + if (j->ip4s > 0) { + ip4 = (struct in_addr *)malloc(j->ip4s * sizeof(struct in_addr), + M_PRISON, M_WAITOK | M_ZERO); + error = copyin(j->ip4, ip4, j->ip4s * sizeof(struct in_addr)); + if (error) + goto e_free_ip; + /* Sort all but the first IPv4 address. */ + if (j->ip4s > 1) + qsort((ip4 + 1), j->ip4s - 1, + sizeof(struct in_addr), qcmp_v4); + + /* + * We do not have to care about byte order for these checks + * so we will do them in NBO. + */ + for (i=0; iip4s; i++) { + if (ip4[i].s_addr == htonl(INADDR_ANY) || + ip4[i].s_addr == htonl(INADDR_BROADCAST)) { + error = EINVAL; + goto e_free_ip; + } + if ((i+1) < j->ip4s && + (ip4[0].s_addr == ip4[i+1].s_addr || + ip4[i].s_addr == ip4[i+1].s_addr)) { + error = EINVAL; + goto e_free_ip; + } + } + + j->ip4 = ip4; + } else + j->ip4 = NULL; +#endif +#ifdef INET6 + if (j->ip6s > 0) { + ip6 = (struct in6_addr *)malloc(j->ip6s * sizeof(struct in6_addr), + M_PRISON, M_WAITOK | M_ZERO); + error = copyin(j->ip6, ip6, j->ip6s * sizeof(struct in6_addr)); + if (error) + goto e_free_ip; + /* Sort all but the first IPv6 address. */ + if (j->ip6s > 1) + qsort((ip6 + 1), j->ip6s - 1, + sizeof(struct in6_addr), qcmp_v6); + for (i=0; iip6s; i++) { + if (IN6_IS_ADDR_UNSPECIFIED(&ip6[i])) { + error = EINVAL; + goto e_free_ip; + } + if ((i+1) < j->ip6s && + (IN6_ARE_ADDR_EQUAL(&ip6[0], &ip6[i+1]) || + IN6_ARE_ADDR_EQUAL(&ip6[i], &ip6[i+1]))) { + error = EINVAL; + goto e_free_ip; + } + } + + j->ip6 = ip6; + } else + j->ip6 = NULL; +#endif + return (0); + +e_free_ip: +#ifdef INET6 + free(ip6, M_PRISON); +#endif +#ifdef INET + free(ip4, M_PRISON); +#endif + return (error); +} +#endif /* INET || INET6 */ + +static int +jail_handle_ips(struct jail *j) +{ +#if defined(INET) || defined(INET6) + int error; +#endif + + /* + * Finish conversion for older versions, copyin and setup IPs. + */ + switch (j->version) { + case 0: + { +#ifdef INET + /* FreeBSD single IPv4 jails. */ + struct in_addr *ip4; + + if (j->ip4s == INADDR_ANY || j->ip4s == INADDR_BROADCAST) + return (EINVAL); + ip4 = (struct in_addr *)malloc(sizeof(struct in_addr), + M_PRISON, M_WAITOK | M_ZERO); + + /* + * Jail version 0 still used HBO for the IPv4 address. + */ + ip4->s_addr = htonl(j->ip4s); + j->ip4s = 1; + j->ip4 = ip4; + break; +#else + return (EINVAL); +#endif + } + + case 1: + /* + * Version 1 was used by multi-IPv4 jail implementations + * that never made it into the official kernel. + * We should never hit this here; jail() should catch it. + */ + return (EINVAL); + + case 2: /* JAIL_API_VERSION */ + /* FreeBSD multi-IPv4/IPv6,noIP jails. */ +#if defined(INET) || defined(INET6) +#ifdef INET + if (j->ip4s > jail_max_af_ips) + return (EINVAL); +#else + if (j->ip4s != 0) + return (EINVAL); +#endif +#ifdef INET6 + if (j->ip6s > jail_max_af_ips) + return (EINVAL); +#else + if (j->ip6s != 0) + return (EINVAL); +#endif + error = jail_copyin_ips(j); + if (error) + return (error); +#endif + break; + + default: + /* Sci-Fi jails are not supported, sorry. */ + return (EINVAL); + } + + return (0); +} + + /* * struct jail_args { * struct jail *jail; @@ -138,23 +432,73 @@ SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORD int jail(struct thread *td, struct jail_args *uap) { + uint32_t version; + int error; + struct jail j; + + error = copyin(uap->jail, &version, sizeof(uint32_t)); + if (error) + return (error); + + switch (version) { + case 0: + /* FreeBSD single IPv4 jails. */ + { + struct jail_v0 j0; + + bzero(&j, sizeof(struct jail)); + error = copyin(uap->jail, &j0, sizeof(struct jail_v0)); + if (error) + return (error); + j.version = j0.version; + j.path = j0.path; + j.hostname = j0.hostname; + j.ip4s = j0.ip_number; + break; + } + + case 1: + /* + * Version 1 was used by multi-IPv4 jail implementations + * that never made it into the official kernel. + */ + return (EINVAL); + + case 2: /* JAIL_API_VERSION */ + /* FreeBSD multi-IPv4/IPv6,noIP jails. */ + error = copyin(uap->jail, &j, sizeof(struct jail)); + if (error) + return (error); + break; + + default: + /* Sci-Fi jails are not supported, sorry. */ + return (EINVAL); + } + return (kern_jail(td, &j)); +} + +int +kern_jail(struct thread *td, struct jail *j) +{ struct nameidata nd; struct prison *pr, *tpr; struct prison_service *psrv; - struct jail j; struct jail_attach_args jaa; int vfslocked, error, tryprid; - error = copyin(uap->jail, &j, sizeof(j)); + KASSERT(j != NULL, ("%s: j is NULL", __func__)); + + /* Handle addresses - convert old structs, copyin, check IPs. */ + error = jail_handle_ips(j); if (error) return (error); - if (j.version != 0) - return (EINVAL); - MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); + /* Allocate struct prison and fill it with life. */ + pr = malloc(sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF); pr->pr_ref = 1; - error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0); + error = copyinstr(j->path, &pr->pr_path, sizeof(pr->pr_path), NULL); if (error) goto e_killmtx; NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF, UIO_SYSSPACE, @@ -167,10 +511,25 @@ jail(struct thread *td, struct jail_args VOP_UNLOCK(nd.ni_vp, 0, td); NDFREE(&nd, NDF_ONLY_PNBUF); VFS_UNLOCK_GIANT(vfslocked); - error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); + error = copyinstr(j->hostname, &pr->pr_host, sizeof(pr->pr_host), NULL); if (error) goto e_dropvnref; - pr->pr_ip = j.ip_number; + if (j->jailname != NULL) { + error = copyinstr(j->jailname, &pr->pr_name, + sizeof(pr->pr_name), NULL); + if (error) + goto e_dropvnref; + } + if (j->ip4s > 0) { + pr->pr_ip4 = j->ip4; + pr->pr_ip4s = j->ip4s; + } +#ifdef INET6 + if (j->ip6s > 0) { + pr->pr_ip6 = j->ip6; + pr->pr_ip6s = j->ip6s; + } +#endif pr->pr_linux = NULL; pr->pr_securelevel = securelevel; if (prison_service_slots == 0) @@ -180,8 +539,29 @@ jail(struct thread *td, struct jail_args M_PRISON, M_ZERO | M_WAITOK); } - /* Determine next pr_id and add prison to allprison list. */ + /* + * Pre-set prison state to ALIVE upon cration. This is needed so we + * can later attach the process to it, etc (avoiding another extra + * state for ther process of creation, complicating things). *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From bz at FreeBSD.org Sat Feb 7 05:27:02 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 05:27:34 2009 Subject: svn commit: r188282 - stable/7/sys/compat/freebsd32 Message-ID: <200902071327.n17DR1jJ092921@svn.freebsd.org> Author: bz Date: Sat Feb 7 13:27:01 2009 New Revision: 188282 URL: http://svn.freebsd.org/changeset/base/188282 Log: Regen after jail support was merged in r188281 (--record-only MFC of r185436). Modified: stable/7/sys/compat/freebsd32/freebsd32_proto.h stable/7/sys/compat/freebsd32/freebsd32_syscall.h stable/7/sys/compat/freebsd32/freebsd32_syscalls.c stable/7/sys/compat/freebsd32/freebsd32_sysent.c Modified: stable/7/sys/compat/freebsd32/freebsd32_proto.h ============================================================================== --- stable/7/sys/compat/freebsd32/freebsd32_proto.h Sat Feb 7 13:19:08 2009 (r188281) +++ stable/7/sys/compat/freebsd32/freebsd32_proto.h Sat Feb 7 13:27:01 2009 (r188282) @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/7/sys/compat/freebsd32/syscalls.master 187559 2009-01-21 18:52:33Z jhb + * created from FreeBSD: stable/7/sys/compat/freebsd32/syscalls.master 188281 2009-02-07 13:19:08Z bz */ #ifndef _FREEBSD32_SYSPROTO_H_ @@ -274,6 +274,9 @@ struct freebsd32_olio_listio_args { char nent_l_[PADL_(int)]; int nent; char nent_r_[PADR_(int)]; char sig_l_[PADL_(struct osigevent32 *)]; struct osigevent32 * sig; char sig_r_[PADR_(struct osigevent32 *)]; }; +struct freebsd32_jail_args { + char jail_l_[PADL_(struct jail32 *)]; struct jail32 * jail; char jail_r_[PADR_(struct jail32 *)]; +}; struct freebsd32_sigtimedwait_args { char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)]; char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)]; @@ -469,6 +472,7 @@ int freebsd32_aio_error(struct thread *, int freebsd32_oaio_read(struct thread *, struct freebsd32_oaio_read_args *); int freebsd32_oaio_write(struct thread *, struct freebsd32_oaio_write_args *); int freebsd32_olio_listio(struct thread *, struct freebsd32_olio_listio_args *); +int freebsd32_jail(struct thread *, struct freebsd32_jail_args *); int freebsd32_sigtimedwait(struct thread *, struct freebsd32_sigtimedwait_args *); int freebsd32_sigwaitinfo(struct thread *, struct freebsd32_sigwaitinfo_args *); int freebsd32_aio_waitcomplete(struct thread *, struct freebsd32_aio_waitcomplete_args *); @@ -691,6 +695,7 @@ int freebsd6_freebsd32_ftruncate(struct #define FREEBSD32_SYS_AUE_freebsd32_oaio_read AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_oaio_write AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_olio_listio AUE_NULL +#define FREEBSD32_SYS_AUE_freebsd32_jail AUE_JAIL #define FREEBSD32_SYS_AUE_freebsd32_sigtimedwait AUE_SIGWAIT #define FREEBSD32_SYS_AUE_freebsd32_sigwaitinfo AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_aio_waitcomplete AUE_NULL Modified: stable/7/sys/compat/freebsd32/freebsd32_syscall.h ============================================================================== --- stable/7/sys/compat/freebsd32/freebsd32_syscall.h Sat Feb 7 13:19:08 2009 (r188281) +++ stable/7/sys/compat/freebsd32/freebsd32_syscall.h Sat Feb 7 13:27:01 2009 (r188282) @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/7/sys/compat/freebsd32/syscalls.master 187559 2009-01-21 18:52:33Z jhb + * created from FreeBSD: stable/7/sys/compat/freebsd32/syscalls.master 188281 2009-02-07 13:19:08Z bz */ #define FREEBSD32_SYS_syscall 0 @@ -264,7 +264,7 @@ #define FREEBSD32_SYS_utrace 335 #define FREEBSD32_SYS_freebsd4_freebsd32_sendfile 336 #define FREEBSD32_SYS_kldsym 337 -#define FREEBSD32_SYS_jail 338 +#define FREEBSD32_SYS_freebsd32_jail 338 #define FREEBSD32_SYS_sigprocmask 340 #define FREEBSD32_SYS_sigsuspend 341 #define FREEBSD32_SYS_freebsd4_freebsd32_sigaction 342 Modified: stable/7/sys/compat/freebsd32/freebsd32_syscalls.c ============================================================================== --- stable/7/sys/compat/freebsd32/freebsd32_syscalls.c Sat Feb 7 13:19:08 2009 (r188281) +++ stable/7/sys/compat/freebsd32/freebsd32_syscalls.c Sat Feb 7 13:27:01 2009 (r188282) @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/7/sys/compat/freebsd32/syscalls.master 187559 2009-01-21 18:52:33Z jhb + * created from FreeBSD: stable/7/sys/compat/freebsd32/syscalls.master 188281 2009-02-07 13:19:08Z bz */ const char *freebsd32_syscallnames[] = { @@ -345,7 +345,7 @@ const char *freebsd32_syscallnames[] = { "utrace", /* 335 = utrace */ "compat4.freebsd32_sendfile", /* 336 = old freebsd32_sendfile */ "kldsym", /* 337 = kldsym */ - "jail", /* 338 = jail */ + "freebsd32_jail", /* 338 = freebsd32_jail */ "#339", /* 339 = pioctl */ "sigprocmask", /* 340 = sigprocmask */ "sigsuspend", /* 341 = sigsuspend */ Modified: stable/7/sys/compat/freebsd32/freebsd32_sysent.c ============================================================================== --- stable/7/sys/compat/freebsd32/freebsd32_sysent.c Sat Feb 7 13:19:08 2009 (r188281) +++ stable/7/sys/compat/freebsd32/freebsd32_sysent.c Sat Feb 7 13:27:01 2009 (r188282) @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: stable/7/sys/compat/freebsd32/syscalls.master 187559 2009-01-21 18:52:33Z jhb + * created from FreeBSD: stable/7/sys/compat/freebsd32/syscalls.master 188281 2009-02-07 13:19:08Z bz */ #include "opt_compat.h" @@ -376,7 +376,7 @@ struct sysent freebsd32_sysent[] = { { AS(utrace_args), (sy_call_t *)utrace, AUE_NULL, NULL, 0, 0 }, /* 335 = utrace */ { compat4(AS(freebsd4_freebsd32_sendfile_args),freebsd32_sendfile), AUE_SENDFILE, NULL, 0, 0 }, /* 336 = old freebsd32_sendfile */ { AS(kldsym_args), (sy_call_t *)kldsym, AUE_NULL, NULL, 0, 0 }, /* 337 = kldsym */ - { AS(jail_args), (sy_call_t *)jail, AUE_JAIL, NULL, 0, 0 }, /* 338 = jail */ + { AS(freebsd32_jail_args), (sy_call_t *)freebsd32_jail, AUE_JAIL, NULL, 0, 0 }, /* 338 = freebsd32_jail */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 339 = pioctl */ { AS(sigprocmask_args), (sy_call_t *)sigprocmask, AUE_SIGPROCMASK, NULL, 0, 0 }, /* 340 = sigprocmask */ { AS(sigsuspend_args), (sy_call_t *)sigsuspend, AUE_SIGSUSPEND, NULL, 0, 0 }, /* 341 = sigsuspend */ From bz at FreeBSD.org Sat Feb 7 05:32:50 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 05:33:02 2009 Subject: svn commit: r188283 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb Message-ID: <200902071332.n17DWnSd093080@svn.freebsd.org> Author: bz Date: Sat Feb 7 13:32:49 2009 New Revision: 188283 URL: http://svn.freebsd.org/changeset/base/188283 Log: Record that r85436 was merged with r188282. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) From bz at FreeBSD.org Sat Feb 7 05:46:56 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 05:47:07 2009 Subject: svn commit: r188284 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb net Message-ID: <200902071346.n17DkpI6093463@svn.freebsd.org> Author: bz Date: Sat Feb 7 13:46:51 2009 New Revision: 188284 URL: http://svn.freebsd.org/changeset/base/188284 Log: MFC: r186956 Take the cred from curthread rather than curproc as curproc would need locking but the credential from curthread (usually) never changes. r186980 Restrict arp, ndp and theoretically the FIB listing (if not read with libkvm) to the addresses of a prison, when inside a jail. While touching RTM_GET in route_output(), consistently use curthread credentials rather than the creds from the socket there. r186986 Rather than using the cred from curthread, take it from the thread referenced in the sysctl req argument. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/net/rtsock.c Modified: stable/7/sys/net/rtsock.c ============================================================================== --- stable/7/sys/net/rtsock.c Sat Feb 7 13:32:49 2009 (r188283) +++ stable/7/sys/net/rtsock.c Sat Feb 7 13:46:51 2009 (r188284) @@ -585,6 +585,12 @@ route_output(struct mbuf *m, struct sock case RTM_GET: report: RT_LOCK_ASSERT(rt); + if (jailed(curthread->td_ucred) && + ((rt->rt_flags & RTF_HOST) == 0 || + !prison_if(curthread->td_ucred, rt_key(rt)))) { + RT_UNLOCK(rt); + senderr(ESRCH); + } info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_NETMASK] = rt_mask(rt); @@ -594,10 +600,10 @@ route_output(struct mbuf *m, struct sock if (ifp) { info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr; - if (jailed(so->so_cred)) { + if (jailed(curthread->td_ucred)) { error = rtm_get_jailed( &info, ifp, rt, &saun, - so->so_cred); + curthread->td_ucred); if (error != 0) { RT_UNLOCK(rt); senderr(ESRCH); @@ -1224,6 +1230,10 @@ sysctl_dumpentry(struct radix_node *rn, if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) return 0; + if (jailed(w->w_req->td->td_ucred) && + ((rt->rt_flags & RTF_HOST) == 0 || + !prison_if(w->w_req->td->td_ucred, rt_key(rt)))) + return (0); bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; @@ -1283,8 +1293,8 @@ sysctl_iflist(int af, struct walkarg *w) while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) { if (af && af != ifa->ifa_addr->sa_family) continue; - if (jailed(curthread->td_ucred) && - !prison_if(curthread->td_ucred, ifa->ifa_addr)) + if (jailed(w->w_req->td->td_ucred) && + !prison_if(w->w_req->td->td_ucred, ifa->ifa_addr)) continue; info.rti_info[RTAX_IFA] = ifa->ifa_addr; info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; @@ -1311,7 +1321,7 @@ done: return (error); } -int +static int sysctl_ifmalist(int af, struct walkarg *w) { struct ifnet *ifp; @@ -1331,8 +1341,8 @@ sysctl_ifmalist(int af, struct walkarg * TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (af && af != ifma->ifma_addr->sa_family) continue; - if (jailed(curproc->p_ucred) && - !prison_if(curproc->p_ucred, ifma->ifma_addr)) + if (jailed(w->w_req->td->td_ucred) && + !prison_if(w->w_req->td->td_ucred, ifma->ifma_addr)) continue; info.rti_info[RTAX_IFA] = ifma->ifma_addr; info.rti_info[RTAX_GATEWAY] = @@ -1397,7 +1407,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) } else /* dump only one table */ i = lim = af; for (error = 0; error == 0 && i <= lim; i++) - if ((rnh = rt_tables[curthread->td_proc->p_fibnum][i]) != NULL) { + if ((rnh = rt_tables[req->td->td_proc->p_fibnum][i]) != NULL) { RADIX_NODE_HEAD_LOCK(rnh); error = rnh->rnh_walktree(rnh, sysctl_dumpentry, &w); From bz at FreeBSD.org Sat Feb 7 05:51:17 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 05:51:23 2009 Subject: svn commit: r188285 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netinet netinet6 Message-ID: <200902071351.n17DpGV1093596@svn.freebsd.org> Author: bz Date: Sat Feb 7 13:51:15 2009 New Revision: 188285 URL: http://svn.freebsd.org/changeset/base/188285 Log: MFC: r186948 Make SIOCGIFADDR and related, as well as SIOCGIFADDR_IN6 and related jail-aware. Up to now we returned the first address of the interface for SIOCGIFADDR w/o an ifr_addr in the query. This caused problems for programs querying for an address but running inside a jail, as the address returned usually did not belong to the jail. Like for v6, if there was an ifr_addr given on v4, you could probe for more addresses on the interfaces that you were not allowed to see from inside a jail. Return an error (EADDRNOTAVAIL) in that case now unless the address is on the given interface and valid for the jail. PR: kern/114325 Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netinet/in.c stable/7/sys/netinet6/in6.c Modified: stable/7/sys/netinet/in.c ============================================================================== --- stable/7/sys/netinet/in.c Sat Feb 7 13:46:51 2009 (r188284) +++ stable/7/sys/netinet/in.c Sat Feb 7 13:51:15 2009 (r188285) @@ -41,7 +41,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include @@ -252,13 +254,19 @@ in_control(struct socket *so, u_long cmd LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) if (iap->ia_ifp == ifp && iap->ia_addr.sin_addr.s_addr == dst.s_addr) { - ia = iap; + if (td == NULL || prison_check_ip4( + td->td_ucred, &dst)) + ia = iap; break; } if (ia == NULL) TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { iap = ifatoia(ifa); if (iap->ia_addr.sin_family == AF_INET) { + if (td != NULL && + !prison_check_ip4(td->td_ucred, + &iap->ia_addr.sin_addr)) + continue; ia = iap; break; } Modified: stable/7/sys/netinet6/in6.c ============================================================================== --- stable/7/sys/netinet6/in6.c Sat Feb 7 13:46:51 2009 (r188284) +++ stable/7/sys/netinet6/in6.c Sat Feb 7 13:51:15 2009 (r188285) @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -468,6 +469,9 @@ in6_control(struct socket *so, u_long cm error = in6_setscope(&sa6->sin6_addr, ifp, NULL); if (error != 0) return (error); + if (td != NULL && !prison_check_ip6(td->td_ucred, + &sa6->sin6_addr)) + return (EADDRNOTAVAIL); ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr); } else ia = NULL; From bz at FreeBSD.org Sat Feb 7 05:55:14 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 05:55:31 2009 Subject: svn commit: r188286 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern net netinet netinet6 sys Message-ID: <200902071355.n17DtCQD093755@svn.freebsd.org> Author: bz Date: Sat Feb 7 13:55:12 2009 New Revision: 188286 URL: http://svn.freebsd.org/changeset/base/188286 Log: MFC: r187684 For consistency with prison_{local,remote,check}_ipN rename prison_getipN to prison_get_ipN. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_jail.c stable/7/sys/net/rtsock.c stable/7/sys/netinet/in_pcb.c stable/7/sys/netinet/raw_ip.c stable/7/sys/netinet6/raw_ip6.c stable/7/sys/sys/jail.h Modified: stable/7/sys/kern/kern_jail.c ============================================================================== --- stable/7/sys/kern/kern_jail.c Sat Feb 7 13:51:15 2009 (r188285) +++ stable/7/sys/kern/kern_jail.c Sat Feb 7 13:55:12 2009 (r188286) @@ -846,7 +846,7 @@ prison_proc_free(struct prison *pr) * Returns 0 on success, 1 on error. Address returned in NBO. */ int -prison_getip4(struct ucred *cred, struct in_addr *ia) +prison_get_ip4(struct ucred *cred, struct in_addr *ia) { KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); @@ -992,7 +992,7 @@ prison_check_ip4(struct ucred *cred, str * Returns 0 on success, 1 on error. */ int -prison_getip6(struct ucred *cred, struct in6_addr *ia6) +prison_get_ip6(struct ucred *cred, struct in6_addr *ia6) { KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); Modified: stable/7/sys/net/rtsock.c ============================================================================== --- stable/7/sys/net/rtsock.c Sat Feb 7 13:51:15 2009 (r188285) +++ stable/7/sys/net/rtsock.c Sat Feb 7 13:55:12 2009 (r188286) @@ -368,7 +368,7 @@ rtm_get_jailed(struct rt_addrinfo *info, * 3. As a last resort return the 'default' * jail address. */ - if (prison_getip4(cred, &ia) != 0) + if (prison_get_ip4(cred, &ia) != 0) return (ESRCH); } bzero(&saun->sin, sizeof(struct sockaddr_in)); @@ -420,7 +420,7 @@ rtm_get_jailed(struct rt_addrinfo *info, * 3. As a last resort return the 'default' * jail address. */ - if (prison_getip6(cred, &ia6) != 0) + if (prison_get_ip6(cred, &ia6) != 0) return (ESRCH); } bzero(&saun->sin6, sizeof(struct sockaddr_in6)); Modified: stable/7/sys/netinet/in_pcb.c ============================================================================== --- stable/7/sys/netinet/in_pcb.c Sat Feb 7 13:51:15 2009 (r188285) +++ stable/7/sys/netinet/in_pcb.c Sat Feb 7 13:55:12 2009 (r188286) @@ -617,7 +617,7 @@ in_pcbladdr(struct inpcb *inp, struct in } /* 3. As a last resort return the 'default' jail address. */ - if (prison_getip4(cred, laddr) != 0) + if (prison_get_ip4(cred, laddr) != 0) error = EADDRNOTAVAIL; goto done; } @@ -670,7 +670,7 @@ in_pcbladdr(struct inpcb *inp, struct in } /* 3. As a last resort return the 'default' jail address. */ - if (prison_getip4(cred, laddr) != 0) + if (prison_get_ip4(cred, laddr) != 0) error = EADDRNOTAVAIL; goto done; } @@ -733,7 +733,7 @@ in_pcbladdr(struct inpcb *inp, struct in } /* 3. As a last resort return the 'default' jail address. */ - if (prison_getip4(cred, laddr) != 0) + if (prison_get_ip4(cred, laddr) != 0) error = EADDRNOTAVAIL; goto done; } @@ -801,7 +801,7 @@ in_pcbconnect_setup(struct inpcb *inp, s */ if (faddr.s_addr == INADDR_ANY) { if (cred != NULL && jailed(cred)) { - if (prison_getip4(cred, &jailia) != 0) + if (prison_get_ip4(cred, &jailia) != 0) return (EADDRNOTAVAIL); faddr.s_addr = jailia.s_addr; } else { Modified: stable/7/sys/netinet/raw_ip.c ============================================================================== --- stable/7/sys/netinet/raw_ip.c Sat Feb 7 13:51:15 2009 (r188285) +++ stable/7/sys/netinet/raw_ip.c Sat Feb 7 13:55:12 2009 (r188286) @@ -359,7 +359,7 @@ rip_output(struct mbuf *m, struct socket ip->ip_p = inp->inp_ip_p; ip->ip_len = m->m_pkthdr.len; if (jailed(inp->inp_cred)) { - if (prison_getip4(inp->inp_cred, &ip->ip_src)) { + if (prison_get_ip4(inp->inp_cred, &ip->ip_src) != 0) { INP_RUNLOCK(inp); m_freem(m); return (EPERM); Modified: stable/7/sys/netinet6/raw_ip6.c ============================================================================== --- stable/7/sys/netinet6/raw_ip6.c Sat Feb 7 13:51:15 2009 (r188285) +++ stable/7/sys/netinet6/raw_ip6.c Sat Feb 7 13:55:12 2009 (r188286) @@ -398,7 +398,7 @@ rip6_output(m, va_alist) goto bad; } if (jailed(in6p->inp_cred)) - if (prison_getip6(in6p->inp_cred, in6a) != 0) { + if (prison_get_ip6(in6p->inp_cred, in6a) != 0) { error = EPERM; goto bad; } Modified: stable/7/sys/sys/jail.h ============================================================================== --- stable/7/sys/sys/jail.h Sat Feb 7 13:51:15 2009 (r188285) +++ stable/7/sys/sys/jail.h Sat Feb 7 13:55:12 2009 (r188286) @@ -178,12 +178,12 @@ void prison_hold(struct prison *pr); void prison_hold_locked(struct prison *pr); void prison_proc_hold(struct prison *); void prison_proc_free(struct prison *); -int prison_getip4(struct ucred *cred, struct in_addr *ia); +int prison_get_ip4(struct ucred *cred, struct in_addr *ia); int prison_local_ip4(struct ucred *cred, struct in_addr *ia); int prison_remote_ip4(struct ucred *cred, struct in_addr *ia); int prison_check_ip4(struct ucred *cred, struct in_addr *ia); #ifdef INET6 -int prison_getip6(struct ucred *, struct in6_addr *); +int prison_get_ip6(struct ucred *, struct in6_addr *); int prison_local_ip6(struct ucred *, struct in6_addr *, int); int prison_remote_ip6(struct ucred *, struct in6_addr *); int prison_check_ip6(struct ucred *, struct in6_addr *); From bz at FreeBSD.org Sat Feb 7 06:04:36 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 06:04:43 2009 Subject: svn commit: r188287 - in stable/7: etc etc/defaults etc/periodic/weekly etc/rc.d share/man/man5 Message-ID: <200902071404.n17E4ZHo094018@svn.freebsd.org> Author: bz Date: Sat Feb 7 14:04:35 2009 New Revision: 188287 URL: http://svn.freebsd.org/changeset/base/188287 Log: MFC: r187708 Update jail startup script for multi-IPv4/v6/no-IP jails. Note: this is only really necessary because of the ifconfig logic to add/remove the jail IPs upon start/stop. Consensus among simon and I is that the logic should really be factored out from the startup script and put into a proper management solution. - We now support starting of no-IP jails. - Implement jail__ip options to support both address familes with regard to ifconfig logic. - Implement _multi support suffix to the jail__ip option to configure additional addresses to avoid overlong, unreadbale jail__ip lines with lots of addresses. Modified: stable/7/etc/ (props changed) stable/7/etc/defaults/rc.conf stable/7/etc/periodic/weekly/ (props changed) stable/7/etc/rc.d/jail stable/7/share/man/man5/ (props changed) stable/7/share/man/man5/rc.conf.5 Modified: stable/7/etc/defaults/rc.conf ============================================================================== --- stable/7/etc/defaults/rc.conf Sat Feb 7 13:55:12 2009 (r188286) +++ stable/7/etc/defaults/rc.conf Sat Feb 7 14:04:35 2009 (r188287) @@ -615,14 +615,16 @@ jail_sysvipc_allow="NO" # Allow SystemV # each jail, specified in jail_list, with the following variables. # NOTES: # - replace 'example' with the jail's name. -# - except rootdir, hostname and ip, all of the following variables may be made -# global jail variables if you don't specify a jail name (ie. jail_interface). +# - except rootdir, hostname, ip and the _multi addresses, +# all of the following variables may be made global jail variables +# if you don't specify a jail name (ie. jail_interface, jail_devfs_ruleset). # #jail_example_rootdir="/usr/jail/default" # Jail's root directory #jail_example_hostname="default.domain.com" # Jail's hostname -#jail_example_ip="192.0.2.10" # Jail's IP number -#jail_example_interface="" # Interface to create the IP alias on -#jail_example_fib="0" # routing table for setfib(1) +#jail_example_interface="" # Jail's interface variable to create IP aliases on +#jail_example_fib="0" # Routing table for setfib(1) +#jail_example_ip="192.0.2.10,2001:db8::17" # Jail's primary IPv4 and IPv6 address +#jail_example_ip_multi0="2001:db8::10" # and another IPv6 address #jail_example_exec_start="/bin/sh /etc/rc" # command to execute in jail for starting #jail_example_exec_afterstart0="/bin/sh command" # command to execute after the one for # starting the jail. More than one can be Modified: stable/7/etc/rc.d/jail ============================================================================== --- stable/7/etc/rc.d/jail Sat Feb 7 13:55:12 2009 (r188286) +++ stable/7/etc/rc.d/jail Sat Feb 7 14:04:35 2009 (r188287) @@ -93,6 +93,7 @@ init_variables() debug "$_j mount enable: $_mount" debug "$_j hostname: $_hostname" debug "$_j ip: $_ip" + jail_show_addresses ${_j} debug "$_j interface: $_interface" debug "$_j fib: $_fib" debug "$_j root: $_rootdir" @@ -126,10 +127,6 @@ init_variables() if [ -z "${_rootdir}" ]; then err 3 "$name: No root directory has been defined for ${_j}" fi - if [ -z "${_ip}" ]; then - err 3 "$name: No IP address has been defined for ${_j}" - fi - } # set_sysctl rc_knob mib msg @@ -275,6 +272,208 @@ jail_mount_fstab() mount -a -F "${_fstab}" } +# jail_show_addresses jail +# Debug print the input for the given _multi aliases +# for a jail for init_variables(). +# +jail_show_addresses() +{ + local _j _type alias + _j="$1" + alias=0 + + if [ -z "${_j}" ]; then + warn "jail_show_addresses: you must specify a jail" + return + fi + + while : ; do + eval _addr=\"\$jail_${_j}_ip_multi${alias}\" + if [ -n "${_addr}" ]; then + debug "${_j} ip_multi${alias}: $_addr" + alias=$((${alias} + 1)) + else + break + fi + done +} + +# jail_extract_address argument +# The second argument is the string from one of the _ip +# or the _multi variables. In case of a comma separated list +# only one argument must be passed in at a time. +# The function alters the _type, _iface, _addr and _mask variables. +# +jail_extract_address() +{ + local _i + _i=$1 + + if [ -z "${_i}" ]; then + warn "jail_extract_address: called without input" + return + fi + + # Check if we have an interface prefix given and split into + # iFace and rest. + case "${_i}" in + *\|*) # ifN|.. prefix there + _iface=${_i%%|*} + _r=${_i##*|} + ;; + *) _iface="" + _r=${_i} + ;; + esac + + # In case the IP has no interface given, check if we have a global one. + _iface=${_iface:-${_interface}} + + # Set address, cut off any prefix/netmask/prefixlen. + _addr=${_r} + _addr=${_addr%%[/ ]*} + + # Theoretically we can return here if interface is not set, + # as we only care about the _mask if we call ifconfig. + # This is not done because we may want to santize IP addresses + # based on _type later, and optionally change the type as well. + + # Extract the prefix/netmask/prefixlen part by cutting off the address. + _mask=${_r} + _mask=`expr "${_mask}" : "${_addr}\(.*\)"` + + # Identify type {inet,inet6}. + case "${_addr}" in + *\.*\.*\.*) _type="inet" ;; + *:*) _type="inet6" ;; + *) warn "jail_extract_address: type not identified" + ;; + esac + + # Handle the special /netmask instead of /prefix or + # "netmask xxx" case for legacy IP. + # We do NOT support shortend class-full netmasks. + if [ "${_type}" = "inet" ]; then + case "${_mask}" in + /*\.*\.*\.*) _mask=" netmask ${_mask#/}" ;; + *) ;; + esac + + # In case _mask is still not set use /32. + _mask=${_mask:-/32} + + elif [ "${_type}" = "inet6" ]; then + # In case _maske is not set for IPv6, use /128. + _mask=${_mask:-/128} + fi +} + +# jail_handle_ips_option {add,del} input +# Handle a single argument imput which can be a comma separated +# list of addresses (theoretically with an option interface and +# prefix/netmask/prefixlen). +# +jail_handle_ips_option() +{ + local _x _action _type _i + _action=$1 + _x=$2 + + if [ -z "${_x}" ]; then + # No IP given. This can happen for the primary address + # of each address family. + return + fi + + # Loop, in case we find a comma separated list, we need to handle + # each argument on its own. + while [ ${#_x} -gt 0 ]; do + case "${_x}" in + *,*) # Extract the first argument and strip it off the list. + _i=`expr "${_x}" : '^\([^,]*\)'` + _x=`expr "${_x}" : "^[^,]*,\(.*\)"` + ;; + *) _i=${_x} + _x="" + ;; + esac + + _type="" + _iface="" + _addr="" + _mask="" + jail_extract_address "${_i}" + + # make sure we got an address. + case "${_addr}" in + "") continue ;; + *) ;; + esac + + # Append address to list of addresses for the jail command. + case "${_addrl}" in + "") _addrl="${_addr}" ;; + *) _addrl="${_addrl},${_addr}" ;; + esac + + # Configure interface alias if requested by a given interface + # and if we could correctly parse everything. + case "${_iface}" in + "") continue ;; + esac + case "${_type}" in + inet) ;; + inet6) ;; + *) warn "Could not determine address family. Not going" \ + "to ${_action} address '${_addr}' for ${_jail}." + continue + ;; + esac + case "${_action}" in + add) ifconfig ${_iface} ${_type} ${_addr}${_mask} alias + ;; + del) # When removing the IP, ignore the _mask. + ifconfig ${_iface} ${_type} ${_addr} -alias + ;; + esac + done +} + +# jail_ips {add,del} +# Extract the comma separated list of addresses and return them +# for the jail command. +# Handle more than one address via the _multi option as well. +# If an interface is given also add/remove an alias for the +# address with an optional netmask. +# +jail_ips() +{ + local _action + _action=$1 + + case "${_action}" in + add) ;; + del) ;; + *) warn "jail_ips: invalid action '${_action}'" + return + ;; + esac + + # Handle addresses. + jail_handle_ips_option ${_action} "${_ip}" + # Handle jail_xxx_ip_multi + alias=0 + while : ; do + eval _x=\"\$jail_${_jail}_ip_multi${alias}\" + case "${_x}" in + "") break ;; + *) jail_handle_ips_option ${_action} "${_x}" + alias=$((${alias} + 1)) + ;; + esac + done +} + jail_start() { echo -n 'Configuring jails:' @@ -296,9 +495,8 @@ jail_start() echo -n " [${_hostname} already running (/var/run/jail_${_jail}.id exists)]" continue; fi - if [ -n "${_interface}" ]; then - ifconfig ${_interface} alias ${_ip} netmask 255.255.255.255 - fi + _addrl="" + jail_ips "add" if [ -n "${_fib}" ]; then _setfib="setfib -F '${_fib}'" else @@ -358,7 +556,7 @@ jail_start() fi _tmp_jail=${_tmp_dir}/jail.$$ eval ${_setfib} jail ${_flags} -i ${_rootdir} ${_hostname} \ - ${_ip} ${_exec_start} > ${_tmp_jail} 2>&1 + \"${_addrl}\" ${_exec_start} > ${_tmp_jail} 2>&1 if [ "$?" -eq 0 ] ; then _jail_id=$(head -1 ${_tmp_jail}) @@ -379,9 +577,7 @@ jail_start() echo ${_jail_id} > /var/run/jail_${_jail}.id else jail_umount_fs - if [ -n "${_interface}" ]; then - ifconfig ${_interface} -alias ${_ip} - fi + jail_ips "del" echo " cannot start jail \"${_jail}\": " tail +2 ${_tmp_jail} fi @@ -410,9 +606,7 @@ jail_stop() jail_umount_fs echo -n " $_hostname" fi - if [ -n "${_interface}" ]; then - ifconfig ${_interface} -alias ${_ip} - fi + jail_ips "del" rm /var/run/jail_${_jail}.id else echo " cannot stop jail ${_jail}. No jail id in /var/run" Modified: stable/7/share/man/man5/rc.conf.5 ============================================================================== --- stable/7/share/man/man5/rc.conf.5 Sat Feb 7 13:55:12 2009 (r188286) +++ stable/7/share/man/man5/rc.conf.5 Sat Feb 7 14:04:35 2009 (r188287) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 9, 2009 +.Dd January 25, 2009 .Dt RC.CONF 5 .Os .Sh NAME @@ -3398,8 +3398,38 @@ Set to the fully qualified domain name ( .It Va jail_ Ns Ao Ar jname Ac Ns Va _ip .Pq Vt str Unset by default. -Set to the IP address assigned to jail -.Va jname . +Set to the (primary) IPv4 and/or IPv6 address(es) assigned to the jail. +The argument can be a sole address or a comma separated list of addresses. +Additionally each address can be prefixed by the name of an interface +followed by a pipe to overwrite +.Va jail_ Ns Ao Ar jname Ac Ns Va _interface +or +.Va jail_interface +and/or suffixed by a netmask, prefixlen or prefix. +In case no netmask, prefixlen or prefix is given, +.Sq /32 +will be used for IPv4 and +.Sq /128 +will be used for an IPv6 address. +If no address is given for the jail then the jail will be started with +no networking support. +.It Va jail_ Ns Ao Ar jname Ac Ns Va _ip_multi Ns Aq Ar n +.Pq Vt str +Unset by default. +Set additional IPv4 and/or IPv6 address(es) assigned to the jail. +The sequence starts with +.Dq Li _multi0 +and the numbers have to be strictly ascending. +These entries follow the same syntax as their primary +.Va jail_ Ns Ao Ar jname Ac Ns Va _ip +entry. +The order of the entries can be important as the first address for +each address family found will be the primary address of the jail. +See +.Va ip-addresses +option in +.Xr jail 8 +for more details. .It Va jail_ Ns Ao Ar jname Ac Ns Va _flags .Pq Vt str Set to From bz at FreeBSD.org Sat Feb 7 06:55:30 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 06:55:36 2009 Subject: svn commit: r188288 - in stable/7: share/mk sys sys/conf sys/contrib/pf sys/dev/cxgb Message-ID: <200902071455.n17EtTpX096114@svn.freebsd.org> Author: bz Date: Sat Feb 7 14:55:29 2009 New Revision: 188288 URL: http://svn.freebsd.org/changeset/base/188288 Log: MFC: r186854 Using KMODOWN/KMODGRP rather than hard coding root/wheel for installing the kernel allows one, like with modules, to override the default user/group and install as non-su to a temporary directory to test, create images or seed a tftp dir. r186894 Document that we started using KMODOWN/KMODGRP for the kernel as well and no longer only for modules. Modified: stable/7/share/mk/ (props changed) stable/7/share/mk/bsd.own.mk stable/7/sys/ (props changed) stable/7/sys/conf/kern.post.mk stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/share/mk/bsd.own.mk ============================================================================== --- stable/7/share/mk/bsd.own.mk Sat Feb 7 14:04:35 2009 (r188287) +++ stable/7/share/mk/bsd.own.mk Sat Feb 7 14:55:29 2009 (r188288) @@ -44,9 +44,9 @@ # KMODDIR Base path for loadable kernel modules # (see kld(4)). [/boot/kernel] # -# KMODOWN KLD owner. [${BINOWN}] +# KMODOWN Kernel and KLD owner. [${BINOWN}] # -# KMODGRP KLD group. [${BINGRP}] +# KMODGRP Kernel and KLD group. [${BINGRP}] # # KMODMODE KLD mode. [${BINMODE}] # Modified: stable/7/sys/conf/kern.post.mk ============================================================================== --- stable/7/sys/conf/kern.post.mk Sat Feb 7 14:04:35 2009 (r188287) +++ stable/7/sys/conf/kern.post.mk Sat Feb 7 14:55:29 2009 (r188288) @@ -223,21 +223,21 @@ kernel-install: fi .endif mkdir -p ${DESTDIR}${KODIR} - ${INSTALL} -p -m 555 -o root -g wheel ${KERNEL_KO} ${DESTDIR}${KODIR} + ${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO} ${DESTDIR}${KODIR} .if defined(DEBUG) && !defined(INSTALL_NODEBUG) - ${INSTALL} -p -m 555 -o root -g wheel ${KERNEL_KO}.symbols ${DESTDIR}${KODIR} + ${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO}.symbols ${DESTDIR}${KODIR} .endif .if defined(KERNEL_EXTRA_INSTALL) - ${INSTALL} -p -m 555 -o root -g wheel ${KERNEL_EXTRA_INSTALL} ${DESTDIR}${KODIR} + ${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_EXTRA_INSTALL} ${DESTDIR}${KODIR} .endif kernel-reinstall: @-chflags -R noschg ${DESTDIR}${KODIR} - ${INSTALL} -p -m 555 -o root -g wheel ${KERNEL_KO} ${DESTDIR}${KODIR} + ${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO} ${DESTDIR}${KODIR} .if defined(DEBUG) && !defined(INSTALL_NODEBUG) - ${INSTALL} -p -m 555 -o root -g wheel ${KERNEL_KO}.symbols ${DESTDIR}${KODIR} + ${INSTALL} -p -m 555 -o ${KMODOWN} -g ${KMODGRP} ${KERNEL_KO}.symbols ${DESTDIR}${KODIR} .endif config.o env.o hints.o vers.o vnode_if.o: From bz at FreeBSD.org Sat Feb 7 07:21:12 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 07:21:28 2009 Subject: svn commit: r188289 - stable/7 Message-ID: <200902071521.n17FLBAe096824@svn.freebsd.org> Author: bz Date: Sat Feb 7 15:21:11 2009 New Revision: 188289 URL: http://svn.freebsd.org/changeset/base/188289 Log: MFC: r186519 Permit digits in the kernel config file names for `make universe'. This catches a few more kernel config for various architectures and permits having local configs named like NOINET6. Modified: stable/7/Makefile (contents, props changed) Modified: stable/7/Makefile ============================================================================== --- stable/7/Makefile Sat Feb 7 14:55:29 2009 (r188288) +++ stable/7/Makefile Sat Feb 7 15:21:11 2009 (r188289) @@ -279,7 +279,7 @@ universe_prologue: @echo "--------------------------------------------------------------" .for target in ${TARGETS} KERNCONFS!= cd ${.CURDIR}/sys/${target}/conf && \ - find [A-Z]*[A-Z] -type f -maxdepth 0 \ + find [A-Z0-9]*[A-Z0-9] -type f -maxdepth 0 \ ! -name DEFAULTS ! -name LINT KERNCONFS:= ${KERNCONFS:S/^NOTES$/LINT/} universe: universe_${target} From bz at FreeBSD.org Sat Feb 7 07:31:25 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 07:31:31 2009 Subject: svn commit: r188290 - stable/7/share/man/man5 Message-ID: <200902071531.n17FVOod097038@svn.freebsd.org> Author: bz Date: Sat Feb 7 15:31:23 2009 New Revision: 188290 URL: http://svn.freebsd.org/changeset/base/188290 Log: MFC: r187668 Change IP addresses/prefixes to be from "Test-Net" (IPv4 documentation prefix 192.0.2.0/24) rather than from private-use networks. Modified: stable/7/share/man/man5/ (props changed) stable/7/share/man/man5/rc.conf.5 Modified: stable/7/share/man/man5/rc.conf.5 ============================================================================== --- stable/7/share/man/man5/rc.conf.5 Sat Feb 7 15:21:11 2009 (r188289) +++ stable/7/share/man/man5/rc.conf.5 Sat Feb 7 15:31:23 2009 (r188290) @@ -1085,9 +1085,9 @@ One can configure more than one IPv4 add variable. One or more IP addresses must be provided in Classless Inter-Domain Routing (CIDR) address notation, whose last byte can be a range like -192.168.0.5-23/24. -In this case the address 192.168.0.5 will be configured with the -netmask /24 and the addresses 192.168.0.6 to 192.168.0.23 with +192.0.2.5-23/24. +In this case the address 192.0.2.5 will be configured with the +netmask /24 and the addresses 192.0.2.6 to 192.0.2.23 with the non-conflicting netmask /32 as explained in the .Xr ifconfig 8 alias section. @@ -1095,7 +1095,7 @@ With the interface in question being .Li ed0 , an example could look like: .Bd -literal -ipv4_addrs_ed0="192.168.0.1/24 192.168.1.1-5/28" +ipv4_addrs_ed0="192.0.2.129/27 192.0.2.1-5/28" .Ed .Pp It is also possible to add IP alias entries using @@ -1205,7 +1205,7 @@ variable. It is also possible to rename interface by doing: .Bd -literal ifconfig_ed0_name="net0" -ifconfig_net0="inet 10.0.0.1 netmask 0xffff0000" +ifconfig_net0="inet 192.0.2.1 netmask 0xffffff00" .Ed .It Va ipv6_network_interfaces .Pq Vt str @@ -3281,7 +3281,7 @@ Assuming that the jail in question was n you would have the following dependent variables: .Bd -literal jail_vjail_hostname="jail.example.com" -jail_vjail_ip="192.168.1.100" +jail_vjail_ip="192.0.2.100" jail_vjail_rootdir="/var/jails/vjail/root" .Ed .Pp From alc at FreeBSD.org Sat Feb 7 07:51:22 2009 From: alc at FreeBSD.org (Alan Cox) Date: Sat Feb 7 07:51:27 2009 Subject: svn commit: r188291 - stable/7 Message-ID: <200902071551.n17FpLZQ097441@svn.freebsd.org> Author: alc Date: Sat Feb 7 15:51:21 2009 New Revision: 188291 URL: http://svn.freebsd.org/changeset/base/188291 Log: Recent changes to the kernel increasing the size of the kernel and kmem maps on amd64 machines should trigger ZFS users to reevaluate their manual tuning of the kmem map. Modified: stable/7/UPDATING Modified: stable/7/UPDATING ============================================================================== --- stable/7/UPDATING Sat Feb 7 15:31:23 2009 (r188290) +++ stable/7/UPDATING Sat Feb 7 15:51:21 2009 (r188291) @@ -9,6 +9,13 @@ Items affecting the ports and packages s portupgrade. 20090207: + ZFS users on amd64 machines with 4GB or more of RAM should + reevaluate their need for setting vm.kmem_size_max and + vm.kmem_size manually. In fact, after recent changes to the + kernel, the default value of vm.kmem_size is larger than the + suggested manual setting in most ZFS/FreeBSD tuning guides. + +20090207: Multi-IPv4/v6/no-IP jail support was merged to STABLE. You need to rebuild jls(8) and to use the new features jail(8), jexec(8) and cpuset(1) with a new kernel. From bz at FreeBSD.org Sat Feb 7 13:07:59 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Sat Feb 7 13:08:11 2009 Subject: svn commit: r188296 - stable/7/sys/conf Message-ID: <200902072107.n17L7w2N003499@svn.freebsd.org> Author: bz Date: Sat Feb 7 21:07:58 2009 New Revision: 188296 URL: http://svn.freebsd.org/changeset/base/188296 Log: "MFC": sys/conf/kern.pre.mk r180012 (out of the larger commit) Without including bsd.own.mk KMODOWN/KMODGRP are not defined which after r188288 broke installkernel. Reported by: kib, Herbert J. Skuhra Reviewed by: kib Pointy hat to: bz Modified: stable/7/sys/conf/kern.pre.mk Modified: stable/7/sys/conf/kern.pre.mk ============================================================================== --- stable/7/sys/conf/kern.pre.mk Sat Feb 7 19:34:44 2009 (r188295) +++ stable/7/sys/conf/kern.pre.mk Sat Feb 7 21:07:58 2009 (r188296) @@ -3,10 +3,7 @@ # Part of a unified Makefile for building kernels. This part contains all # of the definitions that need to be before %BEFORE_DEPEND. -SRCCONF?= /etc/src.conf -.if exists(${SRCCONF}) -.include "${SRCCONF}" -.endif +.include # Can be overridden by makeoptions or /etc/make.conf KERNEL_KO?= kernel From rpaulo at FreeBSD.org Sun Feb 8 11:53:38 2009 From: rpaulo at FreeBSD.org (Rui Paulo) Date: Sun Feb 8 11:53:48 2009 Subject: svn commit: r188322 - in stable/7/sys: . contrib/pf dev/acpi_support dev/ath/ath_hal dev/cxgb Message-ID: <200902081953.n18JrbXk032437@svn.freebsd.org> Author: rpaulo Date: Sun Feb 8 19:53:37 2009 New Revision: 188322 URL: http://svn.freebsd.org/changeset/base/188322 Log: MFC r181885: Fix typo in comment. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/acpi_support/acpi_asus.c stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/dev/acpi_support/acpi_asus.c ============================================================================== --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 19:44:50 2009 (r188321) +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 19:53:37 2009 (r188322) @@ -286,7 +286,7 @@ static struct acpi_asus_model acpi_asus_ }, { .name = "L8L" - /* Only has hotkeys, apparantly */ + /* Only has hotkeys, apparently */ }, { .name = "M1A", From rpaulo at FreeBSD.org Sun Feb 8 11:55:14 2009 From: rpaulo at FreeBSD.org (Rui Paulo) Date: Sun Feb 8 11:55:21 2009 Subject: svn commit: r188324 - in stable/7/sys: . contrib/pf dev/acpi_support dev/ath/ath_hal dev/cxgb Message-ID: <200902081955.n18JtDhM032568@svn.freebsd.org> Author: rpaulo Date: Sun Feb 8 19:55:13 2009 New Revision: 188324 URL: http://svn.freebsd.org/changeset/base/188324 Log: MFC r184625: Add support for Asus A8Sr notebooks. PR: 128553 Submitted by: Eygene Ryabinkin Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/acpi_support/acpi_asus.c stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/dev/acpi_support/acpi_asus.c ============================================================================== --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 19:55:03 2009 (r188323) +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 19:55:13 2009 (r188324) @@ -89,6 +89,9 @@ struct acpi_asus_model { char *crd_set; void (*n_func)(ACPI_HANDLE, UINT32, void *); + + char *lcdd; + void (*lcdd_n_func)(ACPI_HANDLE, UINT32, void *); }; struct acpi_asus_led { @@ -109,6 +112,7 @@ struct acpi_asus_led { struct acpi_asus_softc { device_t dev; ACPI_HANDLE handle; + ACPI_HANDLE lcdd_handle; struct acpi_asus_model *model; struct sysctl_ctx_list sysctl_ctx; @@ -128,6 +132,9 @@ struct acpi_asus_softc { int s_crd; }; +static void acpi_asus_lcdd_notify(ACPI_HANDLE h, UINT32 notify, + void *context); + /* * We can identify Asus laptops from the string they return * as a result of calling the ATK0100 'INIT' method. @@ -200,6 +207,20 @@ static struct acpi_asus_model acpi_asus_ .disp_set = "SDSP" }, { + .name = "A8SR", + .bled_set = "BLED", + .mled_set = "MLED", + .wled_set = "WLED", + .lcd_get = NULL, + .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10", + .brn_get = "GPLV", + .brn_set = "SPLV", + .disp_get = "\\_SB.PCI0.P0P1.VGA.GETD", + .disp_set = "SDSP", + .lcdd = "\\_SB.PCI0.P0P1.VGA.LCDD", + .lcdd_n_func = acpi_asus_lcdd_notify + }, + { .name = "D1x", .mled_set = "MLED", .lcd_get = "\\GP11", @@ -749,6 +770,22 @@ acpi_asus_attach(device_t dev) AcpiInstallNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY, sc->model->n_func, dev); + /* Find and hook the 'LCDD' object */ + if (sc->model->lcdd != NULL && sc->model->lcdd_n_func != NULL) { + ACPI_STATUS res; + + sc->lcdd_handle = NULL; + res = AcpiGetHandle((sc->model->lcdd[0] == '\\' ? + NULL : sc->handle), sc->model->lcdd, &(sc->lcdd_handle)); + if (ACPI_SUCCESS(res)) { + AcpiInstallNotifyHandler((sc->lcdd_handle), + ACPI_DEVICE_NOTIFY, sc->model->lcdd_n_func, dev); + } else { + printf("%s: unable to find LCD device '%s'\n", + __func__, sc->model->lcdd); + } + } + return (0); } @@ -783,6 +820,13 @@ acpi_asus_detach(device_t dev) /* Remove notify handler */ AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY, acpi_asus_notify); + + if (sc->lcdd_handle) { + KASSERT(sc->model->lcdd_n_func != NULL, + ("model->lcdd_n_func is NULL, but lcdd_handle is non-zero")); + AcpiRemoveNotifyHandler((sc->lcdd_handle), + ACPI_DEVICE_NOTIFY, sc->model->lcdd_n_func); + } /* Free sysctl tree */ sysctl_ctx_free(&sc->sysctl_ctx); @@ -1124,6 +1168,12 @@ acpi_asus_notify(ACPI_HANDLE h, UINT32 n } else if (notify == 0x34) { sc->s_lcd = 0; ACPI_VPRINT(sc->dev, acpi_sc, "LCD turned off\n"); + } else if (notify == 0x86) { + acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn-1); + ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n"); + } else if (notify == 0x87) { + acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn+1); + ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n"); } else { /* Notify devd(8) */ acpi_UserNotify("ASUS", h, notify); @@ -1132,6 +1182,31 @@ acpi_asus_notify(ACPI_HANDLE h, UINT32 n } static void +acpi_asus_lcdd_notify(ACPI_HANDLE h, UINT32 notify, void *context) +{ + struct acpi_asus_softc *sc; + struct acpi_softc *acpi_sc; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + sc = device_get_softc((device_t)context); + acpi_sc = acpi_device_get_parent_softc(sc->dev); + + ACPI_SERIAL_BEGIN(asus); + switch (notify) { + case 0x87: + acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn-1); + ACPI_VPRINT(sc->dev, acpi_sc, "Brightness decreased\n"); + break; + case 0x86: + acpi_asus_sysctl_set(sc, ACPI_ASUS_METHOD_BRN, sc->s_brn+1); + ACPI_VPRINT(sc->dev, acpi_sc, "Brightness increased\n"); + break; + } + ACPI_SERIAL_END(asus); +} + +static void acpi_asus_eeepc_notify(ACPI_HANDLE h, UINT32 notify, void *context) { struct acpi_asus_softc *sc; From rpaulo at FreeBSD.org Sun Feb 8 12:00:38 2009 From: rpaulo at FreeBSD.org (Rui Paulo) Date: Sun Feb 8 12:00:57 2009 Subject: svn commit: r188326 - in stable/7/sys: . contrib/pf dev/acpi_support dev/cxgb Message-ID: <200902082000.n18K0aBr032797@svn.freebsd.org> Author: rpaulo Date: Sun Feb 8 20:00:36 2009 New Revision: 188326 URL: http://svn.freebsd.org/changeset/base/188326 Log: MFC r186529 (stas): - Fix incorrect array declaration that was causing the stack overflow on some (most?) Asus laptops. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/acpi_support/acpi_asus.c stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/dev/acpi_support/acpi_asus.c ============================================================================== --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 20:00:33 2009 (r188325) +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 20:00:36 2009 (r188326) @@ -958,7 +958,9 @@ acpi_asus_sysctl_get(struct acpi_asus_so static int acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg) { - ACPI_STATUS status = AE_OK; + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_LIST acpiargs; + ACPI_OBJECT acpiarg[1]; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_SERIAL_ASSERT(asus); From christoph.mallon at gmx.de Sun Feb 8 12:47:38 2009 From: christoph.mallon at gmx.de (Christoph Mallon) Date: Sun Feb 8 12:47:50 2009 Subject: svn commit: r188326 - in stable/7/sys: . contrib/pf dev/acpi_support dev/cxgb In-Reply-To: <200902082000.n18K0aBr032797@svn.freebsd.org> References: <200902082000.n18K0aBr032797@svn.freebsd.org> Message-ID: <498F3EA7.4050900@gmx.de> Rui Paulo schrieb: > Author: rpaulo > Date: Sun Feb 8 20:00:36 2009 > New Revision: 188326 > URL: http://svn.freebsd.org/changeset/base/188326 > > Log: > MFC r186529 (stas): > - Fix incorrect array declaration that was causing the stack overflow > on some (most?) Asus laptops. > > Modified: > stable/7/sys/ (props changed) > stable/7/sys/contrib/pf/ (props changed) > stable/7/sys/dev/acpi_support/acpi_asus.c > stable/7/sys/dev/cxgb/ (props changed) > > Modified: stable/7/sys/dev/acpi_support/acpi_asus.c > ============================================================================== > --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 20:00:33 2009 (r188325) > +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 20:00:36 2009 (r188326) > @@ -958,7 +958,9 @@ acpi_asus_sysctl_get(struct acpi_asus_so > static int > acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg) > { > - ACPI_STATUS status = AE_OK; > + ACPI_STATUS status = AE_OK; > + ACPI_OBJECT_LIST acpiargs; > + ACPI_OBJECT acpiarg[1]; > > ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); > ACPI_SERIAL_ASSERT(asus); r186529 does not seem to apply to 7.x, because you just added two unused variables. Maybe you forgot to MFC something else (r180268?) first. From rpaulo at FreeBSD.org Sun Feb 8 12:54:44 2009 From: rpaulo at FreeBSD.org (Rui Paulo) Date: Sun Feb 8 12:54:51 2009 Subject: svn commit: r188326 - in stable/7/sys: . contrib/pf dev/acpi_support dev/cxgb In-Reply-To: <498F3EA7.4050900@gmx.de> References: <200902082000.n18K0aBr032797@svn.freebsd.org> <498F3EA7.4050900@gmx.de> Message-ID: <1F7BDEA8-EFB8-42D9-A32D-1D3F49F9C9EC@FreeBSD.org> On 8 Feb 2009, at 20:20, Christoph Mallon wrote: > Rui Paulo schrieb: >> Author: rpaulo >> Date: Sun Feb 8 20:00:36 2009 >> New Revision: 188326 >> URL: http://svn.freebsd.org/changeset/base/188326 >> Log: >> MFC r186529 (stas): >> - Fix incorrect array declaration that was causing the stack >> overflow >> on some (most?) Asus laptops. >> Modified: >> stable/7/sys/ (props changed) >> stable/7/sys/contrib/pf/ (props changed) >> stable/7/sys/dev/acpi_support/acpi_asus.c >> stable/7/sys/dev/cxgb/ (props changed) >> Modified: stable/7/sys/dev/acpi_support/acpi_asus.c >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 20:00:33 >> 2009 (r188325) >> +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 20:00:36 >> 2009 (r188326) >> @@ -958,7 +958,9 @@ acpi_asus_sysctl_get(struct acpi_asus_so >> static int >> acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg) >> { >> - ACPI_STATUS status = AE_OK; >> + ACPI_STATUS status = AE_OK; >> + ACPI_OBJECT_LIST acpiargs; >> + ACPI_OBJECT acpiarg[1]; >> ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); >> ACPI_SERIAL_ASSERT(asus); > > r186529 does not seem to apply to 7.x, because you just added two > unused variables. Maybe you forgot to MFC something else (r180268?) > first. This is a merge botch... Sorry. -- Rui Paulo -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 194 bytes Desc: This is a digitally signed message part Url : http://lists.freebsd.org/pipermail/svn-src-stable-7/attachments/20090208/bd47b899/PGP.pgp From rpaulo at FreeBSD.org Sun Feb 8 14:01:21 2009 From: rpaulo at FreeBSD.org (Rui Paulo) Date: Sun Feb 8 14:01:43 2009 Subject: svn commit: r188342 - in stable/7/sys: . contrib/pf dev/acpi_support dev/cxgb Message-ID: <200902082201.n18M1KM3035736@svn.freebsd.org> Author: rpaulo Date: Sun Feb 8 22:01:20 2009 New Revision: 188342 URL: http://svn.freebsd.org/changeset/base/188342 Log: Reverse botched r188326. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/acpi_support/acpi_asus.c stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/dev/acpi_support/acpi_asus.c ============================================================================== --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 21:54:51 2009 (r188341) +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 22:01:20 2009 (r188342) @@ -958,9 +958,7 @@ acpi_asus_sysctl_get(struct acpi_asus_so static int acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg) { - ACPI_STATUS status = AE_OK; - ACPI_OBJECT_LIST acpiargs; - ACPI_OBJECT acpiarg[1]; + ACPI_STATUS status = AE_OK; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_SERIAL_ASSERT(asus); From rpaulo at FreeBSD.org Sun Feb 8 14:09:50 2009 From: rpaulo at FreeBSD.org (Rui Paulo) Date: Sun Feb 8 14:09:57 2009 Subject: svn commit: r188346 - in stable/7/sys: . contrib/pf dev/acpi_support dev/ath/ath_hal dev/cxgb Message-ID: <200902082209.n18M9nIo036273@svn.freebsd.org> Author: rpaulo Date: Sun Feb 8 22:09:49 2009 New Revision: 188346 URL: http://svn.freebsd.org/changeset/base/188346 Log: MFC r180268: Fix my previous commit. We actually should pass evaluation args in AcpiEvaluateObject() calls, otherwise, we are not able to bring devices back up (NULL means 0, hence always off). While there add missing WLAN on/off support. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/acpi_support/acpi_asus.c stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/dev/acpi_support/acpi_asus.c ============================================================================== --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 22:08:48 2009 (r188345) +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 22:09:49 2009 (r188346) @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #define ACPI_ASUS_METHOD_LCD 3 #define ACPI_ASUS_METHOD_CAMERA 4 #define ACPI_ASUS_METHOD_CARDRD 5 +#define ACPI_ASUS_METHOD_WLAN 6 #define _COMPONENT ACPI_OEM ACPI_MODULE_NAME("ASUS") @@ -88,6 +89,9 @@ struct acpi_asus_model { char *crd_get; char *crd_set; + char *wlan_get; + char *wlan_set; + void (*n_func)(ACPI_HANDLE, UINT32, void *); char *lcdd; @@ -130,6 +134,7 @@ struct acpi_asus_softc { int s_lcd; int s_cam; int s_crd; + int s_wlan; }; static void acpi_asus_lcdd_notify(ACPI_HANDLE h, UINT32 notify, @@ -423,6 +428,8 @@ static struct acpi_asus_model acpi_eeepc .cam_set = "\\_SB.ATKD.CAMS", .crd_set = "\\_SB.ATKD.CRDS", .crd_get = "\\_SB.ATKD.CRDG", + .wlan_get = "\\_SB.ATKD.WLDG", + .wlan_set = "\\_SB.ATKD.WLDS", .n_func = acpi_asus_eeepc_notify }, @@ -465,6 +472,12 @@ static struct { .description = "internal card reader state", .flags = CTLTYPE_INT | CTLFLAG_RW }, + { + .name = "wlan", + .method = ACPI_ASUS_METHOD_WLAN, + .description = "wireless lan state", + .flags = CTLTYPE_INT | CTLFLAG_RW + }, { .name = NULL } }; @@ -950,6 +963,9 @@ acpi_asus_sysctl_get(struct acpi_asus_so case ACPI_ASUS_METHOD_CARDRD: val = sc->s_crd; break; + case ACPI_ASUS_METHOD_WLAN: + val = sc->s_wlan; + break; } return (val); @@ -958,11 +974,18 @@ acpi_asus_sysctl_get(struct acpi_asus_so static int acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int arg) { - ACPI_STATUS status = AE_OK; + ACPI_STATUS status = AE_OK; + ACPI_OBJECT_LIST acpiargs; + ACPI_OBJECT acpiarg[0]; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_SERIAL_ASSERT(asus); + acpiargs.Count = 1; + acpiargs.Pointer = acpiarg; + acpiarg[0].Type = ACPI_TYPE_INTEGER; + acpiarg[0].Integer.Value = arg; + switch (method) { case ACPI_ASUS_METHOD_BRN: if (arg < 0 || arg > 15) @@ -1015,7 +1038,7 @@ acpi_asus_sysctl_set(struct acpi_asus_so return (EINVAL); status = AcpiEvaluateObject(sc->handle, - sc->model->cam_set, NULL, NULL); + sc->model->cam_set, &acpiargs, NULL); if (ACPI_SUCCESS(status)) sc->s_cam = arg; @@ -1025,11 +1048,21 @@ acpi_asus_sysctl_set(struct acpi_asus_so return (EINVAL); status = AcpiEvaluateObject(sc->handle, - sc->model->crd_set, NULL, NULL); + sc->model->crd_set, &acpiargs, NULL); if (ACPI_SUCCESS(status)) sc->s_crd = arg; break; + case ACPI_ASUS_METHOD_WLAN: + if (arg < 0 || arg > 1) + return (EINVAL); + + status = AcpiEvaluateObject(sc->handle, + sc->model->wlan_set, &acpiargs, NULL); + + if (ACPI_SUCCESS(status)) + sc->s_wlan = arg; + break; } return (0); @@ -1140,6 +1173,14 @@ acpi_asus_sysctl_init(struct acpi_asus_s return (TRUE); } return (FALSE); + case ACPI_ASUS_METHOD_WLAN: + if (sc->model->wlan_get) { + status = acpi_GetInteger(sc->handle, + sc->model->wlan_get, &sc->s_wlan); + if (ACPI_SUCCESS(status)) + return (TRUE); + } + return (FALSE); } return (FALSE); } From rpaulo at gmail.com Sun Feb 8 14:13:56 2009 From: rpaulo at gmail.com (Rui Paulo) Date: Sun Feb 8 14:14:03 2009 Subject: svn commit: r188326 - in stable/7/sys: . contrib/pf dev/acpi_support dev/cxgb In-Reply-To: <1F7BDEA8-EFB8-42D9-A32D-1D3F49F9C9EC@FreeBSD.org> References: <200902082000.n18K0aBr032797@svn.freebsd.org> <498F3EA7.4050900@gmx.de> <1F7BDEA8-EFB8-42D9-A32D-1D3F49F9C9EC@FreeBSD.org> Message-ID: <8F7136F6-15CC-4ACC-83AC-867900012717@gmail.com> On 8 Feb 2009, at 20:32, Rui Paulo wrote: > > On 8 Feb 2009, at 20:20, Christoph Mallon wrote: > >> Rui Paulo schrieb: >>> Author: rpaulo >>> Date: Sun Feb 8 20:00:36 2009 >>> New Revision: 188326 >>> URL: http://svn.freebsd.org/changeset/base/188326 >>> Log: >>> MFC r186529 (stas): >>> - Fix incorrect array declaration that was causing the stack >>> overflow >>> on some (most?) Asus laptops. >>> Modified: >>> stable/7/sys/ (props changed) >>> stable/7/sys/contrib/pf/ (props changed) >>> stable/7/sys/dev/acpi_support/acpi_asus.c >>> stable/7/sys/dev/cxgb/ (props changed) >>> Modified: stable/7/sys/dev/acpi_support/acpi_asus.c >>> = >>> = >>> = >>> = >>> = >>> = >>> = >>> = >>> = >>> = >>> ==================================================================== >>> --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 20:00:33 >>> 2009 (r188325) >>> +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 20:00:36 >>> 2009 (r188326) >>> @@ -958,7 +958,9 @@ acpi_asus_sysctl_get(struct acpi_asus_so >>> static int >>> acpi_asus_sysctl_set(struct acpi_asus_softc *sc, int method, int >>> arg) >>> { >>> - ACPI_STATUS status = AE_OK; >>> + ACPI_STATUS status = AE_OK; >>> + ACPI_OBJECT_LIST acpiargs; >>> + ACPI_OBJECT acpiarg[1]; >>> ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); >>> ACPI_SERIAL_ASSERT(asus); >> >> r186529 does not seem to apply to 7.x, because you just added two >> unused variables. Maybe you forgot to MFC something else (r180268?) >> first. > > > This is a merge botch... Sorry. Should be fixed now. Thanks, -- Rui Paulo -------------- next part -------------- A non-text attachment was scrubbed... Name: PGP.sig Type: application/pgp-signature Size: 194 bytes Desc: This is a digitally signed message part Url : http://lists.freebsd.org/pipermail/svn-src-stable-7/attachments/20090208/12db8ae6/PGP.pgp From rpaulo at FreeBSD.org Sun Feb 8 14:13:58 2009 From: rpaulo at FreeBSD.org (Rui Paulo) Date: Sun Feb 8 14:14:18 2009 Subject: svn commit: r188347 - in stable/7/sys: . contrib/pf dev/acpi_support dev/cxgb Message-ID: <200902082213.n18MDvrx036425@svn.freebsd.org> Author: rpaulo Date: Sun Feb 8 22:13:57 2009 New Revision: 188347 URL: http://svn.freebsd.org/changeset/base/188347 Log: MFC 186529 (stas): - Fix incorrect array declaration that was causing the stack overflow on some (most?) Asus laptops. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/acpi_support/acpi_asus.c stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/dev/acpi_support/acpi_asus.c ============================================================================== --- stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 22:09:49 2009 (r188346) +++ stable/7/sys/dev/acpi_support/acpi_asus.c Sun Feb 8 22:13:57 2009 (r188347) @@ -976,7 +976,7 @@ acpi_asus_sysctl_set(struct acpi_asus_so { ACPI_STATUS status = AE_OK; ACPI_OBJECT_LIST acpiargs; - ACPI_OBJECT acpiarg[0]; + ACPI_OBJECT acpiarg[1]; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); ACPI_SERIAL_ASSERT(asus); From yongari at FreeBSD.org Sun Feb 8 17:16:38 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 17:16:44 2009 Subject: svn commit: r188356 - in stable/7/sys: . contrib/pf dev/cxgb dev/re pci Message-ID: <200902090116.n191GbaZ040279@svn.freebsd.org> Author: yongari Date: Mon Feb 9 01:16:36 2009 New Revision: 188356 URL: http://svn.freebsd.org/changeset/base/188356 Log: MFC: r185752-185753,185756,185896 r185752: Make sure to return the result of meida change request. Previously it used to return success regardless of the result. r185753: o Implemented miibus_statchg handler. It detects whether re(4) established a valid link or not. In miibus_statchg handler add a check for established link is valid one for the controller(e.g. 1000baseT is not a valid link for fastethernet controllers.) o Added a flag RE_FLAG_FASTETHER to mark fastethernet controllers. o Added additional check to know whether we've really encountered watchdog timeouts or missed Tx completion interrupts. This change may help to track down the cause of watchdog timeouts. o In interrupt handler, removed a check for link state change interrupt. Not all controllers have the bit and re(4) did not rely on the event for a long time. In addition, re(4) didn't request the interrupt in RL_IMR register. r185756: Reduce spin wait time consumed in GMII register access routines. Waiting for 1ms for each GMII register access looks overkill and it may also decrease overall performance of driver because re(4) invokes mii_tick for every hz. r185896: Partly revert r185756. RTL8169SC doesn't like reduced delays in GMII access while Tx/Rx is in progress. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/re/if_re.c stable/7/sys/pci/if_rlreg.h Modified: stable/7/sys/dev/re/if_re.c ============================================================================== --- stable/7/sys/dev/re/if_re.c Mon Feb 9 00:58:16 2009 (r188355) +++ stable/7/sys/dev/re/if_re.c Mon Feb 9 01:16:36 2009 (r188356) @@ -417,7 +417,6 @@ re_gmii_readreg(device_t dev, int phy, i } CSR_WRITE_4(sc, RL_PHYAR, reg << 16); - DELAY(1000); for (i = 0; i < RL_TIMEOUT; i++) { rval = CSR_READ_4(sc, RL_PHYAR); @@ -445,7 +444,6 @@ re_gmii_writereg(device_t dev, int phy, CSR_WRITE_4(sc, RL_PHYAR, (reg << 16) | (data & RL_PHYAR_PHYDATA) | RL_PHYAR_BUSY); - DELAY(1000); for (i = 0; i < RL_TIMEOUT; i++) { rval = CSR_READ_4(sc, RL_PHYAR); @@ -573,7 +571,39 @@ re_miibus_writereg(device_t dev, int phy static void re_miibus_statchg(device_t dev) { + struct rl_softc *sc; + struct ifnet *ifp; + struct mii_data *mii; + + sc = device_get_softc(dev); + mii = device_get_softc(sc->rl_miibus); + ifp = sc->rl_ifp; + if (mii == NULL || ifp == NULL || + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; + sc->rl_flags &= ~RL_FLAG_LINK; + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: + sc->rl_flags |= RL_FLAG_LINK; + break; + case IFM_1000_T: + if ((sc->rl_flags & RL_FLAG_FASTETHER) != 0) + break; + sc->rl_flags |= RL_FLAG_LINK; + break; + default: + break; + } + } + /* + * RealTek controllers does not provide any interface to + * Tx/Rx MACs for resolved speed, duplex and flow-control + * parameters. + */ } /* @@ -1204,18 +1234,18 @@ re_attach(device_t dev) switch (hw_rev->rl_rev) { case RL_HWREV_8139CPLUS: - sc->rl_flags |= RL_FLAG_NOJUMBO; + sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_FASTETHER; break; case RL_HWREV_8100E: case RL_HWREV_8101E: sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR | - RL_FLAG_PHYWAKE; + RL_FLAG_PHYWAKE | RL_FLAG_FASTETHER; break; case RL_HWREV_8102E: case RL_HWREV_8102EL: sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | - RL_FLAG_MACSTAT; + RL_FLAG_MACSTAT | RL_FLAG_FASTETHER; break; case RL_HWREV_8168_SPIN1: case RL_HWREV_8168_SPIN2: @@ -2011,30 +2041,14 @@ re_tick(void *xsc) { struct rl_softc *sc; struct mii_data *mii; - struct ifnet *ifp; sc = xsc; - ifp = sc->rl_ifp; RL_LOCK_ASSERT(sc); - re_watchdog(sc); - mii = device_get_softc(sc->rl_miibus); mii_tick(mii); - if ((sc->rl_flags & RL_FLAG_LINK) != 0) { - if (!(mii->mii_media_status & IFM_ACTIVE)) - sc->rl_flags &= ~RL_FLAG_LINK; - } else { - if (mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->rl_flags |= RL_FLAG_LINK; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - taskqueue_enqueue_fast(taskqueue_fast, - &sc->rl_txtask); - } - } - + re_watchdog(sc); callout_reset(&sc->rl_stat_callout, hz, re_tick, sc); } @@ -2149,11 +2163,6 @@ re_int_task(void *arg, int npending) re_init_locked(sc); } - if (status & RL_ISR_LINKCHG) { - callout_stop(&sc->rl_stat_callout); - re_tick(sc); - } - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask); @@ -2652,14 +2661,15 @@ re_ifmedia_upd(struct ifnet *ifp) { struct rl_softc *sc; struct mii_data *mii; + int error; sc = ifp->if_softc; mii = device_get_softc(sc->rl_miibus); RL_LOCK(sc); - mii_mediachg(mii); + error = mii_mediachg(mii); RL_UNLOCK(sc); - return (0); + return (error); } /* @@ -2814,18 +2824,30 @@ re_ioctl(struct ifnet *ifp, u_long comma static void re_watchdog(struct rl_softc *sc) { + struct ifnet *ifp; RL_LOCK_ASSERT(sc); if (sc->rl_watchdog_timer == 0 || --sc->rl_watchdog_timer != 0) return; - device_printf(sc->rl_dev, "watchdog timeout\n"); - sc->rl_ifp->if_oerrors++; - + ifp = sc->rl_ifp; re_txeof(sc); + if (sc->rl_ldata.rl_tx_free == sc->rl_ldata.rl_tx_desc_cnt) { + if_printf(ifp, "watchdog timeout (missed Tx interrupts) " + "-- recovering\n"); + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask); + return; + } + + if_printf(ifp, "watchdog timeout\n"); + ifp->if_oerrors++; + re_rxeof(sc); re_init_locked(sc); + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask); } /* Modified: stable/7/sys/pci/if_rlreg.h ============================================================================== --- stable/7/sys/pci/if_rlreg.h Mon Feb 9 00:58:16 2009 (r188355) +++ stable/7/sys/pci/if_rlreg.h Mon Feb 9 01:16:36 2009 (r188356) @@ -855,6 +855,7 @@ struct rl_softc { #define RL_FLAG_PAR 0x0020 #define RL_FLAG_DESCV2 0x0040 #define RL_FLAG_MACSTAT 0x0080 +#define RL_FLAG_FASTETHER 0x0100 #define RL_FLAG_LINK 0x8000 }; From yongari at FreeBSD.org Sun Feb 8 17:26:32 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 17:26:50 2009 Subject: svn commit: r188357 - in stable/7/sys: . contrib/pf dev/cxgb dev/re pci Message-ID: <200902090126.n191QVjF040543@svn.freebsd.org> Author: yongari Date: Mon Feb 9 01:26:31 2009 New Revision: 188357 URL: http://svn.freebsd.org/changeset/base/188357 Log: MFC: r185897,185900-185901,185903 r185897: Always put controller into known state before device intialization. While here remove re_reset calls invoked in system error case as controller reset is always done in device initialization. r185900: Newer RealTek controllers requires setting stop request bit to terminate active Tx/Rx operation. r185901: Don't access undocumented register 0x82 on controllers that have no such register. While here clear undocumented PHY register 0x0B for RTL8110S. r185903: Make WOL work on RTL8168B. This controller seems to require explicit command to enable Rx MAC prior to entering D3. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/re/if_re.c stable/7/sys/pci/if_rlreg.h Modified: stable/7/sys/dev/re/if_re.c ============================================================================== --- stable/7/sys/dev/re/if_re.c Mon Feb 9 01:16:36 2009 (r188356) +++ stable/7/sys/dev/re/if_re.c Mon Feb 9 01:26:31 2009 (r188357) @@ -700,7 +700,12 @@ re_reset(struct rl_softc *sc) if (i == RL_TIMEOUT) device_printf(sc->rl_dev, "reset never completed!\n"); - CSR_WRITE_1(sc, 0x82, 1); + if ((sc->rl_flags & RL_FLAG_PHY8169) != 0) + CSR_WRITE_1(sc, 0x82, 1); + if ((sc->rl_flags & RL_FLAG_PHY8110S) != 0) { + CSR_WRITE_1(sc, 0x82, 1); + re_gmii_writereg(sc->rl_dev, 1, 0x0B, 0); + } } #ifdef RE_DIAG @@ -756,7 +761,6 @@ re_diag(struct rl_softc *sc) ifp->if_flags |= IFF_PROMISC; sc->rl_testmode = 1; - re_reset(sc); re_init_locked(sc); sc->rl_flags |= RL_FLAG_LINK; if (sc->rl_type == RL_8169) @@ -1236,6 +1240,9 @@ re_attach(device_t dev) case RL_HWREV_8139CPLUS: sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_FASTETHER; break; + case RL_HWREV_8110S: + sc->rl_flags |= RL_FLAG_PHY8110S; + break; case RL_HWREV_8100E: case RL_HWREV_8101E: sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR | @@ -1245,10 +1252,12 @@ re_attach(device_t dev) case RL_HWREV_8102EL: sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | - RL_FLAG_MACSTAT | RL_FLAG_FASTETHER; + RL_FLAG_MACSTAT | RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP; break; case RL_HWREV_8168_SPIN1: case RL_HWREV_8168_SPIN2: + sc->rl_flags |= RL_FLAG_WOLRXENB; + /* FALLTHROUGH */ case RL_HWREV_8168_SPIN3: sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | RL_FLAG_MACSTAT; @@ -1258,7 +1267,8 @@ re_attach(device_t dev) case RL_HWREV_8168CP: case RL_HWREV_8168D: sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | - RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT; + RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | + RL_FLAG_CMDSTOP; /* * These controllers support jumbo frame but it seems * that enabling it requires touching additional magic @@ -1271,10 +1281,14 @@ re_attach(device_t dev) */ sc->rl_flags |= RL_FLAG_NOJUMBO; break; + case RL_HWREV_8169: + case RL_HWREV_8169S: + sc->rl_flags |= RL_FLAG_PHY8169; + break; case RL_HWREV_8169_8110SB: case RL_HWREV_8169_8110SC: case RL_HWREV_8169_8110SBL: - sc->rl_flags |= RL_FLAG_PHYWAKE; + sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHY8169; break; default: break; @@ -2091,10 +2105,8 @@ re_poll_locked(struct ifnet *ifp, enum p * XXX check behaviour on receiver stalls. */ - if (status & RL_ISR_SYSTEM_ERR) { - re_reset(sc); + if (status & RL_ISR_SYSTEM_ERR) re_init_locked(sc); - } } } #endif /* DEVICE_POLLING */ @@ -2158,10 +2170,8 @@ re_int_task(void *arg, int npending) RL_ISR_TX_ERR|RL_ISR_TX_DESC_UNAVAIL)) re_txeof(sc); - if (status & RL_ISR_SYSTEM_ERR) { - re_reset(sc); + if (status & RL_ISR_SYSTEM_ERR) re_init_locked(sc); - } if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) taskqueue_enqueue_fast(taskqueue_fast, &sc->rl_txtask); @@ -2482,6 +2492,9 @@ re_init_locked(struct rl_softc *sc) */ re_stop(sc); + /* Put controller into known state. */ + re_reset(sc); + /* * Enable C+ RX and TX mode, as well as VLAN stripping and * RX checksum offload. We must configure the C+ register @@ -2870,7 +2883,12 @@ re_stop(struct rl_softc *sc) callout_stop(&sc->rl_stat_callout); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - CSR_WRITE_1(sc, RL_COMMAND, 0x00); + if ((sc->rl_flags & RL_FLAG_CMDSTOP) != 0) + CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_STOPREQ | RL_CMD_TX_ENB | + RL_CMD_RX_ENB); + else + CSR_WRITE_1(sc, RL_COMMAND, 0x00); + DELAY(1000); CSR_WRITE_2(sc, RL_IMR, 0x0000); CSR_WRITE_2(sc, RL_ISR, 0xFFFF); @@ -3000,6 +3018,9 @@ re_setwol(struct rl_softc *sc) return; ifp = sc->rl_ifp; + if ((ifp->if_capenable & IFCAP_WOL) != 0 && + (sc->rl_flags & RL_FLAG_WOLRXENB) != 0) + CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RX_ENB); /* Enable config register write. */ CSR_WRITE_1(sc, RL_EECMD, RL_EE_MODE); Modified: stable/7/sys/pci/if_rlreg.h ============================================================================== --- stable/7/sys/pci/if_rlreg.h Mon Feb 9 01:16:36 2009 (r188356) +++ stable/7/sys/pci/if_rlreg.h Mon Feb 9 01:26:31 2009 (r188357) @@ -308,6 +308,7 @@ #define RL_CMD_TX_ENB 0x0004 #define RL_CMD_RX_ENB 0x0008 #define RL_CMD_RESET 0x0010 +#define RL_CMD_STOPREQ 0x0080 /* * EEPROM control register @@ -856,6 +857,10 @@ struct rl_softc { #define RL_FLAG_DESCV2 0x0040 #define RL_FLAG_MACSTAT 0x0080 #define RL_FLAG_FASTETHER 0x0100 +#define RL_FLAG_CMDSTOP 0x0200 +#define RL_FLAG_PHY8169 0x0400 +#define RL_FLAG_PHY8110S 0x0800 +#define RL_FLAG_WOLRXENB 0x1000 #define RL_FLAG_LINK 0x8000 }; From yongari at FreeBSD.org Sun Feb 8 17:30:15 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 17:30:27 2009 Subject: svn commit: r188358 - in stable/7/sys: . contrib/pf dev/cxgb dev/re pci Message-ID: <200902090130.n191UEnV040656@svn.freebsd.org> Author: yongari Date: Mon Feb 9 01:30:14 2009 New Revision: 188358 URL: http://svn.freebsd.org/changeset/base/188358 Log: MFC r186210: For RTL8168C SPIN2 controllers, make sure to take the controller out of sleep mode prior to accessing to PHY. This should fix device attach failure seen on these controllers. Also enable the sleep mode when device is put into sleep state. PR: kern/123123, kern/123053 Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/re/if_re.c stable/7/sys/pci/if_rlreg.h Modified: stable/7/sys/dev/re/if_re.c ============================================================================== --- stable/7/sys/dev/re/if_re.c Mon Feb 9 01:26:31 2009 (r188357) +++ stable/7/sys/dev/re/if_re.c Mon Feb 9 01:30:14 2009 (r188358) @@ -1262,8 +1262,13 @@ re_attach(device_t dev) sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | RL_FLAG_MACSTAT; break; - case RL_HWREV_8168C: case RL_HWREV_8168C_SPIN2: + sc->rl_flags |= RL_FLAG_MACSLEEP; + /* FALLTHROUGH */ + case RL_HWREV_8168C: + if ((hwrev & 0x00700000) == 0x00200000) + sc->rl_flags |= RL_FLAG_MACSLEEP; + /* FALLTHROUGH */ case RL_HWREV_8168CP: case RL_HWREV_8168D: sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | @@ -1351,6 +1356,16 @@ re_attach(device_t dev) goto fail; } + /* Take controller out of deep sleep mode. */ + if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) { + if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80) + CSR_WRITE_1(sc, RL_GPIO, + CSR_READ_1(sc, RL_GPIO) | 0x01); + else + CSR_WRITE_1(sc, RL_GPIO, + CSR_READ_1(sc, RL_GPIO) & ~0x01); + } + /* Take PHY out of power down mode. */ if ((sc->rl_flags & RL_FLAG_PHYWAKE) != 0) { re_gmii_writereg(dev, 1, 0x1f, 0); @@ -2963,6 +2978,12 @@ re_resume(device_t dev) RL_LOCK(sc); ifp = sc->rl_ifp; + /* Take controller out of sleep mode. */ + if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) { + if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80) + CSR_WRITE_1(sc, RL_GPIO, + CSR_READ_1(sc, RL_GPIO) | 0x01); + } /* reinitialize interface if necessary */ if (ifp->if_flags & IFF_UP) @@ -3018,6 +3039,12 @@ re_setwol(struct rl_softc *sc) return; ifp = sc->rl_ifp; + /* Put controller into sleep mode. */ + if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) { + if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80) + CSR_WRITE_1(sc, RL_GPIO, + CSR_READ_1(sc, RL_GPIO) & ~0x01); + } if ((ifp->if_capenable & IFCAP_WOL) != 0 && (sc->rl_flags & RL_FLAG_WOLRXENB) != 0) CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RX_ENB); Modified: stable/7/sys/pci/if_rlreg.h ============================================================================== --- stable/7/sys/pci/if_rlreg.h Mon Feb 9 01:26:31 2009 (r188357) +++ stable/7/sys/pci/if_rlreg.h Mon Feb 9 01:30:14 2009 (r188358) @@ -131,6 +131,8 @@ #define RL_TBI_ANAR 0x0068 #define RL_TBI_LPAR 0x006A #define RL_GMEDIASTAT 0x006C /* 8 bits */ +#define RL_MACDBG 0x006D /* 8 bits, 8168C SPIN2 only */ +#define RL_GPIO 0x006E /* 8 bits, 8168C SPIN2 only */ #define RL_MAXRXPKTLEN 0x00DA /* 16 bits, chip multiplies by 8 */ #define RL_GTXSTART 0x0038 /* 8 bits */ @@ -861,6 +863,7 @@ struct rl_softc { #define RL_FLAG_PHY8169 0x0400 #define RL_FLAG_PHY8110S 0x0800 #define RL_FLAG_WOLRXENB 0x1000 +#define RL_FLAG_MACSLEEP 0x2000 #define RL_FLAG_LINK 0x8000 }; From yongari at FreeBSD.org Sun Feb 8 17:38:03 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 17:38:14 2009 Subject: svn commit: r188359 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/re pci Message-ID: <200902090138.n191c2R3040859@svn.freebsd.org> Author: yongari Date: Mon Feb 9 01:38:01 2009 New Revision: 188359 URL: http://svn.freebsd.org/changeset/base/188359 Log: MFC r186214,186389,187417 r186214: It seems that RealTek PCIe controllers require an explicit Tx poll command whenever Tx completion interrupt is raised. The Tx poll bit is cleared when all packets waiting to be transferred have been processed. This means the second Tx poll command can be silently ignored as the Tx poll bit could be still active while processing of previous Tx poll command is in progress. To address the issue re(4) used to invoke the Tx poll command in Tx completion handler whenever it detects there are pending packets in TxQ. However that still does not seem to completely eliminate watchdog timeouts seen on RealTek PCIe controllers. To fix the issue kick Tx poll command only after Tx completion interrupt is raised as this would indicate Tx is now idle state such that it can accept new Tx poll command again. While here apply this workaround for PCIe based controllers as other controllers does not seem to have this limitation. r186389: Since we don't request reset for rlphy(4), the link state 'UP' event from mii(4) may not be delivered if valid link was already established. To address the issue, check current link state after driving MII_TICK. This should fix a regression introduced in r185753 on fast ethernet controllers. r187417: Sometimes RTL8168B seems to take long time to access GMII registers in device attach phase. Double GMII register access timeout value to fix the issue. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/re/if_re.c stable/7/sys/pci/if_rlreg.h Modified: stable/7/sys/dev/re/if_re.c ============================================================================== --- stable/7/sys/dev/re/if_re.c Mon Feb 9 01:30:14 2009 (r188358) +++ stable/7/sys/dev/re/if_re.c Mon Feb 9 01:38:01 2009 (r188359) @@ -418,14 +418,14 @@ re_gmii_readreg(device_t dev, int phy, i CSR_WRITE_4(sc, RL_PHYAR, reg << 16); - for (i = 0; i < RL_TIMEOUT; i++) { + for (i = 0; i < RL_PHY_TIMEOUT; i++) { rval = CSR_READ_4(sc, RL_PHYAR); if (rval & RL_PHYAR_BUSY) break; DELAY(100); } - if (i == RL_TIMEOUT) { + if (i == RL_PHY_TIMEOUT) { device_printf(sc->rl_dev, "PHY read failed\n"); return (0); } @@ -445,14 +445,14 @@ re_gmii_writereg(device_t dev, int phy, CSR_WRITE_4(sc, RL_PHYAR, (reg << 16) | (data & RL_PHYAR_PHYDATA) | RL_PHYAR_BUSY); - for (i = 0; i < RL_TIMEOUT; i++) { + for (i = 0; i < RL_PHY_TIMEOUT; i++) { rval = CSR_READ_4(sc, RL_PHYAR); if (!(rval & RL_PHYAR_BUSY)) break; DELAY(100); } - if (i == RL_TIMEOUT) { + if (i == RL_PHY_TIMEOUT) { device_printf(sc->rl_dev, "PHY write failed\n"); return (0); } @@ -1157,6 +1157,7 @@ re_attach(device_t dev) msic = 0; if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { + sc->rl_flags |= RL_FLAG_PCIE; msic = pci_msi_count(dev); if (bootverbose) device_printf(dev, "MSI count : %d\n", msic); @@ -2042,16 +2043,6 @@ re_txeof(struct rl_softc *sc) /* No changes made to the TX ring, so no flush needed */ if (sc->rl_ldata.rl_tx_free != sc->rl_ldata.rl_tx_desc_cnt) { - /* - * Some chips will ignore a second TX request issued - * while an existing transmission is in progress. If - * the transmitter goes idle but there are still - * packets waiting to be sent, we need to restart the - * channel here to flush them out. This only seems to - * be required with the PCIe devices. - */ - CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); - #ifdef RE_TX_MODERATION /* * If not all descriptors have been reaped yet, reload @@ -2077,6 +2068,8 @@ re_tick(void *xsc) mii = device_get_softc(sc->rl_miibus); mii_tick(mii); + if ((sc->rl_flags & RL_FLAG_LINK) == 0) + re_miibus_statchg(sc->rl_dev); re_watchdog(sc); callout_reset(&sc->rl_stat_callout, hz, re_tick, sc); } @@ -2115,6 +2108,9 @@ re_poll_locked(struct ifnet *ifp, enum p return; if (status) CSR_WRITE_2(sc, RL_ISR, status); + if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) && + (sc->rl_flags & RL_FLAG_PCIE)) + CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); /* * XXX check behaviour on receiver stalls. @@ -2176,6 +2172,17 @@ re_int_task(void *arg, int npending) if (status & (RL_ISR_RX_OK|RL_ISR_RX_ERR|RL_ISR_FIFO_OFLOW)) rval = re_rxeof(sc); + /* + * Some chips will ignore a second TX request issued + * while an existing transmission is in progress. If + * the transmitter goes idle but there are still + * packets waiting to be sent, we need to restart the + * channel here to flush them out. This only seems to + * be required with the PCIe devices. + */ + if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) && + (sc->rl_flags & RL_FLAG_PCIE)) + CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); if (status & ( #ifdef RE_TX_MODERATION RL_ISR_TIMEOUT_EXPIRED| Modified: stable/7/sys/pci/if_rlreg.h ============================================================================== --- stable/7/sys/pci/if_rlreg.h Mon Feb 9 01:30:14 2009 (r188358) +++ stable/7/sys/pci/if_rlreg.h Mon Feb 9 01:38:01 2009 (r188359) @@ -864,6 +864,7 @@ struct rl_softc { #define RL_FLAG_PHY8110S 0x0800 #define RL_FLAG_WOLRXENB 0x1000 #define RL_FLAG_MACSLEEP 0x2000 +#define RL_FLAG_PCIE 0x4000 #define RL_FLAG_LINK 0x8000 }; @@ -909,6 +910,7 @@ struct rl_softc { CSR_WRITE_4(sc, offset, CSR_READ_4(sc, offset) & ~(val)) #define RL_TIMEOUT 1000 +#define RL_PHY_TIMEOUT 2000 /* * General constants that are fun to know. From yongari at FreeBSD.org Sun Feb 8 17:55:31 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 17:55:38 2009 Subject: svn commit: r188360 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/msk Message-ID: <200902090155.n191tUuU041233@svn.freebsd.org> Author: yongari Date: Mon Feb 9 01:55:30 2009 New Revision: 188360 URL: http://svn.freebsd.org/changeset/base/188360 Log: MFC r183346 Add another hardware bug workaround for Yukon II controllers that have hardware ram buffer. The silicon bug seem to be triggered by pause frames if receive buffer is not aligned on FIFO word(8 bytes). To workaround the issue, make sure to align Rx buffers on 8 bytes. Unfortunately this workaround requires yet another Rx fixup for strict alignment architecture machines to align IP header. For newer hardwares that lacks ram buffer may not have this bug so check number of available ram buffer size to see the existence of ram buffer. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/msk/if_msk.c stable/7/sys/dev/msk/if_mskreg.h Modified: stable/7/sys/dev/msk/if_msk.c ============================================================================== --- stable/7/sys/dev/msk/if_msk.c Mon Feb 9 01:38:01 2009 (r188359) +++ stable/7/sys/dev/msk/if_msk.c Mon Feb 9 01:55:30 2009 (r188360) @@ -244,6 +244,9 @@ static __inline void msk_rxput(struct ms static int msk_handle_events(struct msk_softc *); static void msk_handle_hwerr(struct msk_if_softc *, uint32_t); static void msk_intr_hwerr(struct msk_softc *); +#ifndef __NO_STRICT_ALIGNMENT +static __inline void msk_fixup_rx(struct mbuf *); +#endif static void msk_rxeof(struct msk_if_softc *, uint32_t, int); static void msk_jumbo_rxeof(struct msk_if_softc *, uint32_t, int); static void msk_txeof(struct msk_if_softc *, int); @@ -783,7 +786,12 @@ msk_newbuf(struct msk_if_softc *sc_if, i return (ENOBUFS); m->m_len = m->m_pkthdr.len = MCLBYTES; - m_adj(m, ETHER_ALIGN); + if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) + m_adj(m, ETHER_ALIGN); +#ifndef __NO_STRICT_ALIGNMENT + else + m_adj(m, MSK_RX_BUF_ALIGN); +#endif if (bus_dmamap_load_mbuf_sg(sc_if->msk_cdata.msk_rx_tag, sc_if->msk_cdata.msk_rx_sparemap, m, segs, &nsegs, @@ -840,7 +848,12 @@ msk_jumbo_newbuf(struct msk_if_softc *sc return (ENOBUFS); } m->m_pkthdr.len = m->m_len = MSK_JLEN; - m_adj(m, ETHER_ALIGN); + if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) + m_adj(m, ETHER_ALIGN); +#ifndef __NO_STRICT_ALIGNMENT + else + m_adj(m, MSK_RX_BUF_ALIGN); +#endif if (bus_dmamap_load_mbuf_sg(sc_if->msk_cdata.msk_jumbo_rx_tag, sc_if->msk_cdata.msk_jumbo_rx_sparemap, m, segs, &nsegs, @@ -1041,14 +1054,16 @@ mskc_setup_rambuffer(struct msk_softc *s { int next; int i; - uint8_t val; /* Get adapter SRAM size. */ - val = CSR_READ_1(sc, B2_E_0); - sc->msk_ramsize = (val == 0) ? 128 : val * 4; + sc->msk_ramsize = CSR_READ_1(sc, B2_E_0) * 4; if (bootverbose) device_printf(sc->msk_dev, "RAM buffer size : %dKB\n", sc->msk_ramsize); + if (sc->msk_ramsize == 0) + return (0); + + sc->msk_pflags |= MSK_FLAG_RAMBUF; /* * Give receiver 2/3 of memory and round down to the multiple * of 1024. Tx/Rx RAM buffer size of Yukon II shoud be multiple @@ -1412,6 +1427,7 @@ msk_attach(device_t dev) sc_if->msk_if_dev = dev; sc_if->msk_port = port; sc_if->msk_softc = sc; + sc_if->msk_flags = sc->msk_pflags; sc->msk_if[port] = sc_if; /* Setup Tx/Rx queue register offsets. */ if (port == MSK_PORT_A) { @@ -1976,6 +1992,7 @@ msk_txrx_dma_alloc(struct msk_if_softc * struct msk_rxdesc *jrxd; struct msk_jpool_entry *entry; uint8_t *ptr; + bus_size_t rxalign; int error, i; mtx_init(&sc_if->msk_jlist_mtx, "msk_jlist_mtx", NULL, MTX_DEF); @@ -2107,9 +2124,16 @@ msk_txrx_dma_alloc(struct msk_if_softc * goto fail; } + rxalign = 1; + /* + * Workaround hardware hang which seems to happen when Rx buffer + * is not aligned on multiple of FIFO word(8 bytes). + */ + if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) != 0) + rxalign = MSK_RX_BUF_ALIGN; /* Create tag for Rx buffers. */ error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ - 1, 0, /* alignment, boundary */ + rxalign, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ @@ -2918,6 +2942,23 @@ mskc_resume(device_t dev) return (0); } +#ifndef __NO_STRICT_ALIGNMENT +static __inline void +msk_fixup_rx(struct mbuf *m) +{ + int i; + uint16_t *src, *dst; + + src = mtod(m, uint16_t *); + dst = src - 3; + + for (i = 0; i < (m->m_len / sizeof(uint16_t) + 1); i++) + *dst++ = *src++; + + m->m_data -= (MSK_RX_BUF_ALIGN - ETHER_ALIGN); +} +#endif + static void msk_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) { @@ -2955,6 +2996,10 @@ msk_rxeof(struct msk_if_softc *sc_if, ui } m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = len; +#ifndef __NO_STRICT_ALIGNMENT + if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) != 0) + msk_fixup_rx(m); +#endif ifp->if_ipackets++; /* Check for VLAN tagged packets. */ if ((status & GMR_FS_VLAN) != 0 && @@ -3008,6 +3053,10 @@ msk_jumbo_rxeof(struct msk_if_softc *sc_ } m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = len; +#ifndef __NO_STRICT_ALIGNMENT + if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) != 0) + msk_fixup_rx(m); +#endif ifp->if_ipackets++; /* Check for VLAN tagged packets. */ if ((status & GMR_FS_VLAN) != 0 && @@ -3677,7 +3726,7 @@ msk_init_locked(struct msk_if_softc *sc_ /* Configure hardware VLAN tag insertion/stripping. */ msk_setvlan(sc_if, ifp); - if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U) { + if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) { /* Set Rx Pause threshould. */ CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_LP_THR), MSK_ECU_LLPP); @@ -3790,6 +3839,8 @@ msk_set_rambuffer(struct msk_if_softc *s int ltpp, utpp; sc = sc_if->msk_softc; + if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) + return; /* Setup Rx Queue. */ CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_RST_CLR); Modified: stable/7/sys/dev/msk/if_mskreg.h ============================================================================== --- stable/7/sys/dev/msk/if_mskreg.h Mon Feb 9 01:38:01 2009 (r188359) +++ stable/7/sys/dev/msk/if_mskreg.h Mon Feb 9 01:55:30 2009 (r188360) @@ -2158,6 +2158,7 @@ struct msk_stat_desc { #define MSK_TX_RING_CNT 256 #define MSK_RX_RING_CNT 256 +#define MSK_RX_BUF_ALIGN 8 #define MSK_JUMBO_RX_RING_CNT MSK_RX_RING_CNT #define MSK_STAT_RING_CNT ((1 + 3) * (MSK_TX_RING_CNT + MSK_RX_RING_CNT)) #define MSK_MAXTXSEGS 32 @@ -2307,6 +2308,7 @@ struct msk_softc { uint32_t msk_coppertype; uint32_t msk_intrmask; uint32_t msk_intrhwemask; + uint32_t msk_pflags; int msk_suspended; int msk_clock; int msk_msi; @@ -2348,6 +2350,8 @@ struct msk_if_softc { int msk_phytype; int msk_phyaddr; int msk_link; + uint32_t msk_flags; +#define MSK_FLAG_RAMBUF 0x0010 struct callout msk_tick_ch; int msk_watchdog_timer; uint32_t msk_txq; /* Tx. Async Queue offset */ From yongari at FreeBSD.org Sun Feb 8 18:00:44 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 18:01:02 2009 Subject: svn commit: r188361 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/msk Message-ID: <200902090200.n1920h4o041404@svn.freebsd.org> Author: yongari Date: Mon Feb 9 02:00:43 2009 New Revision: 188361 URL: http://svn.freebsd.org/changeset/base/188361 Log: MFC r183485-183486 r183485: Always pullup mbuf prior to accessing TCP header. This should fix occasional Tx checksum corruption issue. r183486: If mbuf is not writable get a writable copy before invoking m_pullup(9). Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/msk/if_msk.c Modified: stable/7/sys/dev/msk/if_msk.c ============================================================================== --- stable/7/sys/dev/msk/if_msk.c Mon Feb 9 01:55:30 2009 (r188360) +++ stable/7/sys/dev/msk/if_msk.c Mon Feb 9 02:00:43 2009 (r188361) @@ -2559,7 +2559,16 @@ msk_encap(struct msk_if_softc *sc_if, st struct ip *ip; struct tcphdr *tcp; - /* TODO check for M_WRITABLE(m) */ + if (M_WRITABLE(m) == 0) { + /* Get a writable copy. */ + m = m_dup(*m_head, M_DONTWAIT); + m_freem(*m_head); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + *m_head = m; + } offset = sizeof(struct ether_header); m = m_pullup(m, offset); @@ -2601,6 +2610,11 @@ msk_encap(struct msk_if_softc *sc_if, st (m->m_pkthdr.csum_flags & CSUM_TCP) != 0) { uint16_t csum; + m = m_pullup(m, offset + sizeof(struct tcphdr)); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } csum = in_cksum_skip(m, ntohs(ip->ip_len) + offset - (ip->ip_hl << 2), offset); *(uint16_t *)(m->m_data + offset + From yongari at FreeBSD.org Sun Feb 8 18:03:51 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 18:03:58 2009 Subject: svn commit: r188362 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/msk Message-ID: <200902090203.n1923nXe041508@svn.freebsd.org> Author: yongari Date: Mon Feb 9 02:03:49 2009 New Revision: 188362 URL: http://svn.freebsd.org/changeset/base/188362 Log: MFC r185244 Save the value read from TX queue CSR, so we don't test against a stale one. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/msk/if_msk.c Modified: stable/7/sys/dev/msk/if_msk.c ============================================================================== --- stable/7/sys/dev/msk/if_msk.c Mon Feb 9 02:00:43 2009 (r188361) +++ stable/7/sys/dev/msk/if_msk.c Mon Feb 9 02:03:49 2009 (r188362) @@ -3966,7 +3966,7 @@ msk_stop(struct msk_if_softc *sc_if) if ((val & (BMU_STOP | BMU_IDLE)) == 0) { CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_STOP); - CSR_READ_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR)); + val = CSR_READ_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR)); } else break; DELAY(1); From yongari at FreeBSD.org Sun Feb 8 18:06:16 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 18:06:22 2009 Subject: svn commit: r188363 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/msk Message-ID: <200902090206.n1926Fgg041601@svn.freebsd.org> Author: yongari Date: Mon Feb 9 02:06:15 2009 New Revision: 188363 URL: http://svn.freebsd.org/changeset/base/188363 Log: MFC r187207: Correct frame length argument of in_cksum_skip. While I'm here remove intermediate variable csum. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/msk/if_msk.c Modified: stable/7/sys/dev/msk/if_msk.c ============================================================================== --- stable/7/sys/dev/msk/if_msk.c Mon Feb 9 02:03:49 2009 (r188362) +++ stable/7/sys/dev/msk/if_msk.c Mon Feb 9 02:06:15 2009 (r188363) @@ -2608,17 +2608,14 @@ msk_encap(struct msk_if_softc *sc_if, st */ if (m->m_pkthdr.len < MSK_MIN_FRAMELEN && (m->m_pkthdr.csum_flags & CSUM_TCP) != 0) { - uint16_t csum; - m = m_pullup(m, offset + sizeof(struct tcphdr)); if (m == NULL) { *m_head = NULL; return (ENOBUFS); } - csum = in_cksum_skip(m, ntohs(ip->ip_len) + offset - - (ip->ip_hl << 2), offset); *(uint16_t *)(m->m_data + offset + - m->m_pkthdr.csum_data) = csum; + m->m_pkthdr.csum_data) = in_cksum_skip(m, + m->m_pkthdr.len, offset); m->m_pkthdr.csum_flags &= ~CSUM_TCP; } if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) { From yongari at FreeBSD.org Sun Feb 8 18:15:26 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 18:15:44 2009 Subject: svn commit: r188364 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/msk Message-ID: <200902090215.n192FPXr041828@svn.freebsd.org> Author: yongari Date: Mon Feb 9 02:15:25 2009 New Revision: 188364 URL: http://svn.freebsd.org/changeset/base/188364 Log: MFC r187208: Remove local jumbo locator and switch to UMA backed page allocator for jumbo frame. o Nuke unneeded jlist lock which was used to protect jumbo buffer management in local allocator. o Added a new tunable hw.mskc.jumbo_disable to disable jumbo frame support for the driver. The tunable could be set for systems that do not need to use jumbo frames and it would save (9K * number of Rx descriptors) bytes kernel memory. o Jumbo buffer allocation failure is no longer critical error for the operation of msk(4). If msk(4) encounter the allocation failure it just disables jumbo frame support and continues to work without your intervention. Using local allocator had several drawbacks such as requirement of large amount of continuous kernel memory and fixed (small) number of available buffers. The need for large continuous memory resulted in failure of loading driver with kldload on running systems. Also small number of buffer used in local allocator showed poor performance for some applications. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/msk/if_msk.c stable/7/sys/dev/msk/if_mskreg.h Modified: stable/7/sys/dev/msk/if_msk.c ============================================================================== --- stable/7/sys/dev/msk/if_msk.c Mon Feb 9 02:06:15 2009 (r188363) +++ stable/7/sys/dev/msk/if_msk.c Mon Feb 9 02:15:25 2009 (r188364) @@ -156,6 +156,8 @@ static int msi_disable = 0; TUNABLE_INT("hw.msk.msi_disable", &msi_disable); static int legacy_intr = 0; TUNABLE_INT("hw.msk.legacy_intr", &legacy_intr); +static int jumbo_disable = 0; +TUNABLE_INT("hw.msk.jumbo_disable", &jumbo_disable); #define MSK_CSUM_FEATURES (CSUM_TCP | CSUM_UDP) @@ -267,9 +269,9 @@ static void msk_dmamap_cb(void *, bus_dm static int msk_status_dma_alloc(struct msk_softc *); static void msk_status_dma_free(struct msk_softc *); static int msk_txrx_dma_alloc(struct msk_if_softc *); +static int msk_rx_dma_jalloc(struct msk_if_softc *); static void msk_txrx_dma_free(struct msk_if_softc *); -static void *msk_jalloc(struct msk_if_softc *); -static void msk_jfree(void *, void *); +static void msk_rx_dma_jfree(struct msk_if_softc *); static int msk_init_rx_ring(struct msk_if_softc *); static int msk_init_jumbo_rx_ring(struct msk_if_softc *); static void msk_init_tx_ring(struct msk_if_softc *); @@ -830,24 +832,15 @@ msk_jumbo_newbuf(struct msk_if_softc *sc bus_dma_segment_t segs[1]; bus_dmamap_t map; int nsegs; - void *buf; - MGETHDR(m, M_DONTWAIT, MT_DATA); + m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); if (m == NULL) return (ENOBUFS); - buf = msk_jalloc(sc_if); - if (buf == NULL) { - m_freem(m); - return (ENOBUFS); - } - /* Attach the buffer to the mbuf. */ - MEXTADD(m, buf, MSK_JLEN, msk_jfree, (struct msk_if_softc *)sc_if, 0, - EXT_NET_DRV); if ((m->m_flags & M_EXT) == 0) { m_freem(m); return (ENOBUFS); } - m->m_pkthdr.len = m->m_len = MSK_JLEN; + m->m_len = m->m_pkthdr.len = MJUM9BYTES; if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) m_adj(m, ETHER_ALIGN); #ifndef __NO_STRICT_ALIGNMENT @@ -936,20 +929,20 @@ msk_ioctl(struct ifnet *ifp, u_long comm switch(command) { case SIOCSIFMTU: - if (ifr->ifr_mtu > MSK_JUMBO_MTU || ifr->ifr_mtu < ETHERMIN) { - error = EINVAL; - break; - } - if (sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_FE && - ifr->ifr_mtu > MSK_MAX_FRAMELEN) { + if (ifr->ifr_mtu > MSK_JUMBO_MTU || ifr->ifr_mtu < ETHERMIN) error = EINVAL; - break; + else if (ifp->if_mtu != ifr->ifr_mtu) { + if ((sc_if->msk_flags & MSK_FLAG_NOJUMBO) != 0 && + ifr->ifr_mtu > ETHERMTU) + error = EINVAL; + else { + MSK_IF_LOCK(sc_if); + ifp->if_mtu = ifr->ifr_mtu; + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + msk_init_locked(sc_if); + MSK_IF_UNLOCK(sc_if); + } } - MSK_IF_LOCK(sc_if); - ifp->if_mtu = ifr->ifr_mtu; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) - msk_init_locked(sc_if); - MSK_IF_UNLOCK(sc_if); break; case SIOCSIFFLAGS: MSK_IF_LOCK(sc_if); @@ -1007,7 +1000,7 @@ msk_ioctl(struct ifnet *ifp, u_long comm else ifp->if_hwassist &= ~CSUM_TSO; } - if (sc_if->msk_framesize > MSK_MAX_FRAMELEN && + if (ifp->if_mtu > ETHERMTU && sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_EC_U) { /* * In Yukon EC Ultra, TSO & checksum offload is not @@ -1443,8 +1436,13 @@ msk_attach(device_t dev) callout_init_mtx(&sc_if->msk_tick_ch, &sc_if->msk_softc->msk_mtx, 0); TASK_INIT(&sc_if->msk_link_task, 0, msk_link_task, sc_if); + /* Disable jumbo frame for Yukon FE. */ + if (sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_FE) + sc_if->msk_flags |= MSK_FLAG_NOJUMBO; + if ((error = msk_txrx_dma_alloc(sc_if) != 0)) goto fail; + msk_rx_dma_jalloc(sc_if); ifp = sc_if->msk_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { @@ -1519,9 +1517,6 @@ msk_attach(device_t dev) */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); - sc_if->msk_framesize = ifp->if_mtu + ETHER_HDR_LEN + - ETHER_VLAN_ENCAP_LEN; - /* * Do miibus setup. */ @@ -1829,6 +1824,7 @@ msk_detach(device_t dev) * } */ + msk_rx_dma_jfree(sc_if); msk_txrx_dma_free(sc_if); bus_generic_detach(dev); @@ -1989,16 +1985,9 @@ msk_txrx_dma_alloc(struct msk_if_softc * struct msk_dmamap_arg ctx; struct msk_txdesc *txd; struct msk_rxdesc *rxd; - struct msk_rxdesc *jrxd; - struct msk_jpool_entry *entry; - uint8_t *ptr; bus_size_t rxalign; int error, i; - mtx_init(&sc_if->msk_jlist_mtx, "msk_jlist_mtx", NULL, MTX_DEF); - SLIST_INIT(&sc_if->msk_jfree_listhead); - SLIST_INIT(&sc_if->msk_jinuse_listhead); - /* Create parent DMA tag. */ /* * XXX @@ -2070,42 +2059,6 @@ msk_txrx_dma_alloc(struct msk_if_softc * goto fail; } - /* Create tag for jumbo Rx ring. */ - error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ - MSK_RING_ALIGN, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - MSK_JUMBO_RX_RING_SZ, /* maxsize */ - 1, /* nsegments */ - MSK_JUMBO_RX_RING_SZ, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc_if->msk_cdata.msk_jumbo_rx_ring_tag); - if (error != 0) { - device_printf(sc_if->msk_if_dev, - "failed to create jumbo Rx ring DMA tag\n"); - goto fail; - } - - /* Create tag for jumbo buffer blocks. */ - error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ - PAGE_SIZE, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - MSK_JMEM, /* maxsize */ - 1, /* nsegments */ - MSK_JMEM, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc_if->msk_cdata.msk_jumbo_tag); - if (error != 0) { - device_printf(sc_if->msk_if_dev, - "failed to create jumbo Rx buffer block DMA tag\n"); - goto fail; - } - /* Create tag for Tx buffers. */ error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 1, 0, /* alignment, boundary */ @@ -2149,24 +2102,6 @@ msk_txrx_dma_alloc(struct msk_if_softc * goto fail; } - /* Create tag for jumbo Rx buffers. */ - error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ - PAGE_SIZE, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - MCLBYTES * MSK_MAXRXSEGS, /* maxsize */ - MSK_MAXRXSEGS, /* nsegments */ - MSK_JLEN, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc_if->msk_cdata.msk_jumbo_rx_tag); - if (error != 0) { - device_printf(sc_if->msk_if_dev, - "failed to create jumbo Rx DMA tag\n"); - goto fail; - } - /* Allocate DMA'able memory and load the DMA map for Tx ring. */ error = bus_dmamem_alloc(sc_if->msk_cdata.msk_tx_ring_tag, (void **)&sc_if->msk_rdata.msk_tx_ring, BUS_DMA_WAITOK | @@ -2209,29 +2144,6 @@ msk_txrx_dma_alloc(struct msk_if_softc * } sc_if->msk_rdata.msk_rx_ring_paddr = ctx.msk_busaddr; - /* Allocate DMA'able memory and load the DMA map for jumbo Rx ring. */ - error = bus_dmamem_alloc(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, - (void **)&sc_if->msk_rdata.msk_jumbo_rx_ring, - BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, - &sc_if->msk_cdata.msk_jumbo_rx_ring_map); - if (error != 0) { - device_printf(sc_if->msk_if_dev, - "failed to allocate DMA'able memory for jumbo Rx ring\n"); - goto fail; - } - - ctx.msk_busaddr = 0; - error = bus_dmamap_load(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, - sc_if->msk_cdata.msk_jumbo_rx_ring_map, - sc_if->msk_rdata.msk_jumbo_rx_ring, MSK_JUMBO_RX_RING_SZ, - msk_dmamap_cb, &ctx, 0); - if (error != 0) { - device_printf(sc_if->msk_if_dev, - "failed to load DMA'able memory for jumbo Rx ring\n"); - goto fail; - } - sc_if->msk_rdata.msk_jumbo_rx_ring_paddr = ctx.msk_busaddr; - /* Create DMA maps for Tx buffers. */ for (i = 0; i < MSK_TX_RING_CNT; i++) { txd = &sc_if->msk_cdata.msk_txdesc[i]; @@ -2264,12 +2176,98 @@ msk_txrx_dma_alloc(struct msk_if_softc * goto fail; } } + +fail: + return (error); +} + +static int +msk_rx_dma_jalloc(struct msk_if_softc *sc_if) +{ + struct msk_dmamap_arg ctx; + struct msk_rxdesc *jrxd; + bus_size_t rxalign; + int error, i; + + if (jumbo_disable != 0 || (sc_if->msk_flags & MSK_FLAG_NOJUMBO) != 0) { + sc_if->msk_flags |= MSK_FLAG_NOJUMBO; + device_printf(sc_if->msk_if_dev, + "disabling jumbo frame support\n"); + sc_if->msk_flags |= MSK_FLAG_NOJUMBO; + return (0); + } + /* Create tag for jumbo Rx ring. */ + error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ + MSK_RING_ALIGN, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + MSK_JUMBO_RX_RING_SZ, /* maxsize */ + 1, /* nsegments */ + MSK_JUMBO_RX_RING_SZ, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc_if->msk_cdata.msk_jumbo_rx_ring_tag); + if (error != 0) { + device_printf(sc_if->msk_if_dev, + "failed to create jumbo Rx ring DMA tag\n"); + goto jumbo_fail; + } + + rxalign = 1; + /* + * Workaround hardware hang which seems to happen when Rx buffer + * is not aligned on multiple of FIFO word(8 bytes). + */ + if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) != 0) + rxalign = MSK_RX_BUF_ALIGN; + /* Create tag for jumbo Rx buffers. */ + error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ + rxalign, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + MJUM9BYTES, /* maxsize */ + 1, /* nsegments */ + MJUM9BYTES, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc_if->msk_cdata.msk_jumbo_rx_tag); + if (error != 0) { + device_printf(sc_if->msk_if_dev, + "failed to create jumbo Rx DMA tag\n"); + goto jumbo_fail; + } + + /* Allocate DMA'able memory and load the DMA map for jumbo Rx ring. */ + error = bus_dmamem_alloc(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, + (void **)&sc_if->msk_rdata.msk_jumbo_rx_ring, + BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, + &sc_if->msk_cdata.msk_jumbo_rx_ring_map); + if (error != 0) { + device_printf(sc_if->msk_if_dev, + "failed to allocate DMA'able memory for jumbo Rx ring\n"); + goto jumbo_fail; + } + + ctx.msk_busaddr = 0; + error = bus_dmamap_load(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, + sc_if->msk_cdata.msk_jumbo_rx_ring_map, + sc_if->msk_rdata.msk_jumbo_rx_ring, MSK_JUMBO_RX_RING_SZ, + msk_dmamap_cb, &ctx, 0); + if (error != 0) { + device_printf(sc_if->msk_if_dev, + "failed to load DMA'able memory for jumbo Rx ring\n"); + goto jumbo_fail; + } + sc_if->msk_rdata.msk_jumbo_rx_ring_paddr = ctx.msk_busaddr; + /* Create DMA maps for jumbo Rx buffers. */ if ((error = bus_dmamap_create(sc_if->msk_cdata.msk_jumbo_rx_tag, 0, &sc_if->msk_cdata.msk_jumbo_rx_sparemap)) != 0) { device_printf(sc_if->msk_if_dev, "failed to create spare jumbo Rx dmamap\n"); - goto fail; + goto jumbo_fail; } for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[i]; @@ -2280,54 +2278,17 @@ msk_txrx_dma_alloc(struct msk_if_softc * if (error != 0) { device_printf(sc_if->msk_if_dev, "failed to create jumbo Rx dmamap\n"); - goto fail; + goto jumbo_fail; } } - /* Allocate DMA'able memory and load the DMA map for jumbo buf. */ - error = bus_dmamem_alloc(sc_if->msk_cdata.msk_jumbo_tag, - (void **)&sc_if->msk_rdata.msk_jumbo_buf, - BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, - &sc_if->msk_cdata.msk_jumbo_map); - if (error != 0) { - device_printf(sc_if->msk_if_dev, - "failed to allocate DMA'able memory for jumbo buf\n"); - goto fail; - } - - ctx.msk_busaddr = 0; - error = bus_dmamap_load(sc_if->msk_cdata.msk_jumbo_tag, - sc_if->msk_cdata.msk_jumbo_map, sc_if->msk_rdata.msk_jumbo_buf, - MSK_JMEM, msk_dmamap_cb, &ctx, 0); - if (error != 0) { - device_printf(sc_if->msk_if_dev, - "failed to load DMA'able memory for jumbobuf\n"); - goto fail; - } - sc_if->msk_rdata.msk_jumbo_buf_paddr = ctx.msk_busaddr; - - /* - * Now divide it up into 9K pieces and save the addresses - * in an array. - */ - ptr = sc_if->msk_rdata.msk_jumbo_buf; - for (i = 0; i < MSK_JSLOTS; i++) { - sc_if->msk_cdata.msk_jslots[i] = ptr; - ptr += MSK_JLEN; - entry = malloc(sizeof(struct msk_jpool_entry), - M_DEVBUF, M_WAITOK); - if (entry == NULL) { - device_printf(sc_if->msk_if_dev, - "no memory for jumbo buffers!\n"); - error = ENOMEM; - goto fail; - } - entry->slot = i; - SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, - jpool_entries); - } + return (0); -fail: +jumbo_fail: + msk_rx_dma_jfree(sc_if); + device_printf(sc_if->msk_if_dev, "disabling jumbo frame support " + "due to resource shortage\n"); + sc_if->msk_flags |= MSK_FLAG_NOJUMBO; return (error); } @@ -2336,39 +2297,8 @@ msk_txrx_dma_free(struct msk_if_softc *s { struct msk_txdesc *txd; struct msk_rxdesc *rxd; - struct msk_rxdesc *jrxd; - struct msk_jpool_entry *entry; int i; - MSK_JLIST_LOCK(sc_if); - while ((entry = SLIST_FIRST(&sc_if->msk_jinuse_listhead))) { - device_printf(sc_if->msk_if_dev, - "asked to free buffer that is in use!\n"); - SLIST_REMOVE_HEAD(&sc_if->msk_jinuse_listhead, jpool_entries); - SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, - jpool_entries); - } - - while (!SLIST_EMPTY(&sc_if->msk_jfree_listhead)) { - entry = SLIST_FIRST(&sc_if->msk_jfree_listhead); - SLIST_REMOVE_HEAD(&sc_if->msk_jfree_listhead, jpool_entries); - free(entry, M_DEVBUF); - } - MSK_JLIST_UNLOCK(sc_if); - - /* Destroy jumbo buffer block. */ - if (sc_if->msk_cdata.msk_jumbo_map) - bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_tag, - sc_if->msk_cdata.msk_jumbo_map); - - if (sc_if->msk_rdata.msk_jumbo_buf) { - bus_dmamem_free(sc_if->msk_cdata.msk_jumbo_tag, - sc_if->msk_rdata.msk_jumbo_buf, - sc_if->msk_cdata.msk_jumbo_map); - sc_if->msk_rdata.msk_jumbo_buf = NULL; - sc_if->msk_cdata.msk_jumbo_map = NULL; - } - /* Tx ring. */ if (sc_if->msk_cdata.msk_tx_ring_tag) { if (sc_if->msk_cdata.msk_tx_ring_map) @@ -2399,21 +2329,6 @@ msk_txrx_dma_free(struct msk_if_softc *s bus_dma_tag_destroy(sc_if->msk_cdata.msk_rx_ring_tag); sc_if->msk_cdata.msk_rx_ring_tag = NULL; } - /* Jumbo Rx ring. */ - if (sc_if->msk_cdata.msk_jumbo_rx_ring_tag) { - if (sc_if->msk_cdata.msk_jumbo_rx_ring_map) - bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, - sc_if->msk_cdata.msk_jumbo_rx_ring_map); - if (sc_if->msk_cdata.msk_jumbo_rx_ring_map && - sc_if->msk_rdata.msk_jumbo_rx_ring) - bus_dmamem_free(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, - sc_if->msk_rdata.msk_jumbo_rx_ring, - sc_if->msk_cdata.msk_jumbo_rx_ring_map); - sc_if->msk_rdata.msk_jumbo_rx_ring = NULL; - sc_if->msk_cdata.msk_jumbo_rx_ring_map = NULL; - bus_dma_tag_destroy(sc_if->msk_cdata.msk_jumbo_rx_ring_tag); - sc_if->msk_cdata.msk_jumbo_rx_ring_tag = NULL; - } /* Tx buffers. */ if (sc_if->msk_cdata.msk_tx_tag) { for (i = 0; i < MSK_TX_RING_CNT; i++) { @@ -2445,6 +2360,33 @@ msk_txrx_dma_free(struct msk_if_softc *s bus_dma_tag_destroy(sc_if->msk_cdata.msk_rx_tag); sc_if->msk_cdata.msk_rx_tag = NULL; } + if (sc_if->msk_cdata.msk_parent_tag) { + bus_dma_tag_destroy(sc_if->msk_cdata.msk_parent_tag); + sc_if->msk_cdata.msk_parent_tag = NULL; + } +} + +static void +msk_rx_dma_jfree(struct msk_if_softc *sc_if) +{ + struct msk_rxdesc *jrxd; + int i; + + /* Jumbo Rx ring. */ + if (sc_if->msk_cdata.msk_jumbo_rx_ring_tag) { + if (sc_if->msk_cdata.msk_jumbo_rx_ring_map) + bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, + sc_if->msk_cdata.msk_jumbo_rx_ring_map); + if (sc_if->msk_cdata.msk_jumbo_rx_ring_map && + sc_if->msk_rdata.msk_jumbo_rx_ring) + bus_dmamem_free(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, + sc_if->msk_rdata.msk_jumbo_rx_ring, + sc_if->msk_cdata.msk_jumbo_rx_ring_map); + sc_if->msk_rdata.msk_jumbo_rx_ring = NULL; + sc_if->msk_cdata.msk_jumbo_rx_ring_map = NULL; + bus_dma_tag_destroy(sc_if->msk_cdata.msk_jumbo_rx_ring_tag); + sc_if->msk_cdata.msk_jumbo_rx_ring_tag = NULL; + } /* Jumbo Rx buffers. */ if (sc_if->msk_cdata.msk_jumbo_rx_tag) { for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { @@ -2464,69 +2406,6 @@ msk_txrx_dma_free(struct msk_if_softc *s bus_dma_tag_destroy(sc_if->msk_cdata.msk_jumbo_rx_tag); sc_if->msk_cdata.msk_jumbo_rx_tag = NULL; } - - if (sc_if->msk_cdata.msk_parent_tag) { - bus_dma_tag_destroy(sc_if->msk_cdata.msk_parent_tag); - sc_if->msk_cdata.msk_parent_tag = NULL; - } - mtx_destroy(&sc_if->msk_jlist_mtx); -} - -/* - * Allocate a jumbo buffer. - */ -static void * -msk_jalloc(struct msk_if_softc *sc_if) -{ - struct msk_jpool_entry *entry; - - MSK_JLIST_LOCK(sc_if); - - entry = SLIST_FIRST(&sc_if->msk_jfree_listhead); - - if (entry == NULL) { - MSK_JLIST_UNLOCK(sc_if); - return (NULL); - } - - SLIST_REMOVE_HEAD(&sc_if->msk_jfree_listhead, jpool_entries); - SLIST_INSERT_HEAD(&sc_if->msk_jinuse_listhead, entry, jpool_entries); - - MSK_JLIST_UNLOCK(sc_if); - - return (sc_if->msk_cdata.msk_jslots[entry->slot]); -} - -/* - * Release a jumbo buffer. - */ -static void -msk_jfree(void *buf, void *args) -{ - struct msk_if_softc *sc_if; - struct msk_jpool_entry *entry; - int i; - - /* Extract the softc struct pointer. */ - sc_if = (struct msk_if_softc *)args; - KASSERT(sc_if != NULL, ("%s: can't find softc pointer!", __func__)); - - MSK_JLIST_LOCK(sc_if); - /* Calculate the slot this buffer belongs to. */ - i = ((vm_offset_t)buf - - (vm_offset_t)sc_if->msk_rdata.msk_jumbo_buf) / MSK_JLEN; - KASSERT(i >= 0 && i < MSK_JSLOTS, - ("%s: asked to free buffer that we don't manage!", __func__)); - - entry = SLIST_FIRST(&sc_if->msk_jinuse_listhead); - KASSERT(entry != NULL, ("%s: buffer not in use!", __func__)); - entry->slot = i; - SLIST_REMOVE_HEAD(&sc_if->msk_jinuse_listhead, jpool_entries); - SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, jpool_entries); - if (SLIST_EMPTY(&sc_if->msk_jinuse_listhead)) - wakeup(sc_if); - - MSK_JLIST_UNLOCK(sc_if); } static int @@ -3328,7 +3207,7 @@ msk_rxput(struct msk_if_softc *sc_if) struct msk_softc *sc; sc = sc_if->msk_softc; - if (sc_if->msk_framesize >(MCLBYTES - ETHER_HDR_LEN)) + if (sc_if->msk_framesize > (MCLBYTES - MSK_RX_BUF_ALIGN)) bus_dmamap_sync( sc_if->msk_cdata.msk_jumbo_rx_ring_tag, sc_if->msk_cdata.msk_jumbo_rx_ring_map, @@ -3395,7 +3274,8 @@ msk_handle_events(struct msk_softc *sc) sc_if->msk_vtag = ntohs(len); break; case OP_RXSTAT: - if (sc_if->msk_framesize > (MCLBYTES - ETHER_HDR_LEN)) + if (sc_if->msk_framesize > + (MCLBYTES - MSK_RX_BUF_ALIGN)) msk_jumbo_rxeof(sc_if, status, len); else msk_rxeof(sc_if, status, len); @@ -3633,9 +3513,12 @@ msk_init_locked(struct msk_if_softc *sc_ /* Cancel pending I/O and free all Rx/Tx buffers. */ msk_stop(sc_if); - sc_if->msk_framesize = ifp->if_mtu + ETHER_HDR_LEN + - ETHER_VLAN_ENCAP_LEN; - if (sc_if->msk_framesize > MSK_MAX_FRAMELEN && + if (ifp->if_mtu < ETHERMTU) + sc_if->msk_framesize = ETHERMTU; + else + sc_if->msk_framesize = ifp->if_mtu; + sc_if->msk_framesize += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; + if (ifp->if_mtu > ETHERMTU && sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_EC_U) { /* * In Yukon EC Ultra, TSO & checksum offload is not @@ -3688,7 +3571,7 @@ msk_init_locked(struct msk_if_softc *sc_ gmac = DATA_BLIND_VAL(DATA_BLIND_DEF) | GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); - if (sc_if->msk_framesize > MSK_MAX_FRAMELEN) + if (ifp->if_mtu > ETHERMTU) gmac |= GM_SMOD_JUMBO_ENA; GMAC_WRITE_2(sc, sc_if->msk_port, GM_SERIAL_MODE, gmac); @@ -3743,7 +3626,7 @@ msk_init_locked(struct msk_if_softc *sc_ MSK_ECU_LLPP); CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_UP_THR), MSK_ECU_ULPP); - if (sc_if->msk_framesize > MSK_MAX_FRAMELEN) { + if (ifp->if_mtu > ETHERMTU) { /* * Set Tx GMAC FIFO Almost Empty Threshold. */ @@ -3803,7 +3686,7 @@ msk_init_locked(struct msk_if_softc *sc_ /* Disable Rx checksum offload and RSS hash. */ CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_DIS_RX_CHKSUM | BMU_DIS_RX_RSS_HASH); - if (sc_if->msk_framesize > (MCLBYTES - ETHER_HDR_LEN)) { + if (sc_if->msk_framesize > (MCLBYTES - MSK_RX_BUF_ALIGN)) { msk_set_prefetch(sc, sc_if->msk_rxq, sc_if->msk_rdata.msk_jumbo_rx_ring_paddr, MSK_JUMBO_RX_RING_CNT - 1); Modified: stable/7/sys/dev/msk/if_mskreg.h ============================================================================== --- stable/7/sys/dev/msk/if_mskreg.h Mon Feb 9 02:06:15 2009 (r188363) +++ stable/7/sys/dev/msk/if_mskreg.h Mon Feb 9 02:15:25 2009 (r188364) @@ -2164,7 +2164,6 @@ struct msk_stat_desc { #define MSK_MAXTXSEGS 32 #define MSK_TSO_MAXSGSIZE 4096 #define MSK_TSO_MAXSIZE (65535 + sizeof(struct ether_vlan_header)) -#define MSK_MAXRXSEGS 32 /* * It seems that the hardware requires extra decriptors(LEs) to offload @@ -2191,20 +2190,6 @@ struct msk_stat_desc { #define MSK_MAX_FRAMELEN \ (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN - ETHER_CRC_LEN) #define MSK_MIN_FRAMELEN (ETHER_MIN_LEN - ETHER_CRC_LEN) -#define MSK_JSLOTS ((MSK_RX_RING_CNT * 3) / 2) - -#define MSK_JRAWLEN (MSK_JUMBO_FRAMELEN + ETHER_ALIGN) -#define MSK_JLEN (MSK_JRAWLEN + (sizeof(uint64_t) - \ - (MSK_JRAWLEN % sizeof(uint64_t)))) -#define MSK_JPAGESZ PAGE_SIZE -#define MSK_RESID \ - (MSK_JPAGESZ - (MSK_JLEN * MSK_JSLOTS) % MSK_JPAGESZ) -#define MSK_JMEM ((MSK_JLEN * MSK_JSLOTS) + MSK_RESID) - -struct msk_jpool_entry { - int slot; - SLIST_ENTRY(msk_jpool_entry) jpool_entries; -}; struct msk_txdesc { struct mbuf *tx_m; @@ -2230,10 +2215,6 @@ struct msk_chain_data { bus_dmamap_t msk_rx_ring_map; bus_dmamap_t msk_rx_sparemap; bus_dma_tag_t msk_jumbo_rx_tag; - bus_dma_tag_t msk_jumbo_tag; - bus_dmamap_t msk_jumbo_map; - bus_dma_tag_t msk_jumbo_mtag; - caddr_t msk_jslots[MSK_JSLOTS]; struct msk_rxdesc msk_jumbo_rxdesc[MSK_JUMBO_RX_RING_CNT]; bus_dma_tag_t msk_jumbo_rx_ring_tag; bus_dmamap_t msk_jumbo_rx_ring_map; @@ -2255,8 +2236,6 @@ struct msk_ring_data { bus_addr_t msk_rx_ring_paddr; struct msk_rx_desc *msk_jumbo_rx_ring; bus_addr_t msk_jumbo_rx_ring_paddr; - void *msk_jumbo_buf; - bus_addr_t msk_jumbo_buf_paddr; }; #define MSK_TX_RING_ADDR(sc, i) \ @@ -2352,6 +2331,7 @@ struct msk_if_softc { int msk_link; uint32_t msk_flags; #define MSK_FLAG_RAMBUF 0x0010 +#define MSK_FLAG_NOJUMBO 0x0020 struct callout msk_tick_ch; int msk_watchdog_timer; uint32_t msk_txq; /* Tx. Async Queue offset */ @@ -2365,14 +2345,8 @@ struct msk_if_softc { int msk_if_flags; int msk_detach; uint16_t msk_vtag; /* VLAN tag id. */ - SLIST_HEAD(__msk_jfreehead, msk_jpool_entry) msk_jfree_listhead; - SLIST_HEAD(__msk_jinusehead, msk_jpool_entry) msk_jinuse_listhead; - struct mtx msk_jlist_mtx; }; -#define MSK_JLIST_LOCK(_sc) mtx_lock(&(_sc)->msk_jlist_mtx) -#define MSK_JLIST_UNLOCK(_sc) mtx_unlock(&(_sc)->msk_jlist_mtx) - #define MSK_TIMEOUT 1000 #define MSK_PHY_POWERUP 1 #define MSK_PHY_POWERDOWN 0 From yongari at FreeBSD.org Sun Feb 8 19:23:01 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:23:08 2009 Subject: svn commit: r188365 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090323.n193N0nL043386@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:23:00 2009 New Revision: 188365 URL: http://svn.freebsd.org/changeset/base/188365 Log: MFC r177507(cvs if_fxp.c, 1.267): Reuse the mbuf that was just retrieved from the receive ring if mbuf exhaustion is encountered. There was a fix made previously for this problem but the solution (breaking out of the receive loop) does not seem to work. mbuf reuse strategy is already adopted by other drivers such as if_bge. The problem was recreated and the patch is also verified in the same test environment. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 02:15:25 2009 (r188364) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:23:00 2009 (r188365) @@ -231,7 +231,7 @@ static int fxp_ioctl(struct ifnet *ifp, caddr_t data); static void fxp_watchdog(struct fxp_softc *sc); static int fxp_add_rfabuf(struct fxp_softc *sc, - struct fxp_rx *rxp); + struct fxp_rx *rxp, struct mbuf *oldm); static int fxp_mc_addrs(struct fxp_softc *sc); static void fxp_mc_setup(struct fxp_softc *sc); static uint16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset, @@ -715,7 +715,7 @@ fxp_attach(device_t dev) device_printf(dev, "can't create DMA map for RX\n"); goto fail; } - if (fxp_add_rfabuf(sc, rxp) != 0) { + if (fxp_add_rfabuf(sc, rxp, NULL) != 0) { error = ENOMEM; goto fail; } @@ -1652,7 +1652,7 @@ fxp_intr_body(struct fxp_softc *sc, stru * If this fails, the old buffer is recycled * instead. */ - fxp_rc = fxp_add_rfabuf(sc, rxp); + fxp_rc = fxp_add_rfabuf(sc, rxp, m); if (fxp_rc == 0) { int total_len; @@ -2245,17 +2245,26 @@ fxp_ifmedia_sts(struct ifnet *ifp, struc * data pointer is fixed up to point just past it. */ static int -fxp_add_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp) +fxp_add_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp, struct mbuf *oldm) { struct mbuf *m; struct fxp_rfa *rfa, *p_rfa; struct fxp_rx *p_rx; bus_dmamap_t tmp_map; - int error; + int error, reused_mbuf=0; m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) - return (ENOBUFS); + if (m == NULL) { + if (oldm == NULL) + return ENOBUFS; + m = oldm; + m->m_data = m->m_ext.ext_buf; + /* + * return error so the receive loop will + * not pass the packet to upper layer + */ + reused_mbuf = EAGAIN; + } /* * Move the data pointer up so that the incoming data packet @@ -2320,7 +2329,7 @@ fxp_add_rfabuf(struct fxp_softc *sc, str sc->fxp_desc.rx_head = rxp; } sc->fxp_desc.rx_tail = rxp; - return (0); + return (reused_mbuf); } static int From yongari at FreeBSD.org Sun Feb 8 19:28:58 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:29:11 2009 Subject: svn commit: r188366 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090328.n193SvUE043552@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:28:57 2009 New Revision: 188366 URL: http://svn.freebsd.org/changeset/base/188366 Log: MFC r185269,185271-185272 r185269: Whitespace fix. r185271: Sort head files and removed ununsed header file. r185272: Make fxp(4) build with FXP_IP_CSUM_WAR. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c stable/7/sys/dev/fxp/if_fxpreg.h stable/7/sys/dev/fxp/if_fxpvar.h Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:23:00 2009 (r188365) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:28:57 2009 (r188366) @@ -40,32 +40,28 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include -#include - /* #include */ #include +#include #include +#include #include +#include #include +#include +#include #include +#include #include #include +#include +#include -#include -#include -#include #include -#include #include -#include -#include - - -#include -#include - #ifdef FXP_IP_CSUM_WAR #include #include @@ -526,7 +522,7 @@ fxp_attach(device_t dev) * Systems based on the ICH2/ICH2-M chip from Intel, and possibly * some systems based a normal 82559 design, have a defect where * the chip can cause a PCI protocol violation if it receives - * a CU_RESUME command when it is entering the IDLE state. The + * a CU_RESUME command when it is entering the IDLE state. The * workaround is to disable Dynamic Standby Mode, so the chip never * deasserts CLKRUN#, and always remains in an active state. * @@ -805,7 +801,7 @@ fxp_attach(device_t dev) ifp->if_snd.ifq_drv_maxlen = FXP_NTXCB - 1; IFQ_SET_READY(&ifp->if_snd); - /* + /* * Hook our interrupt after all initialization is complete. */ error = bus_setup_intr(dev, sc->fxp_res[1], INTR_TYPE_NET | INTR_MPSAFE, @@ -899,7 +895,7 @@ fxp_detach(device_t dev) struct fxp_softc *sc = device_get_softc(dev); #ifdef DEVICE_POLLING - if (sc->ifp->if_capenable & IFCAP_POLLING) + if (sc->ifp->if_capenable & IFCAP_POLLING) ether_poll_deregister(sc->ifp); #endif @@ -964,7 +960,7 @@ fxp_suspend(device_t dev) FXP_LOCK(sc); fxp_stop(sc); - + sc->suspended = 1; FXP_UNLOCK(sc); @@ -996,7 +992,7 @@ fxp_resume(device_t dev) return (0); } -static void +static void fxp_eeprom_shiftin(struct fxp_softc *sc, int data, int length) { uint16_t reg; @@ -1185,7 +1181,7 @@ fxp_start(struct ifnet *ifp) } /* - * Start packet transmission on the interface. + * Start packet transmission on the interface. * This routine must be called with the softc lock held, and is an * internal entry point only. */ @@ -1319,8 +1315,8 @@ fxp_encap(struct fxp_softc *sc, struct m if (m_head->m_pkthdr.len < 38) { struct ip *ip; m_head->m_data += ETHER_HDR_LEN; - ip = mtod(mb_head, struct ip *); - ip->ip_sum = in_cksum(mb_head, ip->ip_hl << 2); + ip = mtod(m_head, struct ip *); + ip->ip_sum = in_cksum(m_head, ip->ip_hl << 2); m_head->m_data -= ETHER_HDR_LEN; } else { txp->tx_cb->ipcb_ip_activation_high = @@ -1511,10 +1507,10 @@ fxp_intr(void *xsc) while ((statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) { /* * It should not be possible to have all bits set; the - * FXP_SCB_INTR_SWI bit always returns 0 on a read. If + * FXP_SCB_INTR_SWI bit always returns 0 on a read. If * all bits are set, this may indicate that the card has * been physically ejected, so ignore it. - */ + */ if (statack == 0xff) { FXP_UNLOCK(sc); return; @@ -1770,7 +1766,7 @@ fxp_tick(void *xsc) * with external storage to be released in a timely manner rather * than being defered for a potentially long time. This limits * the delay to a maximum of one second. - */ + */ fxp_txeof(sc); /* @@ -2203,11 +2199,11 @@ fxp_ifmedia_upd(struct ifnet *ifp) mii = device_get_softc(sc->miibus); FXP_LOCK(sc); - if (mii->mii_instance) { - struct mii_softc *miisc; - LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); - } + if (mii->mii_instance) { + struct mii_softc *miisc; + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) + mii_phy_reset(miisc); + } mii_mediachg(mii); FXP_UNLOCK(sc); return (0); @@ -2260,7 +2256,7 @@ fxp_add_rfabuf(struct fxp_softc *sc, str m = oldm; m->m_data = m->m_ext.ext_buf; /* - * return error so the receive loop will + * return error so the receive loop will * not pass the packet to upper layer */ reused_mbuf = EAGAIN; @@ -2688,7 +2684,7 @@ fxp_load_ucode(struct fxp_softc *sc) bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_POSTWRITE); device_printf(sc->dev, "Microcode loaded, int_delay: %d usec bundle_max: %d\n", - sc->tunable_int_delay, + sc->tunable_int_delay, uc->bundle_max_offset == 0 ? 0 : sc->tunable_bundle_max); sc->flags |= FXP_FLAG_UCODE; } @@ -2710,7 +2706,7 @@ sysctl_int_range(SYSCTL_HANDLER_ARGS, in /* * Interrupt delay is expressed in microseconds, a multiplier is used - * to convert this to the appropriate clock ticks before using. + * to convert this to the appropriate clock ticks before using. */ static int sysctl_hw_fxp_int_delay(SYSCTL_HANDLER_ARGS) Modified: stable/7/sys/dev/fxp/if_fxpreg.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:23:00 2009 (r188365) +++ stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:28:57 2009 (r188366) @@ -287,7 +287,7 @@ struct fxp_cb_tx { /* * The following structure isn't actually part of the TxCB, * unless the extended TxCB feature is being used. In this - * case, the first two elements of the structure below are + * case, the first two elements of the structure below are * fetched along with the TxCB. */ union { @@ -420,7 +420,7 @@ struct fxp_stats { }; #define FXP_STATS_DUMP_COMPLETE 0xa005 #define FXP_STATS_DR_COMPLETE 0xa007 - + /* * Serial EEPROM control register bits */ Modified: stable/7/sys/dev/fxp/if_fxpvar.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:23:00 2009 (r188365) +++ stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:28:57 2009 (r188366) @@ -1,13 +1,13 @@ /*- * Copyright (c) 1995, David Greenman * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions - * are met: + * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following - * disclaimer. + * 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. @@ -86,16 +86,16 @@ /* * Default maximum time, in microseconds, that an interrupt may be delayed - * in an attempt to coalesce interrupts. This is only effective if the Intel + * in an attempt to coalesce interrupts. This is only effective if the Intel * microcode is loaded, and may be changed via either loader tunables or * sysctl. See also the CPUSAVER_DWORD entry in rcvbundl.h. */ #define TUNABLE_INT_DELAY 1000 /* - * Default number of packets that will be bundled, before an interrupt is + * Default number of packets that will be bundled, before an interrupt is * generated. This is only effective if the Intel microcode is loaded, and - * may be changed via either loader tunables or sysctl. This may not be + * may be changed via either loader tunables or sysctl. This may not be * present in all microcode revisions, see also the CPUSAVER_BUNDLE_MAX_DWORD * entry in rcvbundl.h. */ From kientzle at FreeBSD.org Sun Feb 8 19:31:54 2009 From: kientzle at FreeBSD.org (Tim Kientzle) Date: Sun Feb 8 19:32:00 2009 Subject: svn commit: r188367 - in stable/7/lib/libarchive: . test Message-ID: <200902090331.n193VrEu043656@svn.freebsd.org> Author: kientzle Date: Mon Feb 9 03:31:53 2009 New Revision: 188367 URL: http://svn.freebsd.org/changeset/base/188367 Log: MFC r187704: Fix ARCHIVE_EXTRACT_SPARSE handling in libarchive. Add a test to exercise this feature. This should fix --sparse/-S support in tar. Thanks to: Daichi GOTO Added: stable/7/lib/libarchive/test/test_write_disk_sparse.c - copied unchanged from r187704, head/lib/libarchive/test/test_write_disk_sparse.c Modified: stable/7/lib/libarchive/ (props changed) stable/7/lib/libarchive/archive_write_disk.c stable/7/lib/libarchive/test/Makefile Modified: stable/7/lib/libarchive/archive_write_disk.c ============================================================================== --- stable/7/lib/libarchive/archive_write_disk.c Mon Feb 9 03:28:57 2009 (r188366) +++ stable/7/lib/libarchive/archive_write_disk.c Mon Feb 9 03:31:53 2009 (r188367) @@ -176,6 +176,8 @@ struct archive_write_disk { int fd; /* Current offset for writing data to the file. */ off_t offset; + /* Last offset actually written to disk. */ + off_t fd_offset; /* Maximum size of file, -1 if unknown. */ off_t filesize; /* Dir we were in before this restore; only for deep paths. */ @@ -185,8 +187,6 @@ struct archive_write_disk { /* UID/GID to use in restoring this entry. */ uid_t uid; gid_t gid; - /* Last offset written to disk. */ - off_t last_offset; }; /* @@ -232,7 +232,7 @@ static struct fixup_entry *sort_dir_list static gid_t trivial_lookup_gid(void *, const char *, gid_t); static uid_t trivial_lookup_uid(void *, const char *, uid_t); static ssize_t write_data_block(struct archive_write_disk *, - const char *, size_t, off_t); + const char *, size_t); static struct archive_vtable *archive_write_disk_vtable(void); @@ -334,7 +334,7 @@ _archive_write_header(struct archive *_a } a->entry = archive_entry_clone(entry); a->fd = -1; - a->last_offset = 0; + a->fd_offset = 0; a->offset = 0; a->uid = a->user_uid; a->mode = archive_entry_mode(a->entry); @@ -500,9 +500,9 @@ archive_write_disk_set_skip_file(struct } static ssize_t -write_data_block(struct archive_write_disk *a, - const char *buff, size_t size, off_t offset) +write_data_block(struct archive_write_disk *a, const char *buff, size_t size) { + uint64_t start_size = size; ssize_t bytes_written = 0; ssize_t block_size = 0, bytes_to_write; int r; @@ -519,8 +519,9 @@ write_data_block(struct archive_write_di block_size = a->pst->st_blksize; } - if (a->filesize >= 0 && (off_t)(offset + size) > a->filesize) - size = (size_t)(a->filesize - offset); + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (off_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); /* Write the data. */ while (size > 0) { @@ -536,7 +537,7 @@ write_data_block(struct archive_write_di if (*p != '\0') break; } - offset += p - buff; + a->offset += p - buff; size -= p - buff; buff = p; if (size == 0) @@ -544,22 +545,25 @@ write_data_block(struct archive_write_di /* Calculate next block boundary after offset. */ block_end - = (offset / block_size) * block_size + block_size; + = (a->offset / block_size + 1) * block_size; /* If the adjusted write would cross block boundary, * truncate it to the block boundary. */ bytes_to_write = size; - if (offset + bytes_to_write > block_end) - bytes_to_write = block_end - offset; + if (a->offset + bytes_to_write > block_end) + bytes_to_write = block_end - a->offset; } /* Seek if necessary to the specified offset. */ - if (offset != a->last_offset) { - if (lseek(a->fd, offset, SEEK_SET) < 0) { + if (a->offset != a->fd_offset) { + if (lseek(a->fd, a->offset, SEEK_SET) < 0) { archive_set_error(&a->archive, errno, "Seek failed"); return (ARCHIVE_FATAL); } + a->fd_offset = a->offset; + a->archive.file_position = a->offset; + a->archive.raw_position = a->offset; } bytes_written = write(a->fd, buff, bytes_to_write); if (bytes_written < 0) { @@ -568,12 +572,12 @@ write_data_block(struct archive_write_di } buff += bytes_written; size -= bytes_written; - offset += bytes_written; + a->offset += bytes_written; a->archive.file_position += bytes_written; a->archive.raw_position += bytes_written; - a->last_offset = a->offset = offset; + a->fd_offset = a->offset; } - return (bytes_written); + return (start_size - size); } static ssize_t @@ -586,9 +590,9 @@ _archive_write_data_block(struct archive __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, ARCHIVE_STATE_DATA, "archive_write_disk_block"); - r = write_data_block(a, buff, size, offset); - - if (r < 0) + a->offset = offset; + r = write_data_block(a, buff, size); + if (r < ARCHIVE_OK) return (r); if ((size_t)r < size) { archive_set_error(&a->archive, 0, @@ -606,7 +610,7 @@ _archive_write_data(struct archive *_a, __archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, ARCHIVE_STATE_DATA, "archive_write_data"); - return (write_data_block(a, buff, size, a->offset)); + return (write_data_block(a, buff, size)); } static int @@ -627,7 +631,7 @@ _archive_write_finish_entry(struct archi /* There's no file. */ } else if (a->filesize < 0) { /* File size is unknown, so we can't set the size. */ - } else if (a->last_offset == a->filesize) { + } else if (a->fd_offset == a->filesize) { /* Last write ended at exactly the filesize; we're done. */ /* Hopefully, this is the common case. */ } else { Modified: stable/7/lib/libarchive/test/Makefile ============================================================================== --- stable/7/lib/libarchive/test/Makefile Mon Feb 9 03:28:57 2009 (r188366) +++ stable/7/lib/libarchive/test/Makefile Mon Feb 9 03:31:53 2009 (r188367) @@ -58,6 +58,7 @@ TESTS= \ test_write_disk_hardlink.c \ test_write_disk_perms.c \ test_write_disk_secure.c \ + test_write_disk_sparse.c \ test_write_format_ar.c \ test_write_format_cpio.c \ test_write_format_cpio_empty.c \ Copied: stable/7/lib/libarchive/test/test_write_disk_sparse.c (from r187704, head/lib/libarchive/test/test_write_disk_sparse.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/7/lib/libarchive/test/test_write_disk_sparse.c Mon Feb 9 03:31:53 2009 (r188367, copy of r187704, head/lib/libarchive/test/test_write_disk_sparse.c) @@ -0,0 +1,278 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * 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(S) ``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(S) 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 "test.h" +__FBSDID("$FreeBSD$"); + +/* + * Write a file using archive_write_data call, read the file + * back and verify the contents. The data written includes large + * blocks of nulls, so it should exercise the sparsification logic + * if ARCHIVE_EXTRACT_SPARSE is enabled. + */ +static void +verify_write_data(struct archive *a, int sparse) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct stat st; + struct archive_entry *ae; + size_t buff_size = 64 * 1024; + char *buff, *p; + const char *msg = sparse ? "sparse" : "non-sparse"; + int fd; + + buff = malloc(buff_size); + assert(buff != NULL); + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_size(ae, 8 * buff_size); + archive_entry_set_pathname(ae, "test_write_data"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualIntA(a, 0, archive_write_header(a, ae)); + + /* Use archive_write_data() to write three relatively sparse blocks. */ + + /* First has non-null data at beginning. */ + memset(buff, 0, buff_size); + memcpy(buff, data, sizeof(data)); + failure("%s", msg); + assertEqualInt(buff_size, archive_write_data(a, buff, buff_size)); + + /* Second has non-null data in the middle. */ + memset(buff, 0, buff_size); + memcpy(buff + buff_size / 2 - 3, data, sizeof(data)); + failure("%s", msg); + assertEqualInt(buff_size, archive_write_data(a, buff, buff_size)); + + /* Third has non-null data at the end. */ + memset(buff, 0, buff_size); + memcpy(buff + buff_size - sizeof(data), data, sizeof(data)); + failure("%s", msg); + assertEqualInt(buff_size, archive_write_data(a, buff, buff_size)); + + failure("%s", msg); + assertEqualIntA(a, 0, archive_write_finish_entry(a)); + + /* Test the entry on disk. */ + assert(0 == stat(archive_entry_pathname(ae), &st)); + assertEqualInt(st.st_size, 8 * buff_size); + fd = open(archive_entry_pathname(ae), O_RDONLY); + if (!assert(fd >= 0)) + return; + + /* Check first block. */ + assertEqualInt(buff_size, read(fd, buff, buff_size)); + failure("%s", msg); + assertEqualMem(buff, data, sizeof(data)); + for (p = buff + sizeof(data); p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check second block. */ + assertEqualInt(buff_size, read(fd, buff, buff_size)); + for (p = buff; p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (p == buff + buff_size / 2 - 3) { + assertEqualMem(p, data, sizeof(data)); + p += sizeof(data); + } else if (!assertEqualInt(0, *p)) + break; + } + + /* Check third block. */ + assertEqualInt(buff_size, read(fd, buff, buff_size)); + for (p = buff; p < buff + buff_size - sizeof(data); ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + failure("%s", msg); + assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data)); + + /* XXX more XXX */ + + assertEqualInt(0, close(fd)); + free(buff); +} + +/* + * As above, but using the archive_write_data_block() call. + */ +static void +verify_write_data_block(struct archive *a, int sparse) +{ + static const char data[]="abcdefghijklmnopqrstuvwxyz"; + struct stat st; + struct archive_entry *ae; + size_t buff_size = 64 * 1024; + char *buff, *p; + const char *msg = sparse ? "sparse" : "non-sparse"; + int fd; + + buff = malloc(buff_size); + assert(buff != NULL); + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_size(ae, 8 * buff_size); + archive_entry_set_pathname(ae, "test_write_data_block"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualIntA(a, 0, archive_write_header(a, ae)); + + /* Use archive_write_data_block() to write three + relatively sparse blocks. */ + + /* First has non-null data at beginning. */ + memset(buff, 0, buff_size); + memcpy(buff, data, sizeof(data)); + failure("%s", msg); + assertEqualInt(ARCHIVE_OK, + archive_write_data_block(a, buff, buff_size, 100)); + + /* Second has non-null data in the middle. */ + memset(buff, 0, buff_size); + memcpy(buff + buff_size / 2 - 3, data, sizeof(data)); + failure("%s", msg); + assertEqualInt(ARCHIVE_OK, + archive_write_data_block(a, buff, buff_size, buff_size + 200)); + + /* Third has non-null data at the end. */ + memset(buff, 0, buff_size); + memcpy(buff + buff_size - sizeof(data), data, sizeof(data)); + failure("%s", msg); + assertEqualInt(ARCHIVE_OK, + archive_write_data_block(a, buff, buff_size, buff_size * 2 + 300)); + + failure("%s", msg); + assertEqualIntA(a, 0, archive_write_finish_entry(a)); + + /* Test the entry on disk. */ + assert(0 == stat(archive_entry_pathname(ae), &st)); + assertEqualInt(st.st_size, 8 * buff_size); + fd = open(archive_entry_pathname(ae), O_RDONLY); + if (!assert(fd >= 0)) + return; + + /* Check 100-byte gap at beginning */ + assertEqualInt(100, read(fd, buff, 100)); + failure("%s", msg); + for (p = buff; p < buff + 100; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check first block. */ + assertEqualInt(buff_size, read(fd, buff, buff_size)); + failure("%s", msg); + assertEqualMem(buff, data, sizeof(data)); + for (p = buff + sizeof(data); p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check 100-byte gap */ + assertEqualInt(100, read(fd, buff, 100)); + failure("%s", msg); + for (p = buff; p < buff + 100; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check second block. */ + assertEqualInt(buff_size, read(fd, buff, buff_size)); + for (p = buff; p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (p == buff + buff_size / 2 - 3) { + assertEqualMem(p, data, sizeof(data)); + p += sizeof(data); + } else if (!assertEqualInt(0, *p)) + break; + } + + /* Check 100-byte gap */ + assertEqualInt(100, read(fd, buff, 100)); + failure("%s", msg); + for (p = buff; p < buff + 100; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + /* Check third block. */ + assertEqualInt(buff_size, read(fd, buff, buff_size)); + for (p = buff; p < buff + buff_size - sizeof(data); ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + failure("%s", msg); + assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data)); + + /* Check another block size beyond last we wrote. */ + assertEqualInt(buff_size, read(fd, buff, buff_size)); + failure("%s", msg); + for (p = buff; p < buff + buff_size; ++p) { + failure("offset: %d, %s", (int)(p - buff), msg); + if (!assertEqualInt(0, *p)) + break; + } + + + /* XXX more XXX */ + + assertEqualInt(0, close(fd)); + free(buff); +} + +DEFINE_TEST(test_write_disk_sparse) +{ + struct archive *ad; + + + /* + * The return values, etc, of the write data functions + * shouldn't change regardless of whether we've requested + * sparsification. (The performance and pattern of actual + * write calls to the disk should vary, of course, but the + * client program shouldn't see any difference.) + */ + assert((ad = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(ad, 0); + verify_write_data(ad, 0); + verify_write_data_block(ad, 0); + assertEqualInt(0, archive_write_finish(ad)); + + assert((ad = archive_write_disk_new()) != NULL); + archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_SPARSE); + verify_write_data(ad, 1); + verify_write_data_block(ad, 1); + assertEqualInt(0, archive_write_finish(ad)); + +} From yongari at FreeBSD.org Sun Feb 8 19:32:25 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:32:37 2009 Subject: svn commit: r188368 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090332.n193WOPc043706@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:32:23 2009 New Revision: 188368 URL: http://svn.freebsd.org/changeset/base/188368 Log: MFC r185273 Fix Tx/Rx checksum offload ioctl handling and make Rx handler honor checksum offload configuration. Now checksum offload can be controlled by ifconfig(8). While I'm here add an additional check for interface capabilities before applying user's request. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:31:53 2009 (r188367) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:32:23 2009 (r188368) @@ -1558,6 +1558,7 @@ fxp_intr_body(struct fxp_softc *sc, stru struct fxp_rfa *rfa; int rnr = (statack & FXP_SCB_STATACK_RNR) ? 1 : 0; int fxp_rc = 0; + uint16_t status; FXP_LOCK_ASSERT(sc, MA_OWNED); if (rnr) @@ -1635,7 +1636,8 @@ fxp_intr_body(struct fxp_softc *sc, stru } #endif /* DEVICE_POLLING */ - if ((le16toh(rfa->rfa_status) & FXP_RFA_STATUS_C) == 0) + status = le16toh(rfa->rfa_status); + if ((status & FXP_RFA_STATUS_C) == 0) break; /* @@ -1661,14 +1663,14 @@ fxp_intr_body(struct fxp_softc *sc, stru total_len = le16toh(rfa->actual_size) & 0x3fff; if (total_len < sizeof(struct ether_header) || total_len > MCLBYTES - RFA_ALIGNMENT_FUDGE - - sc->rfa_size || - le16toh(rfa->rfa_status) & FXP_RFA_STATUS_CRC) { + sc->rfa_size || status & FXP_RFA_STATUS_CRC) { m_freem(m); continue; } /* Do IP checksum checking. */ - if (le16toh(rfa->rfa_status) & FXP_RFA_STATUS_PARSE) { + if ((ifp->if_capenable & IFCAP_RXCSUM) != 0 && + (status & FXP_RFA_STATUS_PARSE)) { if (rfa->rfax_csum_sts & FXP_RFDX_CS_IP_CSUM_BIT_VALID) m->m_pkthdr.csum_flags |= @@ -2372,7 +2374,7 @@ fxp_ioctl(struct ifnet *ifp, u_long comm struct fxp_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct mii_data *mii; - int flag, mask, error = 0; + int flag, mask, error = 0, reinit; switch (command) { case SIOCSIFFLAGS: @@ -2432,6 +2434,7 @@ fxp_ioctl(struct ifnet *ifp, u_long comm break; case SIOCSIFCAP: + reinit = 0; mask = ifp->if_capenable ^ ifr->ifr_reqcap; #ifdef DEVICE_POLLING if (mask & IFCAP_POLLING) { @@ -2454,8 +2457,20 @@ fxp_ioctl(struct ifnet *ifp, u_long comm } } #endif - if (mask & IFCAP_VLAN_MTU) { - FXP_LOCK(sc); + FXP_LOCK(sc); + if ((mask & IFCAP_TXCSUM) != 0 && + (ifp->if_capabilities & IFCAP_TXCSUM) != 0) { + ifp->if_capenable ^= IFCAP_TXCSUM; + if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) + ifp->if_hwassist |= FXP_CSUM_FEATURES; + else + ifp->if_hwassist &= ~FXP_CSUM_FEATURES; + } + if ((mask & IFCAP_RXCSUM) != 0 && + (ifp->if_capabilities & IFCAP_RXCSUM) != 0) + ifp->if_capenable ^= IFCAP_RXCSUM; + if ((mask & IFCAP_VLAN_MTU) != 0 && + (ifp->if_capabilities & IFCAP_VLAN_MTU) != 0) { ifp->if_capenable ^= IFCAP_VLAN_MTU; if (sc->revision != FXP_REV_82557) flag = FXP_FLAG_LONG_PKT_EN; @@ -2463,9 +2478,11 @@ fxp_ioctl(struct ifnet *ifp, u_long comm flag = FXP_FLAG_SAVE_BAD; sc->flags ^= flag; if (ifp->if_flags & IFF_UP) - fxp_init_body(sc); - FXP_UNLOCK(sc); + reinit++; } + if (reinit > 0) + fxp_init_body(sc); + FXP_UNLOCK(sc); break; default: From yongari at FreeBSD.org Sun Feb 8 19:34:38 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:34:43 2009 Subject: svn commit: r188369 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090334.n193Yakm043810@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:34:35 2009 New Revision: 188369 URL: http://svn.freebsd.org/changeset/base/188369 Log: MFC r185276 Move unarming watchdog timer and pending multicast configuration check to fxp_txeof(). While I'm here unarm watchdog timer only if there are no pending queued Tx requests. Previously the watchdog timer was unarmed whenever Tx interrupt is raised. This could be resulted in hiding root cause of watchdog timeouts. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:32:23 2009 (r188368) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:34:35 2009 (r188369) @@ -1547,6 +1547,11 @@ fxp_txeof(struct fxp_softc *sc) } sc->fxp_desc.tx_first = txp; bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE); + if (sc->tx_queued == 0) { + sc->watchdog_timer = 0; + if (sc->need_mcsetup) + fxp_mc_setup(sc); + } } static void @@ -1587,11 +1592,6 @@ fxp_intr_body(struct fxp_softc *sc, stru if (statack & (FXP_SCB_STATACK_CXTNO | FXP_SCB_STATACK_CNA)) { fxp_txeof(sc); - sc->watchdog_timer = 0; - if (sc->tx_queued == 0) { - if (sc->need_mcsetup) - fxp_mc_setup(sc); - } /* * Try to start more packets transmitting. */ From yongari at FreeBSD.org Sun Feb 8 19:38:02 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:38:19 2009 Subject: svn commit: r188370 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090338.n193c1Ii043921@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:38:01 2009 New Revision: 188370 URL: http://svn.freebsd.org/changeset/base/188370 Log: MFC r185285: - Allow fxp_encap() enqueue failed transmissions and set IFF_DRV_OACTIVE to note resource shortage to upper stack. - Don't count number of mbuf chains. Default 32 DMA segments for a frame is enough for most cases. If bus_dmamap_mbuf_sg fails use m_collapse(9) to collapse the mbuf chain instead of relying on expensive m_defrag(9). - Move bpf handling to fxp_start_body() which is supposed to be more appropriate place. - Always arm watchdog timer whenever a new Tx request is made. Previously fxp(4) used to arm watchdog timer only when FXP_CXINT_THRESH-th Tx request is made. Because fxp(4) does not rely on Tx interrupt to reclaim transmitted mbufs it's better to arm watchdog timer to detect potential lockups. - Add more aggresive Tx buffer reclaiming in fxp_start_body to make room for new Tx requests. Since fxp(4) does not request Tx completion interrupt for every frames it's necessary to clean TXCBs in advance to saturate link. - Make fxp(4) try to start more packets transmitting regardless of interrupt type in fxp_intr_body. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c stable/7/sys/dev/fxp/if_fxpvar.h Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:34:35 2009 (r188369) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:38:01 2009 (r188370) @@ -220,7 +220,8 @@ static void fxp_init_body(struct fxp_s static void fxp_tick(void *xsc); static void fxp_start(struct ifnet *ifp); static void fxp_start_body(struct ifnet *ifp); -static int fxp_encap(struct fxp_softc *sc, struct mbuf *m_head); +static int fxp_encap(struct fxp_softc *sc, struct mbuf **m_head); +static void fxp_txeof(struct fxp_softc *sc); static void fxp_stop(struct fxp_softc *sc); static void fxp_release(struct fxp_softc *sc); static int fxp_ioctl(struct ifnet *ifp, u_long command, @@ -1190,7 +1191,7 @@ fxp_start_body(struct ifnet *ifp) { struct fxp_softc *sc = ifp->if_softc; struct mbuf *mb_head; - int error, txqueued; + int txqueued; FXP_LOCK_ASSERT(sc, MA_OWNED); @@ -1202,6 +1203,8 @@ fxp_start_body(struct ifnet *ifp) if (sc->need_mcsetup) return; + if (sc->tx_queued > FXP_NTXCB_HIWAT) + fxp_txeof(sc); /* * We're finished if there is nothing more to add to the list or if * we're all filled up with buffers to transmit. @@ -1219,32 +1222,44 @@ fxp_start_body(struct ifnet *ifp) if (mb_head == NULL) break; - error = fxp_encap(sc, mb_head); - if (error) - break; - txqueued = 1; + if (fxp_encap(sc, &mb_head)) { + if (mb_head == NULL) + break; + IFQ_DRV_PREPEND(&ifp->if_snd, mb_head); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + } + txqueued++; + /* + * Pass packet to bpf if there is a listener. + */ + BPF_MTAP(ifp, mb_head); } - bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE); /* * We're finished. If we added to the list, issue a RESUME to get DMA * going again if suspended. */ - if (txqueued) { + if (txqueued > 0) { + bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE); fxp_scb_wait(sc); fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME); + /* + * Set a 5 second timer just in case we don't hear + * from the card again. + */ + sc->watchdog_timer = 5; } } static int -fxp_encap(struct fxp_softc *sc, struct mbuf *m_head) +fxp_encap(struct fxp_softc *sc, struct mbuf **m_head) { struct ifnet *ifp; struct mbuf *m; struct fxp_tx *txp; struct fxp_cb_tx *cbp; bus_dma_segment_t segs[FXP_NTXSEG]; - int chainlen, error, i, nseg; + int error, i, nseg; FXP_LOCK_ASSERT(sc, MA_OWNED); ifp = sc->ifp; @@ -1271,6 +1286,7 @@ fxp_encap(struct fxp_softc *sc, struct m txp->tx_cb->ipcb_ip_activation_high = FXP_IPCB_HARDWAREPARSING_ENABLE; + m = *m_head; /* * Deal with TCP/IP checksum offload. Note that * in order for TCP checksum offload to work, @@ -1279,11 +1295,11 @@ fxp_encap(struct fxp_softc *sc, struct m * in the TCP header. The stack should have * already done this for us. */ - if (m_head->m_pkthdr.csum_flags) { - if (m_head->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + if (m->m_pkthdr.csum_flags) { + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { txp->tx_cb->ipcb_ip_schedule = FXP_IPCB_TCPUDP_CHECKSUM_ENABLE; - if (m_head->m_pkthdr.csum_flags & CSUM_TCP) + if (m->m_pkthdr.csum_flags & CSUM_TCP) txp->tx_cb->ipcb_ip_schedule |= FXP_IPCB_TCP_PACKET; } @@ -1311,13 +1327,13 @@ fxp_encap(struct fxp_softc *sc, struct m * the header sizes/offsets vary. */ - if (m_head->m_pkthdr.csum_flags & CSUM_IP) { - if (m_head->m_pkthdr.len < 38) { + if (m->m_pkthdr.csum_flags & CSUM_IP) { + if (m->m_pkthdr.len < 38) { struct ip *ip; - m_head->m_data += ETHER_HDR_LEN; - ip = mtod(m_head, struct ip *); - ip->ip_sum = in_cksum(m_head, ip->ip_hl << 2); - m_head->m_data -= ETHER_HDR_LEN; + m->m_data += ETHER_HDR_LEN; + ip = mtod(m, struct ip *); + ip->ip_sum = in_cksum(m, ip->ip_hl << 2); + m->m_data -= ETHER_HDR_LEN; } else { txp->tx_cb->ipcb_ip_activation_high = FXP_IPCB_HARDWAREPARSING_ENABLE; @@ -1328,40 +1344,33 @@ fxp_encap(struct fxp_softc *sc, struct m #endif } - chainlen = 0; - for (m = m_head; m != NULL && chainlen <= sc->maxtxseg; m = m->m_next) - chainlen++; - if (chainlen > sc->maxtxseg) { - struct mbuf *mn; - - /* - * We ran out of segments. We have to recopy this - * mbuf chain first. Bail out if we can't get the - * new buffers. - */ - mn = m_defrag(m_head, M_DONTWAIT); - if (mn == NULL) { - m_freem(m_head); - return (-1); - } else { - m_head = mn; + error = bus_dmamap_load_mbuf_sg(sc->fxp_mtag, txp->tx_map, *m_head, + segs, &nseg, 0); + if (error == EFBIG) { + m = m_collapse(*m_head, M_DONTWAIT, sc->maxtxseg); + if (m == NULL) { + m_freem(*m_head); + *m_head = NULL; + return (ENOMEM); + } + *m_head = m; + error = bus_dmamap_load_mbuf_sg(sc->fxp_mtag, txp->tx_map, + *m_head, segs, &nseg, 0); + if (error != 0) { + m_freem(*m_head); + *m_head = NULL; + return (ENOMEM); } - } - - /* - * Go through each of the mbufs in the chain and initialize - * the transmit buffer descriptors with the physical address - * and size of the mbuf. - */ - error = bus_dmamap_load_mbuf_sg(sc->fxp_mtag, txp->tx_map, - m_head, segs, &nseg, 0); - if (error) { - device_printf(sc->dev, "can't map mbuf (error %d)\n", error); - m_freem(m_head); - return (-1); + } else if (error != 0) + return (error); + if (nseg == 0) { + m_freem(*m_head); + *m_head = NULL; + return (EIO); } KASSERT(nseg <= sc->maxtxseg, ("too many DMA segments")); + bus_dmamap_sync(sc->fxp_mtag, txp->tx_map, BUS_DMASYNC_PREWRITE); cbp = txp->tx_cb; for (i = 0; i < nseg; i++) { @@ -1389,24 +1398,17 @@ fxp_encap(struct fxp_softc *sc, struct m } cbp->tbd_number = nseg; - bus_dmamap_sync(sc->fxp_mtag, txp->tx_map, BUS_DMASYNC_PREWRITE); - txp->tx_mbuf = m_head; + txp->tx_mbuf = m; txp->tx_cb->cb_status = 0; txp->tx_cb->byte_count = 0; - if (sc->tx_queued != FXP_CXINT_THRESH - 1) { + if (sc->tx_queued != FXP_CXINT_THRESH - 1) txp->tx_cb->cb_command = htole16(sc->tx_cmd | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_S); - } else { + else txp->tx_cb->cb_command = htole16(sc->tx_cmd | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_S | FXP_CB_COMMAND_I); - /* - * Set a 5 second timer just in case we don't hear - * from the card again. - */ - sc->watchdog_timer = 5; - } txp->tx_cb->tx_threshold = tx_threshold; /* @@ -1439,10 +1441,6 @@ fxp_encap(struct fxp_softc *sc, struct m sc->tx_queued++; - /* - * Pass packet to bpf if there is a listener. - */ - BPF_MTAP(ifp, m_head); return (0); } @@ -1528,8 +1526,10 @@ fxp_intr(void *xsc) static void fxp_txeof(struct fxp_softc *sc) { + struct ifnet *ifp; struct fxp_tx *txp; + ifp = sc->ifp; bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREREAD); for (txp = sc->fxp_desc.tx_first; sc->tx_queued && (le16toh(txp->tx_cb->cb_status) & FXP_CB_STATUS_C) != 0; @@ -1544,6 +1544,7 @@ fxp_txeof(struct fxp_softc *sc) txp->tx_cb->tbd[0].tb_addr = 0; } sc->tx_queued--; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } sc->fxp_desc.tx_first = txp; bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE); @@ -1589,15 +1590,14 @@ fxp_intr_body(struct fxp_softc *sc, stru * packets go out onto the wire for about 5 to 10 seconds * after the interface is ifconfig'ed for the first time. */ - if (statack & (FXP_SCB_STATACK_CXTNO | FXP_SCB_STATACK_CNA)) { + if (statack & (FXP_SCB_STATACK_CXTNO | FXP_SCB_STATACK_CNA)) fxp_txeof(sc); - /* - * Try to start more packets transmitting. - */ - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - fxp_start_body(ifp); - } + /* + * Try to start more packets transmitting. + */ + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + fxp_start_body(ifp); /* * Just return if nothing happened on the receive side. Modified: stable/7/sys/dev/fxp/if_fxpvar.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:34:35 2009 (r188369) +++ stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:38:01 2009 (r188370) @@ -38,6 +38,7 @@ * This must be a power of two. */ #define FXP_NTXCB 128 +#define FXP_NTXCB_HIWAT ((FXP_NTXCB * 7) / 10) /* * Size of the TxCB list. From yongari at FreeBSD.org Sun Feb 8 19:40:53 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:41:04 2009 Subject: svn commit: r188371 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090340.n193eq9A044021@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:40:51 2009 New Revision: 188371 URL: http://svn.freebsd.org/changeset/base/188371 Log: MFC r185286: Simplify Tx checksum offload configuration. Also clear CSUM_IP if we've computed IP checksum with software method. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:38:01 2009 (r188370) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:40:51 2009 (r188371) @@ -1295,14 +1295,10 @@ fxp_encap(struct fxp_softc *sc, struct m * in the TCP header. The stack should have * already done this for us. */ - if (m->m_pkthdr.csum_flags) { - if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - txp->tx_cb->ipcb_ip_schedule = - FXP_IPCB_TCPUDP_CHECKSUM_ENABLE; - if (m->m_pkthdr.csum_flags & CSUM_TCP) - txp->tx_cb->ipcb_ip_schedule |= - FXP_IPCB_TCP_PACKET; - } + if (m->m_pkthdr.csum_flags & FXP_CSUM_FEATURES) { + txp->tx_cb->ipcb_ip_schedule = FXP_IPCB_TCPUDP_CHECKSUM_ENABLE; + if (m->m_pkthdr.csum_flags & CSUM_TCP) + txp->tx_cb->ipcb_ip_schedule |= FXP_IPCB_TCP_PACKET; #ifdef FXP_IP_CSUM_WAR /* @@ -1334,6 +1330,7 @@ fxp_encap(struct fxp_softc *sc, struct m ip = mtod(m, struct ip *); ip->ip_sum = in_cksum(m, ip->ip_hl << 2); m->m_data -= ETHER_HDR_LEN; + m->m_pkthdr.csum_flags &= ~CSUM_IP; } else { txp->tx_cb->ipcb_ip_activation_high = FXP_IPCB_HARDWAREPARSING_ENABLE; From yongari at FreeBSD.org Sun Feb 8 19:43:47 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:44:01 2009 Subject: svn commit: r188372 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090343.n193hltc044113@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:43:46 2009 New Revision: 188372 URL: http://svn.freebsd.org/changeset/base/188372 Log: MFC r185328: o Introduce a new function, fxp_new_rfabuf which allocates a new Rx buffer and loads DMA map. Also add a function fxp_discard_rfabuf that handles reusing Rx buffer/DMA map. With this change fxp_add_rfabuf just handles appending a new RFA to existing chain. o Initialize mbuf length in fxp_new_rfabuf. o Don't reset rnr and have fxp(4) handle received frames even if it couldn't allocate new Rx buffer. This will make fxp(4) reload updated RFA under rnr case. The rnr would still be reset to 0 if polling is active and fxp(4) processed number of allowed Rx events. o Update if_iqdrops if fxp(4) couldn't allocate Rx buffer. Previously fxp(4) used to try to reuse Rx buffer when new buffer allocation is failed. But fxp(4) didn't take into account loaded DMA map such that the same DMA map was loaded again without unloading the map. There is no reason to unload the loaded map and reload the same map again, just reusing the map is enough. I believe the spare DMA map in softc was introduced to implement this behaviour. Also fxp(4) used to stop Rx processing if once Rx buffer allocation or DMA map load fails which in turn resulted in losing incoming frames under heavy network load. With this change fxp(4) should survive from resource shortage condition. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:40:51 2009 (r188371) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:43:46 2009 (r188372) @@ -227,8 +227,12 @@ static void fxp_release(struct fxp_sof static int fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data); static void fxp_watchdog(struct fxp_softc *sc); -static int fxp_add_rfabuf(struct fxp_softc *sc, - struct fxp_rx *rxp, struct mbuf *oldm); +static void fxp_add_rfabuf(struct fxp_softc *sc, + struct fxp_rx *rxp); +static void fxp_discard_rfabuf(struct fxp_softc *sc, + struct fxp_rx *rxp); +static int fxp_new_rfabuf(struct fxp_softc *sc, + struct fxp_rx *rxp); static int fxp_mc_addrs(struct fxp_softc *sc); static void fxp_mc_setup(struct fxp_softc *sc); static uint16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset, @@ -712,10 +716,11 @@ fxp_attach(device_t dev) device_printf(dev, "can't create DMA map for RX\n"); goto fail; } - if (fxp_add_rfabuf(sc, rxp, NULL) != 0) { + if (fxp_new_rfabuf(sc, rxp) != 0) { error = ENOMEM; goto fail; } + fxp_add_rfabuf(sc, rxp); } /* @@ -1560,7 +1565,6 @@ fxp_intr_body(struct fxp_softc *sc, stru struct fxp_rx *rxp; struct fxp_rfa *rfa; int rnr = (statack & FXP_SCB_STATACK_RNR) ? 1 : 0; - int fxp_rc = 0; uint16_t status; FXP_LOCK_ASSERT(sc, MA_OWNED); @@ -1647,8 +1651,7 @@ fxp_intr_body(struct fxp_softc *sc, stru * If this fails, the old buffer is recycled * instead. */ - fxp_rc = fxp_add_rfabuf(sc, rxp, m); - if (fxp_rc == 0) { + if (fxp_new_rfabuf(sc, rxp) == 0) { int total_len; /* @@ -1700,10 +1703,12 @@ fxp_intr_body(struct fxp_softc *sc, stru FXP_UNLOCK(sc); (*ifp->if_input)(ifp, m); FXP_LOCK(sc); - } else if (fxp_rc == ENOBUFS) { - rnr = 0; - break; + } else { + /* Reuse RFA and loaded DMA map. */ + ifp->if_iqdrops++; + fxp_discard_rfabuf(sc, rxp); } + fxp_add_rfabuf(sc, rxp); } if (rnr) { fxp_scb_wait(sc); @@ -2234,32 +2239,21 @@ fxp_ifmedia_sts(struct ifnet *ifp, struc /* * Add a buffer to the end of the RFA buffer list. * Return 0 if successful, 1 for failure. A failure results in - * adding the 'oldm' (if non-NULL) on to the end of the list - - * tossing out its old contents and recycling it. + * reusing the RFA buffer. * The RFA struct is stuck at the beginning of mbuf cluster and the * data pointer is fixed up to point just past it. */ static int -fxp_add_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp, struct mbuf *oldm) +fxp_new_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp) { struct mbuf *m; - struct fxp_rfa *rfa, *p_rfa; - struct fxp_rx *p_rx; + struct fxp_rfa *rfa; bus_dmamap_t tmp_map; - int error, reused_mbuf=0; + int error; m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - if (oldm == NULL) - return ENOBUFS; - m = oldm; - m->m_data = m->m_ext.ext_buf; - /* - * return error so the receive loop will - * not pass the packet to upper layer - */ - reused_mbuf = EAGAIN; - } + if (m == NULL) + return (ENOBUFS); /* * Move the data pointer up so that the incoming data packet @@ -2278,6 +2272,8 @@ fxp_add_rfabuf(struct fxp_softc *sc, str rfa->rfa_status = 0; rfa->rfa_control = htole16(FXP_RFA_CONTROL_EL); rfa->actual_size = 0; + m->m_len = m->m_pkthdr.len = MCLBYTES - RFA_ALIGNMENT_FUDGE - + sc->rfa_size; /* * Initialize the rest of the RFA. Note that since the RFA @@ -2305,6 +2301,14 @@ fxp_add_rfabuf(struct fxp_softc *sc, str bus_dmamap_sync(sc->fxp_mtag, rxp->rx_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + return (0); +} + +static void +fxp_add_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp) +{ + struct fxp_rfa *p_rfa; + struct fxp_rx *p_rx; /* * If there are other buffers already on the list, attach this @@ -2324,7 +2328,45 @@ fxp_add_rfabuf(struct fxp_softc *sc, str sc->fxp_desc.rx_head = rxp; } sc->fxp_desc.rx_tail = rxp; - return (reused_mbuf); +} + +static void +fxp_discard_rfabuf(struct fxp_softc *sc, struct fxp_rx *rxp) +{ + struct mbuf *m; + struct fxp_rfa *rfa; + + m = rxp->rx_mbuf; + m->m_data = m->m_ext.ext_buf; + /* + * Move the data pointer up so that the incoming data packet + * will be 32-bit aligned. + */ + m->m_data += RFA_ALIGNMENT_FUDGE; + + /* + * Get a pointer to the base of the mbuf cluster and move + * data start past it. + */ + rfa = mtod(m, struct fxp_rfa *); + m->m_data += sc->rfa_size; + rfa->size = htole16(MCLBYTES - sc->rfa_size - RFA_ALIGNMENT_FUDGE); + + rfa->rfa_status = 0; + rfa->rfa_control = htole16(FXP_RFA_CONTROL_EL); + rfa->actual_size = 0; + + /* + * Initialize the rest of the RFA. Note that since the RFA + * is misaligned, we cannot store values directly. We're thus + * using the le32enc() function which handles endianness and + * is also alignment-safe. + */ + le32enc(&rfa->link_addr, 0xffffffff); + le32enc(&rfa->rbd_addr, 0xffffffff); + + bus_dmamap_sync(sc->fxp_mtag, rxp->rx_map, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } static int From yongari at FreeBSD.org Sun Feb 8 19:46:16 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:46:33 2009 Subject: svn commit: r188373 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090346.n193kFN1044227@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:46:15 2009 New Revision: 188373 URL: http://svn.freebsd.org/changeset/base/188373 Log: MFC r185329: Implement Rx checksum offload for 82559 or later controllers. 82559 or later controllers added simple checksum calculation logic in RU. For backward compatibility the computed checksum is appended at the end of the data posted to Rx buffer. This type of simple checksum calculation support had been used on several vendors such as Sun HME/GEM, SysKonnect GENESIS and Marvell Yukon controllers. Because this type of checksum offload support requires parsing of received frame and pseudo checksum calculation with software routine it still consumes more CPU cycles than that of full-fledged checksum offload controller. But it's still better than software checksum calculation. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c stable/7/sys/dev/fxp/if_fxpvar.h Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:43:46 2009 (r188372) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:46:15 2009 (r188373) @@ -59,15 +59,15 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include - -#ifdef FXP_IP_CSUM_WAR #include #include #include +#include +#include + +#include #include -#endif +#include #include #include /* for PCIM_CMD_xxx */ @@ -213,6 +213,8 @@ static int fxp_suspend(device_t dev); static int fxp_resume(device_t dev); static void fxp_intr(void *xsc); +static void fxp_rxcsum(struct fxp_softc *sc, struct ifnet *ifp, + struct mbuf *m, uint16_t status, int pos); static void fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp, uint8_t statack, int count); static void fxp_init(void *xsc); @@ -591,6 +593,9 @@ fxp_attach(device_t dev) sc->flags |= FXP_FLAG_SAVE_BAD; } + /* For 82559 or later chips, Rx checksum offload is supported. */ + if (sc->revision >= FXP_REV_82559_A0) + sc->flags |= FXP_FLAG_82559_RXCSUM; /* * Enable use of extended RFDs and TCBs for 82550 * and later chips. Note: we need extended TXCB support @@ -603,6 +608,8 @@ fxp_attach(device_t dev) sc->rfa_size = sizeof (struct fxp_rfa); sc->tx_cmd = FXP_CB_COMMAND_IPCBXMIT; sc->flags |= FXP_FLAG_EXT_RFA; + /* Use extended RFA instead of 82559 checksum mode. */ + sc->flags &= ~FXP_FLAG_82559_RXCSUM; } else { sc->rfa_size = sizeof (struct fxp_rfa) - FXP_RFAX_LEN; sc->tx_cmd = FXP_CB_COMMAND_XMIT; @@ -780,6 +787,11 @@ fxp_attach(device_t dev) ifp->if_capenable |= IFCAP_HWCSUM; } + if (sc->flags & FXP_FLAG_82559_RXCSUM) { + ifp->if_capabilities |= IFCAP_RXCSUM; + ifp->if_capenable |= IFCAP_RXCSUM; + } + #ifdef DEVICE_POLLING /* Inform the world we support polling. */ ifp->if_capabilities |= IFCAP_POLLING; @@ -1558,6 +1570,84 @@ fxp_txeof(struct fxp_softc *sc) } static void +fxp_rxcsum(struct fxp_softc *sc, struct ifnet *ifp, struct mbuf *m, + uint16_t status, int pos) +{ + struct ether_header *eh; + struct ip *ip; + struct udphdr *uh; + int32_t hlen, len, pktlen, temp32; + uint16_t csum, *opts; + + if ((sc->flags & FXP_FLAG_82559_RXCSUM) == 0) { + if ((status & FXP_RFA_STATUS_PARSE) != 0) { + if (status & FXP_RFDX_CS_IP_CSUM_BIT_VALID) + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if (status & FXP_RFDX_CS_IP_CSUM_VALID) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + if ((status & FXP_RFDX_CS_TCPUDP_CSUM_BIT_VALID) && + (status & FXP_RFDX_CS_TCPUDP_CSUM_VALID)) { + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | + CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + } + return; + } + + pktlen = m->m_pkthdr.len; + if (pktlen < sizeof(struct ether_header) + sizeof(struct ip)) + return; + eh = mtod(m, struct ether_header *); + if (eh->ether_type != htons(ETHERTYPE_IP)) + return; + ip = (struct ip *)(eh + 1); + if (ip->ip_v != IPVERSION) + return; + + hlen = ip->ip_hl << 2; + pktlen -= sizeof(struct ether_header); + if (hlen < sizeof(struct ip)) + return; + if (ntohs(ip->ip_len) < hlen) + return; + if (ntohs(ip->ip_len) != pktlen) + return; + if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) + return; /* can't handle fragmented packet */ + + switch (ip->ip_p) { + case IPPROTO_TCP: + if (pktlen < (hlen + sizeof(struct tcphdr))) + return; + break; + case IPPROTO_UDP: + if (pktlen < (hlen + sizeof(struct udphdr))) + return; + uh = (struct udphdr *)((caddr_t)ip + hlen); + if (uh->uh_sum == 0) + return; /* no checksum */ + break; + default: + return; + } + /* Extract computed checksum. */ + csum = be16dec(mtod(m, char *) + pos); + /* checksum fixup for IP options */ + len = hlen - sizeof(struct ip); + if (len > 0) { + opts = (uint16_t *)(ip + 1); + for (; len > 0; len -= sizeof(uint16_t), opts++) { + temp32 = csum - *opts; + temp32 = (temp32 >> 16) + (temp32 & 65535); + csum = temp32 & 65535; + } + } + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; + m->m_pkthdr.csum_data = csum; +} + +static void fxp_intr_body(struct fxp_softc *sc, struct ifnet *ifp, uint8_t statack, int count) { @@ -1661,6 +1751,11 @@ fxp_intr_body(struct fxp_softc *sc, stru * of bogus length or CRC errors. */ total_len = le16toh(rfa->actual_size) & 0x3fff; + if ((sc->flags & FXP_FLAG_82559_RXCSUM) != 0 && + (ifp->if_capenable & IFCAP_RXCSUM) != 0) { + /* Adjust for appended checksum bytes. */ + total_len -= 2; + } if (total_len < sizeof(struct ether_header) || total_len > MCLBYTES - RFA_ALIGNMENT_FUDGE - sc->rfa_size || status & FXP_RFA_STATUS_CRC) { @@ -1668,30 +1763,12 @@ fxp_intr_body(struct fxp_softc *sc, stru continue; } - /* Do IP checksum checking. */ - if ((ifp->if_capenable & IFCAP_RXCSUM) != 0 && - (status & FXP_RFA_STATUS_PARSE)) { - if (rfa->rfax_csum_sts & - FXP_RFDX_CS_IP_CSUM_BIT_VALID) - m->m_pkthdr.csum_flags |= - CSUM_IP_CHECKED; - if (rfa->rfax_csum_sts & - FXP_RFDX_CS_IP_CSUM_VALID) - m->m_pkthdr.csum_flags |= - CSUM_IP_VALID; - if ((rfa->rfax_csum_sts & - FXP_RFDX_CS_TCPUDP_CSUM_BIT_VALID) && - (rfa->rfax_csum_sts & - FXP_RFDX_CS_TCPUDP_CSUM_VALID)) { - m->m_pkthdr.csum_flags |= - CSUM_DATA_VALID|CSUM_PSEUDO_HDR; - m->m_pkthdr.csum_data = 0xffff; - } - } - m->m_pkthdr.len = m->m_len = total_len; m->m_pkthdr.rcvif = ifp; + /* Do IP checksum checking. */ + if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) + fxp_rxcsum(sc, ifp, m, status, total_len); /* * Drop locks before calling if_input() since it * may re-enter fxp_start() in the netisr case. @@ -2024,7 +2101,8 @@ fxp_init_body(struct fxp_softc *sc) cbp->ext_rfa = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; cbp->mediatype = sc->flags & FXP_FLAG_SERIAL_MEDIA ? 0 : 1; cbp->csma_dis = 0; /* (don't) disable link */ - cbp->tcp_udp_cksum = 0; /* (don't) enable checksum */ + cbp->tcp_udp_cksum = ((sc->flags & FXP_FLAG_82559_RXCSUM) != 0 && + (ifp->if_capenable & IFCAP_RXCSUM) != 0) ? 1 : 0; cbp->vlan_tco = 0; /* (don't) enable vlan wakeup */ cbp->link_wake_en = 0; /* (don't) assert PME# on link change */ cbp->arp_wake_en = 0; /* (don't) assert PME# on arp */ @@ -2506,8 +2584,11 @@ fxp_ioctl(struct ifnet *ifp, u_long comm ifp->if_hwassist &= ~FXP_CSUM_FEATURES; } if ((mask & IFCAP_RXCSUM) != 0 && - (ifp->if_capabilities & IFCAP_RXCSUM) != 0) + (ifp->if_capabilities & IFCAP_RXCSUM) != 0) { ifp->if_capenable ^= IFCAP_RXCSUM; + if ((sc->flags & FXP_FLAG_82559_RXCSUM) != 0) + reinit++; + } if ((mask & IFCAP_VLAN_MTU) != 0 && (ifp->if_capabilities & IFCAP_VLAN_MTU) != 0) { ifp->if_capenable ^= IFCAP_VLAN_MTU; Modified: stable/7/sys/dev/fxp/if_fxpvar.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:43:46 2009 (r188372) +++ stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:46:15 2009 (r188373) @@ -194,6 +194,7 @@ struct fxp_softc { #define FXP_FLAG_DEFERRED_RNR 0x0200 /* DEVICE_POLLING deferred RNR */ #define FXP_FLAG_EXT_RFA 0x0400 /* extended RFDs for csum offload */ #define FXP_FLAG_SAVE_BAD 0x0800 /* save bad pkts: bad size, CRC, etc */ +#define FXP_FLAG_82559_RXCSUM 0x1000 /* 82559 compatible RX checksum */ /* Macros to ease CSR access. */ #define CSR_READ_1(sc, reg) bus_read_1(sc->fxp_res[0], reg) From yongari at FreeBSD.org Sun Feb 8 19:48:50 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:48:57 2009 Subject: svn commit: r188374 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090348.n193mnDw044318@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:48:49 2009 New Revision: 188374 URL: http://svn.freebsd.org/changeset/base/188374 Log: MFC r185330: Implement TSO for 82550/82551 controllers. o Configure controller to use dynamic TBD as TSO requires that operation mode. o Add a dummy TBD to tx_cb_u as TSO can access one more TBD in TSO operation. o Increase a DMA segment size to 4096 to hold a full IP segment with link layer header. o Unlike other TSO capable controllers, 82550/82551 does not modify the first IP packet in TSO operation so driver should create an IP packet with proper header. Subsequent IP packets are generated from the header information in the first IP packet header. Likewise pseudo checksum also should be computed by driver for the first packet. o TSO requires one more TBD to hold total TCP payload. To make code simple for TSO/non-TSO case, increase the index of the first available TBD array. o Remove KASSERT that checks the size of a DMA segment should be less than or equal to MCLBYTES as it's no longer valid in TSO. o Tx threshold and number of TBDs field is used to store MSS in TSO. So don't set the Tx threshold in TSO case. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c stable/7/sys/dev/fxp/if_fxpreg.h stable/7/sys/dev/fxp/if_fxpvar.h Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:46:15 2009 (r188373) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:48:49 2009 (r188374) @@ -619,11 +619,15 @@ fxp_attach(device_t dev) * Allocate DMA tags and DMA safe memory. */ sc->maxtxseg = FXP_NTXSEG; - if (sc->flags & FXP_FLAG_EXT_RFA) + sc->maxsegsize = MCLBYTES; + if (sc->flags & FXP_FLAG_EXT_RFA) { sc->maxtxseg--; + sc->maxsegsize = FXP_TSO_SEGSIZE; + } error = bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - MCLBYTES * sc->maxtxseg, sc->maxtxseg, MCLBYTES, 0, + sc->maxsegsize * sc->maxtxseg + sizeof(struct ether_vlan_header), + sc->maxtxseg, sc->maxsegsize, 0, busdma_lock_mutex, &Giant, &sc->fxp_mtag); if (error) { device_printf(dev, "could not allocate dma tag\n"); @@ -780,11 +784,11 @@ fxp_attach(device_t dev) ifp->if_capabilities = ifp->if_capenable = 0; - /* Enable checksum offload for 82550 or better chips */ + /* Enable checksum offload/TSO for 82550 or better chips */ if (sc->flags & FXP_FLAG_EXT_RFA) { - ifp->if_hwassist = FXP_CSUM_FEATURES; - ifp->if_capabilities |= IFCAP_HWCSUM; - ifp->if_capenable |= IFCAP_HWCSUM; + ifp->if_hwassist = FXP_CSUM_FEATURES | CSUM_TSO; + ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4; + ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_TSO4; } if (sc->flags & FXP_FLAG_82559_RXCSUM) { @@ -1275,12 +1279,15 @@ fxp_encap(struct fxp_softc *sc, struct m struct mbuf *m; struct fxp_tx *txp; struct fxp_cb_tx *cbp; + struct tcphdr *tcp; bus_dma_segment_t segs[FXP_NTXSEG]; - int error, i, nseg; + int error, i, nseg, tcp_payload; FXP_LOCK_ASSERT(sc, MA_OWNED); ifp = sc->ifp; + tcp_payload = 0; + tcp = NULL; /* * Get pointer to next available tx desc. */ @@ -1358,6 +1365,75 @@ fxp_encap(struct fxp_softc *sc, struct m #endif } + if (m->m_pkthdr.csum_flags & CSUM_TSO) { + /* + * 82550/82551 requires ethernet/IP/TCP headers must be + * contained in the first active transmit buffer. + */ + struct ether_header *eh; + struct ip *ip; + uint32_t ip_off, poff; + + if (M_WRITABLE(*m_head) == 0) { + /* Get a writable copy. */ + m = m_dup(*m_head, M_DONTWAIT); + m_freem(*m_head); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + *m_head = m; + } + ip_off = sizeof(struct ether_header); + m = m_pullup(*m_head, ip_off); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + eh = mtod(m, struct ether_header *); + /* Check the existence of VLAN tag. */ + if (eh->ether_type == htons(ETHERTYPE_VLAN)) { + ip_off = sizeof(struct ether_vlan_header); + m = m_pullup(m, ip_off); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + } + m = m_pullup(m, ip_off + sizeof(struct ip)); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + ip = (struct ip *)(mtod(m, char *) + ip_off); + poff = ip_off + (ip->ip_hl << 2); + m = m_pullup(m, poff + sizeof(struct tcphdr)); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + tcp = (struct tcphdr *)(mtod(m, char *) + poff); + m = m_pullup(m, poff + sizeof(struct tcphdr) + tcp->th_off); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } + + /* + * Since 82550/82551 doesn't modify IP length and pseudo + * checksum in the first frame driver should compute it. + */ + ip->ip_sum = 0; + ip->ip_len = htons(ifp->if_mtu); + tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, + htons(IPPROTO_TCP + (tcp->th_off << 2) + + m->m_pkthdr.tso_segsz)); + /* Compute total TCP payload. */ + tcp_payload = m->m_pkthdr.len - ip_off - (ip->ip_hl << 2); + tcp_payload -= tcp->th_off << 2; + *m_head = m; + } + error = bus_dmamap_load_mbuf_sg(sc->fxp_mtag, txp->tx_map, *m_head, segs, &nseg, 0); if (error == EFBIG) { @@ -1388,7 +1464,6 @@ fxp_encap(struct fxp_softc *sc, struct m cbp = txp->tx_cb; for (i = 0; i < nseg; i++) { - KASSERT(segs[i].ds_len <= MCLBYTES, ("segment size too large")); /* * If this is an 82550/82551, then we're using extended * TxCBs _and_ we're using checksum offload. This means @@ -1403,14 +1478,28 @@ fxp_encap(struct fxp_softc *sc, struct m * the chip is an 82550/82551 or not. */ if (sc->flags & FXP_FLAG_EXT_RFA) { - cbp->tbd[i + 1].tb_addr = htole32(segs[i].ds_addr); - cbp->tbd[i + 1].tb_size = htole32(segs[i].ds_len); + cbp->tbd[i + 2].tb_addr = htole32(segs[i].ds_addr); + cbp->tbd[i + 2].tb_size = htole32(segs[i].ds_len); } else { cbp->tbd[i].tb_addr = htole32(segs[i].ds_addr); cbp->tbd[i].tb_size = htole32(segs[i].ds_len); } } - cbp->tbd_number = nseg; + if (sc->flags & FXP_FLAG_EXT_RFA) { + /* Configure dynamic TBD for 82550/82551. */ + cbp->tbd_number = 0xFF; + cbp->tbd[nseg + 1].tb_size |= htole32(0x8000); + } else + cbp->tbd_number = nseg; + /* Configure TSO. */ + if (m->m_pkthdr.csum_flags & CSUM_TSO) { + cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16); + cbp->tbd[1].tb_size = htole32(tcp_payload << 16); + cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE | + FXP_IPCB_IP_CHECKSUM_ENABLE | + FXP_IPCB_TCP_PACKET | + FXP_IPCB_TCPUDP_CHECKSUM_ENABLE; + } txp->tx_mbuf = m; txp->tx_cb->cb_status = 0; @@ -1423,7 +1512,8 @@ fxp_encap(struct fxp_softc *sc, struct m txp->tx_cb->cb_command = htole16(sc->tx_cmd | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_S | FXP_CB_COMMAND_I); - txp->tx_cb->tx_threshold = tx_threshold; + if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0) + txp->tx_cb->tx_threshold = tx_threshold; /* * Advance the end of list forward. @@ -2097,7 +2187,7 @@ fxp_init_body(struct fxp_softc *sc) cbp->disc_short_rx = !prm; /* discard short packets */ cbp->underrun_retry = 1; /* retry mode (once) on DMA underrun */ cbp->two_frames = 0; /* do not limit FIFO to 2 frames */ - cbp->dyn_tbd = 0; /* (no) dynamic TBD mode */ + cbp->dyn_tbd = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; cbp->ext_rfa = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; cbp->mediatype = sc->flags & FXP_FLAG_SERIAL_MEDIA ? 0 : 1; cbp->csma_dis = 0; /* (don't) disable link */ @@ -2589,6 +2679,14 @@ fxp_ioctl(struct ifnet *ifp, u_long comm if ((sc->flags & FXP_FLAG_82559_RXCSUM) != 0) reinit++; } + if ((mask & IFCAP_TSO4) != 0 && + (ifp->if_capabilities & IFCAP_TSO4) != 0) { + ifp->if_capenable ^= IFCAP_TSO4; + if ((ifp->if_capenable & IFCAP_TSO4) != 0) + ifp->if_hwassist |= CSUM_TSO; + else + ifp->if_hwassist &= ~CSUM_TSO; + } if ((mask & IFCAP_VLAN_MTU) != 0 && (ifp->if_capabilities & IFCAP_VLAN_MTU) != 0) { ifp->if_capenable ^= IFCAP_VLAN_MTU; Modified: stable/7/sys/dev/fxp/if_fxpreg.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:46:15 2009 (r188373) +++ stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:48:49 2009 (r188374) @@ -292,7 +292,7 @@ struct fxp_cb_tx { */ union { struct fxp_ipcb ipcb; - struct fxp_tbd tbd[FXP_NTXSEG]; + struct fxp_tbd tbd[FXP_NTXSEG + 1]; } tx_cb_u; }; Modified: stable/7/sys/dev/fxp/if_fxpvar.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:46:15 2009 (r188373) +++ stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:48:49 2009 (r188374) @@ -41,6 +41,11 @@ #define FXP_NTXCB_HIWAT ((FXP_NTXCB * 7) / 10) /* + * Maximum size of a DMA segment. + */ +#define FXP_TSO_SEGSIZE 4096 + +/* * Size of the TxCB list. */ #define FXP_TXCB_SZ (FXP_NTXCB * sizeof(struct fxp_cb_tx)) @@ -157,6 +162,7 @@ struct fxp_softc { bus_dmamap_t spare_map; /* spare DMA map */ struct fxp_desc_list fxp_desc; /* descriptors management struct */ int maxtxseg; /* maximum # of TX segments */ + int maxsegsize; /* maximum size of a TX segment */ int tx_queued; /* # of active TxCB's */ int need_mcsetup; /* multicast filter needs programming */ struct fxp_stats *fxp_stats; /* Pointer to interface stats */ From yongari at FreeBSD.org Sun Feb 8 19:53:21 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:53:39 2009 Subject: svn commit: r188375 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp Message-ID: <200902090353.n193rKkw044451@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:53:20 2009 New Revision: 188375 URL: http://svn.freebsd.org/changeset/base/188375 Log: MFC r185354,185538: r185354: Add basic WOL support for 82550/82551/82558 and 82559 based controllers. ICH based controllers are treated as 82559. 82557, earlier revision of 82558 and 82559ER have no WOL capability. o WOL support requires help of a firmware so add check whether hardware is capable of handling magic frames by reading EEPROM. o Enable accepting WOL frames only when hardware is about to suspend or shutdown. Previously fxp(4) used to allow receipt of magic frame under normal operation mode which could cause hardware hang if magic frame is received by hardware. Datasheet clearly states driver should not allow WOL frames under normal operation mode. o Disable WOL frame reception in device attach so have fxp(4) immunize against system hang which can be triggered by magic packets when the hardware is not in fully initialized state. o Don't reset all hardware configuration data in fxp_stop() otherwise important configuration data is lost and this would reset WOL configuration to default state which in turn cause hardware hang on receipt of magic frames. To fix the issue, preserve hardware configuration data by issuing a selective reset. o Explicitly disable interrupts after issuing selective reset as reset may unmask interrupts. r185538: Make sure to clear PMDR register by writing back power management events. Just reading PMDR register was not enough to have fxp(4) immuninize against received magic packets during system boot. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c stable/7/sys/dev/fxp/if_fxpreg.h stable/7/sys/dev/fxp/if_fxpvar.h Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:48:49 2009 (r188374) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:53:20 2009 (r188375) @@ -405,7 +405,7 @@ fxp_attach(device_t dev) uint32_t val; uint16_t data, myea[ETHER_ADDR_LEN / 2]; u_char eaddr[ETHER_ADDR_LEN]; - int i, prefer_iomap; + int i, pmc, prefer_iomap; int error; error = 0; @@ -483,6 +483,17 @@ fxp_attach(device_t dev) sc->revision = pci_get_revid(dev); /* + * Check availability of WOL. 82559ER does not support WOL. + */ + if (sc->revision >= FXP_REV_82558_A4 && + sc->revision != FXP_REV_82559S_A) { + fxp_read_eeprom(sc, &data, 10, 1); + if ((data & 0x20) != 0 && + pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) + sc->flags |= FXP_FLAG_WOLCAP; + } + + /* * Determine whether we must use the 503 serial interface. */ fxp_read_eeprom(sc, &data, 6, 1); @@ -796,6 +807,11 @@ fxp_attach(device_t dev) ifp->if_capenable |= IFCAP_RXCSUM; } + if (sc->flags & FXP_FLAG_WOLCAP) { + ifp->if_capabilities |= IFCAP_WOL_MAGIC; + ifp->if_capenable |= IFCAP_WOL_MAGIC; + } + #ifdef DEVICE_POLLING /* Inform the world we support polling. */ ifp->if_capabilities |= IFCAP_POLLING; @@ -834,6 +850,19 @@ fxp_attach(device_t dev) goto fail; } + /* + * Configure hardware to reject magic frames otherwise + * system will hang on recipt of magic frames. + */ + if ((sc->flags & FXP_FLAG_WOLCAP) != 0) { + FXP_LOCK(sc); + /* Clear wakeup events. */ + CSR_WRITE_1(sc, FXP_CSR_PMDR, CSR_READ_1(sc, FXP_CSR_PMDR)); + fxp_init_body(sc); + fxp_stop(sc); + FXP_UNLOCK(sc); + } + fail: if (error) fxp_release(sc); @@ -956,17 +985,13 @@ fxp_detach(device_t dev) static int fxp_shutdown(device_t dev) { - struct fxp_softc *sc = device_get_softc(dev); /* * Make sure that DMA is disabled prior to reboot. Not doing * do could allow DMA to corrupt kernel memory during the * reboot before the driver initializes. */ - FXP_LOCK(sc); - fxp_stop(sc); - FXP_UNLOCK(sc); - return (0); + return (fxp_suspend(dev)); } /* @@ -978,9 +1003,25 @@ static int fxp_suspend(device_t dev) { struct fxp_softc *sc = device_get_softc(dev); + struct ifnet *ifp; + int pmc; + uint16_t pmstat; FXP_LOCK(sc); + ifp = sc->ifp; + if (pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) { + pmstat = pci_read_config(sc->dev, pmc + PCIR_POWER_STATUS, 2); + pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); + if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) { + /* Request PME. */ + pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; + sc->flags |= FXP_FLAG_WOL; + /* Reconfigure hardware to accept magic frames. */ + fxp_init_body(sc); + } + pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2); + } fxp_stop(sc); sc->suspended = 1; @@ -998,9 +1039,22 @@ fxp_resume(device_t dev) { struct fxp_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->ifp; + int pmc; + uint16_t pmstat; FXP_LOCK(sc); + if (pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) { + sc->flags &= ~FXP_FLAG_WOL; + pmstat = pci_read_config(sc->dev, pmc + PCIR_POWER_STATUS, 2); + /* Disable PME and clear PME status. */ + pmstat &= ~PCIM_PSTAT_PMEENABLE; + pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2); + if ((sc->flags & FXP_FLAG_WOLCAP) != 0) + CSR_WRITE_1(sc, FXP_CSR_PMDR, + CSR_READ_1(sc, FXP_CSR_PMDR)); + } + CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); DELAY(10); @@ -2015,11 +2069,13 @@ fxp_stop(struct fxp_softc *sc) callout_stop(&sc->stat_ch); /* - * Issue software reset, which also unloads the microcode. + * Preserve PCI configuration, configure, IA/multicast + * setup and put RU and CU into idle state. */ - sc->flags &= ~FXP_FLAG_UCODE; - CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET); + CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); DELAY(50); + /* Disable interrupts. */ + CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE); /* * Release any xmit buffers. @@ -2099,6 +2155,13 @@ fxp_init_body(struct fxp_softc *sc) */ fxp_stop(sc); + /* + * Issue software reset, which also unloads the microcode. + */ + sc->flags &= ~FXP_FLAG_UCODE; + CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET); + DELAY(50); + prm = (ifp->if_flags & IFF_PROMISC) ? 1 : 0; /* @@ -2215,8 +2278,7 @@ fxp_init_body(struct fxp_softc *sc) cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */ cbp->long_rx_en = sc->flags & FXP_FLAG_LONG_PKT_EN ? 1 : 0; cbp->ia_wake_en = 0; /* (don't) wake up on address match */ - cbp->magic_pkt_dis = 0; /* (don't) disable magic packet */ - /* must set wake_en in PMCSR also */ + cbp->magic_pkt_dis = sc->flags & FXP_FLAG_WOL ? 0 : 1; cbp->force_fdx = 0; /* (don't) force full duplex */ cbp->fdx_pin_en = 1; /* (enable) FDX# pin */ cbp->multi_ia = 0; /* (don't) accept multiple IAs */ @@ -2687,6 +2749,9 @@ fxp_ioctl(struct ifnet *ifp, u_long comm else ifp->if_hwassist &= ~CSUM_TSO; } + if ((mask & IFCAP_WOL_MAGIC) != 0 && + (ifp->if_capabilities & IFCAP_WOL_MAGIC) != 0) + ifp->if_capenable ^= IFCAP_WOL_MAGIC; if ((mask & IFCAP_VLAN_MTU) != 0 && (ifp->if_capabilities & IFCAP_VLAN_MTU) != 0) { ifp->if_capenable ^= IFCAP_VLAN_MTU; Modified: stable/7/sys/dev/fxp/if_fxpreg.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:48:49 2009 (r188374) +++ stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:53:20 2009 (r188375) @@ -46,6 +46,7 @@ #define FXP_CSR_EEPROMCONTROL 14 /* eeprom control (2 bytes) */ #define FXP_CSR_MDICONTROL 16 /* mdi control (4 bytes) */ #define FXP_CSR_FLOWCONTROL 0x19 /* flow control (2 bytes) */ +#define FXP_CSR_PMDR 0x1B /* power management driver (1 byte) */ #define FXP_CSR_GENCONTROL 0x1C /* general control (1 byte) */ /* Modified: stable/7/sys/dev/fxp/if_fxpvar.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:48:49 2009 (r188374) +++ stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:53:20 2009 (r188375) @@ -201,6 +201,8 @@ struct fxp_softc { #define FXP_FLAG_EXT_RFA 0x0400 /* extended RFDs for csum offload */ #define FXP_FLAG_SAVE_BAD 0x0800 /* save bad pkts: bad size, CRC, etc */ #define FXP_FLAG_82559_RXCSUM 0x1000 /* 82559 compatible RX checksum */ +#define FXP_FLAG_WOLCAP 0x2000 /* WOL capability */ +#define FXP_FLAG_WOL 0x4000 /* WOL active */ /* Macros to ease CSR access. */ #define CSR_READ_1(sc, reg) bus_read_1(sc->fxp_res[0], reg) From yongari at FreeBSD.org Sun Feb 8 19:55:52 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:56:09 2009 Subject: svn commit: r188376 - in stable/7/sys: . contrib/pf dev/cxgb dev/fxp Message-ID: <200902090355.n193tpNJ044569@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:55:51 2009 New Revision: 188376 URL: http://svn.freebsd.org/changeset/base/188376 Log: MFC r185540: Add VLAN hardware tag insertion/stripping support. Tx/Rx checksum offload for VLAN frames are also supported. The VLAN hardware assistance is available only on 82550/82551 based controllers. While I'm here change the confusing name of bit1 in byte 22 of configuration block to vlan_drop_en. The bit controls whether hardware strips VLAN tagged frame or not. Special thanks to wpaul who sent valuable VLAN related information to me. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c stable/7/sys/dev/fxp/if_fxpreg.h Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:53:20 2009 (r188375) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:55:51 2009 (r188376) @@ -830,6 +830,12 @@ fxp_attach(device_t dev) ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities |= IFCAP_VLAN_MTU; ifp->if_capenable |= IFCAP_VLAN_MTU; /* the hw bits already set */ + if ((sc->flags & FXP_FLAG_EXT_RFA) != 0) { + ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | + IFCAP_VLAN_HWCSUM; + ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | + IFCAP_VLAN_HWCSUM; + } /* * Let the system queue as many packets as we have available @@ -1554,6 +1560,12 @@ fxp_encap(struct fxp_softc *sc, struct m FXP_IPCB_TCP_PACKET | FXP_IPCB_TCPUDP_CHECKSUM_ENABLE; } + /* Configure VLAN hardware tag insertion. */ + if ((m->m_flags & M_VLANTAG) != 0) { + cbp->ipcb_vlan_id = htons(m->m_pkthdr.ether_vtag); + txp->tx_cb->ipcb_ip_activation_high |= + FXP_IPCB_INSERTVLAN_ENABLE; + } txp->tx_mbuf = m; txp->tx_cb->cb_status = 0; @@ -1913,6 +1925,12 @@ fxp_intr_body(struct fxp_softc *sc, stru /* Do IP checksum checking. */ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) fxp_rxcsum(sc, ifp, m, status, total_len); + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && + (status & FXP_RFA_STATUS_VLAN) != 0) { + m->m_pkthdr.ether_vtag = + ntohs(rfa->rfax_vlan_id); + m->m_flags |= M_VLANTAG; + } /* * Drop locks before calling if_input() since it * may re-enter fxp_start() in the netisr case. @@ -2284,6 +2302,8 @@ fxp_init_body(struct fxp_softc *sc) cbp->multi_ia = 0; /* (don't) accept multiple IAs */ cbp->mc_all = sc->flags & FXP_FLAG_ALL_MCAST ? 1 : 0; cbp->gamla_rx = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; + cbp->vlan_strip_en = ((sc->flags & FXP_FLAG_EXT_RFA) != 0 && + (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) ? 1 : 0; if (sc->tunable_noflow || sc->revision == FXP_REV_82557) { /* @@ -2763,9 +2783,15 @@ fxp_ioctl(struct ifnet *ifp, u_long comm if (ifp->if_flags & IFF_UP) reinit++; } - if (reinit > 0) + if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && + (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) { + ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + reinit++; + } + if (reinit > 0 && ifp->if_flags & IFF_UP) fxp_init_body(sc); FXP_UNLOCK(sc); + VLAN_CAPABILITIES(ifp); break; default: Modified: stable/7/sys/dev/fxp/if_fxpreg.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:53:20 2009 (r188375) +++ stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:55:51 2009 (r188376) @@ -224,7 +224,7 @@ struct fxp_cb_config { /* Bytes 22 - 31 -- i82550 only */ u_int __FXP_BITFIELD3(gamla_rx:1, - vlan_drop_en:1, + vlan_strip_en:1, :6); uint8_t pad[9]; }; @@ -377,6 +377,7 @@ struct fxp_rfa { #define FXP_RFA_STATUS_RNR 0x0200 /* no resources */ #define FXP_RFA_STATUS_ALIGN 0x0400 /* alignment error */ #define FXP_RFA_STATUS_CRC 0x0800 /* CRC error */ +#define FXP_RFA_STATUS_VLAN 0x1000 /* VLAN tagged frame */ #define FXP_RFA_STATUS_OK 0x2000 /* packet received okay */ #define FXP_RFA_STATUS_C 0x8000 /* packet reception complete */ #define FXP_RFA_CONTROL_SF 0x08 /* simple/flexible memory mode */ From yongari at FreeBSD.org Sun Feb 8 19:58:30 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 19:58:47 2009 Subject: svn commit: r188377 - in stable/7/sys: . contrib/pf dev/cxgb dev/fxp Message-ID: <200902090358.n193wTZh044659@svn.freebsd.org> Author: yongari Date: Mon Feb 9 03:58:29 2009 New Revision: 188377 URL: http://svn.freebsd.org/changeset/base/188377 Log: MFC r185758: mutex.h is needed here. It got it by namespace pollution. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:55:51 2009 (r188376) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:58:29 2009 (r188377) @@ -44,7 +44,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include From yongari at FreeBSD.org Sun Feb 8 20:00:56 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 20:01:02 2009 Subject: svn commit: r188378 - in stable/7/sys: . contrib/pf dev/cxgb dev/fxp Message-ID: <200902090400.n1940tvv044785@svn.freebsd.org> Author: yongari Date: Mon Feb 9 04:00:54 2009 New Revision: 188378 URL: http://svn.freebsd.org/changeset/base/188378 Log: MFC r186262: It seems that we don't need to reserve a TBD to set total TCP payload length in TSO case. Leaving unused TBD also seem to cause SCB timeouts under certain conditions when TSO/non-TSO traffics are active at the same time. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:58:29 2009 (r188377) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 04:00:54 2009 (r188378) @@ -1540,8 +1540,8 @@ fxp_encap(struct fxp_softc *sc, struct m * the chip is an 82550/82551 or not. */ if (sc->flags & FXP_FLAG_EXT_RFA) { - cbp->tbd[i + 2].tb_addr = htole32(segs[i].ds_addr); - cbp->tbd[i + 2].tb_size = htole32(segs[i].ds_len); + cbp->tbd[i + 1].tb_addr = htole32(segs[i].ds_addr); + cbp->tbd[i + 1].tb_size = htole32(segs[i].ds_len); } else { cbp->tbd[i].tb_addr = htole32(segs[i].ds_addr); cbp->tbd[i].tb_size = htole32(segs[i].ds_len); @@ -1550,13 +1550,13 @@ fxp_encap(struct fxp_softc *sc, struct m if (sc->flags & FXP_FLAG_EXT_RFA) { /* Configure dynamic TBD for 82550/82551. */ cbp->tbd_number = 0xFF; - cbp->tbd[nseg + 1].tb_size |= htole32(0x8000); + cbp->tbd[nseg].tb_size |= htole32(0x8000); } else cbp->tbd_number = nseg; /* Configure TSO. */ if (m->m_pkthdr.csum_flags & CSUM_TSO) { cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16); - cbp->tbd[1].tb_size = htole32(tcp_payload << 16); + cbp->tbd[1].tb_size |= htole32(tcp_payload << 16); cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE | FXP_IPCB_IP_CHECKSUM_ENABLE | FXP_IPCB_TCP_PACKET | From yongari at FreeBSD.org Sun Feb 8 20:02:55 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Sun Feb 8 20:03:07 2009 Subject: svn commit: r188379 - in stable/7/sys: . contrib/pf dev/cxgb dev/fxp Message-ID: <200902090402.n1942r56044867@svn.freebsd.org> Author: yongari Date: Mon Feb 9 04:02:53 2009 New Revision: 188379 URL: http://svn.freebsd.org/changeset/base/188379 Log: MFC r186884: Always check whether dma map is valid before unloading the map. When fxp(4) intializes Rx buffers for the first time, there is no loaded dma map so attempting to unload it is an invalid operation. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 04:00:54 2009 (r188378) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 04:02:53 2009 (r188379) @@ -2545,7 +2545,8 @@ fxp_new_rfabuf(struct fxp_softc *sc, str return (error); } - bus_dmamap_unload(sc->fxp_mtag, rxp->rx_map); + if (rxp->rx_mbuf != NULL) + bus_dmamap_unload(sc->fxp_mtag, rxp->rx_map); tmp_map = sc->spare_map; sc->spare_map = rxp->rx_map; rxp->rx_map = tmp_map; From maxim at FreeBSD.org Mon Feb 9 02:28:17 2009 From: maxim at FreeBSD.org (Maxim Konovalov) Date: Mon Feb 9 02:28:34 2009 Subject: svn commit: r188384 - stable/7/libexec/ftpd Message-ID: <200902091028.n19ASGsJ052053@svn.freebsd.org> Author: maxim Date: Mon Feb 9 10:28:16 2009 New Revision: 188384 URL: http://svn.freebsd.org/changeset/base/188384 Log: MFC r187913: fix typo. Modified: stable/7/libexec/ftpd/ftpd.8 Modified: stable/7/libexec/ftpd/ftpd.8 ============================================================================== --- stable/7/libexec/ftpd/ftpd.8 Mon Feb 9 06:23:21 2009 (r188383) +++ stable/7/libexec/ftpd/ftpd.8 Mon Feb 9 10:28:16 2009 (r188384) @@ -205,7 +205,7 @@ for more information. Note that option is a virtual no-op in .Fx 5.0 and above; both port -ranges are indentical by default. +ranges are identical by default. .It Fl u The default file creation mode mask is set to .Ar umask , From kib at FreeBSD.org Mon Feb 9 04:22:50 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Mon Feb 9 04:23:06 2009 Subject: svn commit: r188389 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb fs/fifofs Message-ID: <200902091222.n19CMnfR059846@svn.freebsd.org> Author: kib Date: Mon Feb 9 12:22:49 2009 New Revision: 188389 URL: http://svn.freebsd.org/changeset/base/188389 Log: MFC r187715: The kernel may do unbalanced calls to fifo_close() for fifo vnode, without corresponding number of fifo_open(). This causes assertion failure in fifo_close() due to vp->v_fifoinfo being NULL for kernel with INVARIANTS, or NULL pointer dereference otherwise. In fact, we may ignore excess calls to fifo_close() without bad consequences. Turn KASSERT() into the return, and print warning for now. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/fs/fifofs/fifo_vnops.c Modified: stable/7/sys/fs/fifofs/fifo_vnops.c ============================================================================== --- stable/7/sys/fs/fifofs/fifo_vnops.c Mon Feb 9 11:42:23 2009 (r188388) +++ stable/7/sys/fs/fifofs/fifo_vnops.c Mon Feb 9 12:22:49 2009 (r188389) @@ -424,7 +424,10 @@ fifo_close(ap) struct fifoinfo *fip = vp->v_fifoinfo; ASSERT_VOP_LOCKED(vp, "fifo_close"); - KASSERT(fip != NULL, ("fifo_close: no v_fifoinfo")); + if (fip == NULL) { + printf("fifo_close: no v_fifoinfo %p\n", vp); + return (0); + } if (ap->a_fflag & FREAD) { fip->fi_readers--; if (fip->fi_readers == 0) From emax at FreeBSD.org Mon Feb 9 09:14:51 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Mon Feb 9 09:15:03 2009 Subject: svn commit: r188397 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/kbdmux Message-ID: <200902091714.n19HEndG066252@svn.freebsd.org> Author: emax Date: Mon Feb 9 17:14:49 2009 New Revision: 188397 URL: http://svn.freebsd.org/changeset/base/188397 Log: MFC r188030 Properly retun error core from kbdmux_modevent() Reported by: Christoph Mallon < christoph -dot- mallon -at- gmx -dot- de > Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/kbdmux/kbdmux.c Modified: stable/7/sys/dev/kbdmux/kbdmux.c ============================================================================== --- stable/7/sys/dev/kbdmux/kbdmux.c Mon Feb 9 17:07:29 2009 (r188396) +++ stable/7/sys/dev/kbdmux/kbdmux.c Mon Feb 9 17:14:49 2009 (r188397) @@ -1384,7 +1384,7 @@ kbdmux_modevent(module_t mod, int type, break; } - return (0); + return (error); } DEV_MODULE(kbdmux, kbdmux_modevent, NULL); From emax at FreeBSD.org Mon Feb 9 09:50:20 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Mon Feb 9 09:50:52 2009 Subject: svn commit: r188400 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netgraph/bluetooth/l2cap Message-ID: <200902091750.n19HoJmJ066982@svn.freebsd.org> Author: emax Date: Mon Feb 9 17:50:19 2009 New Revision: 188400 URL: http://svn.freebsd.org/changeset/base/188400 Log: MFC r187454 Properly return error code to the caller. This should fix the following panic in ng_l2cap(4). panic: ng_l2cap_l2ca_con_req: ubt0l2cap - could not find connection! While i'm here get rid of few goto's. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c Modified: stable/7/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c ============================================================================== --- stable/7/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c Mon Feb 9 17:38:16 2009 (r188399) +++ stable/7/sys/netgraph/bluetooth/l2cap/ng_l2cap_llpi.c Mon Feb 9 17:50:19 2009 (r188400) @@ -116,10 +116,14 @@ ng_l2cap_lp_con_req(ng_l2cap_p l2cap, bd NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, 0); if (error != 0) { - if ((error = ng_l2cap_lp_untimeout(con)) != 0) - return (error); + if (ng_l2cap_lp_untimeout(con) == 0) + ng_l2cap_free_con(con); - ng_l2cap_free_con(con); + /* + * Do not free connection if ng_l2cap_lp_untimeout() failed + * let timeout handler deal with it. Always return error to + * the caller. + */ } return (error); @@ -213,8 +217,8 @@ ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, st NG_L2CAP_ALERT( "%s: %s - invalid LP_ConnectInd message size\n", __func__, NG_NODE_NAME(l2cap->node)); - error = EMSGSIZE; - goto out; + + return (EMSGSIZE); } ep = (ng_hci_lp_con_ind_ep *) (msg->data); @@ -227,8 +231,8 @@ ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, st "Connection already exists, state=%d, con_handle=%d\n", __func__, NG_NODE_NAME(l2cap->node), con->state, con->con_handle); - error = EEXIST; - goto out; + + return (EEXIST); } /* Check if lower layer protocol is still connected */ @@ -236,24 +240,22 @@ ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, st NG_L2CAP_ERR( "%s: %s - hook \"%s\" is not connected or valid", __func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI); - error = ENOTCONN; - goto out; + + return (ENOTCONN); } /* Create and intialize new connection descriptor */ con = ng_l2cap_new_con(l2cap, &ep->bdaddr); - if (con == NULL) { - error = ENOMEM; - goto out; - } + if (con == NULL) + return (ENOMEM); /* Create and send LP_ConnectRsp event */ NG_MKMESSAGE(rsp, NGM_HCI_COOKIE, NGM_HCI_LP_CON_RSP, sizeof(*rp), M_NOWAIT); if (rsp == NULL) { ng_l2cap_free_con(con); - error = ENOMEM; - goto out; + + return (ENOMEM); } rp = (ng_hci_lp_con_rsp_ep *)(rsp->data); @@ -266,14 +268,18 @@ ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, st NG_SEND_MSG_HOOK(error, l2cap->node, rsp, l2cap->hci, 0); if (error != 0) { - if ((error = ng_l2cap_lp_untimeout(con)) != 0) - goto out; + if (ng_l2cap_lp_untimeout(con) == 0) + ng_l2cap_free_con(con); - ng_l2cap_free_con(con); + /* + * Do not free connection if ng_l2cap_lp_untimeout() failed + * let timeout handler deal with it. Always return error to + * the caller. + */ } -out: + return (error); -} /* ng_hci_lp_con_ind */ +} /* ng_l2cap_lp_con_ind */ /* * Process LP_DisconnectInd event from the lower layer protocol. We have been From emax at FreeBSD.org Mon Feb 9 09:53:46 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Mon Feb 9 09:54:03 2009 Subject: svn commit: r188401 - in stable/7/sys: . contrib/pf dev/cxgb netgraph/bluetooth/hci Message-ID: <200902091753.n19HrjwG067085@svn.freebsd.org> Author: emax Date: Mon Feb 9 17:53:45 2009 New Revision: 188401 URL: http://svn.freebsd.org/changeset/base/188401 Log: MFC r186466 Change message severity level from WARN to INFO. This should reduce amount of messages sent to syslog Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netgraph/bluetooth/hci/ng_hci_main.c Modified: stable/7/sys/netgraph/bluetooth/hci/ng_hci_main.c ============================================================================== --- stable/7/sys/netgraph/bluetooth/hci/ng_hci_main.c Mon Feb 9 17:50:19 2009 (r188400) +++ stable/7/sys/netgraph/bluetooth/hci/ng_hci_main.c Mon Feb 9 17:53:45 2009 (r188401) @@ -728,7 +728,7 @@ ng_hci_drv_rcvdata(hook_p hook, item_p i if ((unit->state & NG_HCI_UNIT_READY) != NG_HCI_UNIT_READY || unit->sco == NULL || NG_HOOK_NOT_VALID(unit->sco)) { - NG_HCI_WARN( + NG_HCI_INFO( "%s: %s - could not forward HCI SCO data packet, state=%#x, hook=%p\n", __func__, NG_NODE_NAME(unit->node), unit->state, unit->sco); From cognet at FreeBSD.org Mon Feb 9 14:21:40 2009 From: cognet at FreeBSD.org (Olivier Houchard) Date: Mon Feb 9 14:21:52 2009 Subject: svn commit: r188420 - stable/7/sys/arm/arm Message-ID: <200902092221.n19MLcHb073259@svn.freebsd.org> Author: cognet Date: Mon Feb 9 22:21:38 2009 New Revision: 188420 URL: http://svn.freebsd.org/changeset/base/188420 Log: MFC r188112 r188112 | cognet | 2009-02-04 02:14:06 +0100 (Wed, 04 Feb 2009) | 8 lines Erm... Report the buffer as being bounced even when it's the entire buffer, or we would end up invalidating the cache line for what we just copied... Modified: stable/7/sys/arm/arm/busdma_machdep.c Modified: stable/7/sys/arm/arm/busdma_machdep.c ============================================================================== --- stable/7/sys/arm/arm/busdma_machdep.c Mon Feb 9 22:18:11 2009 (r188419) +++ stable/7/sys/arm/arm/busdma_machdep.c Mon Feb 9 22:21:38 2009 (r188420) @@ -1164,7 +1164,7 @@ _bus_dma_buf_is_in_bp(bus_dmamap_t map, STAILQ_FOREACH(bpage, &map->bpages, links) { if ((vm_offset_t)buf >= bpage->datavaddr && - (vm_offset_t)buf + len < bpage->datavaddr + + (vm_offset_t)buf + len <= bpage->datavaddr + bpage->datacount) return (1); } From bms at FreeBSD.org Mon Feb 9 15:00:58 2009 From: bms at FreeBSD.org (Bruce M. Simpson) Date: Mon Feb 9 15:01:04 2009 Subject: svn commit: r188375 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp In-Reply-To: <200902090353.n193rKkw044451@svn.freebsd.org> References: <200902090353.n193rKkw044451@svn.freebsd.org> Message-ID: <4990B1F9.7020009@FreeBSD.org> This looks really cool and I look forward to trying WOL once I have the right combo of cards/machines which should really sleep here. I would ask though: I managed to get WOL working on Linux, but only if the parent ACPI devices have been explicitly activated for wakeup. I wonder if we've addressed that yet? On Linux it's necessary to use acpitool -W to fully enable the WOL capable device to bring the system out of sleep, it seems. From pyunyh at gmail.com Mon Feb 9 17:26:12 2009 From: pyunyh at gmail.com (Pyun YongHyeon) Date: Mon Feb 9 17:26:18 2009 Subject: svn commit: r188375 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp In-Reply-To: <4990B1F9.7020009@FreeBSD.org> References: <200902090353.n193rKkw044451@svn.freebsd.org> <4990B1F9.7020009@FreeBSD.org> Message-ID: <20090210005928.GE98095@michelle.cdnetworks.co.kr> On Mon, Feb 09, 2009 at 10:45:13PM +0000, Bruce M. Simpson wrote: > This looks really cool and I look forward to trying WOL once I have the > right combo of cards/machines which should really sleep here. > > I would ask though: I managed to get WOL working on Linux, but only if > the parent ACPI devices have been explicitly activated for wakeup. I > wonder if we've addressed that yet? > If you mean suspend/resume support on amd64 I don't know. > On Linux it's necessary to use acpitool -W > to fully enable the WOL capable > device to bring the system out of sleep, it seems. I don't use Linux at all except comparing driver performance so I have no idea how Linux WOL works. Resuming with WOL was tested on FreeBSD i386 box and display was not restored to previous state on my box, except that system worked as normal. From kib at FreeBSD.org Tue Feb 10 09:43:50 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Tue Feb 10 09:44:08 2009 Subject: svn commit: r188441 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern ufs/ffs Message-ID: <200902101743.n1AHhmhA099857@svn.freebsd.org> Author: kib Date: Tue Feb 10 17:43:47 2009 New Revision: 188441 URL: http://svn.freebsd.org/changeset/base/188441 Log: MFC r187467: Change vinvalbuf() to not remove any pages from the object when V_NORMAL or V_ALT are specified. Instead, the only in-tree caller in ffs_inode.c:ffs_truncate() that specifies V_ALT explicitely removes the corresponding page range. The V_NORMAL caller does vnode_pager_setsize(vp, 0) immediately after the call to vinvalbuf(V_NORMAL) already. MFC r187490: The r187467 should remove all pages for V_NORMAL case too, because indirect block pages are not removed by the mentioned invocation of the vnode_pager_setsize(). Put a common code into the helper function ffs_pages_remove(). Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/vfs_subr.c stable/7/sys/ufs/ffs/ffs_inode.c Modified: stable/7/sys/kern/vfs_subr.c ============================================================================== --- stable/7/sys/kern/vfs_subr.c Tue Feb 10 15:50:19 2009 (r188440) +++ stable/7/sys/kern/vfs_subr.c Tue Feb 10 17:43:47 2009 (r188441) @@ -1103,7 +1103,7 @@ bufobj_invalbuf(struct bufobj *bo, int f /* * Destroy the copy in the VM cache, too. */ - if (bo->bo_object != NULL) { + if (bo->bo_object != NULL && (flags & (V_ALT | V_NORMAL)) == 0) { VM_OBJECT_LOCK(bo->bo_object); vm_object_page_remove(bo->bo_object, 0, 0, (flags & V_SAVE) ? TRUE : FALSE); Modified: stable/7/sys/ufs/ffs/ffs_inode.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_inode.c Tue Feb 10 15:50:19 2009 (r188440) +++ stable/7/sys/ufs/ffs/ffs_inode.c Tue Feb 10 17:43:47 2009 (r188441) @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -128,6 +129,18 @@ ffs_update(vp, waitfor) } } +static void +ffs_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end) +{ + vm_object_t object; + + if ((object = vp->v_object) == NULL) + return; + VM_OBJECT_LOCK(object); + vm_object_page_remove(object, start, end, FALSE); + VM_OBJECT_UNLOCK(object); +} + #define SINGLE 0 /* index of single indirect block */ #define DOUBLE 1 /* index of double indirect block */ #define TRIPLE 2 /* index of triple indirect block */ @@ -203,6 +216,8 @@ ffs_truncate(vp, length, flags, cred, td (void) chkdq(ip, -extblocks, NOCRED, 0); #endif vinvalbuf(vp, V_ALT, td, 0, 0); + ffs_pages_remove(vp, + OFF_TO_IDX(lblktosize(fs, -extblocks)), 0); ip->i_din2->di_extsize = 0; for (i = 0; i < NXADDR; i++) { oldblks[i] = ip->i_din2->di_extb[i]; @@ -279,6 +294,9 @@ ffs_truncate(vp, length, flags, cred, td IO_EXT | IO_NORMAL : IO_NORMAL); ASSERT_VOP_LOCKED(vp, "ffs_truncate1"); vinvalbuf(vp, needextclean ? 0 : V_NORMAL, td, 0, 0); + if (!needextclean) + ffs_pages_remove(vp, 0, + OFF_TO_IDX(lblktosize(fs, -extblocks))); vnode_pager_setsize(vp, 0); ip->i_flag |= IN_CHANGE | IN_UPDATE; return (ffs_update(vp, 0)); From kib at FreeBSD.org Tue Feb 10 09:47:36 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Tue Feb 10 09:47:43 2009 Subject: svn commit: r188442 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb ufs/ffs Message-ID: <200902101747.n1AHlZMK099980@svn.freebsd.org> Author: kib Date: Tue Feb 10 17:47:35 2009 New Revision: 188442 URL: http://svn.freebsd.org/changeset/base/188442 Log: MFC r187468: Revert vnode_pager_setsize() back when UFS_BALLOC() failed, for ffs_truncate() and ffs_write(). Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/ufs/ffs/ffs_inode.c stable/7/sys/ufs/ffs/ffs_vnops.c Modified: stable/7/sys/ufs/ffs/ffs_inode.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_inode.c Tue Feb 10 17:43:47 2009 (r188441) +++ stable/7/sys/ufs/ffs/ffs_inode.c Tue Feb 10 17:47:35 2009 (r188442) @@ -312,8 +312,10 @@ ffs_truncate(vp, length, flags, cred, td vnode_pager_setsize(vp, length); flags |= BA_CLRBUF; error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp); - if (error) + if (error) { + vnode_pager_setsize(vp, osize); return (error); + } ip->i_size = length; DIP_SET(ip, i_size, length); if (bp->b_bufsize == fs->fs_bsize) Modified: stable/7/sys/ufs/ffs/ffs_vnops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vnops.c Tue Feb 10 17:43:47 2009 (r188441) +++ stable/7/sys/ufs/ffs/ffs_vnops.c Tue Feb 10 17:47:35 2009 (r188442) @@ -723,8 +723,10 @@ ffs_write(ap) /* XXX is uio->uio_offset the right thing here? */ error = UFS_BALLOC(vp, uio->uio_offset, xfersize, ap->a_cred, flags, &bp); - if (error != 0) + if (error != 0) { + vnode_pager_setsize(vp, ip->i_size); break; + } /* * If the buffer is not valid we have to clear out any * garbage data from the pages instantiated for the buffer. From kib at FreeBSD.org Tue Feb 10 09:50:06 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Tue Feb 10 09:50:18 2009 Subject: svn commit: r188443 - in stable/7/sys: . amd64/amd64 contrib/pf dev/ath/ath_hal dev/cxgb Message-ID: <200902101750.n1AHo3WQ000176@svn.freebsd.org> Author: kib Date: Tue Feb 10 17:50:03 2009 New Revision: 188443 URL: http://svn.freebsd.org/changeset/base/188443 Log: MFC r187470: Unconditionally reload fsbase when switching to 32bit binary. Modified: stable/7/sys/ (props changed) stable/7/sys/amd64/amd64/cpu_switch.S stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/amd64/amd64/cpu_switch.S ============================================================================== --- stable/7/sys/amd64/amd64/cpu_switch.S Tue Feb 10 17:47:35 2009 (r188442) +++ stable/7/sys/amd64/amd64/cpu_switch.S Tue Feb 10 17:50:03 2009 (r188443) @@ -199,6 +199,7 @@ done_load_seg: cmpq PCB_FSBASE(%r8),%r9 jz 1f /* Restore userland %fs */ +restore_fsbase: movl $MSR_FSBASE,%ecx movl PCB_FSBASE(%r8),%eax movl PCB_FSBASE+4(%r8),%edx @@ -281,7 +282,7 @@ load_seg: movl PCB_DS(%r8),%ds movl PCB_ES(%r8),%es movl PCB_FS(%r8),%fs - jmp done_load_seg + jmp restore_fsbase /* Restore userland %gs while preserving kernel gsbase */ 2: movq PCPU(GS32P),%rax movq PCB_GS32SD(%r8),%rcx From emax at FreeBSD.org Tue Feb 10 12:03:27 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Tue Feb 10 12:03:44 2009 Subject: svn commit: r188449 - stable/7/share/man/man4 Message-ID: <200902102003.n1AK3QQD002938@svn.freebsd.org> Author: emax Date: Tue Feb 10 20:03:26 2009 New Revision: 188449 URL: http://svn.freebsd.org/changeset/base/188449 Log: MFC r182881 Document TAPGIFNAME, TAPSIFINFO and TAPGIFINFO tap(4) character device ioctl's. Modified: stable/7/share/man/man4/ (props changed) stable/7/share/man/man4/igb.4 (props changed) stable/7/share/man/man4/tap.4 Modified: stable/7/share/man/man4/tap.4 ============================================================================== --- stable/7/share/man/man4/tap.4 Tue Feb 10 19:37:38 2009 (r188448) +++ stable/7/share/man/man4/tap.4 Tue Feb 10 20:03:26 2009 (r188449) @@ -1,7 +1,7 @@ .\" $FreeBSD$ .\" Based on PR#2411 .\" -.Dd March 19, 2007 +.Dd September 8, 2008 .Os .Dt TAP 4 .Sh NAME @@ -163,6 +163,14 @@ calls are supported (defined in .In net/if_tap.h ) : .Bl -tag -width VMIO_SIOCSETMACADDR +.It Dv TAPSIFINFO +Set network interface information (line speed, MTU and type). +The argument should be a pointer to a +.Va struct tapinfo . +.It Dv TAPGIFINFO +Retrieve network interface information (line speed, MTU and type). +The argument should be a pointer to a +.Va struct tapinfo . .It Dv TAPSDEBUG The argument should be a pointer to an .Va int ; @@ -174,6 +182,13 @@ code. The argument should be a pointer to an .Va int ; this stores the internal debugging variable's value into it. +.It Dv TAPGIFNAME +Retrieve network interface name. +The argument should be a pointer to a +.Va struct ifreq . +The interface name will be returned in the +.Va ifr_name +field. .It Dv FIONBIO Turn non-blocking I/O for reads off or on, according as the argument .Va int Ns 's From emax at FreeBSD.org Tue Feb 10 12:04:23 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Tue Feb 10 12:04:33 2009 Subject: svn commit: r188450 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb net Message-ID: <200902102004.n1AK4KgW002994@svn.freebsd.org> Author: emax Date: Tue Feb 10 20:04:20 2009 New Revision: 188450 URL: http://svn.freebsd.org/changeset/base/188450 Log: MFC r182880$$ Add new TAPGIFNAME tap(4) character device ioctl. This is a convenient shortcut to obtain network interface name using file descriptor for character device. Obtained from: NetBSD Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/net/if_tap.c stable/7/sys/net/if_tap.h Modified: stable/7/sys/net/if_tap.c ============================================================================== --- stable/7/sys/net/if_tap.c Tue Feb 10 20:03:26 2009 (r188449) +++ stable/7/sys/net/if_tap.c Tue Feb 10 20:04:20 2009 (r188450) @@ -745,6 +745,12 @@ tapioctl(struct cdev *dev, u_long cmd, c *(int *)data = tapdebug; break; + case TAPGIFNAME: { + struct ifreq *ifr = (struct ifreq *) data; + + strlcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ); + } break; + case FIONBIO: break; Modified: stable/7/sys/net/if_tap.h ============================================================================== --- stable/7/sys/net/if_tap.h Tue Feb 10 20:03:26 2009 (r188449) +++ stable/7/sys/net/if_tap.h Tue Feb 10 20:04:20 2009 (r188450) @@ -55,6 +55,7 @@ struct tapinfo { #define TAPGDEBUG _IOR('t', 89, int) #define TAPSIFINFO _IOW('t', 91, struct tapinfo) #define TAPGIFINFO _IOR('t', 92, struct tapinfo) +#define TAPGIFNAME _IOR('t', 93, struct ifreq) /* VMware ioctl's */ #define VMIO_SIOCSIFFLAGS _IOWINT('V', 0) From emax at FreeBSD.org Tue Feb 10 12:08:05 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Tue Feb 10 12:08:11 2009 Subject: svn commit: r188451 - stable/7/usr.sbin/bluetooth/sdpd Message-ID: <200902102008.n1AK83fs003103@svn.freebsd.org> Author: emax Date: Tue Feb 10 20:08:03 2009 New Revision: 188451 URL: http://svn.freebsd.org/changeset/base/188451 Log: MFC r185320 Straighten out those pesky SDP records for the Bluetooth Service Discovery Application Profile. Discussed with: Iain Hibbert of NetBSD plunky at rya dash online dot net Modified: stable/7/usr.sbin/bluetooth/sdpd/ (props changed) stable/7/usr.sbin/bluetooth/sdpd/sd.c Modified: stable/7/usr.sbin/bluetooth/sdpd/sd.c ============================================================================== --- stable/7/usr.sbin/bluetooth/sdpd/sd.c Tue Feb 10 20:04:20 2009 (r188450) +++ stable/7/usr.sbin/bluetooth/sdpd/sd.c Tue Feb 10 20:08:03 2009 (r188451) @@ -52,6 +52,22 @@ sd_profile_create_service_class_id_list( } static int32_t +sd_profile_create_bluetooth_profile_descriptor_list( + uint8_t *buf, uint8_t const * const eob, + uint8_t const *data, uint32_t datalen) +{ + static uint16_t profile_descriptor_list[] = { + SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, + 0x0100 + }; + + return (common_profile_create_bluetooth_profile_descriptor_list( + buf, eob, + (uint8_t const *) profile_descriptor_list, + sizeof(profile_descriptor_list))); +} + +static int32_t sd_profile_create_service_id( uint8_t *buf, uint8_t const * const eob, uint8_t const *data, uint32_t datalen) @@ -89,25 +105,23 @@ sd_profile_create_protocol_descriptor_li uint8_t *buf, uint8_t const * const eob, uint8_t const *data, uint32_t datalen) { - if (buf + 13 > eob) + if (buf + 12 > eob) return (-1); SDP_PUT8(SDP_DATA_SEQ8, buf); - SDP_PUT8(11, buf); + SDP_PUT8(10, buf); SDP_PUT8(SDP_DATA_SEQ8, buf); - SDP_PUT8(9, buf); - + SDP_PUT8(3, buf); SDP_PUT8(SDP_DATA_UUID16, buf); SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf); - SDP_PUT8(SDP_DATA_UINT16, buf); - SDP_PUT16(NG_L2CAP_PSM_SDP, buf); - - SDP_PUT8(SDP_DATA_UINT16, buf); - SDP_PUT16(1, buf); /* version */ + SDP_PUT8(SDP_DATA_SEQ8, buf); + SDP_PUT8(3, buf); + SDP_PUT8(SDP_DATA_UUID16, buf); + SDP_PUT16(SDP_UUID_PROTOCOL_SDP, buf); - return (13); + return (12); } static int32_t @@ -182,6 +196,8 @@ static attr_t sd_profile_attrs[] = { common_profile_create_service_record_handle }, { SDP_ATTR_SERVICE_CLASS_ID_LIST, sd_profile_create_service_class_id_list }, + { SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, + sd_profile_create_bluetooth_profile_descriptor_list }, { SDP_ATTR_SERVICE_ID, sd_profile_create_service_id }, { SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST, From emax at FreeBSD.org Tue Feb 10 13:09:55 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Tue Feb 10 13:10:45 2009 Subject: svn commit: r188454 - in stable/7/lib/libc: . string uuid Message-ID: <200902102109.n1AL9s3j004415@svn.freebsd.org> Author: emax Date: Tue Feb 10 21:09:54 2009 New Revision: 188454 URL: http://svn.freebsd.org/changeset/base/188454 Log: MFC r183058 Add uuid_enc,dec_le,be() functions to Symbol.map Pointy hat goes to me. MFC r183192 Move uuid_enc_le, uuid_dec_le, uuid_enc_be and uuid_dec_be symbols into FBSD_1.1 section where they should be (as Pointed out by: kib, deischen) Modified: stable/7/lib/libc/ (props changed) stable/7/lib/libc/string/ffsll.c (props changed) stable/7/lib/libc/string/flsll.c (props changed) stable/7/lib/libc/uuid/Symbol.map Modified: stable/7/lib/libc/uuid/Symbol.map ============================================================================== --- stable/7/lib/libc/uuid/Symbol.map Tue Feb 10 20:29:57 2009 (r188453) +++ stable/7/lib/libc/uuid/Symbol.map Tue Feb 10 21:09:54 2009 (r188454) @@ -12,3 +12,10 @@ FBSD_1.0 { uuid_create; uuid_compare; }; + +FBSD_1.1 { + uuid_enc_le; + uuid_dec_le; + uuid_enc_be; + uuid_dec_be; +}; From maxim at FreeBSD.org Wed Feb 11 02:28:57 2009 From: maxim at FreeBSD.org (Maxim Konovalov) Date: Wed Feb 11 02:29:03 2009 Subject: svn commit: r188479 - stable/7/usr.bin/netstat Message-ID: <200902111028.n1BAStLU020668@svn.freebsd.org> Author: maxim Date: Wed Feb 11 10:28:55 2009 New Revision: 188479 URL: http://svn.freebsd.org/changeset/base/188479 Log: MFC r186644: show unix sockets listen queues stats with -L flag. Modified: stable/7/usr.bin/netstat/ (props changed) stable/7/usr.bin/netstat/main.c stable/7/usr.bin/netstat/unix.c Modified: stable/7/usr.bin/netstat/main.c ============================================================================== --- stable/7/usr.bin/netstat/main.c Wed Feb 11 09:18:09 2009 (r188478) +++ stable/7/usr.bin/netstat/main.c Wed Feb 11 10:28:55 2009 (r188479) @@ -589,7 +589,7 @@ main(int argc, char *argv[]) for (tp = netgraphprotox; tp->pr_name; tp++) printproto(tp, tp->pr_name); #endif /* NETGRAPH */ - if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) + if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value); exit(0); Modified: stable/7/usr.bin/netstat/unix.c ============================================================================== --- stable/7/usr.bin/netstat/unix.c Wed Feb 11 09:18:09 2009 (r188478) +++ stable/7/usr.bin/netstat/unix.c Wed Feb 11 10:28:55 2009 (r188479) @@ -247,6 +247,7 @@ unixdomainpr(struct xunpcb *xunp, struct struct unpcb *unp; struct sockaddr_un *sa; static int first = 1; + char buf1[15]; unp = &xunp->xu_unp; if (unp->unp_addr) @@ -254,7 +255,7 @@ unixdomainpr(struct xunpcb *xunp, struct else sa = (struct sockaddr_un *)0; - if (first) { + if (first && !Lflag) { printf("Active UNIX domain sockets\n"); printf( "%-8.8s %-6.6s %-6.6s %-6.6s %8.8s %8.8s %8.8s %8.8s Addr\n", @@ -262,11 +263,21 @@ unixdomainpr(struct xunpcb *xunp, struct "Inode", "Conn", "Refs", "Nextref"); first = 0; } - printf("%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx", - (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc, - so->so_snd.sb_cc, - (long)unp->unp_vnode, (long)unp->unp_conn, - (long)LIST_FIRST(&unp->unp_refs), (long)LIST_NEXT(unp, unp_reflink)); + + if (Lflag && so->so_qlimit == 0) + return; + + if (Lflag) { + snprintf(buf1, 15, "%d/%d/%d", so->so_qlen, + so->so_incqlen, so->so_qlimit); + printf("unix %-14.14s", buf1); + } else { + printf("%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx", + (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc, + so->so_snd.sb_cc, (long)unp->unp_vnode, (long)unp->unp_conn, + (long)LIST_FIRST(&unp->unp_refs), + (long)LIST_NEXT(unp, unp_reflink)); + } if (sa) printf(" %.*s", (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)), From jhb at FreeBSD.org Thu Feb 12 06:38:00 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 12 06:38:06 2009 Subject: svn commit: r188514 - in stable/7/sys: . contrib/pf dev/cxgb libkern Message-ID: <200902121437.n1CEbwUe058325@svn.freebsd.org> Author: jhb Date: Thu Feb 12 14:37:58 2009 New Revision: 188514 URL: http://svn.freebsd.org/changeset/base/188514 Log: MFC: Add simple locking for the in-kernel iconv code. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/libkern/iconv.c Modified: stable/7/sys/libkern/iconv.c ============================================================================== --- stable/7/sys/libkern/iconv.c Thu Feb 12 13:49:51 2009 (r188513) +++ stable/7/sys/libkern/iconv.c Thu Feb 12 14:37:58 2009 (r188514) @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include "iconv_converter_if.h" @@ -52,6 +53,8 @@ MALLOC_DEFINE(M_ICONVDATA, "iconv_data", MODULE_VERSION(libiconv, 2); +static struct sx iconv_lock; + #ifdef notnow /* * iconv converter instance @@ -86,11 +89,16 @@ iconv_mod_unload(void) { struct iconv_cspair *csp; + sx_xlock(&iconv_lock); while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL) { if (csp->cp_refcount) return EBUSY; - iconv_unregister_cspair(csp); } + + while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL) + iconv_unregister_cspair(csp); + sx_xunlock(&iconv_lock); + sx_destroy(&iconv_lock); return 0; } @@ -102,6 +110,7 @@ iconv_mod_handler(module_t mod, int type switch (type) { case MOD_LOAD: error = 0; + sx_init(&iconv_lock, "iconv"); break; case MOD_UNLOAD: error = iconv_mod_unload(); @@ -311,7 +320,7 @@ iconv_sysctl_drvlist(SYSCTL_HANDLER_ARGS int error; error = 0; - + sx_slock(&iconv_lock); TAILQ_FOREACH(dcp, &iconv_converters, cc_link) { name = ICONV_CONVERTER_NAME(dcp); if (name == NULL) @@ -320,6 +329,7 @@ iconv_sysctl_drvlist(SYSCTL_HANDLER_ARGS if (error) break; } + sx_sunlock(&iconv_lock); if (error) return error; spc = 0; @@ -343,7 +353,7 @@ iconv_sysctl_cslist(SYSCTL_HANDLER_ARGS) error = 0; bzero(&csi, sizeof(csi)); csi.cs_version = ICONV_CSPAIR_INFO_VER; - + sx_slock(&iconv_lock); TAILQ_FOREACH(csp, &iconv_cslist, cp_link) { csi.cs_id = csp->cp_id; csi.cs_refcount = csp->cp_refcount; @@ -354,6 +364,7 @@ iconv_sysctl_cslist(SYSCTL_HANDLER_ARGS) if (error) break; } + sx_sunlock(&iconv_lock); return error; } @@ -387,9 +398,12 @@ iconv_sysctl_add(SYSCTL_HANDLER_ARGS) return EINVAL; if (iconv_lookupconv(din.ia_converter, &dcp) != 0) return EINVAL; + sx_xlock(&iconv_lock); error = iconv_register_cspair(din.ia_to, din.ia_from, dcp, NULL, &csp); - if (error) + if (error) { + sx_xunlock(&iconv_lock); return error; + } if (din.ia_datalen) { csp->cp_data = malloc(din.ia_datalen, M_ICONVDATA, M_WAITOK); error = copyin(din.ia_data, csp->cp_data, din.ia_datalen); @@ -400,10 +414,12 @@ iconv_sysctl_add(SYSCTL_HANDLER_ARGS) error = SYSCTL_OUT(req, &dout, sizeof(dout)); if (error) goto bad; + sx_xunlock(&iconv_lock); ICDEBUG("%s => %s, %d bytes\n",din.ia_from, din.ia_to, din.ia_datalen); return 0; bad: iconv_unregister_cspair(csp); + sx_xunlock(&iconv_lock); return error; } @@ -433,16 +449,22 @@ iconv_converter_handler(module_t mod, in switch (type) { case MOD_LOAD: + sx_xlock(&iconv_lock); error = iconv_register_converter(dcp); - if (error) + if (error) { + sx_xunlock(&iconv_lock); break; + } error = ICONV_CONVERTER_INIT(dcp); if (error) iconv_unregister_converter(dcp); + sx_xunlock(&iconv_lock); break; case MOD_UNLOAD: + sx_xlock(&iconv_lock); ICONV_CONVERTER_DONE(dcp); error = iconv_unregister_converter(dcp); + sx_xunlock(&iconv_lock); break; default: error = EINVAL; From jhb at FreeBSD.org Thu Feb 12 06:41:26 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 12 06:41:40 2009 Subject: svn commit: r188515 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902121441.n1CEfNM5058448@svn.freebsd.org> Author: jhb Date: Thu Feb 12 14:41:23 2009 New Revision: 188515 URL: http://svn.freebsd.org/changeset/base/188515 Log: MFC: Drop the kernel linker lock while running SYSUNINIT routines and removing sysctls during a linker file unload. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_linker.c Modified: stable/7/sys/kern/kern_linker.c ============================================================================== --- stable/7/sys/kern/kern_linker.c Thu Feb 12 14:37:58 2009 (r188514) +++ stable/7/sys/kern/kern_linker.c Thu Feb 12 14:41:23 2009 (r188515) @@ -642,8 +642,11 @@ linker_file_unload(linker_file_t file, i * link error. */ if (file->flags & LINKER_FILE_LINKED) { + file->flags &= ~LINKER_FILE_LINKED; + KLD_UNLOCK(); linker_file_sysuninit(file); linker_file_unregister_sysctls(file); + KLD_LOCK(); } TAILQ_REMOVE(&linker_files, file, link); From cognet at FreeBSD.org Thu Feb 12 07:26:01 2009 From: cognet at FreeBSD.org (Olivier Houchard) Date: Thu Feb 12 07:26:13 2009 Subject: svn commit: r188518 - stable/7/sys/dev/sound/pci Message-ID: <200902121526.n1CFQ0Ic059451@svn.freebsd.org> Author: cognet Date: Thu Feb 12 15:26:00 2009 New Revision: 188518 URL: http://svn.freebsd.org/changeset/base/188518 Log: MFC: r188424 | cognet | 2009-02-09 23:59:22 +0100 (Mon, 09 Feb 2009) | 6 lines Hmm... "base? base : 0" and "base" should be equivalent. Modified: stable/7/sys/dev/sound/pci/ds1.c Modified: stable/7/sys/dev/sound/pci/ds1.c ============================================================================== --- stable/7/sys/dev/sound/pci/ds1.c Thu Feb 12 14:49:20 2009 (r188517) +++ stable/7/sys/dev/sound/pci/ds1.c Thu Feb 12 15:26:00 2009 (r188518) @@ -396,7 +396,7 @@ ds_initpbank(volatile struct pbank *pb, pb->Format |= b16? 0 : 0x80000000; pb->Format |= (stereo && (ch == 2 || ch == 4))? 0x00000001 : 0; pb->LoopDefault = 0; - pb->PgBase = base? base : 0; + pb->PgBase = base; pb->PgLoop = 0; pb->PgLoopEnd = len >> ss; pb->PgLoopFrac = 0; From rrs at FreeBSD.org Thu Feb 12 08:40:49 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 08:41:00 2009 Subject: svn commit: r188521 - in stable/7/sys: . netinet Message-ID: <200902121640.n1CGemoZ061021@svn.freebsd.org> Author: rrs Date: Thu Feb 12 16:40:48 2009 New Revision: 188521 URL: http://svn.freebsd.org/changeset/base/188521 Log: Merges in 182268 from head close bug where we failed to NULL the sctp_socket. Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp_pcb.c Modified: stable/7/sys/netinet/sctp_pcb.c ============================================================================== --- stable/7/sys/netinet/sctp_pcb.c Thu Feb 12 15:28:15 2009 (r188520) +++ stable/7/sys/netinet/sctp_pcb.c Thu Feb 12 16:40:48 2009 (r188521) @@ -3270,6 +3270,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, #ifdef SCTP_LOG_CLOSING sctp_log_closing(inp, NULL, 2); #endif + inp->sctp_socket = NULL; return; } } From rrs at FreeBSD.org Thu Feb 12 09:26:17 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 09:26:29 2009 Subject: svn commit: r188522 - in stable/7/sys: . netinet Message-ID: <200902121726.n1CHQGgR061986@svn.freebsd.org> Author: rrs Date: Thu Feb 12 17:26:16 2009 New Revision: 188522 URL: http://svn.freebsd.org/changeset/base/188522 Log: MFC of 184030 - socket accept inherit bug. Basically accepted sockets were not inheriting the proper sock buf size. Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp_usrreq.c Modified: stable/7/sys/netinet/sctp_usrreq.c ============================================================================== --- stable/7/sys/netinet/sctp_usrreq.c Thu Feb 12 16:40:48 2009 (r188521) +++ stable/7/sys/netinet/sctp_usrreq.c Thu Feb 12 17:26:16 2009 (r188522) @@ -516,9 +516,11 @@ sctp_attach(struct socket *so, int proto SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); return EINVAL; } - error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace)); - if (error) { - return error; + if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { + error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace)); + if (error) { + return error; + } } error = sctp_inpcb_alloc(so, vrf_id); if (error) { From rrs at FreeBSD.org Thu Feb 12 09:31:41 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 09:31:58 2009 Subject: svn commit: r188523 - in stable/7/sys: . netinet Message-ID: <200902121731.n1CHVdD4062199@svn.freebsd.org> Author: rrs Date: Thu Feb 12 17:31:39 2009 New Revision: 188523 URL: http://svn.freebsd.org/changeset/base/188523 Log: MFC of 184336: Two inter-related bugs. - If we send EXACTLY the size left in the send buffer and then send again, we end up with exactly 0 bytes and don't hit the pre-block code to wait for more space. - If we fall into the loop with our max_len == 0 (the bug above) we then call in to copy out the data, setup the length of the waiting to transmit data to 0 and call the mbuf copy routine which 0 indicates copy all the data to the mbuf chain.. which it does. This then leaves a "stuck" message on the stream queue with its size exactly 0 bytes but all the data there and thus nothing left in the uio structure. We then reach a stuck forever state never being able to send data. Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp_output.c Modified: stable/7/sys/netinet/sctp_output.c ============================================================================== --- stable/7/sys/netinet/sctp_output.c Thu Feb 12 17:26:16 2009 (r188522) +++ stable/7/sys/netinet/sctp_output.c Thu Feb 12 17:31:39 2009 (r188523) @@ -11686,7 +11686,12 @@ sctp_copy_it_in(struct sctp_tcb *stcb, sp->put_last_out = 0; resv_in_first = sizeof(struct sctp_data_chunk); sp->data = sp->tail_mbuf = NULL; + if (sp->length == 0) { + *error = 0; + goto skip_copy; + } *error = sctp_copy_one(sp, uio, resv_in_first); +skip_copy: if (*error) { sctp_free_a_strmoq(stcb, sp); sp = NULL; @@ -12448,7 +12453,8 @@ sctp_lower_sosend(struct socket *so, goto skip_preblock; } if (((max_len <= local_add_more) && - (SCTP_SB_LIMIT_SND(so) > local_add_more)) || + (SCTP_SB_LIMIT_SND(so) >= local_add_more)) || + (max_len == 0) || ((stcb->asoc.chunks_on_out_queue + stcb->asoc.stream_queue_cnt) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) { /* if */ /* No room right now ! */ SOCKBUF_LOCK(&so->so_snd); @@ -13063,7 +13069,7 @@ skip_out_eof: (void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out, &reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point, SCTP_SO_LOCKED); } - SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d", + SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d\n", queue_only, stcb->asoc.peers_rwnd, un_sent, stcb->asoc.total_flight, stcb->asoc.chunks_on_out_queue, stcb->asoc.total_output_queue_size, error); From rrs at FreeBSD.org Thu Feb 12 09:57:30 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 09:57:37 2009 Subject: svn commit: r188524 - in stable/7/sys: . netinet Message-ID: <200902121757.n1CHvSVo062783@svn.freebsd.org> Author: rrs Date: Thu Feb 12 17:57:28 2009 New Revision: 188524 URL: http://svn.freebsd.org/changeset/base/188524 Log: MFC of 182367 and 182403 - Make strict-sacks be the default. - Change it so that without INVARIANTs there are no panics in SCTP. - sctp_timer changes so that we have a recovery mechanism when the sent list is out of order. Fixes compile error when INVARIANTs is on. Adds an empty goto to keep the compiler happy. Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp_indata.c stable/7/sys/netinet/sctp_lock_bsd.h stable/7/sys/netinet/sctp_output.c stable/7/sys/netinet/sctp_sysctl.h stable/7/sys/netinet/sctp_timer.c stable/7/sys/netinet/sctp_timer.h stable/7/sys/netinet/sctp_var.h stable/7/sys/netinet/sctputil.c Modified: stable/7/sys/netinet/sctp_indata.c ============================================================================== --- stable/7/sys/netinet/sctp_indata.c Thu Feb 12 17:31:39 2009 (r188523) +++ stable/7/sys/netinet/sctp_indata.c Thu Feb 12 17:57:28 2009 (r188524) @@ -386,12 +386,21 @@ abandon: if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { goto abandon; } else { +#ifdef INVARIANTS if ((stcb->asoc.control_pdapi == NULL) || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) { panic("This should not happen control_pdapi NULL?"); } /* if we did not panic, it was a EOM */ panic("Bad chunking ??"); - return; +#else + if ((stcb->asoc.control_pdapi == NULL) || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) { + SCTP_PRINTF("This should not happen control_pdapi NULL?\n"); + } + SCTP_PRINTF("Bad chunking ??\n"); + SCTP_PRINTF("Dumping re-assembly queue this will probably hose the association\n"); + +#endif + goto abandon; } } cntDel++; Modified: stable/7/sys/netinet/sctp_lock_bsd.h ============================================================================== --- stable/7/sys/netinet/sctp_lock_bsd.h Thu Feb 12 17:31:39 2009 (r188523) +++ stable/7/sys/netinet/sctp_lock_bsd.h Thu Feb 12 17:57:28 2009 (r188524) @@ -365,14 +365,20 @@ extern int sctp_logoff_stuff; do { \ atomic_add_int(&SCTP_BASE_INFO(ipi_count_chunk), 1); \ } while (0) - +#ifdef INVARIANTS #define SCTP_DECR_CHK_COUNT() \ do { \ if(SCTP_BASE_INFO(ipi_count_chunk) == 0) \ panic("chunk count to 0?"); \ atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_chunk), 1); \ } while (0) - +#else +#define SCTP_DECR_CHK_COUNT() \ + do { \ + if(SCTP_BASE_INFO(ipi_count_chunk) != 0) \ + atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_chunk), 1); \ + } while (0) +#endif #define SCTP_INCR_READQ_COUNT() \ do { \ atomic_add_int(&SCTP_BASE_INFO(ipi_count_readq),1); \ Modified: stable/7/sys/netinet/sctp_output.c ============================================================================== --- stable/7/sys/netinet/sctp_output.c Thu Feb 12 17:31:39 2009 (r188523) +++ stable/7/sys/netinet/sctp_output.c Thu Feb 12 17:57:28 2009 (r188524) @@ -11381,6 +11381,7 @@ sctp_send_operr_to(struct mbuf *m, int i struct ip *iph; struct udphdr *udp = NULL; struct mbuf *mout; + #ifdef INET6 #ifdef SCTP_DEBUG struct sockaddr_in6 lsa6, fsa6; Modified: stable/7/sys/netinet/sctp_sysctl.h ============================================================================== --- stable/7/sys/netinet/sctp_sysctl.h Thu Feb 12 17:31:39 2009 (r188523) +++ stable/7/sys/netinet/sctp_sysctl.h Thu Feb 12 17:57:28 2009 (r188524) @@ -152,7 +152,7 @@ struct sctp_sysctl { #define SCTPCTL_STRICT_SACKS_DESC "Enable SCTP Strict SACK checking" #define SCTPCTL_STRICT_SACKS_MIN 0 #define SCTPCTL_STRICT_SACKS_MAX 1 -#define SCTPCTL_STRICT_SACKS_DEFAULT 0 +#define SCTPCTL_STRICT_SACKS_DEFAULT 1 /* loopback_nocsum: Enable NO Csum on packets sent on loopback */ #define SCTPCTL_LOOPBACK_NOCSUM_DESC "Enable NO Csum on packets sent on loopback" Modified: stable/7/sys/netinet/sctp_timer.c ============================================================================== --- stable/7/sys/netinet/sctp_timer.c Thu Feb 12 17:31:39 2009 (r188523) +++ stable/7/sys/netinet/sctp_timer.c Thu Feb 12 17:57:28 2009 (r188524) @@ -561,6 +561,49 @@ sctp_backoff_on_timeout(struct sctp_tcb } } +void +sctp_recover_sent_list(struct sctp_tcb *stcb) +{ + struct sctp_tmit_chunk *chk, *tp2; + struct sctp_association *asoc; + + asoc = &stcb->asoc; + chk = TAILQ_FIRST(&stcb->asoc.sent_queue); + for (; chk != NULL; chk = tp2) { + tp2 = TAILQ_NEXT(chk, sctp_next); + if ((compare_with_wrap(stcb->asoc.last_acked_seq, + chk->rec.data.TSN_seq, + MAX_TSN)) || + (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) { + + SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n", + chk, chk->rec.data.TSN_seq, stcb->asoc.last_acked_seq); + TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); + if (chk->pr_sctp_on) { + if (asoc->pr_sctp_cnt != 0) + asoc->pr_sctp_cnt--; + } + if (chk->data) { + /* sa_ignore NO_NULL_CHK */ + sctp_free_bufspace(stcb, asoc, chk, 1); + sctp_m_freem(chk->data); + if (PR_SCTP_BUF_ENABLED(chk->flags)) { + asoc->sent_queue_cnt_removeable--; + } + } + chk->data = NULL; + asoc->sent_queue_cnt--; + sctp_free_a_chunk(stcb, chk); + } + } + SCTP_PRINTF("after recover order is as follows\n"); + chk = TAILQ_FIRST(&stcb->asoc.sent_queue); + for (; chk != NULL; chk = tp2) { + tp2 = TAILQ_NEXT(chk, sctp_next); + SCTP_PRINTF("chk:%p TSN:%x\n", chk, chk->rec.data.TSN_seq); + } +} + static int sctp_mark_all_for_resend(struct sctp_tcb *stcb, struct sctp_nets *net, @@ -583,6 +626,7 @@ sctp_mark_all_for_resend(struct sctp_tcb unsigned int cnt_mk; uint32_t orig_flight, orig_tf; uint32_t tsnlast, tsnfirst; + int recovery_cnt = 0; /* none in flight now */ @@ -635,6 +679,7 @@ sctp_mark_all_for_resend(struct sctp_tcb /* Now on to each chunk */ num_mk = cnt_mk = 0; tsnfirst = tsnlast = 0; +start_again: chk = TAILQ_FIRST(&stcb->asoc.sent_queue); for (; chk != NULL; chk = tp2) { tp2 = TAILQ_NEXT(chk, sctp_next); @@ -643,8 +688,22 @@ sctp_mark_all_for_resend(struct sctp_tcb MAX_TSN)) || (stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) { /* Strange case our list got out of order? */ - SCTP_PRINTF("Our list is out of order?\n"); - panic("Out of order list"); + SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x", + (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq); + recovery_cnt++; +#ifdef INVARIANTS + panic("last acked >= chk on sent-Q"); + /* to keep compiler happy */ + goto start_again; +#else + SCTP_PRINTF("Recover attempts a restart cnt:%d\n", recovery_cnt); + sctp_recover_sent_list(stcb); + if (recovery_cnt < 10) { + goto start_again; + } else { + SCTP_PRINTF("Recovery fails %d times??\n", recovery_cnt); + } +#endif } if ((chk->whoTo == net) && (chk->sent < SCTP_DATAGRAM_ACKED)) { /* Modified: stable/7/sys/netinet/sctp_timer.h ============================================================================== --- stable/7/sys/netinet/sctp_timer.h Thu Feb 12 17:31:39 2009 (r188523) +++ stable/7/sys/netinet/sctp_timer.h Thu Feb 12 17:57:28 2009 (r188524) @@ -99,6 +99,8 @@ void sctp_audit_retranmission_queue(stru void sctp_iterator_timer(struct sctp_iterator *it); +void sctp_recover_sent_list(struct sctp_tcb *stcb); + #endif #endif Modified: stable/7/sys/netinet/sctp_var.h ============================================================================== --- stable/7/sys/netinet/sctp_var.h Thu Feb 12 17:31:39 2009 (r188523) +++ stable/7/sys/netinet/sctp_var.h Thu Feb 12 17:57:28 2009 (r188524) @@ -160,6 +160,9 @@ extern struct pr_usrreqs sctp_usrreqs; } \ } +#ifdef INVARIANTS + + #define sctp_sbfree(ctl, stcb, sb, m) { \ uint32_t val; \ val = atomic_fetchadd_int(&(sb)->sb_cc,-(SCTP_BUF_LEN((m)))); \ @@ -186,6 +189,35 @@ extern struct pr_usrreqs sctp_usrreqs; } +#else + +#define sctp_sbfree(ctl, stcb, sb, m) { \ + uint32_t val; \ + val = atomic_fetchadd_int(&(sb)->sb_cc,-(SCTP_BUF_LEN((m)))); \ + if (val < SCTP_BUF_LEN((m))) { \ + (sb)->sb_cc = 0;\ + } \ + val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(MSIZE)); \ + if (val < MSIZE) { \ + (sb)->sb_mbcnt = 0; \ + } \ + if (((ctl)->do_not_ref_stcb == 0) && stcb) {\ + val = atomic_fetchadd_int(&(stcb)->asoc.sb_cc,-(SCTP_BUF_LEN((m)))); \ + if (val < SCTP_BUF_LEN((m))) {\ + (stcb)->asoc.sb_cc = 0; \ + } \ + val = atomic_fetchadd_int(&(stcb)->asoc.my_rwnd_control_len,-(MSIZE)); \ + if (val < MSIZE) { \ + (stcb)->asoc.my_rwnd_control_len = 0; \ + } \ + } \ + if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ + SCTP_BUF_TYPE(m) != MT_OOBDATA) \ + atomic_subtract_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \ +} + +#endif + #define sctp_sballoc(stcb, sb, m) { \ atomic_add_int(&(sb)->sb_cc,SCTP_BUF_LEN((m))); \ atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \ Modified: stable/7/sys/netinet/sctputil.c ============================================================================== --- stable/7/sys/netinet/sctputil.c Thu Feb 12 17:31:39 2009 (r188523) +++ stable/7/sys/netinet/sctputil.c Thu Feb 12 17:57:28 2009 (r188524) @@ -922,7 +922,9 @@ sctp_init_asoc(struct sctp_inpcb *m, str asoc->my_vtag = override_tag; } else { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); +#ifdef INVARIANTS panic("Huh is_in_timewait fails"); +#endif return (ENOMEM); } @@ -4848,6 +4850,7 @@ sctp_find_ifa_by_addr(struct sockaddr *a vrf = sctp_find_vrf(vrf_id); if (vrf == NULL) { +stage_right: if (holds_lock == 0) SCTP_IPI_ADDR_RUNLOCK(); return (NULL); @@ -4868,7 +4871,13 @@ sctp_find_ifa_by_addr(struct sockaddr *a } LIST_FOREACH(sctp_ifap, hash_head, next_bucket) { if (sctp_ifap == NULL) { +#ifdef INVARIANTS panic("Huh LIST_FOREACH corrupt"); + goto stage_right; +#else + SCTP_PRINTF("LIST corrupt of sctp_ifap's?\n"); + goto stage_right; +#endif } if (addr->sa_family != sctp_ifap->address.sa.sa_family) continue; @@ -5918,7 +5927,12 @@ out: * the atomic add to the refcnt. */ if (stcb == NULL) { +#ifdef INVARIANTS panic("stcb for refcnt has gone NULL?"); + goto stage_left; +#else + goto stage_left; +#endif } atomic_add_int(&stcb->asoc.refcnt, -1); freecnt_applied = 0; @@ -5940,6 +5954,7 @@ out: so->so_rcv.sb_cc); } } +stage_left: if (wakeup_read_socket) { sctp_sorwakeup(inp, so); } From rrs at FreeBSD.org Thu Feb 12 10:02:48 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 10:02:54 2009 Subject: svn commit: r188525 - in stable/7/sys: . netinet Message-ID: <200902121802.n1CI2ktB063039@svn.freebsd.org> Author: rrs Date: Thu Feb 12 18:02:46 2009 New Revision: 188525 URL: http://svn.freebsd.org/changeset/base/188525 Log: MFC of 184027: Reported by Yehuda Weinraub (yehudasa@gamil.com) - CRC32C algorithm uses incorrect init_bytes value. It SHOULD have the number of bytes to get to a 4 byte boundary. PR: 128134 Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp_crc32.c Modified: stable/7/sys/netinet/sctp_crc32.c ============================================================================== --- stable/7/sys/netinet/sctp_crc32.c Thu Feb 12 17:57:28 2009 (r188524) +++ stable/7/sys/netinet/sctp_crc32.c Thu Feb 12 18:02:46 2009 (r188525) @@ -583,13 +583,13 @@ update_crc32(uint32_t crc32c, unsigned char *buffer, unsigned int length) { - uint32_t offset; + uint32_t to_even_word; if (length == 0) { return (crc32c); } - offset = ((uintptr_t) buffer) & 0x3; - return (sctp_crc32c_sb8_64_bit(crc32c, buffer, length, offset)); + to_even_word = (4 - (((uintptr_t) buffer) & 0x3)); + return (sctp_crc32c_sb8_64_bit(crc32c, buffer, length, to_even_word)); } uint32_t sctp_crc_c[256] = { From rrs at FreeBSD.org Thu Feb 12 10:22:12 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 10:22:23 2009 Subject: svn commit: r188526 - in stable/7/sys: . netinet Message-ID: <200902121822.n1CIMB9s063465@svn.freebsd.org> Author: rrs Date: Thu Feb 12 18:22:11 2009 New Revision: 188526 URL: http://svn.freebsd.org/changeset/base/188526 Log: MFC of 184031: The flags value was not always being copied out in the recv routine like it should be. Obtained from: Michael Tuexen Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctputil.c Modified: stable/7/sys/netinet/sctputil.c ============================================================================== --- stable/7/sys/netinet/sctputil.c Thu Feb 12 18:02:46 2009 (r188525) +++ stable/7/sys/netinet/sctputil.c Thu Feb 12 18:22:11 2009 (r188526) @@ -5896,9 +5896,10 @@ release_unlocked: (no_rcv_needed == 0)) sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); } - if (msg_flags) - *msg_flags = out_flags; out: + if (msg_flags) { + *msg_flags = out_flags; + } if (((out_flags & MSG_EOR) == 0) && ((in_flags & MSG_PEEK) == 0) && (sinfo) && From rrs at FreeBSD.org Thu Feb 12 10:24:55 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 10:25:14 2009 Subject: svn commit: r188527 - in stable/7/sys: . netinet Message-ID: <200902121824.n1CIOsTm063576@svn.freebsd.org> Author: rrs Date: Thu Feb 12 18:24:54 2009 New Revision: 188527 URL: http://svn.freebsd.org/changeset/base/188527 Log: MFC 184333 Invariants changes that make more sense. Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp_timer.c stable/7/sys/netinet/sctp_timer.h Modified: stable/7/sys/netinet/sctp_timer.c ============================================================================== --- stable/7/sys/netinet/sctp_timer.c Thu Feb 12 18:22:11 2009 (r188526) +++ stable/7/sys/netinet/sctp_timer.c Thu Feb 12 18:24:54 2009 (r188527) @@ -561,7 +561,8 @@ sctp_backoff_on_timeout(struct sctp_tcb } } -void +#ifndef INVARIANTS +static void sctp_recover_sent_list(struct sctp_tcb *stcb) { struct sctp_tmit_chunk *chk, *tp2; @@ -604,6 +605,8 @@ sctp_recover_sent_list(struct sctp_tcb * } } +#endif + static int sctp_mark_all_for_resend(struct sctp_tcb *stcb, struct sctp_nets *net, @@ -679,7 +682,9 @@ sctp_mark_all_for_resend(struct sctp_tcb /* Now on to each chunk */ num_mk = cnt_mk = 0; tsnfirst = tsnlast = 0; +#ifndef INVARIANTS start_again: +#endif chk = TAILQ_FIRST(&stcb->asoc.sent_queue); for (; chk != NULL; chk = tp2) { tp2 = TAILQ_NEXT(chk, sctp_next); @@ -693,8 +698,6 @@ start_again: recovery_cnt++; #ifdef INVARIANTS panic("last acked >= chk on sent-Q"); - /* to keep compiler happy */ - goto start_again; #else SCTP_PRINTF("Recover attempts a restart cnt:%d\n", recovery_cnt); sctp_recover_sent_list(stcb); Modified: stable/7/sys/netinet/sctp_timer.h ============================================================================== --- stable/7/sys/netinet/sctp_timer.h Thu Feb 12 18:22:11 2009 (r188526) +++ stable/7/sys/netinet/sctp_timer.h Thu Feb 12 18:24:54 2009 (r188527) @@ -99,8 +99,6 @@ void sctp_audit_retranmission_queue(stru void sctp_iterator_timer(struct sctp_iterator *it); -void sctp_recover_sent_list(struct sctp_tcb *stcb); - #endif #endif From rrs at FreeBSD.org Thu Feb 12 10:28:44 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 10:28:51 2009 Subject: svn commit: r188528 - in stable/7/sys: . netinet Message-ID: <200902121828.n1CISh44063767@svn.freebsd.org> Author: rrs Date: Thu Feb 12 18:28:42 2009 New Revision: 188528 URL: http://svn.freebsd.org/changeset/base/188528 Log: MFC of 184340 More issues with pre-blocking: a) Need for EEOR mode to take the min of the socket buffer size and the add more threshold, otherwise if you are so silly as to set a send buf size less than the add-more you could block forever in eeor mode. b) We were incorrectly using the sysctl vs the calculated value. This causes us to block forever if the addmore theshold is larger than then the socket buffer size. Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp_output.c Modified: stable/7/sys/netinet/sctp_output.c ============================================================================== --- stable/7/sys/netinet/sctp_output.c Thu Feb 12 18:24:54 2009 (r188527) +++ stable/7/sys/netinet/sctp_output.c Thu Feb 12 18:28:42 2009 (r188528) @@ -12441,7 +12441,7 @@ sctp_lower_sosend(struct socket *so, goto out_unlocked; } if (user_marks_eor) { - local_add_more = SCTP_BASE_SYSCTL(sctp_add_more_threshold); + local_add_more = min(SCTP_SB_LIMIT_SND(so), SCTP_BASE_SYSCTL(sctp_add_more_threshold)); } else { /*- * For non-eeor the whole message must fit in @@ -12460,9 +12460,15 @@ sctp_lower_sosend(struct socket *so, /* No room right now ! */ SOCKBUF_LOCK(&so->so_snd); inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk)); - while ((SCTP_SB_LIMIT_SND(so) < (inqueue_bytes + SCTP_BASE_SYSCTL(sctp_add_more_threshold))) || - ((stcb->asoc.stream_queue_cnt + stcb->asoc.chunks_on_out_queue) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) /* while */ )) { - + while ((SCTP_SB_LIMIT_SND(so) < (inqueue_bytes + local_add_more)) || + ((stcb->asoc.stream_queue_cnt + stcb->asoc.chunks_on_out_queue) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue)) /* while */ ) { + SCTPDBG(SCTP_DEBUG_OUTPUT1, "pre_block limit:%d <(inq:%d + %d) || (%d+%d > %d)\n", + SCTP_SB_LIMIT_SND(so), + inqueue_bytes, + local_add_more, + stcb->asoc.stream_queue_cnt, + stcb->asoc.chunks_on_out_queue, + SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue)); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { sctp_log_block(SCTP_BLOCK_LOG_INTO_BLKA, so, asoc, sndlen); From rrs at FreeBSD.org Thu Feb 12 10:33:28 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 10:33:42 2009 Subject: svn commit: r188530 - in stable/7/sys: . netinet Message-ID: <200902121833.n1CIXQ8o063979@svn.freebsd.org> Author: rrs Date: Thu Feb 12 18:33:26 2009 New Revision: 188530 URL: http://svn.freebsd.org/changeset/base/188530 Log: MFC 184883 - a pack of bug fixes and misc adjustments: -Improvement: Add '\n' on debug output in sctp_lower_sosend(). -Improvement: panic() on INVARIANTS kernels if memory allocation fails for a tagblock in sctp_add_vtag_to_timewait(). -Bugfix: Protect code in sctp_is_in_timewait() by SCTP_INP_INFO_WLOCK/SCTP_INP_INFO_WUNLOCK. -Cleanup: Get rid of unused variable now in sctp_init_asoc(). -Bugfix: Reuse the correct vtag in sctp_add_vtag_to_timewait(). -Cleanup: Get rid of unused constant SCTP_TIME_WAIT_SHORT in sctp_constants.h. -Improvement: Use all hash buckets of the vtag hash table. -Cleanup: Get rid of then unused constant SCTP_STACK_VTAG_HASH_SIZE_A. -Bugfix: Handle SHUTDOWN;SACK packet correctly. -Bugfix: Last TSN in a gap ack block was not being "ack'd" in the internal scoreboard. Obtained from: (with help from Michael Tuexen) Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp_constants.h stable/7/sys/netinet/sctp_indata.c stable/7/sys/netinet/sctp_input.c stable/7/sys/netinet/sctp_pcb.c stable/7/sys/netinet/sctp_pcb.h stable/7/sys/netinet/sctputil.c Modified: stable/7/sys/netinet/sctp_constants.h ============================================================================== --- stable/7/sys/netinet/sctp_constants.h Thu Feb 12 18:33:13 2009 (r188529) +++ stable/7/sys/netinet/sctp_constants.h Thu Feb 12 18:33:26 2009 (r188530) @@ -1001,8 +1001,7 @@ __FBSDID("$FreeBSD$"); * entries must be searched to see if the tag is in timed wait. If so we * reject it. */ -#define SCTP_STACK_VTAG_HASH_SIZE 31 -#define SCTP_STACK_VTAG_HASH_SIZE_A 32 +#define SCTP_STACK_VTAG_HASH_SIZE 32 /* @@ -1016,12 +1015,6 @@ __FBSDID("$FreeBSD$"); */ #define SCTP_TIME_WAIT 60 -/* This time wait is the same as the default cookie life - * since we now enter a tag in every time we send a cookie. - * We want this shorter to avoid vtag depletion. - */ -#define SCTP_TIME_WAIT_SHORT 60 - /* The system retains a cache of free chunks such to * cut down on calls the memory allocation system. There * is a per association limit of free items and a overall Modified: stable/7/sys/netinet/sctp_indata.c ============================================================================== --- stable/7/sys/netinet/sctp_indata.c Thu Feb 12 18:33:13 2009 (r188529) +++ stable/7/sys/netinet/sctp_indata.c Thu Feb 12 18:33:26 2009 (r188530) @@ -2766,8 +2766,8 @@ sctp_handle_segments(struct mbuf *m, int struct sctp_sack *sack; struct sctp_gap_ack_block *frag, block; struct sctp_tmit_chunk *tp1; - int i; - unsigned int j; + int i, j; + unsigned int theTSN; int num_frs = 0; uint16_t frag_strt, frag_end, primary_flag_set; @@ -2835,7 +2835,8 @@ sctp_handle_segments(struct mbuf *m, int } last_frag_high = frag_end + last_tsn; } - for (j = frag_strt + last_tsn; (compare_with_wrap((frag_end + last_tsn), j, MAX_TSN)); j++) { + for (j = frag_strt; j <= frag_end; j++) { + theTSN = j + last_tsn; while (tp1) { if (tp1->rec.data.doing_fast_retransmit) num_frs++; @@ -2858,7 +2859,7 @@ sctp_handle_segments(struct mbuf *m, int tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq; tp1->whoTo->find_rtx_pseudo_cumack = 0; } - if (tp1->rec.data.TSN_seq == j) { + if (tp1->rec.data.TSN_seq == theTSN) { if (tp1->sent != SCTP_DATAGRAM_UNSENT) { /* * must be held until @@ -3030,8 +3031,8 @@ sctp_handle_segments(struct mbuf *m, int } } break; - } /* if (tp1->TSN_seq == j) */ - if (compare_with_wrap(tp1->rec.data.TSN_seq, j, + } /* if (tp1->TSN_seq == theTSN) */ + if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN, MAX_TSN)) break; Modified: stable/7/sys/netinet/sctp_input.c ============================================================================== --- stable/7/sys/netinet/sctp_input.c Thu Feb 12 18:33:13 2009 (r188529) +++ stable/7/sys/netinet/sctp_input.c Thu Feb 12 18:33:26 2009 (r188530) @@ -4280,7 +4280,6 @@ process_control_chunks: if ((stcb == NULL) || (chk_length < sizeof(struct sctp_sack_chunk))) { SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on sack chunk, too small\n"); - ignore_sack: *offset = length; if (locked_tcb) { SCTP_TCB_UNLOCK(locked_tcb); @@ -4293,7 +4292,7 @@ process_control_chunks: * attention to a sack sent in to us since * we don't care anymore. */ - goto ignore_sack; + break; } sack = (struct sctp_sack_chunk *)ch; nonce_sum_flag = ch->chunk_flags & SCTP_SACK_NONCE_SUM; Modified: stable/7/sys/netinet/sctp_pcb.c ============================================================================== --- stable/7/sys/netinet/sctp_pcb.c Thu Feb 12 18:33:13 2009 (r188529) +++ stable/7/sys/netinet/sctp_pcb.c Thu Feb 12 18:33:26 2009 (r188530) @@ -4191,6 +4191,7 @@ sctp_is_in_timewait(uint32_t tag) int found = 0; int i; + SCTP_INP_INFO_WLOCK(); chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; if (!SCTP_LIST_EMPTY(chain)) { LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { @@ -4204,6 +4205,7 @@ sctp_is_in_timewait(uint32_t tag) break; } } + SCTP_INP_INFO_WUNLOCK(); return (found); } @@ -4236,8 +4238,8 @@ sctp_add_vtag_to_timewait(uint32_t tag, twait_block->vtag_block[i].v_tag = 0; if (set == 0) { /* Reuse it for my new tag */ - twait_block->vtag_block[0].tv_sec_at_expire = now.tv_sec + time; - twait_block->vtag_block[0].v_tag = tag; + twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time; + twait_block->vtag_block[i].v_tag = tag; set = 1; } } @@ -4256,6 +4258,9 @@ sctp_add_vtag_to_timewait(uint32_t tag, SCTP_MALLOC(twait_block, struct sctp_tagblock *, sizeof(struct sctp_tagblock), SCTP_M_TIMW); if (twait_block == NULL) { +#ifdef INVARIANTS + panic("Can not alloc tagblock"); +#endif return; } memset(twait_block, 0, sizeof(struct sctp_tagblock)); @@ -5392,7 +5397,7 @@ sctp_pcb_init() SCTP_OS_TIMER_INIT(&SCTP_BASE_INFO(addr_wq_timer.timer)); /* Init the TIMEWAIT list */ - for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE_A; i++) { + for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { LIST_INIT(&SCTP_BASE_INFO(vtag_timewait[i])); } @@ -5462,7 +5467,7 @@ sctp_pcb_finish(void) * free the TIMEWAIT list elements malloc'd in the function * sctp_add_vtag_to_timewait()... */ - for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE_A; i++) { + for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { chain = &SCTP_BASE_INFO(vtag_timewait)[i]; if (!SCTP_LIST_EMPTY(chain)) { prev_twait_block = NULL; Modified: stable/7/sys/netinet/sctp_pcb.h ============================================================================== --- stable/7/sys/netinet/sctp_pcb.h Thu Feb 12 18:33:13 2009 (r188529) +++ stable/7/sys/netinet/sctp_pcb.h Thu Feb 12 18:33:26 2009 (r188530) @@ -228,7 +228,7 @@ struct sctp_epinfo { uint32_t ipi_free_strmoq; - struct sctpvtaghead vtag_timewait[SCTP_STACK_VTAG_HASH_SIZE_A]; + struct sctpvtaghead vtag_timewait[SCTP_STACK_VTAG_HASH_SIZE]; /* address work queue handling */ #if defined(SCTP_USE_THREAD_BASED_ITERATOR) Modified: stable/7/sys/netinet/sctputil.c ============================================================================== --- stable/7/sys/netinet/sctputil.c Thu Feb 12 18:33:13 2009 (r188529) +++ stable/7/sys/netinet/sctputil.c Thu Feb 12 18:33:26 2009 (r188530) @@ -910,9 +910,6 @@ sctp_init_asoc(struct sctp_inpcb *m, str #endif asoc->sb_send_resv = 0; if (override_tag) { - struct timeval now; - - (void)SCTP_GETTIME_TIMEVAL(&now); if (sctp_is_in_timewait(override_tag)) { /* * It must be in the time-wait hash, we put it there @@ -1466,6 +1463,9 @@ sctp_timeout_handler(void *t) SCTP_INP_INCR_REF(inp); if ((inp->sctp_socket == 0) && ((tmr->type != SCTP_TIMER_TYPE_INPKILL) && + (tmr->type != SCTP_TIMER_TYPE_SEND) && + (tmr->type != SCTP_TIMER_TYPE_RECV) && + (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) && (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) && (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) && (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) && From rrs at FreeBSD.org Thu Feb 12 10:50:28 2009 From: rrs at FreeBSD.org (Randall Stewart) Date: Thu Feb 12 10:50:48 2009 Subject: svn commit: r188532 - in stable/7/sys: . netinet netinet6 Message-ID: <200902121850.n1CIoRMp064401@svn.freebsd.org> Author: rrs Date: Thu Feb 12 18:50:27 2009 New Revision: 188532 URL: http://svn.freebsd.org/changeset/base/188532 Log: MFC of 185694 - The IETF hack session: Code from the hack-session known as the IETF (and a bit of debugging afterwards): - Fix protection code for notification generation. - Decouple associd from vtag - Allow vtags to have less strigent requirements in non-uniqueness. o don't pre-hash them when you issue one in a cookie. o Allow duplicates and use addresses and ports to discriminate amongst the duplicates during lookup. - Add support for the NAT draft draft-ietf-behave-sctpnat-00, this is still experimental and needs more extensive testing with the Jason Butt ipfw changes. - Support for the SENDER_DRY event to get DTLS in OpenSSL working with a set of patches from Michael Tuexen (hopefully heading to OpenSSL soon). - Update the support of SCTP-AUTH by Peter Lei. - Use macros for refcounting. - Fix MTU for UDP encapsulation. - Fix reporting back of unsent data. - Update assoc send counter handling to be consistent with endpoint sent counter. - Fix a bug in PR-SCTP. - Fix so we only send another FWD-TSN when a SACK arrives IF and only if the adv-peer-ack point progressed. However we still make sure a timer is running if we do have an adv_peer_ack point. - Fix PR-SCTP bug where chunks were retransmitted if they are sent unreliable but not abandoned yet. With the help of: Michael Teuxen and Peter Lei :-) Modified: stable/7/sys/ (props changed) stable/7/sys/netinet/sctp.h stable/7/sys/netinet/sctp_asconf.c stable/7/sys/netinet/sctp_asconf.h stable/7/sys/netinet/sctp_auth.c stable/7/sys/netinet/sctp_auth.h stable/7/sys/netinet/sctp_constants.h stable/7/sys/netinet/sctp_header.h stable/7/sys/netinet/sctp_indata.c stable/7/sys/netinet/sctp_indata.h stable/7/sys/netinet/sctp_input.c stable/7/sys/netinet/sctp_os_bsd.h stable/7/sys/netinet/sctp_output.c stable/7/sys/netinet/sctp_output.h stable/7/sys/netinet/sctp_pcb.c stable/7/sys/netinet/sctp_pcb.h stable/7/sys/netinet/sctp_structs.h stable/7/sys/netinet/sctp_sysctl.c stable/7/sys/netinet/sctp_sysctl.h stable/7/sys/netinet/sctp_timer.c stable/7/sys/netinet/sctp_uio.h stable/7/sys/netinet/sctp_usrreq.c stable/7/sys/netinet/sctp_var.h stable/7/sys/netinet/sctputil.c stable/7/sys/netinet/sctputil.h stable/7/sys/netinet6/sctp6_usrreq.c Modified: stable/7/sys/netinet/sctp.h ============================================================================== --- stable/7/sys/netinet/sctp.h Thu Feb 12 18:33:56 2009 (r188531) +++ stable/7/sys/netinet/sctp.h Thu Feb 12 18:50:27 2009 (r188532) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -111,6 +111,7 @@ struct sctp_paramhdr { /* explict EOR signalling */ #define SCTP_EXPLICIT_EOR 0x0000001b #define SCTP_REUSE_PORT 0x0000001c /* rw */ +#define SCTP_AUTH_DEACTIVATE_KEY 0x0000001d /* * read-only options @@ -154,6 +155,8 @@ struct sctp_paramhdr { /* CMT ON/OFF socket option */ #define SCTP_CMT_ON_OFF 0x00001200 #define SCTP_CMT_USE_DAC 0x00001201 +/* EY - NR_SACK on/off socket option */ +#define SCTP_NR_SACK_ON_OFF 0x00001300 /* JRS - Pluggable Congestion Control Socket option */ #define SCTP_PLUGGABLE_CC 0x00001202 @@ -293,11 +296,15 @@ struct sctp_paramhdr { #define SCTP_CAUSE_PROTOCOL_VIOLATION 0x000d /* Error causes from RFC5061 */ -#define SCTP_CAUSE_DELETING_LAST_ADDR 0xa0 -#define SCTP_CAUSE_RESOURCE_SHORTAGE 0xa1 -#define SCTP_CAUSE_DELETING_SRC_ADDR 0xa2 -#define SCTP_CAUSE_ILLEGAL_ASCONF_ACK 0xa3 -#define SCTP_CAUSE_REQUEST_REFUSED 0xa4 +#define SCTP_CAUSE_DELETING_LAST_ADDR 0x00a0 +#define SCTP_CAUSE_RESOURCE_SHORTAGE 0x00a1 +#define SCTP_CAUSE_DELETING_SRC_ADDR 0x00a2 +#define SCTP_CAUSE_ILLEGAL_ASCONF_ACK 0x00a3 +#define SCTP_CAUSE_REQUEST_REFUSED 0x00a4 + +/* Error causes from nat-draft */ +#define SCTP_CAUSE_NAT_COLLIDING_STATE 0x00b0 +#define SCTP_CAUSE_NAT_MISSING_STATE 0x00b1 /* Error causes from RFC4895 */ #define SCTP_CAUSE_UNSUPPORTED_HMACID 0x0105 @@ -364,6 +371,8 @@ struct sctp_error_unrecognized_chunk { #define SCTP_SHUTDOWN_COMPLETE 0x0e /* RFC4895 */ #define SCTP_AUTHENTICATION 0x0f +/* EY nr_sack chunk id*/ +#define SCTP_NR_SELECTIVE_ACK 0x10 /************0x40 series ***********/ /************0x80 series ***********/ /* RFC5061 */ @@ -406,6 +415,9 @@ struct sctp_error_unrecognized_chunk { /* ECN Nonce: SACK Chunk Specific Flags */ #define SCTP_SACK_NONCE_SUM 0x01 +/* EY nr_sack all bit - All bit is the 2nd LSB of nr_sack chunk flags*/ +/* if All bit is set in an nr-sack chunk, then all nr gap acks gap acks*/ +#define SCTP_NR_SACK_ALL_BIT 0x02 /* CMT DAC algorithm SACK flag */ #define SCTP_SACK_CMT_DAC 0x80 @@ -467,6 +479,7 @@ struct sctp_error_unrecognized_chunk { #define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x00800000 #define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x01000000 #define SCTP_PCB_FLAGS_PORTREUSE 0x02000000 +#define SCTP_PCB_FLAGS_DRYEVNT 0x04000000 /*- * mobility_features parameters (by micchie).Note * these features are applied against the Modified: stable/7/sys/netinet/sctp_asconf.c ============================================================================== --- stable/7/sys/netinet/sctp_asconf.c Thu Feb 12 18:33:56 2009 (r188531) +++ stable/7/sys/netinet/sctp_asconf.c Thu Feb 12 18:50:27 2009 (r188532) @@ -761,6 +761,9 @@ sctp_handle_asconf(struct mbuf *m, unsig m_result = sctp_process_asconf_set_primary(m, aph, stcb, error); break; + case SCTP_NAT_VTAGS: + SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n"); + break; case SCTP_SUCCESS_REPORT: /* not valid in an ASCONF chunk */ break; @@ -1349,6 +1352,7 @@ sctp_asconf_queue_mgmt(struct sctp_tcb * SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n"); return (-1); } + aa->special_del = 0; /* fill in asconf address parameter fields */ /* top level elements are "networked" during send */ aa->ap.aph.ph.param_type = type; @@ -1555,6 +1559,7 @@ sctp_asconf_queue_sa_delete(struct sctp_ "sctp_asconf_queue_sa_delete: failed to get memory!\n"); return (-1); } + aa->special_del = 0; /* fill in asconf address parameter fields */ /* top level elements are "networked" during send */ aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; @@ -2691,6 +2696,7 @@ sctp_compose_asconf(struct sctp_tcb *stc * case) */ if (lookup_used == 0 && + (aa->special_del == 0) && aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { struct sctp_ipv6addr_param *lookup; uint16_t p_size, addr_size; @@ -3234,3 +3240,195 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb * } return (0); } + +void +sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, + struct sctp_nets *net) +{ + struct sctp_asconf_addr *aa; + struct sctp_ifa *sctp_ifap; + struct sctp_asconf_tag_param *vtag; + struct sockaddr_in *to; + +#ifdef INET6 + struct sockaddr_in6 *to6; + +#endif + if (net == NULL) { + SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n"); + return; + } + if (stcb == NULL) { + SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n"); + return; + } + /* + * Need to have in the asconf: - vtagparam(my_vtag/peer_vtag) - + * add(0.0.0.0) - del(0.0.0.0) - Any global addresses add(addr) + */ + SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), + SCTP_M_ASC_ADDR); + if (aa == NULL) { + /* didn't get memory */ + SCTPDBG(SCTP_DEBUG_ASCONF1, + "sctp_asconf_send_nat_state_update: failed to get memory!\n"); + return; + } + aa->special_del = 0; + /* fill in asconf address parameter fields */ + /* top level elements are "networked" during send */ + aa->ifa = NULL; + aa->sent = 0; /* clear sent flag */ + vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph; + vtag->aph.ph.param_type = SCTP_NAT_VTAGS; + vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param); + vtag->local_vtag = htonl(stcb->asoc.my_vtag); + vtag->remote_vtag = htonl(stcb->asoc.peer_vtag); + TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); + + SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), + SCTP_M_ASC_ADDR); + if (aa == NULL) { + /* didn't get memory */ + SCTPDBG(SCTP_DEBUG_ASCONF1, + "sctp_asconf_send_nat_state_update: failed to get memory!\n"); + return; + } + memset(aa, 0, sizeof(struct sctp_asconf_addr)); + /* fill in asconf address parameter fields */ + /* ADD(0.0.0.0) */ + if (net->ro._l_addr.sa.sa_family == AF_INET) { + aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); + aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; + aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param); + /* No need to add an address, we are using 0.0.0.0 */ + TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); + } +#ifdef INET6 + else if (net->ro._l_addr.sa.sa_family == AF_INET6) { + aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); + aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; + aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param); + /* No need to add an address, we are using 0.0.0.0 */ + TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); + } +#endif /* INET6 */ + SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), + SCTP_M_ASC_ADDR); + if (aa == NULL) { + /* didn't get memory */ + SCTPDBG(SCTP_DEBUG_ASCONF1, + "sctp_asconf_send_nat_state_update: failed to get memory!\n"); + return; + } + memset(aa, 0, sizeof(struct sctp_asconf_addr)); + /* fill in asconf address parameter fields */ + /* ADD(0.0.0.0) */ + if (net->ro._l_addr.sa.sa_family == AF_INET) { + aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS; + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param); + aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; + aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param); + /* No need to add an address, we are using 0.0.0.0 */ + TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); + } +#ifdef INET6 + else if (net->ro._l_addr.sa.sa_family == AF_INET6) { + aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param); + aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; + aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param); + /* No need to add an address, we are using 0.0.0.0 */ + TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); + } +#endif /* INET6 */ + /* Now we must hunt the addresses and add all global addresses */ + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { + struct sctp_vrf *vrf = NULL; + struct sctp_ifn *sctp_ifnp; + uint32_t vrf_id; + + vrf_id = stcb->sctp_ep->def_vrf_id; + vrf = sctp_find_vrf(vrf_id); + if (vrf == NULL) { + goto skip_rest; + } + SCTP_IPI_ADDR_RLOCK(); + LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) { + LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) { + if (sctp_ifap->address.sa.sa_family == AF_INET) { + to = &sctp_ifap->address.sin; + + if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { + continue; + } + if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { + continue; + } + } +#ifdef INET6 + else if (sctp_ifap->address.sa.sa_family == AF_INET6) { + to6 = &sctp_ifap->address.sin6; + if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { + continue; + } + if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { + continue; + } + } +#endif + sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); + } + } + SCTP_IPI_ADDR_RUNLOCK(); + } else { + struct sctp_laddr *laddr; + + LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { + if (laddr->ifa == NULL) { + continue; + } + if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) + /* + * Address being deleted by the system, dont + * list. + */ + continue; + if (laddr->action == SCTP_DEL_IP_ADDRESS) { + /* + * Address being deleted on this ep don't + * list. + */ + continue; + } + sctp_ifap = laddr->ifa; + if (sctp_ifap->address.sa.sa_family == AF_INET) { + to = &sctp_ifap->address.sin; + + if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) { + continue; + } + if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) { + continue; + } + } +#ifdef INET6 + else if (sctp_ifap->address.sa.sa_family == AF_INET6) { + to6 = &sctp_ifap->address.sin6; + if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) { + continue; + } + if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) { + continue; + } + } +#endif + sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS); + } + } +skip_rest: + /* Now we must send the asconf into the queue */ + sctp_send_asconf(stcb, net, 0); +} Modified: stable/7/sys/netinet/sctp_asconf.h ============================================================================== --- stable/7/sys/netinet/sctp_asconf.h Thu Feb 12 18:33:56 2009 (r188531) +++ stable/7/sys/netinet/sctp_asconf.h Thu Feb 12 18:50:27 2009 (r188532) @@ -86,6 +86,10 @@ extern void extern void sctp_net_immediate_retrans(struct sctp_tcb *, struct sctp_nets *); +extern void +sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb, + struct sctp_nets *net); + extern int sctp_is_addr_pending(struct sctp_tcb *, struct sctp_ifa *); Modified: stable/7/sys/netinet/sctp_auth.c ============================================================================== --- stable/7/sys/netinet/sctp_auth.c Thu Feb 12 18:33:56 2009 (r188531) +++ stable/7/sys/netinet/sctp_auth.c Thu Feb 12 18:50:27 2009 (r188532) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -359,9 +359,11 @@ sctp_set_key(uint8_t * key, uint32_t key return (new_key); } -/* +/*- * given two keys of variable size, compute which key is "larger/smaller" - * returns: 1 if key1 > key2 -1 if key1 < key2 0 if key1 = key2 + * returns: 1 if key1 > key2 + * -1 if key1 < key2 + * 0 if key1 = key2 */ static int sctp_compare_key(sctp_key_t * key1, sctp_key_t * key2) @@ -531,13 +533,18 @@ sctp_alloc_sharedkey(void) } new_key->keyid = 0; new_key->key = NULL; + new_key->refcount = 1; + new_key->deactivated = 0; return (new_key); } void sctp_free_sharedkey(sctp_sharedkey_t * skey) { - if (skey != NULL) { + if (skey == NULL) + return; + + if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&skey->refcount)) { if (skey->key != NULL) sctp_free_key(skey->key); SCTP_FREE(skey, SCTP_M_AUTH_KY); @@ -556,40 +563,93 @@ sctp_find_sharedkey(struct sctp_keyhead return (NULL); } -void +int sctp_insert_sharedkey(struct sctp_keyhead *shared_keys, sctp_sharedkey_t * new_skey) { sctp_sharedkey_t *skey; if ((shared_keys == NULL) || (new_skey == NULL)) - return; + return (EINVAL); /* insert into an empty list? */ if (SCTP_LIST_EMPTY(shared_keys)) { LIST_INSERT_HEAD(shared_keys, new_skey, next); - return; + return (0); } /* insert into the existing list, ordered by key id */ LIST_FOREACH(skey, shared_keys, next) { if (new_skey->keyid < skey->keyid) { /* insert it before here */ LIST_INSERT_BEFORE(skey, new_skey, next); - return; + return (0); } else if (new_skey->keyid == skey->keyid) { /* replace the existing key */ + /* verify this key *can* be replaced */ + if ((skey->deactivated) && (skey->refcount > 1)) { + SCTPDBG(SCTP_DEBUG_AUTH1, + "can't replace shared key id %u\n", + new_skey->keyid); + return (EBUSY); + } SCTPDBG(SCTP_DEBUG_AUTH1, "replacing shared key id %u\n", new_skey->keyid); LIST_INSERT_BEFORE(skey, new_skey, next); LIST_REMOVE(skey, next); sctp_free_sharedkey(skey); - return; + return (0); } if (LIST_NEXT(skey, next) == NULL) { /* belongs at the end of the list */ LIST_INSERT_AFTER(skey, new_skey, next); - return; + return (0); + } + } + /* shouldn't reach here */ + return (0); +} + +void +sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t key_id) +{ + sctp_sharedkey_t *skey; + + /* find the shared key */ + skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, key_id); + + /* bump the ref count */ + if (skey) { + atomic_add_int(&skey->refcount, 1); + SCTPDBG(SCTP_DEBUG_AUTH2, + "%s: stcb %p key %u refcount acquire to %d\n", + __FUNCTION__, stcb, key_id, skey->refcount); + } +} + +void +sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id) +{ + sctp_sharedkey_t *skey; + + /* find the shared key */ + skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, key_id); + + /* decrement the ref count */ + if (skey) { + sctp_free_sharedkey(skey); + SCTPDBG(SCTP_DEBUG_AUTH2, + "%s: stcb %p key %u refcount release to %d\n", + __FUNCTION__, stcb, key_id, skey->refcount); + + /* see if a notification should be generated */ + if ((skey->refcount <= 1) && (skey->deactivated)) { + /* notify ULP that key is no longer used */ + sctp_ulp_notify(SCTP_NOTIFY_AUTH_FREE_KEY, stcb, + key_id, 0, SCTP_SO_NOT_LOCKED); + SCTPDBG(SCTP_DEBUG_AUTH2, + "%s: stcb %p key %u no longer used, %d\n", + __FUNCTION__, stcb, key_id, skey->refcount); } } } @@ -623,7 +683,7 @@ sctp_copy_skeylist(const struct sctp_key LIST_FOREACH(skey, src, next) { new_skey = sctp_copy_sharedkey(skey); if (new_skey != NULL) { - sctp_insert_sharedkey(dest, new_skey); + (void)sctp_insert_sharedkey(dest, new_skey); count++; } } @@ -727,9 +787,9 @@ sctp_default_supported_hmaclist(void) return (new_list); } -/* - * HMAC algos are listed in priority/preference order find the best HMAC id - * to use for the peer based on local support +/*- + * HMAC algos are listed in priority/preference order + * find the best HMAC id to use for the peer based on local support */ uint16_t sctp_negotiate_hmacid(sctp_hmaclist_t * peer, sctp_hmaclist_t * local) @@ -760,9 +820,9 @@ sctp_negotiate_hmacid(sctp_hmaclist_t * return (SCTP_AUTH_HMAC_ID_RSVD); } -/* - * serialize the HMAC algo list and return space used caller must guarantee - * ptr has appropriate space +/*- + * serialize the HMAC algo list and return space used + * caller must guarantee ptr has appropriate space */ int sctp_serialize_hmaclist(sctp_hmaclist_t * list, uint8_t * ptr) @@ -994,7 +1054,7 @@ sctp_hmac_final(uint16_t hmac_algo, sctp } /* end switch */ } -/* +/*- * Keyed-Hashing for Message Authentication: FIPS 198 (RFC 2104) * * Compute the HMAC digest using the desired hash key, text, and HMAC @@ -1142,9 +1202,10 @@ sctp_hmac_m(uint16_t hmac_algo, uint8_t return (digestlen); } -/* +/*- * verify the HMAC digest using the desired hash key, text, and HMAC - * algorithm. Returns -1 on error, 0 on success. + * algorithm. + * Returns -1 on error, 0 on success. */ int sctp_verify_hmac(uint16_t hmac_algo, uint8_t * key, uint32_t keylen, @@ -1263,10 +1324,10 @@ sctp_auth_is_supported_hmac(sctp_hmaclis } -/* - * clear any cached key(s) if they match the given key id on an association - * the cached key(s) will be recomputed and re-cached at next use. ASSUMES - * TCB_LOCK is already held +/*- + * clear any cached key(s) if they match the given key id on an association. + * the cached key(s) will be recomputed and re-cached at next use. + * ASSUMES TCB_LOCK is already held */ void sctp_clear_cachedkeys(struct sctp_tcb *stcb, uint16_t keyid) @@ -1284,9 +1345,10 @@ sctp_clear_cachedkeys(struct sctp_tcb *s } } -/* +/*- * clear any cached key(s) if they match the given key id for all assocs on - * an association ASSUMES INP_WLOCK is already held + * an endpoint. + * ASSUMES INP_WLOCK is already held */ void sctp_clear_cachedkeys_ep(struct sctp_inpcb *inp, uint16_t keyid) @@ -1304,8 +1366,9 @@ sctp_clear_cachedkeys_ep(struct sctp_inp } } -/* - * delete a shared key from an association ASSUMES TCB_LOCK is already held +/*- + * delete a shared key from an association + * ASSUMES TCB_LOCK is already held */ int sctp_delete_sharedkey(struct sctp_tcb *stcb, uint16_t keyid) @@ -1316,7 +1379,7 @@ sctp_delete_sharedkey(struct sctp_tcb *s return (-1); /* is the keyid the assoc active sending key */ - if (keyid == stcb->asoc.authinfo.assoc_keyid) + if (keyid == stcb->asoc.authinfo.active_keyid) return (-1); /* does the key exist? */ @@ -1324,6 +1387,10 @@ sctp_delete_sharedkey(struct sctp_tcb *s if (skey == NULL) return (-1); + /* are there other refcount holders on the key? */ + if (skey->refcount > 1) + return (-1); + /* remove it */ LIST_REMOVE(skey, next); sctp_free_sharedkey(skey); /* frees skey->key as well */ @@ -1333,35 +1400,29 @@ sctp_delete_sharedkey(struct sctp_tcb *s return (0); } -/* - * deletes a shared key from the endpoint ASSUMES INP_WLOCK is already held +/*- + * deletes a shared key from the endpoint + * ASSUMES INP_WLOCK is already held */ int sctp_delete_sharedkey_ep(struct sctp_inpcb *inp, uint16_t keyid) { sctp_sharedkey_t *skey; - struct sctp_tcb *stcb; if (inp == NULL) return (-1); - /* is the keyid the active sending key on the endpoint or any assoc */ + /* is the keyid the active sending key on the endpoint */ if (keyid == inp->sctp_ep.default_keyid) return (-1); - LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { - SCTP_TCB_LOCK(stcb); - if (keyid == stcb->asoc.authinfo.assoc_keyid) { - SCTP_TCB_UNLOCK(stcb); - return (-1); - } - SCTP_TCB_UNLOCK(stcb); - } /* does the key exist? */ skey = sctp_find_sharedkey(&inp->sctp_ep.shared_keys, keyid); if (skey == NULL) return (-1); + /* endpoint keys are not refcounted */ + /* remove it */ LIST_REMOVE(skey, next); sctp_free_sharedkey(skey); /* frees skey->key as well */ @@ -1371,60 +1432,36 @@ sctp_delete_sharedkey_ep(struct sctp_inp return (0); } -/* - * set the active key on an association ASSUME TCB_LOCK is already held +/*- + * set the active key on an association + * ASSUMES TCB_LOCK is already held */ int sctp_auth_setactivekey(struct sctp_tcb *stcb, uint16_t keyid) { sctp_sharedkey_t *skey = NULL; - sctp_key_t *key = NULL; - int using_ep_key = 0; /* find the key on the assoc */ skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid); if (skey == NULL) { - /* if not on the assoc, find the key on the endpoint */ - atomic_add_int(&stcb->asoc.refcnt, 1); - SCTP_TCB_UNLOCK(stcb); - SCTP_INP_RLOCK(stcb->sctp_ep); - SCTP_TCB_LOCK(stcb); - atomic_add_int(&stcb->asoc.refcnt, -1); - skey = sctp_find_sharedkey(&stcb->sctp_ep->sctp_ep.shared_keys, - keyid); - using_ep_key = 1; - } - if (skey == NULL) { /* that key doesn't exist */ - if (using_ep_key) { - SCTP_INP_RUNLOCK(stcb->sctp_ep); - } return (-1); } - /* get the shared key text */ - key = skey->key; - - /* free any existing cached key */ - if (stcb->asoc.authinfo.assoc_key != NULL) - sctp_free_key(stcb->asoc.authinfo.assoc_key); - /* compute a new assoc key and cache it */ - stcb->asoc.authinfo.assoc_key = - sctp_compute_hashkey(stcb->asoc.authinfo.random, - stcb->asoc.authinfo.peer_random, key); - stcb->asoc.authinfo.assoc_keyid = keyid; -#ifdef SCTP_DEBUG - if (SCTP_AUTH_DEBUG) - sctp_print_key(stcb->asoc.authinfo.assoc_key, "Assoc Key"); -#endif - - if (using_ep_key) { - SCTP_INP_RUNLOCK(stcb->sctp_ep); + if ((skey->deactivated) && (skey->refcount > 1)) { + /* can't reactivate a deactivated key with other refcounts */ + return (-1); } + /* set the (new) active key */ + stcb->asoc.authinfo.active_keyid = keyid; + /* reset the deactivated flag */ + skey->deactivated = 0; + return (0); } -/* - * set the active key on an endpoint ASSUMES INP_WLOCK is already held +/*- + * set the active key on an endpoint + * ASSUMES INP_WLOCK is already held */ int sctp_auth_setactivekey_ep(struct sctp_inpcb *inp, uint16_t keyid) @@ -1441,6 +1478,69 @@ sctp_auth_setactivekey_ep(struct sctp_in return (0); } +/*- + * deactivates a shared key from the association + * ASSUMES INP_WLOCK is already held + */ +int +sctp_deact_sharedkey(struct sctp_tcb *stcb, uint16_t keyid) +{ + sctp_sharedkey_t *skey; + + if (stcb == NULL) + return (-1); + + /* is the keyid the assoc active sending key */ + if (keyid == stcb->asoc.authinfo.active_keyid) + return (-1); + + /* does the key exist? */ + skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid); + if (skey == NULL) + return (-1); + + /* are there other refcount holders on the key? */ + if (skey->refcount == 1) { + /* no other users, send a notification for this key */ + sctp_ulp_notify(SCTP_NOTIFY_AUTH_FREE_KEY, stcb, keyid, 0, + SCTP_SO_LOCKED); + } + /* mark the key as deactivated */ + skey->deactivated = 1; + + return (0); +} + +/*- + * deactivates a shared key from the endpoint + * ASSUMES INP_WLOCK is already held + */ +int +sctp_deact_sharedkey_ep(struct sctp_inpcb *inp, uint16_t keyid) +{ + sctp_sharedkey_t *skey; + + if (inp == NULL) + return (-1); + + /* is the keyid the active sending key on the endpoint */ + if (keyid == inp->sctp_ep.default_keyid) + return (-1); + + /* does the key exist? */ + skey = sctp_find_sharedkey(&inp->sctp_ep.shared_keys, keyid); + if (skey == NULL) + return (-1); + + /* endpoint keys are not refcounted */ + + /* remove it */ + LIST_REMOVE(skey, next); + sctp_free_sharedkey(skey); /* frees skey->key as well */ + + return (0); +} + /* * get local authentication parameters from cookie (from INIT-ACK) */ @@ -1581,9 +1681,13 @@ sctp_auth_get_cookie_params(struct sctp_ /* negotiate what HMAC to use for the peer */ stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs, stcb->asoc.local_hmacs); + /* copy defaults from the endpoint */ /* FIX ME: put in cookie? */ - stcb->asoc.authinfo.assoc_keyid = stcb->sctp_ep->sctp_ep.default_keyid; + stcb->asoc.authinfo.active_keyid = stcb->sctp_ep->sctp_ep.default_keyid; + /* copy out the shared key list (by reference) from the endpoint */ + (void)sctp_copy_skeylist(&stcb->sctp_ep->sctp_ep.shared_keys, + &stcb->asoc.shared_keys); } /* @@ -1591,7 +1695,7 @@ sctp_auth_get_cookie_params(struct sctp_ */ void sctp_fill_hmac_digest_m(struct mbuf *m, uint32_t auth_offset, - struct sctp_auth_chunk *auth, struct sctp_tcb *stcb) + struct sctp_auth_chunk *auth, struct sctp_tcb *stcb, uint16_t keyid) { uint32_t digestlen; sctp_sharedkey_t *skey; @@ -1603,15 +1707,15 @@ sctp_fill_hmac_digest_m(struct mbuf *m, /* zero the digest + chunk padding */ digestlen = sctp_get_hmac_digest_len(stcb->asoc.peer_hmac_id); bzero(auth->hmac, SCTP_SIZE32(digestlen)); - /* is an assoc key cached? */ - if (stcb->asoc.authinfo.assoc_key == NULL) { - skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, - stcb->asoc.authinfo.assoc_keyid); - if (skey == NULL) { - /* not in the assoc list, so check the endpoint list */ - skey = sctp_find_sharedkey(&stcb->sctp_ep->sctp_ep.shared_keys, - stcb->asoc.authinfo.assoc_keyid); + + /* is the desired key cached? */ + if ((keyid != stcb->asoc.authinfo.assoc_keyid) || + (stcb->asoc.authinfo.assoc_key == NULL)) { + if (stcb->asoc.authinfo.assoc_key != NULL) { + /* free the old cached key */ + sctp_free_key(stcb->asoc.authinfo.assoc_key); } + skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, keyid); /* the only way skey is NULL is if null key id 0 is used */ if (skey != NULL) key = skey->key; @@ -1621,6 +1725,7 @@ sctp_fill_hmac_digest_m(struct mbuf *m, stcb->asoc.authinfo.assoc_key = sctp_compute_hashkey(stcb->asoc.authinfo.random, stcb->asoc.authinfo.peer_random, key); + stcb->asoc.authinfo.assoc_keyid = keyid; SCTPDBG(SCTP_DEBUG_AUTH1, "caching key id %u\n", stcb->asoc.authinfo.assoc_keyid); #ifdef SCTP_DEBUG @@ -1630,11 +1735,10 @@ sctp_fill_hmac_digest_m(struct mbuf *m, #endif } /* set in the active key id */ - auth->shared_key_id = htons(stcb->asoc.authinfo.assoc_keyid); + auth->shared_key_id = htons(keyid); /* compute and fill in the digest */ - (void)sctp_compute_hmac_m(stcb->asoc.peer_hmac_id, - stcb->asoc.authinfo.assoc_key, + (void)sctp_compute_hmac_m(stcb->asoc.peer_hmac_id, stcb->asoc.authinfo.assoc_key, m, auth_offset, auth->hmac); } @@ -1671,9 +1775,11 @@ sctp_bzero_m(struct mbuf *m, uint32_t m_ } } -/* - * process the incoming Authentication chunk return codes: -1 on any - * authentication error 0 on authentication verification +/*- + * process the incoming Authentication chunk + * return codes: + * -1 on any authentication error + * 0 on authentication verification */ int sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth, @@ -1736,12 +1842,8 @@ sctp_handle_auth(struct sctp_tcb *stcb, if ((stcb->asoc.authinfo.recv_key == NULL) || (stcb->asoc.authinfo.recv_keyid != shared_key_id)) { /* find the shared key on the assoc first */ - skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, shared_key_id); - if (skey == NULL) { - /* if not on the assoc, find it on the endpoint */ - skey = sctp_find_sharedkey(&stcb->sctp_ep->sctp_ep.shared_keys, - shared_key_id); - } + skey = sctp_find_sharedkey(&stcb->asoc.shared_keys, + shared_key_id); /* if the shared key isn't found, discard the chunk */ if (skey == NULL) { SCTP_STAT_INCR(sctps_recvivalkeyid); @@ -1758,7 +1860,8 @@ sctp_handle_auth(struct sctp_tcb *stcb, * *)stcb->asoc.authinfo.recv_keyid); */ sctp_notify_authentication(stcb, SCTP_AUTH_NEWKEY, - shared_key_id, stcb->asoc.authinfo.recv_keyid); + shared_key_id, stcb->asoc.authinfo.recv_keyid, + SCTP_SO_NOT_LOCKED); /* compute a new recv assoc key and cache it */ if (stcb->asoc.authinfo.recv_key != NULL) sctp_free_key(stcb->asoc.authinfo.recv_key); @@ -1801,7 +1904,11 @@ sctp_handle_auth(struct sctp_tcb *stcb, */ void sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication, - uint16_t keyid, uint16_t alt_keyid) + uint16_t keyid, uint16_t alt_keyid, int so_locked +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) + SCTP_UNUSED +#endif +) { struct mbuf *m_notify; struct sctp_authkey_event *auth; @@ -1851,11 +1958,11 @@ sctp_notify_authentication(struct sctp_t /* not that we need this */ control->tail_mbuf = m_notify; sctp_add_to_readq(stcb->sctp_ep, stcb, control, - &stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED); + &stcb->sctp_socket->so_rcv, 1, so_locked); } -/* +/*- * validates the AUTHentication related parameters in an INIT/INIT-ACK * Note: currently only used for INIT as INIT-ACK is handled inline * with sctp_load_addresses_from_init() @@ -2027,7 +2134,11 @@ sctp_initialize_auth_params(struct sctp_ } } /* copy defaults from the endpoint */ - stcb->asoc.authinfo.assoc_keyid = inp->sctp_ep.default_keyid; + stcb->asoc.authinfo.active_keyid = inp->sctp_ep.default_keyid; + + /* copy out the shared key list (by reference) from the endpoint */ + (void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys, + &stcb->asoc.shared_keys); /* now set the concatenated key (random + chunks + hmacs) */ #ifdef SCTP_AUTH_DRAFT_04 @@ -2135,11 +2246,13 @@ sctp_test_hmac_sha1(void) uint32_t digestlen = 20; int failed = 0; - /* - * test_case = 1 key = - * 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b key_len = 20 - * data = "Hi There" data_len = 8 digest = - * 0xb617318655057264e28bc0b6fb378c8ef146be00 + /*- + * test_case = 1 + * key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b + * key_len = 20 + * data = "Hi There" + * data_len = 8 + * digest = 0xb617318655057264e28bc0b6fb378c8ef146be00 */ keylen = 20; memset(key, 0x0b, keylen); @@ -2150,10 +2263,13 @@ sctp_test_hmac_sha1(void) text, textlen, digest, digestlen) < 0) failed++; - /* - * test_case = 2 key = "Jefe" key_len = 4 data = - * "what do ya want for nothing?" data_len = 28 digest = - * 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79 + /*- + * test_case = 2 + * key = "Jefe" + * key_len = 4 + * data = "what do ya want for nothing?" + * data_len = 28 + * digest = 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79 */ keylen = 4; strcpy(key, "Jefe"); @@ -2164,11 +2280,13 @@ sctp_test_hmac_sha1(void) text, textlen, digest, digestlen) < 0) failed++; - /* - * test_case = 3 key = - * 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa key_len = 20 - * data = 0xdd repeated 50 times data_len = 50 digest - * = 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3 + /*- + * test_case = 3 + * key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + * key_len = 20 + * data = 0xdd repeated 50 times + * data_len = 50 + * digest = 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3 */ keylen = 20; memset(key, 0xaa, keylen); @@ -2179,11 +2297,13 @@ sctp_test_hmac_sha1(void) text, textlen, digest, digestlen) < 0) failed++; - /* - * test_case = 4 key = - * 0x0102030405060708090a0b0c0d0e0f10111213141516171819 key_len = 25 - * data = 0xcd repeated 50 times data_len = 50 digest - * = 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da + /*- + * test_case = 4 + * key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819 + * key_len = 25 + * data = 0xcd repeated 50 times + * data_len = 50 + * digest = 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da */ keylen = 25; memcpy(key, "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", keylen); @@ -2194,12 +2314,14 @@ sctp_test_hmac_sha1(void) text, textlen, digest, digestlen) < 0) failed++; - /* - * test_case = 5 key = - * 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c key_len = 20 - * data = "Test With Truncation" data_len = 20 digest - * = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 digest-96 = *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From emax at FreeBSD.org Thu Feb 12 17:14:01 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Thu Feb 12 17:14:18 2009 Subject: svn commit: r188547 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netgraph/bluetooth/socket Message-ID: <200902130114.n1D1E0Pu072049@svn.freebsd.org> Author: emax Date: Fri Feb 13 01:14:00 2009 New Revision: 188547 URL: http://svn.freebsd.org/changeset/base/188547 Log: MFC r188452 Update comment. soalloc() is no longer performing M_WAITOK memory allocations. Submitted by: ru Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c Modified: stable/7/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c ============================================================================== --- stable/7/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c Fri Feb 13 00:01:11 2009 (r188546) +++ stable/7/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c Fri Feb 13 01:14:00 2009 (r188547) @@ -518,13 +518,9 @@ ng_btsocket_rfcomm_connect(struct socket return (EDESTADDRREQ); /* - * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e. - * soalloc() is allowed to sleep in MALLOC. This creates "could sleep" - * WITNESS warnings. To work around this problem we will create L2CAP - * socket first and then check if we actually need it. Note that we - * will not check for errors in socreate() because if we failed to - * create L2CAP socket at this point we still might have already open - * session. + * Note that we will not check for errors in socreate() because + * if we failed to create L2CAP socket at this point we still + * might have already open session. */ error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET, @@ -857,13 +853,9 @@ ng_btsocket_rfcomm_listen(struct socket mtx_unlock(&pcb->pcb_mtx); /* - * XXX FIXME - This is FUBAR. socreate() will call soalloc(1), i.e. - * soalloc() is allowed to sleep in MALLOC. This creates "could sleep" - * WITNESS warnings. To work around this problem we will create L2CAP - * socket first and then check if we actually need it. Note that we - * will not check for errors in socreate() because if we failed to - * create L2CAP socket at this point we still might have already open - * session. + * Note that we will not check for errors in socreate() because + * if we failed to create L2CAP socket at this point we still + * might have already open session. */ socreate_error = socreate(PF_BLUETOOTH, &l2so, SOCK_SEQPACKET, From yongari at FreeBSD.org Thu Feb 12 18:41:17 2009 From: yongari at FreeBSD.org (Pyun YongHyeon) Date: Thu Feb 12 18:41:22 2009 Subject: svn commit: r188551 - stable/7/share/man/man4 Message-ID: <200902130241.n1D2fF5i073860@svn.freebsd.org> Author: yongari Date: Fri Feb 13 02:41:15 2009 New Revision: 188551 URL: http://svn.freebsd.org/changeset/base/188551 Log: MFC r186126: Elaborate on the hardware features fxp(4) supports. Modified: stable/7/share/man/man4/ (props changed) stable/7/share/man/man4/fxp.4 stable/7/share/man/man4/igb.4 (props changed) Modified: stable/7/share/man/man4/fxp.4 ============================================================================== --- stable/7/share/man/man4/fxp.4 Fri Feb 13 02:08:20 2009 (r188550) +++ stable/7/share/man/man4/fxp.4 Fri Feb 13 02:41:15 2009 (r188551) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 7, 2007 +.Dd December 15, 2008 .Dt FXP 4 .Os .Sh NAME @@ -51,6 +51,13 @@ The .Nm driver provides support for Ethernet adapters based on the Intel i82557, i82558, i82559, i82550, and i82562 chips. +The driver supports TCP/UDP/IP checksum offload for both transmit +and receive on i82550 and i82551. +On i82559 only TCP/UDP checksum offload for receive is supported. +TCP segmentation offload (TSO) for IPv4 as well as VLAN hardware +tag insertion/stripping is supported on i82550 and i82551. +Wake On Lan (WOL) support is provided on all controllers +except i82557, i82259ER and early i82558 revisions. .Pp The .Nm From kib at FreeBSD.org Fri Feb 13 04:15:47 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Fri Feb 13 04:16:00 2009 Subject: svn commit: r188574 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902131215.n1DCFj2V088381@svn.freebsd.org> Author: kib Date: Fri Feb 13 12:15:45 2009 New Revision: 188574 URL: http://svn.freebsd.org/changeset/base/188574 Log: MFC r187223: Redo the locking of the semaphores lifetime cycle. MFC r187298: Lock the semaphore identifier lock during semaphore initialization. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/sysv_sem.c Modified: stable/7/sys/kern/sysv_sem.c ============================================================================== --- stable/7/sys/kern/sysv_sem.c Fri Feb 13 12:07:45 2009 (r188573) +++ stable/7/sys/kern/sysv_sem.c Fri Feb 13 12:15:45 2009 (r188574) @@ -88,7 +88,7 @@ int semop(struct thread *td, struct semo static struct sem_undo *semu_alloc(struct thread *td); static int semundo_adjust(struct thread *td, struct sem_undo **supptr, - int semid, int semnum, int adjval); + int semid, int semseq, int semnum, int adjval); static void semundo_clear(int semid, int semnum); /* XXX casting to (sy_call_t *) is bogus, as usual. */ @@ -98,15 +98,17 @@ static sy_call_t *semcalls[] = { }; static struct mtx sem_mtx; /* semaphore global lock */ +static struct mtx sem_undo_mtx; static int semtot = 0; static struct semid_kernel *sema; /* semaphore id pool */ static struct mtx *sema_mtx; /* semaphore id pool mutexes*/ static struct sem *sem; /* semaphore pool */ -SLIST_HEAD(, sem_undo) semu_list; /* list of active undo structures */ +LIST_HEAD(, sem_undo) semu_list; /* list of active undo structures */ +LIST_HEAD(, sem_undo) semu_free_list; /* list of free undo structures */ static int *semu; /* undo structure pool */ static eventhandler_tag semexit_tag; -#define SEMUNDO_MTX sem_mtx +#define SEMUNDO_MTX sem_undo_mtx #define SEMUNDO_LOCK() mtx_lock(&SEMUNDO_MTX); #define SEMUNDO_UNLOCK() mtx_unlock(&SEMUNDO_MTX); #define SEMUNDO_LOCKASSERT(how) mtx_assert(&SEMUNDO_MTX, (how)); @@ -122,13 +124,14 @@ struct sem { * Undo structure (one per process) */ struct sem_undo { - SLIST_ENTRY(sem_undo) un_next; /* ptr to next active undo structure */ + LIST_ENTRY(sem_undo) un_next; /* ptr to next active undo structure */ struct proc *un_proc; /* owner of this structure */ short un_cnt; /* # of active entries */ struct undo { short un_adjval; /* adjust on exit values */ short un_num; /* semaphore # */ int un_id; /* semid */ + unsigned short un_seq; } un_ent[1]; /* undo entries */ }; @@ -250,12 +253,15 @@ seminit(void) } for (i = 0; i < seminfo.semmni; i++) mtx_init(&sema_mtx[i], "semid", NULL, MTX_DEF); + LIST_INIT(&semu_free_list); for (i = 0; i < seminfo.semmnu; i++) { struct sem_undo *suptr = SEMU(i); suptr->un_proc = NULL; + LIST_INSERT_HEAD(&semu_free_list, suptr, un_next); } - SLIST_INIT(&semu_list); + LIST_INIT(&semu_list); mtx_init(&sem_mtx, "sem", NULL, MTX_DEF); + mtx_init(&sem_undo_mtx, "semu", NULL, MTX_DEF); semexit_tag = EVENTHANDLER_REGISTER(process_exit, semexit_myhook, NULL, EVENTHANDLER_PRI_ANY); } @@ -265,6 +271,7 @@ semunload(void) { int i; + /* XXXKIB */ if (semtot != 0) return (EBUSY); @@ -279,6 +286,7 @@ semunload(void) for (i = 0; i < seminfo.semmni; i++) mtx_destroy(&sema_mtx[i]); mtx_destroy(&sem_mtx); + mtx_destroy(&sem_undo_mtx); return (0); } @@ -350,69 +358,31 @@ semsys(td, uap) */ static struct sem_undo * -semu_alloc(td) - struct thread *td; +semu_alloc(struct thread *td) { - int i; struct sem_undo *suptr; - struct sem_undo **supptr; - int attempt; SEMUNDO_LOCKASSERT(MA_OWNED); - /* - * Try twice to allocate something. - * (we'll purge an empty structure after the first pass so - * two passes are always enough) - */ - - for (attempt = 0; attempt < 2; attempt++) { - /* - * Look for a free structure. - * Fill it in and return it if we find one. - */ - - for (i = 0; i < seminfo.semmnu; i++) { - suptr = SEMU(i); - if (suptr->un_proc == NULL) { - SLIST_INSERT_HEAD(&semu_list, suptr, un_next); - suptr->un_cnt = 0; - suptr->un_proc = td->td_proc; - return(suptr); - } - } + if ((suptr = LIST_FIRST(&semu_free_list)) == NULL) + return (NULL); + LIST_REMOVE(suptr, un_next); + LIST_INSERT_HEAD(&semu_list, suptr, un_next); + suptr->un_cnt = 0; + suptr->un_proc = td->td_proc; + return (suptr); +} - /* - * We didn't find a free one, if this is the first attempt - * then try to free a structure. - */ +static int +semu_try_free(struct sem_undo *suptr) +{ - if (attempt == 0) { - /* All the structures are in use - try to free one */ - int did_something = 0; - - SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list, - un_next) { - if (suptr->un_cnt == 0) { - suptr->un_proc = NULL; - did_something = 1; - *supptr = SLIST_NEXT(suptr, un_next); - break; - } - } + SEMUNDO_LOCKASSERT(MA_OWNED); - /* If we didn't free anything then just give-up */ - if (!did_something) - return(NULL); - } else { - /* - * The second pass failed even though we freed - * something after the first pass! - * This is IMPOSSIBLE! - */ - panic("semu_alloc - second attempt failed"); - } - } - return (NULL); + if (suptr->un_cnt != 0) + return (0); + LIST_REMOVE(suptr, un_next); + LIST_INSERT_HEAD(&semu_free_list, suptr, un_next); + return (1); } /* @@ -420,11 +390,8 @@ semu_alloc(td) */ static int -semundo_adjust(td, supptr, semid, semnum, adjval) - struct thread *td; - struct sem_undo **supptr; - int semid, semnum; - int adjval; +semundo_adjust(struct thread *td, struct sem_undo **supptr, int semid, + int semseq, int semnum, int adjval) { struct proc *p = td->td_proc; struct sem_undo *suptr; @@ -437,7 +404,7 @@ semundo_adjust(td, supptr, semid, semnum suptr = *supptr; if (suptr == NULL) { - SLIST_FOREACH(suptr, &semu_list, un_next) { + LIST_FOREACH(suptr, &semu_list, un_next) { if (suptr->un_proc == p) { *supptr = suptr; break; @@ -448,7 +415,7 @@ semundo_adjust(td, supptr, semid, semnum return(0); suptr = semu_alloc(td); if (suptr == NULL) - return(ENOSPC); + return (ENOSPC); *supptr = suptr; } } @@ -472,58 +439,59 @@ semundo_adjust(td, supptr, semid, semnum if (i < suptr->un_cnt) suptr->un_ent[i] = suptr->un_ent[suptr->un_cnt]; + if (suptr->un_cnt == 0) + semu_try_free(suptr); } - return(0); + return (0); } /* Didn't find the right entry - create it */ if (adjval == 0) - return(0); + return (0); if (adjval > seminfo.semaem || adjval < -seminfo.semaem) return (ERANGE); if (suptr->un_cnt != seminfo.semume) { sunptr = &suptr->un_ent[suptr->un_cnt]; suptr->un_cnt++; sunptr->un_adjval = adjval; - sunptr->un_id = semid; sunptr->un_num = semnum; + sunptr->un_id = semid; + sunptr->un_num = semnum; + sunptr->un_seq = semseq; } else - return(EINVAL); - return(0); + return (EINVAL); + return (0); } static void -semundo_clear(semid, semnum) - int semid, semnum; +semundo_clear(int semid, int semnum) { - struct sem_undo *suptr; + struct sem_undo *suptr, *suptr1; + struct undo *sunptr; + int i; SEMUNDO_LOCKASSERT(MA_OWNED); - SLIST_FOREACH(suptr, &semu_list, un_next) { - struct undo *sunptr = &suptr->un_ent[0]; - int i = 0; - - while (i < suptr->un_cnt) { - if (sunptr->un_id == semid) { - if (semnum == -1 || sunptr->un_num == semnum) { - suptr->un_cnt--; - if (i < suptr->un_cnt) { - suptr->un_ent[i] = - suptr->un_ent[suptr->un_cnt]; - continue; - } + LIST_FOREACH_SAFE(suptr, &semu_list, un_next, suptr1) { + sunptr = &suptr->un_ent[0]; + for (i = 0; i < suptr->un_cnt; i++, sunptr++) { + if (sunptr->un_id != semid) + continue; + if (semnum == -1 || sunptr->un_num == semnum) { + suptr->un_cnt--; + if (i < suptr->un_cnt) { + suptr->un_ent[i] = + suptr->un_ent[suptr->un_cnt]; + continue; } - if (semnum != -1) - break; + semu_try_free(suptr); } - i++, sunptr++; + if (semnum != -1) + break; } } } static int -semvalid(semid, semakptr) - int semid; - struct semid_kernel *semakptr; +semvalid(int semid, struct semid_kernel *semakptr) { return ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 || @@ -542,9 +510,7 @@ struct __semctl_args { }; #endif int -__semctl(td, uap) - struct thread *td; - struct __semctl_args *uap; +__semctl(struct thread *td, struct __semctl_args *uap) { struct semid_ds dsbuf; union semun arg, semun; @@ -655,6 +621,8 @@ kern_semctl(struct thread *td, int semid semakptr = &sema[semidx]; sema_mtxp = &sema_mtx[semidx]; + if (cmd == IPC_RMID) + mtx_lock(&sem_mtx); mtx_lock(sema_mtxp); #ifdef MAC error = mac_check_sysv_semctl(cred, semakptr, cmd); @@ -673,22 +641,29 @@ kern_semctl(struct thread *td, int semid goto done2; semakptr->u.sem_perm.cuid = cred->cr_uid; semakptr->u.sem_perm.uid = cred->cr_uid; - semtot -= semakptr->u.sem_nsems; + semakptr->u.sem_perm.mode = 0; + SEMUNDO_LOCK(); + semundo_clear(semidx, -1); + SEMUNDO_UNLOCK(); +#ifdef MAC + mac_cleanup_sysv_sem(semakptr); +#endif + wakeup(semakptr); + for (i = 0; i < seminfo.semmni; i++) { + if ((sema[i].u.sem_perm.mode & SEM_ALLOC) && + sema[i].u.sem_base > semakptr->u.sem_base) + mtx_lock_flags(&sema_mtx[i], LOP_DUPOK); + } for (i = semakptr->u.sem_base - sem; i < semtot; i++) sem[i] = sem[i + semakptr->u.sem_nsems]; for (i = 0; i < seminfo.semmni; i++) { if ((sema[i].u.sem_perm.mode & SEM_ALLOC) && - sema[i].u.sem_base > semakptr->u.sem_base) + sema[i].u.sem_base > semakptr->u.sem_base) { sema[i].u.sem_base -= semakptr->u.sem_nsems; + mtx_unlock(&sema_mtx[i]); + } } - semakptr->u.sem_perm.mode = 0; -#ifdef MAC - mac_cleanup_sysv_sem(semakptr); -#endif - SEMUNDO_LOCK(); - semundo_clear(semidx, -1); - SEMUNDO_UNLOCK(); - wakeup(semakptr); + semtot -= semakptr->u.sem_nsems; break; case IPC_SET: @@ -855,6 +830,8 @@ kern_semctl(struct thread *td, int semid done2: mtx_unlock(sema_mtxp); + if (cmd == IPC_RMID) + mtx_unlock(&sem_mtx); if (array != NULL) free(array, M_TEMP); return(error); @@ -868,9 +845,7 @@ struct semget_args { }; #endif int -semget(td, uap) - struct thread *td; - struct semget_args *uap; +semget(struct thread *td, struct semget_args *uap) { int semid, error = 0; int key = uap->key; @@ -882,7 +857,7 @@ semget(td, uap) if (!jail_sysvipc_allowed && jailed(td->td_ucred)) return (ENOSYS); - mtx_lock(&Giant); + mtx_lock(&sem_mtx); if (key != IPC_PRIVATE) { for (semid = 0; semid < seminfo.semmni; semid++) { if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) && @@ -939,6 +914,9 @@ semget(td, uap) goto done2; } DPRINTF(("semid %d is available\n", semid)); + mtx_lock(&sema_mtx[semid]); + KASSERT((sema[semid].u.sem_perm.mode & SEM_ALLOC) == 0, + ("Lost semaphore %d", semid)); sema[semid].u.sem_perm.key = key; sema[semid].u.sem_perm.cuid = cred->cr_uid; sema[semid].u.sem_perm.uid = cred->cr_uid; @@ -957,6 +935,7 @@ semget(td, uap) #ifdef MAC mac_create_sysv_sem(cred, &sema[semid]); #endif + mtx_unlock(&sema_mtx[semid]); DPRINTF(("sembase = %p, next = %p\n", sema[semid].u.sem_base, &sem[semtot])); } else { @@ -968,7 +947,7 @@ semget(td, uap) found: td->td_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].u.sem_perm); done2: - mtx_unlock(&Giant); + mtx_unlock(&sem_mtx); return (error); } @@ -980,9 +959,7 @@ struct semop_args { }; #endif int -semop(td, uap) - struct thread *td; - struct semop_args *uap; +semop(struct thread *td, struct semop_args *uap) { #define SMALL_SOPS 8 struct sembuf small_sops[SMALL_SOPS]; @@ -997,6 +974,7 @@ semop(td, uap) size_t i, j, k; int error; int do_wakeup, do_undos; + unsigned short seq; #ifdef SEM_DEBUG sops = NULL; @@ -1036,7 +1014,8 @@ semop(td, uap) error = EINVAL; goto done2; } - if (semakptr->u.sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { + seq = semakptr->u.sem_perm.seq; + if (seq != IPCID_TO_SEQ(uap->semid)) { error = EINVAL; goto done2; } @@ -1160,8 +1139,9 @@ semop(td, uap) /* * Make sure that the semaphore still exists */ + seq = semakptr->u.sem_perm.seq; if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 || - semakptr->u.sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { + seq != IPCID_TO_SEQ(uap->semid)) { error = EIDRM; goto done2; } @@ -1213,7 +1193,7 @@ done: adjval = sops[i].sem_op; if (adjval == 0) continue; - error = semundo_adjust(td, &suptr, semid, + error = semundo_adjust(td, &suptr, semid, seq, sops[i].sem_num, -adjval); if (error == 0) continue; @@ -1234,7 +1214,7 @@ done: adjval = sops[k].sem_op; if (adjval == 0) continue; - if (semundo_adjust(td, &suptr, semid, + if (semundo_adjust(td, &suptr, semid, seq, sops[k].sem_num, adjval) != 0) panic("semop - can't undo undos"); } @@ -1281,28 +1261,28 @@ done2: * semaphores. */ static void -semexit_myhook(arg, p) - void *arg; - struct proc *p; +semexit_myhook(void *arg, struct proc *p) { struct sem_undo *suptr; - struct sem_undo **supptr; + struct semid_kernel *semakptr; + struct mtx *sema_mtxp; + int semid, semnum, adjval, ix; + unsigned short seq; /* * Go through the chain of undo vectors looking for one * associated with this process. */ SEMUNDO_LOCK(); - SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list, un_next) { - if (suptr->un_proc == p) { - *supptr = SLIST_NEXT(suptr, un_next); + LIST_FOREACH(suptr, &semu_list, un_next) { + if (suptr->un_proc == p) break; - } } - SEMUNDO_UNLOCK(); - - if (suptr == NULL) + if (suptr == NULL) { + SEMUNDO_UNLOCK(); return; + } + LIST_REMOVE(suptr, un_next); DPRINTF(("proc @%p has undo structure with %d entries\n", p, suptr->un_cnt)); @@ -1311,21 +1291,21 @@ semexit_myhook(arg, p) * If there are any active undo elements then process them. */ if (suptr->un_cnt > 0) { - int ix; - + SEMUNDO_UNLOCK(); for (ix = 0; ix < suptr->un_cnt; ix++) { - int semid = suptr->un_ent[ix].un_id; - int semnum = suptr->un_ent[ix].un_num; - int adjval = suptr->un_ent[ix].un_adjval; - struct semid_kernel *semakptr; - struct mtx *sema_mtxp; - + semid = suptr->un_ent[ix].un_id; + semnum = suptr->un_ent[ix].un_num; + adjval = suptr->un_ent[ix].un_adjval; + seq = suptr->un_ent[ix].un_seq; semakptr = &sema[semid]; sema_mtxp = &sema_mtx[semid]; + mtx_lock(sema_mtxp); - SEMUNDO_LOCK(); - if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0) - panic("semexit - semid not allocated"); + if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 || + (semakptr->u.sem_perm.seq != seq)) { + mtx_unlock(sema_mtxp); + continue; + } if (semnum >= semakptr->u.sem_nsems) panic("semexit - semnum out of range"); @@ -1336,29 +1316,26 @@ semexit_myhook(arg, p) suptr->un_ent[ix].un_adjval, semakptr->u.sem_base[semnum].semval)); - if (adjval < 0) { - if (semakptr->u.sem_base[semnum].semval < - -adjval) - semakptr->u.sem_base[semnum].semval = 0; - else - semakptr->u.sem_base[semnum].semval += - adjval; - } else + if (adjval < 0 && semakptr->u.sem_base[semnum].semval < + -adjval) + semakptr->u.sem_base[semnum].semval = 0; + else semakptr->u.sem_base[semnum].semval += adjval; wakeup(semakptr); DPRINTF(("semexit: back from wakeup\n")); mtx_unlock(sema_mtxp); - SEMUNDO_UNLOCK(); } + SEMUNDO_LOCK(); } /* * Deallocate the undo vector. */ DPRINTF(("removing vector\n")); - SEMUNDO_LOCK(); suptr->un_proc = NULL; + suptr->un_cnt = 0; + LIST_INSERT_HEAD(&semu_free_list, suptr, un_next); SEMUNDO_UNLOCK(); } From luigi at FreeBSD.org Fri Feb 13 05:35:45 2009 From: luigi at FreeBSD.org (Luigi Rizzo) Date: Fri Feb 13 05:36:02 2009 Subject: svn commit: r188576 - stable/7/sys/netinet Message-ID: <200902131335.n1DDZffx089893@svn.freebsd.org> Author: luigi Date: Fri Feb 13 13:35:41 2009 New Revision: 188576 URL: http://svn.freebsd.org/changeset/base/188576 Log: remove some unnecessary #include The change is not directly applicable to HEAD because there a lot of headers are already included by vnet.h Modified: stable/7/sys/netinet/ip_dummynet.c stable/7/sys/netinet/ip_fw2.c Modified: stable/7/sys/netinet/ip_dummynet.c ============================================================================== --- stable/7/sys/netinet/ip_dummynet.c Fri Feb 13 12:59:54 2009 (r188575) +++ stable/7/sys/netinet/ip_dummynet.c Fri Feb 13 13:35:41 2009 (r188576) @@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -81,7 +80,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include /* for struct arpcom */ +#include /* various ether_* routines */ #include /* for ip6_input, ip6_output prototypes */ #include Modified: stable/7/sys/netinet/ip_fw2.c ============================================================================== --- stable/7/sys/netinet/ip_fw2.c Fri Feb 13 12:59:54 2009 (r188575) +++ stable/7/sys/netinet/ip_fw2.c Fri Feb 13 13:35:41 2009 (r188576) @@ -83,17 +83,12 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #include -#include #include #include #include #include -#include - #include #include #ifdef INET6 @@ -104,7 +99,9 @@ __FBSDID("$FreeBSD$"); #include /* XXX for in_cksum */ +#ifdef MAC #include +#endif /* * set_disable contains one bit per set value (0..31). From luigi at FreeBSD.org Fri Feb 13 10:04:57 2009 From: luigi at FreeBSD.org (Luigi Rizzo) Date: Fri Feb 13 10:05:02 2009 Subject: svn commit: r188586 - stable/7/sys/netinet Message-ID: <200902131804.n1DI4uWN095330@svn.freebsd.org> Author: luigi Date: Fri Feb 13 18:04:55 2009 New Revision: 188586 URL: http://svn.freebsd.org/changeset/base/188586 Log: document why certain headers are required. Modified: stable/7/sys/netinet/ip_dummynet.c Modified: stable/7/sys/netinet/ip_dummynet.c ============================================================================== --- stable/7/sys/netinet/ip_dummynet.c Fri Feb 13 17:45:09 2009 (r188585) +++ stable/7/sys/netinet/ip_dummynet.c Fri Feb 13 18:04:55 2009 (r188586) @@ -70,15 +70,14 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include /* IFNAMSIZ, struct ifaddr, ifq head, lock.h mutex.h */ #include #include -#include -#include -#include +#include /* n_long, SYSCTL_DECL(_net) */ +#include /* ip_len, ip_off */ #include #include -#include +#include /* ip_output(), IP_FORWARDING */ #include /* various ether_* routines */ @@ -154,6 +153,9 @@ static struct callout dn_timeout; extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *); #ifdef SYSCTL_NODE +SYSCTL_DECL(_net_inet); +SYSCTL_DECL(_net_inet_ip); + SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet, CTLFLAG_RW, 0, "Dummynet"); SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, hash_size, CTLFLAG_RW, &dn_hash_size, 0, "Default hash table size"); @@ -889,7 +891,7 @@ dummynet_send(struct mbuf *m) case DN_TO_IP_OUT: ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); break ; - case DN_TO_IP_IN : + case DN_TO_IP_IN : ip = mtod(m, struct ip *); ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); From luigi at FreeBSD.org Fri Feb 13 10:09:39 2009 From: luigi at FreeBSD.org (Luigi Rizzo) Date: Fri Feb 13 10:09:46 2009 Subject: svn commit: r188587 - stable/7/sys/netinet Message-ID: <200902131809.n1DI9cXb095457@svn.freebsd.org> Author: luigi Date: Fri Feb 13 18:09:38 2009 New Revision: 188587 URL: http://svn.freebsd.org/changeset/base/188587 Log: MFC - replace usage of n_* types with uint*_t , to help removing unnecessary dependencies on in_systm.h Modified: stable/7/sys/netinet/in_systm.h stable/7/sys/netinet/ip.h stable/7/sys/netinet/ip_icmp.c stable/7/sys/netinet/ip_icmp.h stable/7/sys/netinet/ip_options.c stable/7/sys/netinet/tcp_debug.h stable/7/sys/netinet/tcp_subr.c Modified: stable/7/sys/netinet/in_systm.h ============================================================================== --- stable/7/sys/netinet/in_systm.h Fri Feb 13 18:04:55 2009 (r188586) +++ stable/7/sys/netinet/in_systm.h Fri Feb 13 18:09:38 2009 (r188587) @@ -52,7 +52,7 @@ typedef u_int32_t n_long; /* long as re typedef u_int32_t n_time; /* ms since 00:00 GMT, byte rev */ #ifdef _KERNEL -n_time iptime(void); +uint32_t iptime(void); #endif #endif Modified: stable/7/sys/netinet/ip.h ============================================================================== --- stable/7/sys/netinet/ip.h Fri Feb 13 18:04:55 2009 (r188586) +++ stable/7/sys/netinet/ip.h Fri Feb 13 18:09:38 2009 (r188587) @@ -159,10 +159,10 @@ struct ip_timestamp { ipt_flg:4; /* flags, see below */ #endif union ipt_timestamp { - n_long ipt_time[1]; + uint32_t ipt_time[1]; /* network format */ struct ipt_ta { struct in_addr ipt_addr; - n_long ipt_time; + uint32_t ipt_time; /* network format */ } ipt_ta[1]; } ipt_timestamp; }; Modified: stable/7/sys/netinet/ip_icmp.c ============================================================================== --- stable/7/sys/netinet/ip_icmp.c Fri Feb 13 18:04:55 2009 (r188586) +++ stable/7/sys/netinet/ip_icmp.c Fri Feb 13 18:09:38 2009 (r188587) @@ -141,7 +141,7 @@ extern struct protosw inetsw[]; * in response to bad packet ip. */ void -icmp_error(struct mbuf *n, int type, int code, n_long dest, int mtu) +icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu) { register struct ip *oip = mtod(n, struct ip *), *nip; register unsigned oiphlen = oip->ip_hl << 2; @@ -825,7 +825,10 @@ icmp_send(struct mbuf *m, struct mbuf *o (void) ip_output(m, opts, NULL, 0, NULL, NULL); } -n_time +/* + * Return milliseconds since 00:00 GMT in network format. + */ +uint32_t iptime(void) { struct timeval atv; Modified: stable/7/sys/netinet/ip_icmp.h ============================================================================== --- stable/7/sys/netinet/ip_icmp.h Fri Feb 13 18:04:55 2009 (r188586) +++ stable/7/sys/netinet/ip_icmp.h Fri Feb 13 18:09:38 2009 (r188587) @@ -68,15 +68,15 @@ struct icmp { u_char ih_pptr; /* ICMP_PARAMPROB */ struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ struct ih_idseq { - n_short icd_id; - n_short icd_seq; + uint16_t icd_id; /* network format */ + uint16_t icd_seq; /* network format */ } ih_idseq; int ih_void; /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ struct ih_pmtu { - n_short ipm_void; - n_short ipm_nextmtu; + uint16_t ipm_void; /* network format */ + uint16_t ipm_nextmtu; /* network format */ } ih_pmtu; struct ih_rtradv { @@ -97,9 +97,13 @@ struct icmp { #define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime union { struct id_ts { /* ICMP Timestamp */ - n_time its_otime; /* Originate */ - n_time its_rtime; /* Receive */ - n_time its_ttime; /* Transmit */ + /* + * The next 3 fields are in network format, + * milliseconds since 00:00 GMT + */ + uint32_t its_otime; /* Originate */ + uint32_t its_rtime; /* Receive */ + uint32_t its_ttime; /* Transmit */ } id_ts; struct id_ip { struct ip idi_ip; @@ -127,7 +131,7 @@ struct icmp { * ip header length. */ #define ICMP_MINLEN 8 /* abs minimum */ -#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ +#define ICMP_TSLEN (8 + 3 * sizeof (uint32_t)) /* timestamp */ #define ICMP_MASKLEN 12 /* address mask */ #define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ #define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) @@ -202,7 +206,7 @@ struct icmp { (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) #ifdef _KERNEL -void icmp_error(struct mbuf *, int, int, n_long, int); +void icmp_error(struct mbuf *, int, int, uint32_t, int); void icmp_input(struct mbuf *, int); int ip_next_mtu(int, int); #endif Modified: stable/7/sys/netinet/ip_options.c ============================================================================== --- stable/7/sys/netinet/ip_options.c Fri Feb 13 18:04:55 2009 (r188586) +++ stable/7/sys/netinet/ip_options.c Fri Feb 13 18:09:38 2009 (r188587) @@ -102,7 +102,7 @@ ip_dooptions(struct mbuf *m, int pass) struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; struct in_addr *sin, dst; - n_time ntime; + uint32_t ntime; struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; /* Ignore or reject packets with IP options. */ @@ -317,7 +317,7 @@ dropit: break; case IPOPT_TS_TSANDADDR: - if (off + sizeof(n_time) + + if (off + sizeof(uint32_t) + sizeof(struct in_addr) > optlen) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; @@ -334,7 +334,7 @@ dropit: break; case IPOPT_TS_PRESPEC: - if (off + sizeof(n_time) + + if (off + sizeof(uint32_t) + sizeof(struct in_addr) > optlen) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; @@ -352,8 +352,8 @@ dropit: goto bad; } ntime = iptime(); - (void)memcpy(cp + off, &ntime, sizeof(n_time)); - cp[IPOPT_OFFSET] += sizeof(n_time); + (void)memcpy(cp + off, &ntime, sizeof(uint32_t)); + cp[IPOPT_OFFSET] += sizeof(uint32_t); } } if (forward && ipforwarding) { Modified: stable/7/sys/netinet/tcp_debug.h ============================================================================== --- stable/7/sys/netinet/tcp_debug.h Fri Feb 13 18:04:55 2009 (r188586) +++ stable/7/sys/netinet/tcp_debug.h Fri Feb 13 18:09:38 2009 (r188587) @@ -34,7 +34,7 @@ #define _NETINET_TCP_DEBUG_H_ struct tcp_debug { - n_time td_time; + uint32_t td_time; /* network format */ short td_act; short td_ostate; caddr_t td_tcb; Modified: stable/7/sys/netinet/tcp_subr.c ============================================================================== --- stable/7/sys/netinet/tcp_subr.c Fri Feb 13 18:04:55 2009 (r188586) +++ stable/7/sys/netinet/tcp_subr.c Fri Feb 13 18:09:38 2009 (r188587) @@ -484,7 +484,7 @@ tcp_respond(struct tcpcb *tp, void *ipge } else #endif /* INET6 */ { - xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, n_long); + xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, uint32_t); nth = (struct tcphdr *)(ip + 1); } if (th != nth) { @@ -496,7 +496,7 @@ tcp_respond(struct tcpcb *tp, void *ipge nth->th_sport = th->th_sport; nth->th_dport = th->th_dport; } - xchg(nth->th_dport, nth->th_sport, n_short); + xchg(nth->th_dport, nth->th_sport, uint16_t); #undef xchg } #ifdef INET6 From luigi at FreeBSD.org Fri Feb 13 10:31:36 2009 From: luigi at FreeBSD.org (Luigi Rizzo) Date: Fri Feb 13 10:31:53 2009 Subject: svn commit: r188589 - stable/7/sys/netinet Message-ID: <200902131831.n1DIVZpj095941@svn.freebsd.org> Author: luigi Date: Fri Feb 13 18:31:35 2009 New Revision: 188589 URL: http://svn.freebsd.org/changeset/base/188589 Log: remove some unnecessary #include Again, this change is not directly applicable to HEAD due to the presence of vnet.h and vinet.h which bring in almost every network-related header. Modified: stable/7/sys/netinet/ip_dummynet.c stable/7/sys/netinet/ip_fw2.c stable/7/sys/netinet/ip_fw_pfil.c stable/7/sys/netinet/ip_input.c Modified: stable/7/sys/netinet/ip_dummynet.c ============================================================================== --- stable/7/sys/netinet/ip_dummynet.c Fri Feb 13 18:18:14 2009 (r188588) +++ stable/7/sys/netinet/ip_dummynet.c Fri Feb 13 18:31:35 2009 (r188589) @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include /* IFNAMSIZ, struct ifaddr, ifq head, lock.h mutex.h */ #include #include -#include /* n_long, SYSCTL_DECL(_net) */ #include /* ip_len, ip_off */ #include #include Modified: stable/7/sys/netinet/ip_fw2.c ============================================================================== --- stable/7/sys/netinet/ip_fw2.c Fri Feb 13 18:18:14 2009 (r188588) +++ stable/7/sys/netinet/ip_fw2.c Fri Feb 13 18:31:35 2009 (r188589) @@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$"); #define IPFW_INTERNAL /* Access to protected data structures in ip_fw.h. */ #include -#include #include #include #include Modified: stable/7/sys/netinet/ip_fw_pfil.c ============================================================================== --- stable/7/sys/netinet/ip_fw_pfil.c Fri Feb 13 18:18:14 2009 (r188588) +++ stable/7/sys/netinet/ip_fw_pfil.c Fri Feb 13 18:31:35 2009 (r188589) @@ -46,15 +46,11 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include -#include #include #include -#include -#include #include #include #include Modified: stable/7/sys/netinet/ip_input.c ============================================================================== --- stable/7/sys/netinet/ip_input.c Fri Feb 13 18:18:14 2009 (r188588) +++ stable/7/sys/netinet/ip_input.c Fri Feb 13 18:31:35 2009 (r188589) @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include From rwatson at FreeBSD.org Fri Feb 13 10:54:38 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Fri Feb 13 10:54:56 2009 Subject: svn commit: r188587 - stable/7/sys/netinet In-Reply-To: <200902131809.n1DI9cXb095457@svn.freebsd.org> References: <200902131809.n1DI9cXb095457@svn.freebsd.org> Message-ID: On Fri, 13 Feb 2009, Luigi Rizzo wrote: > Author: luigi > Date: Fri Feb 13 18:09:38 2009 > New Revision: 188587 > URL: http://svn.freebsd.org/changeset/base/188587 > > Log: > MFC - replace usage of n_* types with uint*_t , to help removing > unnecessary dependencies on in_systm.h As harmless as these changes may seem, insta-MFCs often come with unexpected side effects. A three day MFC wait will also never hurt for what are definitely not critical bug fixes :-). Robert N M Watson Computer Laboratory University of Cambridge > > Modified: > stable/7/sys/netinet/in_systm.h > stable/7/sys/netinet/ip.h > stable/7/sys/netinet/ip_icmp.c > stable/7/sys/netinet/ip_icmp.h > stable/7/sys/netinet/ip_options.c > stable/7/sys/netinet/tcp_debug.h > stable/7/sys/netinet/tcp_subr.c > > Modified: stable/7/sys/netinet/in_systm.h > ============================================================================== > --- stable/7/sys/netinet/in_systm.h Fri Feb 13 18:04:55 2009 (r188586) > +++ stable/7/sys/netinet/in_systm.h Fri Feb 13 18:09:38 2009 (r188587) > @@ -52,7 +52,7 @@ typedef u_int32_t n_long; /* long as re > typedef u_int32_t n_time; /* ms since 00:00 GMT, byte rev */ > > #ifdef _KERNEL > -n_time iptime(void); > +uint32_t iptime(void); > #endif > > #endif > > Modified: stable/7/sys/netinet/ip.h > ============================================================================== > --- stable/7/sys/netinet/ip.h Fri Feb 13 18:04:55 2009 (r188586) > +++ stable/7/sys/netinet/ip.h Fri Feb 13 18:09:38 2009 (r188587) > @@ -159,10 +159,10 @@ struct ip_timestamp { > ipt_flg:4; /* flags, see below */ > #endif > union ipt_timestamp { > - n_long ipt_time[1]; > + uint32_t ipt_time[1]; /* network format */ > struct ipt_ta { > struct in_addr ipt_addr; > - n_long ipt_time; > + uint32_t ipt_time; /* network format */ > } ipt_ta[1]; > } ipt_timestamp; > }; > > Modified: stable/7/sys/netinet/ip_icmp.c > ============================================================================== > --- stable/7/sys/netinet/ip_icmp.c Fri Feb 13 18:04:55 2009 (r188586) > +++ stable/7/sys/netinet/ip_icmp.c Fri Feb 13 18:09:38 2009 (r188587) > @@ -141,7 +141,7 @@ extern struct protosw inetsw[]; > * in response to bad packet ip. > */ > void > -icmp_error(struct mbuf *n, int type, int code, n_long dest, int mtu) > +icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu) > { > register struct ip *oip = mtod(n, struct ip *), *nip; > register unsigned oiphlen = oip->ip_hl << 2; > @@ -825,7 +825,10 @@ icmp_send(struct mbuf *m, struct mbuf *o > (void) ip_output(m, opts, NULL, 0, NULL, NULL); > } > > -n_time > +/* > + * Return milliseconds since 00:00 GMT in network format. > + */ > +uint32_t > iptime(void) > { > struct timeval atv; > > Modified: stable/7/sys/netinet/ip_icmp.h > ============================================================================== > --- stable/7/sys/netinet/ip_icmp.h Fri Feb 13 18:04:55 2009 (r188586) > +++ stable/7/sys/netinet/ip_icmp.h Fri Feb 13 18:09:38 2009 (r188587) > @@ -68,15 +68,15 @@ struct icmp { > u_char ih_pptr; /* ICMP_PARAMPROB */ > struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ > struct ih_idseq { > - n_short icd_id; > - n_short icd_seq; > + uint16_t icd_id; /* network format */ > + uint16_t icd_seq; /* network format */ > } ih_idseq; > int ih_void; > > /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ > struct ih_pmtu { > - n_short ipm_void; > - n_short ipm_nextmtu; > + uint16_t ipm_void; /* network format */ > + uint16_t ipm_nextmtu; /* network format */ > } ih_pmtu; > > struct ih_rtradv { > @@ -97,9 +97,13 @@ struct icmp { > #define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime > union { > struct id_ts { /* ICMP Timestamp */ > - n_time its_otime; /* Originate */ > - n_time its_rtime; /* Receive */ > - n_time its_ttime; /* Transmit */ > + /* > + * The next 3 fields are in network format, > + * milliseconds since 00:00 GMT > + */ > + uint32_t its_otime; /* Originate */ > + uint32_t its_rtime; /* Receive */ > + uint32_t its_ttime; /* Transmit */ > } id_ts; > struct id_ip { > struct ip idi_ip; > @@ -127,7 +131,7 @@ struct icmp { > * ip header length. > */ > #define ICMP_MINLEN 8 /* abs minimum */ > -#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ > +#define ICMP_TSLEN (8 + 3 * sizeof (uint32_t)) /* timestamp */ > #define ICMP_MASKLEN 12 /* address mask */ > #define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ > #define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) > @@ -202,7 +206,7 @@ struct icmp { > (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) > > #ifdef _KERNEL > -void icmp_error(struct mbuf *, int, int, n_long, int); > +void icmp_error(struct mbuf *, int, int, uint32_t, int); > void icmp_input(struct mbuf *, int); > int ip_next_mtu(int, int); > #endif > > Modified: stable/7/sys/netinet/ip_options.c > ============================================================================== > --- stable/7/sys/netinet/ip_options.c Fri Feb 13 18:04:55 2009 (r188586) > +++ stable/7/sys/netinet/ip_options.c Fri Feb 13 18:09:38 2009 (r188587) > @@ -102,7 +102,7 @@ ip_dooptions(struct mbuf *m, int pass) > struct in_ifaddr *ia; > int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; > struct in_addr *sin, dst; > - n_time ntime; > + uint32_t ntime; > struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; > > /* Ignore or reject packets with IP options. */ > @@ -317,7 +317,7 @@ dropit: > break; > > case IPOPT_TS_TSANDADDR: > - if (off + sizeof(n_time) + > + if (off + sizeof(uint32_t) + > sizeof(struct in_addr) > optlen) { > code = &cp[IPOPT_OFFSET] - (u_char *)ip; > goto bad; > @@ -334,7 +334,7 @@ dropit: > break; > > case IPOPT_TS_PRESPEC: > - if (off + sizeof(n_time) + > + if (off + sizeof(uint32_t) + > sizeof(struct in_addr) > optlen) { > code = &cp[IPOPT_OFFSET] - (u_char *)ip; > goto bad; > @@ -352,8 +352,8 @@ dropit: > goto bad; > } > ntime = iptime(); > - (void)memcpy(cp + off, &ntime, sizeof(n_time)); > - cp[IPOPT_OFFSET] += sizeof(n_time); > + (void)memcpy(cp + off, &ntime, sizeof(uint32_t)); > + cp[IPOPT_OFFSET] += sizeof(uint32_t); > } > } > if (forward && ipforwarding) { > > Modified: stable/7/sys/netinet/tcp_debug.h > ============================================================================== > --- stable/7/sys/netinet/tcp_debug.h Fri Feb 13 18:04:55 2009 (r188586) > +++ stable/7/sys/netinet/tcp_debug.h Fri Feb 13 18:09:38 2009 (r188587) > @@ -34,7 +34,7 @@ > #define _NETINET_TCP_DEBUG_H_ > > struct tcp_debug { > - n_time td_time; > + uint32_t td_time; /* network format */ > short td_act; > short td_ostate; > caddr_t td_tcb; > > Modified: stable/7/sys/netinet/tcp_subr.c > ============================================================================== > --- stable/7/sys/netinet/tcp_subr.c Fri Feb 13 18:04:55 2009 (r188586) > +++ stable/7/sys/netinet/tcp_subr.c Fri Feb 13 18:09:38 2009 (r188587) > @@ -484,7 +484,7 @@ tcp_respond(struct tcpcb *tp, void *ipge > } else > #endif /* INET6 */ > { > - xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, n_long); > + xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, uint32_t); > nth = (struct tcphdr *)(ip + 1); > } > if (th != nth) { > @@ -496,7 +496,7 @@ tcp_respond(struct tcpcb *tp, void *ipge > nth->th_sport = th->th_sport; > nth->th_dport = th->th_dport; > } > - xchg(nth->th_dport, nth->th_sport, n_short); > + xchg(nth->th_dport, nth->th_sport, uint16_t); > #undef xchg > } > #ifdef INET6 > From mav at FreeBSD.org Fri Feb 13 11:16:17 2009 From: mav at FreeBSD.org (Alexander Motin) Date: Fri Feb 13 11:16:29 2009 Subject: svn commit: r188593 - stable/7/sbin/route Message-ID: <200902131916.n1DJGFtg096988@svn.freebsd.org> Author: mav Date: Fri Feb 13 19:16:15 2009 New Revision: 188593 URL: http://svn.freebsd.org/changeset/base/188593 Log: MFC rev. 187384 Fix regression introduced at rev. 173124: 0.0.0.0/1 is not the same as 0.0.0.0/0. Modified: stable/7/sbin/route/ (props changed) stable/7/sbin/route/route.c Modified: stable/7/sbin/route/route.c ============================================================================== --- stable/7/sbin/route/route.c Fri Feb 13 18:51:39 2009 (r188592) +++ stable/7/sbin/route/route.c Fri Feb 13 19:16:15 2009 (r188593) @@ -797,33 +797,34 @@ inet_makenetandmask(net, sin, bits) char *cp; rtm_addrs |= RTA_NETMASK; - if (net == 0) - mask = addr = 0; - else { - if (net <= 0xff) - addr = net << IN_CLASSA_NSHIFT; - else if (net <= 0xffff) - addr = net << IN_CLASSB_NSHIFT; - else if (net <= 0xffffff) - addr = net << IN_CLASSC_NSHIFT; - else - addr = net; + /* + * XXX: This approach unable to handle 0.0.0.1/32 correctly + * as inet_network() converts 0.0.0.1 and 1 equally. + */ + if (net <= 0xff) + addr = net << IN_CLASSA_NSHIFT; + else if (net <= 0xffff) + addr = net << IN_CLASSB_NSHIFT; + else if (net <= 0xffffff) + addr = net << IN_CLASSC_NSHIFT; + else + addr = net; + + if (bits != 0) + mask = 0xffffffff << (32 - bits); + else if (net == 0) + mask = 0; + else if (IN_CLASSA(addr)) + mask = IN_CLASSA_NET; + else if (IN_CLASSB(addr)) + mask = IN_CLASSB_NET; + else if (IN_CLASSC(addr)) + mask = IN_CLASSC_NET; + else if (IN_MULTICAST(addr)) + mask = IN_CLASSD_NET; + else + mask = 0xffffffff; - if (bits != 0) - mask = 0xffffffff << (32 - bits); - else { - if (IN_CLASSA(addr)) - mask = IN_CLASSA_NET; - else if (IN_CLASSB(addr)) - mask = IN_CLASSB_NET; - else if (IN_CLASSC(addr)) - mask = IN_CLASSC_NET; - else if (IN_MULTICAST(addr)) - mask = IN_CLASSD_NET; - else - mask = 0xffffffff; - } - } sin->sin_addr.s_addr = htonl(addr); sin = &so_mask.sin; sin->sin_addr.s_addr = htonl(mask); From lulf at FreeBSD.org Fri Feb 13 11:49:36 2009 From: lulf at FreeBSD.org (Ulf Lilleengen) Date: Fri Feb 13 11:49:42 2009 Subject: svn commit: r188596 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb geom/label Message-ID: <200902131949.n1DJnZLj097705@svn.freebsd.org> Author: lulf Date: Fri Feb 13 19:49:35 2009 New Revision: 188596 URL: http://svn.freebsd.org/changeset/base/188596 Log: MFC r188492: - Use the correct argument when determining the buffer size. PR: kern/131575 Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/geom/label/g_label_msdosfs.c Modified: stable/7/sys/geom/label/g_label_msdosfs.c ============================================================================== --- stable/7/sys/geom/label/g_label_msdosfs.c Fri Feb 13 19:25:35 2009 (r188595) +++ stable/7/sys/geom/label/g_label_msdosfs.c Fri Feb 13 19:49:35 2009 (r188596) @@ -186,7 +186,7 @@ g_label_msdosfs_taste(struct g_consumer FAT_DES_ATTR_VOLUME_ID) { strlcpy(label, pfat_entry->DIR_Name, MIN(size, - sizeof(pfat_bsbpb->BS_VolLab) + 1)); + sizeof(pfat_entry->DIR_Name) + 1)); goto endofchecks; } } while((uint8_t *)(++pfat_entry) < From rizzo at iet.unipi.it Fri Feb 13 15:04:31 2009 From: rizzo at iet.unipi.it (Luigi Rizzo) Date: Fri Feb 13 15:04:38 2009 Subject: svn commit: r188587 - stable/7/sys/netinet In-Reply-To: References: <200902131809.n1DI9cXb095457@svn.freebsd.org> Message-ID: <20090213225427.GA69192@onelab2.iet.unipi.it> On Fri, Feb 13, 2009 at 06:54:37PM +0000, Robert Watson wrote: > > On Fri, 13 Feb 2009, Luigi Rizzo wrote: > > >Author: luigi > >Date: Fri Feb 13 18:09:38 2009 > >New Revision: 188587 > >URL: http://svn.freebsd.org/changeset/base/188587 > > > >Log: > > MFC - replace usage of n_* types with uint*_t , to help removing > > unnecessary dependencies on in_systm.h > > As harmless as these changes may seem, insta-MFCs often come with > unexpected side effects. A three day MFC wait will also never hurt for > what are definitely not critical bug fixes :-). To put this commit in the right context: I know the recommendation on MFC. But this is actually not an MFC but an MFStable as I will explain below. I started this work to remove useless header dependencies from ipfw and dummynet (and, as a side effect, the network stack as well). You may have seen userland changes being committed 1-2 weeks ago, in that case only in HEAD because that's was the appropriate approach in that context. But the kernel side is different. As I mentioned in some other commits today, HEAD and RELENG_7 are largely different in this respect after the VIMAGE import: in HEAD, several netinet/ files #include vnet.h and vinet.h which in turn bring in almost everything related to networking: if.h, route.h, <*_var.h> for the stats records, locks and so on. As a result, the cleanup work needs to be done differently in the two branches. In fact, the real reference is RELENG_7 which is clean from nested #include's: it's there that I can find out which headers are not necessary, and then I use the information to drive the changes to HEAD keeping in mind that eventually vinet.h should be cleaned up as well. That's why I say that these changes are closer to Merge >From Stable than to MFC. The n_* cleanup just happens to be part of both changesets, but that's only a minor part. cheers luigi From kib at FreeBSD.org Sat Feb 14 12:42:55 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 12:43:12 2009 Subject: svn commit: r188610 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern sys Message-ID: <200902142042.n1EKgsDR029815@svn.freebsd.org> Author: kib Date: Sat Feb 14 20:42:54 2009 New Revision: 188610 URL: http://svn.freebsd.org/changeset/base/188610 Log: MFC r182364: Introduce the VV_FORCEINSMQ vnode flag. It instructs the insmnque() function to ignore the unmounting and forces insertion of the vnode into the mount vnode list. Change insmntque() to fail when forced unmount is in progress and VV_FORCEINSMQ is not specified. Add an assertion to the insmntque(), requiring the vnode to be exclusively locked for mp-safe filesystems. MFC note: because zfs in stable/7 does not follow the insmntque() protocol, the assertion is commented out. Use the VV_FORCEINSMQ for the creation of the syncvnode. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/vfs_subr.c stable/7/sys/sys/vnode.h Modified: stable/7/sys/kern/vfs_subr.c ============================================================================== --- stable/7/sys/kern/vfs_subr.c Sat Feb 14 19:46:28 2009 (r188609) +++ stable/7/sys/kern/vfs_subr.c Sat Feb 14 20:42:54 2009 (r188610) @@ -1007,17 +1007,30 @@ int insmntque1(struct vnode *vp, struct mount *mp, void (*dtr)(struct vnode *, void *), void *dtr_arg) { + int locked; KASSERT(vp->v_mount == NULL, ("insmntque: vnode already on per mount vnode list")); VNASSERT(mp != NULL, vp, ("Don't call insmntque(foo, NULL)")); +#if 0 +#ifdef DEBUG_VFS_LOCKS + if (!VFS_NEEDSGIANT(mp)) + ASSERT_VOP_ELOCKED(vp, + "insmntque: mp-safe fs and non-locked vp"); +#endif +#endif MNT_ILOCK(mp); if ((mp->mnt_kern_flag & MNTK_NOINSMNTQ) != 0 && - mp->mnt_nvnodelistsize == 0) { - MNT_IUNLOCK(mp); - if (dtr != NULL) - dtr(vp, dtr_arg); - return (EBUSY); + ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0 || + mp->mnt_nvnodelistsize == 0)) { + locked = VOP_ISLOCKED(vp, curthread); + if (!locked || (locked == LK_EXCLUSIVE && + (vp->v_vflag & VV_FORCEINSMQ) == 0)) { + MNT_IUNLOCK(mp); + if (dtr != NULL) + dtr(vp, dtr_arg); + return (EBUSY); + } } vp->v_mount = mp; MNT_REF(mp); @@ -3140,9 +3153,13 @@ vfs_allocate_syncvnode(struct mount *mp) return (error); } vp->v_type = VNON; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); + vp->v_vflag |= VV_FORCEINSMQ; error = insmntque(vp, mp); if (error != 0) panic("vfs_allocate_syncvnode: insmntque failed"); + vp->v_vflag &= ~VV_FORCEINSMQ; + VOP_UNLOCK(vp, 0, curthread); /* * Place the vnode onto the syncer worklist. We attempt to * scatter them about on the list so that they will go off Modified: stable/7/sys/sys/vnode.h ============================================================================== --- stable/7/sys/sys/vnode.h Sat Feb 14 19:46:28 2009 (r188609) +++ stable/7/sys/sys/vnode.h Sat Feb 14 20:42:54 2009 (r188610) @@ -251,6 +251,7 @@ struct xvnode { #define VV_NOKNOTE 0x0200 /* don't activate knotes on this vnode */ #define VV_DELETED 0x0400 /* should be removed */ #define VV_MD 0x0800 /* vnode backs the md device */ +#define VV_FORCEINSMQ 0x1000 /* force the insmntque to succeed */ /* * Vnode attributes. A field value of VNOVAL represents a field whose value From kib at FreeBSD.org Sat Feb 14 12:59:52 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 13:00:10 2009 Subject: svn commit: r188611 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb ufs/ffs Message-ID: <200902142059.n1EKxo5F030146@svn.freebsd.org> Author: kib Date: Sat Feb 14 20:59:50 2009 New Revision: 188611 URL: http://svn.freebsd.org/changeset/base/188611 Log: MFC r182365: Softdep code may need to instantiate vnode when processing dependencies. In particular, it may need this while syncing filesystem being unmounted. Since during unmount MNTK_NOINSMNTQUE flag is set, that could sometimes disallow insertion of the vnode into the vnode mount list, softdep code needs to overwrite the MNTK_NOINSMNTQUE flag. Create the ffs_vgetf() function that sets the VV_FORCEINSMQ flag for new vnode and use it consistently from the softdep code instead of ffs_vget(). Add the retry logic to the softdep_flushfiles() to flush the vnodes that could be instantiated while flushing softdep dependencies. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/ufs/ffs/ffs_extern.h stable/7/sys/ufs/ffs/ffs_softdep.c stable/7/sys/ufs/ffs/ffs_vfsops.c Modified: stable/7/sys/ufs/ffs/ffs_extern.h ============================================================================== --- stable/7/sys/ufs/ffs/ffs_extern.h Sat Feb 14 20:42:54 2009 (r188610) +++ stable/7/sys/ufs/ffs/ffs_extern.h Sat Feb 14 20:59:50 2009 (r188611) @@ -87,6 +87,9 @@ int ffs_valloc(struct vnode *, int, stru int ffs_vfree(struct vnode *, ino_t, int); vfs_vget_t ffs_vget; +int ffs_vgetf(struct mount *, ino_t, int, struct vnode **, int); + +#define FFSV_FORCEINSMQ 0x0001 extern struct vop_vector ffs_vnodeops1; extern struct vop_vector ffs_fifoops1; Modified: stable/7/sys/ufs/ffs/ffs_softdep.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_softdep.c Sat Feb 14 20:42:54 2009 (r188610) +++ stable/7/sys/ufs/ffs/ffs_softdep.c Sat Feb 14 20:59:50 2009 (r188611) @@ -921,8 +921,8 @@ process_worklist_item(mp, flags) wk->wk_state |= INPROGRESS; ump->softdep_on_worklist_inprogress++; FREE_LOCK(&lk); - ffs_vget(mp, WK_DIRREM(wk)->dm_oldinum, - LK_NOWAIT | LK_EXCLUSIVE, &vp); + ffs_vgetf(mp, WK_DIRREM(wk)->dm_oldinum, + LK_NOWAIT | LK_EXCLUSIVE, &vp, FFSV_FORCEINSMQ); ACQUIRE_LOCK(&lk); wk->wk_state &= ~INPROGRESS; ump->softdep_on_worklist_inprogress--; @@ -1076,8 +1076,11 @@ softdep_flushfiles(oldmnt, flags, td) int flags; struct thread *td; { - int error, count, loopcnt; + int error, depcount, loopcnt, retry_flush_count, retry; + loopcnt = 10; + retry_flush_count = 3; +retry_flush: error = 0; /* @@ -1086,15 +1089,15 @@ softdep_flushfiles(oldmnt, flags, td) * creates. In theory, this loop can happen at most twice, * but we give it a few extra just to be sure. */ - for (loopcnt = 10; loopcnt > 0; loopcnt--) { + for (; loopcnt > 0; loopcnt--) { /* * Do another flush in case any vnodes were brought in * as part of the cleanup operations. */ if ((error = ffs_flushfiles(oldmnt, flags, td)) != 0) break; - if ((error = softdep_flushworklist(oldmnt, &count, td)) != 0 || - count == 0) + if ((error = softdep_flushworklist(oldmnt, &depcount, td)) != 0 || + depcount == 0) break; } /* @@ -1109,6 +1112,24 @@ softdep_flushfiles(oldmnt, flags, td) } if (!error) error = softdep_waitidle(oldmnt); + if (!error) { + if (oldmnt->mnt_kern_flag & MNTK_UNMOUNT) { + retry = 0; + MNT_ILOCK(oldmnt); + KASSERT((oldmnt->mnt_kern_flag & MNTK_NOINSMNTQ) != 0, + ("softdep_flushfiles: !MNTK_NOINSMNTQ")); + if (oldmnt->mnt_nvnodelistsize > 0) { + if (--retry_flush_count > 0) { + retry = 1; + loopcnt = 3; + } else + error = EBUSY; + } + MNT_IUNLOCK(oldmnt); + if (retry) + goto retry_flush; + } + } return (error); } @@ -2777,8 +2798,9 @@ handle_workitem_freeblocks(freeblks, fla */ if (freeblks->fb_chkcnt != blocksreleased && (fs->fs_flags & FS_UNCLEAN) != 0 && - ffs_vget(freeblks->fb_list.wk_mp, freeblks->fb_previousinum, - (flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp) == 0) { + ffs_vgetf(freeblks->fb_list.wk_mp, freeblks->fb_previousinum, + (flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp, FFSV_FORCEINSMQ) + == 0) { ip = VTOI(vp); DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + \ freeblks->fb_chkcnt - blocksreleased); @@ -3565,8 +3587,8 @@ handle_workitem_remove(dirrem, xp) int error; if ((vp = xp) == NULL && - (error = ffs_vget(dirrem->dm_list.wk_mp, - dirrem->dm_oldinum, LK_EXCLUSIVE, &vp)) != 0) { + (error = ffs_vgetf(dirrem->dm_list.wk_mp, + dirrem->dm_oldinum, LK_EXCLUSIVE, &vp, FFSV_FORCEINSMQ)) != 0) { softdep_error("handle_workitem_remove: vget", error); return; } @@ -5081,9 +5103,11 @@ softdep_fsync(vp) * for details on possible races. */ FREE_LOCK(&lk); - if (ffs_vget(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp)) { + if (ffs_vgetf(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp, + FFSV_FORCEINSMQ)) { VOP_UNLOCK(vp, 0, td); - error = ffs_vget(mp, parentino, LK_EXCLUSIVE, &pvp); + error = ffs_vgetf(mp, parentino, LK_EXCLUSIVE, + &pvp, FFSV_FORCEINSMQ); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (error != 0) return (error); @@ -5583,7 +5607,8 @@ flush_pagedep_deps(pvp, mp, diraddhdp) inum = dap->da_newinum; if (dap->da_state & MKDIR_BODY) { FREE_LOCK(&lk); - if ((error = ffs_vget(mp, inum, LK_EXCLUSIVE, &vp))) + if ((error = ffs_vgetf(mp, inum, LK_EXCLUSIVE, &vp, + FFSV_FORCEINSMQ))) break; if ((error=ffs_syncvnode(vp, MNT_NOWAIT)) || (error=ffs_syncvnode(vp, MNT_NOWAIT))) { @@ -5921,7 +5946,8 @@ clear_remove(td) if (vn_start_write(NULL, &mp, V_NOWAIT) != 0) continue; FREE_LOCK(&lk); - if ((error = ffs_vget(mp, ino, LK_EXCLUSIVE, &vp))) { + if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp, + FFSV_FORCEINSMQ))) { softdep_error("clear_remove: vget", error); vn_finished_write(mp); ACQUIRE_LOCK(&lk); @@ -5992,7 +6018,8 @@ clear_inodedeps(td) if (vn_start_write(NULL, &mp, V_NOWAIT) != 0) continue; FREE_LOCK(&lk); - if ((error = ffs_vget(mp, ino, LK_EXCLUSIVE, &vp)) != 0) { + if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp, + FFSV_FORCEINSMQ)) != 0) { softdep_error("clear_inodedeps: vget", error); vn_finished_write(mp); ACQUIRE_LOCK(&lk); Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 20:42:54 2009 (r188610) +++ stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 20:59:50 2009 (r188611) @@ -1295,6 +1295,17 @@ ffs_vget(mp, ino, flags, vpp) int flags; struct vnode **vpp; { + return (ffs_vgetf(mp, ino, flags, vpp, 0)); +} + +int +ffs_vgetf(mp, ino, flags, vpp, ffs_flags) + struct mount *mp; + ino_t ino; + int flags; + struct vnode **vpp; + int ffs_flags; +{ struct fs *fs; struct inode *ip; struct ufsmount *ump; @@ -1369,13 +1380,16 @@ ffs_vget(mp, ino, flags, vpp) td = curthread; lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL, td); + if (ffs_flags & FFSV_FORCEINSMQ) + vp->v_vflag |= VV_FORCEINSMQ; error = insmntque(vp, mp); if (error != 0) { uma_zfree(uma_inode, ip); *vpp = NULL; return (error); } - error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL); + vp->v_vflag &= ~VV_FORCEINSMQ; + error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL); if (error || *vpp != NULL) return (error); From kib at FreeBSD.org Sat Feb 14 13:08:43 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 13:08:59 2009 Subject: svn commit: r188612 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb ufs/ffs Message-ID: <200902142108.n1EL8gQT030349@svn.freebsd.org> Author: kib Date: Sat Feb 14 21:08:40 2009 New Revision: 188612 URL: http://svn.freebsd.org/changeset/base/188612 Log: MFC r182366: In ffs_valloc(), ffs_vget() may fail because insmntque() refused to insert new vnode into the mount vnode list. Then, for the SU-enabled mount, ffs_vfree could create freefile dependency. This dependency can hang around forever since inode is not marked as IN_MODIFIED and correspondingly inodeblock may be not marked as dirty. After ffs_vget() fails, retry with FFSV_FORCEINSMQ, mark the inode as modified, and vput() it immediately. Take care of the dup alloc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/ufs/ffs/ffs_alloc.c Modified: stable/7/sys/ufs/ffs/ffs_alloc.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_alloc.c Sat Feb 14 20:59:50 2009 (r188611) +++ stable/7/sys/ufs/ffs/ffs_alloc.c Sat Feb 14 21:08:40 2009 (r188612) @@ -930,7 +930,7 @@ ffs_valloc(pvp, mode, cred, vpp) struct timespec ts; struct ufsmount *ump; ino_t ino, ipref; - int cg, error; + int cg, error, error1; static struct timeval lastfail; static int curfail; @@ -967,11 +967,21 @@ ffs_valloc(pvp, mode, cred, vpp) goto noinodes; error = ffs_vget(pvp->v_mount, ino, LK_EXCLUSIVE, vpp); if (error) { + error1 = ffs_vgetf(pvp->v_mount, ino, LK_EXCLUSIVE, vpp, + FFSV_FORCEINSMQ); ffs_vfree(pvp, ino, mode); + if (error1 == 0) { + ip = VTOI(*vpp); + if (ip->i_mode) + goto dup_alloc; + ip->i_flag |= IN_MODIFIED; + vput(*vpp); + } return (error); } ip = VTOI(*vpp); if (ip->i_mode) { +dup_alloc: printf("mode = 0%o, inum = %lu, fs = %s\n", ip->i_mode, (u_long)ip->i_number, fs->fs_fsmnt); panic("ffs_valloc: dup alloc"); From kib at FreeBSD.org Sat Feb 14 13:13:00 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 13:13:07 2009 Subject: svn commit: r188614 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb ufs/ffs ufs/ufs Message-ID: <200902142112.n1ELCx2H030518@svn.freebsd.org> Author: kib Date: Sat Feb 14 21:12:58 2009 New Revision: 188614 URL: http://svn.freebsd.org/changeset/base/188614 Log: MFC r183070: When downgrading the read-write mount to read-only, do_unmount() sets MNT_RDONLY flag before the VFS_MOUNT() is called. In ufs_inactive() and ufs_itimes_locked(), UFS verifies whether the fs is read-only by checking MNT_RDONLY, but this may cause loss of the IN_MODIFIED flag for inode on the fs being remounted rw->ro. Introduce UFS_RDONLY() struct ufsmount' method that reports the value of the fs_ronly. The later is set to 1 only after the remount is finished. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/ufs/ffs/ffs_extern.h stable/7/sys/ufs/ffs/ffs_inode.c stable/7/sys/ufs/ffs/ffs_vfsops.c stable/7/sys/ufs/ufs/ufs_inode.c stable/7/sys/ufs/ufs/ufs_vnops.c stable/7/sys/ufs/ufs/ufsmount.h Modified: stable/7/sys/ufs/ffs/ffs_extern.h ============================================================================== --- stable/7/sys/ufs/ffs/ffs_extern.h Sat Feb 14 21:12:24 2009 (r188613) +++ stable/7/sys/ufs/ffs/ffs_extern.h Sat Feb 14 21:12:58 2009 (r188614) @@ -131,4 +131,6 @@ int softdep_process_worklist(struct int softdep_fsync(struct vnode *); int softdep_waitidle(struct mount *); +int ffs_rdonly(struct inode *); + #endif /* !_UFS_FFS_EXTERN_H */ Modified: stable/7/sys/ufs/ffs/ffs_inode.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_inode.c Sat Feb 14 21:12:24 2009 (r188613) +++ stable/7/sys/ufs/ffs/ffs_inode.c Sat Feb 14 21:12:58 2009 (r188614) @@ -665,3 +665,11 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, lev *countp = blocksreleased; return (allerror); } + +int +ffs_rdonly(struct inode *ip) +{ + + return (ip->i_ump->um_fs->fs_ronly != 0); +} + Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 21:12:24 2009 (r188613) +++ stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 21:12:58 2009 (r188614) @@ -734,6 +734,7 @@ ffs_mountfs(devvp, mp, td) ump->um_valloc = ffs_valloc; ump->um_vfree = ffs_vfree; ump->um_ifree = ffs_ifree; + ump->um_rdonly = ffs_rdonly; mtx_init(UFS_MTX(ump), "FFS", "FFS Lock", MTX_DEF); bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize); if (fs->fs_sbsize < SBLOCKSIZE) Modified: stable/7/sys/ufs/ufs/ufs_inode.c ============================================================================== --- stable/7/sys/ufs/ufs/ufs_inode.c Sat Feb 14 21:12:24 2009 (r188613) +++ stable/7/sys/ufs/ufs/ufs_inode.c Sat Feb 14 21:12:58 2009 (r188614) @@ -90,8 +90,7 @@ ufs_inactive(ap) ufs_gjournal_close(vp); #endif if ((ip->i_effnlink == 0 && DOINGSOFTDEP(vp)) || - (ip->i_nlink <= 0 && - (vp->v_mount->mnt_flag & MNT_RDONLY) == 0)) { + (ip->i_nlink <= 0 && !UFS_RDONLY(ip))) { loop: if (vn_start_secondary_write(vp, &mp, V_NOWAIT) != 0) { /* Cannot delete file while file system is suspended */ @@ -121,7 +120,7 @@ ufs_inactive(ap) } if (ip->i_effnlink == 0 && DOINGSOFTDEP(vp)) softdep_releasefile(ip); - if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { + if (ip->i_nlink <= 0 && !UFS_RDONLY(ip)) { #ifdef QUOTA if (!getinoquota(ip)) (void)chkiq(ip, -1, NOCRED, FORCE); Modified: stable/7/sys/ufs/ufs/ufs_vnops.c ============================================================================== --- stable/7/sys/ufs/ufs/ufs_vnops.c Sat Feb 14 21:12:24 2009 (r188613) +++ stable/7/sys/ufs/ufs/ufs_vnops.c Sat Feb 14 21:12:58 2009 (r188614) @@ -135,7 +135,7 @@ ufs_itimes_locked(struct vnode *vp) ASSERT_VI_LOCKED(vp, __func__); ip = VTOI(vp); - if ((vp->v_mount->mnt_flag & MNT_RDONLY) != 0) + if (UFS_RDONLY(ip)) goto out; if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0) return; Modified: stable/7/sys/ufs/ufs/ufsmount.h ============================================================================== --- stable/7/sys/ufs/ufs/ufsmount.h Sat Feb 14 21:12:24 2009 (r188613) +++ stable/7/sys/ufs/ufs/ufsmount.h Sat Feb 14 21:12:58 2009 (r188614) @@ -93,6 +93,7 @@ struct ufsmount { int (*um_valloc)(struct vnode *, int, struct ucred *, struct vnode **); int (*um_vfree)(struct vnode *, ino_t, int); void (*um_ifree)(struct ufsmount *, struct inode *); + int (*um_rdonly)(struct inode *); }; #define UFS_BALLOC(aa, bb, cc, dd, ee, ff) VFSTOUFS((aa)->v_mount)->um_balloc(aa, bb, cc, dd, ee, ff) @@ -102,6 +103,7 @@ struct ufsmount { #define UFS_VALLOC(aa, bb, cc, dd) VFSTOUFS((aa)->v_mount)->um_valloc(aa, bb, cc, dd) #define UFS_VFREE(aa, bb, cc) VFSTOUFS((aa)->v_mount)->um_vfree(aa, bb, cc) #define UFS_IFREE(aa, bb) ((aa)->um_ifree(aa, bb)) +#define UFS_RDONLY(aa) ((aa)->i_ump->um_rdonly(aa)) #define UFS_LOCK(aa) mtx_lock(&(aa)->um_lock) #define UFS_UNLOCK(aa) mtx_unlock(&(aa)->um_lock) From kib at FreeBSD.org Sat Feb 14 14:24:05 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 14:24:16 2009 Subject: svn commit: r188618 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern ufs/ffs Message-ID: <200902142224.n1EMO4j9031957@svn.freebsd.org> Author: kib Date: Sat Feb 14 22:24:04 2009 New Revision: 188618 URL: http://svn.freebsd.org/changeset/base/188618 Log: MFC r183072: Add the ffs structures introspection functions for ddb. Show the b_dep value for the buffer in the show buffer command. Add a comand to dump the dirty/clean buffer list for vnode. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/vfs_bio.c stable/7/sys/ufs/ffs/ffs_softdep.c stable/7/sys/ufs/ffs/ffs_vfsops.c Modified: stable/7/sys/kern/vfs_bio.c ============================================================================== --- stable/7/sys/kern/vfs_bio.c Sat Feb 14 22:07:22 2009 (r188617) +++ stable/7/sys/kern/vfs_bio.c Sat Feb 14 22:24:04 2009 (r188618) @@ -3920,9 +3920,10 @@ DB_SHOW_COMMAND(buffer, db_show_buffer) db_printf("b_flags = 0x%b\n", (u_int)bp->b_flags, PRINT_BUF_FLAGS); db_printf( "b_error = %d, b_bufsize = %ld, b_bcount = %ld, b_resid = %ld\n" - "b_bufobj = (%p), b_data = %p, b_blkno = %jd\n", + "b_bufobj = (%p), b_data = %p, b_blkno = %jd, b_dep = %p\n", bp->b_error, bp->b_bufsize, bp->b_bcount, bp->b_resid, - bp->b_bufobj, bp->b_data, (intmax_t)bp->b_blkno); + bp->b_bufobj, bp->b_data, (intmax_t)bp->b_blkno, + bp->b_dep.lh_first); if (bp->b_npages) { int i; db_printf("b_npages = %d, pages(OBJ, IDX, PA): ", bp->b_npages); @@ -3952,4 +3953,26 @@ DB_SHOW_COMMAND(lockedbufs, lockedbufs) } } } + +DB_SHOW_COMMAND(vnodebufs, db_show_vnodebufs) +{ + struct vnode *vp; + struct buf *bp; + + if (!have_addr) { + db_printf("usage: show vnodebufs \n"); + return; + } + vp = (struct vnode *)addr; + db_printf("Clean buffers:\n"); + TAILQ_FOREACH(bp, &vp->v_bufobj.bo_clean.bv_hd, b_bobufs) { + db_show_buffer((uintptr_t)bp, 1, 0, NULL); + db_printf("\n"); + } + db_printf("Dirty buffers:\n"); + TAILQ_FOREACH(bp, &vp->v_bufobj.bo_dirty.bv_hd, b_bobufs) { + db_show_buffer((uintptr_t)bp, 1, 0, NULL); + db_printf("\n"); + } +} #endif /* DDB */ Modified: stable/7/sys/ufs/ffs/ffs_softdep.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_softdep.c Sat Feb 14 22:07:22 2009 (r188617) +++ stable/7/sys/ufs/ffs/ffs_softdep.c Sat Feb 14 22:24:04 2009 (r188618) @@ -41,6 +41,9 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_ffs.h" +#include "opt_ddb.h" + /* * For now we want the safety net that DEBUG flags provide. */ @@ -77,7 +80,7 @@ __FBSDID("$FreeBSD$"); #include -#include "opt_ffs.h" +#include #include "opt_quota.h" #ifndef SOFTUPDATES @@ -6336,4 +6339,30 @@ softdep_error(func, error) printf("%s: got error %d while accessing filesystem\n", func, error); } +#ifdef DDB + +DB_SHOW_COMMAND(inodedeps, db_show_inodedeps) +{ + struct inodedep_hashhead *inodedephd; + struct inodedep *inodedep; + struct fs *fs; + int cnt; + + fs = have_addr ? (struct fs *)addr : NULL; + for (cnt = 0; cnt < inodedep_hash; cnt++) { + inodedephd = &inodedep_hashtbl[cnt]; + LIST_FOREACH(inodedep, inodedephd, id_hash) { + if (fs != NULL && fs != inodedep->id_fs) + continue; + db_printf("%p fs %p st %x ino %jd inoblk %jd\n", + inodedep, inodedep->id_fs, inodedep->id_state, + (intmax_t)inodedep->id_ino, + (intmax_t)fsbtodb(inodedep->id_fs, + ino_to_fsba(inodedep->id_fs, inodedep->id_ino))); + } + } +} + +#endif /* DDB */ + #endif /* SOFTUPDATES */ Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 22:07:22 2009 (r188617) +++ stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 22:24:04 2009 (r188618) @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include "opt_quota.h" #include "opt_ufs.h" #include "opt_ffs.h" +#include "opt_ddb.h" #include #include @@ -71,6 +72,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + static uma_zone_t uma_inode, uma_ufs1, uma_ufs2; static int ffs_reload(struct mount *, struct thread *); @@ -1864,3 +1867,35 @@ ffs_geom_strategy(struct bufobj *bo, str } g_vfs_strategy(bo, bp); } + +#ifdef DDB + +static void +db_print_ffs(struct ufsmount *ump) +{ + db_printf("mp %p %s devvp %p fs %p su_wl %d su_wl_in %d su_deps %d " + "su_req %d\n", + ump->um_mountp, ump->um_mountp->mnt_stat.f_mntonname, + ump->um_devvp, ump->um_fs, ump->softdep_on_worklist, + ump->softdep_on_worklist_inprogress, ump->softdep_deps, + ump->softdep_req); +} + +DB_SHOW_COMMAND(ffs, db_show_ffs) +{ + struct mount *mp; + struct ufsmount *ump; + + if (have_addr) { + ump = VFSTOUFS((struct mount *)addr); + db_print_ffs(ump); + return; + } + + TAILQ_FOREACH(mp, &mountlist, mnt_list) { + if (!strcmp(mp->mnt_stat.f_fstypename, ufs_vfsconf.vfc_name)) + db_print_ffs(VFSTOUFS(mp)); + } +} + +#endif /* DDB */ From kib at FreeBSD.org Sat Feb 14 15:02:22 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 15:02:29 2009 Subject: svn commit: r188620 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern sys ufs/ffs Message-ID: <200902142302.n1EN2LPM032787@svn.freebsd.org> Author: kib Date: Sat Feb 14 23:02:21 2009 New Revision: 188620 URL: http://svn.freebsd.org/changeset/base/188620 Log: MFC r183073: When attempt is made to suspend a filesystem that is already syspended, wait until the current suspension is lifted instead of silently returning success immediately. The consequences of calling vfs_write() resume when not owning the suspension are not well-defined at best. Add the vfs_susp_clean() mount method to be called from vfs_write_resume(). Set it to process_deferred_inactive() for ffs, and stop calling it manually. Add the thread flag TDP_IGNSUSP that allows to bypass the suspension point in the vn_start_write. It is intended for use by VFS in the situations where the suspender want to do some i/o requiring calls to vn_start_write(), and this i/o cannot be done later. Note that addition of the mount method and new struct mount field change the KBI. This was approved by re and no objections on stable@ were raised. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/vfs_vnops.c stable/7/sys/sys/mount.h stable/7/sys/sys/proc.h stable/7/sys/ufs/ffs/ffs_extern.h stable/7/sys/ufs/ffs/ffs_snapshot.c stable/7/sys/ufs/ffs/ffs_vfsops.c Modified: stable/7/sys/kern/vfs_vnops.c ============================================================================== --- stable/7/sys/kern/vfs_vnops.c Sat Feb 14 22:29:54 2009 (r188619) +++ stable/7/sys/kern/vfs_vnops.c Sat Feb 14 23:02:21 2009 (r188620) @@ -916,15 +916,18 @@ vn_start_write(vp, mpp, flags) /* * Check on status of suspension. */ - while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) { - if (flags & V_NOWAIT) { - error = EWOULDBLOCK; - goto unlock; + if ((curthread->td_pflags & TDP_IGNSUSP) == 0 || + mp->mnt_susp_owner != curthread) { + while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) { + if (flags & V_NOWAIT) { + error = EWOULDBLOCK; + goto unlock; + } + error = msleep(&mp->mnt_flag, MNT_MTX(mp), + (PUSER - 1) | (flags & PCATCH), "suspfs", 0); + if (error) + goto unlock; } - error = msleep(&mp->mnt_flag, MNT_MTX(mp), - (PUSER - 1) | (flags & PCATCH), "suspfs", 0); - if (error) - goto unlock; } if (flags & V_XSLEEP) goto unlock; @@ -1048,11 +1051,14 @@ vfs_write_suspend(mp) int error; MNT_ILOCK(mp); - if (mp->mnt_kern_flag & MNTK_SUSPEND) { + if (mp->mnt_susp_owner == curthread) { MNT_IUNLOCK(mp); - return (0); + return (EALREADY); } + while (mp->mnt_kern_flag & MNTK_SUSPEND) + msleep(&mp->mnt_flag, MNT_MTX(mp), PUSER - 1, "wsuspfs", 0); mp->mnt_kern_flag |= MNTK_SUSPEND; + mp->mnt_susp_owner = curthread; if (mp->mnt_writeopcount > 0) (void) msleep(&mp->mnt_writeopcount, MNT_MTX(mp), (PUSER - 1)|PDROP, "suspwt", 0); @@ -1073,12 +1079,17 @@ vfs_write_resume(mp) MNT_ILOCK(mp); if ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) { + KASSERT(mp->mnt_susp_owner == curthread, ("mnt_susp_owner")); mp->mnt_kern_flag &= ~(MNTK_SUSPEND | MNTK_SUSPEND2 | MNTK_SUSPENDED); + mp->mnt_susp_owner = NULL; wakeup(&mp->mnt_writeopcount); wakeup(&mp->mnt_flag); - } - MNT_IUNLOCK(mp); + curthread->td_pflags &= ~TDP_IGNSUSP; + MNT_IUNLOCK(mp); + VFS_SUSP_CLEAN(mp); + } else + MNT_IUNLOCK(mp); } /* Modified: stable/7/sys/sys/mount.h ============================================================================== --- stable/7/sys/sys/mount.h Sat Feb 14 22:29:54 2009 (r188619) +++ stable/7/sys/sys/mount.h Sat Feb 14 23:02:21 2009 (r188620) @@ -175,6 +175,7 @@ struct mount { int mnt_holdcntwaiters; /* waits on hold count */ int mnt_secondary_writes; /* (i) # of secondary writes */ int mnt_secondary_accwrites;/* (i) secondary wr. starts */ + struct thread *mnt_susp_owner; /* (i) thread owning suspension */ #define mnt_endzero mnt_gjprovider char *mnt_gjprovider; /* gjournal provider name */ struct lock mnt_explock; /* vfs_export walkers lock */ @@ -539,6 +540,7 @@ typedef int vfs_extattrctl_t(struct moun typedef int vfs_mount_t(struct mount *mp, struct thread *td); typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op, struct sysctl_req *req); +typedef void vfs_susp_clean_t(struct mount *mp); struct vfsops { vfs_mount_t *vfs_mount; @@ -555,6 +557,7 @@ struct vfsops { vfs_uninit_t *vfs_uninit; vfs_extattrctl_t *vfs_extattrctl; vfs_sysctl_t *vfs_sysctl; + vfs_susp_clean_t *vfs_susp_clean; }; vfs_statfs_t __vfs_statfs; @@ -576,6 +579,9 @@ vfs_statfs_t __vfs_statfs; (*(MP)->mnt_op->vfs_extattrctl)(MP, C, FN, NS, N, P) #define VFS_SYSCTL(MP, OP, REQ) \ (*(MP)->mnt_op->vfs_sysctl)(MP, OP, REQ) +#define VFS_SUSP_CLEAN(MP) \ + ({if (*(MP)->mnt_op->vfs_susp_clean != NULL) \ + (*(MP)->mnt_op->vfs_susp_clean)(MP); }) extern int mpsafe_vfs; Modified: stable/7/sys/sys/proc.h ============================================================================== --- stable/7/sys/sys/proc.h Sat Feb 14 22:29:54 2009 (r188619) +++ stable/7/sys/sys/proc.h Sat Feb 14 23:02:21 2009 (r188620) @@ -378,6 +378,7 @@ do { \ #define TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */ #define TDP_WAKEUP 0x00080000 /* Don't sleep in umtx cond_wait */ #define TDP_INBDFLUSH 0x00100000 /* Already in BO_BDFLUSH, do not recurse */ +#define TDP_IGNSUSP 0x00800000 /* Permission to ignore the MNTK_SUSPEND* */ /* * Reasons that the current thread can not be run yet. Modified: stable/7/sys/ufs/ffs/ffs_extern.h ============================================================================== --- stable/7/sys/ufs/ffs/ffs_extern.h Sat Feb 14 22:29:54 2009 (r188619) +++ stable/7/sys/ufs/ffs/ffs_extern.h Sat Feb 14 23:02:21 2009 (r188620) @@ -80,6 +80,7 @@ void ffs_snapremove(struct vnode *vp); int ffs_snapshot(struct mount *mp, char *snapfile); void ffs_snapshot_mount(struct mount *mp); void ffs_snapshot_unmount(struct mount *mp); +void process_deferred_inactive(struct mount *mp); int ffs_syncvnode(struct vnode *vp, int waitfor); int ffs_truncate(struct vnode *, off_t, int, struct ucred *, struct thread *); int ffs_update(struct vnode *, int); Modified: stable/7/sys/ufs/ffs/ffs_snapshot.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_snapshot.c Sat Feb 14 22:29:54 2009 (r188619) +++ stable/7/sys/ufs/ffs/ffs_snapshot.c Sat Feb 14 23:02:21 2009 (r188620) @@ -161,7 +161,6 @@ static int snapacct_ufs2(struct vnode *, static int mapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *, ufs_lbn_t, int); static int readblock(struct vnode *vp, struct buf *, ufs2_daddr_t); -static void process_deferred_inactive(struct mount *); static void try_free_snapdata(struct vnode *devvp, struct thread *td); static int ffs_bp_snapblk(struct vnode *, struct buf *); @@ -2429,12 +2428,14 @@ readblock(vp, bp, lbn) return (bp->b_error); } +#endif + /* * Process file deletes that were deferred by ufs_inactive() due to * the file system being suspended. Transfer IN_LAZYACCESS into * IN_MODIFIED for vnodes that were accessed during suspension. */ -static void +void process_deferred_inactive(struct mount *mp) { struct vnode *vp, *mvp; @@ -2507,6 +2508,8 @@ process_deferred_inactive(struct mount * vn_finished_secondary_write(mp); } +#ifndef NO_FFS_SNAPSHOT + /* Try to free snapdata associated with devvp */ static void try_free_snapdata(struct vnode *devvp, Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 22:29:54 2009 (r188619) +++ stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 23:02:21 2009 (r188620) @@ -105,6 +105,7 @@ static struct vfsops ufs_vfsops = { .vfs_uninit = ffs_uninit, .vfs_unmount = ffs_unmount, .vfs_vget = ffs_vget, + .vfs_susp_clean = process_deferred_inactive, }; VFS_SET(ufs_vfsops, ufs, 0); From kib at FreeBSD.org Sat Feb 14 15:22:40 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 15:22:57 2009 Subject: svn commit: r188623 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb ufs/ffs Message-ID: <200902142322.n1ENMcpo033268@svn.freebsd.org> Author: kib Date: Sat Feb 14 23:22:37 2009 New Revision: 188623 URL: http://svn.freebsd.org/changeset/base/188623 Log: MFC r183074: Suspend the write operations on the UFS filesystem being unmounted or remounted from rw to ro. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/ufs/ffs/ffs_vfsops.c Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 23:20:00 2009 (r188622) +++ stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 23:22:37 2009 (r188623) @@ -189,14 +189,35 @@ ffs_mount(struct mount *mp, struct threa devvp = ump->um_devvp; if (fs->fs_ronly == 0 && vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { - if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0) - return (error); /* - * Flush any dirty data. + * Flush any dirty data and suspend filesystem. */ - if ((error = ffs_sync(mp, MNT_WAIT, td)) != 0) { - vn_finished_write(mp); + if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0) return (error); + for (;;) { + vn_finished_write(mp); + if ((error = vfs_write_suspend(mp)) != 0) + return (error); + MNT_ILOCK(mp); + if (mp->mnt_kern_flag & MNTK_SUSPENDED) { + /* + * Allow the secondary writes + * to proceed. + */ + mp->mnt_kern_flag &= ~(MNTK_SUSPENDED | + MNTK_SUSPEND2); + wakeup(&mp->mnt_flag); + MNT_IUNLOCK(mp); + /* + * Allow the curthread to + * ignore the suspension to + * synchronize on-disk state. + */ + curthread->td_pflags |= TDP_IGNSUSP; + break; + } + MNT_IUNLOCK(mp); + vn_start_write(NULL, &mp, V_WAIT); } /* * Check for and optionally get rid of files open @@ -211,7 +232,7 @@ ffs_mount(struct mount *mp, struct threa error = ffs_flushfiles(mp, flags, td); } if (error) { - vn_finished_write(mp); + vfs_write_resume(mp); return (error); } if (fs->fs_pendingblocks != 0 || @@ -228,10 +249,9 @@ ffs_mount(struct mount *mp, struct threa if ((error = ffs_sbupdate(ump, MNT_WAIT, 0)) != 0) { fs->fs_ronly = 0; fs->fs_clean = 0; - vn_finished_write(mp); + vfs_write_resume(mp); return (error); } - vn_finished_write(mp); DROP_GIANT(); g_topology_lock(); g_access(ump->um_cp, 0, -1, 0); @@ -241,6 +261,11 @@ ffs_mount(struct mount *mp, struct threa MNT_ILOCK(mp); mp->mnt_flag |= MNT_RDONLY; MNT_IUNLOCK(mp); + /* + * Allow the writers to note that filesystem + * is ro now. + */ + vfs_write_resume(mp); } if ((mp->mnt_flag & MNT_RELOAD) && (error = ffs_reload(mp, td)) != 0) @@ -1004,12 +1029,15 @@ ffs_unmount(mp, mntflags, td) { struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; - int error, flags; + int error, flags, susp; flags = 0; + fs = ump->um_fs; if (mntflags & MNT_FORCE) { flags |= FORCECLOSE; - } + susp = fs->fs_ronly != 0; + } else + susp = 0; #ifdef UFS_EXTATTR if ((error = ufs_extattr_stop(mp, td))) { if (error != EOPNOTSUPP) @@ -1019,14 +1047,34 @@ ffs_unmount(mp, mntflags, td) ufs_extattr_uepm_destroy(&ump->um_extattr); } #endif + if (susp) { + /* + * dounmount already called vn_start_write(). + */ + for (;;) { + vn_finished_write(mp); + if ((error = vfs_write_suspend(mp)) != 0) + return (error); + MNT_ILOCK(mp); + if (mp->mnt_kern_flag & MNTK_SUSPENDED) { + mp->mnt_kern_flag &= ~(MNTK_SUSPENDED | + MNTK_SUSPEND2); + wakeup(&mp->mnt_flag); + MNT_IUNLOCK(mp); + curthread->td_pflags |= TDP_IGNSUSP; + break; + } + MNT_IUNLOCK(mp); + vn_start_write(NULL, &mp, V_WAIT); + } + } if (mp->mnt_flag & MNT_SOFTDEP) { if ((error = softdep_flushfiles(mp, flags, td)) != 0) - return (error); + goto fail; } else { if ((error = ffs_flushfiles(mp, flags, td)) != 0) - return (error); + goto fail; } - fs = ump->um_fs; UFS_LOCK(ump); if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { printf("%s: unmount pending error: blocks %jd files %d\n", @@ -1041,9 +1089,13 @@ ffs_unmount(mp, mntflags, td) error = ffs_sbupdate(ump, MNT_WAIT, 0); if (error) { fs->fs_clean = 0; - return (error); + goto fail; } } + if (susp) { + vfs_write_resume(mp); + vn_start_write(NULL, &mp, V_WAIT); + } DROP_GIANT(); g_topology_lock(); g_vfs_close(ump->um_cp, td); @@ -1063,6 +1115,13 @@ ffs_unmount(mp, mntflags, td) mp->mnt_flag &= ~MNT_LOCAL; MNT_IUNLOCK(mp); return (error); + +fail: + if (susp) { + vfs_write_resume(mp); + vn_start_write(NULL, &mp, V_WAIT); + } + return (error); } /* From kib at FreeBSD.org Sat Feb 14 15:45:25 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 15:45:42 2009 Subject: svn commit: r188624 - in stable/7/sys: . contrib/pf dev/cxgb ufs/ffs Message-ID: <200902142345.n1ENjO96033694@svn.freebsd.org> Author: kib Date: Sat Feb 14 23:45:24 2009 New Revision: 188624 URL: http://svn.freebsd.org/changeset/base/188624 Log: MFC r186897: If unmount of the ffs mp failed, reinitialize the extended attributes for the mp, and restart them if autostart is enabled. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/ufs/ffs/ffs_vfsops.c Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 23:22:37 2009 (r188623) +++ stable/7/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 23:45:24 2009 (r188624) @@ -1030,6 +1030,9 @@ ffs_unmount(mp, mntflags, td) struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; int error, flags, susp; +#ifdef UFS_EXTATTR + int e_restart; +#endif flags = 0; fs = ump->um_fs; @@ -1043,8 +1046,10 @@ ffs_unmount(mp, mntflags, td) if (error != EOPNOTSUPP) printf("ffs_unmount: ufs_extattr_stop returned %d\n", error); + e_restart = 0; } else { ufs_extattr_uepm_destroy(&ump->um_extattr); + e_restart = 1; } #endif if (susp) { @@ -1121,6 +1126,15 @@ fail: vfs_write_resume(mp); vn_start_write(NULL, &mp, V_WAIT); } +#ifdef UFS_EXTATTR + if (e_restart) { + ufs_extattr_uepm_init(&ump->um_extattr); +#ifdef UFS_EXTATTR_AUTOSTART + (void) ufs_extattr_autostart(mp, td); +#endif + } +#endif + return (error); } From kib at FreeBSD.org Sat Feb 14 15:48:27 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sat Feb 14 15:48:33 2009 Subject: svn commit: r188625 - stable/7/sys/sys Message-ID: <200902142348.n1ENmQ89033778@svn.freebsd.org> Author: kib Date: Sat Feb 14 23:48:26 2009 New Revision: 188625 URL: http://svn.freebsd.org/changeset/base/188625 Log: Bump __FreeBSD_version after the r188620, that changed struct mount and struct vfsops. Modified: stable/7/sys/sys/param.h Modified: stable/7/sys/sys/param.h ============================================================================== --- stable/7/sys/sys/param.h Sat Feb 14 23:45:24 2009 (r188624) +++ stable/7/sys/sys/param.h Sat Feb 14 23:48:26 2009 (r188625) @@ -57,7 +57,7 @@ * is created, otherwise 1. */ #undef __FreeBSD_version -#define __FreeBSD_version 701103 /* Master, propagated to newvers */ +#define __FreeBSD_version 701104 /* Master, propagated to newvers */ #ifndef LOCORE #include From luigi at FreeBSD.org Mon Feb 16 08:36:33 2009 From: luigi at FreeBSD.org (Luigi Rizzo) Date: Mon Feb 16 08:36:44 2009 Subject: svn commit: r188679 - stable/7/sys/netinet Message-ID: <200902161636.n1GGaWDO067186@svn.freebsd.org> Author: luigi Date: Mon Feb 16 16:36:31 2009 New Revision: 188679 URL: http://svn.freebsd.org/changeset/base/188679 Log: make the dependency on lock.h and mutex.h explicit instead of inheriting them from net/if.h Modified: stable/7/sys/netinet/ip_dummynet.c Modified: stable/7/sys/netinet/ip_dummynet.c ============================================================================== --- stable/7/sys/netinet/ip_dummynet.c Mon Feb 16 15:32:12 2009 (r188678) +++ stable/7/sys/netinet/ip_dummynet.c Mon Feb 16 16:36:31 2009 (r188679) @@ -62,7 +62,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include @@ -70,7 +72,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include /* IFNAMSIZ, struct ifaddr, ifq head, lock.h mutex.h */ +#include /* IFNAMSIZ, struct ifaddr, ifq head */ #include #include #include /* ip_len, ip_off */ From luigi at FreeBSD.org Mon Feb 16 08:48:52 2009 From: luigi at FreeBSD.org (Luigi Rizzo) Date: Mon Feb 16 08:49:04 2009 Subject: svn commit: r188680 - stable/7/sys/netinet Message-ID: <200902161648.n1GGmnYQ068531@svn.freebsd.org> Author: luigi Date: Mon Feb 16 16:48:49 2009 New Revision: 188680 URL: http://svn.freebsd.org/changeset/base/188680 Log: various cleanup (mostly MFC, one not applicable to head): - remove 3 unneeded headers (this is not applicable to head); - replace netinet/if_ether.h with net/ethernet.h which is really needed; - add missing #ifdef SYSCTL_NODE / #endif - use the 'ch' argument instead of &layer3_chain when adding entries to a table; - remove an assigment within a conditional; - properly initialize a couple of variables - use a constant format string in a log message - remove unnecessary braces and simplify the error messages in IP_FW_NAT_* handler Modified: stable/7/sys/netinet/ip_fw2.c Modified: stable/7/sys/netinet/ip_fw2.c ============================================================================== --- stable/7/sys/netinet/ip_fw2.c Mon Feb 16 16:36:31 2009 (r188679) +++ stable/7/sys/netinet/ip_fw2.c Mon Feb 16 16:48:49 2009 (r188680) @@ -48,8 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include #include #include @@ -58,12 +56,12 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include #include #include +#include /* for ETHERTYPE_IP */ #include #include #include @@ -94,8 +92,6 @@ __FBSDID("$FreeBSD$"); #include #endif -#include /* XXX for ETHERTYPE_IP */ - #include /* XXX for in_cksum */ #ifdef MAC @@ -111,11 +107,10 @@ __FBSDID("$FreeBSD$"); * Rules in set RESVD_SET can only be deleted explicitly. */ static u_int32_t set_disable; - static int fw_verbose; +static struct callout ipfw_timeout; static int verbose_limit; -static struct callout ipfw_timeout; static uma_zone_t ipfw_dyn_rule_zone; /* @@ -176,6 +171,9 @@ SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, ve &verbose_limit, 0, "Set upper limit of matches of ipfw rules logged"); SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD, NULL, IPFW_DEFAULT_RULE, "The default/max possible rule number."); +SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD, + NULL, IPFW_TABLES_MAX, "The maximum number of tables."); +#endif /* SYSCTL_NODE */ /* * Description of dynamic rules. @@ -252,6 +250,7 @@ static u_int32_t static_len; /* size in static u_int32_t dyn_count; /* # of dynamic rules */ static u_int32_t dyn_max = 4096; /* max # of dynamic rules */ +#ifdef SYSCTL_NODE SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_buckets, CTLFLAG_RW, &dyn_buckets, 0, "Number of dyn. buckets"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, curr_dyn_buckets, CTLFLAG_RD, @@ -276,17 +275,19 @@ SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dy &dyn_short_lifetime, 0, "Lifetime of dyn. rules for other situations"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_keepalive, CTLFLAG_RW, &dyn_keepalive, 0, "Enable keepalives for dyn. rules"); +#endif /* SYSCTL_NODE */ #ifdef INET6 /* * IPv6 specific variables */ +#ifdef SYSCTL_NODE SYSCTL_DECL(_net_inet6_ip6); +#endif /* SYSCTL_NODE */ static struct sysctl_ctx_list ip6_fw_sysctl_ctx; static struct sysctl_oid *ip6_fw_sysctl_tree; #endif /* INET6 */ -#endif /* SYSCTL_NODE */ static int fw_deny_unknown_exthdrs = 1; @@ -1773,6 +1774,7 @@ add_table_entry(struct ip_fw_chain *ch, { struct radix_node_head *rnh; struct table_entry *ent; + struct radix_node *rn; if (tbl >= IPFW_TABLES_MAX) return (EINVAL); @@ -1784,14 +1786,14 @@ add_table_entry(struct ip_fw_chain *ch, ent->addr.sin_len = ent->mask.sin_len = 8; ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0); ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr; - IPFW_WLOCK(&layer3_chain); - if (rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent) == - NULL) { - IPFW_WUNLOCK(&layer3_chain); + IPFW_WLOCK(ch); + rn = rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent); + if (rn == NULL) { + IPFW_WUNLOCK(ch); free(ent, M_IPFW_TBL); return (EEXIST); } - IPFW_WUNLOCK(&layer3_chain); + IPFW_WUNLOCK(ch); return (0); } @@ -2205,6 +2207,7 @@ ipfw_chk(struct ip_fw_args *args) if (m->m_flags & M_SKIP_FIREWALL) return (IP_FW_PASS); /* accept */ + dst_ip.s_addr = 0; /* make sure it is initialized */ pktlen = m->m_pkthdr.len; args->f_id.fib = M_GETFIB(m); /* note mbuf not altered) */ proto = args->f_id.proto = 0; /* mark f_id invalid */ @@ -2662,7 +2665,7 @@ check_body: uint32_t a = (cmd->opcode == O_IP_DST_LOOKUP) ? dst_ip.s_addr : src_ip.s_addr; - uint32_t v; + uint32_t v = 0; match = lookup_table(chain, cmd->arg1, a, &v); @@ -3714,8 +3717,8 @@ zero_entry(struct ip_fw_chain *chain, u_ continue; clear_counters(rule, log_only); } - msg = log_only ? "ipfw: All logging counts reset.\n" : - "ipfw: Accounting cleared.\n"; + msg = log_only ? "logging counts reset" : + "Accounting cleared"; } else { int cleared = 0; /* @@ -3736,13 +3739,18 @@ zero_entry(struct ip_fw_chain *chain, u_ IPFW_WUNLOCK(chain); return (EINVAL); } - msg = log_only ? "ipfw: Entry %d logging count reset.\n" : - "ipfw: Entry %d cleared.\n"; + msg = log_only ? "logging count reset" : "cleared"; } IPFW_WUNLOCK(chain); - if (fw_verbose) - log(LOG_SECURITY | LOG_NOTICE, msg, rulenum); + if (fw_verbose) { + int lev = LOG_SECURITY | LOG_NOTICE; + + if (rulenum) + log(lev, "ipfw: Entry %d %s.\n", rulenum, msg); + else + log(lev, "ipfw: %s.\n", msg); + } return (0); } @@ -4357,49 +4365,44 @@ ipfw_ctl(struct sockopt *sopt) break; case IP_FW_NAT_CFG: - { if (IPFW_NAT_LOADED) error = ipfw_nat_cfg_ptr(sopt); else { - printf("IP_FW_NAT_CFG: ipfw_nat not present, please load it.\n"); + printf("IP_FW_NAT_CFG: %s\n", + "ipfw_nat not present, please load it"); error = EINVAL; } - } - break; + break; case IP_FW_NAT_DEL: - { if (IPFW_NAT_LOADED) error = ipfw_nat_del_ptr(sopt); else { - printf("IP_FW_NAT_DEL: ipfw_nat not present, please load it.\n"); - printf("ipfw_nat not loaded: %d\n", sopt->sopt_name); + printf("IP_FW_NAT_DEL: %s\n", + "ipfw_nat not present, please load it"); error = EINVAL; } - } - break; + break; case IP_FW_NAT_GET_CONFIG: - { if (IPFW_NAT_LOADED) error = ipfw_nat_get_cfg_ptr(sopt); else { - printf("IP_FW_NAT_GET_CFG: ipfw_nat not present, please load it.\n"); + printf("IP_FW_NAT_GET_CFG: %s\n", + "ipfw_nat not present, please load it"); error = EINVAL; } - } - break; + break; case IP_FW_NAT_GET_LOG: - { if (IPFW_NAT_LOADED) error = ipfw_nat_get_log_ptr(sopt); else { - printf("IP_FW_NAT_GET_LOG: ipfw_nat not present, please load it.\n"); + printf("IP_FW_NAT_GET_LOG: %s\n", + "ipfw_nat not present, please load it"); error = EINVAL; } - } - break; + break; default: printf("ipfw: ipfw_ctl invalid option %d\n", sopt->sopt_name); From ume at FreeBSD.org Mon Feb 16 10:24:50 2009 From: ume at FreeBSD.org (Hajimu UMEMOTO) Date: Mon Feb 16 10:25:02 2009 Subject: svn commit: r188690 - in stable/7/lib/libc: . net string Message-ID: <200902161824.n1GIOnO3079452@svn.freebsd.org> Author: ume Date: Mon Feb 16 18:24:48 2009 New Revision: 188690 URL: http://svn.freebsd.org/changeset/base/188690 Log: MFH 188316: Shutup warning for DNAME RR. PR: bin/127591 Submitted by: "Eugene M. Kim" <20080111.freebsd.org__at__ab.ote.we.lv> Modified: stable/7/lib/libc/ (props changed) stable/7/lib/libc/net/getaddrinfo.c stable/7/lib/libc/net/gethostbydns.c stable/7/lib/libc/string/ffsll.c (props changed) stable/7/lib/libc/string/flsll.c (props changed) Modified: stable/7/lib/libc/net/getaddrinfo.c ============================================================================== --- stable/7/lib/libc/net/getaddrinfo.c Mon Feb 16 18:07:23 2009 (r188689) +++ stable/7/lib/libc/net/getaddrinfo.c Mon Feb 16 18:24:48 2009 (r188690) @@ -1884,7 +1884,8 @@ getanswer(const querybuf *answer, int an } } else if (type != qtype) { #ifdef DEBUG - if (type != T_KEY && type != T_SIG) + if (type != T_KEY && type != T_SIG && + type != ns_t_dname) syslog(LOG_NOTICE|LOG_AUTH, "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", qname, p_class(C_IN), p_type(qtype), Modified: stable/7/lib/libc/net/gethostbydns.c ============================================================================== --- stable/7/lib/libc/net/gethostbydns.c Mon Feb 16 18:07:23 2009 (r188689) +++ stable/7/lib/libc/net/gethostbydns.c Mon Feb 16 18:24:48 2009 (r188690) @@ -294,7 +294,7 @@ gethostanswer(const querybuf *answer, in continue; } if (type != qtype) { - if (type != T_SIG) + if (type != T_SIG && type != ns_t_dname) syslog(LOG_NOTICE|LOG_AUTH, "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"", qname, p_class(C_IN), p_type(qtype), From emax at FreeBSD.org Mon Feb 16 12:04:59 2009 From: emax at FreeBSD.org (Maksim Yevmenkin) Date: Mon Feb 16 12:05:16 2009 Subject: svn commit: r188696 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/kbdmux Message-ID: <200902162004.n1GK4vwb090681@svn.freebsd.org> Author: emax Date: Mon Feb 16 20:04:57 2009 New Revision: 188696 URL: http://svn.freebsd.org/changeset/base/188696 Log: MFC r188603 Since r188030 the error value for attach is returned, this means if kbdmux fails to attach (possibly due to disable hints) then we get called back for unload. Correctly handle the case where the keyboard isnt found rather than calling panic. Submitted by: thompsa Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/kbdmux/kbdmux.c Modified: stable/7/sys/dev/kbdmux/kbdmux.c ============================================================================== --- stable/7/sys/dev/kbdmux/kbdmux.c Mon Feb 16 19:18:14 2009 (r188695) +++ stable/7/sys/dev/kbdmux/kbdmux.c Mon Feb 16 20:04:57 2009 (r188696) @@ -1367,15 +1367,14 @@ kbdmux_modevent(module_t mod, int type, panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL"); kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0)); - if (kbd == NULL) - panic("kbd_get_keyboard(kbd_find_keyboard(" KEYBOARD_NAME ", 0)) == NULL"); - - (*sw->disable)(kbd); + if (kbd != NULL) { + (*sw->disable)(kbd); #ifdef KBD_INSTALL_CDEV - kbd_detach(kbd); + kbd_detach(kbd); #endif - (*sw->term)(kbd); - kbd_delete_driver(&kbdmux_kbd_driver); + (*sw->term)(kbd); + kbd_delete_driver(&kbdmux_kbd_driver); + } error = 0; break; From cperciva at FreeBSD.org Mon Feb 16 13:56:20 2009 From: cperciva at FreeBSD.org (Colin Percival) Date: Mon Feb 16 13:56:36 2009 Subject: svn commit: r188699 - head/contrib/telnet/telnetd releng/7.0 releng/7.0/contrib/telnet/telnetd releng/7.0/sys/conf releng/7.1 releng/7.1/contrib/telnet/telnetd releng/7.1/sys/conf stable/7/contrib/... Message-ID: <200902162156.n1GLuHkd095723@svn.freebsd.org> Author: cperciva Date: Mon Feb 16 21:56:17 2009 New Revision: 188699 URL: http://svn.freebsd.org/changeset/base/188699 Log: Correctly scrub telnetd's environment. Approved by: so (cperciva) Security: FreeBSD-SA-09:05.telnetd Modified: stable/7/contrib/telnet/telnetd/sys_term.c Changes in other areas also in this revision: Modified: head/contrib/telnet/telnetd/sys_term.c releng/7.0/UPDATING releng/7.0/contrib/telnet/telnetd/sys_term.c releng/7.0/sys/conf/newvers.sh releng/7.1/UPDATING releng/7.1/contrib/telnet/telnetd/sys_term.c releng/7.1/sys/conf/newvers.sh Modified: stable/7/contrib/telnet/telnetd/sys_term.c ============================================================================== --- stable/7/contrib/telnet/telnetd/sys_term.c Mon Feb 16 21:42:41 2009 (r188698) +++ stable/7/contrib/telnet/telnetd/sys_term.c Mon Feb 16 21:56:17 2009 (r188699) @@ -1285,8 +1285,18 @@ scrub_env(void) char **cpp, **cpp2; const char **p; - - for (cpp2 = cpp = environ; *cpp; cpp++) { + char ** new_environ; + size_t count; + + /* Allocate space for scrubbed environment. */ + for (count = 1, cpp = environ; *cpp; count++, cpp++) + continue; + if ((new_environ = malloc(count * sizeof(char *))) == NULL) { + environ = NULL; + return; + } + + for (cpp2 = new_environ, cpp = environ; *cpp; cpp++) { int reject_it = 0; for(p = rej; *p; p++) @@ -1300,10 +1310,15 @@ scrub_env(void) for(p = acc; *p; p++) if(strncmp(*cpp, *p, strlen(*p)) == 0) break; - if(*p != NULL) - *cpp2++ = *cpp; + if(*p != NULL) { + if ((*cpp2++ = strdup(*cpp)) == NULL) { + environ = new_environ; + return; + } + } } *cpp2 = NULL; + environ = new_environ; } /* From jhb at FreeBSD.org Tue Feb 17 07:41:43 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 07:41:54 2009 Subject: svn commit: r188714 - stable/7/sys/sys Message-ID: <200902171541.n1HFffIZ018867@svn.freebsd.org> Author: jhb Date: Tue Feb 17 15:41:41 2009 New Revision: 188714 URL: http://svn.freebsd.org/changeset/base/188714 Log: MFC 1.39: Include in in the kernel so that curthread is always defined. Modified: stable/7/sys/sys/sx.h Modified: stable/7/sys/sys/sx.h ============================================================================== --- stable/7/sys/sys/sx.h Tue Feb 17 15:39:16 2009 (r188713) +++ stable/7/sys/sys/sx.h Tue Feb 17 15:41:41 2009 (r188714) @@ -34,9 +34,10 @@ #include #include -#include #ifdef _KERNEL +#include +#include #include #endif From jhb at FreeBSD.org Tue Feb 17 07:54:10 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 07:54:16 2009 Subject: svn commit: r188716 - in stable/7/cddl/contrib/opensolaris: . lib/libdtrace/common Message-ID: <200902171554.n1HFs994019930@svn.freebsd.org> Author: jhb Date: Tue Feb 17 15:54:09 2009 New Revision: 188716 URL: http://svn.freebsd.org/changeset/base/188716 Log: MFC: Correct the sense of the "use32" terenary operator so that it uses 'lib32' for 32-bit binaries on amd64 and 'lib' for 64-bit binaries. Remove an #ifdef __i386__ that defined use32 to the wrong value on i386 to workaround the bug in the terenary operator. Modified: stable/7/cddl/contrib/opensolaris/ (props changed) stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c Modified: stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c ============================================================================== --- stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c Tue Feb 17 15:47:13 2009 (r188715) +++ stable/7/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c Tue Feb 17 15:54:09 2009 (r188716) @@ -1739,15 +1739,11 @@ dtrace_program_link(dtrace_hdl_t *dtp, d * Arches which are 32-bit only just use the normal * library path. */ -#if defined(__i386__) - int use_32 = 1; /* use /usr/lib/... -sson */ -#else int use_32 = 0; #endif -#endif (void) snprintf(drti, sizeof (drti), "/usr/lib%s/dtrace/drti.o", - use_32 ? "":"32"); + use_32 ? "32":""); len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile, drti) + 1; From jhb at FreeBSD.org Tue Feb 17 07:58:44 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 07:58:49 2009 Subject: svn commit: r188717 - in stable/7/sys: . compat/linprocfs contrib/pf dev/ath/ath_hal dev/cxgb Message-ID: <200902171558.n1HFwgPq020070@svn.freebsd.org> Author: jhb Date: Tue Feb 17 15:58:42 2009 New Revision: 188717 URL: http://svn.freebsd.org/changeset/base/188717 Log: MFC: Fix a bug in the previous change to the mtab handler: use the path returned by vn_fullpath() when vn_fullpath() succeeds instead of when it fails. Modified: stable/7/sys/ (props changed) stable/7/sys/compat/linprocfs/linprocfs.c stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/compat/linprocfs/linprocfs.c ============================================================================== --- stable/7/sys/compat/linprocfs/linprocfs.c Tue Feb 17 15:54:09 2009 (r188716) +++ stable/7/sys/compat/linprocfs/linprocfs.c Tue Feb 17 15:58:42 2009 (r188717) @@ -317,7 +317,7 @@ linprocfs_domtab(PFS_FILL_ARGS) error = namei(&nd); lep = linux_emul_path; if (error == 0) { - if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) != 0) + if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) lep = dlep; vrele(nd.ni_vp); VFS_UNLOCK_GIANT(NDHASGIANT(&nd)); From jhb at FreeBSD.org Tue Feb 17 11:57:53 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 11:58:12 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat Message-ID: <200902171957.n1HJvqk8026145@svn.freebsd.org> Author: jhb Date: Tue Feb 17 19:57:52 2009 New Revision: 188727 URL: http://svn.freebsd.org/changeset/base/188727 Log: MFC: Rework the lifetime management of the kernel implementation of POSIX semaphores. Specifically, semaphores are now represented as new file descriptor type that is set to close on exec. This removes the need for all of the manual process reference counting (and fork, exec, and exit event handlers) as the normal file descriptor operations handle all of that for us nicely. It is also suggested as one possible implementation in the spec and at least one other OS (OS X) uses this approach. Refer to the original commit for more details on specific bug fixes, etc. A notable difference in this MFC relative to the original commit to HEAD is that the MAC entry points are unchanged to preserve the ABI for MAC policy modules. fstat() on a POSIX semaphore in 7 uses the mac_check_posix_sem_getvalue() hook to determine access as that is the closest match to stat() of the available hooks. Discussed with: rwatson (MAC bits (or lack thereof)) Added: stable/7/tools/regression/posixsem/ - copied from r180059, head/tools/regression/posixsem/ Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_descrip.c stable/7/sys/kern/uipc_sem.c stable/7/sys/modules/sem/Makefile stable/7/sys/sys/file.h stable/7/sys/sys/ksem.h stable/7/sys/sys/user.h stable/7/usr.bin/procstat/ (props changed) stable/7/usr.bin/procstat/procstat_files.c Modified: stable/7/sys/kern/kern_descrip.c ============================================================================== --- stable/7/sys/kern/kern_descrip.c Tue Feb 17 19:37:04 2009 (r188726) +++ stable/7/sys/kern/kern_descrip.c Tue Feb 17 19:57:52 2009 (r188727) @@ -2933,6 +2933,10 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER kif->kf_type = KF_TYPE_MQUEUE; break; + case DTYPE_SEM: + kif->kf_type = KF_TYPE_SEM; + break; + default: kif->kf_type = KF_TYPE_UNKNOWN; break; @@ -3070,6 +3074,8 @@ file_type_to_name(short type) return ("crpt"); case DTYPE_MQUEUE: return ("mque"); + case DTYPE_SEM: + return ("ksem"); default: return ("unkn"); } Modified: stable/7/sys/kern/uipc_sem.c ============================================================================== --- stable/7/sys/kern/uipc_sem.c Tue Feb 17 19:37:04 2009 (r188726) +++ stable/7/sys/kern/uipc_sem.c Tue Feb 17 19:57:52 2009 (r188727) @@ -38,583 +38,592 @@ __FBSDID("$FreeBSD$"); #include "opt_posix.h" #include -#include -#include -#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include -#include +#include #include -#include +#include #include -#include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include -static int sem_count_proc(struct proc *p); -static struct ksem *sem_lookup_byname(const char *name); -static int sem_create(struct thread *td, const char *name, - struct ksem **ksret, mode_t mode, unsigned int value); -static void sem_free(struct ksem *ksnew); -static int sem_perm(struct thread *td, struct ksem *ks); -static void sem_enter(struct proc *p, struct ksem *ks); -static int sem_leave(struct proc *p, struct ksem *ks); -static void sem_exechook(void *arg, struct proc *p, - struct image_params *imgp); -static void sem_exithook(void *arg, struct proc *p); -static void sem_forkhook(void *arg, struct proc *p1, struct proc *p2, - int flags); -static int sem_hasopen(struct thread *td, struct ksem *ks); - -static int kern_sem_close(struct thread *td, semid_t id); -static int kern_sem_post(struct thread *td, semid_t id); -static int kern_sem_wait(struct thread *td, semid_t id, int tryflag, - struct timespec *abstime); -static int kern_sem_init(struct thread *td, int dir, unsigned int value, - semid_t *idp); -static int kern_sem_open(struct thread *td, int dir, const char *name, - int oflag, mode_t mode, unsigned int value, semid_t *idp); -static int kern_sem_unlink(struct thread *td, const char *name); +/* + * TODO + * + * - Resource limits? + * - Update fstat(1) + * - Replace global sem_lock with mtx_pool locks? + * - Add a MAC check_create() hook for creating new named semaphores. + */ #ifndef SEM_MAX #define SEM_MAX 30 #endif -#define SEM_MAX_NAMELEN 14 - -#define SEM_TO_ID(x) ((intptr_t)(x)) -#define ID_TO_SEM(x) id_to_sem(x) - -/* - * Available semaphores go here, this includes sem_init and any semaphores - * created via sem_open that have not yet been unlinked. - */ -LIST_HEAD(, ksem) ksem_head = LIST_HEAD_INITIALIZER(&ksem_head); +#ifdef SEM_DEBUG +#define DP(x) printf x +#else +#define DP(x) +#endif -/* - * Semaphores still in use but have been sem_unlink()'d go here. - */ -LIST_HEAD(, ksem) ksem_deadhead = LIST_HEAD_INITIALIZER(&ksem_deadhead); +struct ksem_mapping { + char *km_path; + Fnv32_t km_fnv; + struct ksem *km_ksem; + LIST_ENTRY(ksem_mapping) km_link; +}; +static MALLOC_DEFINE(M_KSEM, "ksem", "semaphore file descriptor"); +static LIST_HEAD(, ksem_mapping) *ksem_dictionary; +static struct sx ksem_dict_lock; +static struct mtx ksem_count_lock; static struct mtx sem_lock; -static MALLOC_DEFINE(M_SEM, "sems", "semaphore data"); +static u_long ksem_hash; +static int ksem_dead; + +#define KSEM_HASH(fnv) (&ksem_dictionary[(fnv) & ksem_hash]) static int nsems = 0; SYSCTL_DECL(_p1003_1b); -SYSCTL_INT(_p1003_1b, OID_AUTO, nsems, CTLFLAG_RD, &nsems, 0, ""); +SYSCTL_INT(_p1003_1b, OID_AUTO, nsems, CTLFLAG_RD, &nsems, 0, + "Number of active kernel POSIX semaphores"); -static eventhandler_tag sem_exit_tag, sem_exec_tag, sem_fork_tag; +static int kern_sem_wait(struct thread *td, semid_t id, int tryflag, + struct timespec *abstime); +static int ksem_access(struct ksem *ks, struct ucred *ucred); +static struct ksem *ksem_alloc(struct ucred *ucred, mode_t mode, + unsigned int value); +static int ksem_create(struct thread *td, const char *path, + semid_t *semidp, mode_t mode, unsigned int value, + int flags); +static void ksem_drop(struct ksem *ks); +static int ksem_get(struct thread *td, semid_t id, struct file **fpp); +static struct ksem *ksem_hold(struct ksem *ks); +static void ksem_insert(char *path, Fnv32_t fnv, struct ksem *ks); +static struct ksem *ksem_lookup(char *path, Fnv32_t fnv); +static void ksem_module_destroy(void); +static int ksem_module_init(void); +static int ksem_remove(char *path, Fnv32_t fnv, struct ucred *ucred); +static int sem_modload(struct module *module, int cmd, void *arg); -#ifdef SEM_DEBUG -#define DP(x) printf x -#else -#define DP(x) -#endif +static fo_rdwr_t ksem_read; +static fo_rdwr_t ksem_write; +static fo_ioctl_t ksem_ioctl; +static fo_poll_t ksem_poll; +static fo_kqfilter_t ksem_kqfilter; +static fo_stat_t ksem_stat; +static fo_close_t ksem_closef; + +/* File descriptor operations. */ +static struct fileops ksem_ops = { + .fo_read = ksem_read, + .fo_write = ksem_write, + .fo_ioctl = ksem_ioctl, + .fo_poll = ksem_poll, + .fo_kqfilter = ksem_kqfilter, + .fo_stat = ksem_stat, + .fo_close = ksem_closef, + .fo_flags = DFLAG_PASSABLE +}; -static __inline void -sem_ref(struct ksem *ks) +FEATURE(posix_sem, "POSIX semaphores"); + +static int +ksem_read(struct file *fp, struct uio *uio, struct ucred *active_cred, + int flags, struct thread *td) { - mtx_assert(&sem_lock, MA_OWNED); - ks->ks_ref++; - DP(("sem_ref: ks = %p, ref = %d\n", ks, ks->ks_ref)); + return (EOPNOTSUPP); } -static __inline void -sem_rel(struct ksem *ks) +static int +ksem_write(struct file *fp, struct uio *uio, struct ucred *active_cred, + int flags, struct thread *td) { - mtx_assert(&sem_lock, MA_OWNED); - DP(("sem_rel: ks = %p, ref = %d\n", ks, ks->ks_ref - 1)); - if (--ks->ks_ref == 0) - sem_free(ks); + return (EOPNOTSUPP); } -static __inline -struct ksem * -id_to_sem(semid_t id) +static int +ksem_ioctl(struct file *fp, u_long com, void *data, + struct ucred *active_cred, struct thread *td) { - struct ksem *ks; - mtx_assert(&sem_lock, MA_OWNED); - DP(("id_to_sem: id = %0x,%p\n", id, (struct ksem *)id)); - LIST_FOREACH(ks, &ksem_head, ks_entry) { - DP(("id_to_sem: ks = %p\n", ks)); - if (ks == (struct ksem *)id) - return (ks); - } - return (NULL); + return (EOPNOTSUPP); } -static struct ksem * -sem_lookup_byname(const char *name) +static int +ksem_poll(struct file *fp, int events, struct ucred *active_cred, + struct thread *td) { - struct ksem *ks; - mtx_assert(&sem_lock, MA_OWNED); - LIST_FOREACH(ks, &ksem_head, ks_entry) - if (ks->ks_name != NULL && strcmp(ks->ks_name, name) == 0) - return (ks); - return (NULL); + return (EOPNOTSUPP); } static int -sem_create(struct thread *td, const char *name, struct ksem **ksret, - mode_t mode, unsigned int value) +ksem_kqfilter(struct file *fp, struct knote *kn) { - struct ksem *ret; - struct proc *p; - struct ucred *uc; - size_t len; + + return (EOPNOTSUPP); +} + +static int +ksem_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, + struct thread *td) +{ + struct ksem *ks; +#ifdef MAC int error; +#endif - DP(("sem_create\n")); - p = td->td_proc; - uc = td->td_ucred; - if (value > SEM_VALUE_MAX) - return (EINVAL); - ret = malloc(sizeof(*ret), M_SEM, M_WAITOK | M_ZERO); - if (name != NULL) { - len = strlen(name); - if (len > SEM_MAX_NAMELEN) { - free(ret, M_SEM); - return (ENAMETOOLONG); - } + ks = fp->f_data; - /* Name must start with a '/' but not contain one. */ - if (*name != '/' || len < 2 || index(name + 1, '/') != NULL) { - free(ret, M_SEM); - return (EINVAL); - } - ret->ks_name = malloc(len + 1, M_SEM, M_WAITOK); - strcpy(ret->ks_name, name); - } else { - ret->ks_name = NULL; - } - ret->ks_mode = mode; - ret->ks_value = value; - ret->ks_ref = 1; - ret->ks_waiters = 0; - ret->ks_uid = uc->cr_uid; - ret->ks_gid = uc->cr_gid; - ret->ks_onlist = 0; - cv_init(&ret->ks_cv, "sem"); - LIST_INIT(&ret->ks_users); #ifdef MAC - mac_init_posix_sem(ret); - mac_create_posix_sem(uc, ret); + /* + * XXX: This isn't quite right, but adding a new stat() hook + * would break the ABI. This seems to be the closest match of + * the existing MAC hooks for POSIX semaphores in 7. + */ + error = mac_check_posix_sem_getvalue(active_cred, ks); + if (error) + return (error); #endif - if (name != NULL) - sem_enter(td->td_proc, ret); - *ksret = ret; - mtx_lock(&sem_lock); - nsems++; - if (nsems > p31b_getcfg(CTL_P1003_1B_SEM_NSEMS_MAX)) { - sem_leave(td->td_proc, ret); - sem_free(ret); - error = ENFILE; - } else - error = 0; - mtx_unlock(&sem_lock); - return (error); + + /* + * Attempt to return sanish values for fstat() on a semaphore + * file descriptor. + */ + bzero(sb, sizeof(*sb)); + sb->st_mode = S_IFREG | ks->ks_mode; /* XXX */ + + sb->st_atimespec = ks->ks_atime; + sb->st_ctimespec = ks->ks_ctime; + sb->st_mtimespec = ks->ks_mtime; + sb->st_birthtimespec = ks->ks_birthtime; + sb->st_uid = ks->ks_uid; + sb->st_gid = ks->ks_gid; + + return (0); } -#ifndef _SYS_SYSPROTO_H_ -struct ksem_init_args { - unsigned int value; - semid_t *idp; -}; -int ksem_init(struct thread *td, struct ksem_init_args *uap); -#endif -int -ksem_init(struct thread *td, struct ksem_init_args *uap) +static int +ksem_closef(struct file *fp, struct thread *td) { + struct ksem *ks; - return (kern_sem_init(td, UIO_USERSPACE, uap->value, uap->idp)); + ks = fp->f_data; + fp->f_data = NULL; + ksem_drop(ks); + + return (0); } -static int -kern_sem_init(struct thread *td, int dir, unsigned int value, semid_t *idp) +/* + * ksem object management including creation and reference counting + * routines. + */ +static struct ksem * +ksem_alloc(struct ucred *ucred, mode_t mode, unsigned int value) { struct ksem *ks; - semid_t id; - int error; - error = sem_create(td, NULL, &ks, S_IRWXU | S_IRWXG, value); - if (error) - return (error); - id = SEM_TO_ID(ks); - if (dir == UIO_USERSPACE) { - error = copyout(&id, idp, sizeof(id)); - if (error) { - mtx_lock(&sem_lock); - sem_rel(ks); - mtx_unlock(&sem_lock); - return (error); - } - } else { - *idp = id; + mtx_lock(&ksem_count_lock); + if (nsems == p31b_getcfg(CTL_P1003_1B_SEM_NSEMS_MAX) || ksem_dead) { + mtx_unlock(&ksem_count_lock); + return (NULL); } - mtx_lock(&sem_lock); - LIST_INSERT_HEAD(&ksem_head, ks, ks_entry); - ks->ks_onlist = 1; - mtx_unlock(&sem_lock); - return (error); + nsems++; + mtx_unlock(&ksem_count_lock); + ks = malloc(sizeof(*ks), M_KSEM, M_WAITOK | M_ZERO); + ks->ks_uid = ucred->cr_uid; + ks->ks_gid = ucred->cr_gid; + ks->ks_mode = mode; + ks->ks_value = value; + cv_init(&ks->ks_cv, "ksem"); + vfs_timestamp(&ks->ks_birthtime); + ks->ks_atime = ks->ks_mtime = ks->ks_ctime = ks->ks_birthtime; + refcount_init(&ks->ks_ref, 1); +#ifdef MAC + mac_init_posix_sem(ks); + mac_create_posix_sem(ucred, ks); +#endif + + return (ks); } -#ifndef _SYS_SYSPROTO_H_ -struct ksem_open_args { - char *name; - int oflag; - mode_t mode; - unsigned int value; - semid_t *idp; -}; -int ksem_open(struct thread *td, struct ksem_open_args *uap); +static struct ksem * +ksem_hold(struct ksem *ks) +{ + + refcount_acquire(&ks->ks_ref); + return (ks); +} + +static void +ksem_drop(struct ksem *ks) +{ + + if (refcount_release(&ks->ks_ref)) { +#ifdef MAC + mac_destroy_posix_sem(ks); #endif -int -ksem_open(struct thread *td, struct ksem_open_args *uap) + cv_destroy(&ks->ks_cv); + free(ks, M_KSEM); + mtx_lock(&ksem_count_lock); + nsems--; + mtx_unlock(&ksem_count_lock); + } +} + +/* + * Determine if the credentials have sufficient permissions for read + * and write access. + */ +static int +ksem_access(struct ksem *ks, struct ucred *ucred) { - char name[SEM_MAX_NAMELEN + 1]; - size_t done; int error; - error = copyinstr(uap->name, name, SEM_MAX_NAMELEN + 1, &done); + error = vaccess(VREG, ks->ks_mode, ks->ks_uid, ks->ks_gid, + VREAD | VWRITE, ucred, NULL); if (error) - return (error); - DP((">>> sem_open start\n")); - error = kern_sem_open(td, UIO_USERSPACE, - name, uap->oflag, uap->mode, uap->value, uap->idp); - DP(("<<< sem_open end\n")); + error = priv_check_cred(ucred, PRIV_SEM_WRITE, 0); return (error); } -static int -kern_sem_open(struct thread *td, int dir, const char *name, int oflag, - mode_t mode, unsigned int value, semid_t *idp) +/* + * Dictionary management. We maintain an in-kernel dictionary to map + * paths to semaphore objects. We use the FNV hash on the path to + * store the mappings in a hash table. + */ +static struct ksem * +ksem_lookup(char *path, Fnv32_t fnv) { - struct ksem *ksnew, *ks; - int error; - semid_t id; - - ksnew = NULL; - mtx_lock(&sem_lock); - ks = sem_lookup_byname(name); + struct ksem_mapping *map; - /* - * If we found it but O_EXCL is set, error. - */ - if (ks != NULL && (oflag & O_EXCL) != 0) { - mtx_unlock(&sem_lock); - return (EEXIST); + LIST_FOREACH(map, KSEM_HASH(fnv), km_link) { + if (map->km_fnv != fnv) + continue; + if (strcmp(map->km_path, path) == 0) + return (map->km_ksem); } - /* - * If we didn't find it... - */ - if (ks == NULL) { - /* - * didn't ask for creation? error. - */ - if ((oflag & O_CREAT) == 0) { - mtx_unlock(&sem_lock); - return (ENOENT); - } + return (NULL); +} - /* - * We may block during creation, so drop the lock. - */ - mtx_unlock(&sem_lock); - error = sem_create(td, name, &ksnew, mode, value); - if (error != 0) - return (error); - id = SEM_TO_ID(ksnew); - if (dir == UIO_USERSPACE) { - DP(("about to copyout! %d to %p\n", id, idp)); - error = copyout(&id, idp, sizeof(id)); - if (error) { - mtx_lock(&sem_lock); - sem_leave(td->td_proc, ksnew); - sem_rel(ksnew); - mtx_unlock(&sem_lock); - return (error); - } - } else { - DP(("about to set! %d to %p\n", id, idp)); - *idp = id; - } +static void +ksem_insert(char *path, Fnv32_t fnv, struct ksem *ks) +{ + struct ksem_mapping *map; - /* - * We need to make sure we haven't lost a race while - * allocating during creation. - */ - mtx_lock(&sem_lock); - ks = sem_lookup_byname(name); - if (ks != NULL) { - /* we lost... */ - sem_leave(td->td_proc, ksnew); - sem_rel(ksnew); - /* we lost and we can't loose... */ - if ((oflag & O_EXCL) != 0) { - mtx_unlock(&sem_lock); - return (EEXIST); - } - } else { - DP(("sem_create: about to add to list...\n")); - LIST_INSERT_HEAD(&ksem_head, ksnew, ks_entry); - DP(("sem_create: setting list bit...\n")); - ksnew->ks_onlist = 1; - DP(("sem_create: done, about to unlock...\n")); - } - } else { + map = malloc(sizeof(struct ksem_mapping), M_KSEM, M_WAITOK); + map->km_path = path; + map->km_fnv = fnv; + map->km_ksem = ksem_hold(ks); + LIST_INSERT_HEAD(KSEM_HASH(fnv), map, km_link); +} + +static int +ksem_remove(char *path, Fnv32_t fnv, struct ucred *ucred) +{ + struct ksem_mapping *map; + int error; + + LIST_FOREACH(map, KSEM_HASH(fnv), km_link) { + if (map->km_fnv != fnv) + continue; + if (strcmp(map->km_path, path) == 0) { #ifdef MAC - error = mac_check_posix_sem_open(td->td_ucred, ks); - if (error) - goto err_open; + error = mac_check_posix_sem_unlink(ucred, map->km_ksem); + if (error) + return (error); #endif - /* - * if we aren't the creator, then enforce permissions. - */ - error = sem_perm(td, ks); - if (error) - goto err_open; - sem_ref(ks); - mtx_unlock(&sem_lock); - id = SEM_TO_ID(ks); - if (dir == UIO_USERSPACE) { - error = copyout(&id, idp, sizeof(id)); - if (error) { - mtx_lock(&sem_lock); - sem_rel(ks); - mtx_unlock(&sem_lock); + error = ksem_access(map->km_ksem, ucred); + if (error) return (error); - } - } else { - *idp = id; + LIST_REMOVE(map, km_link); + ksem_drop(map->km_ksem); + free(map->km_path, M_KSEM); + free(map, M_KSEM); + return (0); } - sem_enter(td->td_proc, ks); - mtx_lock(&sem_lock); - sem_rel(ks); } -err_open: - mtx_unlock(&sem_lock); - return (error); + + return (ENOENT); } +/* Other helper routines. */ static int -sem_perm(struct thread *td, struct ksem *ks) +ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, + unsigned int value, int flags) { - struct ucred *uc; + struct filedesc *fdp; + struct ksem *ks; + struct file *fp; + char *path; + semid_t semid; + Fnv32_t fnv; + int error, fd; + + if (value > SEM_VALUE_MAX) + return (EINVAL); + + fdp = td->td_proc->p_fd; + mode = (mode & ~fdp->fd_cmask) & ACCESSPERMS; + error = falloc(td, &fp, &fd); + if (error) { + if (name == NULL) + error = ENOSPC; + return (error); + } /* - * XXXRW: This permission routine appears to be incorrect. If the - * user matches, we shouldn't go on to the group if the user - * permissions don't allow the action? Not changed for now. To fix, - * change from a series of if (); if (); to if () else if () else... + * Go ahead and copyout the file descriptor now. This is a bit + * premature, but it is a lot easier to handle errors as opposed + * to later when we've possibly created a new semaphore, etc. */ - uc = td->td_ucred; - DP(("sem_perm: uc(%d,%d) ks(%d,%d,%o)\n", - uc->cr_uid, uc->cr_gid, - ks->ks_uid, ks->ks_gid, ks->ks_mode)); - if ((uc->cr_uid == ks->ks_uid) && (ks->ks_mode & S_IWUSR) != 0) - return (0); - if ((uc->cr_gid == ks->ks_gid) && (ks->ks_mode & S_IWGRP) != 0) - return (0); - if ((ks->ks_mode & S_IWOTH) != 0) - return (0); - return (priv_check(td, PRIV_SEM_WRITE)); -} + semid = fd; + error = copyout(&semid, semidp, sizeof(semid)); + if (error) { + fdclose(fdp, fp, fd, td); + fdrop(fp, td); + return (error); + } -static void -sem_free(struct ksem *ks) -{ + if (name == NULL) { + /* Create an anonymous semaphore. */ + ks = ksem_alloc(td->td_ucred, mode, value); + if (ks == NULL) + error = ENOSPC; + else + ks->ks_flags |= KS_ANONYMOUS; + } else { + path = malloc(MAXPATHLEN, M_KSEM, M_WAITOK); + error = copyinstr(name, path, MAXPATHLEN, NULL); + + /* Require paths to start with a '/' character. */ + if (error == 0 && path[0] != '/') + error = EINVAL; + if (error) { + fdclose(fdp, fp, fd, td); + fdrop(fp, td); + free(path, M_KSEM); + return (error); + } + fnv = fnv_32_str(path, FNV1_32_INIT); + sx_xlock(&ksem_dict_lock); + ks = ksem_lookup(path, fnv); + if (ks == NULL) { + /* Object does not exist, create it if requested. */ + if (flags & O_CREAT) { + ks = ksem_alloc(td->td_ucred, mode, value); + if (ks == NULL) + error = ENFILE; + else { + ksem_insert(path, fnv, ks); + path = NULL; + } + } else + error = ENOENT; + } else { + /* + * Object already exists, obtain a new + * reference if requested and permitted. + */ + if ((flags & (O_CREAT | O_EXCL)) == + (O_CREAT | O_EXCL)) + error = EEXIST; + else { #ifdef MAC - mac_destroy_posix_sem(ks); + error = mac_check_posix_sem_open(td->td_ucred, + ks); + if (error == 0) #endif - nsems--; - if (ks->ks_onlist) - LIST_REMOVE(ks, ks_entry); - if (ks->ks_name != NULL) - free(ks->ks_name, M_SEM); - cv_destroy(&ks->ks_cv); - free(ks, M_SEM); -} + error = ksem_access(ks, td->td_ucred); + } + if (error == 0) + ksem_hold(ks); +#ifdef INVARIANTS + else + ks = NULL; +#endif + } + sx_xunlock(&ksem_dict_lock); + if (path) + free(path, M_KSEM); + } -static __inline struct kuser * -sem_getuser(struct proc *p, struct ksem *ks) -{ - struct kuser *k; + if (error) { + KASSERT(ks == NULL, ("ksem_create error with a ksem")); + fdclose(fdp, fp, fd, td); + fdrop(fp, td); + return (error); + } + KASSERT(ks != NULL, ("ksem_create w/o a ksem")); - LIST_FOREACH(k, &ks->ks_users, ku_next) - if (k->ku_pid == p->p_pid) - return (k); - return (NULL); -} + fp->f_data = ks; + fp->f_flag = FREAD | FWRITE; + fp->f_type = DTYPE_SEM; + fp->f_ops = &ksem_ops; -static int -sem_hasopen(struct thread *td, struct ksem *ks) -{ - - return ((ks->ks_name == NULL && sem_perm(td, ks) == 0) - || sem_getuser(td->td_proc, ks) != NULL); + FILEDESC_XLOCK(fdp); + if (fdp->fd_ofiles[fd] == fp) + fdp->fd_ofileflags[fd] |= UF_EXCLOSE; + FILEDESC_XUNLOCK(fdp); + fdrop(fp, td); + + return (0); } static int -sem_leave(struct proc *p, struct ksem *ks) +ksem_get(struct thread *td, semid_t id, struct file **fpp) { - struct kuser *k; + struct ksem *ks; + struct file *fp; + int error; - DP(("sem_leave: ks = %p\n", ks)); - k = sem_getuser(p, ks); - DP(("sem_leave: ks = %p, k = %p\n", ks, k)); - if (k != NULL) { - LIST_REMOVE(k, ku_next); - sem_rel(ks); - DP(("sem_leave: about to free k\n")); - free(k, M_SEM); - DP(("sem_leave: returning\n")); - return (0); + error = fget(td, id, &fp); + if (error) + return (EINVAL); + if (fp->f_type != DTYPE_SEM) { + fdrop(fp, td); + return (EINVAL); } - return (EINVAL); + ks = fp->f_data; + if (ks->ks_flags & KS_DEAD) { + fdrop(fp, td); + return (EINVAL); + } + *fpp = fp; + return (0); } -static void -sem_enter(struct proc *p, struct ksem *ks) +/* System calls. */ +#ifndef _SYS_SYSPROTO_H_ +struct ksem_init_args { + unsigned int value; + semid_t *idp; +}; +#endif +int +ksem_init(struct thread *td, struct ksem_init_args *uap) { - struct kuser *ku, *k; - ku = malloc(sizeof(*ku), M_SEM, M_WAITOK); - ku->ku_pid = p->p_pid; - mtx_lock(&sem_lock); - k = sem_getuser(p, ks); - if (k != NULL) { - mtx_unlock(&sem_lock); - free(ku, M_TEMP); - return; - } - LIST_INSERT_HEAD(&ks->ks_users, ku, ku_next); - sem_ref(ks); - mtx_unlock(&sem_lock); + return (ksem_create(td, NULL, uap->idp, S_IRWXU | S_IRWXG, uap->value, + 0)); } #ifndef _SYS_SYSPROTO_H_ -struct ksem_unlink_args { - char *name; +struct ksem_open_args { + char *name; + int oflag; + mode_t mode; + unsigned int value; + semid_t *idp; }; -int ksem_unlink(struct thread *td, struct ksem_unlink_args *uap); #endif int -ksem_unlink(struct thread *td, struct ksem_unlink_args *uap) +ksem_open(struct thread *td, struct ksem_open_args *uap) { - char name[SEM_MAX_NAMELEN + 1]; - size_t done; - int error; - error = copyinstr(uap->name, name, SEM_MAX_NAMELEN + 1, &done); - return (error ? error : - kern_sem_unlink(td, name)); + if ((uap->oflag & ~(O_CREAT | O_EXCL)) != 0) + return (EINVAL); + return (ksem_create(td, uap->name, uap->idp, uap->mode, uap->value, + uap->oflag)); } -static int -kern_sem_unlink(struct thread *td, const char *name) +#ifndef _SYS_SYSPROTO_H_ +struct ksem_unlink_args { + char *name; +}; +#endif +int +ksem_unlink(struct thread *td, struct ksem_unlink_args *uap) { - struct ksem *ks; + char *path; + Fnv32_t fnv; int error; - mtx_lock(&sem_lock); - ks = sem_lookup_byname(name); - if (ks != NULL) { -#ifdef MAC - error = mac_check_posix_sem_unlink(td->td_ucred, ks); - if (error) { - mtx_unlock(&sem_lock); - return (error); - } -#endif - error = sem_perm(td, ks); - } else - error = ENOENT; - DP(("sem_unlink: '%s' ks = %p, error = %d\n", name, ks, error)); - if (error == 0) { - LIST_REMOVE(ks, ks_entry); - LIST_INSERT_HEAD(&ksem_deadhead, ks, ks_entry); - sem_rel(ks); + path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + error = copyinstr(uap->name, path, MAXPATHLEN, NULL); + if (error) { + free(path, M_TEMP); + return (error); } - mtx_unlock(&sem_lock); + + fnv = fnv_32_str(path, FNV1_32_INIT); + sx_xlock(&ksem_dict_lock); + error = ksem_remove(path, fnv, td->td_ucred); + sx_xunlock(&ksem_dict_lock); + free(path, M_TEMP); + return (error); } #ifndef _SYS_SYSPROTO_H_ struct ksem_close_args { - semid_t id; + semid_t id; }; -int ksem_close(struct thread *td, struct ksem_close_args *uap); #endif int ksem_close(struct thread *td, struct ksem_close_args *uap) { - - return (kern_sem_close(td, uap->id)); -} - -static int -kern_sem_close(struct thread *td, semid_t id) -{ struct ksem *ks; + struct file *fp; int error; - error = EINVAL; - mtx_lock(&sem_lock); - ks = ID_TO_SEM(id); - - /* - * This is not a valid operation for unnamed sems. - */ - if (ks != NULL && ks->ks_name != NULL) *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From jhb at FreeBSD.org Tue Feb 17 13:02:38 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 13:02:50 2009 Subject: svn commit: r188730 - in stable/7: share/man/man9 sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern Message-ID: <200902172102.n1HL2ZZJ027560@svn.freebsd.org> Author: jhb Date: Tue Feb 17 21:02:35 2009 New Revision: 188730 URL: http://svn.freebsd.org/changeset/base/188730 Log: MFC: Permit Giant to be passed as the explicit interlock either to msleep/mtx_sleep or the various cv_*wait*() routines. Modified: stable/7/share/man/man9/ (props changed) stable/7/share/man/man9/condvar.9 stable/7/share/man/man9/sleep.9 stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_condvar.c stable/7/sys/kern/kern_synch.c Modified: stable/7/share/man/man9/condvar.9 ============================================================================== --- stable/7/share/man/man9/condvar.9 Tue Feb 17 20:35:11 2009 (r188729) +++ stable/7/share/man/man9/condvar.9 Tue Feb 17 21:02:35 2009 (r188730) @@ -136,9 +136,27 @@ When a thread waits on a condition, .Fa lock is atomically released before the thread is blocked, then reacquired before the function call returns. +In addition, the thread will fully drop the +.Va Giant +mutex +(even if recursed) +while the it is suspended and will reacquire the +.Va Giant +mutex before the function returns. The .Fn cv_wait_unlock function does not reacquire the lock before returning. +Note that the +.Va Giant +mutex may be specified as +.Fa lock . +However, +.Va Giant +may not be used as +.Fa lock +for the +.Fn cv_wait_unlock +function. All waiters must pass the same .Fa lock in conjunction with Modified: stable/7/share/man/man9/sleep.9 ============================================================================== --- stable/7/share/man/man9/sleep.9 Tue Feb 17 20:35:11 2009 (r188729) +++ stable/7/share/man/man9/sleep.9 Tue Feb 17 21:02:35 2009 (r188730) @@ -153,6 +153,12 @@ mutex while the thread is suspended and will reacquire the .Va Giant mutex before the function returns. +Note that the +.Va Giant +mutex may be specified as the lock to drop. +In that case, however, the +.Dv PDROP +flag is not allowed. .Pp To avoid lost wakeups, either a lock should be used to protect against races, Modified: stable/7/sys/kern/kern_condvar.c ============================================================================== --- stable/7/sys/kern/kern_condvar.c Tue Feb 17 20:35:11 2009 (r188729) +++ stable/7/sys/kern/kern_condvar.c Tue Feb 17 21:02:35 2009 (r188730) @@ -100,6 +100,7 @@ _cv_wait(struct cv *cvp, struct lock_obj int lock_state; td = curthread; + lock_state = 0; #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); @@ -126,11 +127,13 @@ _cv_wait(struct cv *cvp, struct lock_obj DROP_GIANT(); sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR, 0); - if (class->lc_flags & LC_SLEEPABLE) - sleepq_release(cvp); - lock_state = class->lc_unlock(lock); - if (class->lc_flags & LC_SLEEPABLE) - sleepq_lock(cvp); + if (lock != &Giant.lock_object) { + if (class->lc_flags & LC_SLEEPABLE) + sleepq_release(cvp); + lock_state = class->lc_unlock(lock); + if (class->lc_flags & LC_SLEEPABLE) + sleepq_lock(cvp); + } sleepq_wait(cvp); #ifdef KTRACE @@ -138,8 +141,10 @@ _cv_wait(struct cv *cvp, struct lock_obj ktrcsw(0, 0); #endif PICKUP_GIANT(); - class->lc_lock(lock, lock_state); - WITNESS_RESTORE(lock, lock_witness); + if (lock != &Giant.lock_object) { + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); + } } /* @@ -160,6 +165,8 @@ _cv_wait_unlock(struct cv *cvp, struct l CV_ASSERT(cvp, lock, td); WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, "Waiting on \"%s\"", cvp->cv_description); + KASSERT(lock != &Giant.lock_object, + ("cv_wait_unlock cannot be used with Giant")); class = LOCK_CLASS(lock); if (cold || panicstr) { @@ -210,6 +217,7 @@ _cv_wait_sig(struct cv *cvp, struct lock td = curthread; p = td->td_proc; + lock_state = 0; #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); @@ -237,11 +245,13 @@ _cv_wait_sig(struct cv *cvp, struct lock sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR | SLEEPQ_INTERRUPTIBLE, 0); - if (class->lc_flags & LC_SLEEPABLE) - sleepq_release(cvp); - lock_state = class->lc_unlock(lock); - if (class->lc_flags & LC_SLEEPABLE) - sleepq_lock(cvp); + if (lock != &Giant.lock_object) { + if (class->lc_flags & LC_SLEEPABLE) + sleepq_release(cvp); + lock_state = class->lc_unlock(lock); + if (class->lc_flags & LC_SLEEPABLE) + sleepq_lock(cvp); + } rval = sleepq_wait_sig(cvp); #ifdef KTRACE @@ -249,8 +259,10 @@ _cv_wait_sig(struct cv *cvp, struct lock ktrcsw(0, 0); #endif PICKUP_GIANT(); - class->lc_lock(lock, lock_state); - WITNESS_RESTORE(lock, lock_witness); + if (lock != &Giant.lock_object) { + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); + } return (rval); } @@ -270,6 +282,7 @@ _cv_timedwait(struct cv *cvp, struct loc td = curthread; rval = 0; + lock_state = 0; #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); @@ -297,11 +310,13 @@ _cv_timedwait(struct cv *cvp, struct loc sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR, 0); sleepq_set_timeout(cvp, timo); - if (class->lc_flags & LC_SLEEPABLE) - sleepq_release(cvp); - lock_state = class->lc_unlock(lock); - if (class->lc_flags & LC_SLEEPABLE) - sleepq_lock(cvp); + if (lock != &Giant.lock_object) { + if (class->lc_flags & LC_SLEEPABLE) + sleepq_release(cvp); + lock_state = class->lc_unlock(lock); + if (class->lc_flags & LC_SLEEPABLE) + sleepq_lock(cvp); + } rval = sleepq_timedwait(cvp); #ifdef KTRACE @@ -309,8 +324,10 @@ _cv_timedwait(struct cv *cvp, struct loc ktrcsw(0, 0); #endif PICKUP_GIANT(); - class->lc_lock(lock, lock_state); - WITNESS_RESTORE(lock, lock_witness); + if (lock != &Giant.lock_object) { + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); + } return (rval); } @@ -333,6 +350,7 @@ _cv_timedwait_sig(struct cv *cvp, struct td = curthread; p = td->td_proc; rval = 0; + lock_state = 0; #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) ktrcsw(1, 0); @@ -361,11 +379,13 @@ _cv_timedwait_sig(struct cv *cvp, struct sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR | SLEEPQ_INTERRUPTIBLE, 0); sleepq_set_timeout(cvp, timo); - if (class->lc_flags & LC_SLEEPABLE) - sleepq_release(cvp); - lock_state = class->lc_unlock(lock); - if (class->lc_flags & LC_SLEEPABLE) - sleepq_lock(cvp); + if (lock != &Giant.lock_object) { + if (class->lc_flags & LC_SLEEPABLE) + sleepq_release(cvp); + lock_state = class->lc_unlock(lock); + if (class->lc_flags & LC_SLEEPABLE) + sleepq_lock(cvp); + } rval = sleepq_timedwait_sig(cvp); #ifdef KTRACE @@ -373,8 +393,10 @@ _cv_timedwait_sig(struct cv *cvp, struct ktrcsw(0, 0); #endif PICKUP_GIANT(); - class->lc_lock(lock, lock_state); - WITNESS_RESTORE(lock, lock_witness); + if (lock != &Giant.lock_object) { + class->lc_lock(lock, lock_state); + WITNESS_RESTORE(lock, lock_witness); + } return (rval); } Modified: stable/7/sys/kern/kern_synch.c ============================================================================== --- stable/7/sys/kern/kern_synch.c Tue Feb 17 20:35:11 2009 (r188729) +++ stable/7/sys/kern/kern_synch.c Tue Feb 17 21:02:35 2009 (r188730) @@ -139,6 +139,9 @@ _sleep(void *ident, struct lock_object * ident == &lbolt, ("sleeping without a lock")); KASSERT(p != NULL, ("msleep1")); KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep")); + if (priority & PDROP) + KASSERT(lock != NULL && lock != &Giant.lock_object, + ("PDROP requires a non-Giant lock")); if (lock != NULL) class = LOCK_CLASS(lock); else @@ -180,7 +183,8 @@ _sleep(void *ident, struct lock_object * td->td_tid, p->p_pid, p->p_comm, wmesg, ident); DROP_GIANT(); - if (lock != NULL && !(class->lc_flags & LC_SLEEPABLE)) { + if (lock != NULL && lock != &Giant.lock_object && + !(class->lc_flags & LC_SLEEPABLE)) { WITNESS_SAVE(lock, lock_witness); lock_state = class->lc_unlock(lock); } else @@ -231,7 +235,7 @@ _sleep(void *ident, struct lock_object * ktrcsw(0, 0); #endif PICKUP_GIANT(); - if (lock != NULL && !(priority & PDROP)) { + if (lock != NULL && lock != &Giant.lock_object && !(priority & PDROP)) { class->lc_lock(lock, lock_state); WITNESS_RESTORE(lock, lock_witness); } From jhb at FreeBSD.org Tue Feb 17 13:35:56 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 13:36:09 2009 Subject: svn commit: r188734 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902172135.n1HLZs40028338@svn.freebsd.org> Author: jhb Date: Tue Feb 17 21:35:54 2009 New Revision: 188734 URL: http://svn.freebsd.org/changeset/base/188734 Log: MFC: Use shared vnode locks instead of exclusive vnode locks for the access(), chdir(), chroot(), eaccess(), fchdir(), fpathconf(), fstat(), fstatfs(), lseek() (when figuring out the current size of the file in the SEEK_END case), pathconf(), readlink(), and statfs() system calls. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_descrip.c stable/7/sys/kern/vfs_syscalls.c stable/7/sys/kern/vfs_vnops.c Modified: stable/7/sys/kern/kern_descrip.c ============================================================================== --- stable/7/sys/kern/kern_descrip.c Tue Feb 17 21:35:17 2009 (r188733) +++ stable/7/sys/kern/kern_descrip.c Tue Feb 17 21:35:54 2009 (r188734) @@ -1261,7 +1261,7 @@ fpathconf(struct thread *td, struct fpat if (vp != NULL) { int vfslocked; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_SHARED | LK_RETRY, td); error = VOP_PATHCONF(vp, uap->name, td->td_retval); VOP_UNLOCK(vp, 0, td); VFS_UNLOCK_GIANT(vfslocked); Modified: stable/7/sys/kern/vfs_syscalls.c ============================================================================== --- stable/7/sys/kern/vfs_syscalls.c Tue Feb 17 21:35:17 2009 (r188733) +++ stable/7/sys/kern/vfs_syscalls.c Tue Feb 17 21:35:54 2009 (r188734) @@ -296,8 +296,8 @@ kern_statfs(struct thread *td, char *pat int error; struct nameidata nd; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, pathseg, path, td); error = namei(&nd); if (error) return (error); @@ -378,7 +378,7 @@ kern_fstatfs(struct thread *td, int fd, return (error); vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_SHARED | LK_RETRY, td); #ifdef AUDIT AUDIT_ARG(vnode, vp, ARG_VNODE1); #endif @@ -746,7 +746,7 @@ fchdir(td, uap) VREF(vp); fdrop(fp, td); vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_SHARED | LK_RETRY, td); AUDIT_ARG(vnode, vp, ARG_VNODE1); error = change_dir(vp, td); while (!error && (mp = vp->v_mountedhere) != NULL) { @@ -754,7 +754,7 @@ fchdir(td, uap) if (vfs_busy(mp, 0, 0, td)) continue; tvfslocked = VFS_LOCK_GIANT(mp); - error = VFS_ROOT(mp, LK_EXCLUSIVE, &tdp, td); + error = VFS_ROOT(mp, LK_SHARED, &tdp, td); vfs_unbusy(mp, td); if (error) { VFS_UNLOCK_GIANT(tvfslocked); @@ -810,8 +810,8 @@ kern_chdir(struct thread *td, char *path struct vnode *vp; int vfslocked; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1 | MPSAFE, - pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1 | + MPSAFE, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -896,8 +896,8 @@ chroot(td, uap) error = priv_check(td, PRIV_VFS_CHROOT); if (error) return (error); - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - UIO_USERSPACE, uap->path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, UIO_USERSPACE, uap->path, td); error = namei(&nd); if (error) goto error; @@ -1779,7 +1779,7 @@ lseek(td, uap) offset += fp->f_offset; break; case L_XTND: - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_SHARED | LK_RETRY, td); error = VOP_GETATTR(vp, &vattr, cred, td); VOP_UNLOCK(vp, 0, td); if (error) @@ -1936,8 +1936,8 @@ kern_access(struct thread *td, char *pat tmpcred->cr_uid = cred->cr_ruid; tmpcred->cr_groups[0] = cred->cr_rgid; td->td_ucred = tmpcred; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, pathseg, path, td); if ((error = namei(&nd)) != 0) goto out1; vfslocked = NDHASGIANT(&nd); @@ -2308,8 +2308,8 @@ kern_pathconf(struct thread *td, char *p struct nameidata nd; int error, vfslocked; - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); @@ -2360,8 +2360,8 @@ kern_readlink(struct thread *td, char *p struct nameidata nd; int vfslocked; - NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, - pathseg, path, td); + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | + AUDITVNODE1, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); Modified: stable/7/sys/kern/vfs_vnops.c ============================================================================== --- stable/7/sys/kern/vfs_vnops.c Tue Feb 17 21:35:17 2009 (r188733) +++ stable/7/sys/kern/vfs_vnops.c Tue Feb 17 21:35:54 2009 (r188734) @@ -610,7 +610,7 @@ vn_statfile(fp, sb, active_cred, td) int error; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_SHARED | LK_RETRY, td); error = vn_stat(vp, sb, active_cred, fp->f_cred, td); VOP_UNLOCK(vp, 0, td); VFS_UNLOCK_GIANT(vfslocked); From jhb at FreeBSD.org Tue Feb 17 13:59:55 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 14:00:11 2009 Subject: svn commit: r188735 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern security/audit Message-ID: <200902172159.n1HLxsdo028840@svn.freebsd.org> Author: jhb Date: Tue Feb 17 21:59:54 2009 New Revision: 188735 URL: http://svn.freebsd.org/changeset/base/188735 Log: MFC: Use shared vnode locks for auditing vnode arguments. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/vfs_syscalls.c stable/7/sys/security/audit/audit_arg.c Modified: stable/7/sys/kern/vfs_syscalls.c ============================================================================== --- stable/7/sys/kern/vfs_syscalls.c Tue Feb 17 21:35:54 2009 (r188734) +++ stable/7/sys/kern/vfs_syscalls.c Tue Feb 17 21:59:54 2009 (r188735) @@ -2525,7 +2525,7 @@ fchflags(td, uap) return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT - vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY, td); AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); VOP_UNLOCK(fp->f_vnode, 0, td); #endif @@ -2665,7 +2665,7 @@ fchmod(td, uap) return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT - vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY, td); AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); VOP_UNLOCK(fp->f_vnode, 0, td); #endif @@ -2822,7 +2822,7 @@ fchown(td, uap) return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT - vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY, td); AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); VOP_UNLOCK(fp->f_vnode, 0, td); #endif @@ -3035,7 +3035,7 @@ kern_futimes(struct thread *td, int fd, return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT - vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY, td); AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1); VOP_UNLOCK(fp->f_vnode, 0, td); #endif Modified: stable/7/sys/security/audit/audit_arg.c ============================================================================== --- stable/7/sys/security/audit/audit_arg.c Tue Feb 17 21:35:54 2009 (r188734) +++ stable/7/sys/security/audit/audit_arg.c Tue Feb 17 21:59:54 2009 (r188735) @@ -633,7 +633,7 @@ audit_arg_file(struct proc *p, struct fi */ vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); + vn_lock(vp, LK_SHARED | LK_RETRY, curthread); audit_arg_vnode(vp, ARG_VNODE1); VOP_UNLOCK(vp, 0, curthread); VFS_UNLOCK_GIANT(vfslocked); @@ -851,7 +851,7 @@ audit_sysclose(struct thread *td, int fd vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(vp, LK_SHARED | LK_RETRY, td); audit_arg_vnode(vp, ARG_VNODE1); VOP_UNLOCK(vp, 0, td); VFS_UNLOCK_GIANT(vfslocked); From jhb at FreeBSD.org Tue Feb 17 14:46:32 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 14:46:43 2009 Subject: svn commit: r188738 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/hwpmc fs/procfs kern Message-ID: <200902172246.n1HMkUeQ029936@svn.freebsd.org> Author: jhb Date: Tue Feb 17 22:46:30 2009 New Revision: 188738 URL: http://svn.freebsd.org/changeset/base/188738 Log: MFC: Remove unnecessary locking around vn_fullpath(). This also includes closing some races between procfs' /file and execve(2) and using a shared vnode lock for the VOP_GETATTR() in the kern.proc.vmmap sysctl handler. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/hwpmc/hwpmc_mod.c stable/7/sys/fs/procfs/procfs.c stable/7/sys/fs/procfs/procfs_map.c stable/7/sys/kern/kern_descrip.c stable/7/sys/kern/kern_proc.c Modified: stable/7/sys/dev/hwpmc/hwpmc_mod.c ============================================================================== --- stable/7/sys/dev/hwpmc/hwpmc_mod.c Tue Feb 17 22:25:19 2009 (r188737) +++ stable/7/sys/dev/hwpmc/hwpmc_mod.c Tue Feb 17 22:46:30 2009 (r188738) @@ -669,9 +669,7 @@ pmc_getfilename(struct vnode *v, char ** td = curthread; *fullpath = "unknown"; *freepath = NULL; - vn_lock(v, LK_CANRECURSE | LK_EXCLUSIVE | LK_RETRY, td); vn_fullpath(td, v, fullpath, freepath); - VOP_UNLOCK(v, 0, td); } /* Modified: stable/7/sys/fs/procfs/procfs.c ============================================================================== --- stable/7/sys/fs/procfs/procfs.c Tue Feb 17 22:25:19 2009 (r188737) +++ stable/7/sys/fs/procfs/procfs.c Tue Feb 17 22:46:30 2009 (r188738) @@ -70,17 +70,13 @@ procfs_doprocfile(PFS_FILL_ARGS) char *fullpath = "unknown"; char *freepath = NULL; struct vnode *textvp; - int err; + PROC_LOCK(p); textvp = p->p_textvp; - VI_LOCK(textvp); - vholdl(textvp); - err = vn_lock(textvp, LK_EXCLUSIVE | LK_INTERLOCK, td); - vdrop(textvp); - if (err) - return (err); + vhold(textvp); + PROC_UNLOCK(p); vn_fullpath(td, textvp, &fullpath, &freepath); - VOP_UNLOCK(textvp, 0, td); + vdrop(textvp); sbuf_printf(sb, "%s", fullpath); if (freepath) free(freepath, M_TEMP); Modified: stable/7/sys/fs/procfs/procfs_map.c ============================================================================== --- stable/7/sys/fs/procfs/procfs_map.c Tue Feb 17 22:25:19 2009 (r188737) +++ stable/7/sys/fs/procfs/procfs_map.c Tue Feb 17 22:46:30 2009 (r188738) @@ -190,10 +190,9 @@ procfs_doprocmap(PFS_FILL_ARGS) shadow_count = obj->shadow_count; VM_OBJECT_UNLOCK(obj); if (vp != NULL) { - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); vn_fullpath(td, vp, &fullpath, &freepath); - vput(vp); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vrele(vp); VFS_UNLOCK_GIANT(vfslocked); } } else { Modified: stable/7/sys/kern/kern_descrip.c ============================================================================== --- stable/7/sys/kern/kern_descrip.c Tue Feb 17 22:25:19 2009 (r188737) +++ stable/7/sys/kern/kern_descrip.c Tue Feb 17 22:46:30 2009 (r188738) @@ -2836,10 +2836,9 @@ export_vnode_for_sysctl(struct vnode *vp freepath = NULL; fullpath = "-"; FILEDESC_SUNLOCK(fdp); - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); vn_fullpath(curthread, vp, &fullpath, &freepath); - vput(vp); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vrele(vp); VFS_UNLOCK_GIANT(vfslocked); strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path)); if (freepath != NULL) @@ -3001,10 +3000,9 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER freepath = NULL; fullpath = "-"; FILEDESC_SUNLOCK(fdp); - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); vn_fullpath(curthread, vp, &fullpath, &freepath); - vput(vp); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vrele(vp); VFS_UNLOCK_GIANT(vfslocked); strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path)); Modified: stable/7/sys/kern/kern_proc.c ============================================================================== --- stable/7/sys/kern/kern_proc.c Tue Feb 17 22:25:19 2009 (r188737) +++ stable/7/sys/kern/kern_proc.c Tue Feb 17 22:46:30 2009 (r188738) @@ -1475,12 +1475,11 @@ sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_A kve->kve_shadow_count = obj->shadow_count; VM_OBJECT_UNLOCK(obj); if (vp != NULL) { - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, - curthread); vn_fullpath(curthread, vp, &fullpath, &freepath); cred = curthread->td_ucred; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_SHARED | LK_RETRY, curthread); if (VOP_GETATTR(vp, &va, cred, curthread) == 0) { kve->kve_fileid = va.va_fileid; kve->kve_fsid = va.va_fsid; From jhb at FreeBSD.org Tue Feb 17 14:50:00 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Tue Feb 17 14:50:06 2009 Subject: svn commit: r188739 - stable/7/sys/kern Message-ID: <200902172249.n1HMnwAG030037@svn.freebsd.org> Author: jhb Date: Tue Feb 17 22:49:58 2009 New Revision: 188739 URL: http://svn.freebsd.org/changeset/base/188739 Log: The previous MFC only fixed the old kern.proc.vmmap sysctl. Fix the new one as well to not hold the vnode lock for vn_fullpath() and only use a shared vnode lock for VOP_GETATTR(). Modified: stable/7/sys/kern/kern_proc.c Modified: stable/7/sys/kern/kern_proc.c ============================================================================== --- stable/7/sys/kern/kern_proc.c Tue Feb 17 22:46:30 2009 (r188738) +++ stable/7/sys/kern/kern_proc.c Tue Feb 17 22:49:58 2009 (r188739) @@ -1646,12 +1646,11 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_AR kve->kve_shadow_count = obj->shadow_count; VM_OBJECT_UNLOCK(obj); if (vp != NULL) { - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, - curthread); vn_fullpath(curthread, vp, &fullpath, &freepath); cred = curthread->td_ucred; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_SHARED | LK_RETRY, curthread); if (VOP_GETATTR(vp, &va, cred, curthread) == 0) { kve->kve_fileid = va.va_fileid; kve->kve_fsid = va.va_fsid; From peterjeremy at optushome.com.au Tue Feb 17 16:30:14 2009 From: peterjeremy at optushome.com.au (Peter Jeremy) Date: Tue Feb 17 16:30:26 2009 Subject: svn commit: r188514 - in stable/7/sys: . contrib/pf dev/cxgb libkern In-Reply-To: <200902121437.n1CEbwUe058325@svn.freebsd.org> References: <200902121437.n1CEbwUe058325@svn.freebsd.org> Message-ID: <20090218001533.GA3214@server.vk2pj.dyndns.org> On 2009-Feb-12 14:37:58 +0000, John Baldwin wrote: >Log: > MFC: Add simple locking for the in-kernel iconv code. This breaks building LIBICONV: Given a config file comprising include GENERIC options LIBICONV you get: cc -c -O2 -frename-registers -pipe -fno-strict-aliasing -march=nocona -std=c99 -g -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual -Wundef -Wno-pointer-sign -fformat-extensions -nostdinc -I. -I/home/pjeremy/xxx/src/sys -I/home/pjeremy/xxx/src/sys/contrib/altq -D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global.h -fno-common -finline-limit=8000 --param inline-unit-growth=100 --param large-function-growth=1000 -mcmodel=kernel -mno-red-zone -mfpmath=387 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -msoft-float -fno-asynchronous-unwind-tables -ffreestanding -Werror /home/pjeremy/xxx/src/sys/libkern/iconv.c /home/pjeremy/xxx/src/sys/libkern/iconv.c: In function 'iconv_mod_unload': /home/pjeremy/xxx/src/sys/libkern/iconv.c:92: error: 'curthread' undeclared (first use in this function) /home/pjeremy/xxx/src/sys/libkern/iconv.c:92: error: (Each undeclared identifier is reported only once /home/pjeremy/xxx/src/sys/libkern/iconv.c:92: error: for each function it appears in.) /home/pjeremy/xxx/src/sys/libkern/iconv.c: In function 'iconv_sysctl_add': /home/pjeremy/xxx/src/sys/libkern/iconv.c:401: error: 'curthread' undeclared (first use in this function) /home/pjeremy/xxx/src/sys/libkern/iconv.c: In function 'iconv_converter_handler': /home/pjeremy/xxx/src/sys/libkern/iconv.c:452: error: 'curthread' undeclared (first use in this function) *** Error code 1 Stop in /var/obj/home/pjeremy/xxx/src/sys/LIBICONV. I think you need to include to get curthread. (This should probably be documented in sx(9)). -- Peter Jeremy -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 196 bytes Desc: not available Url : http://lists.freebsd.org/pipermail/svn-src-stable-7/attachments/20090218/139802c1/attachment.pgp From bms at incunabulum.net Wed Feb 18 00:18:10 2009 From: bms at incunabulum.net (Bruce Simpson) Date: Wed Feb 18 00:18:27 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat In-Reply-To: <200902171957.n1HJvqk8026145@svn.freebsd.org> References: <200902171957.n1HJvqk8026145@svn.freebsd.org> Message-ID: <499BC43B.6030701@incunabulum.net> John Baldwin wrote: > Author: jhb > Date: Tue Feb 17 19:57:52 2009 > New Revision: 188727 > URL: http://svn.freebsd.org/changeset/base/188727 > > Log: > MFC: Rework the lifetime management of the kernel implementation of POSIX > semaphores. Specifically, semaphores are now represented as new file > descriptor type that is set to close on exec. This removes the need for > all of the manual process reference counting (and fork, exec, and exit > event handlers) as the normal file descriptor operations handle all of > that for us nicely. It is also suggested as one possible implementation > in the spec and at least one other OS (OS X) uses this approach. FYI: This change *may* fix Python 2.6's 'multiprocessing' module on FreeBSD 7-STABLE, which is known to have problems there; it depends on POSIX semaphores to synchronize its IPC between different fork()'s of the Python interpreter. If anyone else has an interest in ths they may wish to test, if not, I will try to get around to it eventually. cheers BMS From bms at incunabulum.net Wed Feb 18 06:16:40 2009 From: bms at incunabulum.net (Bruce Simpson) Date: Wed Feb 18 06:17:02 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat In-Reply-To: <499BC43B.6030701@incunabulum.net> References: <200902171957.n1HJvqk8026145@svn.freebsd.org> <499BC43B.6030701@incunabulum.net> Message-ID: <499C1843.90008@incunabulum.net> Bruce Simpson wrote: > .... > FYI: > This change *may* fix Python 2.6's 'multiprocessing' module on FreeBSD > 7-STABLE, which is known to have problems there; it depends on POSIX > semaphores to synchronize its IPC between different fork()'s of the > Python interpreter. > If anyone else has an interest in ths they may wish to test, if not, I > will try to get around to it eventually. I just tested this and Python 2.5 still dumps core in sem_open() when called from semlock_new() in _multiprocessing.so, this is with the most recent back-port of multiprocessing to Python 2.5: http://pypi.python.org/pypi/multiprocessing cheers BMS From jhb at freebsd.org Wed Feb 18 07:10:51 2009 From: jhb at freebsd.org (John Baldwin) Date: Wed Feb 18 07:11:03 2009 Subject: svn commit: r188514 - in stable/7/sys: . contrib/pf dev/cxgb libkern In-Reply-To: <20090218001533.GA3214@server.vk2pj.dyndns.org> References: <200902121437.n1CEbwUe058325@svn.freebsd.org> <20090218001533.GA3214@server.vk2pj.dyndns.org> Message-ID: <200902180948.52908.jhb@freebsd.org> On Tuesday 17 February 2009 7:15:33 pm Peter Jeremy wrote: > On 2009-Feb-12 14:37:58 +0000, John Baldwin wrote: > >Log: > > MFC: Add simple locking for the in-kernel iconv code. > > This breaks building LIBICONV: Given a config file comprising > include GENERIC > options LIBICONV > > you get: > cc -c -O2 -frename-registers -pipe -fno-strict-aliasing -march=nocona -std=c99 -g -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual -Wundef -Wno-pointer-sign -fformat-extensions -nostdinc -I. -I/home/pjeremy/xxx/src/sys -I/home/pjeremy/xxx/src/sys/contrib/altq -D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global.h -fno-common -finline-limit=8000 --param inline-unit-growth=100 --param large-function-growth=1000 -mcmodel=kernel -mno-red-zone -mfpmath=387 -mno-sse -mno-sse2 -mno-mmx -mno-3dnow -msoft-float -fno-asynchronous-unwind-tables -ffreestanding -Werror /home/pjeremy/xxx/src/sys/libkern/iconv.c > /home/pjeremy/xxx/src/sys/libkern/iconv.c: In function 'iconv_mod_unload': > /home/pjeremy/xxx/src/sys/libkern/iconv.c:92: error: 'curthread' undeclared (first use in this function) > /home/pjeremy/xxx/src/sys/libkern/iconv.c:92: error: (Each undeclared identifier is reported only once > /home/pjeremy/xxx/src/sys/libkern/iconv.c:92: error: for each function it appears in.) > /home/pjeremy/xxx/src/sys/libkern/iconv.c: In function 'iconv_sysctl_add': > /home/pjeremy/xxx/src/sys/libkern/iconv.c:401: error: 'curthread' undeclared (first use in this function) > /home/pjeremy/xxx/src/sys/libkern/iconv.c: In function 'iconv_converter_handler': > /home/pjeremy/xxx/src/sys/libkern/iconv.c:452: error: 'curthread' undeclared (first use in this function) > *** Error code 1 > > Stop in /var/obj/home/pjeremy/xxx/src/sys/LIBICONV. > > I think you need to include to get curthread. (This should > probably be documented in sx(9)). This was fixed by the MFC to yesterday to include in the _KERNEL section. I had missed this since the build worked fine with LINT and the module build. -- John Baldwin From jhb at freebsd.org Wed Feb 18 07:10:59 2009 From: jhb at freebsd.org (John Baldwin) Date: Wed Feb 18 07:11:24 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat In-Reply-To: <499BC43B.6030701@incunabulum.net> References: <200902171957.n1HJvqk8026145@svn.freebsd.org> <499BC43B.6030701@incunabulum.net> Message-ID: <200902180949.32691.jhb@freebsd.org> On Wednesday 18 February 2009 3:18:03 am Bruce Simpson wrote: > John Baldwin wrote: > > Author: jhb > > Date: Tue Feb 17 19:57:52 2009 > > New Revision: 188727 > > URL: http://svn.freebsd.org/changeset/base/188727 > > > > Log: > > MFC: Rework the lifetime management of the kernel implementation of POSIX > > semaphores. Specifically, semaphores are now represented as new file > > descriptor type that is set to close on exec. This removes the need for > > all of the manual process reference counting (and fork, exec, and exit > > event handlers) as the normal file descriptor operations handle all of > > that for us nicely. It is also suggested as one possible implementation > > in the spec and at least one other OS (OS X) uses this approach. > > FYI: > This change *may* fix Python 2.6's 'multiprocessing' module on FreeBSD > 7-STABLE, which is known to have problems there; it depends on POSIX > semaphores to synchronize its IPC between different fork()'s of the > Python interpreter. > > If anyone else has an interest in ths they may wish to test, if not, I > will try to get around to it eventually. When Kris tested it, it made things significantly better. I'm not sure if it resolved all the issues though. -- John Baldwin From jhb at freebsd.org Wed Feb 18 07:11:04 2009 From: jhb at freebsd.org (John Baldwin) Date: Wed Feb 18 07:11:57 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat In-Reply-To: <499C1843.90008@incunabulum.net> References: <200902171957.n1HJvqk8026145@svn.freebsd.org> <499BC43B.6030701@incunabulum.net> <499C1843.90008@incunabulum.net> Message-ID: <200902181005.28625.jhb@freebsd.org> On Wednesday 18 February 2009 9:16:35 am Bruce Simpson wrote: > Bruce Simpson wrote: > > .... > > FYI: > > This change *may* fix Python 2.6's 'multiprocessing' module on FreeBSD > > 7-STABLE, which is known to have problems there; it depends on POSIX > > semaphores to synchronize its IPC between different fork()'s of the > > Python interpreter. > > If anyone else has an interest in ths they may wish to test, if not, I > > will try to get around to it eventually. > > I just tested this and Python 2.5 still dumps core in sem_open() when > called from semlock_new() in _multiprocessing.so, this is with the most > recent back-port of multiprocessing to Python 2.5: > http://pypi.python.org/pypi/multiprocessing Do you have a core dump with symbols? If so, can you get the trace? -- John Baldwin From bms at incunabulum.net Wed Feb 18 07:17:54 2009 From: bms at incunabulum.net (Bruce Simpson) Date: Wed Feb 18 07:18:07 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat In-Reply-To: <200902181005.28625.jhb@freebsd.org> References: <200902171957.n1HJvqk8026145@svn.freebsd.org> <499BC43B.6030701@incunabulum.net> <499C1843.90008@incunabulum.net> <200902181005.28625.jhb@freebsd.org> Message-ID: <499C269D.7030406@incunabulum.net> John Baldwin wrote: > ... > >> I just tested this and Python 2.5 still dumps core in sem_open() when >> called from semlock_new() in _multiprocessing.so, this is with the most >> recent back-port of multiprocessing to Python 2.5: >> http://pypi.python.org/pypi/multiprocessing >> > > Do you have a core dump with symbols? If so, can you get the trace? > Here you are... have runtime ELF symbols but no line numbers. I had to comment out some stuff in its "setup.py" to persuade the _multiprocessing C shim to use sem_open() (remove freebsd7 and/or freebsd8 from that file before "python setup.py config" and "python setup.py build"). I was running the Doc/includes/mp_benchmarks.py file which ships with multiprocessing. multiprocessing is part of Python 2.6 base now, so likely what is Not OK in the backport, would need to be forward-ported when it is happy with sem_open() in Python 2.5. cheers BMS -------------- next part -------------- (gdb) bt #0 0x0000000800a9ec7c in ksem_open () from /lib/libc.so.7 #1 0x0000000800a9504d in sem_open () from /lib/libc.so.7 #2 0x000000080131842c in semlock_new () from /usr/local/lib/python2.5/site-packages/multiprocessing-2.6.1.1-py2.5-freebsd-7.1-STABLE-amd64.egg/multiprocessing/_multiprocessing.so #3 0x000000000044bc73 in PyType_IsSubtype () #4 0x00000000004151d3 in PyObject_Call () #5 0x000000000046e55b in PyEval_EvalFrameEx () #6 0x000000000047174c in PyEval_EvalCodeEx () #7 0x00000000004afbda in PyClassMethod_New () #8 0x00000000004151d3 in PyObject_Call () #9 0x000000000041ae0d in PyClass_IsSubclass () #10 0x00000000004151d3 in PyObject_Call () #11 0x000000000046e55b in PyEval_EvalFrameEx () #12 0x000000000047174c in PyEval_EvalCodeEx () #13 0x00000000004afbda in PyClassMethod_New () #14 0x00000000004151d3 in PyObject_Call () #15 0x000000000041ae0d in PyClass_IsSubclass () #16 0x00000000004151d3 in PyObject_Call () #17 0x000000000044f938 in _PyType_Lookup () #18 0x000000000044bcb8 in PyType_IsSubtype () #19 0x00000000004151d3 in PyObject_Call () #20 0x000000000046e55b in PyEval_EvalFrameEx () #21 0x000000000047174c in PyEval_EvalCodeEx () #22 0x00000000004afbda in PyClassMethod_New () #23 0x00000000004151d3 in PyObject_Call () #24 0x000000000041ae0d in PyClass_IsSubclass () #25 0x00000000004151d3 in PyObject_Call () #26 0x000000000044f938 in _PyType_Lookup () #27 0x000000000044bcb8 in PyType_IsSubtype () #28 0x00000000004151d3 in PyObject_Call () #29 0x000000000046e55b in PyEval_EvalFrameEx () #30 0x000000000047174c in PyEval_EvalCodeEx () #31 0x000000000046fef4 in PyEval_EvalFrameEx () #32 0x00000000004706fd in PyEval_EvalFrameEx () #33 0x000000000047174c in PyEval_EvalCodeEx () #34 0x0000000000471862 in PyEval_EvalCode () #35 0x000000000048ae02 in Py_CompileString () #36 0x000000000048aed6 in PyRun_FileExFlags () #37 0x000000000048c373 in PyRun_SimpleFileExFlags () #38 0x0000000000412219 in Py_Main () #39 0x0000000000411897 in main () From jhb at freebsd.org Wed Feb 18 07:55:06 2009 From: jhb at freebsd.org (John Baldwin) Date: Wed Feb 18 07:55:13 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat In-Reply-To: <499C269D.7030406@incunabulum.net> References: <200902171957.n1HJvqk8026145@svn.freebsd.org> <200902181005.28625.jhb@freebsd.org> <499C269D.7030406@incunabulum.net> Message-ID: <200902181054.35709.jhb@freebsd.org> On Wednesday 18 February 2009 10:17:49 am Bruce Simpson wrote: > John Baldwin wrote: > > ... > > > >> I just tested this and Python 2.5 still dumps core in sem_open() when > >> called from semlock_new() in _multiprocessing.so, this is with the most > >> recent back-port of multiprocessing to Python 2.5: > >> http://pypi.python.org/pypi/multiprocessing > >> > > > > Do you have a core dump with symbols? If so, can you get the trace? > > > > Here you are... have runtime ELF symbols but no line numbers. > > I had to comment out some stuff in its "setup.py" to persuade the > _multiprocessing C shim to use sem_open() (remove freebsd7 and/or > freebsd8 from that file before "python setup.py config" and "python > setup.py build"). > > I was running the Doc/includes/mp_benchmarks.py file which ships with > multiprocessing. > > multiprocessing is part of Python 2.6 base now, so likely what is Not OK > in the backport, would need to be forward-ported when it is happy with > sem_open() in Python 2.5. Hmm, by symbols I meant having things built with debug symbols (i.e. "-g"). Also, do you have 'sem.ko' loaded? The only reason I can think of why you would get a core dump in ksem_open() itself would be if you got a SIGSYS because the module wasn't loaded. -- John Baldwin From jamie at FreeBSD.org Wed Feb 18 12:12:10 2009 From: jamie at FreeBSD.org (Jamie Gritton) Date: Wed Feb 18 12:12:29 2009 Subject: svn commit: r188761 - in stable/7: lib/libc lib/libc/string lib/libc/sys sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/net sys/netinet sys/netinet6 sys/sys Message-ID: <200902182012.n1IKC88S073575@svn.freebsd.org> Author: jamie Date: Wed Feb 18 20:12:08 2009 New Revision: 188761 URL: http://svn.freebsd.org/changeset/base/188761 Log: MFC: r188144: Standardize the various prison_foo_ip[46] functions and prison_if to return zero on success and an error code otherwise. The possible errors are EADDRNOTAVAIL if an address being checked for doesn't match the prison, and EAFNOSUPPORT if the prison doesn't have any addresses in that address family. For most callers of these functions, use the returned error code instead of e.g. a hard-coded EADDRNOTAVAIL or EINVAL. Always include a jailed() check in these functions, where a non-jailed cred always returns success (and makes no changes). Remove the explicit jailed() checks that preceded many of the function calls. r188146: Don't allow creating a socket with a protocol family that the current jail doesn't support. This involves a new function prison_check_af, like prison_check_ip[46] but that checks only the family. With this change, most of the errors generated by jailed sockets shouldn't ever occur, at least until jails are changeable. r188148: Remove redundant calls of prison_local_ip4 in in_pcbbind_setup, and of prison_local_ip6 in in6_pcbbind. r188149: Call prison_if from rtm_get_jailed, instead of splitting it out into prison_check_ip4 and prison_check_ip6. As prison_if includes a jailed() check, remove that check before calling rtm_get_jailed. r188151: Don't bother null-checking the thread pointer before the prison checks in udp6_connect (td is already dereferenced elsewhere without such a check). This makes the conversion from a sockaddr to a sockaddr_in6 always happen, so convert once at the beginning of the function rather than twice in the middle. Approved by: bz (mentor) Modified: stable/7/lib/libc/ (props changed) stable/7/lib/libc/string/ffsll.c (props changed) stable/7/lib/libc/string/flsll.c (props changed) stable/7/lib/libc/sys/send.2 stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_jail.c stable/7/sys/kern/uipc_socket.c stable/7/sys/net/if.c stable/7/sys/net/rtsock.c stable/7/sys/netinet/in.c stable/7/sys/netinet/in_pcb.c stable/7/sys/netinet/raw_ip.c stable/7/sys/netinet/tcp_usrreq.c stable/7/sys/netinet/udp_usrreq.c stable/7/sys/netinet6/in6.c stable/7/sys/netinet6/in6_pcb.c stable/7/sys/netinet6/in6_src.c stable/7/sys/netinet6/raw_ip6.c stable/7/sys/netinet6/udp6_usrreq.c stable/7/sys/sys/jail.h Modified: stable/7/lib/libc/sys/send.2 ============================================================================== --- stable/7/lib/libc/sys/send.2 Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/lib/libc/sys/send.2 Wed Feb 18 20:12:08 2009 (r188761) @@ -28,7 +28,7 @@ .\" From: @(#)send.2 8.2 (Berkeley) 2/21/94 .\" $FreeBSD$ .\" -.Dd September 13, 2006 +.Dd February 5, 2009 .Dt SEND 2 .Os .Sh NAME @@ -190,7 +190,7 @@ receiver is not listening on the remote The remote host was down. .It Bq Er ENETDOWN The remote network was down. -.It Bq Er EPERM +.It Bq Er EADDRNOTAVAIL The process using a .Dv SOCK_RAW socket was jailed and the source Modified: stable/7/sys/kern/kern_jail.c ============================================================================== --- stable/7/sys/kern/kern_jail.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/kern/kern_jail.c Wed Feb 18 20:12:08 2009 (r188761) @@ -230,7 +230,7 @@ prison_check_conflicting_ips(struct pris if ((p->pr_ip4s >= 1 && pr->pr_ip4s > 1) || (p->pr_ip4s > 1 && pr->pr_ip4s >= 1)) { for (i = 0; i < p->pr_ip4s; i++) { - if (_prison_check_ip4(pr, &p->pr_ip4[i])) + if (_prison_check_ip4(pr, &p->pr_ip4[i]) == 0) return (EINVAL); } } @@ -239,7 +239,7 @@ prison_check_conflicting_ips(struct pris if ((p->pr_ip6s >= 1 && pr->pr_ip6s > 1) || (p->pr_ip6s > 1 && pr->pr_ip6s >= 1)) { for (i = 0; i < p->pr_ip6s; i++) { - if (_prison_check_ip6(pr, &p->pr_ip6[i])) + if (_prison_check_ip6(pr, &p->pr_ip6[i]) == 0) return (EINVAL); } } @@ -841,9 +841,10 @@ prison_proc_free(struct prison *pr) * Pass back primary IPv4 address of this jail. * * If not jailed return success but do not alter the address. Caller has to - * make sure to intialize it correctly (INADDR_ANY). + * make sure to intialize it correctly (e.g. INADDR_ANY). * - * Returns 0 on success, 1 on error. Address returned in NBO. + * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4. + * Address returned in NBO. */ int prison_get_ip4(struct ucred *cred, struct in_addr *ia) @@ -857,7 +858,7 @@ prison_get_ip4(struct ucred *cred, struc return (0); if (cred->cr_prison->pr_ip4 == NULL) - return (1); + return (EAFNOSUPPORT); ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; return (0); @@ -867,8 +868,9 @@ prison_get_ip4(struct ucred *cred, struc * Make sure our (source) address is set to something meaningful to this * jail. * - * Returns 0 on success, 1 on error. Address passed in in NBO and returned - * in NBO. + * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if + * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv4. + * Address passed in in NBO and returned in NBO. */ int prison_local_ip4(struct ucred *cred, struct in_addr *ia) @@ -881,7 +883,7 @@ prison_local_ip4(struct ucred *cred, str if (!jailed(cred)) return (0); if (cred->cr_prison->pr_ip4 == NULL) - return (1); + return (EAFNOSUPPORT); ia0.s_addr = ntohl(ia->s_addr); if (ia0.s_addr == INADDR_LOOPBACK) { @@ -889,25 +891,23 @@ prison_local_ip4(struct ucred *cred, str return (0); } - /* - * In case there is only 1 IPv4 address, bind directly. - */ - if (ia0.s_addr == INADDR_ANY && cred->cr_prison->pr_ip4s == 1) { - ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; + if (ia0.s_addr == INADDR_ANY) { + /* + * In case there is only 1 IPv4 address, bind directly. + */ + if (cred->cr_prison->pr_ip4s == 1) + ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; return (0); } - if (ia0.s_addr == INADDR_ANY || prison_check_ip4(cred, ia)) - return (0); - - return (1); + return (_prison_check_ip4(cred->cr_prison, ia)); } /* * Rewrite destination address in case we will connect to loopback address. * - * Returns 0 on success, 1 on error. Address passed in in NBO and returned - * in NBO. + * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4. + * Address passed in in NBO and returned in NBO. */ int prison_remote_ip4(struct ucred *cred, struct in_addr *ia) @@ -919,7 +919,8 @@ prison_remote_ip4(struct ucred *cred, st if (!jailed(cred)) return (0); if (cred->cr_prison->pr_ip4 == NULL) - return (1); + return (EAFNOSUPPORT); + if (ntohl(ia->s_addr) == INADDR_LOOPBACK) { ia->s_addr = cred->cr_prison->pr_ip4[0].s_addr; return (0); @@ -932,23 +933,22 @@ prison_remote_ip4(struct ucred *cred, st } /* - * Check if given address belongs to the jail referenced by cred. + * Check if given address belongs to the jail referenced by cred/prison. * - * Returns 1 if address belongs to jail, 0 if not. Address passed in in NBO. + * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if + * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv4. + * Address passed in in NBO. */ static int _prison_check_ip4(struct prison *pr, struct in_addr *ia) { int i, a, z, d; - if (pr->pr_ip4 == NULL) - return (0); - /* * Check the primary IP. */ if (pr->pr_ip4[0].s_addr == ia->s_addr) - return (1); + return (0); /* * All the other IPs are sorted so we can do a binary search. @@ -963,9 +963,10 @@ _prison_check_ip4(struct prison *pr, str else if (d < 0) a = i + 1; else - return (1); + return (0); } - return (0); + + return (EADDRNOTAVAIL); } int @@ -976,7 +977,9 @@ prison_check_ip4(struct ucred *cred, str KASSERT(ia != NULL, ("%s: ia is NULL", __func__)); if (!jailed(cred)) - return (1); + return (0); + if (cred->cr_prison->pr_ip4 == NULL) + return (EAFNOSUPPORT); return (_prison_check_ip4(cred->cr_prison, ia)); } @@ -987,9 +990,9 @@ prison_check_ip4(struct ucred *cred, str * Pass back primary IPv6 address for this jail. * * If not jailed return success but do not alter the address. Caller has to - * make sure to intialize it correctly (IN6ADDR_ANY_INIT). + * make sure to intialize it correctly (e.g. IN6ADDR_ANY_INIT). * - * Returns 0 on success, 1 on error. + * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6. */ int prison_get_ip6(struct ucred *cred, struct in6_addr *ia6) @@ -1001,7 +1004,8 @@ prison_get_ip6(struct ucred *cred, struc if (!jailed(cred)) return (0); if (cred->cr_prison->pr_ip6 == NULL) - return (1); + return (EAFNOSUPPORT); + bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr)); return (0); } @@ -1012,7 +1016,8 @@ prison_get_ip6(struct ucred *cred, struc * v6only should be set based on (inp->inp_flags & IN6P_IPV6_V6ONLY != 0) * when needed while binding. * - * Returns 0 on success, 1 on error. + * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if + * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv6. */ int prison_local_ip6(struct ucred *cred, struct in6_addr *ia6, int v6only) @@ -1024,32 +1029,32 @@ prison_local_ip6(struct ucred *cred, str if (!jailed(cred)) return (0); if (cred->cr_prison->pr_ip6 == NULL) - return (1); + return (EAFNOSUPPORT); + if (IN6_IS_ADDR_LOOPBACK(ia6)) { bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr)); return (0); } - /* - * In case there is only 1 IPv6 address, and v6only is true, then - * bind directly. - */ - if (v6only != 0 && IN6_IS_ADDR_UNSPECIFIED(ia6) && - cred->cr_prison->pr_ip6s == 1) { - bcopy(&cred->cr_prison->pr_ip6[0], ia6, - sizeof(struct in6_addr)); + if (IN6_IS_ADDR_UNSPECIFIED(ia6)) { + /* + * In case there is only 1 IPv6 address, and v6only is true, + * then bind directly. + */ + if (v6only != 0 && cred->cr_prison->pr_ip6s == 1) + bcopy(&cred->cr_prison->pr_ip6[0], ia6, + sizeof(struct in6_addr)); return (0); } - if (IN6_IS_ADDR_UNSPECIFIED(ia6) || prison_check_ip6(cred, ia6)) - return (0); - return (1); + + return (_prison_check_ip6(cred->cr_prison, ia6)); } /* * Rewrite destination address in case we will connect to loopback address. * - * Returns 0 on success, 1 on error. + * Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6. */ int prison_remote_ip6(struct ucred *cred, struct in6_addr *ia6) @@ -1061,7 +1066,8 @@ prison_remote_ip6(struct ucred *cred, st if (!jailed(cred)) return (0); if (cred->cr_prison->pr_ip6 == NULL) - return (1); + return (EAFNOSUPPORT); + if (IN6_IS_ADDR_LOOPBACK(ia6)) { bcopy(&cred->cr_prison->pr_ip6[0], ia6, sizeof(struct in6_addr)); @@ -1075,23 +1081,21 @@ prison_remote_ip6(struct ucred *cred, st } /* - * Check if given address belongs to the jail referenced by cred. + * Check if given address belongs to the jail referenced by cred/prison. * - * Returns 1 if address belongs to jail, 0 if not. + * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if + * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow IPv6. */ static int _prison_check_ip6(struct prison *pr, struct in6_addr *ia6) { int i, a, z, d; - if (pr->pr_ip6 == NULL) - return (0); - /* * Check the primary IP. */ if (IN6_ARE_ADDR_EQUAL(&pr->pr_ip6[0], ia6)) - return (1); + return (0); /* * All the other IPs are sorted so we can do a binary search. @@ -1106,9 +1110,10 @@ _prison_check_ip6(struct prison *pr, str else if (d < 0) a = i + 1; else - return (1); + return (0); } - return (0); + + return (EADDRNOTAVAIL); } int @@ -1119,18 +1124,63 @@ prison_check_ip6(struct ucred *cred, str KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__)); if (!jailed(cred)) - return (1); + return (0); + if (cred->cr_prison->pr_ip6 == NULL) + return (EAFNOSUPPORT); return (_prison_check_ip6(cred->cr_prison, ia6)); } #endif /* + * Check if a jail supports the given address family. + * + * Returns 0 if not jailed or the address family is supported, EAFNOSUPPORT + * if not. + */ +int +prison_check_af(struct ucred *cred, int af) +{ + int error; + + KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); + + + if (!jailed(cred)) + return (0); + + error = 0; + switch (af) + { +#ifdef INET + case AF_INET: + if (cred->cr_prison->pr_ip4 == NULL) + error = EAFNOSUPPORT; + break; +#endif +#ifdef INET6 + case AF_INET6: + if (cred->cr_prison->pr_ip6 == NULL) + error = EAFNOSUPPORT; + break; +#endif + case AF_LOCAL: + case AF_ROUTE: + break; + default: + if (jail_socket_unixiproute_only) + error = EAFNOSUPPORT; + } + return (error); +} + +/* * Check if given address belongs to the jail referenced by cred (wrapper to * prison_check_ip[46]). * - * Returns 1 if address belongs to jail, 0 if not. IPv4 Address passed in in - * NBO. + * Returns 0 if not jailed or if address belongs to jail, EADDRNOTAVAIL if + * the address doesn't belong, or EAFNOSUPPORT if the jail doesn't allow + * the address family. IPv4 Address passed in in NBO. */ int prison_if(struct ucred *cred, struct sockaddr *sa) @@ -1141,35 +1191,31 @@ prison_if(struct ucred *cred, struct soc #ifdef INET6 struct sockaddr_in6 *sai6; #endif - int ok; + int error; KASSERT(cred != NULL, ("%s: cred is NULL", __func__)); KASSERT(sa != NULL, ("%s: sa is NULL", __func__)); - ok = 0; - switch(sa->sa_family) + error = 0; + switch (sa->sa_family) { #ifdef INET case AF_INET: sai = (struct sockaddr_in *)sa; - if (prison_check_ip4(cred, &sai->sin_addr)) - ok = 1; + error = prison_check_ip4(cred, &sai->sin_addr); break; - #endif #ifdef INET6 case AF_INET6: sai6 = (struct sockaddr_in6 *)sa; - if (prison_check_ip6(cred, (struct in6_addr *)&sai6->sin6_addr)) - ok = 1; + error = prison_check_ip6(cred, &sai6->sin6_addr); break; - #endif default: - if (!jail_socket_unixiproute_only) - ok = 1; + if (jailed(cred) && jail_socket_unixiproute_only) + error = EAFNOSUPPORT; } - return (ok); + return (error); } /* Modified: stable/7/sys/kern/uipc_socket.c ============================================================================== --- stable/7/sys/kern/uipc_socket.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/kern/uipc_socket.c Wed Feb 18 20:12:08 2009 (r188761) @@ -345,15 +345,8 @@ socreate(int dom, struct socket **aso, i prp->pr_usrreqs->pru_attach == pru_attach_notsupp) return (EPROTONOSUPPORT); - if (jailed(cred) && jail_socket_unixiproute_only && - prp->pr_domain->dom_family != PF_LOCAL && - prp->pr_domain->dom_family != PF_INET && -#ifdef INET6 - prp->pr_domain->dom_family != PF_INET6 && -#endif - prp->pr_domain->dom_family != PF_ROUTE) { + if (prison_check_af(cred, prp->pr_domain->dom_family) != 0) return (EPROTONOSUPPORT); - } if (prp->pr_type != type) return (EPROTOTYPE); Modified: stable/7/sys/net/if.c ============================================================================== --- stable/7/sys/net/if.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/net/if.c Wed Feb 18 20:12:08 2009 (r188761) @@ -2196,8 +2196,7 @@ again: TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { struct sockaddr *sa = ifa->ifa_addr; - if (jailed(curthread->td_ucred) && - !prison_if(curthread->td_ucred, sa)) + if (prison_if(curthread->td_ucred, sa) != 0) continue; addrs++; #ifdef COMPAT_43 Modified: stable/7/sys/net/rtsock.c ============================================================================== --- stable/7/sys/net/rtsock.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/net/rtsock.c Wed Feb 18 20:12:08 2009 (r188761) @@ -329,55 +329,48 @@ rtm_get_jailed(struct rt_addrinfo *info, struct rtentry *rt, union sockaddr_union *saun, struct ucred *cred) { + /* First, see if the returned address is part of the jail. */ + if (prison_if(cred, rt->rt_ifa->ifa_addr) == 0) { + info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; + return (0); + } + switch (info->rti_info[RTAX_DST]->sa_family) { #ifdef INET case AF_INET: { struct in_addr ia; + struct ifaddr *ifa; + int found; + found = 0; /* - * 1. Check if the returned address is part of the jail. + * Try to find an address on the given outgoing interface + * that belongs to the jail. */ - ia = ((struct sockaddr_in *)rt->rt_ifa->ifa_addr)->sin_addr; - if (prison_check_ip4(cred, &ia) != 0) { - info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; - - } else { - struct ifaddr *ifa; - int found; - - found = 0; - + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + struct sockaddr *sa; + sa = ifa->ifa_addr; + if (sa->sa_family != AF_INET) + continue; + ia = ((struct sockaddr_in *)sa)->sin_addr; + if (prison_check_ip4(cred, &ia) == 0) { + found = 1; + break; + } + } + if (!found) { /* - * 2. Try to find an address on the given outgoing - * interface that belongs to the jail. + * As a last resort return the 'default' jail address. */ - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - struct sockaddr *sa; - sa = ifa->ifa_addr; - if (sa->sa_family != AF_INET) - continue; - ia = ((struct sockaddr_in *)sa)->sin_addr; - if (prison_check_ip4(cred, &ia) != 0) { - found = 1; - break; - } - } - if (!found) { - /* - * 3. As a last resort return the 'default' - * jail address. - */ - if (prison_get_ip4(cred, &ia) != 0) - return (ESRCH); - } - bzero(&saun->sin, sizeof(struct sockaddr_in)); - saun->sin.sin_len = sizeof(struct sockaddr_in); - saun->sin.sin_family = AF_INET; - saun->sin.sin_addr.s_addr = ia.s_addr; - info->rti_info[RTAX_IFA] = - (struct sockaddr *)&saun->sin; + if (prison_get_ip4(cred, &ia) != 0) + return (ESRCH); } + bzero(&saun->sin, sizeof(struct sockaddr_in)); + saun->sin.sin_len = sizeof(struct sockaddr_in); + saun->sin.sin_family = AF_INET; + saun->sin.sin_addr.s_addr = ia.s_addr; + info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin; break; } #endif @@ -385,54 +378,40 @@ rtm_get_jailed(struct rt_addrinfo *info, case AF_INET6: { struct in6_addr ia6; + struct ifaddr *ifa; + int found; + found = 0; /* - * 1. Check if the returned address is part of the jail. + * Try to find an address on the given outgoing interface + * that belongs to the jail. */ - bcopy(&((struct sockaddr_in6 *)rt->rt_ifa->ifa_addr)->sin6_addr, - &ia6, sizeof(struct in6_addr)); - if (prison_check_ip6(cred, &ia6) != 0) { - info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr; - } else { - struct ifaddr *ifa; - int found; - - found = 0; - + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + struct sockaddr *sa; + sa = ifa->ifa_addr; + if (sa->sa_family != AF_INET6) + continue; + bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr, + &ia6, sizeof(struct in6_addr)); + if (prison_check_ip6(cred, &ia6) == 0) { + found = 1; + break; + } + } + if (!found) { /* - * 2. Try to find an address on the given outgoing - * interface that belongs to the jail. + * As a last resort return the 'default' jail address. */ - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - struct sockaddr *sa; - sa = ifa->ifa_addr; - if (sa->sa_family != AF_INET6) - continue; - bcopy(&((struct sockaddr_in6 *)sa)->sin6_addr, - &ia6, sizeof(struct in6_addr)); - if (prison_check_ip6(cred, &ia6) != 0) { - found = 1; - break; - } - } - if (!found) { - /* - * 3. As a last resort return the 'default' - * jail address. - */ - if (prison_get_ip6(cred, &ia6) != 0) - return (ESRCH); - } - bzero(&saun->sin6, sizeof(struct sockaddr_in6)); - saun->sin6.sin6_len = sizeof(struct sockaddr_in6); - saun->sin6.sin6_family = AF_INET6; - bcopy(&ia6, &saun->sin6.sin6_addr, - sizeof(struct in6_addr)); - if (sa6_recoverscope(&saun->sin6) != 0) + if (prison_get_ip6(cred, &ia6) != 0) return (ESRCH); - info->rti_info[RTAX_IFA] = - (struct sockaddr *)&saun->sin6; } + bzero(&saun->sin6, sizeof(struct sockaddr_in6)); + saun->sin6.sin6_len = sizeof(struct sockaddr_in6); + saun->sin6.sin6_family = AF_INET6; + bcopy(&ia6, &saun->sin6.sin6_addr, sizeof(struct in6_addr)); + if (sa6_recoverscope(&saun->sin6) != 0) + return (ESRCH); + info->rti_info[RTAX_IFA] = (struct sockaddr *)&saun->sin6; break; } #endif @@ -585,9 +564,10 @@ route_output(struct mbuf *m, struct sock case RTM_GET: report: RT_LOCK_ASSERT(rt); - if (jailed(curthread->td_ucred) && - ((rt->rt_flags & RTF_HOST) == 0 || - !prison_if(curthread->td_ucred, rt_key(rt)))) { + if ((rt->rt_flags & RTF_HOST) == 0 + ? jailed(curthread->td_ucred) + : prison_if(curthread->td_ucred, + rt_key(rt)) != 0) { RT_UNLOCK(rt); senderr(ESRCH); } @@ -600,17 +580,11 @@ route_output(struct mbuf *m, struct sock if (ifp) { info.rti_info[RTAX_IFP] = ifp->if_addr->ifa_addr; - if (jailed(curthread->td_ucred)) { - error = rtm_get_jailed( - &info, ifp, rt, &saun, - curthread->td_ucred); - if (error != 0) { - RT_UNLOCK(rt); - senderr(ESRCH); - } - } else { - info.rti_info[RTAX_IFA] = - rt->rt_ifa->ifa_addr; + error = rtm_get_jailed(&info, ifp, rt, + &saun, curthread->td_ucred); + if (error != 0) { + RT_UNLOCK(rt); + senderr(error); } if (ifp->if_flags & IFF_POINTOPOINT) info.rti_info[RTAX_BRD] = @@ -1230,9 +1204,9 @@ sysctl_dumpentry(struct radix_node *rn, if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) return 0; - if (jailed(w->w_req->td->td_ucred) && - ((rt->rt_flags & RTF_HOST) == 0 || - !prison_if(w->w_req->td->td_ucred, rt_key(rt)))) + if ((rt->rt_flags & RTF_HOST) == 0 + ? jailed(w->w_req->td->td_ucred) + : prison_if(w->w_req->td->td_ucred, rt_key(rt)) != 0) return (0); bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); @@ -1293,8 +1267,8 @@ sysctl_iflist(int af, struct walkarg *w) while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) { if (af && af != ifa->ifa_addr->sa_family) continue; - if (jailed(w->w_req->td->td_ucred) && - !prison_if(w->w_req->td->td_ucred, ifa->ifa_addr)) + if (prison_if(w->w_req->td->td_ucred, + ifa->ifa_addr) != 0) continue; info.rti_info[RTAX_IFA] = ifa->ifa_addr; info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; @@ -1341,8 +1315,8 @@ sysctl_ifmalist(int af, struct walkarg * TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (af && af != ifma->ifma_addr->sa_family) continue; - if (jailed(w->w_req->td->td_ucred) && - !prison_if(w->w_req->td->td_ucred, ifma->ifma_addr)) + if (prison_if(w->w_req->td->td_ucred, + ifma->ifma_addr) != 0) continue; info.rti_info[RTAX_IFA] = ifma->ifma_addr; info.rti_info[RTAX_GATEWAY] = Modified: stable/7/sys/netinet/in.c ============================================================================== --- stable/7/sys/netinet/in.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/netinet/in.c Wed Feb 18 20:12:08 2009 (r188761) @@ -255,7 +255,7 @@ in_control(struct socket *so, u_long cmd if (iap->ia_ifp == ifp && iap->ia_addr.sin_addr.s_addr == dst.s_addr) { if (td == NULL || prison_check_ip4( - td->td_ucred, &dst)) + td->td_ucred, &dst) == 0) ia = iap; break; } @@ -264,8 +264,8 @@ in_control(struct socket *so, u_long cmd iap = ifatoia(ifa); if (iap->ia_addr.sin_family == AF_INET) { if (td != NULL && - !prison_check_ip4(td->td_ucred, - &iap->ia_addr.sin_addr)) + prison_check_ip4(td->td_ucred, + &iap->ia_addr.sin_addr) != 0) continue; ia = iap; break; Modified: stable/7/sys/netinet/in_pcb.c ============================================================================== --- stable/7/sys/netinet/in_pcb.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/netinet/in_pcb.c Wed Feb 18 20:12:08 2009 (r188761) @@ -296,7 +296,10 @@ in_pcbbind_setup(struct inpcb *inp, stru return (EINVAL); if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) wild = INPLOOKUP_WILDCARD; - if (nam) { + if (nam == NULL) { + if ((error = prison_local_ip4(cred, &laddr)) != 0) + return (error); + } else { sin = (struct sockaddr_in *)nam; if (nam->sa_len != sizeof (*sin)) return (EINVAL); @@ -308,8 +311,9 @@ in_pcbbind_setup(struct inpcb *inp, stru if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); #endif - if (prison_local_ip4(cred, &sin->sin_addr)) - return (EINVAL); + error = prison_local_ip4(cred, &sin->sin_addr); + if (error) + return (error); if (sin->sin_port != *lportp) { /* Don't allow the port to change. */ if (*lportp != 0) @@ -365,8 +369,6 @@ in_pcbbind_setup(struct inpcb *inp, stru t->inp_cred->cr_uid)) return (EADDRINUSE); } - if (prison_local_ip4(cred, &sin->sin_addr)) - return (EADDRNOTAVAIL); t = in_pcblookup_local(pcbinfo, sin->sin_addr, lport, wild, cred); if (t && (t->inp_vflag & INP_TIMEWAIT)) { @@ -400,9 +402,6 @@ in_pcbbind_setup(struct inpcb *inp, stru u_short first, last; int count; - if (prison_local_ip4(cred, &laddr)) - return (EINVAL); - if (inp->inp_flags & INP_HIGHPORT) { first = ipport_hifirstauto; /* sysctl */ last = ipport_hilastauto; @@ -485,8 +484,6 @@ in_pcbbind_setup(struct inpcb *inp, stru wild, cred)); } } - if (prison_local_ip4(cred, &laddr)) - return (EINVAL); *laddrp = laddr.s_addr; *lportp = lport; return (0); @@ -606,7 +603,7 @@ in_pcbladdr(struct inpcb *inp, struct in if (sa->sa_family != AF_INET) continue; sin = (struct sockaddr_in *)sa; - if (prison_check_ip4(cred, &sin->sin_addr)) { + if (prison_check_ip4(cred, &sin->sin_addr) == 0) { ia = (struct in_ifaddr *)ifa; break; } @@ -617,8 +614,7 @@ in_pcbladdr(struct inpcb *inp, struct in } /* 3. As a last resort return the 'default' jail address. */ - if (prison_get_ip4(cred, laddr) != 0) - error = EADDRNOTAVAIL; + error = prison_get_ip4(cred, laddr); goto done; } @@ -643,7 +639,7 @@ in_pcbladdr(struct inpcb *inp, struct in /* Jailed. */ /* 1. Check if the iface address belongs to the jail. */ sin = (struct sockaddr_in *)sro.ro_rt->rt_ifa->ifa_addr; - if (prison_check_ip4(cred, &sin->sin_addr)) { + if (prison_check_ip4(cred, &sin->sin_addr) == 0) { ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa; laddr->s_addr = ia->ia_addr.sin_addr.s_addr; goto done; @@ -659,7 +655,7 @@ in_pcbladdr(struct inpcb *inp, struct in if (sa->sa_family != AF_INET) continue; sin = (struct sockaddr_in *)sa; - if (prison_check_ip4(cred, &sin->sin_addr)) { + if (prison_check_ip4(cred, &sin->sin_addr) == 0) { ia = (struct in_ifaddr *)ifa; break; } @@ -670,8 +666,7 @@ in_pcbladdr(struct inpcb *inp, struct in } /* 3. As a last resort return the 'default' jail address. */ - if (prison_get_ip4(cred, laddr) != 0) - error = EADDRNOTAVAIL; + error = prison_get_ip4(cred, laddr); goto done; } @@ -721,7 +716,8 @@ in_pcbladdr(struct inpcb *inp, struct in if (sa->sa_family != AF_INET) continue; sin = (struct sockaddr_in *)sa; - if (prison_check_ip4(cred, &sin->sin_addr)) { + if (prison_check_ip4(cred, + &sin->sin_addr) == 0) { ia = (struct in_ifaddr *)ifa; break; } @@ -733,8 +729,7 @@ in_pcbladdr(struct inpcb *inp, struct in } /* 3. As a last resort return the 'default' jail address. */ - if (prison_get_ip4(cred, laddr) != 0) - error = EADDRNOTAVAIL; + error = prison_get_ip4(cred, laddr); goto done; } @@ -767,7 +762,7 @@ in_pcbconnect_setup(struct inpcb *inp, s struct sockaddr_in *sin = (struct sockaddr_in *)nam; struct in_ifaddr *ia; struct inpcb *oinp; - struct in_addr laddr, faddr, jailia; + struct in_addr laddr, faddr; u_short lport, fport; int error; @@ -800,15 +795,11 @@ in_pcbconnect_setup(struct inpcb *inp, s * choose the broadcast address for that interface. */ if (faddr.s_addr == INADDR_ANY) { - if (cred != NULL && jailed(cred)) { - if (prison_get_ip4(cred, &jailia) != 0) - return (EADDRNOTAVAIL); - faddr.s_addr = jailia.s_addr; - } else { - faddr = - IA_SIN(TAILQ_FIRST(&in_ifaddrhead))-> - sin_addr; - } + faddr = + IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr; + if (cred != NULL && + (error = prison_get_ip4(cred, &faddr)) != 0) + return (error); } else if (faddr.s_addr == (u_long)INADDR_BROADCAST && (TAILQ_FIRST(&in_ifaddrhead)->ia_ifp->if_flags & IFF_BROADCAST)) @@ -1290,7 +1281,8 @@ in_pcblookup_hash(struct inpcbinfo *pcbi injail = jailed(inp->inp_cred); if (injail) { - if (!prison_check_ip4(inp->inp_cred, &laddr)) + if (prison_check_ip4(inp->inp_cred, + &laddr) != 0) continue; } else { if (local_exact != NULL) Modified: stable/7/sys/netinet/raw_ip.c ============================================================================== --- stable/7/sys/netinet/raw_ip.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/netinet/raw_ip.c Wed Feb 18 20:12:08 2009 (r188761) @@ -265,10 +265,8 @@ rip_input(struct mbuf *m, int off) continue; if (inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; - if (jailed(inp->inp_cred)) { - if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst)) - continue; - } + if (prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0) + continue; if (last) { struct mbuf *n; @@ -295,10 +293,8 @@ rip_input(struct mbuf *m, int off) if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; - if (jailed(inp->inp_cred)) { - if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst)) - continue; - } + if (prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0) + continue; if (last) { struct mbuf *n; @@ -358,14 +354,12 @@ rip_output(struct mbuf *m, struct socket ip->ip_off = 0; ip->ip_p = inp->inp_ip_p; ip->ip_len = m->m_pkthdr.len; - if (jailed(inp->inp_cred)) { - if (prison_get_ip4(inp->inp_cred, &ip->ip_src) != 0) { - INP_RUNLOCK(inp); - m_freem(m); - return (EPERM); - } - } else { - ip->ip_src = inp->inp_laddr; + ip->ip_src = inp->inp_laddr; + error = prison_get_ip4(inp->inp_cred, &ip->ip_src); + if (error != 0) { + INP_RUNLOCK(inp); + m_freem(m); + return (error); } ip->ip_dst.s_addr = dst; ip->ip_ttl = inp->inp_ip_ttl; @@ -376,10 +370,11 @@ rip_output(struct mbuf *m, struct socket } INP_RLOCK(inp); ip = mtod(m, struct ip *); - if (!prison_check_ip4(inp->inp_cred, &ip->ip_src)) { + error = prison_check_ip4(inp->inp_cred, &ip->ip_src); + if (error != 0) { INP_RUNLOCK(inp); m_freem(m); - return (EPERM); + return (error); } /* @@ -783,12 +778,14 @@ rip_bind(struct socket *so, struct socka { struct sockaddr_in *addr = (struct sockaddr_in *)nam; struct inpcb *inp; + int error; if (nam->sa_len != sizeof(*addr)) return (EINVAL); - if (!prison_check_ip4(td->td_ucred, &addr->sin_addr)) - return (EADDRNOTAVAIL); + error = prison_check_ip4(td->td_ucred, &addr->sin_addr); + if (error != 0) + return (error); if (TAILQ_EMPTY(&ifnet) || (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) || Modified: stable/7/sys/netinet/tcp_usrreq.c ============================================================================== --- stable/7/sys/netinet/tcp_usrreq.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/netinet/tcp_usrreq.c Wed Feb 18 20:12:08 2009 (r188761) @@ -462,8 +462,8 @@ tcp_usr_connect(struct socket *so, struc if (sinp->sin_family == AF_INET && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) return (EAFNOSUPPORT); - if (prison_remote_ip4(td->td_ucred, &sinp->sin_addr) != 0) - return (EINVAL); + if ((error = prison_remote_ip4(td->td_ucred, &sinp->sin_addr)) != 0) + return (error); TCPDEBUG0; INP_INFO_WLOCK(&tcbinfo); @@ -528,10 +528,9 @@ tcp6_usr_connect(struct socket *so, stru in6_sin6_2_sin(&sin, sin6p); inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; - if (prison_remote_ip4(td->td_ucred, &sin.sin_addr) != 0) { - error = EINVAL; + if ((error = prison_remote_ip4(td->td_ucred, + &sin.sin_addr)) != 0) goto out; - } if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0) goto out; error = tcp_output_connect(so, nam); @@ -540,10 +539,8 @@ tcp6_usr_connect(struct socket *so, stru inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; inp->inp_inc.inc_isipv6 = 1; - if (prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr) != 0) { - error = EINVAL; + if ((error = prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr)) != 0) goto out; - } if ((error = tcp6_connect(tp, nam, td)) != 0) goto out; error = tcp_output_connect(so, nam); Modified: stable/7/sys/netinet/udp_usrreq.c ============================================================================== --- stable/7/sys/netinet/udp_usrreq.c Wed Feb 18 19:59:27 2009 (r188760) +++ stable/7/sys/netinet/udp_usrreq.c Wed Feb 18 20:12:08 2009 (r188761) @@ -938,10 +938,9 @@ udp_output(struct inpcb *inp, struct mbu * Jail may rewrite the destination address, so let it do *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From kib at FreeBSD.org Thu Feb 19 08:01:02 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Thu Feb 19 08:01:14 2009 Subject: svn commit: r188817 - in stable/7/sys: . cddl/contrib/opensolaris/uts/common/fs cddl/contrib/opensolaris/uts/common/fs/zfs contrib/pf dev/ath/ath_hal dev/cxgb Message-ID: <200902191601.n1JG10YG001669@svn.freebsd.org> Author: kib Date: Thu Feb 19 16:01:00 2009 New Revision: 188817 URL: http://svn.freebsd.org/changeset/base/188817 Log: Unbreak ZFS after the r188610: MFC r182781 (by pjd): Catch up after last insmntque() changes: - The vnode has to be locked exclusively before calling insmntque(). - Until I find a way to handle insmntque() failures use VV_FORCEINSMQ flag to force insmntque() to always succeed. MFC r182824 (by pjd): Lock vnode exclusively around insmntque(). MFC r182840 (by pjd): Initialize vp, so we don't call VOP_UNLOCK() with NULL vnode pointer. Tested by: cy, pjd No objections by: pjd Modified: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c ============================================================================== --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c Thu Feb 19 15:37:43 2009 (r188816) +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c Thu Feb 19 16:01:00 2009 (r188817) @@ -358,6 +358,7 @@ gfs_file_create(size_t size, vnode_t *pv fp = kmem_zalloc(size, KM_SLEEP); error = getnewvnode("zfs", vfsp, ops, &vp); ASSERT(error == 0); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); vp->v_data = (caddr_t)fp; /* @@ -368,7 +369,9 @@ gfs_file_create(size_t size, vnode_t *pv fp->gfs_size = size; fp->gfs_type = GFS_FILE; + vp->v_vflag |= VV_FORCEINSMQ; error = insmntque(vp, vfsp); + vp->v_vflag &= ~VV_FORCEINSMQ; KASSERT(error == 0, ("insmntque() failed: error %d", error)); /* Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c ============================================================================== --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c Thu Feb 19 15:37:43 2009 (r188816) +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c Thu Feb 19 16:01:00 2009 (r188817) @@ -176,6 +176,8 @@ zfsctl_create(zfsvfs_t *zfsvfs) vp->v_vflag &= ~VV_ROOT; zfsvfs->z_ctldir = vp; + + VOP_UNLOCK(vp, 0, curthread); } /* @@ -789,6 +791,7 @@ zfsctl_mknode_snapdir(vnode_t *pvp) mutex_init(&sdp->sd_lock, NULL, MUTEX_DEFAULT, NULL); avl_create(&sdp->sd_snaps, snapentry_compare, sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t, se_node)); + VOP_UNLOCK(vp, 0, curthread); return (vp); } @@ -862,6 +865,7 @@ zfsctl_snapshot_mknode(vnode_t *pvp, uin &zfsctl_ops_snapshot, NULL, NULL, MAXNAMELEN, NULL, NULL); zcp = vp->v_data; zcp->zc_id = objset; + VOP_UNLOCK(vp, 0, curthread); return (vp); } Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ============================================================================== --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Thu Feb 19 15:37:43 2009 (r188816) +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Thu Feb 19 16:01:00 2009 (r188817) @@ -1303,12 +1303,6 @@ top: } } out: - - if (error == 0) { - *vpp = ZTOV(zp); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td); - } - if (dl) zfs_dirent_unlock(dl); @@ -1588,8 +1582,6 @@ top: zfs_log_create(zilog, tx, TX_MKDIR, dzp, zp, dirname); dmu_tx_commit(tx); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread); - zfs_dirent_unlock(dl); ZFS_EXIT(zfsvfs); @@ -2773,7 +2765,6 @@ out: if (error == 0) { zfs_log_symlink(zilog, tx, TX_SYMLINK, dzp, zp, name, link); *vpp = ZTOV(zp); - vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td); } dmu_tx_commit(tx); Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c ============================================================================== --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c Thu Feb 19 15:37:43 2009 (r188816) +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c Thu Feb 19 16:01:00 2009 (r188817) @@ -113,6 +113,7 @@ zfs_znode_cache_constructor(void *buf, v if (cdrarg != NULL) { error = getnewvnode("zfs", vfsp, &zfs_vnodeops, &vp); ASSERT(error == 0); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); zp->z_vnode = vp; vp->v_data = (caddr_t)zp; vp->v_vnlock->lk_flags |= LK_CANRECURSE; @@ -348,7 +349,9 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_bu if (vp == NULL) return (zp); + vp->v_vflag |= VV_FORCEINSMQ; error = insmntque(vp, zfsvfs->z_vfs); + vp->v_vflag &= ~VV_FORCEINSMQ; KASSERT(error == 0, ("insmntque() failed: error %d", error)); vp->v_type = IFTOVT((mode_t)zp->z_phys->zp_mode); @@ -535,8 +538,10 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, u *zpp = zp; } else { - if (ZTOV(zp) != NULL) + if (ZTOV(zp) != NULL) { ZTOV(zp)->v_count = 0; + VOP_UNLOCK(ZTOV(zp), 0, curthread); + } dmu_buf_rele(dbp, NULL); zfs_znode_free(zp); } @@ -598,14 +603,18 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_ &zp->z_vnode); ASSERT(err == 0); vp = ZTOV(zp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); vp->v_data = (caddr_t)zp; vp->v_vnlock->lk_flags |= LK_CANRECURSE; vp->v_vnlock->lk_flags &= ~LK_NOSHARE; vp->v_type = IFTOVT((mode_t)zp->z_phys->zp_mode); if (vp->v_type == VDIR) zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */ + vp->v_vflag |= VV_FORCEINSMQ; err = insmntque(vp, zfsvfs->z_vfs); + vp->v_vflag &= ~VV_FORCEINSMQ; KASSERT(err == 0, ("insmntque() failed: error %d", err)); + VOP_UNLOCK(vp, 0, curthread); } mutex_exit(&zp->z_lock); ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); @@ -621,6 +630,8 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_ zfs_znode_dmu_init(zp); ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); *zpp = zp; + if ((vp = ZTOV(zp)) != NULL) + VOP_UNLOCK(vp, 0, curthread); return (0); } From luigi at FreeBSD.org Thu Feb 19 13:29:31 2009 From: luigi at FreeBSD.org (Luigi Rizzo) Date: Thu Feb 19 13:29:38 2009 Subject: svn commit: r188830 - stable/7/sys/netinet Message-ID: <200902192129.n1JLTUq4008297@svn.freebsd.org> Author: luigi Date: Thu Feb 19 21:29:30 2009 New Revision: 188830 URL: http://svn.freebsd.org/changeset/base/188830 Log: correct the spelling of a log message (missing "All "); on passing, rename a variable within a macro to reduce the chance of shadowing other variables with the same name Modified: stable/7/sys/netinet/ip_fw2.c Modified: stable/7/sys/netinet/ip_fw2.c ============================================================================== --- stable/7/sys/netinet/ip_fw2.c Thu Feb 19 20:45:37 2009 (r188829) +++ stable/7/sys/netinet/ip_fw2.c Thu Feb 19 21:29:30 2009 (r188830) @@ -2219,15 +2219,15 @@ ipfw_chk(struct ip_fw_args *args) * pointer might become stale after other pullups (but we never use it * this way). */ -#define PULLUP_TO(len, p, T) \ +#define PULLUP_TO(_len, p, T) \ do { \ - int x = (len) + sizeof(T); \ + int x = (_len) + sizeof(T); \ if ((m)->m_len < x) { \ args->m = m = m_pullup(m, x); \ if (m == NULL) \ goto pullup_failed; \ } \ - p = (mtod(m, char *) + (len)); \ + p = (mtod(m, char *) + (_len)); \ } while (0) /* @@ -3717,7 +3717,7 @@ zero_entry(struct ip_fw_chain *chain, u_ continue; clear_counters(rule, log_only); } - msg = log_only ? "logging counts reset" : + msg = log_only ? "All logging counts reset" : "Accounting cleared"; } else { int cleared = 0; From luigi at FreeBSD.org Thu Feb 19 16:39:42 2009 From: luigi at FreeBSD.org (Luigi Rizzo) Date: Thu Feb 19 16:40:01 2009 Subject: svn commit: r188836 - stable/7/sbin/ipfw Message-ID: <200902200039.n1K0ddVa011946@svn.freebsd.org> Author: luigi Date: Fri Feb 20 00:39:39 2009 New Revision: 188836 URL: http://svn.freebsd.org/changeset/base/188836 Log: MFC: sync the ipfw code with the version in HEAD. The only new feature is that now one can write "table all {flush | list}" to act on all tables. Just for the records, there is one difference which probably has no practical importance; two "tos" flags are represented differently now: @@ -182,8 +182,8 @@ static struct _s_x f_iptos[] = { { "throughput", IPTOS_THROUGHPUT}, { "reliability", IPTOS_RELIABILITY}, { "mincost", IPTOS_MINCOST}, - { "congestion", IPTOS_CE}, - { "ecntransport", IPTOS_ECT}, + { "congestion", IPTOS_ECN_CE}, + { "ecntransport", IPTOS_ECN_ECT0}, { "ip tos option", 0}, { NULL, 0 } }; IPTOS_ECT = IPTOS_ECN_ECT0 = 2 so 'ecntransport' is the same. IPTOS_CE = 1, IPTOS_ECN_CE = 3 so 'congestion' is represented by a different codepoint, but this also reflects a different specification (RFC3168 obsoletes RFC2481) so the change is just adopting the new spec. Added: stable/7/sbin/ipfw/altq.c (contents, props changed) stable/7/sbin/ipfw/dummynet.c (contents, props changed) stable/7/sbin/ipfw/ipfw2.h (contents, props changed) stable/7/sbin/ipfw/ipv6.c (contents, props changed) stable/7/sbin/ipfw/main.c (contents, props changed) stable/7/sbin/ipfw/nat.c (contents, props changed) Modified: stable/7/sbin/ipfw/Makefile stable/7/sbin/ipfw/ipfw.8 stable/7/sbin/ipfw/ipfw2.c Modified: stable/7/sbin/ipfw/Makefile ============================================================================== --- stable/7/sbin/ipfw/Makefile Fri Feb 20 00:05:33 2009 (r188835) +++ stable/7/sbin/ipfw/Makefile Fri Feb 20 00:39:39 2009 (r188836) @@ -1,8 +1,8 @@ # $FreeBSD$ PROG= ipfw -SRCS= ipfw2.c -WARNS?= 0 +SRCS= ipfw2.c dummynet.c ipv6.c main.c nat.c altq.c +WARNS?= 2 MAN= ipfw.8 .include Added: stable/7/sbin/ipfw/altq.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/7/sbin/ipfw/altq.c Fri Feb 20 00:39:39 2009 (r188836) @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2002-2003 Luigi Rizzo + * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp + * Copyright (c) 1994 Ugen J.S.Antsilevich + * + * Idea and grammar partially left from: + * Copyright (c) 1993 Daniel Boulet + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + * + * NEW command line interface for IP firewall facility + * + * $FreeBSD$ + * + * altq interface + */ + +#include +#include +#include + +#include "ipfw2.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* IFNAMSIZ */ +#include +#include + +/* + * Map between current altq queue id numbers and names. + */ +static TAILQ_HEAD(, pf_altq) altq_entries = + TAILQ_HEAD_INITIALIZER(altq_entries); + +void +altq_set_enabled(int enabled) +{ + int pffd; + + pffd = open("/dev/pf", O_RDWR); + if (pffd == -1) + err(EX_UNAVAILABLE, + "altq support opening pf(4) control device"); + if (enabled) { + if (ioctl(pffd, DIOCSTARTALTQ) != 0 && errno != EEXIST) + err(EX_UNAVAILABLE, "enabling altq"); + } else { + if (ioctl(pffd, DIOCSTOPALTQ) != 0 && errno != ENOENT) + err(EX_UNAVAILABLE, "disabling altq"); + } + close(pffd); +} + +static void +altq_fetch(void) +{ + struct pfioc_altq pfioc; + struct pf_altq *altq; + int pffd; + unsigned int mnr; + static int altq_fetched = 0; + + if (altq_fetched) + return; + altq_fetched = 1; + pffd = open("/dev/pf", O_RDONLY); + if (pffd == -1) { + warn("altq support opening pf(4) control device"); + return; + } + bzero(&pfioc, sizeof(pfioc)); + if (ioctl(pffd, DIOCGETALTQS, &pfioc) != 0) { + warn("altq support getting queue list"); + close(pffd); + return; + } + mnr = pfioc.nr; + for (pfioc.nr = 0; pfioc.nr < mnr; pfioc.nr++) { + if (ioctl(pffd, DIOCGETALTQ, &pfioc) != 0) { + if (errno == EBUSY) + break; + warn("altq support getting queue list"); + close(pffd); + return; + } + if (pfioc.altq.qid == 0) + continue; + altq = safe_calloc(1, sizeof(*altq)); + *altq = pfioc.altq; + TAILQ_INSERT_TAIL(&altq_entries, altq, entries); + } + close(pffd); +} + +u_int32_t +altq_name_to_qid(const char *name) +{ + struct pf_altq *altq; + + altq_fetch(); + TAILQ_FOREACH(altq, &altq_entries, entries) + if (strcmp(name, altq->qname) == 0) + break; + if (altq == NULL) + errx(EX_DATAERR, "altq has no queue named `%s'", name); + return altq->qid; +} + +const char * +altq_qid_to_name(u_int32_t qid) +{ + struct pf_altq *altq; + + altq_fetch(); + TAILQ_FOREACH(altq, &altq_entries, entries) + if (qid == altq->qid) + break; + if (altq == NULL) + return NULL; + return altq->qname; +} + +void +print_altq_cmd(ipfw_insn_altq *altqptr) +{ + if (altqptr) { + const char *qname; + + qname = altq_qid_to_name(altqptr->qid); + if (qname == NULL) + printf(" altq ?<%u>", altqptr->qid); + else + printf(" altq %s", qname); + } +} Added: stable/7/sbin/ipfw/dummynet.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/7/sbin/ipfw/dummynet.c Fri Feb 20 00:39:39 2009 (r188836) @@ -0,0 +1,719 @@ +/* + * Copyright (c) 2002-2003 Luigi Rizzo + * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp + * Copyright (c) 1994 Ugen J.S.Antsilevich + * + * Idea and grammar partially left from: + * Copyright (c) 1993 Daniel Boulet + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + * + * NEW command line interface for IP firewall facility + * + * $FreeBSD$ + * + * dummynet support + */ + +#include +#include +#include +/* XXX there are several sysctl leftover here */ +#include + +#include "ipfw2.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include /* inet_ntoa */ + +static struct _s_x dummynet_params[] = { + { "plr", TOK_PLR }, + { "noerror", TOK_NOERROR }, + { "buckets", TOK_BUCKETS }, + { "dst-ip", TOK_DSTIP }, + { "src-ip", TOK_SRCIP }, + { "dst-port", TOK_DSTPORT }, + { "src-port", TOK_SRCPORT }, + { "proto", TOK_PROTO }, + { "weight", TOK_WEIGHT }, + { "all", TOK_ALL }, + { "mask", TOK_MASK }, + { "droptail", TOK_DROPTAIL }, + { "red", TOK_RED }, + { "gred", TOK_GRED }, + { "bw", TOK_BW }, + { "bandwidth", TOK_BW }, + { "delay", TOK_DELAY }, + { "pipe", TOK_PIPE }, + { "queue", TOK_QUEUE }, + { "flow-id", TOK_FLOWID}, + { "dst-ipv6", TOK_DSTIP6}, + { "dst-ip6", TOK_DSTIP6}, + { "src-ipv6", TOK_SRCIP6}, + { "src-ip6", TOK_SRCIP6}, + { "dummynet-params", TOK_NULL }, + { NULL, 0 } /* terminator */ +}; + +static int +sort_q(const void *pa, const void *pb) +{ + int rev = (co.do_sort < 0); + int field = rev ? -co.do_sort : co.do_sort; + long long res = 0; + const struct dn_flow_queue *a = pa; + const struct dn_flow_queue *b = pb; + + switch (field) { + case 1: /* pkts */ + res = a->len - b->len; + break; + case 2: /* bytes */ + res = a->len_bytes - b->len_bytes; + break; + + case 3: /* tot pkts */ + res = a->tot_pkts - b->tot_pkts; + break; + + case 4: /* tot bytes */ + res = a->tot_bytes - b->tot_bytes; + break; + } + if (res < 0) + res = -1; + if (res > 0) + res = 1; + return (int)(rev ? res : -res); +} + +static void +list_queues(struct dn_flow_set *fs, struct dn_flow_queue *q) +{ + int l; + int index_printed, indexes = 0; + char buff[255]; + struct protoent *pe; + + if (fs->rq_elements == 0) + return; + + if (co.do_sort != 0) + heapsort(q, fs->rq_elements, sizeof *q, sort_q); + + /* Print IPv4 flows */ + index_printed = 0; + for (l = 0; l < fs->rq_elements; l++) { + struct in_addr ina; + + /* XXX: Should check for IPv4 flows */ + if (IS_IP6_FLOW_ID(&(q[l].id))) + continue; + + if (!index_printed) { + index_printed = 1; + if (indexes > 0) /* currently a no-op */ + printf("\n"); + indexes++; + printf(" " + "mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n", + fs->flow_mask.proto, + fs->flow_mask.src_ip, fs->flow_mask.src_port, + fs->flow_mask.dst_ip, fs->flow_mask.dst_port); + + printf("BKT Prot ___Source IP/port____ " + "____Dest. IP/port____ " + "Tot_pkt/bytes Pkt/Byte Drp\n"); + } + + printf("%3d ", q[l].hash_slot); + pe = getprotobynumber(q[l].id.proto); + if (pe) + printf("%-4s ", pe->p_name); + else + printf("%4u ", q[l].id.proto); + ina.s_addr = htonl(q[l].id.src_ip); + printf("%15s/%-5d ", + inet_ntoa(ina), q[l].id.src_port); + ina.s_addr = htonl(q[l].id.dst_ip); + printf("%15s/%-5d ", + inet_ntoa(ina), q[l].id.dst_port); + printf("%4llu %8llu %2u %4u %3u\n", + align_uint64(&q[l].tot_pkts), + align_uint64(&q[l].tot_bytes), + q[l].len, q[l].len_bytes, q[l].drops); + if (co.verbose) + printf(" S %20llu F %20llu\n", + align_uint64(&q[l].S), align_uint64(&q[l].F)); + } + + /* Print IPv6 flows */ + index_printed = 0; + for (l = 0; l < fs->rq_elements; l++) { + if (!IS_IP6_FLOW_ID(&(q[l].id))) + continue; + + if (!index_printed) { + index_printed = 1; + if (indexes > 0) + printf("\n"); + indexes++; + printf("\n mask: proto: 0x%02x, flow_id: 0x%08x, ", + fs->flow_mask.proto, fs->flow_mask.flow_id6); + inet_ntop(AF_INET6, &(fs->flow_mask.src_ip6), + buff, sizeof(buff)); + printf("%s/0x%04x -> ", buff, fs->flow_mask.src_port); + inet_ntop( AF_INET6, &(fs->flow_mask.dst_ip6), + buff, sizeof(buff) ); + printf("%s/0x%04x\n", buff, fs->flow_mask.dst_port); + + printf("BKT ___Prot___ _flow-id_ " + "______________Source IPv6/port_______________ " + "_______________Dest. IPv6/port_______________ " + "Tot_pkt/bytes Pkt/Byte Drp\n"); + } + printf("%3d ", q[l].hash_slot); + pe = getprotobynumber(q[l].id.proto); + if (pe != NULL) + printf("%9s ", pe->p_name); + else + printf("%9u ", q[l].id.proto); + printf("%7d %39s/%-5d ", q[l].id.flow_id6, + inet_ntop(AF_INET6, &(q[l].id.src_ip6), buff, sizeof(buff)), + q[l].id.src_port); + printf(" %39s/%-5d ", + inet_ntop(AF_INET6, &(q[l].id.dst_ip6), buff, sizeof(buff)), + q[l].id.dst_port); + printf(" %4llu %8llu %2u %4u %3u\n", + align_uint64(&q[l].tot_pkts), + align_uint64(&q[l].tot_bytes), + q[l].len, q[l].len_bytes, q[l].drops); + if (co.verbose) + printf(" S %20llu F %20llu\n", + align_uint64(&q[l].S), + align_uint64(&q[l].F)); + } +} + +static void +print_flowset_parms(struct dn_flow_set *fs, char *prefix) +{ + int l; + char qs[30]; + char plr[30]; + char red[90]; /* Display RED parameters */ + + l = fs->qsize; + if (fs->flags_fs & DN_QSIZE_IS_BYTES) { + if (l >= 8192) + sprintf(qs, "%d KB", l / 1024); + else + sprintf(qs, "%d B", l); + } else + sprintf(qs, "%3d sl.", l); + if (fs->plr) + sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff)); + else + plr[0] = '\0'; + if (fs->flags_fs & DN_IS_RED) /* RED parameters */ + sprintf(red, + "\n\t %cRED w_q %f min_th %d max_th %d max_p %f", + (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ', + 1.0 * fs->w_q / (double)(1 << SCALE_RED), + SCALE_VAL(fs->min_th), + SCALE_VAL(fs->max_th), + 1.0 * fs->max_p / (double)(1 << SCALE_RED)); + else + sprintf(red, "droptail"); + + printf("%s %s%s %d queues (%d buckets) %s\n", + prefix, qs, plr, fs->rq_elements, fs->rq_size, red); +} + +void +ipfw_list_pipes(void *data, uint nbytes, int ac, char *av[]) +{ + int rulenum; + void *next = data; + struct dn_pipe *p = (struct dn_pipe *) data; + struct dn_flow_set *fs; + struct dn_flow_queue *q; + int l; + + if (ac > 0) + rulenum = strtoul(*av++, NULL, 10); + else + rulenum = 0; + for (; nbytes >= sizeof *p; p = (struct dn_pipe *)next) { + double b = p->bandwidth; + char buf[30]; + char prefix[80]; + + if (SLIST_NEXT(p, next) != (struct dn_pipe *)DN_IS_PIPE) + break; /* done with pipes, now queues */ + + /* + * compute length, as pipe have variable size + */ + l = sizeof(*p) + p->fs.rq_elements * sizeof(*q); + next = (char *)p + l; + nbytes -= l; + + if ((rulenum != 0 && rulenum != p->pipe_nr) || co.do_pipe == 2) + continue; + + /* + * Print rate (or clocking interface) + */ + if (p->if_name[0] != '\0') + sprintf(buf, "%s", p->if_name); + else if (b == 0) + sprintf(buf, "unlimited"); + else if (b >= 1000000) + sprintf(buf, "%7.3f Mbit/s", b/1000000); + else if (b >= 1000) + sprintf(buf, "%7.3f Kbit/s", b/1000); + else + sprintf(buf, "%7.3f bit/s ", b); + + sprintf(prefix, "%05d: %s %4d ms ", + p->pipe_nr, buf, p->delay); + print_flowset_parms(&(p->fs), prefix); + if (co.verbose) + printf(" V %20llu\n", align_uint64(&p->V) >> MY_M); + + q = (struct dn_flow_queue *)(p+1); + list_queues(&(p->fs), q); + } + for (fs = next; nbytes >= sizeof *fs; fs = next) { + char prefix[80]; + + if (SLIST_NEXT(fs, next) != (struct dn_flow_set *)DN_IS_QUEUE) + break; + l = sizeof(*fs) + fs->rq_elements * sizeof(*q); + next = (char *)fs + l; + nbytes -= l; + + if (rulenum != 0 && ((rulenum != fs->fs_nr && co.do_pipe == 2) || + (rulenum != fs->parent_nr && co.do_pipe == 1))) { + continue; + } + + q = (struct dn_flow_queue *)(fs+1); + sprintf(prefix, "q%05d: weight %d pipe %d ", + fs->fs_nr, fs->weight, fs->parent_nr); + print_flowset_parms(fs, prefix); + list_queues(fs, q); + } +} + +/* + * Delete pipe or queue i + */ +int +ipfw_delete_pipe(int pipe_or_queue, int i) +{ + struct dn_pipe p; + + memset(&p, 0, sizeof p); + if (pipe_or_queue == 1) + p.pipe_nr = i; /* pipe */ + else + p.fs.fs_nr = i; /* queue */ + i = do_cmd(IP_DUMMYNET_DEL, &p, sizeof p); + if (i) { + i = 1; + warn("rule %u: setsockopt(IP_DUMMYNET_DEL)", i); + } + return i; +} + +void +ipfw_config_pipe(int ac, char **av) +{ + struct dn_pipe p; + int i; + char *end; + void *par = NULL; + + memset(&p, 0, sizeof p); + + av++; ac--; + /* Pipe number */ + if (ac && isdigit(**av)) { + i = atoi(*av); av++; ac--; + if (co.do_pipe == 1) + p.pipe_nr = i; + else + p.fs.fs_nr = i; + } + while (ac > 0) { + double d; + int tok = match_token(dummynet_params, *av); + ac--; av++; + + switch(tok) { + case TOK_NOERROR: + p.fs.flags_fs |= DN_NOERROR; + break; + + case TOK_PLR: + NEED1("plr needs argument 0..1\n"); + d = strtod(av[0], NULL); + if (d > 1) + d = 1; + else if (d < 0) + d = 0; + p.fs.plr = (int)(d*0x7fffffff); + ac--; av++; + break; + + case TOK_QUEUE: + NEED1("queue needs queue size\n"); + end = NULL; + p.fs.qsize = strtoul(av[0], &end, 0); + if (*end == 'K' || *end == 'k') { + p.fs.flags_fs |= DN_QSIZE_IS_BYTES; + p.fs.qsize *= 1024; + } else if (*end == 'B' || + _substrcmp2(end, "by", "bytes") == 0) { + p.fs.flags_fs |= DN_QSIZE_IS_BYTES; + } + ac--; av++; + break; + + case TOK_BUCKETS: + NEED1("buckets needs argument\n"); + p.fs.rq_size = strtoul(av[0], NULL, 0); + ac--; av++; + break; + + case TOK_MASK: + NEED1("mask needs mask specifier\n"); + /* + * per-flow queue, mask is dst_ip, dst_port, + * src_ip, src_port, proto measured in bits + */ + par = NULL; + + bzero(&p.fs.flow_mask, sizeof(p.fs.flow_mask)); + end = NULL; + + while (ac >= 1) { + uint32_t *p32 = NULL; + uint16_t *p16 = NULL; + uint32_t *p20 = NULL; + struct in6_addr *pa6 = NULL; + uint32_t a; + + tok = match_token(dummynet_params, *av); + ac--; av++; + switch(tok) { + case TOK_ALL: + /* + * special case, all bits significant + */ + p.fs.flow_mask.dst_ip = ~0; + p.fs.flow_mask.src_ip = ~0; + p.fs.flow_mask.dst_port = ~0; + p.fs.flow_mask.src_port = ~0; + p.fs.flow_mask.proto = ~0; + n2mask(&(p.fs.flow_mask.dst_ip6), 128); + n2mask(&(p.fs.flow_mask.src_ip6), 128); + p.fs.flow_mask.flow_id6 = ~0; + p.fs.flags_fs |= DN_HAVE_FLOW_MASK; + goto end_mask; + + case TOK_DSTIP: + p32 = &p.fs.flow_mask.dst_ip; + break; + + case TOK_SRCIP: + p32 = &p.fs.flow_mask.src_ip; + break; + + case TOK_DSTIP6: + pa6 = &(p.fs.flow_mask.dst_ip6); + break; + + case TOK_SRCIP6: + pa6 = &(p.fs.flow_mask.src_ip6); + break; + + case TOK_FLOWID: + p20 = &p.fs.flow_mask.flow_id6; + break; + + case TOK_DSTPORT: + p16 = &p.fs.flow_mask.dst_port; + break; + + case TOK_SRCPORT: + p16 = &p.fs.flow_mask.src_port; + break; + + case TOK_PROTO: + break; + + default: + ac++; av--; /* backtrack */ + goto end_mask; + } + if (ac < 1) + errx(EX_USAGE, "mask: value missing"); + if (*av[0] == '/') { + a = strtoul(av[0]+1, &end, 0); + if (pa6 == NULL) + a = (a == 32) ? ~0 : (1 << a) - 1; + } else + a = strtoul(av[0], &end, 0); + if (p32 != NULL) + *p32 = a; + else if (p16 != NULL) { + if (a > 0xFFFF) + errx(EX_DATAERR, + "port mask must be 16 bit"); + *p16 = (uint16_t)a; + } else if (p20 != NULL) { + if (a > 0xfffff) + errx(EX_DATAERR, + "flow_id mask must be 20 bit"); + *p20 = (uint32_t)a; + } else if (pa6 != NULL) { + if (a > 128) + errx(EX_DATAERR, + "in6addr invalid mask len"); + else + n2mask(pa6, a); + } else { + if (a > 0xFF) + errx(EX_DATAERR, + "proto mask must be 8 bit"); + p.fs.flow_mask.proto = (uint8_t)a; + } + if (a != 0) + p.fs.flags_fs |= DN_HAVE_FLOW_MASK; + ac--; av++; + } /* end while, config masks */ +end_mask: + break; + + case TOK_RED: + case TOK_GRED: + NEED1("red/gred needs w_q/min_th/max_th/max_p\n"); + p.fs.flags_fs |= DN_IS_RED; + if (tok == TOK_GRED) + p.fs.flags_fs |= DN_IS_GENTLE_RED; + /* + * the format for parameters is w_q/min_th/max_th/max_p + */ + if ((end = strsep(&av[0], "/"))) { + double w_q = strtod(end, NULL); + if (w_q > 1 || w_q <= 0) + errx(EX_DATAERR, "0 < w_q <= 1"); + p.fs.w_q = (int) (w_q * (1 << SCALE_RED)); + } + if ((end = strsep(&av[0], "/"))) { + p.fs.min_th = strtoul(end, &end, 0); + if (*end == 'K' || *end == 'k') + p.fs.min_th *= 1024; + } + if ((end = strsep(&av[0], "/"))) { + p.fs.max_th = strtoul(end, &end, 0); + if (*end == 'K' || *end == 'k') + p.fs.max_th *= 1024; + } + if ((end = strsep(&av[0], "/"))) { + double max_p = strtod(end, NULL); + if (max_p > 1 || max_p <= 0) + errx(EX_DATAERR, "0 < max_p <= 1"); + p.fs.max_p = (int)(max_p * (1 << SCALE_RED)); + } + ac--; av++; + break; + + case TOK_DROPTAIL: + p.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED); + break; + + case TOK_BW: + NEED1("bw needs bandwidth or interface\n"); + if (co.do_pipe != 1) + errx(EX_DATAERR, "bandwidth only valid for pipes"); + /* + * set clocking interface or bandwidth value + */ + if (av[0][0] >= 'a' && av[0][0] <= 'z') { + int l = sizeof(p.if_name)-1; + /* interface name */ + strncpy(p.if_name, av[0], l); + p.if_name[l] = '\0'; + p.bandwidth = 0; + } else { + p.if_name[0] = '\0'; + p.bandwidth = strtoul(av[0], &end, 0); + if (*end == 'K' || *end == 'k') { + end++; + p.bandwidth *= 1000; + } else if (*end == 'M') { + end++; + p.bandwidth *= 1000000; + } + if ((*end == 'B' && + _substrcmp2(end, "Bi", "Bit/s") != 0) || + _substrcmp2(end, "by", "bytes") == 0) + p.bandwidth *= 8; + if (p.bandwidth < 0) + errx(EX_DATAERR, "bandwidth too large"); + } + ac--; av++; + break; + + case TOK_DELAY: + if (co.do_pipe != 1) + errx(EX_DATAERR, "delay only valid for pipes"); + NEED1("delay needs argument 0..10000ms\n"); + p.delay = strtoul(av[0], NULL, 0); + ac--; av++; + break; + + case TOK_WEIGHT: + if (co.do_pipe == 1) + errx(EX_DATAERR,"weight only valid for queues"); + NEED1("weight needs argument 0..100\n"); + p.fs.weight = strtoul(av[0], &end, 0); + ac--; av++; + break; + + case TOK_PIPE: + if (co.do_pipe == 1) + errx(EX_DATAERR,"pipe only valid for queues"); + NEED1("pipe needs pipe_number\n"); + p.fs.parent_nr = strtoul(av[0], &end, 0); + ac--; av++; + break; + + default: + errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]); + } + } + if (co.do_pipe == 1) { + if (p.pipe_nr == 0) + errx(EX_DATAERR, "pipe_nr must be > 0"); + if (p.delay > 10000) + errx(EX_DATAERR, "delay must be < 10000"); + } else { /* co.do_pipe == 2, queue */ + if (p.fs.parent_nr == 0) + errx(EX_DATAERR, "pipe must be > 0"); + if (p.fs.weight >100) + errx(EX_DATAERR, "weight must be <= 100"); + } + if (p.fs.flags_fs & DN_QSIZE_IS_BYTES) { + size_t len; + long limit; + + len = sizeof(limit); + if (sysctlbyname("net.inet.ip.dummynet.pipe_byte_limit", + &limit, &len, NULL, 0) == -1) + limit = 1024*1024; + if (p.fs.qsize > limit) + errx(EX_DATAERR, "queue size must be < %ldB", limit); + } else { + size_t len; + long limit; + + len = sizeof(limit); + if (sysctlbyname("net.inet.ip.dummynet.pipe_slot_limit", + &limit, &len, NULL, 0) == -1) + limit = 100; + if (p.fs.qsize > limit) + errx(EX_DATAERR, "2 <= queue size <= %ld", limit); + } + if (p.fs.flags_fs & DN_IS_RED) { + size_t len; + int lookup_depth, avg_pkt_size; + double s, idle, weight, w_q; + struct clockinfo ck; + int t; + + if (p.fs.min_th >= p.fs.max_th) + errx(EX_DATAERR, "min_th %d must be < than max_th %d", + p.fs.min_th, p.fs.max_th); + if (p.fs.max_th == 0) + errx(EX_DATAERR, "max_th must be > 0"); + + len = sizeof(int); + if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth", + &lookup_depth, &len, NULL, 0) == -1) + errx(1, "sysctlbyname(\"%s\")", + "net.inet.ip.dummynet.red_lookup_depth"); + if (lookup_depth == 0) + errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth" + " must be greater than zero"); + + len = sizeof(int); + if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size", + &avg_pkt_size, &len, NULL, 0) == -1) + + errx(1, "sysctlbyname(\"%s\")", + "net.inet.ip.dummynet.red_avg_pkt_size"); + if (avg_pkt_size == 0) + errx(EX_DATAERR, + "net.inet.ip.dummynet.red_avg_pkt_size must" + " be greater than zero"); + + len = sizeof(struct clockinfo); + if (sysctlbyname("kern.clockrate", &ck, &len, NULL, 0) == -1) + errx(1, "sysctlbyname(\"%s\")", "kern.clockrate"); + + /* + * Ticks needed for sending a medium-sized packet. + * Unfortunately, when we are configuring a WF2Q+ queue, we + * do not have bandwidth information, because that is stored + * in the parent pipe, and also we have multiple queues + * competing for it. So we set s=0, which is not very + * correct. But on the other hand, why do we want RED with + * WF2Q+ ? + */ + if (p.bandwidth==0) /* this is a WF2Q+ queue */ + s = 0; + else + s = (double)ck.hz * avg_pkt_size * 8 / p.bandwidth; + + /* + * max idle time (in ticks) before avg queue size becomes 0. + * NOTA: (3/w_q) is approx the value x so that + * (1-w_q)^x < 10^-3. + */ + w_q = ((double)p.fs.w_q) / (1 << SCALE_RED); + idle = s * 3. / w_q; + p.fs.lookup_step = (int)idle / lookup_depth; + if (!p.fs.lookup_step) + p.fs.lookup_step = 1; + weight = 1 - w_q; + for (t = p.fs.lookup_step; t > 1; --t) + weight *= 1 - w_q; + p.fs.lookup_weight = (int)(weight * (1 << SCALE_RED)); + } + i = do_cmd(IP_DUMMYNET_CONFIGURE, &p, sizeof p); + if (i) + err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE"); +} Modified: stable/7/sbin/ipfw/ipfw.8 ============================================================================== --- stable/7/sbin/ipfw/ipfw.8 Fri Feb 20 00:05:33 2009 (r188835) +++ stable/7/sbin/ipfw/ipfw.8 Fri Feb 20 00:39:39 2009 (r188836) @@ -1,7 +1,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 5, 2007 +.Dd September 27, 2008 .Dt IPFW 8 .Os .Sh NAME @@ -49,9 +49,13 @@ .Nm .Cm table Ar number Cm delete Ar addr Ns Op / Ns Ar masklen .Nm -.Cm table Ar number Cm flush +.Cm table +.Brq Ar number | all +.Cm flush .Nm -.Cm table Ar number Cm list +.Cm table +.Brq Ar number | all +.Cm list .Pp .Nm .Brq Cm pipe | queue @@ -537,7 +541,7 @@ A match is only declared with the specif This can be useful for a number of applications such as random packet drop or (in conjunction with -.Xr dummynet 4 ) +.Nm dummynet ) to simulate the effect of multiple paths leading to out-of-order packet delivery. .Pp @@ -553,7 +557,7 @@ with a .Dv LOG_SECURITY facility. The logging only occurs if the sysctl variable -.Em net.inet.ip.fw.verbose +.Va net.inet.ip.fw.verbose is set to 1 (which is the default when the kernel is compiled with .Dv IPFIREWALL_VERBOSE ) @@ -564,7 +568,7 @@ parameter. If no .Cm logamount is specified, the limit is taken from the sysctl variable -.Em net.inet.ip.fw.verbose_limit . +.Va net.inet.ip.fw.verbose_limit . In both cases, a value of 0 removes the logging limit. .Pp Once the limit is reached, logging can be re-enabled by @@ -666,7 +670,7 @@ and .Nm .Cm disable Ar altq . The usage of -.Em net.inet.ip.fw.one_pass +.Va net.inet.ip.fw.one_pass is irrelevant to ALTQ traffic shaping, as the actual rule action is followed always after adding an ALTQ tag. .El @@ -760,7 +764,7 @@ see the Section for further information. .It Cm pipe Ar pipe_nr Pass packet to a -.Xr dummynet 4 +.Nm dummynet .Dq pipe (for bandwidth limitation, delay, etc.). See the @@ -770,12 +774,12 @@ The search terminates; however, on exit the .Xr sysctl 8 variable -.Em net.inet.ip.fw.one_pass +.Va net.inet.ip.fw.one_pass is not set, the packet is passed again to the firewall code starting from the next rule. .It Cm queue Ar queue_nr Pass packet to a -.Xr dummynet 4 +.Nm dummynet .Dq queue (for bandwidth limitation using WF2Q+). .It Cm reject @@ -841,12 +845,12 @@ Divert packet into netgraph with given The search terminates. If packet is later returned from netgraph it is either accepted or continues with the next rule, depending on -.Em net.inet.ip.fw.one_pass +.Va net.inet.ip.fw.one_pass sysctl variable. .It Cm ngtee Ar cookie A copy of packet is diverted into netgraph, original packet is either accepted or continues with the next rule, depending on -.Em net.inet.ip.fw.one_pass +.Va net.inet.ip.fw.one_pass sysctl variable. See .Xr ng_ipfw 4 @@ -1193,7 +1197,7 @@ Matches ICMP packets whose ICMP type is .Ar types . The list may be specified as any combination of individual types (numeric) separated by commas. -.Em Ranges are not allowed. +.Em Ranges are not allowed . The supported ICMP types are: .Pp echo reply @@ -1231,7 +1235,7 @@ Matches ICMP6 packets whose ICMP6 type i *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From maxim at FreeBSD.org Thu Feb 19 23:10:34 2009 From: maxim at FreeBSD.org (Maxim Konovalov) Date: Thu Feb 19 23:10:50 2009 Subject: svn commit: r188841 - stable/7/usr.bin/stat Message-ID: <200902200710.n1K7AX1E019621@svn.freebsd.org> Author: maxim Date: Fri Feb 20 07:10:33 2009 New Revision: 188841 URL: http://svn.freebsd.org/changeset/base/188841 Log: MFC r188481: print an octal representation of suid, sgid and sticky bits with -x flag. Modified: stable/7/usr.bin/stat/ (props changed) stable/7/usr.bin/stat/stat.c Modified: stable/7/usr.bin/stat/stat.c ============================================================================== --- stable/7/usr.bin/stat/stat.c Fri Feb 20 06:10:12 2009 (r188840) +++ stable/7/usr.bin/stat/stat.c Fri Feb 20 07:10:33 2009 (r188841) @@ -108,7 +108,7 @@ __FBSDID("$FreeBSD$"); #define LINUX_FORMAT \ " File: \"%N\"%n" \ " Size: %-11z FileType: %HT%n" \ - " Mode: (%04OLp/%.10Sp) Uid: (%5u/%8Su) Gid: (%5g/%8Sg)%n" \ + " Mode: (%OMp%03OLp/%.10Sp) Uid: (%5u/%8Su) Gid: (%5g/%8Sg)%n" \ "Device: %Hd,%Ld Inode: %i Links: %l%n" \ "Access: %Sa%n" \ "Modify: %Sm%n" \ From maxim at FreeBSD.org Thu Feb 19 23:17:09 2009 From: maxim at FreeBSD.org (Maxim Konovalov) Date: Thu Feb 19 23:17:25 2009 Subject: svn commit: r188842 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb net Message-ID: <200902200717.n1K7H6fi019773@svn.freebsd.org> Author: maxim Date: Fri Feb 20 07:17:06 2009 New Revision: 188842 URL: http://svn.freebsd.org/changeset/base/188842 Log: MFC r188575: don't leak a device unit number. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/net/if_vlan.c Modified: stable/7/sys/net/if_vlan.c ============================================================================== --- stable/7/sys/net/if_vlan.c Fri Feb 20 07:10:33 2009 (r188841) +++ stable/7/sys/net/if_vlan.c Fri Feb 20 07:17:06 2009 (r188842) @@ -740,6 +740,7 @@ vlan_clone_create(struct if_clone *ifc, ether_ifdetach(ifp); vlan_unconfig(ifp); if_free_type(ifp, IFT_ETHER); + ifc_free_unit(ifc, unit); free(ifv, M_VLAN); return (error); From maxim at FreeBSD.org Thu Feb 19 23:23:01 2009 From: maxim at FreeBSD.org (Maxim Konovalov) Date: Thu Feb 19 23:23:12 2009 Subject: svn commit: r188843 - stable/7/share/misc Message-ID: <200902200722.n1K7Mwga019967@svn.freebsd.org> Author: maxim Date: Fri Feb 20 07:22:58 2009 New Revision: 188843 URL: http://svn.freebsd.org/changeset/base/188843 Log: MFC r188749,188759: DragonFly 2.2.0. Modified: stable/7/share/misc/ (props changed) stable/7/share/misc/bsd-family-tree Modified: stable/7/share/misc/bsd-family-tree ============================================================================== --- stable/7/share/misc/bsd-family-tree Fri Feb 20 07:17:06 2009 (r188842) +++ stable/7/share/misc/bsd-family-tree Fri Feb 20 07:22:58 2009 (r188843) @@ -226,7 +226,7 @@ FreeBSD 5.2 | | | | 6.4 | | | | | | | | | | | FreeBSD 7.1 | | | | - | | | | | | + | | | | | DragonFly 2.2.0 | V | | | | | | | | | FreeBSD 8 -current | NetBSD -current OpenBSD -current | @@ -495,6 +495,7 @@ DragonFly 2.0.0 2008-07-21 [DFB] OpenBSD 4.4 2008-11-01 [OBD] FreeBSD 6.4 2008-11-28 [FBD] FreeBSD 7.1 2009-01-04 [FBD] +DragonFly 2.2.0 2009-02-17 [DFB] Bibliography ------------------------ From kris at FreeBSD.org Sat Feb 21 04:56:24 2009 From: kris at FreeBSD.org (Kris Kennaway) Date: Sat Feb 21 04:56:35 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat In-Reply-To: <200902180949.32691.jhb@freebsd.org> References: <200902171957.n1HJvqk8026145@svn.freebsd.org> <499BC43B.6030701@incunabulum.net> <200902180949.32691.jhb@freebsd.org> Message-ID: <499FF9F2.3030408@FreeBSD.org> John Baldwin wrote: > On Wednesday 18 February 2009 3:18:03 am Bruce Simpson wrote: >> John Baldwin wrote: >>> Author: jhb >>> Date: Tue Feb 17 19:57:52 2009 >>> New Revision: 188727 >>> URL: http://svn.freebsd.org/changeset/base/188727 >>> >>> Log: >>> MFC: Rework the lifetime management of the kernel implementation of > POSIX >>> semaphores. Specifically, semaphores are now represented as new file >>> descriptor type that is set to close on exec. This removes the need for >>> all of the manual process reference counting (and fork, exec, and exit >>> event handlers) as the normal file descriptor operations handle all of >>> that for us nicely. It is also suggested as one possible implementation >>> in the spec and at least one other OS (OS X) uses this approach. >> FYI: >> This change *may* fix Python 2.6's 'multiprocessing' module on FreeBSD >> 7-STABLE, which is known to have problems there; it depends on POSIX >> semaphores to synchronize its IPC between different fork()'s of the >> Python interpreter. >> >> If anyone else has an interest in ths they may wish to test, if not, I >> will try to get around to it eventually. > > When Kris tested it, it made things significantly better. I'm not sure if it > resolved all the issues though. > Some of the self-tests still failed, but there was confusion about whether the tests were broken or the kernel. Kris From sam at FreeBSD.org Sat Feb 21 11:19:13 2009 From: sam at FreeBSD.org (Sam Leffler) Date: Sat Feb 21 11:19:25 2009 Subject: svn commit: r188898 - stable/7/share/man/man4 Message-ID: <200902211919.n1LJJCs2073388@svn.freebsd.org> Author: sam Date: Sat Feb 21 19:19:11 2009 New Revision: 188898 URL: http://svn.freebsd.org/changeset/base/188898 Log: fix cross-refs to wlandebug PR: docs/131927 Submitted by: David Horn Modified: stable/7/share/man/man4/wlan.4 Modified: stable/7/share/man/man4/wlan.4 ============================================================================== --- stable/7/share/man/man4/wlan.4 Sat Feb 21 16:39:26 2009 (r188897) +++ stable/7/share/man/man4/wlan.4 Sat Feb 21 19:19:11 2009 (r188898) @@ -101,7 +101,7 @@ For example, enables debugging messages related to scanning for an access point, adhoc neighbor, or an unoccupied channel when operation as an access point. The -.Xr 80211debug +.Xr wlandebug tool provides a more user-friendly mechanism for doing the same thing. .Pp Many drivers will also display the contents of each 802.11 frame @@ -135,7 +135,8 @@ was used to be compatible with .Xr wlan_tkip 4 , .Xr wlan_wep 4 , .Xr wlan_xauth 4 , -.Xr zyd 4 +.Xr zyd 4 , +.Xr wlandebug 8 .Sh STANDARDS More information can be found in the IEEE 802.11 Standard. .Sh HISTORY From alc at FreeBSD.org Sat Feb 21 19:02:48 2009 From: alc at FreeBSD.org (Alan Cox) Date: Sat Feb 21 19:03:04 2009 Subject: svn commit: r188909 - in stable/7/sys: . amd64/amd64 contrib/pf dev/ath/ath_hal dev/cxgb i386/i386 Message-ID: <200902220302.n1M32lZ2082427@svn.freebsd.org> Author: alc Date: Sun Feb 22 03:02:46 2009 New Revision: 188909 URL: http://svn.freebsd.org/changeset/base/188909 Log: MFC r188608 Remove unnecessary page queues locking around vm_page_busy() and vm_page_wakeup(). Modified: stable/7/sys/ (props changed) stable/7/sys/amd64/amd64/pmap.c stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/i386/i386/pmap.c Modified: stable/7/sys/amd64/amd64/pmap.c ============================================================================== --- stable/7/sys/amd64/amd64/pmap.c Sun Feb 22 02:50:31 2009 (r188908) +++ stable/7/sys/amd64/amd64/pmap.c Sun Feb 22 03:02:46 2009 (r188909) @@ -2639,9 +2639,7 @@ retry: } p = vm_page_lookup(object, pindex); - vm_page_lock_queues(); vm_page_wakeup(p); - vm_page_unlock_queues(); } ptepa = VM_PAGE_TO_PHYS(p); @@ -2655,15 +2653,11 @@ retry: while ((pdpg = pmap_allocpde(pmap, va, M_NOWAIT)) == NULL) { PMAP_UNLOCK(pmap); - vm_page_lock_queues(); vm_page_busy(p); - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); VM_WAIT; VM_OBJECT_LOCK(object); - vm_page_lock_queues(); vm_page_wakeup(p); - vm_page_unlock_queues(); PMAP_LOCK(pmap); } pde = (pd_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pdpg)); Modified: stable/7/sys/i386/i386/pmap.c ============================================================================== --- stable/7/sys/i386/i386/pmap.c Sun Feb 22 02:50:31 2009 (r188908) +++ stable/7/sys/i386/i386/pmap.c Sun Feb 22 03:02:46 2009 (r188909) @@ -2713,9 +2713,7 @@ retry: } p = vm_page_lookup(object, pindex); - vm_page_lock_queues(); vm_page_wakeup(p); - vm_page_unlock_queues(); } ptepa = VM_PAGE_TO_PHYS(p); From kib at FreeBSD.org Sun Feb 22 02:17:12 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sun Feb 22 02:17:28 2009 Subject: svn commit: r188910 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern sys ufs/ufs Message-ID: <200902221017.n1MAHAiC090149@svn.freebsd.org> Author: kib Date: Sun Feb 22 10:17:10 2009 New Revision: 188910 URL: http://svn.freebsd.org/changeset/base/188910 Log: MFC r187528: Move the code from ufs_lookup.c used to do dotdot lookup, into the helper function. It is supposed to be useful for any filesystem that has to unlock dvp to walk to the ".." entry in lookup routine. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/vfs_vnops.c stable/7/sys/sys/vnode.h stable/7/sys/ufs/ufs/ufs_lookup.c Modified: stable/7/sys/kern/vfs_vnops.c ============================================================================== --- stable/7/sys/kern/vfs_vnops.c Sun Feb 22 03:02:46 2009 (r188909) +++ stable/7/sys/kern/vfs_vnops.c Sun Feb 22 10:17:10 2009 (r188910) @@ -1221,3 +1221,35 @@ vn_extattr_rm(struct vnode *vp, int iofl return (error); } + +int +vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags, struct vnode **rvp) +{ + struct mount *mp; + int ltype, error; + + mp = vp->v_mount; + ltype = VOP_ISLOCKED(vp, curthread); + KASSERT(ltype == LK_EXCLUSIVE || ltype == LK_SHARED, + ("vn_vget_ino: vp not locked")); + for (;;) { + error = vfs_busy(mp, LK_NOWAIT, NULL, curthread); + if (error == 0) + break; + VOP_UNLOCK(vp, 0, curthread); + pause("vn_vget", 1); + vn_lock(vp, ltype | LK_RETRY, curthread); + if (vp->v_iflag & VI_DOOMED) + return (ENOENT); + } + VOP_UNLOCK(vp, 0, curthread); + error = VFS_VGET(mp, ino, lkflags, rvp); + vfs_unbusy(mp, curthread); + vn_lock(vp, ltype | LK_RETRY, curthread); + if (vp->v_iflag & VI_DOOMED) { + if (error == 0) + vput(*rvp); + error = ENOENT; + } + return (error); +} Modified: stable/7/sys/sys/vnode.h ============================================================================== --- stable/7/sys/sys/vnode.h Sun Feb 22 03:02:46 2009 (r188909) +++ stable/7/sys/sys/vnode.h Sun Feb 22 10:17:10 2009 (r188910) @@ -633,6 +633,9 @@ int vn_extattr_set(struct vnode *vp, int const char *attrname, int buflen, char *buf, struct thread *td); int vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace, const char *attrname, struct thread *td); +int vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags, + struct vnode **rvp); + int vfs_cache_lookup(struct vop_lookup_args *ap); void vfs_timestamp(struct timespec *); void vfs_write_resume(struct mount *mp); Modified: stable/7/sys/ufs/ufs/ufs_lookup.c ============================================================================== --- stable/7/sys/ufs/ufs/ufs_lookup.c Sun Feb 22 03:02:46 2009 (r188909) +++ stable/7/sys/ufs/ufs/ufs_lookup.c Sun Feb 22 10:17:10 2009 (r188910) @@ -158,7 +158,6 @@ ufs_lookup(ap) struct thread *td = cnp->cn_thread; ino_t ino; int ltype; - struct mount *mp; bp = NULL; slotoffset = -1; @@ -579,27 +578,7 @@ found: */ pdp = vdp; if (flags & ISDOTDOT) { - ltype = VOP_ISLOCKED(pdp, td); - mp = pdp->v_mount; - for (;;) { - error = vfs_busy(mp, LK_NOWAIT, NULL, td); - if (error == 0) - break; - VOP_UNLOCK(pdp, 0, td); - pause("ufs_dd", 1); - vn_lock(pdp, ltype | LK_RETRY, td); - if (pdp->v_iflag & VI_DOOMED) - return (ENOENT); - } - VOP_UNLOCK(pdp, 0, td); /* race to get the inode */ - error = VFS_VGET(mp, ino, cnp->cn_lkflags, &tdp); - vfs_unbusy(mp, td); - vn_lock(pdp, ltype | LK_RETRY, td); - if (pdp->v_iflag & VI_DOOMED) { - if (error == 0) - vput(tdp); - error = ENOENT; - } + error = vn_vget_ino(pdp, ino, cnp->cn_lkflags, &tdp); if (error) return (error); *vpp = tdp; From kib at FreeBSD.org Sun Feb 22 02:25:09 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sun Feb 22 02:25:18 2009 Subject: svn commit: r188911 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb fs/tmpfs Message-ID: <200902221025.n1MAP7rl093858@svn.freebsd.org> Author: kib Date: Sun Feb 22 10:25:07 2009 New Revision: 188911 URL: http://svn.freebsd.org/changeset/base/188911 Log: MFC r188318: Lookup up the directory entry for the tmpfs node that are deleted by both node pointer and name component. This does the right thing for hardlinks to the same node in the same directory. PR: kern/131356 Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/fs/tmpfs/tmpfs.h stable/7/sys/fs/tmpfs/tmpfs_subr.c stable/7/sys/fs/tmpfs/tmpfs_vnops.c Modified: stable/7/sys/fs/tmpfs/tmpfs.h ============================================================================== --- stable/7/sys/fs/tmpfs/tmpfs.h Sun Feb 22 10:17:10 2009 (r188910) +++ stable/7/sys/fs/tmpfs/tmpfs.h Sun Feb 22 10:25:07 2009 (r188911) @@ -408,9 +408,8 @@ int tmpfs_alloc_file(struct vnode *, str void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *); void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *); struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node, + struct tmpfs_node *f, struct componentname *cnp); -struct tmpfs_dirent *tmpfs_dir_search(struct tmpfs_node *node, - struct tmpfs_node *f); int tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *); int tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *); struct tmpfs_dirent * tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t); Modified: stable/7/sys/fs/tmpfs/tmpfs_subr.c ============================================================================== --- stable/7/sys/fs/tmpfs/tmpfs_subr.c Sun Feb 22 10:17:10 2009 (r188910) +++ stable/7/sys/fs/tmpfs/tmpfs_subr.c Sun Feb 22 10:25:07 2009 (r188911) @@ -572,7 +572,8 @@ tmpfs_dir_detach(struct vnode *vp, struc * Returns a pointer to the entry when found, otherwise NULL. */ struct tmpfs_dirent * -tmpfs_dir_lookup(struct tmpfs_node *node, struct componentname *cnp) +tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f, + struct componentname *cnp) { boolean_t found; struct tmpfs_dirent *de; @@ -584,6 +585,8 @@ tmpfs_dir_lookup(struct tmpfs_node *node found = 0; TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) { + if (f != NULL && de->td_node != f) + continue; MPASS(cnp->cn_namelen < 0xffff); if (de->td_namelen == (uint16_t)cnp->cn_namelen && memcmp(de->td_name, cnp->cn_nameptr, de->td_namelen) == 0) { @@ -596,20 +599,6 @@ tmpfs_dir_lookup(struct tmpfs_node *node return found ? de : NULL; } -struct tmpfs_dirent * -tmpfs_dir_search(struct tmpfs_node *node, struct tmpfs_node *f) -{ - struct tmpfs_dirent *de; - - TMPFS_VALIDATE_DIR(node); - node->tn_status |= TMPFS_NODE_ACCESSED; - TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) { - if (de->td_node == f) - return (de); - } - return (NULL); -} - /* --------------------------------------------------------------------- */ /* Modified: stable/7/sys/fs/tmpfs/tmpfs_vnops.c ============================================================================== --- stable/7/sys/fs/tmpfs/tmpfs_vnops.c Sun Feb 22 10:17:10 2009 (r188910) +++ stable/7/sys/fs/tmpfs/tmpfs_vnops.c Sun Feb 22 10:25:07 2009 (r188911) @@ -104,7 +104,7 @@ tmpfs_lookup(struct vop_cachedlookup_arg *vpp = dvp; error = 0; } else { - de = tmpfs_dir_lookup(dnode, cnp); + de = tmpfs_dir_lookup(dnode, NULL, cnp); if (de == NULL) { /* The entry was not found in the directory. * This is OK if we are creating or renaming an @@ -771,7 +771,7 @@ tmpfs_remove(struct vop_remove_args *v) dnode = VP_TO_TMPFS_DIR(dvp); node = VP_TO_TMPFS_NODE(vp); tmp = VFS_TO_TMPFS(vp->v_mount); - de = tmpfs_dir_search(dnode, node); + de = tmpfs_dir_lookup(dnode, node, v->a_cnp); MPASS(de != NULL); /* Files marked as immutable or append-only cannot be deleted. */ @@ -918,7 +918,7 @@ tmpfs_rename(struct vop_rename_args *v) } fdnode = VP_TO_TMPFS_DIR(fdvp); fnode = VP_TO_TMPFS_NODE(fvp); - de = tmpfs_dir_search(fdnode, fnode); + de = tmpfs_dir_lookup(fdnode, fnode, fcnp); /* Avoid manipulating '.' and '..' entries. */ if (de == NULL) { @@ -1030,7 +1030,7 @@ tmpfs_rename(struct vop_rename_args *v) * from the target directory. */ if (tvp != NULL) { /* Remove the old entry from the target directory. */ - de = tmpfs_dir_search(tdnode, tnode); + de = tmpfs_dir_lookup(tdnode, tnode, tcnp); tmpfs_dir_detach(tdvp, de); /* Free the directory entry we just deleted. Note that the @@ -1118,7 +1118,7 @@ tmpfs_rmdir(struct vop_rmdir_args *v) /* Get the directory entry associated with node (vp). This was * filled by tmpfs_lookup while looking up the entry. */ - de = tmpfs_dir_search(dnode, node); + de = tmpfs_dir_lookup(dnode, node, v->a_cnp); MPASS(TMPFS_DIRENT_MATCHES(de, v->a_cnp->cn_nameptr, v->a_cnp->cn_namelen)); From kib at FreeBSD.org Sun Feb 22 02:28:10 2009 From: kib at FreeBSD.org (Konstantin Belousov) Date: Sun Feb 22 02:28:17 2009 Subject: svn commit: r188913 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb vm Message-ID: <200902221028.n1MAS9EV094057@svn.freebsd.org> Author: kib Date: Sun Feb 22 10:28:09 2009 New Revision: 188913 URL: http://svn.freebsd.org/changeset/base/188913 Log: MFC r188320: Do not leak the MAP_ENTRY_IN_TRANSITION flag when copying map entry on fork. Otherwise, copied entry cannot be removed in the child map. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/vm/vm_map.c Modified: stable/7/sys/vm/vm_map.c ============================================================================== --- stable/7/sys/vm/vm_map.c Sun Feb 22 10:26:02 2009 (r188912) +++ stable/7/sys/vm/vm_map.c Sun Feb 22 10:28:09 2009 (r188913) @@ -2648,7 +2648,8 @@ vmspace_fork(struct vmspace *vm1) */ new_entry = vm_map_entry_create(new_map); *new_entry = *old_entry; - new_entry->eflags &= ~MAP_ENTRY_USER_WIRED; + new_entry->eflags &= ~(MAP_ENTRY_USER_WIRED | + MAP_ENTRY_IN_TRANSITION); new_entry->wired_count = 0; /* @@ -2674,7 +2675,8 @@ vmspace_fork(struct vmspace *vm1) */ new_entry = vm_map_entry_create(new_map); *new_entry = *old_entry; - new_entry->eflags &= ~MAP_ENTRY_USER_WIRED; + new_entry->eflags &= ~(MAP_ENTRY_USER_WIRED | + MAP_ENTRY_IN_TRANSITION); new_entry->wired_count = 0; new_entry->object.vm_object = NULL; vm_map_entry_link(new_map, new_map->header.prev, From bms at incunabulum.net Sun Feb 22 04:58:18 2009 From: bms at incunabulum.net (Bruce Simpson) Date: Sun Feb 22 04:58:30 2009 Subject: svn commit: r188727 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cxgb sys/kern sys/modules/sem sys/sys tools/regression/posixsem usr.bin/procstat In-Reply-To: <200902181054.35709.jhb@freebsd.org> References: <200902171957.n1HJvqk8026145@svn.freebsd.org> <200902181005.28625.jhb@freebsd.org> <499C269D.7030406@incunabulum.net> <200902181054.35709.jhb@freebsd.org> Message-ID: <49A14BE5.7020400@incunabulum.net> John Baldwin wrote: > Hmm, by symbols I meant having things built with debug symbols (i.e. "-g"). > OK... I will try to build a Python interpreter w/debug symbols next time around. I am just giving this a dry run for now -- I am collaborating on a project where we've ended up implementing stuff on Linux using Python multiprocessing as it seemed the best fit for the team's capabilities. So I'm posting this here for lists to pick up, hopefully someone looking to use multiprocessing seriously on FreeBSD will come across this. It would be nice to port to FreeBSD at a later date, unfortunately, we're a bit further down this road now... > Also, do you have 'sem.ko' loaded? The only reason I can think of why you > would get a core dump in ksem_open() itself would be if you got a SIGSYS > because the module wasn't loaded. > That seems to have been the issue! Thanks. If I cd src/modules/sem && make && make install, and kldload the module before running Python, then I do not see the core dump. I didn't realise a separate kernel module was needed for POSIX semaphores, the option seems to be P1003_1B_SEMAPHORES according to sem(4). It is quite possible the Python guys totally missed this... It seems that whilst ipcs(1) is the appropriate tool to examine SYSV IPC facilities, there is no such tool for POSIX semaphores on FreeBSD, or am I wrong? When the Python process is running and using sem(4), I see a segment of shared memory in ipcs(1) output. Perhaps the libc wrapper should be taught to return ENOSYS if the system call(s) it requires are not present, rather than SIGSYS? However, the mp_benchmarks.py script just hangs when testing multiprocessing.Queue. A ktrace reveals that a child process is simply waiting for data on a pipe which doesn't arrive. Killing Python at this point and restarting results in future attempts to open a semaphore by the module failing with ENFILE after the 4th ksem_open() call: %%% Traceback (most recent call last): File "Doc/includes/mp_benchmarks.py", line 238, in test() File "Doc/includes/mp_benchmarks.py", line 192, in test multiprocessing.Condition()) File "/usr/local/lib/python2.5/site-packages/multiprocessing-2.6.1.1-py2.5-freebsd-7.1-STABLE-amd64.egg/multiprocessing/__init__.py", line 190, in Condition return Condition(lock) File "/usr/local/lib/python2.5/site-packages/multiprocessing-2.6.1.1-py2.5-freebsd-7.1-STABLE-amd64.egg/multiprocessing/synchronize.py", line 168, in __init__ self._lock = lock or RLock() File "/usr/local/lib/python2.5/site-packages/multiprocessing-2.6.1.1-py2.5-freebsd-7.1-STABLE-amd64.egg/multiprocessing/synchronize.py", line 142, in __init__ SemLock.__init__(self, RECURSIVE_MUTEX, 1, 1) File "/usr/local/lib/python2.5/site-packages/multiprocessing-2.6.1.1-py2.5-freebsd-7.1-STABLE-amd64.egg/multiprocessing/synchronize.py", line 49, in __init__ sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue) OSError: [Errno 23] Too many open files in system Exit 1 anglepoise:~/p/multiprocessing-2.6.1.1 % %%% From bms at FreeBSD.org Sun Feb 22 05:34:02 2009 From: bms at FreeBSD.org (Bruce M Simpson) Date: Sun Feb 22 05:34:08 2009 Subject: svn commit: r188915 - stable/7/usr.sbin/ifmcstat Message-ID: <200902221334.n1MDY1Kn097387@svn.freebsd.org> Author: bms Date: Sun Feb 22 13:34:01 2009 New Revision: 188915 URL: http://svn.freebsd.org/changeset/base/188915 Log: MFC: Fix a typo which caused ifmcstat's sysctl path to print the network-layer endpoint address of the group membership, rather than its link-layer mapping as intended. The KVM path is not affected. Modified: stable/7/usr.sbin/ifmcstat/ifmcstat.c Modified: stable/7/usr.sbin/ifmcstat/ifmcstat.c ============================================================================== --- stable/7/usr.sbin/ifmcstat/ifmcstat.c Sun Feb 22 12:40:58 2009 (r188914) +++ stable/7/usr.sbin/ifmcstat/ifmcstat.c Sun Feb 22 13:34:01 2009 (r188915) @@ -768,7 +768,7 @@ ifmcstat_getifmaddrs(void) /* Link-layer mapping, if present. */ pllsa = (sockunion_t *)ifma->ifma_lladdr; if (pllsa != NULL) { - error = getnameinfo(&pifasa->sa, pifasa->sa.sa_len, + error = getnameinfo(&pllasa->sa, pllasa->sa.sa_len, addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST); fprintf(stdout, "\t\t\tmcast-macaddr %s\n", addrbuf); } From bms at FreeBSD.org Sun Feb 22 11:23:59 2009 From: bms at FreeBSD.org (Bruce M Simpson) Date: Sun Feb 22 11:24:11 2009 Subject: svn commit: r188928 - stable/7/usr.sbin/ifmcstat Message-ID: <200902221923.n1MJNwq0004470@svn.freebsd.org> Author: bms Date: Sun Feb 22 19:23:58 2009 New Revision: 188928 URL: http://svn.freebsd.org/changeset/base/188928 Log: fix typo! Modified: stable/7/usr.sbin/ifmcstat/ifmcstat.c Modified: stable/7/usr.sbin/ifmcstat/ifmcstat.c ============================================================================== --- stable/7/usr.sbin/ifmcstat/ifmcstat.c Sun Feb 22 18:53:56 2009 (r188927) +++ stable/7/usr.sbin/ifmcstat/ifmcstat.c Sun Feb 22 19:23:58 2009 (r188928) @@ -768,7 +768,7 @@ ifmcstat_getifmaddrs(void) /* Link-layer mapping, if present. */ pllsa = (sockunion_t *)ifma->ifma_lladdr; if (pllsa != NULL) { - error = getnameinfo(&pllasa->sa, pllasa->sa.sa_len, + error = getnameinfo(&pllsa->sa, pllsa->sa.sa_len, addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST); fprintf(stdout, "\t\t\tmcast-macaddr %s\n", addrbuf); } From mav at FreeBSD.org Mon Feb 23 11:52:49 2009 From: mav at FreeBSD.org (Alexander Motin) Date: Mon Feb 23 11:53:10 2009 Subject: svn commit: r188952 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/mmc Message-ID: <200902231952.n1NJqlR0034513@svn.freebsd.org> Author: mav Date: Mon Feb 23 19:52:47 2009 New Revision: 188952 URL: http://svn.freebsd.org/changeset/base/188952 Log: MFC rev. 187525 187543 187546 187551 187875 187877 188044 188725 Sync MMC subsystem with HEAD. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/mmc/mmc.c stable/7/sys/dev/mmc/mmcreg.h stable/7/sys/dev/mmc/mmcsd.c Modified: stable/7/sys/dev/mmc/mmc.c ============================================================================== --- stable/7/sys/dev/mmc/mmc.c Mon Feb 23 19:31:48 2009 (r188951) +++ stable/7/sys/dev/mmc/mmc.c Mon Feb 23 19:52:47 2009 (r188952) @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -104,6 +105,11 @@ struct mmc_ivars { #define CMD_RETRIES 3 +SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver"); + +static int mmc_debug; +SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RW, &mmc_debug, 0, "Debug level"); + /* bus entry points */ static int mmc_probe(device_t dev); static int mmc_attach(device_t dev); @@ -233,7 +239,7 @@ mmc_acquire_bus(device_t busdev, device_ sc->last_rca = rca; /* Prepare bus width for the new card. */ ivar = device_get_ivars(dev); - if (bootverbose) { + if (bootverbose || mmc_debug) { device_printf(busdev, "setting bus width to %d bits\n", (ivar->bus_width == bus_width_4) ? 4 : @@ -315,11 +321,21 @@ mmc_wait_for_req(struct mmc_softc *sc, s req->done = mmc_wakeup; req->done_data = sc; + if (mmc_debug > 1) { + device_printf(sc->dev, "REQUEST: CMD%d arg %#x flags %#x", + req->cmd->opcode, req->cmd->arg, req->cmd->flags); + if (req->cmd->data) { + printf(" data %d\n", (int)req->cmd->data->len); + } else + printf("\n"); + } MMCBR_REQUEST(device_get_parent(sc->dev), sc->dev, req); MMC_LOCK(sc); while ((req->flags & MMC_REQ_DONE) == 0) msleep(req, &sc->sc_mtx, 0, "mmcreq", 0); MMC_UNLOCK(sc); + if (mmc_debug > 2 || (mmc_debug > 1 && req->cmd->error)) + device_printf(sc->dev, "RESULT: %d\n", req->cmd->error); return (0); } @@ -340,7 +356,6 @@ mmc_wait_for_cmd(struct mmc_softc *sc, s memset(cmd->resp, 0, sizeof(cmd->resp)); cmd->retries = retries; mreq.cmd = cmd; -/* printf("CMD: %x ARG %x\n", cmd->opcode, cmd->arg); */ mmc_wait_for_req(sc, &mreq); return (cmd->error); } @@ -555,7 +570,8 @@ mmc_switch(struct mmc_softc *sc, uint8_t } static int -mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value, uint8_t *res) +mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value, + uint8_t *res) { int err; struct mmc_command cmd; @@ -563,11 +579,11 @@ mmc_sd_switch(struct mmc_softc *sc, uint memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); - memset(res, 0, 64); + cmd.opcode = SD_SWITCH_FUNC; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; - cmd.arg = mode << 31; + cmd.arg = mode << 31; /* 0 - check, 1 - set */ cmd.arg |= 0x00FFFFFF; cmd.arg &= ~(0xF << (grp * 4)); cmd.arg |= value << (grp * 4); @@ -584,11 +600,11 @@ mmc_sd_switch(struct mmc_softc *sc, uint static int mmc_set_card_bus_width(struct mmc_softc *sc, uint16_t rca, int width) { + struct mmc_command cmd; int err; + uint8_t value; if (mmcbr_get_mode(sc->dev) == mode_sd) { - struct mmc_command cmd; - memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = ACMD_SET_BUS_WIDTH; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; @@ -604,8 +620,6 @@ mmc_set_card_bus_width(struct mmc_softc } err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); } else { - uint8_t value; - switch (width) { case bus_width_1: value = EXT_CSD_BUS_WIDTH_1; @@ -619,7 +633,8 @@ mmc_set_card_bus_width(struct mmc_softc default: return (MMC_ERR_INVALID); } - err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, value); + err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, + value); } return (err); } @@ -629,6 +644,7 @@ mmc_set_timing(struct mmc_softc *sc, int { int err; uint8_t value; + u_char switch_res[64]; switch (timing) { case bus_timing_normal: @@ -640,14 +656,12 @@ mmc_set_timing(struct mmc_softc *sc, int default: return (MMC_ERR_INVALID); } - if (mmcbr_get_mode(sc->dev) == mode_sd) { - u_char switch_res[64]; - - err = mmc_sd_switch(sc, 1, 0, value, switch_res); - } else { + if (mmcbr_get_mode(sc->dev) == mode_sd) + err = mmc_sd_switch(sc, SD_SWITCH_MODE_SET, SD_SWITCH_GROUP1, + value, switch_res); + else err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, value); - } return (err); } @@ -749,9 +763,10 @@ mmc_decode_cid_sd(uint32_t *raw_cid, str cid->oid = mmc_get_bits(raw_cid, 128, 104, 16); for (i = 0; i < 5; i++) cid->pnm[i] = mmc_get_bits(raw_cid, 128, 96 - i * 8, 8); + cid->pnm[5] = 0; cid->prv = mmc_get_bits(raw_cid, 128, 56, 8); cid->psn = mmc_get_bits(raw_cid, 128, 24, 32); - cid->mdt_year = mmc_get_bits(raw_cid, 128, 12, 8) + 2001; + cid->mdt_year = mmc_get_bits(raw_cid, 128, 12, 8) + 2000; cid->mdt_month = mmc_get_bits(raw_cid, 128, 8, 4); } @@ -766,6 +781,7 @@ mmc_decode_cid_mmc(uint32_t *raw_cid, st cid->oid = mmc_get_bits(raw_cid, 128, 104, 8); for (i = 0; i < 6; i++) cid->pnm[i] = mmc_get_bits(raw_cid, 128, 96 - i * 8, 8); + cid->pnm[6] = 0; cid->prv = mmc_get_bits(raw_cid, 128, 48, 8); cid->psn = mmc_get_bits(raw_cid, 128, 16, 32); cid->mdt_month = mmc_get_bits(raw_cid, 128, 12, 4); @@ -1060,6 +1076,29 @@ mmc_send_relative_addr(struct mmc_softc } static void +mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard) +{ + device_printf(dev, "Card at relative address %d%s:\n", + ivar->rca, newcard ? " added" : ""); + device_printf(dev, " card: %s%s (0x%x/0x%x/\"%s\" rev %d.%d " + "m/d %02d.%04d s/n %08x)\n", + ivar->mode == mode_sd ? "SD" : "MMC", + ivar->high_cap ? " High Capacity" : "", + ivar->cid.mid, ivar->cid.oid, + ivar->cid.pnm, ivar->cid.prv >> 4, ivar->cid.prv & 0x0f, + ivar->cid.mdt_month, ivar->cid.mdt_year, ivar->cid.psn); + device_printf(dev, " bus: %ubit, %uMHz%s\n", + (ivar->bus_width == bus_width_1 ? 1 : + (ivar->bus_width == bus_width_4 ? 4 : 8)), + (ivar->timing == bus_timing_hs ? + ivar->hs_tran_speed : ivar->tran_speed) / 1000000, + ivar->timing == bus_timing_hs ? ", high speed timing" : ""); + device_printf(dev, " memory: %u blocks, erase sector %u blocks%s\n", + ivar->sec_count, ivar->erase_sector, + ivar->read_only ? ", read-only" : ""); +} + +static void mmc_discover_cards(struct mmc_softc *sc) { struct mmc_ivars *ivar = NULL; @@ -1071,6 +1110,8 @@ mmc_discover_cards(struct mmc_softc *sc) uint16_t rca = 2; u_char switch_res[64]; + if (bootverbose || mmc_debug) + device_printf(sc->dev, "Probing cards\n"); while (1) { err = mmc_all_send_cid(sc, raw_cid); if (err == MMC_ERR_TIMEOUT) @@ -1090,6 +1131,11 @@ mmc_discover_cards(struct mmc_softc *sc) } } free(devlist, M_TEMP); + if (bootverbose || mmc_debug) { + device_printf(sc->dev, "%sard detected (CID %08x%08x%08x%08x)\n", + newcard ? "New c" : "C", + raw_cid[0], raw_cid[1], raw_cid[2], raw_cid[3]); + } if (newcard) { ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF, M_WAITOK | M_ZERO); @@ -1100,6 +1146,7 @@ mmc_discover_cards(struct mmc_softc *sc) if (mmcbr_get_ro(sc->dev)) ivar->read_only = 1; ivar->bus_width = bus_width_1; + ivar->timing = bus_timing_normal; ivar->mode = mmcbr_get_mode(sc->dev); if (ivar->mode == mode_sd) { mmc_decode_cid_sd(ivar->raw_cid, &ivar->cid); @@ -1118,13 +1165,15 @@ mmc_discover_cards(struct mmc_softc *sc) mmc_select_card(sc, ivar->rca); mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr); mmc_app_decode_scr(ivar->raw_scr, &ivar->scr); - /* Get card switch capabilities. */ + /* Get card switch capabilities (command class 10). */ if ((ivar->scr.sda_vsn >= 1) && (ivar->csd.ccc & (1<<10))) { - mmc_sd_switch(sc, 0, 0, 0xF, switch_res); + mmc_sd_switch(sc, SD_SWITCH_MODE_CHECK, + SD_SWITCH_GROUP1, SD_SWITCH_NOCHANGE, + switch_res); if (switch_res[13] & 2) { ivar->timing = bus_timing_hs; - ivar->hs_tran_speed = 50000000; + ivar->hs_tran_speed = SD_MAX_HS; } } mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status); @@ -1139,6 +1188,8 @@ mmc_discover_cards(struct mmc_softc *sc) if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) && (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) ivar->bus_width = bus_width_4; + if (bootverbose || mmc_debug) + mmc_log_card(sc->dev, ivar, newcard); if (newcard) { /* Add device. */ child = device_add_child(sc->dev, NULL, -1); @@ -1174,10 +1225,10 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->timing = bus_timing_hs; if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_52) - ivar->hs_tran_speed = 52000000; + ivar->hs_tran_speed = MMC_TYPE_52_MAX_HS; else if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_26) - ivar->hs_tran_speed = 26000000; + ivar->hs_tran_speed = MMC_TYPE_26_MAX_HS; else ivar->hs_tran_speed = ivar->tran_speed; /* Find max supported bus width. */ @@ -1194,6 +1245,8 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->bus_width = bus_width_1; ivar->timing = bus_timing_normal; } + if (bootverbose || mmc_debug) + mmc_log_card(sc->dev, ivar, newcard); if (newcard) { /* Add device. */ child = device_add_child(sc->dev, NULL, -1); @@ -1214,6 +1267,9 @@ mmc_rescan_cards(struct mmc_softc *sc) for (i = 0; i < devcount; i++) { ivar = device_get_ivars(devlist[i]); if (mmc_select_card(sc, ivar->rca)) { + if (bootverbose || mmc_debug) + device_printf(sc->dev, "Card at relative address %d lost.\n", + ivar->rca); device_delete_child(sc->dev, devlist[i]); free(ivar, M_DEVBUF); } @@ -1233,6 +1289,9 @@ mmc_delete_cards(struct mmc_softc *sc) return (err); for (i = 0; i < devcount; i++) { ivar = device_get_ivars(devlist[i]); + if (bootverbose || mmc_debug) + device_printf(sc->dev, "Card at relative address %d deleted.\n", + ivar->rca); device_delete_child(sc->dev, devlist[i]); free(ivar, M_DEVBUF); } @@ -1255,17 +1314,30 @@ mmc_go_discovery(struct mmc_softc *sc) mmcbr_set_mode(dev, mode_sd); mmc_power_up(sc); mmcbr_set_bus_mode(dev, pushpull); + if (bootverbose || mmc_debug) + device_printf(sc->dev, "Probing bus\n"); mmc_idle_cards(sc); err = mmc_send_if_cond(sc, 1); + if ((bootverbose || mmc_debug) && err == 0) + device_printf(sc->dev, "SD 2.0 interface conditions: OK\n"); if (mmc_send_app_op_cond(sc, err ? 0 : MMC_OCR_CCS, &ocr) != MMC_ERR_NONE) { + if (bootverbose || mmc_debug) + device_printf(sc->dev, "SD probe: failed\n"); /* * Failed, try MMC */ mmcbr_set_mode(dev, mode_mmc); - if (mmc_send_op_cond(sc, 0, &ocr) != MMC_ERR_NONE) + if (mmc_send_op_cond(sc, 0, &ocr) != MMC_ERR_NONE) { + if (bootverbose || mmc_debug) + device_printf(sc->dev, "MMC probe: failed\n"); ocr = 0; /* Failed both, powerdown. */ - } + } else if (bootverbose || mmc_debug) + device_printf(sc->dev, + "MMC probe: OK (OCR: 0x%08x)\n", ocr); + } else if (bootverbose || mmc_debug) + device_printf(sc->dev, "SD probe: OK (OCR: 0x%08x)\n", ocr); + mmcbr_set_ocr(dev, mmc_select_vdd(sc, ocr)); if (mmcbr_get_ocr(dev) != 0) mmc_idle_cards(sc); @@ -1279,6 +1351,8 @@ mmc_go_discovery(struct mmc_softc *sc) * Make sure that we have a mutually agreeable voltage to at least * one card on the bus. */ + if (bootverbose || mmc_debug) + device_printf(sc->dev, "Current OCR: 0x%08x\n", mmcbr_get_ocr(dev)); if (mmcbr_get_ocr(dev) == 0) { mmc_delete_cards(sc); mmc_power_down(sc); @@ -1326,7 +1400,7 @@ mmc_calculate_clock(struct mmc_softc *sc max_timing = ivar->timing; if (ivar->tran_speed < max_dtr) max_dtr = ivar->tran_speed; - if (ivar->hs_tran_speed < max_dtr) + if (ivar->hs_tran_speed < max_hs_dtr) max_hs_dtr = ivar->hs_tran_speed; } for (i = 0; i < nkid; i++) { @@ -1340,7 +1414,7 @@ mmc_calculate_clock(struct mmc_softc *sc free(kids, M_TEMP); if (max_timing == bus_timing_hs) max_dtr = max_hs_dtr; - if (bootverbose) { + if (bootverbose || mmc_debug) { device_printf(sc->dev, "setting transfer rate to %d.%03dMHz%s\n", max_dtr / 1000000, (max_dtr / 1000) % 1000, @@ -1454,5 +1528,5 @@ static driver_t mmc_driver = { static devclass_t mmc_devclass; -DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, 0, 0); -DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, 0, 0); +DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL); +DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL); Modified: stable/7/sys/dev/mmc/mmcreg.h ============================================================================== --- stable/7/sys/dev/mmc/mmcreg.h Mon Feb 23 19:31:48 2009 (r188951) +++ stable/7/sys/dev/mmc/mmcreg.h Mon Feb 23 19:52:47 2009 (r188952) @@ -97,6 +97,7 @@ struct mmc_command { #define MMC_ERR_FAILED 4 #define MMC_ERR_INVALID 5 #define MMC_ERR_NO_MEMORY 6 +#define MMC_ERR_MAX 6 struct mmc_data *data; /* Data segment with cmd */ struct mmc_request *mrq; /* backpointer to request */ }; @@ -287,7 +288,6 @@ struct mmc_request { /* * EXT_CSD fields */ - #define EXT_CSD_ERASE_GRP_DEF 175 /* R/W */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ #define EXT_CSD_HS_TIMING 185 /* R/W */ @@ -300,7 +300,6 @@ struct mmc_request { /* * EXT_CSD field definitions */ - #define EXT_CSD_CMD_SET_NORMAL 1 #define EXT_CSD_CMD_SET_SECURE 2 #define EXT_CSD_CMD_SET_CPSECURE 4 @@ -312,12 +311,27 @@ struct mmc_request { #define EXT_CSD_BUS_WIDTH_4 1 #define EXT_CSD_BUS_WIDTH_8 2 +#define MMC_TYPE_26_MAX_HS 26000000 +#define MMC_TYPE_52_MAX_HS 52000000 + /* * SD bus widths */ #define SD_BUS_WIDTH_1 0 #define SD_BUS_WIDTH_4 2 +/* + * SD Switch + */ +#define SD_SWITCH_MODE_CHECK 0 +#define SD_SWITCH_MODE_SET 1 +#define SD_SWITCH_GROUP1 0 +#define SD_SWITCH_NORMAL_MODE 0 +#define SD_SWITCH_HS_MODE 1 +#define SD_SWITCH_NOCHANGE 0xF + +#define SD_MAX_HS 50000000 + /* OCR bits */ /* Modified: stable/7/sys/dev/mmc/mmcsd.c ============================================================================== --- stable/7/sys/dev/mmc/mmcsd.c Mon Feb 23 19:31:48 2009 (r188951) +++ stable/7/sys/dev/mmc/mmcsd.c Mon Feb 23 19:52:47 2009 (r188952) @@ -91,6 +91,8 @@ static int mmcsd_detach(device_t dev); static int mmcsd_open(struct disk *dp); static int mmcsd_close(struct disk *dp); static void mmcsd_strategy(struct bio *bp); +static int mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, + off_t offset, size_t length); static void mmcsd_task(void *arg); static const char *mmcsd_card_name(device_t dev); @@ -130,7 +132,7 @@ mmcsd_attach(device_t dev) d->d_open = mmcsd_open; d->d_close = mmcsd_close; d->d_strategy = mmcsd_strategy; - // d->d_dump = mmcsd_dump; Need polling mmc layer + d->d_dump = mmcsd_dump; d->d_name = "mmcsd"; d->d_drv1 = sc; d->d_maxsize = 4*1024*1024; /* Maximum defined SD card AU size. */ @@ -415,6 +417,33 @@ mmcsd_delete(struct mmcsd_softc *sc, str return (end); } +static int +mmcsd_dump(void *arg, void *virtual, vm_offset_t physical, + off_t offset, size_t length) +{ + struct disk *disk = arg; + struct mmcsd_softc *sc = (struct mmcsd_softc *)disk->d_drv1; + device_t dev = sc->dev; + struct bio bp; + daddr_t block, end; + + /* length zero is special and really means flush buffers to media */ + if (!length) + return (0); + + bzero(&bp, sizeof(struct bio)); + bp.bio_disk = disk; + bp.bio_pblkno = offset / disk->d_sectorsize; + bp.bio_bcount = length; + bp.bio_data = virtual; + bp.bio_cmd = BIO_WRITE; + end = bp.bio_pblkno + bp.bio_bcount / sc->disk->d_sectorsize; + MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev); + block = mmcsd_rw(sc, &bp); + MMCBUS_RELEASE_BUS(device_get_parent(dev), dev); + return ((end < block) ? EIO : 0); +} + static void mmcsd_task(void *arg) { From mav at FreeBSD.org Mon Feb 23 11:58:38 2009 From: mav at FreeBSD.org (Alexander Motin) Date: Mon Feb 23 11:58:50 2009 Subject: svn commit: r188953 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/sdhci Message-ID: <200902231958.n1NJwaqB034748@svn.freebsd.org> Author: mav Date: Mon Feb 23 19:58:35 2009 New Revision: 188953 URL: http://svn.freebsd.org/changeset/base/188953 Log: MFC rev. 187876, 188462, 188724 Sync sdhci driver with HEAD: Add hw.sdhci.debug sysctl to control debug level. Fix read_ivar prototype. Add support for interruptless kernel dumping. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/sdhci/sdhci.c Modified: stable/7/sys/dev/sdhci/sdhci.c ============================================================================== --- stable/7/sys/dev/sdhci/sdhci.c Mon Feb 23 19:52:47 2009 (r188952) +++ stable/7/sys/dev/sdhci/sdhci.c Mon Feb 23 19:58:35 2009 (r188953) @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -151,6 +152,12 @@ struct sdhci_softc { struct sdhci_slot slots[6]; }; +SYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, "sdhci driver"); + +int sdhci_debug; +TUNABLE_INT("hw.sdhci.debug", &sdhci_debug); +SYSCTL_INT(_hw_sdhci, OID_AUTO, debug, CTLFLAG_RW, &sdhci_debug, 0, "Debug level"); + static inline uint8_t RD1(struct sdhci_slot *slot, bus_size_t off) { @@ -734,7 +741,7 @@ sdhci_attach(device_t dev) if (sc->quirks & SDHCI_QUIRK_FORCE_DMA) slot->opt |= SDHCI_HAVE_DMA; - if (bootverbose) { + if (bootverbose || sdhci_debug) { slot_printf(slot, "%uMHz%s 4bits%s%s%s %s\n", slot->max_clk / 1000000, (caps & SDHCI_CAN_DO_HISPD) ? " HS" : "", @@ -1146,17 +1153,10 @@ sdhci_start(struct sdhci_slot *slot) return; } */ - if (req->cmd->error) { - if (bootverbose) { - slot_printf(slot, - "Command error %d (opcode %u arg %u flags %u " - "dlen %u dflags %u)\n", - req->cmd->error, req->cmd->opcode, req->cmd->arg, - req->cmd->flags, - (req->cmd->data)?(u_int)req->cmd->data->len:0, - (req->cmd->data)?(u_int)req->cmd->data->flags:0); - } - } else if (slot->sc->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST) { + if (sdhci_debug > 1) + slot_printf(slot, "result: %d\n", req->cmd->error); + if (!req->cmd->error && + (slot->sc->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) { sdhci_reset(slot, SDHCI_RESET_CMD); sdhci_reset(slot, SDHCI_RESET_DATA); } @@ -1177,13 +1177,22 @@ sdhci_request(device_t brdev, device_t r SDHCI_UNLOCK(slot); return (EBUSY); } -/* printf("%s cmd op %u arg %u flags %u data %ju\n", __func__, - req->cmd->opcode, req->cmd->arg, req->cmd->flags, - (req->cmd->data)?req->cmd->data->len:0); */ + if (sdhci_debug > 1) { + slot_printf(slot, "CMD%u arg %#x flags %#x dlen %u dflags %#x\n", + req->cmd->opcode, req->cmd->arg, req->cmd->flags, + (req->cmd->data)?(u_int)req->cmd->data->len:0, + (req->cmd->data)?req->cmd->data->flags:0); + } slot->req = req; slot->flags = 0; sdhci_start(slot); SDHCI_UNLOCK(slot); + if (dumping) { + while (slot->req != NULL) { + sdhci_intr(slot->sc); + DELAY(10); + } + } return (0); } @@ -1363,23 +1372,23 @@ sdhci_intr(void *arg) SDHCI_UNLOCK(slot); continue; } -/* - slot_printf(slot, "got interrupt %x\n", intmask); -*/ + if (sdhci_debug > 2) + slot_printf(slot, "Interrupt %#x\n", intmask); + /* Handle card presence interrupts. */ if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { WR4(slot, SDHCI_INT_STATUS, intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)); if (intmask & SDHCI_INT_CARD_REMOVE) { - if (bootverbose) + if (bootverbose || sdhci_debug) slot_printf(slot, "Card removed\n"); callout_stop(&slot->card_callout); taskqueue_enqueue(taskqueue_swi_giant, &slot->card_task); } if (intmask & SDHCI_INT_CARD_INSERT) { - if (bootverbose) + if (bootverbose || sdhci_debug) slot_printf(slot, "Card inserted\n"); callout_reset(&slot->card_callout, hz / 2, sdhci_card_delay, slot); @@ -1424,7 +1433,7 @@ sdhci_intr(void *arg) } static int -sdhci_read_ivar(device_t bus, device_t child, int which, u_char *result) +sdhci_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) { struct sdhci_slot *slot = device_get_ivars(child); From gallatin at FreeBSD.org Tue Feb 24 11:41:26 2009 From: gallatin at FreeBSD.org (Andrew Gallatin) Date: Tue Feb 24 11:41:37 2009 Subject: svn commit: r189008 - in stable/7/sys: . contrib/pf dev/cxgb net Message-ID: <200902241941.n1OJfOBD074561@svn.freebsd.org> Author: gallatin Date: Tue Feb 24 19:41:23 2009 New Revision: 189008 URL: http://svn.freebsd.org/changeset/base/189008 Log: MFH r186260: Additional 10GbE media types (10Gbase-LRM, 10Gbase-Twinax*) Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/net/if_media.h Modified: stable/7/sys/net/if_media.h ============================================================================== --- stable/7/sys/net/if_media.h Tue Feb 24 18:53:07 2009 (r189007) +++ stable/7/sys/net/if_media.h Tue Feb 24 19:41:23 2009 (r189008) @@ -145,6 +145,11 @@ uint64_t ifmedia_baudrate(int); #define IFM_10G_SR 19 /* 10GBase-SR 850nm Multi-mode */ #define IFM_10G_CX4 20 /* 10GBase CX4 copper */ #define IFM_2500_SX 21 /* 2500BaseSX - multi-mode fiber */ +#define IFM_10G_TWINAX 22 /* 10GBase Twinax copper */ +#define IFM_10G_TWINAX_LONG 23 /* 10GBase Twinax Long copper */ +#define IFM_10G_LRM 24 /* 10GBase-LRM 850nm Multi-mode */ +#define IFM_UNKNOWN 25 /* New media types that have not been defined yet */ + /* note 31 is the max! */ @@ -349,6 +354,10 @@ struct ifmedia_description { { IFM_10G_SR, "10Gbase-SR" }, \ { IFM_10G_CX4, "10Gbase-CX4" }, \ { IFM_2500_SX, "2500BaseSX" }, \ + { IFM_10G_LRM, "10Gbase-LRM" }, \ + { IFM_10G_TWINAX, "10Gbase-Twinax" }, \ + { IFM_10G_TWINAX_LONG, "10Gbase-Twinax-Long" }, \ + { IFM_UNKNOWN, "Unknown" }, \ { 0, NULL }, \ } @@ -603,6 +612,9 @@ struct ifmedia_baudrate { { IFM_ETHER | IFM_10G_SR, IF_Gbps(10ULL) }, \ { IFM_ETHER | IFM_10G_CX4, IF_Gbps(10ULL) }, \ { IFM_ETHER | IFM_2500_SX, IF_Mbps(2500ULL) }, \ + { IFM_ETHER | IFM_10G_TWINAX, IF_Gbps(10ULL) }, \ + { IFM_ETHER | IFM_10G_TWINAX_LONG, IF_Gbps(10ULL) }, \ + { IFM_ETHER | IFM_10G_LRM, IF_Gbps(10ULL) }, \ \ { IFM_TOKEN | IFM_TOK_STP4, IF_Mbps(4) }, \ { IFM_TOKEN | IFM_TOK_STP16, IF_Mbps(16) }, \ From gallatin at FreeBSD.org Tue Feb 24 12:16:35 2009 From: gallatin at FreeBSD.org (Andrew Gallatin) Date: Tue Feb 24 12:16:58 2009 Subject: svn commit: r189010 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/mxge Message-ID: <200902242016.n1OKGY8J075287@svn.freebsd.org> Author: gallatin Date: Tue Feb 24 20:16:34 2009 New Revision: 189010 URL: http://svn.freebsd.org/changeset/base/189010 Log: MFH r188736 and r188737: Better support for recent Myricom 10GbE NICs Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/mxge/eth_z8e.h stable/7/sys/dev/mxge/ethp_z8e.h stable/7/sys/dev/mxge/if_mxge.c stable/7/sys/dev/mxge/if_mxge_var.h stable/7/sys/dev/mxge/mxge_mcp.h stable/7/sys/dev/mxge/rss_eth_z8e.h stable/7/sys/dev/mxge/rss_ethp_z8e.h Modified: stable/7/sys/dev/mxge/eth_z8e.h ============================================================================== --- stable/7/sys/dev/mxge/eth_z8e.h Tue Feb 24 19:42:49 2009 (r189009) +++ stable/7/sys/dev/mxge/eth_z8e.h Tue Feb 24 20:16:34 2009 (r189010) @@ -1,6 +1,6 @@ /******************************************************************************* -Copyright (c) 2006-2008, Myricom Inc. +Copyright (c) 2006-2009, Myricom Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,7074 +28,6951 @@ POSSIBILITY OF SUCH DAMAGE. $FreeBSD$ ***************************************************************************/ -static unsigned int eth_z8e_uncompressed_length = 369604; -static unsigned int eth_z8e_length = 113069; -static unsigned char eth_z8e[113069 + 1] = - "\x78\x9c\xec\xbd\x7f\x7c\x54\xd5\xb5\x37\xbc\x66\x32\xc0\x24\x0d" - "\x4c\xb4\x94\x8e\x88\x3a\x2a\xb6\xa3\xa2\x46\xc5\x16\x2d\x6a\x2c" - "\x70\x1b\xef\x8b\x12\x21\x68\x90\x1f\x09\x36\xf8\x44\x45\x18\x21" - "\xc0\x04\x43\x26\x0c\xd8\x06\xca\xaf\x6a\xb4\x28\x81\xa4\x15\x6f" - "\xb1\xc5\x8a\xb7\x78\x4b\x5b\x7e\x8c\x12\xef\xa5\x36\xc9\x44\xc1" - "\xe7\x06\x3f\xb4\x4e\x79\x22\x4d\x79\x82\x4e\xc9\x40\x62\x32\x33" - "\xfb\xfd\xae\xbd\xcf\x99\x9c\x99\x9c\x09\x72\xef\xfd\xbc\xef\x3f" - "\xcd\xe7\x73\x72\x66\xef\xbd\xf6\xda\x6b\xad\xbd\xf6\xda\x6b\xff" - "\x38\x7b\x13\xfd\x37\xfe\xac\x47\x03\xff\x9d\xec\xff\xf8\xfb\xc7" - "\xdf\x3f\xfe\xfe\xf1\xf7\x8f\xbf\x7f\xfc\xfd\xe3\xef\xff\x9f\xbf" - "\xb3\x56\x1b\xbd\xbb\x85\xa8\xdb\x6f\x77\x86\x2c\xb7\x4e\xfe\xc9" - "\x0b\x22\x8a\x68\x4b\x88\xec\x4e\x7e\x6b\x0f\x3d\x8f\x78\xeb\x16" - "\xb2\x5f\x93\x43\xd9\x93\xb6\x13\xd5\x8e\x12\x9d\x2f\xbc\x24\xc2" - "\x6b\x5e\x12\x9d\x93\x5f\x23\x6a\x1c\x4b\xf4\xc2\x28\x11\x01\x9e" - "\x39\x21\x5a\x5b\xc9\x78\xd6\x20\xcc\xe9\x6b\x47\x89\x30\xe2\xcb" - "\x11\x1f\xe1\xf8\xd5\xa3\x80\x6b\x24\x91\xff\x25\xd1\x63\xc0\x6b" - "\xe7\xfc\x8c\x73\xf2\xd5\x92\x9e\x9d\x29\x78\x18\xc7\xbe\x10\x3d" - "\xb7\x70\x10\x1c\xd9\x9c\x5f\xd2\x86\x3c\x5d\x7e\x72\x46\xac\x64" - "\x89\xf8\x03\x5f\x43\xde\x08\x78\x72\x73\xde\xcd\x48\x17\x7e\xca" - "\x60\xbc\xc1\x9e\x28\x35\x56\x12\x01\x96\x5c\x55\x64\x39\x45\x99" - "\x77\x03\xde\xb2\x46\xe5\x77\x21\xce\x2a\xe3\x80\x87\xe3\x38\x0d" - "\xf1\x63\x39\xdc\xed\xcf\xcc\x4f\xe0\x64\x59\x70\xba\x35\x60\x45" - "\xba\x05\xf9\x6c\xc8\xb7\xac\xb1\x81\x48\xe1\xca\xc9\x0c\x51\x66" - "\x9d\x96\xaf\x1a\xf9\xaa\x39\xdf\x61\xa4\x4f\xaa\x53\x3c\xce\xa8" - "\x23\x2b\xa7\xb3\x7c\x51\x8e\x15\x70\xbb\x74\xfc\x0a\x87\xf5\x7e" - "\x8d\x9f\xaf\x20\xad\x31\x39\xcd\xf6\xbc\x96\x96\x8d\xb4\x50\x72" - "\x1a\xf0\xa9\xb4\x4b\x90\x16\x4d\x93\x76\x69\xb7\x3f\xcb\x99\x9c" - "\x76\x30\x57\x4b\xfb\x3a\xd2\xc6\x27\xa7\x59\xf4\x7c\x4e\xa4\x15" - "\xe8\x69\xc6\x7a\x51\x1a\x66\xc3\x33\xc4\x4e\x34\x14\xcf\x30\xbb" - "\x5e\x57\x4b\x9d\x22\xee\xbb\x8c\x6c\x62\xfd\x7e\x7b\xdc\x2f\x28" - "\xe8\xed\x21\xd7\x68\xf2\x9d\xa4\xac\x00\xf0\xd2\xa6\x95\x64\xf7" - "\x79\x44\x4f\xd0\xdb\x49\x2d\xe1\x4e\xf2\x85\x45\x47\x30\x7a\x8e" - "\xaa\xce\x91\x3d\x18\x3d\x43\x55\xcf\x90\xb3\xb1\xf2\x53\x32\xd3" - "\x83\xb8\x55\x90\x6f\x0c\xe7\x6d\xa7\x96\xba\x76\xf2\xd5\x25\xe7" - "\xf5\x5d\x41\xce\x66\x84\xa1\x03\x8e\xf2\xad\x22\xde\xe8\x8a\x52" - "\x34\x6b\xbf\xbd\xf2\x35\xb2\xf9\xae\x26\x6b\x73\x69\x80\x5c\xdf" - "\x60\x5a\xbe\x52\xc3\xb4\xac\x7d\x92\xec\xaf\x3e\x1e\xb0\x8a\xf5" - "\x8d\xf6\x5f\xf5\xf6\x58\xd7\x9c\x26\xdb\x61\xe7\x64\x3a\xec\x3c" - "\x41\xc1\xad\x77\x53\x30\x12\xa5\x4d\x4f\x52\xf6\xe1\xc8\x44\x0a" - "\xae\x8d\x13\xe3\x0b\x2e\x9c\x88\xf7\x39\xc0\x74\x92\x6b\x09\xd1" - "\x29\xfa\x8a\xb7\x16\x78\x42\x0a\x27\x74\xe0\x2b\x6b\xdf\xf1\x10" - "\xb1\xcc\x38\x9c\x46\x9f\x73\x5e\x60\x5d\xb5\x4a\x1d\xea\xac\x1f" - "\x25\x3a\xae\xad\xa5\x91\x80\xcf\x41\xfe\xc6\x90\x75\xef\x3e\x4d" - "\x9f\x3b\x6e\xa9\xa5\x9c\xbd\x55\x61\x1b\xf4\xb0\xd3\xe1\x85\xfe" - "\xad\xa4\x21\x8e\x28\x59\xc0\xc3\xeb\xf5\x88\xbb\x76\xa4\xcc\xd3" - "\x13\xa2\xb7\xda\x38\x8f\xf8\xfa\xec\xbf\xc7\xbf\x3e\x3b\x1c\xff" - "\xc9\xec\xb3\xe2\x27\xb3\xbb\x62\x3f\x99\x1d\xf1\x55\x90\x3d\xf6" - "\xf5\xd9\xe7\x5a\x3c\x52\x56\x39\x2d\x1e\xc8\x2a\x46\xf6\x55\x67" - "\x28\x67\xde\x33\xa8\xa3\xe8\x9f\x68\xd5\x13\xe4\x8c\x67\xbe\x1b" - "\x08\x46\x3f\xa2\x79\x95\x24\xf0\xbb\xd5\x8c\xf6\xae\xac\xc6\x7c" - "\xa5\x5b\x76\xb4\xe5\x6c\x0f\x68\x95\xe5\x76\x65\x35\x69\xf1\x4c" - "\x4f\x76\x8d\x1e\x2f\xb2\x1a\x0b\x51\x1f\xbe\x11\xab\x2d\xb4\xa3" - "\x97\xe8\x96\x38\x59\x4e\x53\x76\x2d\x78\xc9\x31\xe2\x9f\x3e\xe5" - "\xe1\xbb\x29\xf7\xce\x9b\x72\x6f\xff\xf6\x84\xdb\xe9\x81\xfb\x26" - "\xdd\x4d\x05\x8f\x4c\xc7\xbf\x07\xef\xa6\xa2\x7f\xba\x1f\x3f\x26" - "\xdd\x7d\x6b\xee\xf7\x6e\x2a\x98\x74\xff\x94\x9b\x26\xd0\x43\x85" - "\xb7\xe5\xde\x76\x1b\xdd\x37\x65\xea\xad\xb9\xb9\xda\xfb\xd6\x5c" - "\x06\x7a\x74\xc2\x94\x19\x37\x15\x2c\x59\x5c\xbe\xf8\xa6\x07\xef" - "\x9f\x64\xb4\x6f\x39\xf1\xe5\x71\xda\x01\x1d\x17\x5d\xf9\xc4\xb2" - "\x0f\x54\x9d\x45\xfd\x0d\xff\x29\xe4\x1f\x56\xba\x9f\xbd\x07\xf4" - "\xdb\xba\xfd\xc3\xf3\x43\xd6\xb7\x9d\x4c\xbf\xeb\x1a\xae\xe3\x11" - "\x5b\xb9\x3d\xa3\x0e\x22\xcc\x5f\x46\xa5\x84\x59\xa8\xd7\x53\x3c" - "\x6b\x7f\x6e\x64\x69\x99\xb4\x3b\x88\x5f\x8b\xbc\x21\x8e\xdf\x84" - "\x70\xa3\x27\x8f\xc4\xab\xf9\x16\x9b\x4b\xda\x0e\x2e\x2f\xb7\x96" - "\x69\xc8\x6a\x2a\x12\x7d\x45\xa4\xc5\xb5\xc6\x39\xbc\xbe\x69\x96" - "\xf0\x21\x6e\xa5\x8c\xfb\x00\xe1\xa2\x6e\xd8\xb3\x6e\x51\x46\xf1" - "\xa5\x45\xac\x6f\x19\xa0\x65\x0a\x78\xe8\x90\xf0\x5d\x32\xff\x50" - "\xc4\x5d\x07\x7c\xb3\xf0\x3c\xaa\xe1\x84\x6d\xbb\x24\x8c\xfc\xb3" - "\xe3\xa2\x88\x44\xf6\x65\x76\xfc\x9e\x13\x58\xd9\x49\xa7\x3c\x64" - "\x0d\x21\x2d\xee\x2b\x23\x43\xf9\x11\xee\x0f\x50\x96\xad\xbb\xaf" - "\x8c\x42\x34\xbc\x47\xe2\x62\x9c\xfd\x30\xed\x5c\x26\x78\x0c\x43" - "\x4e\x6f\x77\xfb\x47\x80\xff\x7f\x33\xca\xa8\x86\xe1\xc1\x73\x07" - "\xf3\x01\x1c\x21\x2e\x03\x38\xad\x1a\x4e\x3d\x3f\xcb\xf9\xa0\x92" - "\xf3\x88\x3d\x29\x72\x6e\x43\xda\x61\xe8\x7d\x24\xc3\x2b\xd3\x5b" - "\xd1\xae\x6a\x39\x1d\xf9\xcb\x99\x46\x65\x8b\x65\x5a\x67\x72\x5e" - "\x87\xd3\x50\x47\x59\xaa\x8e\x1c\x39\x7a\x1d\x71\xfe\x48\xe6\x71" - "\x8f\x56\xfe\x11\xc0\x64\x20\x3d\x37\x05\xc7\x54\xa4\x35\x71\xbd" - "\x8d\xf0\x50\x06\xe7\xd9\x31\x4a\xb7\xff\x12\x5f\x49\x32\x7c\xce" - "\x18\xc0\x7f\xb0\x59\xe1\xfc\x04\x3a\x6d\x83\x2e\x75\x1e\xf6\x72" - "\x3f\xe7\xd8\x90\x2c\x1f\xc7\x2e\x96\x8b\x94\x87\x90\xf2\xd0\xf9" - "\xe9\x44\xde\x53\x80\xdf\x9f\x02\xdf\x06\x79\xcd\x92\xf5\xdf\x35" - "\x00\xfe\x33\xc0\x77\x26\xc3\xe7\x64\x4b\xfd\x51\x79\xf4\x7a\x2c" - "\xd7\xea\xd5\x92\x52\x26\xf3\x33\xbc\xdb\x9f\x93\xc2\xff\x25\xfb" - "\x80\xfb\xfc\x26\xd5\x46\x46\xa0\xde\x6f\x02\xde\x05\x23\xc2\xe4" - "\x40\xd8\x61\x08\xe7\xe0\xb9\x44\x74\xff\x3f\x71\xc4\xdd\x86\xb8" - "\xe7\xd0\x9e\xac\x08\xc7\x54\xf8\x92\xb7\x10\xb6\x80\x9e\x47\x05" - "\xeb\x59\x77\x3e\xeb\xd0\x78\xc4\xbf\xae\xa5\xff\x54\xc2\x03\x26" - "\xce\x7a\xd6\x95\xd0\xd9\x97\x99\x3e\xd6\x5b\x3d\x9f\x58\x21\xd3" - "\x26\x21\xed\x39\xbc\xef\xc7\xfb\x19\xbc\x1f\xc2\xfb\x01\xdf\x17" - "\xe4\xf4\xc5\x44\x87\x16\xbe\x13\xef\xe9\x78\x5f\x87\xf7\x0c\xbc" - "\x2f\xe1\x36\xc6\x3c\x87\x9f\x45\xfb\xc9\x92\x6d\x69\xa8\x51\x96" - "\xc6\xf6\x95\x88\x53\x70\x56\xa3\xfc\x40\x07\xb7\xdd\x02\xf0\xd9" - "\xc1\x65\x6a\xb8\x86\x98\xe0\xb2\x99\xe0\xb2\x18\x71\x85\x28\x67" - "\xbf\xcf\x2b\x04\xde\xbb\x46\x44\x38\x7c\x49\x03\xe4\x60\x43\x78" - "\x2d\xcb\x44\xd9\x90\x4b\x8e\x24\xd7\xed\xf0\x72\x96\x89\xae\x3b" - "\x5a\x59\x43\x8c\x65\x99\xd9\xea\x3e\xeb\xc8\x77\xd0\x0f\x5f\xda" - "\xe7\x73\x93\xa8\xd9\xef\xba\x89\xc8\x3a\xae\x9a\x32\x83\xd1\x63" - "\x34\x2d\x2a\x62\x78\xfa\xae\x27\xba\x24\x18\x6d\xa2\x6f\x12\x5d" - "\x1d\x8c\xd6\xa2\x2f\x28\xe7\xb4\x43\xd7\x92\xc5\x82\xb7\xef\x06" - "\xb2\x5a\x82\xd1\xf1\x88\xdf\x49\x63\xc9\x66\xf9\xa7\xe7\x44\x77" - "\x30\x3a\x19\xe1\x85\x54\x1c\xa3\x9c\xa9\x43\x84\x6f\x5a\x4c\x7c" - "\xf2\x4f\x43\xe2\x22\x18\x6d\x44\x7c\x29\x4d\x8b\x7d\x21\xa6\xc5" - "\xba\xf1\x7c\x8e\xe7\x13\x3c\x87\xf0\xf8\x84\x58\xb7\xdf\xd5\x87" - "\x3e\x02\x34\xe5\xf6\x89\xb2\x0c\xd0\x94\x8b\x3e\x43\x88\xac\xfd" - "\x79\xc1\xe8\x44\xe0\xb3\x12\x60\x72\xfb\xfa\x90\xb6\x7e\xff\xbd" - "\x12\x26\x6b\xff\x3d\x32\x5c\xb3\xbf\x40\xd8\xf7\xe7\xdd\x54\x4d" - "\xc3\x98\xfe\x38\x64\x16\x8c\xa2\x9f\x8e\x7e\x4a\xd3\x2a\xc2\x82" - "\x79\x18\xb1\x5a\xe0\xf7\x21\x01\xb9\x3a\xa6\x55\xf8\x44\x71\x94" - "\xec\x22\x93\x71\x77\x32\xde\x02\xe0\x7a\x40\xc3\xe5\x01\x6c\x98" - "\xe1\x18\x97\x8e\x87\x71\x30\xec\xb4\x18\xf4\x7d\xdd\x7e\x4f\xdf" - "\xba\xfd\x25\x78\xaa\xf1\xec\x41\xde\x77\xfb\x9e\x95\x72\x6c\xc5" - "\xef\x50\x0f\xea\x55\xca\x31\x46\xc3\x00\xdb\x8a\xfa\x98\xdc\x2d" - "\xe9\x3e\x40\x92\xee\xf5\xfb\x45\x8f\xa2\x3f\xae\xf1\x13\xe3\xf8" - "\x08\xea\x0d\x30\xae\x88\x4c\x3b\x70\x15\xf2\x15\xca\x7c\x35\x07" - "\x5c\xc2\x7e\x20\x37\x0e\x7d\x84\x3c\xab\x59\x96\x90\x6f\x35\xfb" - "\x49\x2c\x53\xb1\x0e\xe9\x99\x07\x72\xfb\xd6\x1d\xc8\x43\xfe\xe9" - "\x7d\x02\xb4\x64\x1d\x28\xe9\x51\x65\x16\x03\xcf\x9c\x6e\xc6\x69" - "\x3f\x50\x02\x5c\x9e\x2f\xfc\x2e\xc8\x42\xf4\x4c\x8b\xae\x8e\x16" - "\x57\x50\x86\x9b\xaa\x41\xef\x76\xf8\x63\x0b\x81\x6f\x2d\xa7\x7d" - "\x32\xad\x82\xbe\x8a\xb2\x0e\x01\x6f\x09\x97\x87\x32\x3c\xc0\xf9" - "\x34\x70\x95\x32\x4d\xbd\x7e\xca\x41\xb8\xba\x57\xd1\xd7\x10\xaf" - "\x39\x10\x88\xdb\x0f\xec\x31\xea\x8f\x92\x19\xeb\xcd\x1b\x1c\x97" - "\xa3\xeb\x4a\xac\xe6\xc0\x96\x1b\x89\x72\x1e\x8c\x88\x28\xeb\xcb" - "\x2d\xe4\xb1\xb4\x44\x9a\xa8\x38\x6a\xa7\x16\xcf\x5e\xba\x81\xd8" - "\x67\x8b\x50\x4b\xa4\x16\xe1\x8d\x78\x97\x53\x73\xe7\x4e\x62\x1a" - "\x1f\xf4\x44\x56\xc7\xec\x07\x73\x9a\x3b\x1f\x20\xe4\x3f\x04\x1a" - "\xe3\xf3\x3c\xb6\xea\x16\x4f\x84\xc3\xbe\xe6\x4e\xe8\x68\x4c\xc4" - "\xa2\x35\x07\xaa\xa3\xf6\x83\xae\x07\xcf\x89\xf0\x03\x9d\xd5\x43" - "\x10\xd7\xe7\xb0\x88\xa8\xc3\xeb\x13\xcd\x9d\x6b\x69\xde\x39\xb2" - "\x34\x97\xed\x95\xba\x3a\xcf\xe3\x21\x99\xff\x5c\xd4\x31\xb7\xb3" - "\x9a\xe6\x96\xd1\x08\xc0\x7f\xce\xba\x2b\x46\x54\x53\x53\x7b\x29" - "\x3d\x70\x26\x9a\xf1\xe0\xb9\x3e\xd1\x54\x52\x4b\xcd\x65\xb5\x2c" - "\x8f\x06\xf6\x99\x1e\x38\xd3\x25\x1e\x3c\xd7\x2d\x9a\xcb\xde\xa0" - "\xa6\x92\xbd\x34\xf5\xd3\x80\x23\xb6\xee\xc0\x96\x78\xe6\x81\x3d" - "\xf1\x75\x07\x02\xd1\x75\x07\xaa\x63\x99\x07\x73\xa2\x99\x07\x5d" - "\x62\xfd\xc1\x2d\x90\x5f\xa6\xac\x8b\xac\x83\x9b\xf0\xdb\x25\xeb" - "\xd7\x7e\xb0\x41\xd4\x1c\x0c\xf4\xad\x3b\xb8\x27\xe8\x9d\x48\x22" - "\xf3\x60\x03\xeb\xbc\x58\x77\x30\x00\xb8\x80\xd2\x91\x83\xad\xac" - "\x23\x80\x09\xe1\x09\xf7\xad\x3b\x84\xb6\x72\xa8\x00\x38\x2e\x51" - "\xf8\x0e\x4d\x63\xb8\xb8\xfd\x50\x41\xbc\xe6\x50\x89\xb0\x1f\xf2" - "\xc0\xb7\xb2\x3e\xf8\x4c\x0f\xe4\x07\xd9\x79\x21\x77\x3f\xda\x87" - "\x37\x86\x70\x8c\xe6\x3d\x43\xbe\xa0\xf7\x04\x7e\x9f\x20\x71\x70" - "\x0b\x3d\xf8\xcc\x21\xc1\x69\x0f\x3e\xe3\x13\x90\x8d\x23\x9e\x09" - "\x3c\xeb\x80\x27\x13\x78\xd6\x07\x2e\xed\x61\x9d\xaa\x09\xe4\x3c" - "\xf0\x9c\x08\x0b\x7b\xc0\x13\x1f\x4a\xb2\x6d\xc4\x0f\x0a\xa1\xda" - "\x47\x27\x74\x72\x74\x75\xb1\x97\x1a\xc4\xba\x40\x8e\xc8\x0c\x20" - "\xdf\xbb\xff\x0a\xbb\x95\x21\xa4\x8d\x79\x77\x4f\xdf\xba\x77\x5b" - "\xf1\x04\xfa\xdb\x14\xb7\xbd\x77\xf7\x7c\xd9\xf1\x43\xb7\x7f\x14" - "\xc6\x3f\xc7\xa4\xff\x84\xdf\xe8\xff\x3f\xda\xab\xfd\x3e\x11\xa2" - "\xfd\xd9\xd2\xa7\x84\x2d\xf3\x54\xd1\xd7\x4e\xd3\xd7\xb7\x80\x5f" - "\xc2\xef\x6c\xfc\xae\x9d\x76\xfd\x21\x11\xdf\x60\x9b\x80\x3a\xed" - "\x66\x5b\x23\xfc\xe3\xd9\xff\xc8\xeb\xee\x2e\xb3\x8b\x6e\x77\xb6" - "\xc8\x6a\x7e\x49\xf4\x39\xd9\xf7\x75\x20\x3c\x02\xb2\x1b\x8b\xf7" - "\xa5\xdb\xcf\xd3\x48\x3c\xce\xed\xfe\x78\x35\xdb\x52\xfc\xce\x15" - "\x2b\x9c\x59\x9b\x96\xd3\x38\x47\x84\xec\xf5\xfe\x78\x91\x63\x75" - "\x0e\xc1\xef\x1e\xc9\xbf\x85\x3f\x90\x5b\x7f\x9e\x6c\xec\x8f\xc7" - "\x87\xa3\x3c\xaf\x43\x88\xa5\x6e\xaa\x5f\x02\x7b\x83\xb1\x69\xbd" - "\x5f\xec\x89\x75\xbb\xad\x4c\xa7\x4e\x0b\xd3\x06\x3a\xaf\x00\x9d" - "\x3b\x67\x56\xe4\xd1\x7b\xf0\x11\xcc\x6c\x76\xb7\xff\xeb\x09\xfe" - "\xd3\xa4\xb7\xeb\x32\x31\x4f\x77\xda\x74\x39\xa5\x19\x7b\x8c\xe4" - "\xb6\x1c\x3b\x2f\xc2\x9b\x17\x11\xcb\xc2\xe9\x8b\x8a\xff\x03\x7b" - "\x5a\x5d\x15\xa3\x2b\xa6\x55\x5c\x25\x82\x61\x11\x08\x7a\xcf\xc8" - "\x71\x7f\x3d\x60\xaa\xa2\x22\xae\x8f\xbf\x6b\x5f\x82\xef\xb9\xae" - "\xd9\x2b\xd6\x35\x97\x77\x2d\x17\x51\xf8\x47\xed\x28\xd3\x1b\xa2" - "\x5b\xa3\xaa\x6e\x0e\x34\xc0\x7f\x68\xef\xb2\x37\x97\x03\xf7\x25" - "\x8c\xbb\xc5\x23\x02\xf1\xcc\xe6\x4a\xc0\x35\x84\xe8\x2f\xd9\xc6" - "\xb1\xff\x5a\xe0\x5c\x0b\x9c\x48\xdb\x1f\xa2\x2b\x06\xcc\x01\xa8" - "\x59\x0a\x42\xbd\xb8\xfa\x27\x37\x2c\x9a\xfa\xe8\x7f\x39\x78\xf2" - "\xcc\x93\x75\xbe\xd1\xf6\x5c\x5d\xf0\xf9\x7d\xab\x68\x0c\xea\xe1" - "\xf2\xd3\x74\xd9\xad\xe8\x87\x4f\x09\xbf\xf3\xc8\xab\x2b\x7b\x30" - "\x26\xbf\x6c\x62\x88\x76\xd5\xa6\x93\x9b\x60\xdb\x77\x5e\x74\x6c" - "\x5e\x9e\x90\xd9\x5f\xa6\x55\xc4\x05\xff\xe6\x36\x55\x8f\x78\x96" - "\x07\xf0\xac\xd5\x65\x91\x46\xfe\x36\x51\xd3\x5c\xa3\x7c\xea\xcb" - "\xda\x05\xc6\xc8\x81\x2b\xa3\xfc\xfb\x53\xe9\x33\xd4\x1c\xdc\xd3" - "\x05\x5b\xc1\xe3\x33\x8c\xef\x22\x18\x4f\xf7\x00\x67\x5b\x88\xae" - "\x0e\x69\xf3\x11\x91\x60\x74\x0a\xdb\x8d\x3d\xe9\xeb\x57\xc7\x3f" - "\xe6\x98\x86\x33\x20\xec\xc7\xf7\x56\x29\xba\x7b\xaa\x22\xa2\x83" - "\x71\xf3\xf8\xa7\x1d\x30\x3b\x50\x0f\xa2\xe6\xf8\xae\x4d\x1c\xb7" - "\xbc\x97\xe3\x3e\x82\x1e\x0b\x45\xd7\x98\x8f\x20\xb7\xaf\xc3\xc7" - "\x0d\x07\x56\xf6\xd2\xa9\x4a\xca\xe0\x71\x67\xb7\x7f\xf4\xc2\x10" - "\xdd\xd3\x20\xc7\x7e\x7e\xfa\x45\x97\x75\xe6\x4c\xc4\x55\x87\xe8" - "\xde\x46\x19\x67\xa5\xaf\x21\xbc\x25\x01\x03\x1c\x08\x37\x18\xf2" - "\xcc\xec\xb2\xde\xf0\x0b\xc4\xed\x4d\xc9\xd3\x98\x92\xe7\x98\x1e" - "\x06\x7d\x9d\xae\xe5\x92\xaf\x17\x91\xbf\x01\x4f\xb5\x56\x6e\x4f" - "\x32\x8e\xcb\xed\xc9\x38\x2e\x77\x0e\xa4\xf5\xf2\x71\x29\x79\x26" - "\xa6\xe4\x99\x3a\x90\xd6\xcb\x4b\x52\xf2\x78\x52\xf2\x54\xeb\x61" - "\x6d\x0e\x26\x17\x71\xb5\x29\x79\x76\xa6\xe4\xd9\x6b\x08\x7f\x15" - "\xe1\x04\xff\x5c\xd7\xf0\x07\x04\x8f\xab\xa1\xb7\xac\xc3\x0d\x6c" - "\x4f\x79\xce\x63\x69\x25\xdc\x8b\x75\x07\x1b\x00\x1f\xd1\xf1\xeb" - "\xba\x23\xe1\x95\xfe\x74\x28\xfd\x19\xe3\x4c\xc0\xc0\xc5\x6a\x74" - "\x45\x08\xb2\xec\xe0\xf9\xb2\x60\x64\x8a\x36\xde\x1c\x33\x87\x75" - "\x4a\x2f\xd3\x51\xa9\xf4\x86\xe7\x0e\xf4\x32\x43\xd0\x15\xee\xaf" - "\x0c\xfa\xd9\xce\x65\x69\x65\x54\xea\x65\x00\x77\x3b\xeb\x8f\x9c" - "\x2f\x01\x7e\x2d\xdf\x1e\x25\xf7\x31\x3b\x93\xe5\x31\x66\x6f\xb2" - "\x3c\xc6\x34\x1a\x65\xc8\x36\x22\x44\x97\xd7\xa4\xf3\x71\xe1\xef" - "\x78\xe0\x93\x5f\xe9\x8b\x8b\x93\xa7\xe8\x8a\x59\xd0\xfb\x0c\x7e" - "\x4b\x3f\xaa\x07\xfc\xda\x8f\x4e\x94\x3e\x54\xe5\x39\xf4\xb9\x12" - "\xf6\xab\x80\x6d\x07\xcc\xfd\x1a\xec\xfd\x6a\x4e\x4f\xbe\x87\xf1" - "\x1b\xfe\xd4\xd3\xb0\x45\x25\x61\x1f\xf7\xdb\xc7\x3d\x7a\x18\x63" - "\x12\x8c\x09\xaf\x70\x8a\x75\x47\x27\x9a\xd3\x82\x3e\x53\xd9\xd6" - "\x4e\x94\xf3\x75\xb6\x11\x90\xdf\x65\xb0\x33\x7f\xa9\x5a\x45\x5f" - "\x65\xfb\x20\x32\x9b\x6b\x95\xbc\xaf\xd8\x2d\xfc\xd5\x14\x44\x6f" - "\xe8\x59\x4e\x97\xc3\x9e\x6e\x38\x4d\x57\xbc\x53\x5c\xe9\x02\xad" - "\x18\xc7\x7e\x46\x24\xfb\x8e\xcc\xe6\x2d\xdc\x8f\xd6\x7f\xc6\x63" - "\xca\x2b\x42\xba\x6d\xc1\xef\xce\xc1\xec\x3c\xea\x2e\xac\xc6\x54" - "\x57\xce\xe2\x3a\x3a\x49\x57\x4e\x66\x7e\xd5\x5c\xe8\x95\x77\x88" - "\xf3\x62\x8e\x60\x5f\x1c\xbe\x46\x88\xae\xf4\xe0\x1d\x96\x8f\x9f" - "\x4a\xb4\x70\x08\x70\x63\xc5\xf9\x38\xc3\xa0\x0e\xae\x9c\x28\xfc" - "\x16\xb6\x71\xfb\xbb\xfd\x57\x96\x85\x68\x7c\x40\x8d\xab\xaf\x1c" - "\xcf\xb8\xd2\xd0\x10\xea\x9f\x67\xb9\xf2\x03\x57\x95\x85\xe9\x78" - "\x4d\xda\x24\xe0\xaa\xb7\xaa\xfe\x36\x0e\x5a\x77\xf8\xe3\x65\xe8" - "\x5b\xcb\xe2\xeb\xff\xb7\x57\xfe\xd6\xd2\x98\x8e\x38\xca\x37\xc5" - "\x9f\xb0\x51\x57\xad\xd2\xec\x5c\x6b\xdc\x7e\x30\xac\xd9\x67\x1e" - "\x17\x66\x9e\xa4\xab\x2a\x11\xc6\x58\xf3\x2a\xd7\xaf\xe2\x61\xeb" - "\x3b\xe5\x7a\x17\x71\x55\xa5\xc9\x93\x8f\xa7\x08\x4f\xa9\x16\xf6" - "\x48\x1e\xba\x4a\x31\x4e\xbb\xaa\x32\x9e\x09\xf9\xd4\xb0\xbc\xae" - "\x2a\x10\x5d\x63\xad\xfa\xef\xfa\xbf\xf3\xdc\xc0\x55\xd0\xff\x2b" - "\x2b\xd3\xd6\x47\x82\x56\xd7\x9d\x06\x5a\x43\x06\x5a\xed\x27\xc9" - "\x35\x41\xa3\xb5\x29\x99\x56\xd7\x04\x3c\xe8\xd2\x5c\x63\xf0\x8c" - "\xd3\xc2\x86\xe7\xaa\x30\xca\x47\x5d\x5c\xd1\xa3\xea\x84\xe3\x50" - "\x06\xcb\xe2\xef\x64\x8f\xf7\x15\x11\xcf\x8f\x72\x3c\xcb\x93\xe3" - "\xe3\xf0\x83\x10\xce\x41\x7a\x0e\xeb\xca\xe6\xb8\xd2\x05\x73\x9f" - "\xc2\x55\x94\xf0\xbd\xe0\x7b\xb2\xfe\x76\xd2\xd5\xa5\xd0\x71\xf0" - "\xf1\x9f\x5e\xd5\xd7\x5c\xbd\x80\xc3\x68\x5b\x7f\xc1\xef\x92\x66" - "\x48\xaf\x77\x7d\x53\x7e\x9f\x95\x86\xf5\x5a\x29\x2f\xba\xc9\x36" - "\x27\x9a\xd5\x58\x18\xec\xd8\x4b\x2d\xd1\x7f\x25\xd7\x93\x12\xc7" - "\xac\x60\x19\x6c\x55\x85\x88\xbd\xd9\xbb\x0b\xe3\xb9\xcf\x03\xe8" - "\x9b\xaf\x3a\x4d\x57\x4b\xfa\x7f\x74\x12\xdc\xcd\x93\xb8\x15\x3f" - "\xd9\xb6\x09\x9b\x1e\x87\x7d\x39\x25\x22\xf0\xe3\xb2\x36\xf6\xd2" - "\xb8\x57\x56\x52\x6e\x5d\x2f\x8d\xdd\xd1\x4b\x6e\xf1\x57\xb7\xb5" - "\x0e\xfe\xd9\xbc\x73\x39\x04\x1d\x2a\x1a\xe1\x21\xfb\x8e\x95\xf0" - "\xd3\xa2\x64\x89\x6d\x84\x9f\x16\x85\x9f\xf6\xb9\x9b\xdb\x52\xc2" - "\x4f\xeb\xeb\x63\x3f\xad\xb9\x87\x61\xd0\x06\x7b\x86\x97\x91\x25" - "\xbb\x84\x72\x40\x9f\xef\x33\x72\xbd\x9c\xdd\x0e\x1f\x11\x3c\x87" - "\x34\x7e\x21\xb3\xdd\x8e\x32\x1a\x26\x79\x45\xfb\x16\xeb\xfe\xd3" - "\x9b\x6e\xdd\x83\x6d\x6d\xe0\xca\x08\xcf\x47\x33\x0f\x6f\xf1\x5c" - "\xed\xde\xd1\x3d\xb6\xa5\x75\xa2\x87\xe3\xcb\xaf\x16\x3d\x88\xdf" - "\xca\x65\xef\x41\x7c\xb7\xff\xea\x40\xc8\xfa\xd6\x89\x8b\x99\x6f" - "\x67\x7f\x42\xae\x89\xc8\xbe\xe3\x1a\x4a\xe9\x7f\x60\x33\xae\x19" - "\xa9\xdb\xdb\xf2\xab\xc9\x59\xee\x12\x1d\x83\xcc\x49\x47\x74\x3f" - "\xef\xf0\x18\x99\xb7\x20\xe1\x77\xa8\xb5\x15\x52\x3e\xc3\x35\xb2" - "\x0d\xb3\x4f\xc0\x7d\x0c\xfb\xc1\x3c\x87\xaa\xe6\xbd\xae\x59\x6b" - "\xf0\x55\xb8\x8f\x89\xec\x5d\xd9\x63\xe3\xfc\xcc\xa7\x96\xbf\x34" - "\x9d\x3d\xe7\xb5\x1e\xf8\x22\x5b\x5b\xea\x88\x5a\xe0\xf2\x35\xd7" - "\xe5\xc1\x3f\xea\x95\xbe\xe8\x49\xba\x46\xce\x99\x07\x16\xf5\x12" - "\xff\x0e\x56\xde\x45\x41\xc0\x28\x7b\x7a\xed\xd8\x46\xaf\x9a\xff" - "\x6b\xf4\x9c\xe5\x75\x1f\x11\x58\xc2\x76\xe7\xda\x87\x0e\x57\x86" - "\x41\xd7\xb5\x63\xf4\x39\xe9\x10\x5d\x5b\xc0\xe5\x77\xd5\x1c\xdf" - "\xc2\xf3\x7b\x72\xce\x2e\x32\x81\x61\xf2\x42\x74\x4d\x62\x2d\x09" - "\x7e\x2c\xec\xde\x35\x3d\x83\xd0\x9a\xa3\xfa\xac\x6b\xbd\xc9\xfe" - "\xc5\x10\xf4\x73\xd7\x6e\x48\xee\xe7\xae\xad\x4b\xee\xe7\xae\xdd" - "\x9d\xec\x5f\x58\xe1\x5f\x5c\x1b\x48\xc9\xd3\x9a\x92\x27\x64\xc8" - "\xb3\x45\x2b\x27\x92\x9c\x67\xac\x2d\x39\xcf\xd8\x91\x86\x30\x78" - "\x1c\x3b\x56\xaf\x9f\x2e\xb9\x5e\x31\x76\xbc\x21\x6c\xad\x95\x6b" - "\x7a\x63\xf3\xf5\x38\xf4\xa3\x04\xff\x30\xc2\x3a\xa1\xe1\x2b\x4d" - "\xd1\x31\x86\xf7\xa6\xd0\x50\x93\x42\xc3\xd6\x84\x4f\x03\xfc\xa8" - "\xaf\x77\x4f\xd1\x75\x1e\xa9\x43\xec\xd3\x55\xd1\x34\x0e\x03\xd7" - "\x56\xc0\x43\x0e\x63\x8f\xa4\xe0\x6b\x4b\xc1\xd7\x61\x08\xe7\x20" - "\xdc\x63\xe0\x21\x27\xc3\x49\x16\xe8\x0b\xc6\x14\xd7\xe5\xe8\xf1" - "\xec\xdb\x82\xde\x0e\x9f\x5c\x2b\xca\xe3\x35\xa9\x4b\x4f\xd2\xd8" - "\x18\xfb\xc1\x0a\xe7\x75\x46\xff\x8f\x14\x5f\xd7\x15\x24\xd3\x71" - "\x5d\x49\x32\x1d\xd7\x79\x0c\x7c\x45\x1c\xab\xe9\x21\x47\x74\xfa" - "\x2c\xf6\x93\x79\xdd\x90\xfd\x55\xf8\x6d\x4e\x94\x99\xc3\xeb\x60" - "\xa7\xca\x29\x23\xe8\xed\x80\x1f\xd2\x1c\x49\xab\x4f\x59\xc7\x1b" - "\xb4\x75\x14\x17\xf0\xb7\xea\xfa\x88\xdf\x18\xff\x5e\x3b\x47\xda" - "\xe0\xf5\x47\x03\xc2\x57\xb4\x15\x72\x44\x5f\xfe\x8d\xf7\x54\x7f" - "\x72\x7c\x2f\xb7\x45\xf8\x4b\x1d\xb0\x33\xd9\x6a\xbe\xfa\x1b\x39" - "\x06\x7d\x8e\xb8\x56\xde\x2b\x4e\xd2\x37\x3e\x60\x3b\xc4\xfe\x1f" - "\xfb\xfc\x87\x23\x61\xf4\x0d\xa7\x89\x69\x46\x5a\xab\x96\x2f\xdf" - "\x90\x2f\xcc\x6d\x8a\xe1\x39\xed\x96\x28\xd9\x38\x0f\x70\x8c\x94" - "\xe3\x01\xe0\x3b\x8c\x36\x8a\x3c\x95\x7a\x1e\xc0\xca\x3c\x8e\x72" - "\xb2\xdd\x5c\x49\xb6\xc0\xca\x93\x12\xb7\x56\xdf\x1d\x1b\x21\x97" - "\x60\x65\x07\x7c\xc3\x36\x1e\x53\xdb\x02\x55\x27\x19\x4f\x6b\x46" - "\x0f\xd9\xbb\xd6\x1d\xc7\x98\xe1\x1b\xad\xb1\x75\xc7\xb7\xc6\x6b" - "\x8e\xef\x09\xd1\x75\x3d\xd0\x3f\x53\x9b\x65\xbe\x46\x48\x8e\xcd" - "\xfe\x78\x5b\xa0\xaa\x9d\x71\x46\xb9\xdf\x0d\x3a\xa3\xd4\x52\x17" - "\x45\x3f\x43\x39\x72\xad\x10\x63\xdb\x60\x03\x7c\x53\x8c\xdb\x8a" - "\xbd\x94\x07\x5f\xa3\x4d\x24\xf2\x45\x90\xef\x9b\xe3\x99\xd6\xb5" - "\x1c\x8f\xfc\xb0\x99\x61\xf6\x65\xd3\xf4\xeb\x0e\x86\x0b\x5c\xc3" - "\x7d\xfb\x37\x17\x2a\xdf\x86\xf2\xe1\xcb\xb4\x99\xae\x9f\x59\x29" - "\xd8\xed\xff\xe6\xae\x10\x4d\xca\xd7\x75\xed\xf0\x56\x59\xdf\x18" - "\x83\x7e\x13\xed\xff\x1b\xe1\x74\x3e\x84\xa6\x97\x1e\xc0\x0e\x03" - "\x6c\xe7\x60\xb0\x4c\xf7\x61\xf0\x2d\xd6\x37\x95\xbc\x5a\x95\x3b" - "\x44\xd3\x29\xf4\xe5\xee\xb1\x7a\xbe\x2f\xc3\x1f\xdb\x63\xb6\x09" - "\xe8\x17\x22\x6a\x2e\xfa\xfa\x97\x79\xed\x12\x78\x30\xfe\xfb\xe6" - "\x16\x8d\x87\xaf\x20\x8c\xfa\xff\x66\x8f\xbe\xee\xc5\x7d\xdf\x52" - "\x0f\xfa\x04\x67\x04\xba\xe1\xde\xaa\xa7\xc9\xf1\x05\xa7\x61\xfc" - "\x72\xd8\xd9\xce\x69\x7b\x13\x69\x9c\x8f\xe9\xf6\x46\x39\xbe\x49" - "\x8f\x57\x76\xcb\x7d\x22\x25\xdc\xa9\x87\xf1\x1b\xed\xff\x9b\x25" - "\xfa\x7a\x3d\x74\x8e\xe7\xeb\x2d\x27\xe9\xfa\x59\x3b\xa4\x3d\xbb" - "\xde\xa9\xa7\x33\x5d\xbe\x9f\x8a\x30\xcf\x3d\xc6\xb3\x9a\x4a\xa4" - "\x9d\x47\x9e\x37\xcf\xf6\x0c\xc1\xd8\xd2\x22\xfa\xca\x88\xe3\x18" - "\x0f\xf7\x6b\xd0\x77\xee\xdb\x3a\x81\x2b\xbb\x9e\xf5\x1a\xf5\xba" - "\x22\x4a\x63\x3c\xf7\xf0\x18\xe2\xfa\x22\xa9\xd3\x7e\xa9\x3f\x82" - "\xf1\xc1\x27\x90\xb8\x19\xdf\x26\xee\x33\xbb\x78\x0d\xec\x7a\xe6" - "\xbf\x29\xfd\x9c\xcd\xf5\xfb\x0c\xb2\x1c\x82\xf0\x91\x64\x5e\xaf" - "\x6f\x4b\x09\x77\xe8\x61\xc8\xab\x5a\xe9\xde\xf5\x27\x54\xda\x0d" - "\xb6\xc1\xca\x62\x7f\x01\x30\xee\xe4\xf2\x6e\x98\x90\x8c\xff\x86" - "\xfc\x94\x70\x91\x1e\xae\x95\xeb\x13\x37\x94\xe9\x65\xc8\x3a\x83" - "\x8e\xed\xac\x0a\x0f\xf9\x72\xfa\x73\xe3\x3b\x4a\x7f\x6e\xd8\x6d" - "\xa0\x61\x28\xc2\xfb\xfb\xeb\xf3\x86\x23\x3a\x7e\xfc\x3e\x66\x80" - "\x43\x1b\xb9\xa1\x3d\x55\x5f\x96\x7a\x59\xcf\x58\x67\x6e\x24\x93" - "\xb4\x1e\x2d\x6d\x8c\xb9\x9e\xdd\x38\xde\x10\x1f\x56\xbe\xc4\x8d" - "\x2f\xeb\x7d\x93\x5c\xdb\xf3\x15\x5a\xa4\x8f\xf3\x92\xd2\x0b\xe8" - "\x43\x44\xea\x85\xdc\xbb\x72\x63\x79\x2a\xde\xc0\xca\x68\x3f\x8e" - "\x7e\x9c\x93\xd5\x5a\xdc\x8d\x3b\xfb\x79\xbb\x11\xf6\xed\xfa\x9d" - "\xba\xde\x2a\x3f\xfa\x86\x86\x74\xfe\x06\xe0\x43\xc9\x32\xbb\x31" - "\xdc\x2f\xb3\x1b\xa3\xfd\x78\xc7\xd9\x0d\x70\xff\x81\xb0\xb3\x1f" - "\x6e\xdc\xd8\x0b\xe9\x87\xda\xef\x33\x6e\x6a\x72\x59\xe3\xe6\x18" - "\x70\x94\x19\xca\x2a\x37\xc0\xb5\x21\xbc\x36\x7d\xfd\x8c\x6b\x48" - "\x5f\x3f\xe3\xf6\x9b\xd7\xcf\xb8\x63\x86\x72\x43\x17\xd6\xed\x9b" - "\x6c\x06\x7a\xea\x11\x1e\x99\xac\xcb\x37\x8d\x4d\x09\x27\xea\x5f" - "\xa0\xfd\xee\x5c\x99\x37\x84\xe3\xe1\x2b\xe7\x28\x5d\xbf\xa9\xd0" - "\x98\xfe\x66\xaf\x4a\x67\x1a\x79\x0e\x44\xce\xfd\x29\xb8\xca\x54" - "\x38\x86\x31\xa4\xd7\xe9\xb4\xaf\x45\x38\xd5\xbf\x4f\xd8\x6d\xad" - "\x1f\x0a\xc6\xb9\x1f\xba\x69\xbf\x1a\x03\x37\x97\x08\xff\xa1\xa2" - "\x74\x7d\x0a\x70\xc3\xfe\xdd\xb4\x47\xcd\x01\x35\x97\x40\x8f\x7a" - "\x4f\xd1\xcd\x3f\xc6\xbb\x0f\xef\x65\xc9\x7d\xdb\xcd\x39\x18\x7b" - "\xcf\xa8\xf7\xa7\xf6\x79\x37\xbb\xe1\xbf\xf4\x3a\xa2\xd5\x45\x26" - "\x69\x93\x85\x3f\x63\xba\x49\x3c\xcf\x21\xf4\x86\xe8\xe6\x2d\x4c" - "\xa3\x21\xbe\x5c\xf8\x47\x14\x32\x7c\x88\xcb\x43\x1e\xf3\xf9\x81" - "\xe6\x92\xa5\x97\x91\x13\x74\x7e\x71\x8a\x6e\xb9\x7e\xa9\x53\x8e" - "\x83\x41\xf3\x2d\xab\x52\xca\x69\x4c\x43\xf3\x09\xd0\xfc\x45\x1a" - "\x9a\xa5\xdf\x2e\xac\xa0\x7b\x40\xff\x7e\xcb\x48\xd0\xfd\x85\x94" - "\x6b\x72\xfc\x38\xdf\xcb\xc4\xf4\xca\x3c\x33\x2a\xfb\xeb\x43\x4b" - "\x9f\xea\xd8\x4a\x05\x03\xcb\xba\xa5\x54\xf8\x87\xcd\x08\xd1\x2d" - "\x75\x7a\x7f\xa0\xc5\x57\x2a\x1a\x20\x0b\xab\x94\x45\x23\xe7\x4b" - "\x57\x8f\x7a\xdb\x63\x39\x74\xfb\x6f\x41\xff\x77\x73\x9d\xde\x67" - "\xa2\xbf\x0c\xb3\xac\xb4\xb4\x8e\x94\xb4\x9e\xfe\xb4\x5c\x5b\x52" - "\xda\xaa\x44\xfc\x18\x3d\xfe\x02\x75\x01\xf9\xe7\xbe\xc3\x79\x92" - "\x79\xcc\xcd\x37\xaf\x83\xdc\x12\xd4\x41\x9f\x79\x1d\xe4\x56\x9a" - "\xeb\x4d\x6e\xad\x78\x9e\xcc\x70\xed\x46\xbd\xf4\x71\xbd\x70\x3d" - "\x0c\x94\x7f\x6e\x93\x2e\xff\x0b\xf0\x10\x3b\x45\xb7\x2e\xeb\xd7" - "\xa7\x5b\xdf\x49\xc6\x73\xeb\x48\x73\x5e\x6e\x1d\x07\x5e\x62\xe6" - "\xbc\xdc\x9a\x6f\xce\xcb\xad\x68\x9b\x14\x1b\xa8\x4b\xb7\x7a\x11" - "\x6f\x06\xbf\x45\xf8\x4d\xf1\xef\x62\xdf\x21\x44\xb7\x9e\xe0\x39" - "\x21\x43\x7c\xa0\xbf\x2d\x81\x6e\xe4\xe1\xf9\xa2\x40\xd5\x6d\xc4" - "\xf4\x9c\x72\x91\x75\x30\x79\x80\xff\xcf\x4f\xd1\x6d\xab\xe3\x56" - "\xcb\x4e\x25\x8b\xdb\x6f\x4d\x2e\xf7\x36\x97\xb9\x2c\x6e\x9b\x00" - "\x59\x7c\x6e\x2e\x8b\xdb\x0a\xcd\x65\x71\xdb\x42\xf0\xfc\xf9\x40" - "\x59\xdc\xb6\x56\x97\x05\xc6\x93\x0e\xb1\xad\x58\xdc\xec\x21\x3b" - "\xf8\xcc\x71\xa0\x8e\x15\x5c\x27\xc3\xed\x76\xf4\xa8\xfa\x75\x2d" - "\x21\xfb\x67\x74\x5b\x9d\xdc\x47\xb2\x6d\xb6\x18\x11\xa6\x61\x0c" - "\x1f\xf4\x7e\x1e\x08\xa2\xa7\xe3\x31\x7d\x4a\x19\x1d\xe6\x6d\xf3" - "\x76\x96\xd3\xf3\x26\xf1\x4e\xb5\x1f\xe3\xf6\xa9\xc9\x6d\xf6\xf6" - "\xdc\x7e\x79\x43\x36\xc8\x63\xd8\x2f\x3b\xe8\x33\x78\x1d\x8c\xbf" - "\x5a\xc9\x7f\xfc\x90\x14\x3a\x1a\xcc\xe5\x7f\xfb\xbe\xf4\xf2\xbf" - "\xfd\x98\xb9\xfc\x6f\xe7\x39\x9a\xcf\x43\x34\xde\x95\x6c\x8f\xc7" - "\xdb\xfa\x79\xba\x9d\xf7\x9b\x38\x84\x7f\xe8\x57\x39\xfc\x65\x79" - "\xd3\x1f\xe0\xb7\xd4\xbf\x42\x90\xa9\xe5\xea\xff\x4a\xfe\x74\xcf" - "\x96\xd1\xe6\xeb\xa1\x18\x2b\x90\xeb\x4a\x1e\xe7\x8e\xff\x14\xba" - "\xd3\x86\xdf\xd6\x53\xf4\xad\x8d\x71\xbf\xb5\x52\x93\xed\x27\xa7" - "\xe8\x8e\xf9\x4a\xb6\xdf\x7a\x3a\x59\x1e\xe3\xa3\xe6\xb2\xbd\x63" - "\x24\x64\xfb\x89\xb9\x6c\xef\xc8\x4d\xdf\x6f\xdc\x31\x15\xfc\x7f" - "\x32\x50\xbf\xef\x28\x55\x79\x68\x0d\xe7\x51\xfb\x42\xef\xf8\x88" - "\x61\x94\x1e\xdf\x71\x80\xd3\x59\xe7\x0d\x79\xb6\x02\x57\x51\xbf" - "\xae\xdf\x51\xab\xe1\x30\xe2\xdd\xef\x08\x9b\xe9\xf4\x1d\x72\x5d" - "\xef\xe6\x88\x94\x4f\xd1\x0e\x2e\x73\x39\xd1\x67\xf4\xad\xeb\x19" - "\x8e\xe3\xaf\x75\x1a\x75\xfa\x5b\x36\x1d\x8e\x6d\x8c\x82\xbd\x23" - "\x2a\xb6\x95\x11\xc3\x25\xe3\xfe\x96\xc6\xff\xb0\x19\xf5\x1a\x3c" - "\xc3\xa5\xc0\x14\xaa\xb6\xf3\xad\xad\xc9\x6d\xe7\x5b\x0b\x93\xfb" - "\xbb\xf1\x3c\xde\x72\xc4\xfd\x16\xf8\xbc\xe3\xdb\x41\xc3\x97\xd6" - "\x97\x41\xda\x12\xea\xfb\xdb\x4f\xab\xfa\xfe\xf6\x43\x29\x74\x75" - "\x9a\xd7\xf7\xb7\x6d\xe9\xeb\xfb\xdb\x2e\xf3\xb6\xf4\xed\x09\x5c" - "\xd7\x21\xfa\xf6\xc2\xe4\xb6\xf4\xed\x82\xfe\xb6\xf4\xad\x4e\xd5" - "\x96\xe8\x92\x8b\x69\x0b\xf0\x15\xd2\xb6\x3d\xbd\x7d\x7d\x59\x99" - "\xa0\x3d\x30\x4d\xd2\xd7\xc1\x18\x7f\x02\xcb\xa8\xc5\x29\xf7\xbc" - "\xfb\x4e\xd1\x84\x0a\x9e\xc7\x55\xb2\xba\xf3\x8e\x64\xfe\x26\x38" - "\xcd\x65\x35\x21\x17\xb2\xf2\x99\xcb\x6a\xc2\x54\x73\x59\x4d\x28" - "\xe5\x3d\xbe\x03\xdb\xc5\x84\x4a\xb6\xfb\xa0\x91\xf7\x50\xb4\x7d" - "\x46\x13\x9a\xa5\xfd\xef\x2a\x16\xd0\x3b\x13\xfb\x3f\xa1\xdf\xfe" - "\x8f\xe6\x36\x31\x41\xfa\x53\xa2\x0b\xf6\x7f\x2b\x0d\xe3\xbe\xa0" - "\xbf\x0f\xc8\x35\xe9\x03\x26\x74\x9a\xf7\x01\x77\xda\xcc\xfb\x80" - "\x3b\xc7\x28\x3d\xbe\xb3\x20\x59\x8f\xef\x1c\xdf\x5f\xc7\x90\xd3" - "\xff\x4c\x1f\xb0\xf9\x14\xdd\x95\x89\x7e\xb8\x5a\xd5\xc7\x5d\xbf" - "\x4d\xa1\x65\x97\x79\x7d\xdc\x19\x40\x7d\x6c\x36\xaf\x8f\x3b\x4f" - "\x98\xd7\xc7\x9d\x3c\x7e\xda\x3c\xb0\x3e\xee\xca\xfe\x72\xfd\xf0" - "\x5d\xe3\x93\xfb\xe1\xbb\xc6\x7e\xf9\x7e\xf8\x2e\x8f\x79\x1d\xdc" - "\x55\x63\x5e\x07\x77\x35\xa8\x3a\xb8\xeb\x58\x72\x1d\xdc\xb5\xaf" - "\xbf\x0e\x20\x9b\xff\x7e\x1d\x94\xaa\xf5\xdd\xef\xdc\xd1\x25\xe7" - "\xcf\xbe\x33\x2e\x44\xdf\x89\xa8\xf5\x80\xef\x74\xa8\x39\x54\x59" - "\x4f\x6f\x02\xc6\x35\xd0\x16\x7f\x27\x5f\x8b\x7b\x64\x60\xbf\xf0" - "\x9d\x52\xd8\xc9\xce\xc6\x4a\xb9\xd6\xa3\xea\x09\xf2\xdd\x0c\x38" - "\x35\x17\xf0\x9d\xb5\x9c\x17\xf5\x28\xf8\xbb\x14\xb6\xad\x80\x8f" - "\x30\x9e\x46\x57\x2c\x45\x7e\xdf\xd9\x73\x31\xfd\x66\x3a\x5e\xd9" - "\x3f\x3c\x45\xf7\xcc\x67\x98\x38\xf3\xb5\x9c\xea\x4f\xd1\xc4\x8d" - "\x78\x43\xf7\xee\xb9\x2f\xb9\xcc\x89\x63\xcd\x75\x6f\xe2\x44\xd0" - "\x5c\x6f\xae\x7b\x13\x8b\xd2\xf7\x93\x13\xe5\x9e\x54\xe8\x58\x7d" - "\x5c\xf9\xf2\x97\xce\xab\x0c\xa5\xf8\xf2\x13\xb7\xea\x7d\x5b\x57" - "\x26\xea\x66\x39\xcb\xfd\xee\x9b\x34\xfa\xae\x4b\x81\x6d\x54\x65" - "\x59\x66\x98\x94\x15\x02\x8d\x6f\xa6\xa1\x31\x6a\xde\x3e\xee\x1e" - "\xa9\xd5\xe5\x9b\x22\x33\xb5\x8d\xdc\x0d\xff\xcf\x6c\x6c\x72\xb7" - "\x5e\xff\x45\x92\x86\xa4\xfa\xbd\xbb\x34\xb9\x7e\xa9\xa8\x1c\xe3" - "\x35\x13\xb8\x0d\x46\x38\xde\x8b\xc3\xb0\xac\x03\x26\xb0\xfb\x52" - "\x71\xa6\x81\x0b\x0d\xd0\x2d\xde\x9b\x61\xaa\x5b\xf7\x64\xab\xb6" - "\x76\xcf\xc2\xe4\xb6\x76\xcf\xd8\xfe\xb6\x36\xb1\x31\x25\x4f\x5e" - "\x72\x9f\x3e\x71\xac\xec\xd3\xa1\x53\xf8\xbd\x97\xeb\xed\x7f\xc0" - "\x36\x1e\x3a\x45\xf7\x6a\xfe\xf1\xbd\x29\xf3\x15\xf7\x04\xcc\x75" - "\xf3\x9e\x36\xf0\x7c\xc8\xbc\xde\xef\x89\x98\xd7\xfb\xbd\x6c\xff" - "\x0e\x69\xe3\xcb\x4b\x67\x54\xe6\x0d\x4b\x49\x1f\x67\x6e\xbb\xee" - "\x4d\x33\xff\x71\xef\x1c\x25\xcf\x7b\xb7\x24\xcb\xf3\x5e\xc3\xfc" - "\x07\xe8\xff\x9f\xe9\x3f\x82\xa7\x28\xef\x7e\x25\xa3\xfb\x6e\x4a" - "\xa1\xa3\xdd\x5c\x46\xf7\x46\x21\xa3\xa0\xb9\x8c\xf2\x9c\xe9\xdb" - "\x6f\x1e\xfa\x3f\x0a\x0e\xec\x3f\xf2\xa6\xfa\xb6\xcb\xf9\x11\xd9" - "\x0e\x67\x44\xe1\x7f\xfa\xf5\x74\xee\x37\xf2\x78\xfc\x27\x1c\x63" - "\xa8\x20\xb8\x35\xca\x7b\x90\x72\x18\xae\xb8\x32\x75\x9d\x24\x4f" - "\xf9\xba\x7e\x41\x0e\x6f\x02\xd6\xae\xc3\xa6\xe0\xe4\xfe\x4f\xe8" - "\x70\x6a\x5e\xa6\x3a\xc5\x96\xe4\xb5\x9b\xd7\x5b\x5e\x9a\xf6\x7f" - "\xdf\x48\x55\x6f\xf7\xa5\x8c\xfd\xee\x1b\x97\xac\xeb\x90\xeb\x45" - "\xd4\x1d\xaf\xa3\x98\xd6\xdf\x9a\xd9\x6d\x9e\x2a\xba\xf2\x34\xdd" - "\xf7\x37\x89\x1f\x61\xfe\x1e\xaa\x38\x4a\x56\xb1\xe6\x29\xe8\xb1" - "\x85\xea\xfd\xa2\x67\xb3\x55\xb4\x6e\xf6\x8b\xd6\x60\xf4\x2c\xfb" - "\x6c\x5f\x3d\x49\xf7\xfd\x56\xd1\x27\x7a\x94\x2c\xee\xdb\xc3\xb0" - "\xdd\xfe\xfb\x3a\xf4\xf9\xbe\x74\xe5\xf1\xfe\x6c\xc6\x3d\xf8\x1c" - "\xef\x77\x73\x21\x83\xb5\xfa\x5a\x2e\xc2\x79\xfd\xfb\x8b\xbe\x3b" - "\x15\x69\x5f\xea\xbb\x4e\xc0\x7a\x8d\x78\xd4\x37\x9d\xdf\xdd\xa0" - "\xef\x11\xc2\xef\xad\x17\xc0\xa5\xd3\x13\x48\xa1\xa7\x15\x7d\xff" - "\x5a\x0d\xc7\x89\xc1\x70\x70\x3d\x29\xfd\xe2\x7a\xfc\x6e\x64\xb0" - "\x79\xa2\x0c\x27\x15\xbc\x30\x40\xe7\x27\xb9\x59\xd6\x8c\x23\x5d" - "\x1b\x54\x7d\xea\xe4\xcb\x54\x1b\x9c\xf4\x45\x4a\xfe\x32\x35\x77" - "\xa8\xfa\xa8\x79\xd1\x54\x1d\x9d\x54\xe3\x88\x98\xe9\xe8\xa4\x06" - "\x5d\x47\xe1\xf3\x32\xde\xe3\x29\xe9\x01\xa5\xab\x93\x9d\xe8\x27" - "\x0d\xe3\x90\x49\x72\xfc\x20\x2e\x55\x6d\x31\x04\xb8\x94\x7c\x3d" - "\xc9\xba\x3c\xa9\x6c\xb0\x79\x58\x8d\xb7\xb7\x14\x6f\x53\x7e\x9c" - "\x8c\x6b\xf2\xe4\xc1\x79\x9b\x5c\x6a\xce\xdb\xe4\xca\x64\xde\xa6" - "\x3c\x93\x92\x2e\xfd\xfb\xae\x01\x7d\xf0\xe4\xbd\xba\x9f\xea\xba" - "\x86\xfd\xcf\x29\x43\xa4\xbf\x5a\x5f\x2c\xc6\xba\xcc\xfc\xd5\xc9" - "\xed\x09\x7f\x55\xc2\x4f\x56\xfb\x5e\xeb\xe1\xaf\x36\xa4\x8e\x1b" - "\xf2\xe8\x70\x34\xd5\x67\x9d\x32\xd6\x51\x67\x46\xff\x94\x89\x9a" - "\x8d\x7c\x7e\xa0\x8d\x9c\x52\xa4\xea\x65\xca\x9e\x64\x1b\x32\xc5" - "\x93\x5c\x2f\x93\xeb\x52\xf2\x6d\x49\xae\x97\xc9\x93\xff\xab\xfd" - "\x03\x0f\x12\x33\x32\x32\xac\x19\x16\xab\x25\x03\xc9\x60\x93\x86" - "\x65\xd8\x32\x86\xe0\x19\xaa\xbd\x87\x59\x33\xac\x36\x3c\x43\xb4" - "\xf7\xd0\x94\xf0\x30\xce\x8b\xc7\xa6\xbd\x87\xa4\x84\x87\x5e\x20" - "\x7d\x98\x56\xae\x5e\xbe\x2d\x25\x3c\xe4\x02\xe9\x43\xff\x9b\xf9" - "\x69\x40\x38\x79\x9f\xd4\xfd\x8b\x96\xcf\x5f\xf8\x44\xa9\x6b\xc5" - "\x92\x27\xca\x17\xb8\xe6\x7f\xff\xfb\x0b\x96\x2e\x75\x95\x2f\x76" - "\x7d\xf7\xbe\xe9\xb7\xdd\xe5\xca\xf5\x5e\xe7\x1d\xe7\x5a\x78\xf7" - "\x75\xa5\x59\xf4\xc0\x8a\x25\x9c\xf0\xc0\x8c\xfb\x8b\x5c\x05\xdf" - "\xbd\x2f\x39\x51\x47\xb3\x64\xc1\xfc\xd2\x41\xb1\x18\x6c\x5a\xde" - "\xba\x51\x44\x1b\x47\x49\xdb\xd6\xde\x8c\x51\x8e\x1a\xab\x3f\xb6" - "\xa0\x69\x27\x91\xe8\xf5\x89\xc0\x35\xbc\xe7\xe2\x7b\x6f\x33\x13" - "\x37\x35\x54\x93\xe7\x71\xfe\x8e\xe1\x7b\x1f\x88\x83\x61\x72\xfd" - "\x33\x59\x4f\xd2\xea\xcc\x46\x78\x9d\x1c\x0e\xb6\x47\xc9\xe5\x23" - "\x3b\xf2\x5f\x82\x34\x8b\xb8\x27\x8e\xb8\x88\xb6\xb7\xf2\x9f\xdf" - "\x93\x71\x07\xab\x75\x38\xc7\x29\xca\xaf\x10\x07\x85\x0c\x8b\x7b" - "\xb6\x68\x70\xf9\xf7\xc7\xfd\xdf\x93\x6b\xb2\x2f\x5f\x4a\xf6\x97" - "\x47\x89\x13\x75\xcf\x93\x6d\xc7\xf3\xbc\x0e\x96\x3f\x31\x64\xfd" - "\xd7\xdd\x6c\x5f\xd7\x21\x3e\x44\xab\xed\x5c\x36\xc3\xc6\xad\xdf" - "\xbb\x8d\xe1\x25\xec\xa5\x44\x9c\x0f\xf0\x0b\x93\xe1\xf3\xf3\xac" - "\x80\x9d\xf6\x29\x39\x7a\xb2\x1a\xf3\x83\x95\xd5\xe4\x88\x89\xbf" - "\xdf\x9c\x4f\x96\x16\x8c\x7e\x2a\xa2\x22\x1a\x58\x72\x9a\x69\x38" - "\xe0\xa8\x10\x7f\x0f\x46\x88\x1e\xe8\xf4\x89\x4d\x67\xc8\x86\x31" - "\xa8\x25\xb0\x84\xf7\x92\xe4\xef\xdc\xf1\x05\xd9\x20\x87\x31\xa7" - "\xe9\xfe\x63\x95\x0f\x88\x98\xef\x01\xb2\xbd\xef\xad\x26\xb1\xbe" - "\xf9\xa5\x4d\x1f\x92\xed\x97\xbd\xd5\xd6\x5e\xe1\xa4\xca\x72\x5e" - "\x9f\x10\xe4\x8b\x88\x1e\x5e\x6f\x6f\x2a\x89\x31\xcc\x0f\xba\x7d" - "\x4e\x6a\x29\x8f\xd0\xaa\x13\xa2\xa7\xe6\x43\xb2\xf3\x5c\x57\x73" - "\x67\x84\xbf\x2b\xb7\xaf\x7a\x80\x32\x4e\x15\x91\xb5\xb9\x6c\x2b" - "\x05\xe7\x44\xa8\xf2\x84\xe8\x68\x2a\xf9\x94\x5a\xca\xf6\x50\x71" - "\x1b\x59\x9b\xda\xff\x44\xf2\x5b\xe9\x4d\xb6\x82\xaa\x73\xe4\x5c" - "\xf5\x04\xc7\x9d\xa3\x95\xab\x68\xf8\xca\x8f\xc8\x11\xec\x68\x43" - "\x39\x67\xe8\xd1\x63\x64\x01\x3e\xeb\xb3\x7f\x22\xe7\xb3\xb3\x78" - "\xbf\x66\x1e\xd5\x55\x91\x53\xf8\xdc\xd9\xbd\x3e\x77\x4e\xaf\x70" - "\x5f\xda\xed\x73\x8f\x6c\xf1\x00\xbe\xfd\x00\x8d\x68\xa3\x91\x07" - "\x4f\xb7\x59\xb7\x9e\xa5\x31\xae\x07\x59\x07\xee\x6f\xad\x3b\x0b" - "\xf8\xf5\xc7\x5b\xe3\xc8\x6b\xcc\x13\xcd\x3c\xde\x11\x2c\xea\xa1" - "\x38\x70\x6d\xed\xa5\x31\x75\xbd\xe4\x8c\xaf\x3b\xde\xca\xb2\xe8" - "\x5b\xdf\x94\x0f\x3b\x38\xec\xcd\xc7\xf6\xd9\x82\x4d\x9d\xd4\x1c" - "\xe9\xa5\x16\xfa\x98\x82\xde\xbf\x06\x7e\xf9\xd8\xbe\x21\x71\x34" - "\x80\xc0\x4a\xde\xf7\xa2\xf4\xc6\xd7\xcc\xdf\xc8\x55\xd3\xe6\x2a" - "\xca\xf6\xac\xa4\x61\xa7\x11\xaf\xc6\xb9\x87\x0a\x82\xd1\xbf\x06" - "\x56\xca\xbd\x9a\xab\xed\x55\xcd\x94\xd1\x12\xd9\xca\xdf\x86\x5b" - "\x63\x23\x6c\x05\xc1\x48\x2b\x05\x3d\x9f\x04\xe2\xd9\xb6\x09\x1b" - "\xe2\x64\x7f\xe3\x7c\xab\x35\x68\x3b\x4f\xc1\xa2\x08\x1d\x42\xd9" - "\x62\x93\x6d\x0e\x6c\x56\x5e\x4b\xa4\x87\xbf\x79\xc9\x15\x5d\xce" - "\xac\xcd\x4b\x68\xdc\x8e\xb3\x34\x76\xfb\x59\x72\x8b\x6e\xb7\x95" - "\xf7\x5f\xce\x3d\x93\x43\xdb\xf1\xce\x6e\x87\xee\x9c\x55\xfb\x30" - "\xc5\x70\x6d\x1f\x66\x9f\x9b\xea\x7b\xfb\xf7\x61\xf6\x76\xf5\xef" - "\xc3\x64\x5d\xe2\xbd\x98\x68\x1b\x3d\xac\xd3\x1b\x16\x91\x6d\xcd" - "\x67\x44\xb7\x54\x5b\x79\xdf\xa8\x38\x89\xf4\xc3\xa5\x31\xf2\xfd" - "\x8d\x65\xff\xcf\x3d\xc9\x7b\x65\xf3\x31\x5e\x99\x06\x23\x30\x2d" - "\x07\xcf\x18\x3c\xe8\xd7\xa7\x8d\xc7\x03\x89\x4c\x83\xbf\x3e\x0d" - "\xf6\x79\x9a\x17\x4f\x0d\x9e\xad\x78\xd0\x32\xa7\xed\xc2\x03\x3b" - "\x3e\x0d\x63\xae\x69\xe8\x6f\xa7\x35\xe1\xc1\xb8\x6a\x1a\xb4\xb4" - "\x00\x76\xa4\x00\x78\x0a\x26\xe0\x29\xc4\x83\xfc\x05\xd5\x78\x90" - "\xb7\x00\x79\x0a\x90\xa7\xe0\x08\x9e\x56\x3c\xe8\x93\x0b\x90\xaf" - "\xa0\x93\xe8\x21\x90\xf3\x10\x2c\xf5\x43\x28\xff\x21\xf4\x23\x0f" - "\xa1\xbf\x78\x08\x54\x3e\x04\xfb\xff\x10\xca\x7c\x08\xf9\x1e\x42" - "\x9e\x87\x90\xe7\xa1\x0e\x3c\x61\x3c\xb0\xe9\xd3\x91\x6f\x3a\xc6" - "\x69\xd3\x5d\x78\x40\xf7\x74\xd0\x3d\x1d\x74\x4f\x07\xcd\xd3\xe1" - "\x37\x4f\x47\x99\xd3\x41\xe3\x74\xe4\x9b\x8e\x3c\xd3\x91\x67\x06" - "\x68\x9c\x01\x7e\x67\xc0\xa7\x9f\x81\x7c\x33\xe0\xc7\xce\x80\x1c" - "\x66\x80\xde\x19\x65\x78\x2a\xf1\x80\xde\x19\x7b\xf1\xa0\xcc\x19" - "\xa0\x71\x06\xf2\x15\x22\x4f\x21\xf2\x14\x82\xc6\xc2\x5c\x3c\xe0" - "\xb1\x10\xf9\x0a\x91\xaf\x10\x7c\x16\x62\xbc\x5a\x08\xd9\x14\x62" - "\xfc\x5d\x08\x1a\x67\x82\xae\x99\x80\x9b\x09\x9a\x66\x02\xef\x4c" - "\xc8\x70\x26\xf8\x99\x09\x98\x99\xa0\x6b\x26\x78\x9a\x09\xda\x66" - "\xa2\xff\x9d\x09\xda\x1e\x06\xfc\xc3\xc0\xfd\xf0\x64\x3c\x80\x7f" - "\x18\xf8\x1e\x06\xdc\xc3\x90\xd7\xc3\xc0\xf7\x08\xe8\x7e\x04\x34" - "\x3c\x02\x98\x47\x80\xf7\x11\x94\xff\x08\xca\x7f\x04\xe5\x3f\x82" - "\xf2\x1f\x01\xfc\x23\xc0\xfd\x08\xca\x7f\x04\xf0\x45\xc0\x57\x04" - "\xb8\x22\x94\x5f\x04\x7c\x45\x28\xbf\x08\xe5\x17\x01\xa6\x08\x78" - "\x8b\x50\x7e\x11\xca\x2f\x02\xfe\x22\xc8\xa7\x88\xf3\x80\xcf\x59" - "\x28\x67\x16\xe4\x32\x0b\xf8\x67\x15\xe0\x81\x3c\x67\x01\xff\x2c" - "\x58\xa6\x59\x28\x63\x16\x64\x33\x0b\x75\x32\x0b\x78\x66\x01\xcf" - "\x2c\xe0\x98\x85\xfc\xb3\xc0\xc3\xa3\xc8\xfb\x28\xf2\x3e\x0a\xba" - "\x1e\x2d\xc1\x83\xba\x7f\x14\xf5\xf0\x28\xe0\x1e\x85\x9e\xc0\x1a" - "\xd0\xa3\x28\xe7\x51\x86\x45\x59\xb3\x51\x7f\xb3\xc1\xd3\x6c\xf0" - "\x34\x1b\x79\x66\xa3\xde\x67\xa3\xac\xd9\xa0\x73\x36\xf2\xcc\x86" - "\xfc\x67\xb7\x13\xf1\xd0\x71\x0e\xf4\x6a\xce\x58\x3c\xa0\x6b\x0e" - "\x60\xe7\x80\xaf\x39\xa0\x6f\x0e\xca\x99\x83\xfa\x9e\x83\x3c\x73" - "\x40\xd3\x1c\xd0\x33\x07\x75\x36\x17\x79\xe6\x82\x96\xb9\xd0\x8b" - "\xb9\x80\x9b\x8b\x71\xfc\x5c\xe8\xd4\x5c\xc8\x61\x2e\x60\xe7\x82" - "\x8f\xb9\xe0\x63\x2e\xf2\xcc\x85\x2c\xe6\x42\x0e\x73\xc1\xc7\x5c" - "\xd0\x37\x0f\x79\xe7\xa1\xae\xe7\x41\x7e\xf3\xa0\x8f\xf3\x90\x7f" - "\x5e\x29\x1e\xe0\x98\x87\xb2\xe6\x81\xaf\x79\xc0\x33\x0f\x78\xe6" - "\x01\xc7\x3c\xe4\x9f\x07\x5a\xe7\x21\x6f\x31\xf2\x16\xa3\xdc\x62" - "\xd0\x58\x0c\xda\x8a\x51\x66\x31\xe0\x8a\x77\xe3\x81\x4e\x15\xa3" - "\x9c\x62\xc0\xc2\x8a\x52\x31\xe8\x2c\x86\x2c\x4a\x20\xb7\x12\xe4" - "\x29\x01\x6f\x25\x28\xab\x04\x32\x28\x41\x9e\x12\xc8\xa0\x04\xf5" - "\x59\x02\xb8\x92\x28\xd1\x7c\xb4\xd5\xf9\xa0\x6b\x3e\x60\xe7\x43" - "\x66\x0f\x72\x1c\x68\x9c\x8f\xb2\xe6\x23\xdf\x7c\x94\x37\x1f\x79" - "\xe7\x83\xb6\xf9\xa0\x6b\x3e\xe8\x9a\x8f\xfc\xf3\x51\xd6\x7c\xb4" - "\xb3\xf9\x68\xa3\x8f\x81\xbe\xc7\x50\xde\x83\x3d\x2f\xbc\x42\xc4" - "\xf6\xa3\x6e\x34\xd9\xf8\x7c\x10\x69\x4b\xb6\x95\xf1\x59\x21\x61" - "\xed\xb7\xa5\xff\xb7\x9b\xe3\x7b\xb4\x78\x2b\xc3\xf3\xf9\x22\x0c" - "\x2f\xe3\x2e\x97\x71\x61\x2d\xce\x32\x30\xce\x9d\x80\xe3\x77\xd7" - "\xb6\xb2\x0c\xc6\xa1\xe7\xd7\xc2\x61\x3d\x2f\x87\x43\xb0\x49\xea" - "\xcd\x61\x37\xf2\x4d\xb3\x69\xef\x1c\xf5\xce\xcf\x63\x1e\x7c\xa1" - "\x04\xed\x36\x94\xd5\xc1\x61\xfe\xad\x95\xc7\xe7\xa0\x84\x53\xe2" - "\x2c\x03\xe3\xdc\xf2\xbc\x94\x14\x38\xc5\x67\x89\xe8\xa8\x02\xef" - "\x08\xdb\xe2\xdb\x14\xfd\xba\x9c\xd2\xa4\x59\xd2\xa7\xb9\xc9\x58" - "\x86\xe4\xdb\x40\x33\xd3\x6b\x88\x0f\x1b\xe2\x8d\x72\x89\xc8\xf4" - "\x24\x3c\x52\x2e\x4d\xda\x3b\xa4\xbd\x03\x9a\x7c\xf4\xfa\x1c\xa2" - "\x95\xc5\x72\x1e\x92\x22\x1f\x63\x9c\x65\x60\x5c\x42\x3e\x46\x38" - "\x5d\x3e\x61\x8d\xcf\x21\x26\xf2\x31\x4b\xb3\xa4\x4f\x93\xf2\x49" - "\x94\x61\x90\x8f\x8c\x33\x91\x8f\x1e\x6f\x90\xcf\x43\x23\x35\xf9" - "\x18\xf0\xb0\x3c\x0a\x3a\xd5\xfb\x21\xd2\xc2\xa1\x64\xf9\xb8\x6d" - "\xfd\x65\xb9\x53\xf5\xc7\x18\x67\x19\x18\x67\x94\x8f\x3b\x55\x7f" - "\x34\x3e\xdd\x66\xfa\x63\x96\x66\x49\x9f\xa6\xcb\xc7\x9d\xaa\x3f" - "\x32\xce\x5c\x3e\xee\x14\xfd\x99\x3e\xbe\x5f\x3e\x6e\x83\xfe\x4c" - "\xcf\xd6\xde\x2e\xed\x4d\x9a\x7c\xf4\x76\x3f\x54\x2b\x8b\xdb\xf8" - "\xd0\x14\xf9\x18\xe3\x2c\x03\xe3\x12\xf2\x31\xc2\xe9\xf2\xe9\xd1" - "\xf4\x60\xa8\x89\x7c\xcc\xd2\x2c\xe9\xd3\xa4\x7c\x12\x65\x18\xe4" - "\x23\xe3\x4c\xe4\xa3\xc7\x1b\xe4\x33\xa3\x50\x93\x8f\x01\x0f\xcb" - "\x63\xc6\x38\xed\xad\x87\x5d\xba\xfd\x61\x5a\x0c\x76\x63\x68\xc2" - "\x6e\x84\x54\xfb\xd7\xed\x5c\x7c\x9b\x4c\x0b\xa7\xa4\x59\xd2\xa7" - "\xb9\x8d\xf9\x7a\x52\xf2\x59\xf5\xb4\x2a\xcd\x86\xb0\x8c\xab\x14" - "\xdd\x5c\xe7\xd6\xf8\xe5\xfd\xe5\x56\x69\xf6\xc4\x04\xc6\x72\x61" - "\x18\x03\x1d\x06\x7e\x75\xfb\x9c\x8e\xe7\xb8\xb1\x1e\x4c\xf8\x36" - "\xa6\x87\xe0\x43\xe9\x76\xad\x1f\xbf\xb2\xf3\x8c\x1f\xe9\x85\x2a" - "\x5c\xe8\xd1\xde\xba\xfd\x0f\x6b\xf0\x43\x52\x68\x09\x6b\x65\x0d" - "\x31\x91\xbf\x31\x2d\x55\xfe\x86\xb4\x01\xf2\x37\xe6\x4b\x95\x7f" - "\xd8\x20\xb7\x21\x69\xe4\x6f\x06\x93\x2a\x7f\x13\x98\x24\xf9\x27" - "\xf8\x35\x91\x7f\x12\xcf\x26\xf2\x4f\xe2\x3b\x59\xfe\x0f\x67\xeb" - "\x76\xa1\x1f\xbf\x51\xfe\x33\x8f\xa9\xf0\xcc\xb0\xf6\x0e\x24\xcb" - "\xdf\x9d\xaa\xff\x5a\x59\x6e\x33\xfd\x37\xa6\xa5\x91\xbf\xdb\x4c" - "\xff\x8d\xf9\x06\x91\xbf\x3b\x9d\xfe\x9b\xc1\x0c\x22\x7f\xb7\x99" - "\xfe\x27\xf8\x4d\x2f\x7f\x77\x3a\xfd\x4f\xe2\x3b\x59\xfe\x8f\x6c" - "\x48\x96\xbf\x3b\x45\xff\x1f\xd1\xf4\xff\x11\x4d\xff\x1f\xc9\xd3" - "\x7d\xb8\xe8\xe5\x65\xc3\xb8\x7c\x7e\x1b\xed\xa7\x21\x6c\x49\x0e" - "\x2b\x7f\xce\x90\x6e\x95\x76\x52\x8b\xd3\x65\x9b\xb0\xef\x03\xe3" - "\x2d\xe6\xf1\x6e\xd2\x71\xea\x3e\x9e\x96\x9e\xe4\xe7\x69\x71\x06" - "\x9b\x5b\xd4\xc1\xef\xfe\xbc\xcc\x5f\xd1\x11\xed\xdd\xa6\xbd\x75" - "\x7d\x4b\xf8\x3d\x92\x6f\x13\xff\x49\x8b\x1f\xe0\x3f\x0d\x8c\x77" - "\x1b\xe1\x7b\x0c\xf0\x56\xa3\x5c\x53\x7d\x39\x9d\x1f\x2d\x7d\x80" - "\xaf\xa7\xf3\x96\x3e\xdd\x50\xae\x56\xa6\xae\x4b\x66\x3c\xa5\xa4" - "\x25\xf1\x65\x4c\x0b\x61\x1c\x66\xf4\x0d\x75\xfd\xd1\xd2\x02\x2a" - "\x3c\x4b\x93\xe7\xac\x3d\x7a\xfb\xd5\x6d\xa7\xa1\xec\x24\x7f\xcb" - "\x50\x6e\x92\xbf\x35\x30\x7e\x80\x3c\x75\xf8\x54\x79\x26\xf9\x7e" - "\x26\xf2\x4c\x4d\x4f\x95\x67\x4a\x7a\x92\x3c\xc3\x46\xdb\x68\xc6" - "\x93\x89\x3c\x13\x7c\x25\xcb\x73\x76\x9e\xd1\x97\x4c\x96\xe7\x6c" - "\x6d\x1c\x32\xdb\xad\xbd\xa9\x5f\x9e\xee\x54\xfd\x4c\xf2\xcf\x92" - "\xcb\x75\x9b\xe9\xa7\x16\x6f\x26\x4f\xb7\x99\x7e\x26\xf9\x8a\xe9" - "\xe5\xe9\x4e\xa7\x9f\x29\xe9\xa9\xf2\x74\x9b\xe9\x67\x82\x27\x73" - "\x79\xba\x4d\xf4\x73\xce\x16\xa3\xef\x99\x2c\xcf\x39\x25\x2a\x3c" - "\xc7\xab\xbd\x0b\xfa\xed\x9b\x7b\xa8\xb2\x25\xee\xa1\xc9\xf6\x2d" - "\x11\xb6\x24\x87\x75\xfb\x96\x48\x37\xd8\x37\xf7\x50\x73\xfb\x96" - "\x14\x6f\x31\x8f\x67\xfb\xe6\x36\xda\xf4\x0e\x2d\x3d\xc5\xbe\xc9" - "\x38\x83\x7d\x9b\x7b\x44\xd9\x37\xb7\xc1\x9f\x9c\xbb\x4b\x7b\xef" - "\xd3\xde\x0d\x03\xed\x9b\x7b\xa8\xb9\x7d\x93\xf1\x26\xf6\x2d\x35" - "\xde\x6d\x84\x37\xb1\x6f\xee\xa1\x83\xdb\x37\xf7\xd0\xc1\xed\x5b" - "\xba\x74\x43\xb9\x03\xec\xdb\x40\x9e\x52\xd2\xd2\xd8\x37\x96\xdd" - "\xbc\x56\x73\xfb\x26\xd3\x1a\x54\x78\x9e\x26\xcf\x79\x5b\x06\xda" - "\xb7\x44\xd9\x29\xf6\x2d\x51\x6e\x8a\x7d\x4b\x8d\x1f\x20\xcf\x14" - "\xfb\xe6\x1e\x3a\xb8\x7d\x73\x0f\x1d\xdc\xbe\xa5\x4b\x4f\x92\x67" - "\x8a\x7d\x1b\xc8\x93\x89\x3c\x4d\xec\x1b\xcb\xac\xc4\x65\x6e\xdf" - "\x38\xad\x58\xf3\xf3\x4a\xec\xea\x5d\xac\xc6\xcb\xe0\x8f\xe7\x8c" - "\x8c\xed\xd0\x10\xb6\x24\x87\x55\x3b\x34\xa4\x27\xda\x21\xc7\x99" - "\xb5\xc3\x94\x78\x8b\x79\xbc\x9b\x74\x9c\x7a\x3b\xd4\xd2\x93\xda" - "\xa1\x16\x67\x68\x87\xf3\x0b\xf8\xdd\x9f\x97\xf9\x9a\x9f\xab\xbd" - "\x65\xf8\x24\x7d\xaf\x9d\xd7\x8c\xba\xac\x0e\x71\xb8\x74\xbc\x5c" - "\xc3\xd9\x3e\x4a\x1c\xd9\xfe\x92\x68\xec\xf6\x3f\x36\x21\x44\x1b" - "\xe5\x19\xd1\x1b\x11\xde\x88\xf8\xc3\x2e\x22\x9e\x73\x6f\x2c\xe3" - "\xb5\xa1\xc7\x8a\x42\x94\xd5\x94\xba\x36\x24\xfc\x53\x3a\x78\x5d" - "\xf6\x57\x55\xad\x43\x84\xf5\x9f\x3a\x5a\x3a\x3a\x69\xf7\xca\x8e" - "\x21\xbe\x3f\x90\x35\x18\x3d\x49\xb7\x8c\x24\x27\xef\x0f\xa8\x7f" - "\x49\x84\xf0\xee\xc0\xd3\xe9\x59\xc9\x67\x60\x3d\xf6\xfa\x8d\xb5" - "\x34\xf2\x8f\x7c\xf6\x89\x5c\xf3\x7a\xec\x9d\xfe\x35\xaf\xea\x8f" - "\x9a\xdb\x03\x86\xf5\xae\xea\xd5\xae\x01\xeb\x5d\x8f\x5f\x27\xe3" - "\x0e\x8a\xa8\x5a\xdf\x8a\x85\xb4\xf8\xcc\x94\xf8\x0e\x15\xbf\xe0" - "\x4c\x4a\x7c\x8f\x16\xff\x51\x4a\x7c\x58\x8b\x1f\xee\xd2\xd6\xd3" - "\x5a\x98\x8e\x15\xbc\x9e\x56\xfa\x77\x5e\x4f\x6b\x29\xd5\xd6\xd3" - "\xe4\xd9\x02\xa5\x1f\x89\x9f\x55\x13\x9f\x99\x84\xdf\x3f\x66\xfa" - "\xc5\x41\xd2\x69\xcf\x44\xdc\x43\x1c\xb7\xe5\xcf\x64\xc3\x23\xd7" - "\xd2\x84\xff\x7b\xd3\x78\x1d\x8d\xd7\xd3\xea\x9f\x27\xda\xf6\x92" - "\x38\x56\x37\x4a\xb4\xd6\xbd\x24\x9a\xba\xfd\xdf\x0f\xe8\x6b\x6a" - "\x1b\x10\xb7\x01\x71\x3f\x42\x3a\xaf\xab\xb1\x4c\xde\x9f\x13\x20" - "\x3e\x5b\x4b\xd4\x34\xd7\x3a\x2c\xe4\xd9\x74\x96\x6c\x7c\x96\xd9" - "\x5a\xc8\x37\x58\x1e\x91\xdf\x33\x6f\x7e\x49\xb4\xc7\xad\xb9\xd4" - "\x52\xde\xce\xeb\x39\xa3\xd6\xc4\xf9\x1b\xb5\x4f\xa9\x2a\x22\x4e" - "\xf3\x77\xcf\x4c\x43\x71\xc5\x3f\xf3\xf9\x89\x96\xc6\x02\x22\x3e" - "\x8b\xa2\xfe\x52\xa2\x1d\x97\x82\x46\xd0\x74\x78\x21\xd7\x77\x69" - "\x7e\x88\x02\xe5\x6a\x6f\xe4\x6a\x3b\x9f\x95\x7c\x92\xbe\xbf\x41" - "\xf8\x45\x0f\xf3\xe6\x88\x55\x13\x9f\xd5\x22\xac\x72\xcf\x4e\xd9" - "\x36\xfc\xde\xa2\x9f\xd7\xe2\x27\x1b\xc3\x04\x4f\xf4\x10\xd3\x1c" - "\xa2\xef\xb7\xbd\x5f\x19\xe0\xfc\x95\x2c\x1b\xe1\xf7\xe9\x38\x2c" - "\xf2\xbc\x17\x3f\xd9\xf9\xbc\x97\x2f\x83\x43\x64\x35\xe5\xbf\x5f" - "\x12\x26\x5e\x63\x0c\xb6\xf6\xd0\xfb\x95\x27\x65\x1a\xc3\x88\xac" - "\xc6\xa4\x34\x3d\x5f\xd6\x2a\xf1\x77\x94\x9d\xcf\x75\xc9\xe7\xb1" - "\xc5\xd4\xd9\x48\xd9\x7c\x76\x47\xa0\xea\x63\xae\xeb\x3f\xd4\xa3" - "\x6e\xb4\x33\xe5\xa0\x8b\x0b\x8e\xf0\xb9\x3b\x7c\x8e\x9c\x3c\x43" - "\xce\x3a\x9e\xc4\x0a\x77\x76\xe2\x1c\xb9\xff\x0f\xce\x90\x43\xdd" - "\x38\x77\x58\xd5\x19\x72\x09\xfe\xe7\x48\x19\xe6\xb2\xae\x72\xdc" - "\x8b\xf3\xc8\x18\xef\xe4\xf8\xcd\x7e\x71\x44\xd7\x13\x4e\x63\xbe" - "\x90\x46\x5a\x5a\xeb\xc0\xb4\xc7\x3a\x38\x8d\xd7\xd5\x82\xa5\x31" - "\xfa\xe5\xe3\x31\xeb\xfa\x5e\xb2\xf1\x1a\x9b\x86\x57\xca\x56\xad" - "\xb3\x3d\x5e\x92\xbc\xce\xf6\xa4\x07\x8f\x17\x4f\x0d\x9e\xad\x78" - "\x76\xe1\xd9\x87\xa7\x15\x4f\x07\xd1\x53\x00\x7b\x2a\x1b\x0f\x2c" - "\xc9\x53\xe3\xf1\x4c\xc4\x03\xab\xf1\x14\xb4\xee\xa9\x22\x3c\xa5" - "\x78\x80\xed\xa9\x0d\x78\x76\xe2\xd9\x8f\xe7\x18\x9e\x08\xd1\xc2" - "\x91\x78\x90\x67\x21\xe0\x17\x02\x6e\x21\x64\xba\x10\xe5\x2c\xac" - "\xc3\x03\xd8\x85\xbb\xf1\xec\xc5\xd3\x88\xe7\x04\x1e\xe4\x79\x1a" - "\x65\x3d\x3d\x16\xcf\x64\x3c\xc8\xf3\xf4\x5a\x3c\xa0\xeb\x69\xc0" - "\x3d\x0d\x9a\x9e\x6e\xc3\xd3\x89\x87\x61\xa3\x44\x8b\x6c\x78\x50" - "\xce\xa2\x71\x78\x90\x67\xd1\x1c\x3c\xa0\x67\x51\x2d\x1e\xe4\x59" - "\x04\x5a\x16\x81\x8f\xc5\x80\x5b\x0c\x1e\x16\xbb\xf1\x80\x87\xc5" - "\x80\x5d\x3c\x15\x4f\x21\x1e\x94\xb3\xb8\x12\x0f\xf2\x2c\x06\x4d" - "\x8b\x41\xcf\xe2\x76\x58\x35\xe4\xf1\x80\x16\xcf\x04\x3c\x80\xf3" - "\x40\x56\x1e\xc8\xca\x03\x5e\x3d\x80\xf5\x80\x0f\x0f\xf8\xf0\x80" - "\x67\x0f\xe8\xf7\x80\x9e\x67\xc6\xe0\x01\xfe\x67\x80\xf3\x19\xc0" - "\x3d\x03\x1a\x9e\x01\xdd\xcf\x80\xde\x25\x4e\x3c\xa0\x61\x09\xd2" - "\x97\xa0\xfc\x25\x28\x7f\x09\xf0\x2e\x41\x6b\x5d\x02\xd8\x25\x28" - "\x7b\x49\x13\x1e\xf0\xb7\x14\x3c\x2d\x05\xdc\x52\xe0\x59\x0a\xb9" - "\x2d\x45\x39\x4b\x8f\xe0\x01\xae\xa5\x9c\x0e\x7c\x4b\x51\x5e\x39" - "\x68\x2c\x47\x99\xe5\x80\x2d\x07\xef\xe5\xe0\xa3\x1c\x74\x95\x83" - "\x87\x72\xc0\x2d\x03\x9e\x65\xb9\x78\x50\xce\x32\xd0\xbe\x0c\xb8" - "\x96\x21\x7d\x19\xf0\x2d\x43\x79\xcb\x40\xdf\xb2\x00\x1e\xc8\x69" - "\x19\xe4\xb4\x0c\x38\x97\xe7\xe0\x81\x3c\x97\xa3\xde\x96\xa3\xfc" - "\xe5\x90\xe7\x72\xd0\xb7\x1c\x79\x96\x23\xcf\x72\xf0\xbb\x1c\xf8" - "\x97\x83\xd6\xe5\xc8\xb7\x1c\xf9\x56\x80\x8e\x15\xe0\x6d\x05\xe8" - "\x58\x01\xbd\x58\x01\x3a\x56\x34\xe0\x01\xdc\x0a\xc8\x66\x05\xf0" - "\x7a\x41\xa7\x17\xf2\xf4\x02\xc6\x0b\xfe\xbd\xe0\xdf\x0b\xba\xbc" - "\xe8\x9d\xbc\xa8\x67\x2f\xe0\xbd\xc0\xed\x45\x1d\x7b\x01\x5f\x01" - "\x7c\x15\x80\xab\x00\x5f\x15\xc0\x57\x01\xba\x2b\x40\x43\x05\x60" - "\x2a\x80\xb7\x02\xe5\x57\xa0\xfc\x0a\x94\xbf\x12\xe5\xaf\x04\xfc" - "\x4a\xe0\x5e\x89\xf2\x57\x02\x7e\x25\xf0\xad\x04\xdc\x4a\x94\xbf" - "\x12\xf8\x9e\x45\xf9\xcf\xa2\xfc\x67\x01\xf3\x2c\xf0\x3e\x8b\xf2" - "\x9f\x45\xf9\xcf\x96\xe0\x01\x8f\xcf\x42\x37\x9f\x45\x19\xcf\xee" - "\xc1\x03\xdc\xcf\x02\x6f\x25\xf0\x56\x42\x86\x95\x90\x47\x25\xf2" - "\x54\x22\x4f\x25\xe8\xa9\x84\x5c\x2a\x51\x6f\x95\xc8\x57\x89\x7c" - "\x95\xa0\x0b\xc6\x8d\x2a\x51\x56\x25\x7a\xc4\x55\x28\x6b\x55\x1e" - "\x1e\xc0\xad\x02\x2d\xab\x80\x77\x15\xe8\x5e\x05\x7a\x56\x01\x66" - "\x15\xf4\x6b\x15\xea\x67\x15\xea\xb1\xca\x8e\x07\x74\x55\x01\xbe" - "\x0a\xb8\xab\x50\x4f\x55\x80\xaf\x02\xbe\xaa\x76\x3e\xb9\x11\xd6" - "\x0e\xf8\x7c\xa0\xdb\x07\x1a\x7c\x80\xf1\x01\xaf\x0f\xe5\x3f\xc9" - "\x6f\xd0\xe0\xab\x61\xef\x07\x0f\x68\xf7\x35\xb2\x67\x89\x07\xf9" - "\xaa\xa1\x73\xd5\xd0\xf9\x6a\xe0\xae\x86\x5c\xaa\xc1\x6b\x35\xf4" - "\xb8\x9a\xdb\x7c\xc9\x36\xd8\x9f\x57\xfe\xcc\xfe\x86\xb2\x11\xfa" - "\xdb\xd7\x06\x1f\xf6\x93\x32\x63\x38\x8c\xb0\x25\x39\xec\x36\xa6" - "\xf7\x20\xdd\x6a\xcc\xef\x2b\x92\x71\x24\x8a\x93\xe2\xc3\x5a\xbc" - "\xc5\x3c\xde\x9d\x04\xdf\x57\xcc\x7e\x51\x32\x4d\x3a\x9d\x9c\xa6" - "\xd3\x65\x8c\x0b\xc1\x8e\xf1\xbb\xaf\xd8\x6d\xed\xe7\xeb\x49\xaf" - "\x0a\x3f\x59\xc3\xef\x6d\x9a\xdd\x95\x78\x8f\x49\xbc\x09\x19\x80" - "\x8e\x0e\x3d\x0e\xb4\x90\x21\x3e\x6c\x88\xb7\x98\xc7\xbb\x8d\xf0" - "\x3d\x06\xf8\x64\xd9\x14\x62\x4c\xc2\x32\x2b\xc6\x98\x04\x72\x4b" - "\x95\xb5\x49\xba\x65\xf0\x74\xf7\x00\x7e\x92\x64\x97\xc2\x53\x92" - "\x0c\x53\xf8\x4a\x96\xe5\x53\x3b\x25\x4c\x02\xa7\x51\xa6\x4f\x95" - "\xab\xf0\x53\x1b\xb4\x77\x29\xcb\x15\xb0\x5c\x27\x43\x52\xca\x96" - "\x71\x26\xf2\xd4\xe3\x53\xe5\xa9\xc5\x0f\x90\xa7\x0e\x9f\x2a\xcf" - "\xb0\x26\x8f\x21\x69\xe4\x99\x9a\x9e\x2a\xcf\x94\xf4\x24\x79\xca" - "\x32\x4d\xe4\x99\xe0\xc9\x44\x9e\x09\xbe\x92\xe5\xb9\x30\xa2\xc9" - "\x53\xc3\x69\x94\xe7\xc2\x46\x15\x5e\x78\x42\x7b\xef\xed\x97\xa7" - "\x3b\x55\x3f\x65\x9c\xb9\x3c\xdd\x66\xfa\xa9\xc5\x9b\xc9\xd3\x6d" - "\xa6\x9f\x9a\x3c\xdc\xe9\xf4\x33\x35\x3d\x8d\x3c\xdd\x66\xfa\x29" - "\xcb\x34\x97\xa7\x3b\x9d\x7e\x26\xf8\x4a\x96\xe7\xa2\xc9\xfd\xf2" - "\x74\xa7\xe8\xe7\xa2\x91\x2a\xbc\x68\x9c\xf6\xb6\x69\xf2\x64\xfb" - "\x33\x34\xa5\x6c\x19\x67\x22\x4f\x3d\x3e\x55\x9e\x5a\xfc\x00\x79" - "\xea\xf0\xa9\xf2\xec\xd1\xf4\x6b\x68\x1a\x79\xa6\xa6\xa7\xca\x33" - "\x25\x3d\x49\x9e\xb2\x4c\x13\x79\x26\x78\x32\x91\x67\x82\xaf\x64" - "\x79\x2e\xae\xd5\xe4\xa9\xe1\x34\xca\x73\x71\xa9\x0a\x2f\xae\xd4" - "\xde\x85\x9a\x3c\x25\x7f\x9a\xfd\x18\x9a\xc2\x77\x47\xd5\x31\x65" - "\xa7\x98\xe7\xf8\x27\x49\xe9\xe1\x94\x74\xcb\xe0\xe9\xee\xd4\xfc" - "\x3d\x29\xf9\xad\xc6\xf4\x2a\xcd\xe6\x71\xbd\x54\x1d\x4b\xd0\x67" - "\x8d\x17\x27\xd3\x51\xa5\xd9\x3f\x13\x38\xcb\x97\x83\x4b\xa1\xcb" - "\x20\x0f\x96\xe5\x97\x91\x49\x6a\x9f\x66\x26\x97\xe4\x7a\xf2\x44" - "\x75\xbb\xdc\x5f\x96\xdb\x6a\x2c\x0b\x30\xfb\x55\x3d\x79\x34\x7b" - "\xe2\xd9\xa9\xdb\x13\x2d\xcf\x10\x13\xda\xc2\x5a\xb9\x43\xd2\xd4" - "\x97\x31\xdd\xac\xbe\x0c\xe9\xa6\xf5\x65\xcc\x6f\x56\x5f\x61\x83" - "\x7c\x87\x0c\x52\x5f\x66\x70\x66\xf5\x65\x02\x37\xa0\xbe\x12\xf2" - "\x48\x53\x5f\x03\x64\x62\x52\x5f\x03\xe4\x92\x5c\x5f\x4b\x76\xeb" - "\x76\xaa\xbf\xac\xd4\xfa\x5a\xb2\x50\xd5\xd3\x12\xad\x3f\x5d\x52" - "\x98\x5c\x5f\x6e\xb3\xf6\xa5\x95\xeb\x4e\xd7\xbe\x8c\xe9\x83\xd4" - "\x97\x3b\x5d\xfb\x32\xe6\xbf\x40\x7d\xb9\x07\x6b\x5f\x66\x70\x17" - "\xa8\x2f\x77\xba\xf6\x95\x90\xc7\xe0\xf5\xe5\x1e\xac\x7d\x0d\x90" - "\x4b\x72\x7d\x95\xcf\x49\xae\x2f\xb7\x49\xfb\x2a\x1f\xa3\xea\xa9" - "\x7c\xa2\xf6\x96\xfd\x4b\xef\x27\xbc\x5e\xd0\x4f\x0f\x87\x53\xed" - "\xbd\x16\x67\x19\x18\x97\xec\x53\x6b\x70\xfd\x7d\x09\xcb\xdc\x10" - "\x3f\xa0\xbf\x4a\x4e\xb3\xa4\x4f\xeb\x2f\x87\xe3\x52\xfd\x6c\x9d" - "\xe6\x54\xb9\xe9\x74\x27\xcb\x6a\x59\x07\xbf\x15\x1e\x63\x7f\xb1" - "\x2c\xa0\xc2\xcb\x8e\x69\x6f\xdd\x9f\x91\xbe\xa4\x8e\x83\xf3\xa5" - "\xf3\x4f\xb5\x34\x53\xff\x74\x60\x9a\x3b\x35\x5f\x92\xff\x9d\x94" - "\x96\xc6\x07\x4f\x81\x31\xf5\xc3\x2f\x0c\x93\x42\x87\xc1\x1f\xbf" - "\x10\xcf\x7a\x3d\xa4\xe3\xdb\x98\x1e\xc2\x78\x3b\xd5\x37\x37\xe2" - "\x0f\x61\x5c\xae\xe4\xbe\x42\xf3\x8b\x96\x1f\x33\xfa\xe7\x26\xb4" - "\x0c\xf0\x67\x0d\x74\x0c\xf0\x67\x07\xa6\x99\xca\x3f\xe1\xaf\x9b" - "\xc8\x7f\x80\xcf\x6e\x22\xdb\x01\x7e\xfb\x85\x61\x06\xc8\x3f\xe1" - "\xbf\x5f\x88\x67\x13\xf9\x27\xf1\x9d\x2c\x7f\x6f\x43\xaa\x2f\x9f" - "\x2c\x7f\x6f\x99\x92\xbb\x77\xad\xf6\x2e\x34\xfa\xf3\xe6\xb4\xb8" - "\xd3\xe9\xff\x00\xff\x77\x60\x5a\x3a\xf9\xbb\xd3\xe9\xff\x00\x1f" - "\x3f\xbd\x6c\xdd\x83\xe9\xff\x00\x5f\x7f\xa0\xfc\xdd\xe9\xf4\x3f" - "\x89\x67\x73\xf9\xbb\xd3\xe8\xff\x4a\x57\x5f\x8a\xef\x9f\x2c\xff" - "\x0a\x4d\xff\x57\x6a\xfa\x5f\x71\x4c\xd9\x67\x77\x52\x7f\xc1\xe1" - "\x81\xf6\x59\xc6\x59\x06\xc6\xa5\xda\x67\x09\x67\x62\x9f\x55\xbc" - "\xb9\x7d\x4e\xa4\x99\xd8\x67\x3d\xcd\x68\x9f\xdd\xc9\xbe\xbd\x81" - "\xe6\x81\xf6\x59\xd1\x9d\x6c\x9f\x9f\xad\x51\xf6\xd9\x9d\xe2\xcf" - "\x3f\x5b\xa2\xc2\xcf\x6a\xe3\xf8\x67\x0b\xcd\xed\xb3\x7b\x68\x7a" - "\xfb\x2c\xd3\xd2\xd8\xe7\xd4\x34\x77\x6a\xbe\x34\xf6\x19\x69\x17" - "\xb4\xcf\x12\xe6\x02\xf6\x39\x1d\x4c\x0a\x1d\xa6\xf6\xd9\x9c\xe7" - "\x7e\xfd\x33\xe7\xdb\x98\x1e\xa2\xca\x40\x7a\xfb\x2c\xd3\x6b\x94" - "\xdc\x2b\x77\x6a\xef\x72\x73\xfb\x9c\xa0\xc5\xc4\x3e\x27\xe8\x30" - "\xb1\xcf\xa9\x69\xa6\xf2\x37\xb1\xcf\x09\xf9\x0f\x62\x9f\x13\xb2" - "\x1d\xc4\x3e\xa7\x83\x19\x20\x7f\x13\xfb\x6c\xce\xb3\x89\xfc\xd3" - "\xd8\x67\x96\x6f\x55\x5e\x7a\xfb\x2c\xd3\xed\x4a\xee\x55\x63\xd5" - "\x7b\x55\x44\xca\x1f\xbc\xf3\x9c\x68\xaa\x4d\xd0\xe2\x2c\x03\xe3" - "\x92\x6d\x82\x06\x37\xc0\x26\xe8\xf1\x66\x36\xc1\x90\x36\xc0\x26" - "\xf4\xa7\xf5\x97\xc3\x71\xa9\x36\x41\xa7\x39\xd5\x26\xe8\x74\x27" - "\xdb\x04\x5f\x1d\xbf\x15\x1e\xa3\x4d\xf0\x69\xb6\xc0\x27\x75\xf3" - "\x24\x3d\x76\xcc\xb8\xde\x9c\xbc\xce\x59\xbd\x4b\x5f\x6f\x3e\xec" - "\xe2\xf5\xc6\xea\x7d\x21\xca\xf2\x70\x98\xd7\x3b\x6b\x21\x4b\x7d" - "\xfd\x53\x5f\xaf\xe2\x32\xd6\x8e\x12\x21\x0e\x4f\x3a\x43\xc3\x0e" - "\x17\x10\xbd\x32\x4a\xb4\xa9\xf5\xeb\xea\x1e\xfd\xec\xe9\xf5\x88" - "\xe3\x35\x6c\xce\x63\xf6\xbd\xac\xfe\x7d\x66\xcc\x4f\x57\xc5\xac" - "\x64\x09\x56\x7f\x4c\xc1\xad\xa2\xba\x25\x7a\x8c\xe6\x95\x93\x35" - "\x9e\xf1\xd4\x5f\x78\x1d\xcd\x51\x49\x43\xf9\xcd\xeb\xc1\xa7\x69" - "\xf5\x94\xe2\x08\x0d\x15\x6b\x90\x66\x45\x9a\x97\xbe\x63\x48\x53" - "\x67\xac\xf4\xe7\xbb\xc9\x90\x26\xef\xa5\xb8\xe9\x33\xbe\xf3\x74" - "\xb5\x3b\x95\x9e\xff\x22\x2d\x1f\x0c\x42\xcb\x99\xf4\xb4\xf8\xe5" - "\xb7\x7f\x37\x75\x92\xc5\xb5\x88\x2e\xf9\x8c\x56\xef\xe5\xb0\xbc" - "\x9f\x70\x8d\x59\x39\xfe\x3b\xb5\xf4\x21\x86\x74\x43\x59\xfe\x59" - "\x26\xf9\x8d\xe5\x55\x5c\x00\xff\xcb\x17\xc0\xff\xdb\x0b\xe0\x3f" - "\xce\xeb\xd2\x90\x9d\x23\x6e\x4d\x86\xbb\x39\x2a\xcf\x4c\x00\xdc" - "\x69\xc0\xad\x91\x1f\x09\x8b\x35\xb3\xff\xe2\xbb\x5a\x7e\x07\x2e" - "\xef\xdb\xd8\x84\xf4\x60\xb4\x5d\xae\x99\x4f\x06\xa5\x37\x47\x92" - "\xf2\xdc\x91\x4a\xdb\x88\xa8\x4e\x9b\x4c\x9f\x99\x4a\x1b\xd2\x6f" - "\x32\xa4\x2f\xeb\xaf\x77\x7f\x38\x5d\xbd\xf3\x5a\x7c\x70\x2b\x11" - "\xdf\x8b\x7d\xd8\x46\xc4\xe7\x0b\xd7\x26\xce\x54\x58\xd3\x14\xa2" - "\xd5\x4e\xc3\x79\xea\x7c\xd6\xd8\x55\x2d\x91\x08\xf1\xf7\xae\xda" - "\xf9\xb3\x5f\xaf\x3a\x47\x97\xf2\xdd\x1e\x7c\x3f\x4f\x71\xac\xc0" - "\x7a\xb8\x92\xdb\xd3\x5a\xbb\x9e\x37\xdd\xd9\x0d\x5c\xae\x56\xa6" - "\x3c\x9b\x19\x79\x26\xea\x79\x18\x37\x9f\x47\x1c\x87\x5e\xaa\xfb" - "\x07\x3b\x79\xbd\xfb\xeb\xbe\x0a\x2e\x8b\xcb\x29\x21\xad\x1c\x0f" - "\xf2\xec\x1c\xa4\x9c\x41\xf8\x5b\xbb\xfb\xe2\xf9\x23\x9d\xbf\x8e" - "\x0b\xf0\x37\x48\xb9\xcf\x8d\xbd\xf8\x72\x73\xb4\x72\x9f\x2b\xb9" - "\x78\xb9\x3e\x57\xfb\xe5\xe5\x9a\xab\xc9\xf5\xb9\x23\x17\x90\xab" - "\x59\x39\xd1\x2f\x5f\x8e\x4b\x2b\xe7\x07\xb9\x66\xe5\x18\xed\xa4" - "\x3c\xe7\x83\xcb\x50\x77\x3d\x58\xd0\xe6\x32\x91\xaf\xcc\x78\x87" - "\x3b\xc7\x23\xae\x52\xbf\xc3\xbd\xff\x2c\xeb\x1f\xbc\x5c\xdc\x20" - "\xcf\x79\x89\x87\xe8\x07\x75\x7c\xc6\xfc\xe4\x55\xfa\xbd\xe9\x32" - "\xcf\x9e\xc1\xee\x8e\xe7\x7b\x4e\x85\x28\x92\xe7\xe3\xab\xbb\x9a" - "\x7e\xf0\x37\x3e\x7b\x59\xdd\x79\xfc\x83\x88\x6a\x83\x3f\x88\x00" - "\x77\xde\x20\x38\xe4\x9d\xca\x63\x9d\xbe\x2f\xe4\xfd\xed\x2b\xc9" - "\x16\x74\x2a\xdd\x38\x45\x3f\x9c\xa9\xce\x80\xfe\xe1\x04\x9d\x1f" - "\xed\x8c\x7d\xe0\xfd\xe1\x54\x9d\x9f\x10\xfd\x50\x9e\xf3\x23\xd6" - "\xff\x67\xf5\x60\xe7\x9c\x0b\xfb\x71\x79\xc7\x39\xca\xb0\x9f\xa2" - "\x9a\x9d\xf5\xea\x6c\x74\xfd\x4e\x67\x1b\xca\x3b\xa7\xe3\x8f\x58" - "\xab\xb9\xdc\x3d\x26\xe5\x36\xea\xe5\x0a\x3f\x65\xb3\xcc\x5c\xd7" - "\xc8\xbc\x67\x22\x99\xc7\x03\xa2\xe6\x78\x80\xef\x0a\x3a\xe5\xe2" - "\xfb\x89\x6b\x76\x92\x3c\x83\xe2\x87\x6d\x61\xa4\x71\x5f\xaa\x70" - "\x1f\xce\xee\xf6\xd7\x64\x0f\xc4\x5d\xe3\x32\xe0\xce\xe0\x3b\x10" - "\x94\x5c\x6b\x5e\x56\xf7\x42\xd5\xdc\x7f\x38\xca\x7b\x74\x28\x9b" - "\x71\x8a\x75\xc7\x03\x9c\x17\xf8\xbe\xc2\x6d\x88\xcb\x00\x8e\x52" - "\x1d\xaf\xb0\xb7\x55\x73\xfb\x61\x18\x79\xff\x4b\x94\x65\x59\xb3" - "\x36\xa1\x07\x88\x2b\x77\xc1\x7f\x83\xdc\x18\x9f\x76\x8f\x79\x44" - "\xc7\x9d\xee\x0e\x0c\x29\x33\xd4\xfb\x0b\x4a\x8f\xac\xa7\x68\xfd" - "\xf5\xac\x7f\xea\x9e\xae\x75\xcf\x69\x34\xcb\xfa\x64\x5a\x19\x57" - "\x88\xd6\xf3\xdd\xdd\xa4\xe8\xad\xe6\x76\xd1\xd1\xed\x5f\x97\xa3" - "\xd3\xca\xf7\x4e\xe8\x72\x68\x94\xba\xbf\x6e\x9c\xae\x7b\xbc\x37" - "\x86\xf7\x32\x09\xf0\xa7\xee\xb6\x5b\x97\x0f\x1a\xcb\x38\x4d\x9d" - "\x59\xbf\xee\x69\x52\xe7\xf0\xb4\xca\x3b\xd3\xe4\xf9\x3c\x19\x7f" - "\x3d\x49\xeb\xee\x96\x7a\xa1\xea\x24\x1b\x34\x85\x1b\x6d\xbc\x3e" - "\xbc\x5e\x9d\x09\x22\xef\xdc\xe0\xfc\x35\x7c\x2e\x6b\xf6\x66\x79" - "\x77\xb6\xac\x9f\x2c\x91\xd9\x56\x8d\x72\xf6\x18\xe8\x0b\xeb\xed" - "\x62\x6c\x65\xb1\xd4\x4f\xa4\xb7\x26\x68\xb4\x82\x46\x3f\x68\x04" - "\xaf\xf5\xf2\xfc\xfc\x75\x9d\xc9\x34\xae\xbf\x24\x0d\x8d\x7f\x19" - "\x8c\xc6\x7e\x7d\x7c\x17\xe5\xad\xcf\x1b\xa8\x33\xeb\x0b\xf5\xfa" - "\xe4\xf0\xe1\x6b\x26\x72\x59\x7b\x18\x87\xd2\xe1\xf5\xe5\x09\x1e" - "\x12\xfc\xae\xaf\xe5\xfb\xb5\x99\x5f\xdf\x17\x64\x77\x44\xc9\xca" - "\xed\xde\x80\x73\x97\xce\x57\x48\xc9\xc6\x9e\x6a\x7f\xd2\xdd\x77" - "\x84\x7e\x9c\xeb\xd1\x1a\x5e\x77\xb4\x7c\x5a\x54\xc4\xe1\x07\xa1" - "\x9e\xd7\xc3\xff\xdb\x28\x6d\x9f\x58\x2e\x9a\x36\xf7\xaa\xbb\x18" - "\xa7\xc5\xba\x44\x71\xcc\xce\xe7\x0c\x80\xce\x1f\x8d\xd1\xcf\x36" - "\x52\x6d\xfe\x47\xa8\xff\x1f\xec\xe7\x70\x38\xe3\x86\x4b\xf1\xb8" - "\x4d\xed\x87\x8e\x2f\xf3\x68\x79\x71\x2c\x5b\xe2\x52\xf7\x3c\xfe" - "\x68\x61\xe2\xce\x4b\xd0\x24\xb2\x9a\xcb\xf8\x3e\x9d\x70\x5f\x19" - "\x9f\xeb\x64\x51\x74\xfd\x68\x8b\x5e\xc6\x85\xee\x2f\x19\x84\xdf" - "\x36\xfd\x9c\x28\xe0\x0b\x85\x68\x53\x07\xe3\x73\x58\xf8\xfe\x34" - "\xd1\x83\x32\x47\x22\x3e\xc1\x3f\x9f\x15\xc5\x69\xea\xac\x99\x1f" - "\x1d\x53\x36\x72\x83\xd3\xec\xbc\xa8\xc7\x16\x2f\x2e\x2f\x5e\xb2" - "\x80\x5f\xee\xeb\x96\x5d\x9f\x95\x62\xf7\xb3\xd5\x1d\x56\x1b\xc6" - "\xf2\xfe\xc0\x17\x2e\xd5\xcf\x68\xda\x50\xaa\xef\x51\xe4\xb6\x8c" - "\x76\x73\x2f\xf7\x9b\xdc\xbf\x20\xad\xfa\x9d\xca\x55\x72\x7f\xd8" - "\x5f\xec\x64\x4d\xe7\xf7\xb0\x8e\x76\x65\x8a\x6a\x96\x97\xd8\x38" - "\x0a\x7d\xf2\x06\xf8\xff\x1b\x26\x0c\x72\x36\xb9\x27\xb6\xfe\xe3" - "\x1c\xd7\x68\xe2\x7b\x10\xad\xbf\x5e\xd9\x66\xe5\x73\x22\xaa\xf0" - "\x9b\xfd\x38\x79\xae\x84\x95\x04\xd3\x71\xf0\x6c\x1b\xec\xc5\x46" - "\xd8\x84\x66\xf8\x26\x1b\x6d\x69\x69\x30\x9c\xb5\xc5\x67\x1f\xb5" - "\xd3\xc6\xb1\xe9\x60\x45\x4d\x9b\x76\x9f\xe6\xc6\x8a\x46\x3e\x5b" - "\x75\x34\xfd\xf0\x24\x6d\x5c\x66\x73\x92\x13\xbf\x7f\x8e\xdf\xd2" - "\xd7\xe5\xb4\xa4\x3a\xbd\xe2\x4c\x83\x2d\x43\x58\x85\x10\x16\xa1" - "\xfe\x30\xa0\x52\x7f\x19\x78\xac\xc2\x22\x4f\xac\xc9\x80\xa4\x86" - "\x0d\xb5\x91\x63\x44\xb6\xfd\xaa\x2b\xc7\x38\xef\xbd\x67\xe2\x04" - "\x5f\x55\xa5\x57\xc4\xa3\x3d\x0e\x61\xbc\xc3\x54\xb8\x66\x5e\x5f" - "\xad\xce\x0d\x5b\x27\x5c\x66\xb4\x6e\xf4\x0b\x0f\xdf\xd9\x14\x1f" - "\x31\xaa\xc4\xb7\x8c\xac\x6f\xf6\x86\xac\x7c\xcf\xb8\x6b\x39\xef" - "\xc9\xfd\x13\x9d\xa4\x4d\x43\x0e\x21\x0e\xfc\x7b\xc5\x86\x51\x25" - "\x4a\x4f\x36\x4d\x89\x6f\x1a\x55\xd2\x8f\xdf\x46\x8c\xdf\xf7\x32" - "\x59\x77\x56\x75\x58\x83\xb6\x7b\x28\xe8\x8a\xd0\x21\xfc\x4e\x53" - "\x9f\x1e\xc8\x9f\x18\x47\xbd\x3f\x5e\x83\x36\x6f\xe5\x7d\x8d\xb0" - "\x05\xd6\xcf\x68\xd3\xaa\x3d\x69\xf2\xf1\x9d\x34\x5d\x59\x47\xef" - "\xea\xf6\x6f\x42\xfd\x7f\x3b\x71\x07\x15\xc2\x47\x74\x7d\x46\xfa" - "\x9d\x5d\x7e\x19\x77\x42\x87\x31\xef\xe7\x79\x4f\xaa\x08\x48\x3b" - "\x79\xfe\x6f\x1d\xf5\x55\xe6\xe7\x49\x83\xce\x61\x41\xef\x6d\x7c" - "\xce\xcb\x90\x11\x3d\x94\xed\x3b\x27\xfa\x30\x86\x18\x09\xb5\xb5" - "\x62\x0c\x76\x55\xf4\xbc\x28\x6a\xee\x3c\x4b\x2d\x91\x63\x7c\x46" - "\x94\xe5\x57\x8f\xbf\x6b\x0d\xf6\x7c\x1e\x08\xae\x8d\x53\x8b\x27" - "\x4a\xc1\xba\xcf\x03\xcd\x9d\xc7\xf0\x3b\x46\xcd\xf4\x31\x35\x7b" - "\xff\xb3\x5a\x8e\xdb\xea\x44\x35\xcb\xb9\xef\xbc\x28\x0c\xda\xfe" - "\x37\x71\x5f\x08\x3b\x31\x07\x72\x77\x7d\x46\x9b\x5f\x3b\x08\x3c" - "\x6f\xfe\x19\xb8\xa2\xec\x67\xde\x4d\x87\xf0\xbb\xdb\xbf\x79\x8f" - "\x7e\xbe\x99\x19\xad\x0e\x4b\x60\xa3\xc3\x3b\xd7\x1a\x3f\x2f\x26" - "\xf0\xfd\xb2\xe2\xbc\x18\xcf\x7c\x21\x9c\xcb\x61\xbc\xc7\xf1\xdb" - "\xb1\x3a\xb0\xdd\x11\x9d\x4b\xb0\x55\x45\x6c\x9f\x10\x5f\x58\x7f" - "\x9e\x38\x5c\xa0\x85\xa7\x6a\xe1\x7c\x2d\x3c\x59\x0b\xe7\x69\xe1" - "\x89\x1c\x66\x7a\xbb\xfd\x5b\x26\xeb\x34\x75\x59\x87\xb5\x22\x5c" - "\xa8\xd7\x05\xe8\x19\xee\xf0\xae\xb2\x0a\xa6\x47\xd1\x31\x5e\xa3" - "\x2b\x57\x0b\xeb\xf4\x5c\xe1\x88\xae\xfa\x9f\xa2\xe7\x58\x0a\x3d" - "\xed\x06\x7a\xc8\xe1\xcd\xfb\x32\xf4\xe4\x38\xa2\x79\xff\x2d\x7a" - "\x98\x16\x8e\xeb\xf6\xff\xb8\x34\x99\x9e\x1f\x97\xeb\xf4\xa4\xe9" - "\x3f\x3a\xb8\xff\x58\x7a\x99\xbc\x6b\x7d\x58\x30\x7a\x87\xa1\x0f" - "\xf9\xf1\x9e\xc1\xee\x0a\x46\x5b\x70\x02\x06\xfc\xff\xb8\x5a\x96" - "\xb7\x5c\xec\x57\xfd\xe7\x8f\x3b\xf4\xb3\xf5\xc0\xeb\xae\xcd\x8a" - "\xd7\xdd\x6b\xf9\x6e\xe2\x0a\xba\xdc\xe7\x15\x1d\xf0\xbb\xfe\x4f" - "\xa3\x2b\x9c\xd4\x06\x16\x96\x2f\x5d\xfa\xf4\x5d\xae\x85\xf3\x17" - "\x2d\x70\x5d\x57\xea\x5a\x5a\xf6\xc4\xe3\xe5\x0b\x92\xcf\xac\xca" - "\x61\xdb\xc1\x76\x7e\x87\xba\xbf\x2c\xcc\x6d\x80\xf5\x9f\xfb\x76" - "\x75\xde\xe8\xf3\xaf\x0b\xff\xf3\x23\xb9\x6f\xd8\xf1\x3c\xd9\xea" - "\xe5\xd9\x51\xcf\x7b\xf5\x3e\x61\x8d\xe6\xe3\x58\x73\xf8\x5e\x92" - "\xe7\xd1\xff\x6d\xce\x31\xc4\x33\xec\x4e\x3d\x8e\xf1\x6b\xb6\x69" - "\xd8\x49\x7a\x7e\x0a\x97\x69\x2a\xc3\xf3\xa2\x01\x3e\xb4\x25\x2e" - "\x8a\xac\xb0\x29\x82\xef\xaa\x84\xff\x6b\x45\x3e\x01\x7a\xce\xb1" - "\xed\x2d\x44\x98\xc7\xf6\x2e\x9f\x00\x8d\x2f\x64\x22\xcf\x4e\xc4" - "\xd9\x36\xc5\x79\x97\xa3\xe8\xe0\x7c\x88\xbf\x9a\xef\x7f\x2b\xe4" - "\x33\xe4\xa2\xf2\x6e\x08\x8e\xbb\x83\xef\x67\x43\x5c\x8e\x21\xee" - "\x7e\xc4\x39\x11\xe7\xd2\xf0\xcd\x62\x39\x23\x9c\xa7\xf9\xf2\x0c" - "\xf3\xb4\x56\x6e\xb5\x91\xe6\x82\x49\xf7\x4f\xb9\xed\xe6\x5c\x57" - "\xe1\x8c\x6f\xdd\x7d\xcf\xf7\x17\x2f\x7a\x3c\x8b\xa4\xd8\xdd\xb9" - "\xde\xeb\x72\x6f\xf3\x5e\x7f\x97\xcb\xb3\x60\xc1\x12\xd7\x8a\x05" - "\x8b\xca\x5d\xf3\x57\xcc\xaf\xc8\xa2\xc7\x17\x2f\xf9\xfe\x13\x8b" - "\xfe\x97\xac\x96\xa5\xc5\xdf\x7f\xfc\x7f\xf1\xc1\x62\x0a\x3a\x2b" - "\xa9\x3f\x2e\xe4\xbe\x5d\xbb\x8f\xef\x08\x1e\xbe\x2b\xd3\x89\x77" - "\x23\x9e\xfd\x78\xf6\xe1\xe1\xbb\x9c\x5b\x4f\xd3\xcb\x76\xbc\xf7" - "\x76\xfb\x6b\x73\x74\x7f\xa1\x5f\x77\x6a\xc7\xea\xba\x83\xfe\x7b" - "\xaf\xea\xd7\x6a\x0b\x5b\xa2\xb2\xdd\x24\x74\x69\xf3\xf9\x7e\x5d" - "\x92\x77\x78\xf3\x99\x79\xcb\x91\x0e\xdd\xe5\x7b\xb2\x20\xeb\x4c" - "\x96\xd7\x29\xfa\xc9\x65\xf0\x99\x9b\xf8\x6e\x48\xbc\x1b\xa1\x27" - "\x4d\xca\x07\xac\x6d\x05\xdc\xd5\x28\x63\xbf\x56\x86\x0a\x8f\x12" - "\x47\x90\x9e\x71\x52\x0b\x33\xae\x53\xf4\xd2\xeb\xfc\x9b\xdf\xda" - "\xfe\x7f\x47\x30\x22\xc7\x26\xd6\xfe\xb4\x17\xef\xd4\xca\xe0\x73" - "\x0e\xab\xd9\xf7\xd1\xfd\x5d\x1e\xe7\x3a\x2c\xf7\x0a\xd0\xf3\x79" - "\x3c\x63\x76\x9b\xbc\xaf\xb8\xba\x17\xb6\xe1\xf6\xdb\x83\x5e\x11" - "\x40\xba\x85\xc7\xc1\x0f\x7a\x44\xbc\xc5\x73\x8e\xe2\x19\x4f\xb5" - "\xb1\x2c\x59\x7e\xa7\xa9\x76\x88\x1a\x43\xbd\x6c\x97\xf8\x80\x5f" - "\xd1\xfb\xa2\x3a\x23\x57\xf9\xdd\x7c\x07\x18\xfb\xd5\xfb\xb8\x7c" - "\xbe\xcb\x0f\x70\xad\xf5\x2a\x7c\xac\x9f\xe7\x17\xd7\xea\x34\x69" - "\xf1\xad\x80\x3b\xa6\xee\xc9\xab\x3d\xa1\xa7\x29\xdf\xbc\x2e\x0f" - "\x32\xf8\x0b\xf3\xc2\x78\xe5\x37\x0f\xbd\x51\x09\x87\xbc\x7b\x74" - "\xbb\xc1\x76\xa2\x38\x86\x76\x26\x7d\xd8\x17\x43\x09\x1f\x36\x51" - "\x9f\x2f\x46\xcc\x6c\x81\x59\xfd\x69\x32\x9e\x2b\xfc\x2f\x78\x41" - "\xd7\x1e\x29\x4b\x43\x39\xb0\x4f\x7d\xaa\x9c\x97\xf2\x13\xbe\xad" - "\x96\x8e\xb4\x58\x88\x69\xeb\x95\xdf\xb1\x68\xed\xfe\x25\x8f\xde" - "\xee\x75\xb8\x78\x4d\x4b\x36\xda\xbe\xcd\x61\x11\x71\x87\xd7\x22" - "\x78\xce\x86\xfb\x3c\xe9\x53\x00\x66\xc4\x39\xc8\xb2\x97\xc7\x1f" - "\x2f\x8d\x8b\xaf\x6b\x51\x3e\xa6\xff\x85\x1f\xf5\xdb\x92\x97\x1a" - "\x53\x71\xb2\x2d\x91\x77\x27\xdb\x5b\xb2\x8b\x63\x36\x3e\x33\xd6" - "\x22\x32\x5b\xb2\x39\x5d\xa3\xb7\x27\x95\x5e\xd6\xb3\x69\xb1\x3e" - "\xa1\xdd\x4d\x0a\x7f\xe2\xa5\x42\x99\x36\x4a\x34\xaa\xba\xda\xfa" - "\x0e\xd7\x07\xda\xc9\xee\x6e\xff\x4f\x30\xfe\x7f\xbe\x51\x1b\xc3" - "\x34\xc1\x2e\xed\x3e\xbc\x72\x32\x60\x7e\x52\x98\x52\x9f\xfb\x35" - "\xdd\xae\x30\x8c\xb5\x8e\xa9\xfa\xbc\xa7\xfa\x24\xfd\xa4\xd6\x10" - "\xaf\xd5\xf3\xe1\x82\x93\xb4\xf5\x01\x35\x06\x6b\x6e\x52\xba\xf5" - "\x13\xa9\x0b\x3a\xad\x42\x8d\x9f\xf7\xf2\xfd\xa9\x5c\x07\xfd\x7c" - "\xfd\xa4\x55\xb7\xfd\xdc\x56\x43\x4a\x37\xf6\xb3\xcc\x20\x2b\x1b" - "\xe4\xf6\x0b\x25\xb3\x9f\xf4\x24\x64\xc6\x77\xd4\xa3\x8c\x11\xab" - "\x45\x7c\x44\x04\x6e\x27\xca\x2c\xae\xb0\x11\xeb\x3f\xb7\x59\x9e" - "\xef\x64\x18\xee\x1f\x75\xb9\x76\xfb\xb7\x4e\x18\x58\xdf\x7d\x22" - "\x44\x3f\xd9\xc5\x74\x24\xf3\x39\xac\xf5\xa4\xce\x3f\xec\x10\x8f" - "\xc5\x11\xf6\x6a\xe3\xdd\xa6\xc0\x68\xfe\x2e\xaa\x76\xd5\x61\xdb" - "\xb7\xe8\xb0\x77\x3c\x29\xf9\x6e\xdd\x0a\xf9\x8e\xd3\xc7\xda\x5c" - "\x37\x2c\x63\x96\xa9\xa8\x69\xb1\xeb\x75\xa4\xce\x7e\xab\xf5\x8a" - "\x75\x2d\x72\x8c\xc0\xb4\x74\x59\xe5\x3d\xe3\xad\x4c\x13\xdb\x3a" - "\x6e\x8f\xb2\x3d\x80\x9e\x7e\x39\x6d\xed\x31\xc8\xa9\x91\x65\xa4" - "\xc9\x6a\x6f\x8a\x6d\x5e\xe0\x5a\x78\xb7\xb2\xad\x2e\xf7\x75\xa5" - "\xb7\xf0\xc9\x8d\xd7\xbb\xfe\x69\xd2\x5d\xae\x82\xbb\xaf\xf3\x96" - "\x8d\x7b\x90\x5f\xff\xab\x6c\xdc\xa4\x82\xa9\x1c\x4e\xb6\xbf\xae" - "\x6e\xff\xcb\x25\x21\xcb\x3d\x36\x2e\x27\xbe\x5c\x74\x6e\x3e\x4b" - "\x14\x63\x79\x2f\x62\xbd\x6f\xde\x35\x0d\x36\x74\x5a\x85\xf8\xa2" - "\x1e\xf1\xf5\x88\xe3\xbe\x8d\xc7\x9a\xf1\x75\xcd\xbb\xc2\x99\xc2" - "\x15\xce\x8c\x87\xc2\x99\x47\xa7\x4e\xb9\xde\x27\x80\x6b\xb7\x4e" - "\xb3\xc8\xc0\xf8\x11\xf9\x75\x3b\x15\x8c\x76\xf0\xbd\x94\x36\x8c" - "\x61\x76\x89\x0c\x1e\x47\xbe\xdc\x06\x3b\x5e\xaa\xce\xc1\x7d\x19" - "\xfe\xcf\x0b\x47\x34\x5f\xb9\x00\x61\xb4\xff\x6f\xc8\x3b\x83\x85" - "\xd5\x49\x22\xe3\x86\xe9\x6c\x4b\x24\xce\x75\xf1\x90\x09\xde\xa1" - "\x3a\x5e\xfa\x92\x67\x8e\x8a\xac\x96\x1a\xfe\x76\xa9\xde\x1a\x2f" - "\x72\x44\x2d\xd5\xfc\xfd\x92\xfe\xad\x56\x7c\x3d\xd2\x2c\xea\xbe" - "\x65\xb4\xf7\x6a\x86\xd1\xd3\x36\xfb\xe3\xa1\xcd\xd6\x78\x0f\xc6" - "\x68\x39\xca\xef\xed\x64\xfb\x8d\x31\xe4\x2b\xbb\xf4\x7e\x49\xeb" - "\xd3\xaa\xd5\x39\xae\xaf\xfc\x81\xf3\x9d\xf5\xdb\x60\x1f\x5e\x2e" - "\xb8\x66\xa4\x1c\x5b\xf4\x08\xab\x3e\x9e\x7d\x65\x3b\xa7\x6f\x52" - "\xf3\x35\x57\x39\x56\x8b\x70\x55\x44\x84\x1d\x51\x11\xe6\xf9\x5b" - "\x69\xfb\xe9\x34\x05\x2b\xbb\xab\xf9\x5e\x75\xe9\xbb\xa0\x5c\x65" - "\xf7\x63\xca\xee\xa3\x7c\x8c\xf5\x4b\x60\xfb\x2d\xa7\xe9\x95\x85" - "\x4c\xbf\x26\xa3\xec\x38\xe4\x15\xe4\x7e\x8e\xe5\x93\xd5\x6a\x4f" - "\xc7\x33\x78\x0a\x6d\xf2\x83\x2f\x2b\xf8\xf2\x9e\xe1\xf6\xd1\xc3" - "\xdf\xd8\xa1\x7d\x8d\xea\xbf\xef\x6d\xdb\x06\x73\x1e\xb7\xbd\x31" - "\x38\x8f\xdb\x56\x6b\x6d\x4b\xd2\xc9\xf6\xa2\x93\xb6\xe5\x8d\x58" - "\xcd\xdf\xaf\x35\xef\x82\x4e\x4d\xe2\x76\xb2\xc3\x2f\xf8\xce\xb5" - "\x5d\x66\xf5\xa5\xce\x8b\x66\x5c\x75\x53\x1d\xab\xab\x4b\xba\xfd" - "\x75\x4e\x23\x2d\xdc\xe7\x68\xe9\x77\x9a\xd1\x12\xf7\x33\x2d\x4c" - "\x6b\xdd\x70\xce\xcf\x74\xf0\xfc\x98\x23\x8a\x41\x36\x74\x18\xe3" - "\xac\x1a\xb3\x72\x47\xac\x6e\x60\xba\x4c\xd3\x60\x73\x3a\xd9\x2e" - "\xc9\xfe\xcc\x4b\x62\x1a\x1e\xb6\x41\xa0\x6d\xaf\x6e\x7b\x1c\x16" - "\x57\x86\xb4\x05\x56\xb1\xc5\x0c\x87\x63\xf5\x16\xfe\x7e\x6e\x12" - "\xca\x37\x4d\x87\x8c\x5d\x90\xd1\xd6\xf8\x9a\x1b\xaf\x71\x58\xe8" - "\xde\x70\xc6\x8d\x59\x0e\x6f\x74\x2c\xcb\x10\x38\xbd\xa7\x68\xc7" - "\x3b\x3c\xbe\x54\xf7\x1e\x6f\x1f\x17\xa2\x37\xe4\xbc\x71\x38\xb3" - "\x79\xab\x9a\x13\xda\x9e\x17\xa2\xbd\xd9\xfd\x73\x44\xdb\x0b\x42" - "\x96\x2b\x95\x5d\xcd\xb8\xfc\x15\xb1\xfe\xa8\x33\xee\x77\x08\xd7" - "\x4a\x07\xfc\xbf\xed\x7f\x8b\x0b\xb7\x55\x64\x1d\x75\xf6\xeb\x89" - "\xfa\xb6\x4f\xd7\x13\xe4\xdf\x62\xae\x03\xdb\xdf\x1a\x5c\x07\xb6" - "\x3f\xc7\xe9\x2c\x77\x35\xc6\xd8\xde\x96\x98\xdf\x5a\x73\xf9\x2b" - "\xae\x2a\x59\xfe\x42\x55\x36\xcb\x24\x8f\xe7\xd6\xa6\x42\x2e\xd5" - "\xdd\xfe\x1d\xb6\x84\x3d\x80\xbe\x38\x62\x64\x61\xbb\xc4\xba\x82" - "\x34\x17\x6c\x8e\x9c\x8f\xe2\x3b\x84\x61\xd3\xc6\xc4\xfd\x2f\x8f" - "\x0c\xfb\xca\xb6\xf1\x19\xb0\x91\xcc\x96\x1c\xc0\x60\xfc\x77\x62" - "\x9f\x9a\xdf\x6d\xb1\xc3\x3e\x67\xd7\x5e\x0a\x7b\xab\xbe\x57\xcd" - "\xe6\x36\x8d\x77\x0e\xb7\x6b\xc4\x8d\x04\xdd\x39\x08\x63\x9c\xb2" - "\xa3\x52\xef\x83\xe2\xfe\x3c\xd8\x03\x21\x75\x13\x7d\xcc\x98\x2e" - "\xc8\xee\x45\x6b\x7c\xd7\xf9\x5b\x9c\xc4\x3c\x9f\x5f\x33\x7a\xd7" - "\x0f\x6f\x26\xdb\xbf\x3b\x1f\x23\xcf\x6d\x34\x72\xf5\xb7\x6c\xf4" - "\x7f\x27\x90\x95\xe5\x10\xa2\x1d\x1b\x94\xec\x76\x34\xe9\xf5\x13" - "\xa2\xed\xe3\xb9\x3e\x52\xfd\x6c\xd7\x13\x4b\x5d\xa5\x8b\x57\x2c" - "\xba\xfa\xea\xa4\x31\x8c\x8d\x1f\xe1\xdf\x11\x52\x7d\x63\xfd\x48" - "\x9d\x2e\xab\xbc\x1f\xb2\x1e\xfe\xef\xcb\xf9\xa9\x63\xae\xa9\xc5" - "\xda\x11\xbf\xc5\xb9\xd4\xff\xfb\x56\x9a\x7a\xab\x21\x78\x3b\x4d" - "\xbd\xed\xf6\xe2\xe9\x0b\xe6\x97\x56\x18\x62\xef\x30\xce\x9b\x6d" - "\x7e\x85\x6d\xef\xe8\xef\xc2\x16\x58\x1e\x7c\x96\xfb\xfa\x86\xcc" - "\xaa\xa8\xf8\xab\xe0\xbb\x79\xac\x54\xdc\x5c\x1e\xa5\x66\xd8\x2a" - "\x71\x39\x6c\xb5\x7f\x98\xba\x07\x02\x3e\x12\x74\xc7\x31\x0d\x76" - "\x0c\xfe\xda\x39\x9e\x37\x41\xbe\x9b\x5a\xb6\xf6\xa0\xcd\x1f\x2d" - "\x54\x3e\x43\x3d\x8f\x61\x2e\x41\xfc\x25\x78\x0f\xc5\xfb\x6b\xae" - "\x45\x18\x8f\xf0\x39\xc2\xcb\xf9\x1c\xe1\xfa\x18\xcb\xed\xe6\x48" - "\x35\xdd\xbc\x84\x7d\xea\xfa\x86\xc3\xe5\xec\x67\x35\x14\xc8\x35" - "\x09\xc0\x22\xee\x6f\xae\x27\x29\x97\xdf\xec\xd3\x86\x80\x53\xac" - "\x3b\x5a\x28\xb6\x61\x5c\x55\x45\x63\x81\xf3\x81\x0c\xcb\x5f\x28" - "\xc3\x39\x74\x7f\xb7\xbf\x61\x6a\x88\x36\xd4\xb2\x9c\x90\xdf\x7c" - "\x5e\x2c\xc5\xd7\x28\xae\x80\xaf\x87\x7e\xa6\xd8\xbb\x9e\xf0\xdb" - "\x56\x5f\xa5\x8f\x73\x1b\xb6\x1a\xe6\x5e\xb3\x10\xde\xa5\xeb\x33" - "\x7e\xef\xd5\xf5\xcd\x58\xc6\x94\x45\xe5\x0b\x96\x2c\x28\x75\x5d" - "\xb7\x34\x8b\x0a\x9f\x78\x7a\x41\xe9\x4d\x8b\x97\x95\xbb\x56\x94" - "\x2d\x58\xe4\x5a\xb2\xe0\x99\x65\x0b\x96\x96\xf3\x98\x89\x53\x93" - "\xfa\xe8\x91\x22\xeb\x83\x1a\xfd\x5c\x7a\xd7\x68\x96\xe3\x4f\x2f" *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From rwatson at FreeBSD.org Wed Feb 25 03:00:15 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 03:00:27 2009 Subject: svn commit: r189026 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb net netinet netinet6 Message-ID: <200902251059.n1PAxv4d094194@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 10:59:56 2009 New Revision: 189026 URL: http://svn.freebsd.org/changeset/base/189026 Log: Merge r185747, r185774, r185807, r185849, r185964, r185965, r186051, r186052 from head to stable/7; note that only the locking fixes and invariants checking are added from r185747, but not the move to an rwlock which would modify the kernel binary interface, nor the move to a non-recursible lock, which is still seeing problem reports in head. This corrects, among other things, a deadlock that may occur when processing incoming ICMP redirects. r185747: - convert radix node head lock from mutex to rwlock - make radix node head lock not recursive - fix LOR in rtexpunge - fix LOR in rtredirect Reviewed by: sam r185774: - avoid recursively locking the radix node head lock - assert that it is held if RTF_RNH_LOCKED is not passed r185807: Fix a bug introduced in r185747: rather than dereferencing an uninitialized *rt to something undefined, use the fibnum that came in as function argument. Found with: Coverity Prevent(tm) CID: 4168 r185849: fix a reported panic when adding a route and one hit here when deleting a route - pass RTF_RNH_LOCKED to rtalloc1_fib in 2 cases where the lock is held - make sure the rnh lock is held across rt_setgate and rt_getifa_fib r185964: Pass RTF_RNH_LOCKED to rtalloc1 sunce the node head is locked, this avoids a recursive lock panic on inet6 detach. Reviewed by: kmacy r185965: RTF_RNH_LOCKED needs to be passed in the flags arg not report, apologies to thompsa r186051: in6_addroute is called through rnh_addadr which is always called with the radix node head lock held exclusively. Pass RTF_RNH_LOCKED to rtalloc so that rtalloc1_fib will not try to re-acquire the lock. r186052: don't acquire lock recursively Oiginal commits to head were by kmacy, except r185964 by thompsa and r185807 by bz. A subset of this is a potential errata patch candidate. Reviewed by: bz, kmacy Tested by: Pete French sa_family != AF_INET) /* Only INET supports > 1 fib now */ @@ -290,7 +291,13 @@ rtalloc1_fib(struct sockaddr *dst, int r rtstat.rts_unreach++; goto miss2; } - RADIX_NODE_HEAD_LOCK(rnh); + needlock = !(ignflags & RTF_RNH_LOCKED); + if (needlock) + RADIX_NODE_HEAD_LOCK(rnh); +#ifdef INVARIANTS + else + RADIX_NODE_HEAD_LOCK_ASSERT(rnh); +#endif if ((rn = rnh->rnh_matchaddr(dst, rnh)) && (rn->rn_flags & RNF_ROOT) == 0) { /* @@ -343,7 +350,8 @@ rtalloc1_fib(struct sockaddr *dst, int r RT_LOCK(newrt); RT_ADDREF(newrt); } - RADIX_NODE_HEAD_UNLOCK(rnh); + if (needlock) + RADIX_NODE_HEAD_UNLOCK(rnh); } else { /* * Either we hit the root or couldn't find any match, @@ -352,7 +360,8 @@ rtalloc1_fib(struct sockaddr *dst, int r */ rtstat.rts_unreach++; miss: - RADIX_NODE_HEAD_UNLOCK(rnh); + if (needlock) + RADIX_NODE_HEAD_UNLOCK(rnh); miss2: if (report) { /* * If required, report the failure to the supervising @@ -482,6 +491,8 @@ rtredirect_fib(struct sockaddr *dst, short *stat = NULL; struct rt_addrinfo info; struct ifaddr *ifa; + struct radix_node_head *rnh = + rt_tables[fibnum][dst->sa_family]; /* verify the gateway is directly reachable */ if ((ifa = ifa_ifwithnet(gateway)) == NULL) { @@ -531,6 +542,8 @@ rtredirect_fib(struct sockaddr *dst, info.rti_info[RTAX_NETMASK] = netmask; info.rti_ifa = ifa; info.rti_flags = flags; + if (rt0 != NULL) + RT_UNLOCK(rt0); /* drop lock to avoid LOR with RNH */ error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum); if (rt != NULL) { RT_LOCK(rt); @@ -538,7 +551,7 @@ rtredirect_fib(struct sockaddr *dst, flags = rt->rt_flags; } if (rt0) - RTFREE_LOCKED(rt0); + RTFREE(rt0); stat = &rtstat.rts_dynamic; } else { @@ -554,8 +567,12 @@ rtredirect_fib(struct sockaddr *dst, /* * add the key and gateway (in one malloc'd chunk). */ + RT_UNLOCK(rt); + RADIX_NODE_HEAD_LOCK(rnh); + RT_LOCK(rt); rt_setgate(rt, rt_key(rt), gateway); - gwrt = rtalloc1(gateway, 1, 0); + gwrt = rtalloc1(gateway, 1, RTF_RNH_LOCKED); + RADIX_NODE_HEAD_UNLOCK(rnh); EVENTHANDLER_INVOKE(route_redirect_event, rt, gwrt, dst); RTFREE_LOCKED(gwrt); } @@ -641,7 +658,7 @@ ifa_ifwithroute_fib(int flags, struct so if (ifa == NULL) ifa = ifa_ifwithnet(gateway); if (ifa == NULL) { - struct rtentry *rt = rtalloc1_fib(gateway, 0, 0UL, fibnum); + struct rtentry *rt = rtalloc1_fib(gateway, 0, RTF_RNH_LOCKED, fibnum); if (rt == NULL) return (NULL); /* @@ -788,7 +805,9 @@ rtexpunge(struct rtentry *rt) struct ifaddr *ifa; int error = 0; + rnh = rt_tables[rt->rt_fibnum][rt_key(rt)->sa_family]; RT_LOCK_ASSERT(rt); + RADIX_NODE_HEAD_LOCK_ASSERT(rnh); #if 0 /* * We cannot assume anything about the reference count @@ -804,8 +823,6 @@ rtexpunge(struct rtentry *rt) if (rnh == NULL) return (EAFNOSUPPORT); - RADIX_NODE_HEAD_LOCK(rnh); - /* * Remove the item from the tree; it should be there, * but when callers invoke us blindly it may not (sigh). @@ -860,7 +877,6 @@ rtexpunge(struct rtentry *rt) */ rttrash++; bad: - RADIX_NODE_HEAD_UNLOCK(rnh); return (error); } @@ -874,7 +890,7 @@ int rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt, u_int fibnum) { - int error = 0; + int error = 0, needlock = 0; register struct rtentry *rt; register struct radix_node *rn; register struct radix_node_head *rnh; @@ -891,7 +907,12 @@ rtrequest1_fib(int req, struct rt_addrin rnh = rt_tables[fibnum][dst->sa_family]; if (rnh == NULL) return (EAFNOSUPPORT); - RADIX_NODE_HEAD_LOCK(rnh); + needlock = ((flags & RTF_RNH_LOCKED) == 0); + flags &= ~RTF_RNH_LOCKED; + if (needlock) + RADIX_NODE_HEAD_LOCK(rnh); + else + RADIX_NODE_HEAD_LOCK_ASSERT(rnh); /* * If we are adding a host route then we don't want to put * a netmask in the tree, nor do we want to clone it. @@ -1036,7 +1057,7 @@ rtrequest1_fib(int req, struct rt_addrin * then we just blow it away and retry the insertion * of the new one. */ - rt2 = rtalloc1_fib(dst, 0, 0, fibnum); + rt2 = rtalloc1_fib(dst, 0, RTF_RNH_LOCKED, fibnum); if (rt2 && rt2->rt_parent) { rtexpunge(rt2); RT_UNLOCK(rt2); @@ -1125,7 +1146,8 @@ rtrequest1_fib(int req, struct rt_addrin error = EOPNOTSUPP; } bad: - RADIX_NODE_HEAD_UNLOCK(rnh); + if (needlock) + RADIX_NODE_HEAD_UNLOCK(rnh); return (error); #undef senderr } @@ -1153,7 +1175,7 @@ rt_fixdelete(struct radix_node *rn, void if (rt->rt_parent == rt0 && !(rt->rt_flags & (RTF_PINNED | RTF_CLONING))) { return rtrequest_fib(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), - rt->rt_flags, NULL, rt->rt_fibnum); + rt->rt_flags|RTF_RNH_LOCKED, NULL, rt->rt_fibnum); } return 0; } @@ -1230,6 +1252,7 @@ rt_setgate(struct rtentry *rt, struct so again: RT_LOCK_ASSERT(rt); + RADIX_NODE_HEAD_LOCK_ASSERT(rnh); /* * A host route with the destination equal to the gateway @@ -1256,7 +1279,7 @@ again: struct rtentry *gwrt; RT_UNLOCK(rt); /* XXX workaround LOR */ - gwrt = rtalloc1_fib(gate, 1, 0, rt->rt_fibnum); + gwrt = rtalloc1_fib(gate, 1, RTF_RNH_LOCKED, rt->rt_fibnum); if (gwrt == rt) { RT_REMREF(rt); return (EADDRINUSE); /* failure */ @@ -1327,12 +1350,8 @@ again: arg.rnh = rnh; arg.rt0 = rt; - RT_UNLOCK(rt); /* XXX workaround LOR */ - RADIX_NODE_HEAD_LOCK(rnh); - RT_LOCK(rt); rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt), rt_fixchange, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); } return 0; Modified: stable/7/sys/net/route.h ============================================================================== --- stable/7/sys/net/route.h Wed Feb 25 10:52:09 2009 (r189025) +++ stable/7/sys/net/route.h Wed Feb 25 10:59:56 2009 (r189026) @@ -172,6 +172,7 @@ struct ortentry { #define RTF_BROADCAST 0x400000 /* route represents a bcast address */ #define RTF_MULTICAST 0x800000 /* route represents a mcast address */ /* 0x1000000 and up unassigned */ +#define RTF_RNH_LOCKED 0x40000000 /* radix node head locked by caller */ /* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */ #define RTF_FMASK \ Modified: stable/7/sys/net/rtsock.c ============================================================================== --- stable/7/sys/net/rtsock.c Wed Feb 25 10:52:09 2009 (r189025) +++ stable/7/sys/net/rtsock.c Wed Feb 25 10:59:56 2009 (r189026) @@ -628,9 +628,11 @@ route_output(struct mbuf *m, struct sock !sa_equal(info.rti_info[RTAX_IFA], rt->rt_ifa->ifa_addr))) { RT_UNLOCK(rt); + RADIX_NODE_HEAD_LOCK(rnh); if ((error = rt_getifa_fib(&info, rt->rt_fibnum)) != 0) senderr(error); + RADIX_NODE_HEAD_UNLOCK(rnh); RT_LOCK(rt); } if (info.rti_ifa != NULL && @@ -642,8 +644,14 @@ route_output(struct mbuf *m, struct sock IFAFREE(rt->rt_ifa); } if (info.rti_info[RTAX_GATEWAY] != NULL) { - if ((error = rt_setgate(rt, rt_key(rt), - info.rti_info[RTAX_GATEWAY])) != 0) { + RT_UNLOCK(rt); + RADIX_NODE_HEAD_LOCK(rnh); + RT_LOCK(rt); + + error = rt_setgate(rt, rt_key(rt), + info.rti_info[RTAX_GATEWAY]); + RADIX_NODE_HEAD_UNLOCK(rnh); + if (error != 0) { RT_UNLOCK(rt); senderr(error); } Modified: stable/7/sys/netinet/in_rmx.c ============================================================================== --- stable/7/sys/netinet/in_rmx.c Wed Feb 25 10:52:09 2009 (r189025) +++ stable/7/sys/netinet/in_rmx.c Wed Feb 25 10:59:56 2009 (r189026) @@ -111,7 +111,7 @@ in_addroute(void *v_arg, void *n_arg, st * ARP entry and delete it if so. */ rt2 = in_rtalloc1((struct sockaddr *)sin, 0, - RTF_CLONING, rt->rt_fibnum); + RTF_CLONING|RTF_RNH_LOCKED, rt->rt_fibnum); if (rt2) { if (rt2->rt_flags & RTF_LLINFO && rt2->rt_flags & RTF_HOST && Modified: stable/7/sys/netinet6/in6_ifattach.c ============================================================================== --- stable/7/sys/netinet6/in6_ifattach.c Wed Feb 25 10:52:09 2009 (r189025) +++ stable/7/sys/netinet6/in6_ifattach.c Wed Feb 25 10:59:56 2009 (r189026) @@ -823,7 +823,7 @@ in6_ifdetach(struct ifnet *ifp) /* XXX grab lock first to avoid LOR */ if (rt_tables[0][AF_INET6] != NULL) { RADIX_NODE_HEAD_LOCK(rt_tables[0][AF_INET6]); - rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL); + rt = rtalloc1((struct sockaddr *)&sin6, 0, RTF_RNH_LOCKED); if (rt) { if (rt->rt_ifp == ifp) rtexpunge(rt); Modified: stable/7/sys/netinet6/in6_rmx.c ============================================================================== --- stable/7/sys/netinet6/in6_rmx.c Wed Feb 25 10:52:09 2009 (r189025) +++ stable/7/sys/netinet6/in6_rmx.c Wed Feb 25 10:59:56 2009 (r189026) @@ -154,7 +154,7 @@ in6_addroute(void *v_arg, void *n_arg, s * Find out if it is because of an * ARP entry and delete it if so. */ - rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_CLONING); + rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED|RTF_CLONING); if (rt2) { if (rt2->rt_flags & RTF_LLINFO && rt2->rt_flags & RTF_HOST && @@ -181,7 +181,7 @@ in6_addroute(void *v_arg, void *n_arg, s * net route entry, 3ffe:0501:: -> if0. * This case should not raise an error. */ - rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_CLONING); + rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED|RTF_CLONING); if (rt2) { if ((rt2->rt_flags & (RTF_CLONING|RTF_HOST|RTF_GATEWAY)) == RTF_CLONING From rwatson at FreeBSD.org Wed Feb 25 03:18:19 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 03:18:36 2009 Subject: svn commit: r189029 - stable/7/sys/net Message-ID: <200902251118.n1PBIIcQ094668@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 11:18:18 2009 New Revision: 189029 URL: http://svn.freebsd.org/changeset/base/189029 Log: Correct a deadlock and a rtentry leak in rt_check(): - In the event that a gateway route has to be looked up, drop the lock on 'rt' before reacquiring it 'rt0' in order to avoid deadlock. - In the event the original route has evaporated or is no longer up after the gateway route lookup, call RTFREE() on the gateway route before retrying. This is a potential errata candidate patch. PR: kern/130652 Submitted by: Dmitrij Tejblum Reviewed by: bz Tested by: Pete French Modified: stable/7/sys/net/route.c Modified: stable/7/sys/net/route.c ============================================================================== --- stable/7/sys/net/route.c Wed Feb 25 11:13:13 2009 (r189028) +++ stable/7/sys/net/route.c Wed Feb 25 11:18:18 2009 (r189029) @@ -1650,27 +1650,34 @@ retry: return (ENETUNREACH); } /* - * Relock it and lose the added reference. - * All sorts of things could have happenned while we - * had no lock on it, so check for them. + * Relock it and lose the added reference. All sorts + * of things could have happenned while we had no + * lock on it, so check for them. rt need to be + * unlocked to avoid possible deadlock. */ + RT_UNLOCK(rt); RT_RELOCK(rt0); - if (rt0 == NULL || ((rt0->rt_flags & RTF_UP) == 0)) + if (rt0 == NULL || ((rt0->rt_flags & RTF_UP) == 0)) { /* Ru-roh.. what we had is no longer any good */ + RTFREE(rt); goto retry; + } /* * While we were away, someone replaced the gateway. * Since a reference count is involved we can't just * overwrite it. */ if (rt0->rt_gwroute) { - if (rt0->rt_gwroute != rt) { - RTFREE_LOCKED(rt); - goto retry; - } + if (rt0->rt_gwroute != rt) + RTFREE(rt); } else { rt0->rt_gwroute = rt; } + /* + * Since rt was not locked, we need recheck that + * it still may be used (e.g. up) + */ + goto retry; } RT_LOCK_ASSERT(rt); RT_UNLOCK(rt0); From rwatson at FreeBSD.org Wed Feb 25 03:37:20 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 03:37:27 2009 Subject: svn commit: r189030 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/nve Message-ID: <200902251137.n1PBbJkM095110@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 11:37:19 2009 New Revision: 189030 URL: http://svn.freebsd.org/changeset/base/189030 Log: Merge r179458 from head to stable/7: Import rewritten nve device id's, which brings this more inline with if_nfe. PR: 110883 Submitted by: Claudel Approved by: imp (mentor, implicit) Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/nve/if_nve.c stable/7/sys/dev/nve/if_nvereg.h Modified: stable/7/sys/dev/nve/if_nve.c ============================================================================== --- stable/7/sys/dev/nve/if_nve.c Wed Feb 25 11:18:18 2009 (r189029) +++ stable/7/sys/dev/nve/if_nve.c Wed Feb 25 11:37:19 2009 (r189030) @@ -211,32 +211,52 @@ DRIVER_MODULE(nve, pci, nve_driver, nve_ DRIVER_MODULE(miibus, nve, miibus_driver, miibus_devclass, 0, 0); static struct nve_type nve_devs[] = { - {NVIDIA_VENDORID, NFORCE_MCPNET1_DEVICEID, - "NVIDIA nForce MCP Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET2_DEVICEID, - "NVIDIA nForce MCP2 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET3_DEVICEID, - "NVIDIA nForce MCP3 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET4_DEVICEID, - "NVIDIA nForce MCP4 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET5_DEVICEID, - "NVIDIA nForce MCP5 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET6_DEVICEID, - "NVIDIA nForce MCP6 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET7_DEVICEID, - "NVIDIA nForce MCP7 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET8_DEVICEID, - "NVIDIA nForce MCP8 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET9_DEVICEID, - "NVIDIA nForce MCP9 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET10_DEVICEID, - "NVIDIA nForce MCP10 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET11_DEVICEID, - "NVIDIA nForce MCP11 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET12_DEVICEID, - "NVIDIA nForce MCP12 Networking Adapter"}, - {NVIDIA_VENDORID, NFORCE_MCPNET13_DEVICEID, - "NVIDIA nForce MCP13 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN, + "NVIDIA nForce MCP Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN, + "NVIDIA nForce2 MCP2 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1, + "NVIDIA nForce2 400 MCP4 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2, + "NVIDIA nForce2 400 MCP5 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1, + "NVIDIA nForce3 MCP3 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_LAN, + "NVIDIA nForce3 250 MCP6 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4, + "NVIDIA nForce3 MCP7 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN1, + "NVIDIA nForce4 CK804 MCP8 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN2, + "NVIDIA nForce4 CK804 MCP9 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1, + "NVIDIA nForce MCP04 Networking Adapter"}, // MCP10 + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2, + "NVIDIA nForce MCP04 Networking Adapter"}, // MCP11 + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN1, + "NVIDIA nForce 430 MCP12 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN2, + "NVIDIA nForce 430 MCP13 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1, + "NVIDIA nForce MCP55 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2, + "NVIDIA nForce MCP55 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1, + "NVIDIA nForce MCP61 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, + "NVIDIA nForce MCP61 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3, + "NVIDIA nForce MCP61 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN4, + "NVIDIA nForce MCP61 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1, + "NVIDIA nForce MCP65 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, + "NVIDIA nForce MCP65 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3, + "NVIDIA nForce MCP65 Networking Adapter"}, + {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN4, + "NVIDIA nForce MCP65 Networking Adapter"}, {0, 0, NULL} }; Modified: stable/7/sys/dev/nve/if_nvereg.h ============================================================================== --- stable/7/sys/dev/nve/if_nvereg.h Wed Feb 25 11:18:18 2009 (r189029) +++ stable/7/sys/dev/nve/if_nvereg.h Wed Feb 25 11:37:19 2009 (r189030) @@ -31,23 +31,41 @@ #ifndef _IF_NVEREG_H_ #define _IF_NVEREG_H_ -#ifndef NVIDIA_VENDORID -#define NVIDIA_VENDORID 0x10DE +#ifndef PCI_VENDOR_NVIDIA +#define PCI_VENDOR_NVIDIA 0x10DE #endif -#define NFORCE_MCPNET1_DEVICEID 0x01C3 -#define NFORCE_MCPNET2_DEVICEID 0x0066 -#define NFORCE_MCPNET3_DEVICEID 0x00D6 -#define NFORCE_MCPNET4_DEVICEID 0x0086 -#define NFORCE_MCPNET5_DEVICEID 0x008C -#define NFORCE_MCPNET6_DEVICEID 0x00E6 -#define NFORCE_MCPNET7_DEVICEID 0x00DF -#define NFORCE_MCPNET8_DEVICEID 0x0056 -#define NFORCE_MCPNET9_DEVICEID 0x0057 -#define NFORCE_MCPNET10_DEVICEID 0x0037 -#define NFORCE_MCPNET11_DEVICEID 0x0038 -#define NFORCE_MCPNET12_DEVICEID 0x0268 -#define NFORCE_MCPNET13_DEVICEID 0x0269 +#define PCI_PRODUCT_NVIDIA_NFORCE_LAN 0x01C3 +#define PCI_PRODUCT_NVIDIA_NFORCE2_LAN 0x0066 +#define PCI_PRODUCT_NVIDIA_NFORCE3_LAN1 0x00D6 +#define PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1 0x0086 +#define PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2 0x008C +#define PCI_PRODUCT_NVIDIA_NFORCE3_250_LAN 0x00E6 +#define PCI_PRODUCT_NVIDIA_NFORCE3_LAN4 0x00DF +#define PCI_PRODUCT_NVIDIA_NFORCE4_LAN1 0x0056 +#define PCI_PRODUCT_NVIDIA_NFORCE4_LAN2 0x0057 +#define PCI_PRODUCT_NVIDIA_MCP04_LAN1 0x0037 +#define PCI_PRODUCT_NVIDIA_MCP04_LAN2 0x0038 +#define PCI_PRODUCT_NVIDIA_NFORCE430_LAN1 0x0268 +#define PCI_PRODUCT_NVIDIA_NFORCE430_LAN2 0x0269 +#define PCI_PRODUCT_NVIDIA_MCP55_LAN1 0x0372 +#define PCI_PRODUCT_NVIDIA_MCP55_LAN2 0x0373 +#define PCI_PRODUCT_NVIDIA_MCP61_LAN1 0x03e5 +#define PCI_PRODUCT_NVIDIA_MCP61_LAN2 0x03e6 +#define PCI_PRODUCT_NVIDIA_MCP61_LAN3 0x03ee +#define PCI_PRODUCT_NVIDIA_MCP61_LAN4 0x03ef +#define PCI_PRODUCT_NVIDIA_MCP65_LAN1 0x0450 +#define PCI_PRODUCT_NVIDIA_MCP65_LAN2 0x0451 +#define PCI_PRODUCT_NVIDIA_MCP65_LAN3 0x0452 +#define PCI_PRODUCT_NVIDIA_MCP65_LAN4 0x0453 + +#define PCI_PRODUCT_NVIDIA_NFORCE3_LAN2 PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1 +#define PCI_PRODUCT_NVIDIA_NFORCE3_LAN3 PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2 +#define PCI_PRODUCT_NVIDIA_NFORCE3_LAN5 PCI_PRODUCT_NVIDIA_NFORCE3_250_LAN +#define PCI_PRODUCT_NVIDIA_CK804_LAN1 PCI_PRODUCT_NVIDIA_NFORCE4_LAN1 +#define PCI_PRODUCT_NVIDIA_CK804_LAN2 PCI_PRODUCT_NVIDIA_NFORCE4_LAN2 +#define PCI_PRODUCT_NVIDIA_MCP51_LAN1 PCI_PRODUCT_NVIDIA_NFORCE430_LAN1 +#define PCI_PRODUCT_NVIDIA_MCP51_LAN2 PCI_PRODUCT_NVIDIA_NFORCE430_LAN2 #define NV_RID 0x10 From rwatson at FreeBSD.org Wed Feb 25 03:44:04 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 03:44:15 2009 Subject: svn commit: r189031 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251144.n1PBi3Jp095313@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 11:44:03 2009 New Revision: 189031 URL: http://svn.freebsd.org/changeset/base/189031 Log: Merge r186825 from head to stable/7: Do a lockless read of the audit pipe list before grabbing the audit pipe lock in order to avoid the lock acquire hit if the pipe list is very likely empty. Obtained from: TrustedBSD Project Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 11:37:19 2009 (r189030) +++ stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 11:44:03 2009 (r189031) @@ -407,6 +407,10 @@ audit_pipe_preselect(au_id_t auid, au_ev { struct audit_pipe *ap; + /* Lockless read to avoid acquiring the global lock if not needed. */ + if (TAILQ_EMPTY(&audit_pipe_list)) + return (0); + AUDIT_PIPE_LIST_RLOCK(); TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) { AUDIT_PIPE_LOCK(ap); From rwatson at FreeBSD.org Wed Feb 25 04:00:17 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 04:00:29 2009 Subject: svn commit: r189032 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251200.n1PC0FE9095817@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 12:00:15 2009 New Revision: 189032 URL: http://svn.freebsd.org/changeset/base/189032 Log: Merge r184508 from head to stable/7: Historically, /dev/auditpipe has allows only whole records to be read via read(2), which meant that records longer than the buffer passed to read(2) were dropped. Instead take the approach of allowing partial reads to be continued across multiple system calls more in the style of streaming character device. This means retaining a record on the per-pipe queue in a partially read state, so maintain a current offset into the record. Keep the record on the queue during a read, so add a new lock, ap_sx, to serialize removal of records from the queue by either read(2) or ioctl(2) requesting a pipe flush. Modify the kqueue handler to return bytes left in the current record rather than simply the size of the current record. It is now possible to use praudit, which used the standard FILE * buffer sizes, to track much larger record sizes from /dev/auditpipe, such as very long command lines to execve(2). Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 11:44:03 2009 (r189031) +++ stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 12:00:15 2009 (r189032) @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -84,6 +85,7 @@ static MALLOC_DEFINE(M_AUDIT_PIPE_PRESEL struct audit_pipe_entry { void *ape_record; u_int ape_record_len; + u_int ape_record_offset; TAILQ_ENTRY(audit_pipe_entry) ape_queue; }; @@ -120,7 +122,15 @@ struct audit_pipe { /* * Per-pipe mutex protecting most fields in this data structure. */ - struct mtx ap_lock; + struct mtx ap_mtx; + + /* + * Per-pipe sleep lock serializing user-generated reads and flushes. + * uiomove() is called to copy out the current head record's data + * while the record remains in the queue, so we prevent other threads + * from removing it using this lock. + */ + struct sx ap_sx; /* * Condition variable to signal when data has been delivered to a @@ -147,7 +157,9 @@ struct audit_pipe { TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list; /* - * Current pending record list. + * Current pending record list. Protected by a combination of ap_mtx + * and ap_sx. Note particularly that *both* locks are required to + * remove a record from the head of the queue, as an in-progress read * may sleep while copying and therefore cannot hold ap_mtx. */ TAILQ_HEAD(, audit_pipe_entry) ap_queue; @@ -157,13 +169,19 @@ struct audit_pipe { TAILQ_ENTRY(audit_pipe) ap_list; }; -#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_lock) -#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_lock, MA_OWNED) -#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_lock) -#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_lock, \ - "audit_pipe_lock", NULL, MTX_DEF) -#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_lock) -#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_lock) +#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx) +#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED) +#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx) +#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \ + "audit_pipe_mtx", NULL, MTX_DEF) +#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx) +#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx) + +#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) sx_destroy(&(ap)->ap_sx) +#define AUDIT_PIPE_SX_LOCK_INIT(ap) sx_init(&(ap)->ap_sx, "audit_pipe_sx") +#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) sx_assert(&(ap)->ap_sx, SA_XLOCKED) +#define AUDIT_PIPE_SX_XLOCK_SIG(ap) sx_xlock_sig(&(ap)->ap_sx) +#define AUDIT_PIPE_SX_XUNLOCK(ap) sx_xunlock(&(ap)->ap_sx) /* * Global list of audit pipes, rwlock to protect it. Individual record @@ -461,6 +479,7 @@ audit_pipe_append(struct audit_pipe *ap, bcopy(record, ape->ape_record, record_len); ape->ape_record_len = record_len; + ape->ape_record_offset = 0; TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); ap->ap_inserts++; @@ -534,26 +553,6 @@ audit_pipe_submit_user(void *record, u_i } /* - * Pop the next record off of an audit pipe. - */ -static struct audit_pipe_entry * -audit_pipe_pop(struct audit_pipe *ap) -{ - struct audit_pipe_entry *ape; - - AUDIT_PIPE_LOCK_ASSERT(ap); - - ape = TAILQ_FIRST(&ap->ap_queue); - KASSERT((ape == NULL && ap->ap_qlen == 0) || - (ape != NULL && ap->ap_qlen != 0), ("audit_pipe_pop: qlen")); - if (ape == NULL) - return (NULL); - TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); - ap->ap_qlen--; - return (ape); -} - -/* * Allocate a new audit pipe. Connects the pipe, on success, to the global * list and updates statistics. */ @@ -572,6 +571,7 @@ audit_pipe_alloc(void) knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL, NULL); AUDIT_PIPE_LOCK_INIT(ap); + AUDIT_PIPE_SX_LOCK_INIT(ap); cv_init(&ap->ap_cv, "audit_pipe"); /* @@ -630,6 +630,7 @@ audit_pipe_free(struct audit_pipe *ap) audit_pipe_preselect_flush_locked(ap); audit_pipe_flush(ap); cv_destroy(&ap->ap_cv); + AUDIT_PIPE_SX_LOCK_DESTROY(ap); AUDIT_PIPE_LOCK_DESTROY(ap); knlist_destroy(&ap->ap_selinfo.si_note); TAILQ_REMOVE(&audit_pipe_list, ap, ap_list); @@ -758,7 +759,8 @@ audit_pipe_ioctl(struct cdev *dev, u_lon AUDIT_PIPE_LOCK(ap); if (TAILQ_FIRST(&ap->ap_queue) != NULL) *(int *)data = - TAILQ_FIRST(&ap->ap_queue)->ape_record_len; + TAILQ_FIRST(&ap->ap_queue)->ape_record_len - + TAILQ_FIRST(&ap->ap_queue)->ape_record_offset; else *(int *)data = 0; AUDIT_PIPE_UNLOCK(ap); @@ -892,9 +894,12 @@ audit_pipe_ioctl(struct cdev *dev, u_lon break; case AUDITPIPE_FLUSH: + if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) + return (EINTR); AUDIT_PIPE_LOCK(ap); audit_pipe_flush(ap); AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_SX_XUNLOCK(ap); error = 0; break; @@ -949,45 +954,68 @@ audit_pipe_read(struct cdev *dev, struct { struct audit_pipe_entry *ape; struct audit_pipe *ap; + u_int toread; int error; ap = dev->si_drv1; KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL")); + /* + * We hold an sx(9) lock over read and flush because we rely on the + * stability of a record in the queue during uiomove(9). + */ + if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) + return (EINTR); AUDIT_PIPE_LOCK(ap); - do { - /* - * Wait for a record that fits into the read buffer, dropping - * records that would be truncated if actually passed to the - * process. This helps maintain the discreet record read - * interface. - */ - while ((ape = audit_pipe_pop(ap)) == NULL) { - if (ap->ap_flags & AUDIT_PIPE_NBIO) { - AUDIT_PIPE_UNLOCK(ap); - return (EAGAIN); - } - error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); - if (error) { - AUDIT_PIPE_UNLOCK(ap); - return (error); - } + while (TAILQ_EMPTY(&ap->ap_queue)) { + if (ap->ap_flags & AUDIT_PIPE_NBIO) { + AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_SX_XUNLOCK(ap); + return (EAGAIN); } - if (ape->ape_record_len <= uio->uio_resid) - break; - audit_pipe_entry_free(ape); - ap->ap_truncates++; - } while (1); + error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap)); + if (error) { + AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_SX_XUNLOCK(ap); + return (error); + } + } + + /* + * Copy as many remaining bytes from the current record to userspace + * as we can. + * + * Note: we rely on the SX lock to maintain ape's stability here. + */ ap->ap_reads++; + ape = TAILQ_FIRST(&ap->ap_queue); + toread = MIN(ape->ape_record_len - ape->ape_record_offset, + uio->uio_resid); AUDIT_PIPE_UNLOCK(ap); + error = uiomove((char *)ape->ape_record + ape->ape_record_offset, + toread, uio); + if (error) { + AUDIT_PIPE_SX_XUNLOCK(ap); + return (error); + } /* - * Now read record to user space memory. Even if the read is short, - * we abandon the remainder of the record, supporting only discreet - * record reads. + * If the copy succeeded, update book-keeping, and if no bytes remain + * in the current record, free it. */ - error = uiomove(ape->ape_record, ape->ape_record_len, uio); - audit_pipe_entry_free(ape); + AUDIT_PIPE_LOCK(ap); + KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, + ("audit_pipe_read: queue out of sync after uiomove")); + ape->ape_record_offset += toread; + if (ape->ape_record_offset == ape->ape_record_len) { + TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); + ap->ap_qlen--; + } else + ape = NULL; + AUDIT_PIPE_UNLOCK(ap); + AUDIT_PIPE_SX_XUNLOCK(ap); + if (ape != NULL) + audit_pipe_entry_free(ape); return (error); } @@ -1056,7 +1084,7 @@ audit_pipe_kqread(struct knote *kn, long ape = TAILQ_FIRST(&ap->ap_queue); KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); - kn->kn_data = ape->ape_record_len; + kn->kn_data = ape->ape_record_len - ape->ape_record_offset; return (1); } else { kn->kn_data = 0; From rwatson at FreeBSD.org Wed Feb 25 04:22:30 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 04:22:47 2009 Subject: svn commit: r189029 - stable/7/sys/net In-Reply-To: <200902251118.n1PBIIcQ094668@svn.freebsd.org> References: <200902251118.n1PBIIcQ094668@svn.freebsd.org> Message-ID: On Wed, 25 Feb 2009, Robert Watson wrote: > Author: rwatson > Date: Wed Feb 25 11:18:18 2009 > New Revision: 189029 > URL: http://svn.freebsd.org/changeset/base/189029 > > Log: > Correct a deadlock and a rtentry leak in rt_check(): > > - In the event that a gateway route has to be looked up, drop the lock > on 'rt' before reacquiring it 'rt0' in order to avoid deadlock. > > - In the event the original route has evaporated or is no longer up > after the gateway route lookup, call RTFREE() on the gateway route > before retrying. > > This is a potential errata candidate patch. Just to clarify preemptively: rt_check() isn't present in 8.x due to the link layer routing rewrite, so this was committed directly to 7.x. Robert N M Watson Computer Laboratory University of Cambridge > > PR: kern/130652 > Submitted by: Dmitrij Tejblum > Reviewed by: bz > Tested by: Pete French > > Modified: > stable/7/sys/net/route.c > > Modified: stable/7/sys/net/route.c > ============================================================================== > --- stable/7/sys/net/route.c Wed Feb 25 11:13:13 2009 (r189028) > +++ stable/7/sys/net/route.c Wed Feb 25 11:18:18 2009 (r189029) > @@ -1650,27 +1650,34 @@ retry: > return (ENETUNREACH); > } > /* > - * Relock it and lose the added reference. > - * All sorts of things could have happenned while we > - * had no lock on it, so check for them. > + * Relock it and lose the added reference. All sorts > + * of things could have happenned while we had no > + * lock on it, so check for them. rt need to be > + * unlocked to avoid possible deadlock. > */ > + RT_UNLOCK(rt); > RT_RELOCK(rt0); > - if (rt0 == NULL || ((rt0->rt_flags & RTF_UP) == 0)) > + if (rt0 == NULL || ((rt0->rt_flags & RTF_UP) == 0)) { > /* Ru-roh.. what we had is no longer any good */ > + RTFREE(rt); > goto retry; > + } > /* > * While we were away, someone replaced the gateway. > * Since a reference count is involved we can't just > * overwrite it. > */ > if (rt0->rt_gwroute) { > - if (rt0->rt_gwroute != rt) { > - RTFREE_LOCKED(rt); > - goto retry; > - } > + if (rt0->rt_gwroute != rt) > + RTFREE(rt); > } else { > rt0->rt_gwroute = rt; > } > + /* > + * Since rt was not locked, we need recheck that > + * it still may be used (e.g. up) > + */ > + goto retry; > } > RT_LOCK_ASSERT(rt); > RT_UNLOCK(rt0); > From rwatson at FreeBSD.org Wed Feb 25 04:32:17 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 04:32:28 2009 Subject: svn commit: r189033 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251232.n1PCWF9O096642@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 12:32:15 2009 New Revision: 189033 URL: http://svn.freebsd.org/changeset/base/189033 Log: Merge 3184510 from head to stable/7: Since there is no longer the opportunity for record truncation, just return 0 if the truncation counter is queried on an audit pipe. Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 12:00:15 2009 (r189032) +++ stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 12:32:15 2009 (r189033) @@ -144,7 +144,6 @@ struct audit_pipe { u_int64_t ap_inserts; /* Records added. */ u_int64_t ap_reads; /* Records read. */ u_int64_t ap_drops; /* Records dropped. */ - u_int64_t ap_truncates; /* Records too long. */ /* * Fields relating to pipe interest: global masks for unmatched @@ -924,7 +923,7 @@ audit_pipe_ioctl(struct cdev *dev, u_lon break; case AUDITPIPE_GET_TRUNCATES: - *(u_int *)data = ap->ap_truncates; + *(u_int *)data = 0; error = 0; break; From rwatson at FreeBSD.org Wed Feb 25 05:17:47 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 05:17:53 2009 Subject: svn commit: r189034 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251317.n1PDHkA3097581@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 13:17:46 2009 New Revision: 189034 URL: http://svn.freebsd.org/changeset/base/189034 Log: Merge r184534 from head to stable/7: Allow a single read(2) system call on an audit pipe to retrieve data from more than one audit record at a time in order to improve efficiency. Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 12:32:15 2009 (r189033) +++ stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:17:46 2009 (r189034) @@ -934,19 +934,8 @@ audit_pipe_ioctl(struct cdev *dev, u_lon } /* - * Audit pipe read. Pull one record off the queue and copy to user space. - * On error, the record is dropped. - * - * Providing more sophisticated behavior, such as partial reads, is tricky - * due to the potential for parallel I/O. If partial read support is - * required, it will require a per-pipe "current record being read" along - * with an offset into that trecord which has already been read. Threads - * performing partial reads will need to allocate per-thread copies of the - * data so that if another thread completes the read of the record, it can be - * freed without adding reference count logic. If this is added, a flag to - * indicate that only atomic record reads are desired would be useful, as if - * different threads are all waiting for records on the pipe, they will want - * independent record reads, which is currently the behavior. + * Audit pipe read. Read one or more partial or complete records to user + * memory. */ static int audit_pipe_read(struct cdev *dev, struct uio *uio, int flag) @@ -982,40 +971,43 @@ audit_pipe_read(struct cdev *dev, struct /* * Copy as many remaining bytes from the current record to userspace - * as we can. + * as we can. Keep processing records until we run out of records in + * the queue, or until the user buffer runs out of space. * * Note: we rely on the SX lock to maintain ape's stability here. */ ap->ap_reads++; - ape = TAILQ_FIRST(&ap->ap_queue); - toread = MIN(ape->ape_record_len - ape->ape_record_offset, - uio->uio_resid); - AUDIT_PIPE_UNLOCK(ap); - error = uiomove((char *)ape->ape_record + ape->ape_record_offset, - toread, uio); - if (error) { - AUDIT_PIPE_SX_XUNLOCK(ap); - return (error); - } + while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL && + uio->uio_resid > 0) { + AUDIT_PIPE_LOCK_ASSERT(ap); - /* - * If the copy succeeded, update book-keeping, and if no bytes remain - * in the current record, free it. - */ - AUDIT_PIPE_LOCK(ap); - KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, - ("audit_pipe_read: queue out of sync after uiomove")); - ape->ape_record_offset += toread; - if (ape->ape_record_offset == ape->ape_record_len) { - TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); - ap->ap_qlen--; - } else - ape = NULL; + toread = MIN(ape->ape_record_len - ape->ape_record_offset, + uio->uio_resid); + AUDIT_PIPE_UNLOCK(ap); + error = uiomove((char *)ape->ape_record + + ape->ape_record_offset, toread, uio); + if (error) { + AUDIT_PIPE_SX_XUNLOCK(ap); + return (error); + } + + /* + * If the copy succeeded, update book-keeping, and if no + * bytes remain in the current record, free it. + */ + AUDIT_PIPE_LOCK(ap); + KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, + ("audit_pipe_read: queue out of sync after uiomove")); + ape->ape_record_offset += toread; + if (ape->ape_record_offset == ape->ape_record_len) { + TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); + audit_pipe_entry_free(ape); + ap->ap_qlen--; + } + } AUDIT_PIPE_UNLOCK(ap); AUDIT_PIPE_SX_XUNLOCK(ap); - if (ape != NULL) - audit_pipe_entry_free(ape); - return (error); + return (0); } /* From rwatson at FreeBSD.org Wed Feb 25 05:21:30 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 05:21:42 2009 Subject: svn commit: r189035 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251321.n1PDLSNK097763@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 13:21:28 2009 New Revision: 189035 URL: http://svn.freebsd.org/changeset/base/189035 Log: Merge r184536 from head to stable/7: We only allow a partial read of the first record in an audit pipe record queue, so move the offset field from the per-record audit_pipe_entry structure to the audit_pipe structure. Now that we support reading more than one record at a time, add a new summary field to audit_pipe, ap_qbyteslen, which tracks the total number of bytes present in a pipe, and return that (minus the current offset) via FIONREAD and kqueue's data variable for the pending byte count rather than the number of bytes remaining in only the first record. Add a number of asserts to confirm that these counts and offsets following the expected rules. Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:17:46 2009 (r189034) +++ stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:21:28 2009 (r189035) @@ -85,7 +85,6 @@ static MALLOC_DEFINE(M_AUDIT_PIPE_PRESEL struct audit_pipe_entry { void *ape_record; u_int ape_record_len; - u_int ape_record_offset; TAILQ_ENTRY(audit_pipe_entry) ape_queue; }; @@ -138,8 +137,17 @@ struct audit_pipe { */ struct cv ap_cv; + /* + * Various queue-reated variables: qlen and qlimit are a count of + * records in the queue; qbyteslen is the number of bytes of data + * across all records, and qoffset is the amount read so far of the + * first record in the queue. The number of bytes available for + * reading in the queue is qbyteslen - qoffset. + */ u_int ap_qlen; u_int ap_qlimit; + u_int ap_qbyteslen; + u_int ap_qoffset; u_int64_t ap_inserts; /* Records added. */ u_int64_t ap_reads; /* Records read. */ @@ -478,11 +486,11 @@ audit_pipe_append(struct audit_pipe *ap, bcopy(record, ape->ape_record, record_len); ape->ape_record_len = record_len; - ape->ape_record_offset = 0; TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue); ap->ap_inserts++; ap->ap_qlen++; + ap->ap_qbyteslen += ape->ape_record_len; selwakeuppri(&ap->ap_selinfo, PSOCK); KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0); if (ap->ap_flags & AUDIT_PIPE_ASYNC) @@ -607,10 +615,14 @@ audit_pipe_flush(struct audit_pipe *ap) while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) { TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); + ap->ap_qbyteslen -= ape->ape_record_len; audit_pipe_entry_free(ape); ap->ap_qlen--; } - KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen")); + ap->ap_qoffset = 0; + + KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qbyteslen")); + KASSERT(ap->ap_qbyteslen == 0, ("audit_pipe_flush: ap_qbyteslen")); } /* @@ -756,12 +768,7 @@ audit_pipe_ioctl(struct cdev *dev, u_lon case FIONREAD: AUDIT_PIPE_LOCK(ap); - if (TAILQ_FIRST(&ap->ap_queue) != NULL) - *(int *)data = - TAILQ_FIRST(&ap->ap_queue)->ape_record_len - - TAILQ_FIRST(&ap->ap_queue)->ape_record_offset; - else - *(int *)data = 0; + *(int *)data = ap->ap_qbyteslen - ap->ap_qoffset; AUDIT_PIPE_UNLOCK(ap); error = 0; break; @@ -981,11 +988,13 @@ audit_pipe_read(struct cdev *dev, struct uio->uio_resid > 0) { AUDIT_PIPE_LOCK_ASSERT(ap); - toread = MIN(ape->ape_record_len - ape->ape_record_offset, + KASSERT(ape->ape_record_len > ap->ap_qoffset, + ("audit_pipe_read: record_len > qoffset (1)")); + toread = MIN(ape->ape_record_len - ap->ap_qoffset, uio->uio_resid); AUDIT_PIPE_UNLOCK(ap); - error = uiomove((char *)ape->ape_record + - ape->ape_record_offset, toread, uio); + error = uiomove((char *)ape->ape_record + ap->ap_qoffset, + toread, uio); if (error) { AUDIT_PIPE_SX_XUNLOCK(ap); return (error); @@ -998,11 +1007,15 @@ audit_pipe_read(struct cdev *dev, struct AUDIT_PIPE_LOCK(ap); KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape, ("audit_pipe_read: queue out of sync after uiomove")); - ape->ape_record_offset += toread; - if (ape->ape_record_offset == ape->ape_record_len) { + ap->ap_qoffset += toread; + KASSERT(ape->ape_record_len >= ap->ap_qoffset, + ("audit_pipe_read: record_len >= qoffset (2)")); + if (ap->ap_qoffset == ape->ape_record_len) { TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue); + ap->ap_qbyteslen -= ape->ape_record_len; audit_pipe_entry_free(ape); ap->ap_qlen--; + ap->ap_qoffset = 0; } } AUDIT_PIPE_UNLOCK(ap); @@ -1075,7 +1088,7 @@ audit_pipe_kqread(struct knote *kn, long ape = TAILQ_FIRST(&ap->ap_queue); KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); - kn->kn_data = ape->ape_record_len - ape->ape_record_offset; + kn->kn_data = ap->ap_qbyteslen - ap->ap_qoffset; return (1); } else { kn->kn_data = 0; From rwatson at FreeBSD.org Wed Feb 25 05:26:31 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 05:26:47 2009 Subject: svn commit: r189036 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251326.n1PDQUO2097928@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 13:26:30 2009 New Revision: 189036 URL: http://svn.freebsd.org/changeset/base/189036 Log: Merge r184540 from head to stable/7: Add comment for per-pipe stats. Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:21:28 2009 (r189035) +++ stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:26:30 2009 (r189036) @@ -149,6 +149,9 @@ struct audit_pipe { u_int ap_qbyteslen; u_int ap_qoffset; + /* + * Per-pipe operation statistics. + */ u_int64_t ap_inserts; /* Records added. */ u_int64_t ap_reads; /* Records read. */ u_int64_t ap_drops; /* Records dropped. */ From rwatson at FreeBSD.org Wed Feb 25 05:30:18 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 05:30:24 2009 Subject: svn commit: r189037 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251330.n1PDUH3P098086@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 13:30:17 2009 New Revision: 189037 URL: http://svn.freebsd.org/changeset/base/189037 Log: Merge r184544 and r184545 from head to stable/7: Remove stale comment about filtering in audit pipe ioctl routine: we do support filtering now, although we may want to make it more interesting in the future. Update introductory comment for audit pipes. Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:26:30 2009 (r189036) +++ stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:30:17 2009 (r189037) @@ -57,10 +57,10 @@ __FBSDID("$FreeBSD$"); /* * Implementation of a clonable special device providing a live stream of BSM - * audit data. This is a "tee" of the data going to the file. It provides - * unreliable but timely access to audit events. Consumers of this interface - * should be very careful to avoid introducing event cycles. Consumers may - * express interest via a set of preselection ioctls. + * audit data. Consumers receive a "tee" of the system audit trail by + * default, but may also define alternative event selections using ioctls. + * This interface provides unreliable but timely access to audit events. + * Consumers should be very careful to avoid introducing event cycles. */ /* @@ -736,9 +736,6 @@ audit_pipe_close(struct cdev *dev, int f /* * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer * commands. - * - * Would be desirable to support filtering, although perhaps something simple - * like an event mask, as opposed to something complicated like BPF. */ static int audit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, From rwatson at FreeBSD.org Wed Feb 25 05:42:39 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 05:42:51 2009 Subject: svn commit: r189038 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251342.n1PDgcdd098367@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 13:42:38 2009 New Revision: 189038 URL: http://svn.freebsd.org/changeset/base/189038 Log: Merge r184825 from head to stable/7: Wrap sx locking of the audit worker sleep lock in macros, update comments. Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_worker.c Modified: stable/7/sys/security/audit/audit_worker.c ============================================================================== --- stable/7/sys/security/audit/audit_worker.c Wed Feb 25 13:30:17 2009 (r189037) +++ stable/7/sys/security/audit/audit_worker.c Wed Feb 25 13:42:38 2009 (r189038) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1999-2005 Apple Inc. + * Copyright (c) 1999-2008 Apple Inc. * Copyright (c) 2006-2008 Robert N. M. Watson * All rights reserved. * @@ -78,17 +78,24 @@ static struct proc *audit_thread; /* * audit_cred and audit_vp are the stored credential and vnode to use for - * active audit trail. They are protected by audit_worker_sx, which will be - * held across all I/O and all rotation to prevent them from being replaced - * (rotated) while in use. The audit_file_rotate_wait flag is set when the - * kernel has delivered a trigger to auditd to rotate the trail, and is - * cleared when the next rotation takes place. It is also protected by - * audit_worker_sx. + * active audit trail. They are protected by the audit worker lock, which + * will be held across all I/O and all rotation to prevent them from being + * replaced (rotated) while in use. The audit_file_rotate_wait flag is set + * when the kernel has delivered a trigger to auditd to rotate the trail, and + * is cleared when the next rotation takes place. It is also protected by + * the audit worker lock. */ static int audit_file_rotate_wait; -static struct sx audit_worker_sx; static struct ucred *audit_cred; static struct vnode *audit_vp; +static struct sx audit_worker_lock; + +#define AUDIT_WORKER_LOCK_INIT() sx_init(&audit_worker_lock, \ + "audit_worker_lock"); +#define AUDIT_WORKER_LOCK_ASSERT() sx_assert(&audit_worker_lock, \ + SA_XLOCKED) +#define AUDIT_WORKER_LOCK() sx_xlock(&audit_worker_lock) +#define AUDIT_WORKER_UNLOCK() sx_xunlock(&audit_worker_lock) /* * Write an audit record to a file, performed as the last stage after both @@ -111,7 +118,7 @@ audit_record_write(struct vnode *vp, str struct vattr vattr; long temp; - sx_assert(&audit_worker_sx, SA_LOCKED); /* audit_file_rotate_wait. */ + AUDIT_WORKER_LOCK_ASSERT(); if (vp == NULL) return; @@ -191,7 +198,7 @@ audit_record_write(struct vnode *vp, str */ if ((audit_fstat.af_filesz != 0) && (audit_file_rotate_wait == 0) && (vattr.va_size >= audit_fstat.af_filesz)) { - sx_assert(&audit_worker_sx, SA_XLOCKED); + AUDIT_WORKER_LOCK_ASSERT(); audit_file_rotate_wait = 1; (void)audit_send_trigger(AUDIT_TRIGGER_ROTATE_KERNEL); @@ -300,20 +307,20 @@ audit_worker_process_record(struct kaudi au_event_t event; au_id_t auid; int error, sorf; - int trail_locked; + int locked; /* - * We hold the audit_worker_sx lock over both writes, if there are - * two, so that the two records won't be split across a rotation and - * end up in two different trail files. + * We hold the audit worker lock over both writes, if there are two, + * so that the two records won't be split across a rotation and end + * up in two different trail files. */ if (((ar->k_ar_commit & AR_COMMIT_USER) && (ar->k_ar_commit & AR_PRESELECT_USER_TRAIL)) || (ar->k_ar_commit & AR_PRESELECT_TRAIL)) { - sx_xlock(&audit_worker_sx); - trail_locked = 1; + AUDIT_WORKER_LOCK(); + locked = 1; } else - trail_locked = 0; + locked = 0; /* * First, handle the user record, if any: commit to the system trail @@ -321,7 +328,7 @@ audit_worker_process_record(struct kaudi */ if ((ar->k_ar_commit & AR_COMMIT_USER) && (ar->k_ar_commit & AR_PRESELECT_USER_TRAIL)) { - sx_assert(&audit_worker_sx, SA_XLOCKED); + AUDIT_WORKER_LOCK_ASSERT(); audit_record_write(audit_vp, audit_cred, ar->k_udata, ar->k_ulen); } @@ -360,7 +367,7 @@ audit_worker_process_record(struct kaudi } if (ar->k_ar_commit & AR_PRESELECT_TRAIL) { - sx_assert(&audit_worker_sx, SA_XLOCKED); + AUDIT_WORKER_LOCK_ASSERT(); audit_record_write(audit_vp, audit_cred, bsm->data, bsm->len); } @@ -371,8 +378,8 @@ audit_worker_process_record(struct kaudi kau_free(bsm); out: - if (trail_locked) - sx_xunlock(&audit_worker_sx); + if (locked) + AUDIT_WORKER_UNLOCK(); } /* @@ -453,14 +460,14 @@ audit_rotate_vnode(struct ucred *cred, s * Rotate the vnode/cred, and clear the rotate flag so that we will * send a rotate trigger if the new file fills. */ - sx_xlock(&audit_worker_sx); + AUDIT_WORKER_LOCK(); old_audit_cred = audit_cred; old_audit_vp = audit_vp; audit_cred = cred; audit_vp = vp; audit_file_rotate_wait = 0; audit_enabled = (audit_vp != NULL); - sx_xunlock(&audit_worker_sx); + AUDIT_WORKER_UNLOCK(); /* * If there was an old vnode/credential, close and free. @@ -479,7 +486,7 @@ audit_worker_init(void) { int error; - sx_init(&audit_worker_sx, "audit_worker_sx"); + AUDIT_WORKER_LOCK_INIT(); error = kthread_create(audit_worker, NULL, &audit_thread, RFHIGHPID, 0, "audit"); if (error) From rwatson at FreeBSD.org Wed Feb 25 05:47:11 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 05:47:17 2009 Subject: svn commit: r189039 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251347.n1PDl9KO098533@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 13:47:09 2009 New Revision: 189039 URL: http://svn.freebsd.org/changeset/base/189039 Log: Merge r188122 from head to stable/7: Eliminate the local variable 'ape' in audit_pipe_kqread(), as it's only used for an assertion that we don't really need anymore. Reported by: Christoph Mallon Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_pipe.c Modified: stable/7/sys/security/audit/audit_pipe.c ============================================================================== --- stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:42:38 2009 (r189038) +++ stable/7/sys/security/audit/audit_pipe.c Wed Feb 25 13:47:09 2009 (r189039) @@ -1076,18 +1076,13 @@ audit_pipe_kqfilter(struct cdev *dev, st static int audit_pipe_kqread(struct knote *kn, long hint) { - struct audit_pipe_entry *ape; struct audit_pipe *ap; ap = (struct audit_pipe *)kn->kn_hook; KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL")); - AUDIT_PIPE_LOCK_ASSERT(ap); if (ap->ap_qlen != 0) { - ape = TAILQ_FIRST(&ap->ap_queue); - KASSERT(ape != NULL, ("audit_pipe_kqread: ape == NULL")); - kn->kn_data = ap->ap_qbyteslen - ap->ap_qoffset; return (1); } else { From rwatson at FreeBSD.org Wed Feb 25 06:08:29 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 06:08:41 2009 Subject: svn commit: r189040 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902251408.n1PE8SsE099031@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 14:08:28 2009 New Revision: 189040 URL: http://svn.freebsd.org/changeset/base/189040 Log: Merge r183689 from head to stable/7: Differentiate pr_usrreqs for stream and datagram UNIX domain sockets, and employ soreceive_dgram for the datagram case. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/uipc_usrreq.c Modified: stable/7/sys/kern/uipc_usrreq.c ============================================================================== --- stable/7/sys/kern/uipc_usrreq.c Wed Feb 25 13:47:09 2009 (r189039) +++ stable/7/sys/kern/uipc_usrreq.c Wed Feb 25 14:08:28 2009 (r189040) @@ -247,20 +247,20 @@ static struct mbuf *unp_addsockcred(stru * Definitions of protocols supported in the LOCAL domain. */ static struct domain localdomain; -static struct pr_usrreqs uipc_usrreqs; +static struct pr_usrreqs uipc_usrreqs_dgram, uipc_usrreqs_stream; static struct protosw localsw[] = { { .pr_type = SOCK_STREAM, .pr_domain = &localdomain, .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS, .pr_ctloutput = &uipc_ctloutput, - .pr_usrreqs = &uipc_usrreqs + .pr_usrreqs = &uipc_usrreqs_stream }, { .pr_type = SOCK_DGRAM, .pr_domain = &localdomain, .pr_flags = PR_ATOMIC|PR_ADDR|PR_RIGHTS, - .pr_usrreqs = &uipc_usrreqs + .pr_usrreqs = &uipc_usrreqs_dgram }, }; @@ -990,7 +990,7 @@ uipc_sockaddr(struct socket *so, struct return (0); } -static struct pr_usrreqs uipc_usrreqs = { +static struct pr_usrreqs uipc_usrreqs_dgram = { .pru_abort = uipc_abort, .pru_accept = uipc_accept, .pru_attach = uipc_attach, @@ -1006,6 +1006,27 @@ static struct pr_usrreqs uipc_usrreqs = .pru_sense = uipc_sense, .pru_shutdown = uipc_shutdown, .pru_sockaddr = uipc_sockaddr, + .pru_soreceive = soreceive_dgram, + .pru_close = uipc_close, +}; + +static struct pr_usrreqs uipc_usrreqs_stream = { + .pru_abort = uipc_abort, + .pru_accept = uipc_accept, + .pru_attach = uipc_attach, + .pru_bind = uipc_bind, + .pru_connect = uipc_connect, + .pru_connect2 = uipc_connect2, + .pru_detach = uipc_detach, + .pru_disconnect = uipc_disconnect, + .pru_listen = uipc_listen, + .pru_peeraddr = uipc_peeraddr, + .pru_rcvd = uipc_rcvd, + .pru_send = uipc_send, + .pru_sense = uipc_sense, + .pru_shutdown = uipc_shutdown, + .pru_sockaddr = uipc_sockaddr, + .pru_soreceive = soreceive_generic, .pru_close = uipc_close, }; From rwatson at FreeBSD.org Wed Feb 25 06:26:19 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 06:26:36 2009 Subject: svn commit: r189041 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902251426.n1PEQG4v099440@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 14:26:16 2009 New Revision: 189041 URL: http://svn.freebsd.org/changeset/base/189041 Log: Merge r188123 from head to stable/7: Remove written-to but never read local variable 'offset' from soreceive_dgram(). Submitted by: Christoph Mallon Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/uipc_socket.c Modified: stable/7/sys/kern/uipc_socket.c ============================================================================== --- stable/7/sys/kern/uipc_socket.c Wed Feb 25 14:08:28 2009 (r189040) +++ stable/7/sys/kern/uipc_socket.c Wed Feb 25 14:26:16 2009 (r189041) @@ -1851,7 +1851,7 @@ soreceive_dgram(struct socket *so, struc struct mbuf **mp0, struct mbuf **controlp, int *flagsp) { struct mbuf *m, *m2; - int flags, len, error, offset; + int flags, len, error; struct protosw *pr = so->so_proto; struct mbuf *nextrecord; @@ -2001,7 +2001,6 @@ soreceive_dgram(struct socket *so, struc } KASSERT(m->m_type == MT_DATA, ("soreceive_dgram: !data")); - offset = 0; while (m != NULL && uio->uio_resid > 0) { len = uio->uio_resid; if (len > m->m_len) From rwatson at FreeBSD.org Wed Feb 25 06:48:14 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 06:48:21 2009 Subject: svn commit: r189042 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netatalk Message-ID: <200902251448.n1PEmD0r099898@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 14:48:13 2009 New Revision: 189042 URL: http://svn.freebsd.org/changeset/base/189042 Log: Merge 3188124 from head to stable/7: Remove local variable 'ddp' from DDP's attach and detach routines; they were used only for assertions, and rather than ifdef'ing them INVARIANTS and using local variables, just directly access so_pcb. Submitted by: Christoph Mallon Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/netatalk/ddp_usrreq.c Modified: stable/7/sys/netatalk/ddp_usrreq.c ============================================================================== --- stable/7/sys/netatalk/ddp_usrreq.c Wed Feb 25 14:26:16 2009 (r189041) +++ stable/7/sys/netatalk/ddp_usrreq.c Wed Feb 25 14:48:13 2009 (r189042) @@ -75,11 +75,9 @@ static struct ifqueue atintrq1, atintrq2 static int ddp_attach(struct socket *so, int proto, struct thread *td) { - struct ddpcb *ddp; int error = 0; - ddp = sotoddpcb(so); - KASSERT(ddp == NULL, ("ddp_attach: ddp != NULL")); + KASSERT(sotoddpcb(so) == NULL, ("ddp_attach: ddp != NULL")); /* * Allocate socket buffer space first so that it's present @@ -175,10 +173,8 @@ ddp_disconnect(struct socket *so) static int ddp_shutdown(struct socket *so) { - struct ddpcb *ddp; - ddp = sotoddpcb(so); - KASSERT(ddp != NULL, ("ddp_shutdown: ddp == NULL")); + KASSERT(sotoddpcb(so) != NULL, ("ddp_shutdown: ddp == NULL")); socantsendmore(so); return (0); From rwatson at FreeBSD.org Wed Feb 25 07:01:28 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 07:01:39 2009 Subject: svn commit: r189043 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb security/audit Message-ID: <200902251501.n1PF1Qcv000386@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 15:01:26 2009 New Revision: 189043 URL: http://svn.freebsd.org/changeset/base/189043 Log: Merge r188312 from head to stable/7: Audit AUE_MAC_EXECVE; currently just the standard AUE_EXECVE arguments and not the label. Obtained from: TrustedBSD Project Sponsored by: Apple, Inc. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/security/audit/audit_bsm.c Modified: stable/7/sys/security/audit/audit_bsm.c ============================================================================== --- stable/7/sys/security/audit/audit_bsm.c Wed Feb 25 14:48:13 2009 (r189042) +++ stable/7/sys/security/audit/audit_bsm.c Wed Feb 25 15:01:26 2009 (r189043) @@ -764,6 +764,7 @@ kaudit_to_bsm(struct kaudit_record *kar, break; case AUE_EXECVE: + case AUE_MAC_EXECVE: if (ARG_IS_VALID(kar, ARG_ARGV)) { tok = au_to_exec_args(ar->ar_arg_argv, ar->ar_arg_argc); From rwatson at FreeBSD.org Wed Feb 25 07:04:32 2009 From: rwatson at FreeBSD.org (Robert Watson) Date: Wed Feb 25 07:04:49 2009 Subject: svn commit: r189044 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern Message-ID: <200902251504.n1PF4UjR000511@svn.freebsd.org> Author: rwatson Date: Wed Feb 25 15:04:30 2009 New Revision: 189044 URL: http://svn.freebsd.org/changeset/base/189044 Log: Merge r188485 from head to stable/7: Modify fdcopy() so that, during fork(2), it won't copy file descriptors from the parent to the child process if they have an operation vector of &badfileops. This narrows a set of races involving system calls that allocate a new file descriptor, potentially block for some extended period, and then return the file descriptor, when invoked by a threaded program that concurrently invokes fork(2). Similar approches are used in both Solaris and Linux, and the wideness of this race was introduced in FreeBSD when we moved to a more optimistic implementation of accept(2) in order to simplify locking. A small race necessarily remains because the fork(2) might occur after the finit() in accept(2) but before the system call has returned, but that appears unavoidable using current APIs. However, this race is vastly narrower. The fix can be validated using the newfileops_on_fork regression test. PR: kern/130348 Reported by: Ivan Shcheklein Reviewed by: jhb, kib Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/kern/kern_descrip.c Modified: stable/7/sys/kern/kern_descrip.c ============================================================================== --- stable/7/sys/kern/kern_descrip.c Wed Feb 25 15:01:26 2009 (r189043) +++ stable/7/sys/kern/kern_descrip.c Wed Feb 25 15:04:30 2009 (r189044) @@ -1613,7 +1613,8 @@ fdcopy(struct filedesc *fdp) newfdp->fd_freefile = -1; for (i = 0; i <= fdp->fd_lastfile; ++i) { if (fdisused(fdp, i) && - fdp->fd_ofiles[i]->f_type != DTYPE_KQUEUE) { + fdp->fd_ofiles[i]->f_type != DTYPE_KQUEUE && + fdp->fd_ofiles[i]->f_ops != &badfileops) { newfdp->fd_ofiles[i] = fdp->fd_ofiles[i]; newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i]; fhold(newfdp->fd_ofiles[i]); From gallatin at cs.duke.edu Wed Feb 25 08:29:45 2009 From: gallatin at cs.duke.edu (Andrew Gallatin) Date: Wed Feb 25 08:30:02 2009 Subject: svn commit: r189044 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern In-Reply-To: <200902251504.n1PF4UjR000511@svn.freebsd.org> References: <200902251504.n1PF4UjR000511@svn.freebsd.org> Message-ID: <49A571BE.4060107@cs.duke.edu> Just picking a commit at random, but is there any way to clean up the props on pf, ath and cxgb: > stable/7/sys/contrib/pf/ (props changed) > stable/7/sys/dev/ath/ath_hal/ (props changed) > stable/7/sys/dev/cxgb/ (props changed) > stable/7/sys/kern/kern_descrip.c Or at the very least, have the email script ignore them? Having this props change garbage always in the $SUBJECT of MFCs makes it very hard to distinguish from the commit message what part of the tree is actually changing. Thanks, Drew From jhb at freebsd.org Wed Feb 25 08:42:57 2009 From: jhb at freebsd.org (John Baldwin) Date: Wed Feb 25 08:43:14 2009 Subject: svn commit: r189044 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern In-Reply-To: <49A571BE.4060107@cs.duke.edu> References: <200902251504.n1PF4UjR000511@svn.freebsd.org> <49A571BE.4060107@cs.duke.edu> Message-ID: <200902251142.38334.jhb@freebsd.org> On Wednesday 25 February 2009 11:28:46 am Andrew Gallatin wrote: > Just picking a commit at random, but is there any way > to clean up the props on pf, ath and cxgb: > > > stable/7/sys/contrib/pf/ (props changed) > > stable/7/sys/dev/ath/ath_hal/ (props changed) > > stable/7/sys/dev/cxgb/ (props changed) > > stable/7/sys/kern/kern_descrip.c > > Or at the very least, have the email script ignore them? > > Having this props change garbage always in the $SUBJECT of > MFCs makes it very hard to distinguish from the commit > message what part of the tree is actually changing. In theory the mail script is just a python script in svnadmin so we can change it. I know several folks miss the subject lines from CVS that had all the filenames (so you could easily search for commit e-mails to a file by searching subjects in a mail client like kmail), and excluding paths that only have property changes at the same time would probably be good. -- John Baldwin From bz at FreeBSD.org Wed Feb 25 09:22:23 2009 From: bz at FreeBSD.org (Bjoern A. Zeeb) Date: Wed Feb 25 09:22:34 2009 Subject: svn commit: r189044 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern In-Reply-To: <200902251142.38334.jhb@freebsd.org> References: <200902251504.n1PF4UjR000511@svn.freebsd.org> <49A571BE.4060107@cs.duke.edu> <200902251142.38334.jhb@freebsd.org> Message-ID: <20090225170115.R53478@maildrop.int.zabbadoz.net> On Wed, 25 Feb 2009, John Baldwin wrote: > On Wednesday 25 February 2009 11:28:46 am Andrew Gallatin wrote: >> Just picking a commit at random, but is there any way >> to clean up the props on pf, ath and cxgb: >> >>> stable/7/sys/contrib/pf/ (props changed) >>> stable/7/sys/dev/ath/ath_hal/ (props changed) >>> stable/7/sys/dev/cxgb/ (props changed) >>> stable/7/sys/kern/kern_descrip.c >> >> Or at the very least, have the email script ignore them? >> >> Having this props change garbage always in the $SUBJECT of >> MFCs makes it very hard to distinguish from the commit >> message what part of the tree is actually changing. > > In theory the mail script is just a python script in svnadmin so we can change > it. I know several folks miss the subject lines from CVS that had all the > filenames (so you could easily search for commit e-mails to a file by > searching subjects in a mail client like kmail), and excluding paths that > only have property changes at the same time would probably be good. I think there are two points here: 1) the svn interface; I remember peter mumbling something about old we use and new one. Maybe that was for something else. 2) the script itself seems very readable but it made me run away last time I tried to look at this. If you like python and have a svn test installation with the freebsd setup it's probably fixable; we could at least sort the prop-only changes to the end of the subject. I think we might need to keep them for the time when people do svn merge --record-only as that ends to be a prop-only change as well. -- Bjoern A. Zeeb The greatest risk is not taking one. From emaste at FreeBSD.org Wed Feb 25 12:56:28 2009 From: emaste at FreeBSD.org (Ed Maste) Date: Wed Feb 25 12:56:39 2009 Subject: svn commit: r189056 - stable/7/lib/libthread_db Message-ID: <200902252056.n1PKuRhk007807@svn.freebsd.org> Author: emaste Date: Wed Feb 25 20:56:27 2009 New Revision: 189056 URL: http://svn.freebsd.org/changeset/base/189056 Log: MFC r177490 - diff reduction w/ head. Use linker set to collection all target operations. Modified: stable/7/lib/libthread_db/ (props changed) stable/7/lib/libthread_db/libc_r_db.c stable/7/lib/libthread_db/libpthread_db.c stable/7/lib/libthread_db/libthr_db.c stable/7/lib/libthread_db/thread_db.c Modified: stable/7/lib/libthread_db/libc_r_db.c ============================================================================== --- stable/7/lib/libthread_db/libc_r_db.c Wed Feb 25 20:26:48 2009 (r189055) +++ stable/7/lib/libthread_db/libc_r_db.c Wed Feb 25 20:56:27 2009 (r189056) @@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -346,3 +347,5 @@ struct ta_ops libc_r_db_ops = { .to_thr_setxmmregs = libc_r_db_thr_setxmmregs, #endif }; + +DATA_SET(__ta_ops, libc_r_db_ops); Modified: stable/7/lib/libthread_db/libpthread_db.c ============================================================================== --- stable/7/lib/libthread_db/libpthread_db.c Wed Feb 25 20:26:48 2009 (r189055) +++ stable/7/lib/libthread_db/libpthread_db.c Wed Feb 25 20:56:27 2009 (r189056) @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1147,3 +1148,5 @@ struct ta_ops libpthread_db_ops = { .to_thr_setxmmregs = pt_thr_setxmmregs, #endif }; + +DATA_SET(__ta_ops, libpthread_db_ops); Modified: stable/7/lib/libthread_db/libthr_db.c ============================================================================== --- stable/7/lib/libthread_db/libthr_db.c Wed Feb 25 20:26:48 2009 (r189055) +++ stable/7/lib/libthread_db/libthr_db.c Wed Feb 25 20:56:27 2009 (r189056) @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -791,3 +792,5 @@ struct ta_ops libthr_db_ops = { .to_thr_setxmmregs = pt_thr_setxmmregs, #endif }; + +DATA_SET(__ta_ops, libthr_db_ops); Modified: stable/7/lib/libthread_db/thread_db.c ============================================================================== --- stable/7/lib/libthread_db/thread_db.c Wed Feb 25 20:26:48 2009 (r189055) +++ stable/7/lib/libthread_db/thread_db.c Wed Feb 25 20:56:27 2009 (r189056) @@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include "thread_db_int.h" @@ -41,24 +43,20 @@ struct td_thragent static TAILQ_HEAD(, td_thragent) proclist = TAILQ_HEAD_INITIALIZER(proclist); -extern struct ta_ops libpthread_db_ops; -extern struct ta_ops libthr_db_ops; - -static struct ta_ops *ops[] = { - &libpthread_db_ops, - &libthr_db_ops, -}; +SET_DECLARE(__ta_ops, struct ta_ops); td_err_e td_init(void) { td_err_e ret, tmp; + struct ta_ops *ops_p, **ops_pp; size_t i; ret = 0; - for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { - if (ops[i]->to_init != NULL) { - tmp = ops[i]->to_init(); + SET_FOREACH(ops_pp, __ta_ops) { + ops_p = *ops_pp; + if (ops_p->to_init != NULL) { + tmp = ops_p->to_init(); if (tmp != TD_OK) ret = tmp; } @@ -107,11 +105,13 @@ td_err_e td_ta_new(struct ps_prochandle *ph, td_thragent_t **pta) { size_t i; + struct ta_ops *ops_p, **ops_pp; - for (i = 0; i < sizeof(ops)/sizeof(ops[0]); ++i) { - if (ops[i]->to_ta_new(ph, pta) == TD_OK) { + SET_FOREACH(ops_pp, __ta_ops) { + ops_p = *ops_pp; + if (ops_p->to_ta_new(ph, pta) == TD_OK) { TAILQ_INSERT_HEAD(&proclist, *pta, ta_next); - (*pta)->ta_ops = ops[i]; + (*pta)->ta_ops = ops_p; return (TD_OK); } } From jhb at FreeBSD.org Thu Feb 26 07:59:23 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 26 07:59:31 2009 Subject: svn commit: r189075 - in stable/7: lib/libc lib/libc/string lib/libc/sys share/man/man9 sys sys/amd64/amd64 sys/amd64/include sys/arm/arm sys/arm/include sys/conf sys/contrib/pf sys/dev/ath/ath_hal... Message-ID: <200902261559.n1QFxMwT031876@svn.freebsd.org> Author: jhb Date: Thu Feb 26 15:59:22 2009 New Revision: 189075 URL: http://svn.freebsd.org/changeset/base/189075 Log: MFC: Add support for "superpages" on amd64 and i386. This includes adding the superpage reservation system to the machine-independent VM system as well as changes to the pmap code for amd64 and i386 to support superpages. Reviewed by: alc Tested by: ps Added: stable/7/sys/vm/vm_reserv.c - copied, changed from r174982, head/sys/vm/vm_reserv.c stable/7/sys/vm/vm_reserv.h - copied, changed from r174982, head/sys/vm/vm_reserv.h Deleted: stable/7/sys/vm/vm_pageq.c Modified: stable/7/lib/libc/ (props changed) stable/7/lib/libc/string/ffsll.c (props changed) stable/7/lib/libc/string/flsll.c (props changed) stable/7/lib/libc/sys/mincore.2 stable/7/share/man/man9/ (props changed) stable/7/share/man/man9/vm_map_find.9 stable/7/sys/ (props changed) stable/7/sys/amd64/amd64/pmap.c stable/7/sys/amd64/include/pmap.h stable/7/sys/amd64/include/vmparam.h stable/7/sys/arm/arm/pmap.c stable/7/sys/arm/include/vmparam.h stable/7/sys/conf/files stable/7/sys/conf/options stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/i386/i386/pmap.c stable/7/sys/i386/include/pmap.h stable/7/sys/i386/include/vmparam.h stable/7/sys/ia64/ia64/pmap.c stable/7/sys/ia64/include/vmparam.h stable/7/sys/kern/kern_exec.c stable/7/sys/kern/kern_malloc.c stable/7/sys/powerpc/include/vmparam.h stable/7/sys/powerpc/powerpc/pmap_dispatch.c stable/7/sys/sparc64/include/vmparam.h stable/7/sys/sparc64/sparc64/pmap.c stable/7/sys/sun4v/include/vmparam.h stable/7/sys/sun4v/sun4v/pmap.c stable/7/sys/sys/mman.h stable/7/sys/vm/device_pager.c stable/7/sys/vm/memguard.c stable/7/sys/vm/pmap.h stable/7/sys/vm/vm.h stable/7/sys/vm/vm_extern.h stable/7/sys/vm/vm_fault.c stable/7/sys/vm/vm_init.c stable/7/sys/vm/vm_kern.c stable/7/sys/vm/vm_map.c stable/7/sys/vm/vm_map.h stable/7/sys/vm/vm_mmap.c stable/7/sys/vm/vm_object.c stable/7/sys/vm/vm_object.h stable/7/sys/vm/vm_page.c stable/7/sys/vm/vm_page.h stable/7/sys/vm/vm_pageout.c stable/7/sys/vm/vm_phys.c stable/7/sys/vm/vm_phys.h stable/7/sys/vm/vnode_pager.c Modified: stable/7/lib/libc/sys/mincore.2 ============================================================================== --- stable/7/lib/libc/sys/mincore.2 Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/lib/libc/sys/mincore.2 Thu Feb 26 15:59:22 2009 (r189075) @@ -72,6 +72,8 @@ Page has been modified by us. Page has been referenced. .It Dv MINCORE_MODIFIED_OTHER Page has been modified. +.It Dv MINCORE_SUPER +Page is part of a "super" page. (only i386 & amd64) .El .Pp The information returned by Modified: stable/7/share/man/man9/vm_map_find.9 ============================================================================== --- stable/7/share/man/man9/vm_map_find.9 Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/share/man/man9/vm_map_find.9 Thu Feb 26 15:59:22 2009 (r189075) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 19, 2003 +.Dd May 10, 2008 .Dt VM_MAP_FIND 9 .Os .Sh NAME @@ -38,7 +38,7 @@ .Ft int .Fo vm_map_find .Fa "vm_map_t map" "vm_object_t object" "vm_ooffset_t offset" -.Fa "vm_offset_t *addr" "vm_size_t length" "boolean_t find_space" +.Fa "vm_offset_t *addr" "vm_size_t length" "int find_space" .Fa "vm_prot_t prot" "vm_prot_t max" "int cow" .Fc .Sh DESCRIPTION @@ -70,11 +70,25 @@ by the caller before calling this functi .Pp If .Fa find_space -is -.Dv TRUE , +is either +.Dv VMFS_ALIGNED_SPACE +or +.Dv VMFS_ANY_SPACE , the function will call .Xr vm_map_findspace 9 to discover a free region. +Moreover, if +.Fa find_space +is +.Dv VMFS_ALIGNED_SPACE , +the address of the free region will be optimized for the use of superpages. +Otherwise, if +.Fa find_space +is +.Dv VMFS_NO_SPACE , +.Xr vm_map_insert 9 +is called with the given address, +.Fa addr . .Sh IMPLEMENTATION NOTES This function acquires a lock on .Fa map @@ -90,9 +104,14 @@ The .Fn vm_map_find function returns .Dv KERN_SUCCESS -if space for the mapping could be found and -the mapping was successfully created. -If space could not be found in the map, +if the mapping was successfully created. +If space could not be found or +.Fa find_space +was +.Dv VMFS_NO_SPACE +and the given address, +.Fa addr , +was already mapped, .Dv KERN_NO_SPACE will be returned. If the discovered range turned out to be bogus, Modified: stable/7/sys/amd64/amd64/pmap.c ============================================================================== --- stable/7/sys/amd64/amd64/pmap.c Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/sys/amd64/amd64/pmap.c Thu Feb 26 15:59:22 2009 (r189075) @@ -7,7 +7,7 @@ * All rights reserved. * Copyright (c) 2003 Peter Wemm * All rights reserved. - * Copyright (c) 2005 Alan L. Cox + * Copyright (c) 2005-2008 Alan L. Cox * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -107,10 +107,12 @@ __FBSDID("$FreeBSD$"); #include "opt_msgbuf.h" #include "opt_pmap.h" +#include "opt_vm.h" #include #include #include +#include #include #include #include @@ -134,6 +136,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -149,11 +152,7 @@ __FBSDID("$FreeBSD$"); #define PMAP_SHPGPERPROC 200 #endif -#if defined(DIAGNOSTIC) -#define PMAP_DIAGNOSTIC -#endif - -#if !defined(PMAP_DIAGNOSTIC) +#if !defined(DIAGNOSTIC) #define PMAP_INLINE __gnu89_inline #else #define PMAP_INLINE @@ -166,6 +165,9 @@ __FBSDID("$FreeBSD$"); #define PV_STAT(x) do { } while (0) #endif +#define pa_index(pa) ((pa) >> PDRSHIFT) +#define pa_to_pvh(pa) (&pv_table[pa_index(pa)]) + struct pmap kernel_pmap_store; vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ @@ -176,6 +178,12 @@ static vm_paddr_t dmaplimit; vm_offset_t kernel_vm_end = VM_MIN_KERNEL_ADDRESS; pt_entry_t pg_nx; +SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); + +static int pg_ps_enabled; +SYSCTL_INT(_vm_pmap, OID_AUTO, pg_ps_enabled, CTLFLAG_RD, &pg_ps_enabled, 0, + "Are large page mappings enabled?"); + static u_int64_t KPTphys; /* phys addr of kernel level 1 */ static u_int64_t KPDphys; /* phys addr of kernel level 2 */ u_int64_t KPDPphys; /* phys addr of kernel level 3 */ @@ -188,6 +196,7 @@ static u_int64_t DMPDPphys; /* phys addr * Data for the pv entry allocation mechanism */ static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0; +static struct md_page *pv_table; static int shpgperproc = PMAP_SHPGPERPROC; /* @@ -204,11 +213,29 @@ static caddr_t crashdumpmap; static void free_pv_entry(pmap_t pmap, pv_entry_t pv); static pv_entry_t get_pv_entry(pmap_t locked_pmap, int try); - +static void pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static boolean_t pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static void pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); +static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, + vm_offset_t va); + +static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); +static boolean_t pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, + vm_prot_t prot); static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte); +static void pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); +static boolean_t pmap_is_modified_pvh(struct md_page *pvh); +static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va); +static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); +static boolean_t pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, + vm_prot_t prot); +static int pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, + vm_page_t *free); static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t sva, pd_entry_t ptepde, vm_page_t *free); +static void pmap_remove_pt_page(pmap_t pmap, vm_page_t mpte); static void pmap_remove_page(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, vm_page_t *free); static void pmap_remove_entry(struct pmap *pmap, vm_page_t m, @@ -362,21 +389,6 @@ pmap_pte(pmap_t pmap, vm_offset_t va) } -static __inline pt_entry_t * -pmap_pte_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *ptepde) -{ - pd_entry_t *pde; - - pde = pmap_pde(pmap, va); - if (pde == NULL || (*pde & PG_V) == 0) - return NULL; - *ptepde = *pde; - if ((*pde & PG_PS) != 0) /* compat with i386 pmap_pte() */ - return ((pt_entry_t *)pde); - return (pmap_pde_to_pte(pde, va)); -} - - PMAP_INLINE pt_entry_t * vtopte(vm_offset_t va) { @@ -511,6 +523,7 @@ pmap_bootstrap(vm_paddr_t *firstaddr) */ PMAP_LOCK_INIT(kernel_pmap); kernel_pmap->pm_pml4 = (pdp_entry_t *) (KERNBASE + KPML4phys); + kernel_pmap->pm_root = NULL; kernel_pmap->pm_active = -1; /* don't allow deactivation */ TAILQ_INIT(&kernel_pmap->pm_pvchunk); @@ -609,6 +622,26 @@ pmap_page_init(vm_page_t m) void pmap_init(void) { + pd_entry_t *pd; + vm_page_t mpte; + vm_size_t s; + int i, pv_npg; + + /* + * Initialize the vm page array entries for the kernel pmap's + * page table pages. + */ + pd = pmap_pde(kernel_pmap, VM_MIN_KERNEL_ADDRESS); + for (i = 0; i < NKPT; i++) { + if ((pd[i] & (PG_PS | PG_V)) == (PG_PS | PG_V)) + continue; + mpte = PHYS_TO_VM_PAGE(pd[i] & PG_FRAME); + KASSERT(mpte >= vm_page_array && + mpte < &vm_page_array[vm_page_array_size], + ("pmap_init: page table page is out of range")); + mpte->pindex = pmap_pde_pindex(VM_MIN_KERNEL_ADDRESS) + i; + mpte->phys_addr = pd[i] & PG_FRAME; + } /* * Initialize the address space (zone) for the pv entries. Set a @@ -619,9 +652,28 @@ pmap_init(void) pv_entry_max = shpgperproc * maxproc + cnt.v_page_count; TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max); pv_entry_high_water = 9 * (pv_entry_max / 10); + + /* + * Are large page mappings enabled? + */ + TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled); + + /* + * Calculate the size of the pv head table for superpages. + */ + for (i = 0; phys_avail[i + 1]; i += 2); + pv_npg = round_2mpage(phys_avail[(i - 2) + 1]) / NBPDR; + + /* + * Allocate memory for the pv head table for superpages. + */ + s = (vm_size_t)(pv_npg * sizeof(struct md_page)); + s = round_page(s); + pv_table = (struct md_page *)kmem_alloc(kernel_map, s); + for (i = 0; i < pv_npg; i++) + TAILQ_INIT(&pv_table[i].pv_list); } -SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); static int pmap_pventry_proc(SYSCTL_HANDLER_ARGS) { @@ -652,6 +704,25 @@ pmap_shpgperproc_proc(SYSCTL_HANDLER_ARG SYSCTL_PROC(_vm_pmap, OID_AUTO, shpgperproc, CTLTYPE_INT|CTLFLAG_RW, &shpgperproc, 0, pmap_shpgperproc_proc, "IU", "Page share factor per proc"); +SYSCTL_NODE(_vm_pmap, OID_AUTO, pde, CTLFLAG_RD, 0, + "2MB page mapping counters"); + +static u_long pmap_pde_demotions; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, demotions, CTLFLAG_RD, + &pmap_pde_demotions, 0, "2MB page demotions"); + +static u_long pmap_pde_mappings; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, mappings, CTLFLAG_RD, + &pmap_pde_mappings, 0, "2MB page mappings"); + +static u_long pmap_pde_p_failures; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, p_failures, CTLFLAG_RD, + &pmap_pde_p_failures, 0, "2MB page promotion failures"); + +static u_long pmap_pde_promotions; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, promotions, CTLFLAG_RD, + &pmap_pde_promotions, 0, "2MB page promotions"); + /*************************************************** * Low level helper routines..... @@ -953,17 +1024,25 @@ pmap_extract_and_hold(pmap_t pmap, vm_of vm_paddr_t pmap_kextract(vm_offset_t va) { - pd_entry_t *pde; + pd_entry_t pde; vm_paddr_t pa; if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) { pa = DMAP_TO_PHYS(va); } else { - pde = vtopde(va); - if (*pde & PG_PS) { - pa = (*pde & PG_PS_FRAME) | (va & PDRMASK); + pde = *vtopde(va); + if (pde & PG_PS) { + pa = (pde & PG_PS_FRAME) | (va & PDRMASK); } else { - pa = *vtopte(va); + /* + * Beware of a concurrent promotion that changes the + * PDE at this point! For example, vtopte() must not + * be used to access the PTE because it would use the + * new PDE. It is, however, safe to use the old PDE + * because the page table page is preserved by the + * promotion. + */ + pa = *pmap_pde_to_pte(&pde, va); pa = (pa & PG_FRAME) | (va & PAGE_MASK); } } @@ -1085,8 +1164,105 @@ pmap_free_zero_pages(vm_page_t free) while (free != NULL) { m = free; free = m->right; - vm_page_free_zero(m); + /* Preserve the page's PG_ZERO setting. */ + vm_page_free_toq(m); + } +} + +/* + * Schedule the specified unused page table page to be freed. Specifically, + * add the page to the specified list of pages that will be released to the + * physical memory manager after the TLB has been updated. + */ +static __inline void +pmap_add_delayed_free_list(vm_page_t m, vm_page_t *free, boolean_t set_PG_ZERO) +{ + + if (set_PG_ZERO) + m->flags |= PG_ZERO; + else + m->flags &= ~PG_ZERO; + m->right = *free; + *free = m; +} + +/* + * Inserts the specified page table page into the specified pmap's collection + * of idle page table pages. Each of a pmap's page table pages is responsible + * for mapping a distinct range of virtual addresses. The pmap's collection is + * ordered by this virtual address range. + */ +static void +pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte) +{ + vm_page_t root; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + root = pmap->pm_root; + if (root == NULL) { + mpte->left = NULL; + mpte->right = NULL; + } else { + root = vm_page_splay(mpte->pindex, root); + if (mpte->pindex < root->pindex) { + mpte->left = root->left; + mpte->right = root; + root->left = NULL; + } else if (mpte->pindex == root->pindex) + panic("pmap_insert_pt_page: pindex already inserted"); + else { + mpte->right = root->right; + mpte->left = root; + root->right = NULL; + } + } + pmap->pm_root = mpte; +} + +/* + * Looks for a page table page mapping the specified virtual address in the + * specified pmap's collection of idle page table pages. Returns NULL if there + * is no page table page corresponding to the specified virtual address. + */ +static vm_page_t +pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va) +{ + vm_page_t mpte; + vm_pindex_t pindex = pmap_pde_pindex(va); + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if ((mpte = pmap->pm_root) != NULL && mpte->pindex != pindex) { + mpte = vm_page_splay(pindex, mpte); + if ((pmap->pm_root = mpte)->pindex != pindex) + mpte = NULL; } + return (mpte); +} + +/* + * Removes the specified page table page from the specified pmap's collection + * of idle page table pages. The specified page table page must be a member of + * the pmap's collection. + */ +static void +pmap_remove_pt_page(pmap_t pmap, vm_page_t mpte) +{ + vm_page_t root; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if (mpte != pmap->pm_root) { + root = vm_page_splay(mpte->pindex, pmap->pm_root); + KASSERT(mpte == root, + ("pmap_remove_pt_page: mpte %p is missing from pmap %p", + mpte, pmap)); + } + if (mpte->left == NULL) + root = mpte->right; + else { + root = vm_page_splay(mpte->pindex, mpte->left); + root->right = mpte->right; + } + pmap->pm_root = root; } /* @@ -1165,8 +1341,7 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_of * Put page on a list so that it is released after * *ALL* TLB shootdown is done */ - m->right = *free; - *free = m; + pmap_add_delayed_free_list(m, free, TRUE); return 1; } @@ -1193,6 +1368,7 @@ pmap_pinit0(pmap_t pmap) PMAP_LOCK_INIT(pmap); pmap->pm_pml4 = (pml4_entry_t *)(KERNBASE + KPML4phys); + pmap->pm_root = NULL; pmap->pm_active = 0; TAILQ_INIT(&pmap->pm_pvchunk); bzero(&pmap->pm_stats, sizeof pmap->pm_stats); @@ -1229,6 +1405,7 @@ pmap_pinit(pmap_t pmap) /* install self-referential address mapping entry(s) */ pmap->pm_pml4[PML4PML4I] = VM_PAGE_TO_PHYS(pml4pg) | PG_V | PG_RW | PG_A | PG_M; + pmap->pm_root = NULL; pmap->pm_active = 0; TAILQ_INIT(&pmap->pm_pvchunk); bzero(&pmap->pm_stats, sizeof pmap->pm_stats); @@ -1404,7 +1581,7 @@ pmap_allocpte(pmap_t pmap, vm_offset_t v { vm_pindex_t ptepindex; pd_entry_t *pd; - vm_page_t m, free; + vm_page_t m; KASSERT((flags & (M_NOWAIT | M_WAITOK)) == M_NOWAIT || (flags & (M_NOWAIT | M_WAITOK)) == M_WAITOK, @@ -1424,21 +1601,21 @@ retry: * This supports switching from a 2MB page to a * normal 4K page. */ - if (pd != 0 && (*pd & (PG_PS | PG_V)) == (PG_PS | PG_V)) { - *pd = 0; - pd = 0; - pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; - free = NULL; - pmap_unuse_pt(pmap, va, *pmap_pdpe(pmap, va), &free); - pmap_invalidate_all(kernel_pmap); - pmap_free_zero_pages(free); + if (pd != NULL && (*pd & (PG_PS | PG_V)) == (PG_PS | PG_V)) { + if (!pmap_demote_pde(pmap, pd, va)) { + /* + * Invalidation of the 2MB page mapping may have caused + * the deallocation of the underlying PD page. + */ + pd = NULL; + } } /* * If the page table page is mapped, we just increment the * hold count, and activate it. */ - if (pd != 0 && (*pd & PG_V) != 0) { + if (pd != NULL && (*pd & PG_V) != 0) { m = PHYS_TO_VM_PAGE(*pd & PG_FRAME); m->wire_count++; } else { @@ -1471,6 +1648,8 @@ pmap_release(pmap_t pmap) KASSERT(pmap->pm_stats.resident_count == 0, ("pmap_release: pmap resident count %ld != 0", pmap->pm_stats.resident_count)); + KASSERT(pmap->pm_root == NULL, + ("pmap_release: pmap has reserved page table page(s)")); m = PHYS_TO_VM_PAGE(pmap->pm_pml4[PML4PML4I] & PG_FRAME); @@ -1645,11 +1824,16 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pmap_coll * drastic measures to free some pages so we can allocate * another pv entry chunk. This is normally called to * unmap inactive pages, and if necessary, active pages. + * + * We do not, however, unmap 2mpages because subsequent accesses will + * allocate per-page pv entries until repromotion occurs, thereby + * exacerbating the shortage of free pv entries. */ static void pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq) { - pd_entry_t ptepde; + struct md_page *pvh; + pd_entry_t *pde; pmap_t pmap; pt_entry_t *pte, tpte; pv_entry_t next_pv, pv; @@ -1668,28 +1852,27 @@ pmap_collect(pmap_t locked_pmap, struct else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) continue; pmap->pm_stats.resident_count--; - pte = pmap_pte_pde(pmap, va, &ptepde); - if (pte == NULL) { - panic("null pte in pmap_collect"); - } + pde = pmap_pde(pmap, va); + KASSERT((*pde & PG_PS) == 0, ("pmap_collect: found" + " a 2mpage in page %p's pv list", m)); + pte = pmap_pde_to_pte(pde, va); tpte = pte_load_clear(pte); KASSERT((tpte & PG_W) == 0, ("pmap_collect: wired pte %#lx", tpte)); if (tpte & PG_A) vm_page_flag_set(m, PG_REFERENCED); - if (tpte & PG_M) { - KASSERT((tpte & PG_RW), - ("pmap_collect: modified page not writable: va: %#lx, pte: %#lx", - va, tpte)); + if ((tpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) vm_page_dirty(m); - } free = NULL; - pmap_unuse_pt(pmap, va, ptepde, &free); + pmap_unuse_pt(pmap, va, *pde, &free); pmap_invalidate_page(pmap, va); pmap_free_zero_pages(free); TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (TAILQ_EMPTY(&m->md.pv_list)) - vm_page_flag_clear(m, PG_WRITEABLE); + if (TAILQ_EMPTY(&m->md.pv_list)) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + if (TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } free_pv_entry(pmap, pv); if (pmap != locked_pmap) PMAP_UNLOCK(pmap); @@ -1824,24 +2007,133 @@ retry: return (pv); } -static void -pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va) +/* + * First find and then remove the pv entry for the specified pmap and virtual + * address from the specified pv list. Returns the pv entry if found and NULL + * otherwise. This operation can be performed on pv lists for either 4KB or + * 2MB page mappings. + */ +static __inline pv_entry_t +pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va) { pv_entry_t pv; - PMAP_LOCK_ASSERT(pmap, MA_OWNED); mtx_assert(&vm_page_queue_mtx, MA_OWNED); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { - if (pmap == PV_PMAP(pv) && va == pv->pv_va) + TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { + if (pmap == PV_PMAP(pv) && va == pv->pv_va) { + TAILQ_REMOVE(&pvh->pv_list, pv, pv_list); break; + } } - KASSERT(pv != NULL, ("pmap_remove_entry: pv not found")); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (TAILQ_EMPTY(&m->md.pv_list)) - vm_page_flag_clear(m, PG_WRITEABLE); + return (pv); +} + +/* + * After demotion from a 2MB page mapping to 512 4KB page mappings, + * destroy the pv entry for the 2MB page mapping and reinstantiate the pv + * entries for each of the 4KB page mappings. + */ +static void +pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + vm_offset_t va_last; + vm_page_t m; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + KASSERT((pa & PDRMASK) == 0, + ("pmap_pv_demote_pde: pa is not 2mpage aligned")); + + /* + * Transfer the 2mpage's pv entry for this mapping to the first + * page's pv list. + */ + pvh = pa_to_pvh(pa); + va = trunc_2mpage(va); + pv = pmap_pvh_remove(pvh, pmap, va); + KASSERT(pv != NULL, ("pmap_pv_demote_pde: pv not found")); + m = PHYS_TO_VM_PAGE(pa); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); + /* Instantiate the remaining NPTEPG - 1 pv entries. */ + va_last = va + NBPDR - PAGE_SIZE; + do { + m++; + KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0, + ("pmap_pv_demote_pde: page %p is not managed", m)); + va += PAGE_SIZE; + pmap_insert_entry(pmap, va, m); + } while (va < va_last); +} + +/* + * After promotion from 512 4KB page mappings to a single 2MB page mapping, + * replace the many pv entries for the 4KB page mappings by a single pv entry + * for the 2MB page mapping. + */ +static void +pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + vm_offset_t va_last; + vm_page_t m; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + KASSERT((pa & PDRMASK) == 0, + ("pmap_pv_promote_pde: pa is not 2mpage aligned")); + + /* + * Transfer the first page's pv entry for this mapping to the + * 2mpage's pv list. Aside from avoiding the cost of a call + * to get_pv_entry(), a transfer avoids the possibility that + * get_pv_entry() calls pmap_collect() and that pmap_collect() + * removes one of the mappings that is being promoted. + */ + m = PHYS_TO_VM_PAGE(pa); + va = trunc_2mpage(va); + pv = pmap_pvh_remove(&m->md, pmap, va); + KASSERT(pv != NULL, ("pmap_pv_promote_pde: pv not found")); + pvh = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list); + /* Free the remaining NPTEPG - 1 pv entries. */ + va_last = va + NBPDR - PAGE_SIZE; + do { + m++; + va += PAGE_SIZE; + pmap_pvh_free(&m->md, pmap, va); + } while (va < va_last); +} + +/* + * First find and then destroy the pv entry for the specified pmap and virtual + * address. This operation can be performed on pv lists for either 4KB or 2MB + * page mappings. + */ +static void +pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va) +{ + pv_entry_t pv; + + pv = pmap_pvh_remove(pvh, pmap, va); + KASSERT(pv != NULL, ("pmap_pvh_free: pv not found")); free_pv_entry(pmap, pv); } +static void +pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va) +{ + struct md_page *pvh; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + pmap_pvh_free(&m->md, pmap, va); + if (TAILQ_EMPTY(&m->md.pv_list)) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + if (TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } +} + /* * Create a pv entry for page at pa for * (pmap, va). @@ -1878,6 +2170,170 @@ pmap_try_insert_pv_entry(pmap_t pmap, vm } /* + * Create the pv entry for a 2MB page mapping. + */ +static boolean_t +pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + if (pv_entry_count < pv_entry_high_water && + (pv = get_pv_entry(pmap, TRUE)) != NULL) { + pv->pv_va = va; + pvh = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list); + return (TRUE); + } else + return (FALSE); +} + +/* + * Tries to demote a 2MB page mapping. + */ +static boolean_t +pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) +{ + pd_entry_t newpde, oldpde; + pt_entry_t *firstpte, newpte, *pte; + vm_paddr_t mptepa; + vm_page_t free, mpte; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + mpte = pmap_lookup_pt_page(pmap, va); + if (mpte != NULL) + pmap_remove_pt_page(pmap, mpte); + else { + KASSERT((*pde & PG_W) == 0, + ("pmap_demote_pde: page table page for a wired mapping" + " is missing")); + free = NULL; + pmap_remove_pde(pmap, pde, trunc_2mpage(va), &free); + pmap_invalidate_page(pmap, trunc_2mpage(va)); + pmap_free_zero_pages(free); + CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#lx" + " in pmap %p", va, pmap); + return (FALSE); + } + mptepa = VM_PAGE_TO_PHYS(mpte); + firstpte = (pt_entry_t *)PHYS_TO_DMAP(mptepa); + oldpde = *pde; + newpde = mptepa | PG_M | PG_A | (oldpde & PG_U) | PG_RW | PG_V; + KASSERT((oldpde & (PG_A | PG_V)) == (PG_A | PG_V), + ("pmap_demote_pde: oldpde is missing PG_A and/or PG_V")); + KASSERT((oldpde & (PG_M | PG_RW)) != PG_RW, + ("pmap_demote_pde: oldpde is missing PG_M")); + KASSERT((oldpde & PG_PS) != 0, + ("pmap_demote_pde: oldpde is missing PG_PS")); + newpte = oldpde & ~PG_PS; + if ((newpte & PG_PDE_PAT) != 0) + newpte ^= PG_PDE_PAT | PG_PTE_PAT; + + /* + * If the mapping has changed attributes, update the page table + * entries. + */ + KASSERT((*firstpte & PG_FRAME) == (newpte & PG_FRAME), + ("pmap_demote_pde: firstpte and newpte map different physical" + " addresses")); + if ((*firstpte & PG_PTE_PROMOTE) != (newpte & PG_PTE_PROMOTE)) + for (pte = firstpte; pte < firstpte + NPTEPG; pte++) { + *pte = newpte; + newpte += PAGE_SIZE; + } + + /* + * Demote the mapping. This pmap is locked. The old PDE has + * PG_A set. If the old PDE has PG_RW set, it also has PG_M + * set. Thus, there is no danger of a race with another + * processor changing the setting of PG_A and/or PG_M between + * the read above and the store below. + */ + pde_store(pde, newpde); + + /* + * Invalidate a stale mapping of the page table page. + */ + pmap_invalidate_page(pmap, (vm_offset_t)vtopte(va)); + + /* + * Demote the pv entry. This depends on the earlier demotion + * of the mapping. Specifically, the (re)creation of a per- + * page pv entry might trigger the execution of pmap_collect(), + * which might reclaim a newly (re)created per-page pv entry + * and destroy the associated mapping. In order to destroy + * the mapping, the PDE must have already changed from mapping + * the 2mpage to referencing the page table page. + */ + if ((oldpde & PG_MANAGED) != 0) + pmap_pv_demote_pde(pmap, va, oldpde & PG_PS_FRAME); + + pmap_pde_demotions++; + CTR2(KTR_PMAP, "pmap_demote_pde: success for va %#lx" + " in pmap %p", va, pmap); + return (TRUE); +} + +/* + * pmap_remove_pde: do the things to unmap a superpage in a process + */ +static int +pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, + vm_page_t *free) +{ + struct md_page *pvh; + pd_entry_t oldpde; + vm_offset_t eva, va; + vm_page_t m, mpte; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT((sva & PDRMASK) == 0, + ("pmap_remove_pde: sva is not 2mpage aligned")); + oldpde = pte_load_clear(pdq); + if (oldpde & PG_W) + pmap->pm_stats.wired_count -= NBPDR / PAGE_SIZE; + + /* + * Machines that don't support invlpg, also don't support + * PG_G. + */ + if (oldpde & PG_G) + pmap_invalidate_page(kernel_pmap, sva); + pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; + if (oldpde & PG_MANAGED) { + pvh = pa_to_pvh(oldpde & PG_PS_FRAME); + pmap_pvh_free(pvh, pmap, sva); + eva = sva + NBPDR; + for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME); + va < eva; va += PAGE_SIZE, m++) { + if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW)) + vm_page_dirty(m); + if (oldpde & PG_A) + vm_page_flag_set(m, PG_REFERENCED); + if (TAILQ_EMPTY(&m->md.pv_list) && + TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } + } + if (pmap == kernel_pmap) { + if (!pmap_demote_pde(pmap, pdq, sva)) + panic("pmap_remove_pde: failed demotion"); + } else { + mpte = pmap_lookup_pt_page(pmap, sva); + if (mpte != NULL) { + pmap_remove_pt_page(pmap, mpte); + KASSERT(mpte->wire_count == NPTEPG, + ("pmap_remove_pde: pte page wire count error")); + mpte->wire_count = 0; + pmap_add_delayed_free_list(mpte, free, FALSE); + atomic_subtract_int(&cnt.v_wire_count, 1); + } + } + return (pmap_unuse_pt(pmap, sva, *pmap_pdpe(pmap, sva), free)); +} + +/* * pmap_remove_pte: do the things to unmap a page in a process */ static int @@ -1900,12 +2356,8 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t pmap->pm_stats.resident_count -= 1; if (oldpte & PG_MANAGED) { m = PHYS_TO_VM_PAGE(oldpte & PG_FRAME); - if (oldpte & PG_M) { - KASSERT((oldpte & PG_RW), - ("pmap_remove_pte: modified page not writable: va: %#lx, pte: %#lx", - va, oldpte)); + if ((oldpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) vm_page_dirty(m); - } if (oldpte & PG_A) vm_page_flag_set(m, PG_REFERENCED); pmap_remove_entry(pmap, m, va); @@ -2013,11 +2465,24 @@ pmap_remove(pmap_t pmap, vm_offset_t sva * Check for large page. */ if ((ptpaddr & PG_PS) != 0) { - *pde = 0; - pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; - pmap_unuse_pt(pmap, sva, *pdpe, &free); - anyvalid = 1; - continue; + /* + * Are we removing the entire large page? If not, + * demote the mapping and fall through. + */ + if (sva + NBPDR == va_next && eva >= va_next) { + /* + * The TLB entry for a PG_G mapping is + * invalidated by pmap_remove_pde(). + */ + if ((ptpaddr & PG_G) == 0) + anyvalid = 1; + pmap_remove_pde(pmap, pde, sva, &free); + continue; + } else if (!pmap_demote_pde(pmap, pde, sva)) { + /* The large page mapping was destroyed. */ + continue; + } else + ptpaddr = *pde; } /* @@ -2067,30 +2532,34 @@ out: void pmap_remove_all(vm_page_t m) { + struct md_page *pvh; pv_entry_t pv; pmap_t pmap; pt_entry_t *pte, tpte; - pd_entry_t ptepde; + pd_entry_t *pde; + vm_offset_t va; vm_page_t free; -#if defined(PMAP_DIAGNOSTIC) - /* - * XXX This makes pmap_remove_all() illegal for non-managed pages! - */ - if (m->flags & PG_FICTITIOUS) { - panic("pmap_remove_all: illegal for unmanaged page, va: 0x%lx", - VM_PAGE_TO_PHYS(m)); - } -#endif + KASSERT((m->flags & PG_FICTITIOUS) == 0, + ("pmap_remove_all: page %p is fictitious", m)); mtx_assert(&vm_page_queue_mtx, MA_OWNED); + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) { + va = pv->pv_va; + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pde = pmap_pde(pmap, va); + (void)pmap_demote_pde(pmap, pde, va); + PMAP_UNLOCK(pmap); + } while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pmap->pm_stats.resident_count--; - pte = pmap_pte_pde(pmap, pv->pv_va, &ptepde); - if (pte == NULL) { - panic("null pte in pmap_remove_all"); - } + pde = pmap_pde(pmap, pv->pv_va); + KASSERT((*pde & PG_PS) == 0, ("pmap_remove_all: found" + " a 2mpage in page %p's pv list", m)); + pte = pmap_pde_to_pte(pde, pv->pv_va); tpte = pte_load_clear(pte); if (tpte & PG_W) pmap->pm_stats.wired_count--; @@ -2100,14 +2569,10 @@ pmap_remove_all(vm_page_t m) /* * Update the vm_page_t clean and reference bits. */ - if (tpte & PG_M) { - KASSERT((tpte & PG_RW), - ("pmap_remove_all: modified page not writable: va: %#lx, pte: %#lx", - pv->pv_va, tpte)); + if ((tpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) vm_page_dirty(m); - } free = NULL; - pmap_unuse_pt(pmap, pv->pv_va, ptepde, &free); + pmap_unuse_pt(pmap, pv->pv_va, *pde, &free); pmap_invalidate_page(pmap, pv->pv_va); pmap_free_zero_pages(free); TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); @@ -2118,6 +2583,54 @@ pmap_remove_all(vm_page_t m) } /* + * pmap_protect_pde: do the things to protect a 2mpage in a process + */ +static boolean_t +pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot) *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From peterjeremy at optushome.com.au Thu Feb 26 10:14:15 2009 From: peterjeremy at optushome.com.au (Peter Jeremy) Date: Thu Feb 26 10:14:27 2009 Subject: svn commit: r189044 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern In-Reply-To: <49A571BE.4060107@cs.duke.edu> References: <200902251504.n1PF4UjR000511@svn.freebsd.org> <49A571BE.4060107@cs.duke.edu> Message-ID: <20090226181400.GB3540@server.vk2pj.dyndns.org> On 2009-Feb-25 11:28:46 -0500, Andrew Gallatin wrote: > Just picking a commit at random, but is there any way > to clean up the props on pf, ath and cxgb: > >> stable/7/sys/contrib/pf/ (props changed) >> stable/7/sys/dev/ath/ath_hal/ (props changed) >> stable/7/sys/dev/cxgb/ (props changed) >> stable/7/sys/kern/kern_descrip.c > > Or at the very least, have the email script ignore them? Having virtually every single commit to 7.x report that properties on sys/contrib/pf, sys/dev/ath/ath_hal and sys/dev/cxgb have changed strikes me as a bug somewhere in the SVN repo or configuration. > Having this props change garbage always in the $SUBJECT of > MFCs makes it very hard to distinguish from the commit > message what part of the tree is actually changing. I also miss having the list of affected files in $SUBJECT - that made it easier to scan for commits to files of interest. -- Peter Jeremy -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 196 bytes Desc: not available Url : http://lists.freebsd.org/pipermail/svn-src-stable-7/attachments/20090226/ee5bd423/attachment.pgp From jhb at FreeBSD.org Thu Feb 26 10:46:23 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 26 10:46:30 2009 Subject: svn commit: r189079 - stable/7/usr.sbin/pciconf Message-ID: <200902261846.n1QIkMZp035219@svn.freebsd.org> Author: jhb Date: Thu Feb 26 18:46:22 2009 New Revision: 189079 URL: http://svn.freebsd.org/changeset/base/189079 Log: MFC: Sort getopt options alphabetically. Modified: stable/7/usr.sbin/pciconf/ (props changed) stable/7/usr.sbin/pciconf/pciconf.c Modified: stable/7/usr.sbin/pciconf/pciconf.c ============================================================================== --- stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:01:07 2009 (r189078) +++ stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:46:22 2009 (r189079) @@ -97,16 +97,24 @@ main(int argc, char **argv) listmode = readmode = writemode = attachedmode = caps = verbose = byte = isshort = 0; - while ((c = getopt(argc, argv, "aclrwbhv")) != -1) { + while ((c = getopt(argc, argv, "abchlrwv")) != -1) { switch(c) { case 'a': attachedmode = 1; break; + case 'b': + byte = 1; + break; + case 'c': caps = 1; break; + case 'h': + isshort = 1; + break; + case 'l': listmode = 1; break; @@ -119,14 +127,6 @@ main(int argc, char **argv) writemode = 1; break; - case 'b': - byte = 1; - break; - - case 'h': - isshort = 1; - break; - case 'v': verbose = 1; break; From jhb at FreeBSD.org Thu Feb 26 10:54:26 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 26 10:54:44 2009 Subject: svn commit: r189080 - in stable/7: sys sys/contrib/pf sys/dev/ath/ath_hal sys/dev/cardbus sys/dev/cxgb sys/dev/pci sys/sys usr.sbin/pciconf Message-ID: <200902261854.n1QIsPLP035420@svn.freebsd.org> Author: jhb Date: Thu Feb 26 18:54:24 2009 New Revision: 189080 URL: http://svn.freebsd.org/changeset/base/189080 Log: MFC: Add a new ioctl to fetch details about an individual BAR of a device and add support for displaying BAR details via a new pciconf flag. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cardbus/cardbus.c stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/pci/pci_user.c stable/7/sys/dev/pci/pcireg.h stable/7/sys/sys/pciio.h stable/7/usr.sbin/pciconf/ (props changed) stable/7/usr.sbin/pciconf/pciconf.8 stable/7/usr.sbin/pciconf/pciconf.c Modified: stable/7/sys/dev/cardbus/cardbus.c ============================================================================== --- stable/7/sys/dev/cardbus/cardbus.c Thu Feb 26 18:46:22 2009 (r189079) +++ stable/7/sys/dev/cardbus/cardbus.c Thu Feb 26 18:54:24 2009 (r189080) @@ -145,7 +145,7 @@ cardbus_device_setup_regs(pcicfgregs *cf * Some cards power up with garbage in their BARs. This * code clears all that junk out. */ - for (i = 0; i < PCI_MAX_BAR_0; i++) + for (i = 0; i < PCIR_MAX_BAR_0; i++) pci_write_config(dev, PCIR_BAR(i), 0, 4); cfg->intline = Modified: stable/7/sys/dev/pci/pci_user.c ============================================================================== --- stable/7/sys/dev/pci/pci_user.c Thu Feb 26 18:46:22 2009 (r189079) +++ stable/7/sys/dev/pci/pci_user.c Thu Feb 26 18:54:24 2009 (r189080) @@ -307,7 +307,10 @@ pci_ioctl(struct cdev *dev, u_long cmd, struct pci_conf_io *cio; struct pci_devinfo *dinfo; struct pci_io *io; + struct pci_bar_io *bio; struct pci_match_conf *pattern_buf; + struct resource_list_entry *rle; + uint32_t value; size_t confsz, iolen, pbufsz; int error, ionum, i, num_patterns; #ifdef PRE7_COMPAT @@ -319,11 +322,11 @@ pci_ioctl(struct cdev *dev, u_long cmd, io_old = NULL; pattern_buf_old = NULL; - if (!(flag & FWRITE) && - (cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD)) + if (!(flag & FWRITE) && cmd != PCIOCGETBAR && + cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD) return EPERM; #else - if (!(flag & FWRITE) && cmd != PCIOCGETCONF) + if (!(flag & FWRITE) && cmd != PCIOCGETBAR && cmd != PCIOCGETCONF) return EPERM; #endif @@ -669,6 +672,70 @@ getconfexit: } break; + case PCIOCGETBAR: + bio = (struct pci_bar_io *)data; + + /* + * Assume that the user-level bus number is + * in fact the physical PCI bus number. + */ + pcidev = pci_find_dbsf(bio->pbi_sel.pc_domain, + bio->pbi_sel.pc_bus, bio->pbi_sel.pc_dev, + bio->pbi_sel.pc_func); + if (pcidev == NULL) { + error = ENODEV; + break; + } + dinfo = device_get_ivars(pcidev); + + /* + * Look for a resource list entry matching the requested BAR. + * + * XXX: This will not find BARs that are not initialized, but + * maybe that is ok? + */ + rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, + bio->pbi_reg); + if (rle == NULL) + rle = resource_list_find(&dinfo->resources, + SYS_RES_IOPORT, bio->pbi_reg); + if (rle == NULL || rle->res == NULL) { + error = EINVAL; + break; + } + + /* + * Ok, we have a resource for this BAR. Read the lower + * 32 bits to get any flags. + */ + value = pci_read_config(pcidev, bio->pbi_reg, 4); + if (PCI_BAR_MEM(value)) { + if (rle->type != SYS_RES_MEMORY) { + error = EINVAL; + break; + } + value &= ~PCIM_BAR_MEM_BASE; + } else { + if (rle->type != SYS_RES_IOPORT) { + error = EINVAL; + break; + } + value &= ~PCIM_BAR_IO_BASE; + } + bio->pbi_base = rman_get_start(rle->res) | value; + bio->pbi_length = rman_get_size(rle->res); + + /* + * Check the command register to determine if this BAR + * is enabled. + */ + value = pci_read_config(pcidev, PCIR_COMMAND, 2); + if (rle->type == SYS_RES_MEMORY) + bio->pbi_enabled = (value & PCIM_CMD_MEMEN) != 0; + else + bio->pbi_enabled = (value & PCIM_CMD_PORTEN) != 0; + error = 0; + break; default: error = ENOTTY; break; Modified: stable/7/sys/dev/pci/pcireg.h ============================================================================== --- stable/7/sys/dev/pci/pcireg.h Thu Feb 26 18:46:22 2009 (r189079) +++ stable/7/sys/dev/pci/pcireg.h Thu Feb 26 18:54:24 2009 (r189080) @@ -117,7 +117,7 @@ #define PCIR_BARS 0x10 #define PCIR_BAR(x) (PCIR_BARS + (x) * 4) -#define PCI_MAX_BAR_0 5 /* Number of standard bars */ +#define PCIR_MAX_BAR_0 5 #define PCI_RID2BAR(rid) (((rid) - PCIR_BARS) / 4) #define PCI_BAR_IO(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_IO_SPACE) #define PCI_BAR_MEM(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_MEM_SPACE) @@ -158,6 +158,7 @@ /* config registers for header type 1 (PCI-to-PCI bridge) devices */ +#define PCIR_MAX_BAR_1 1 #define PCIR_SECSTAT_1 0x1e #define PCIR_PRIBUS_1 0x18 @@ -188,6 +189,7 @@ /* config registers for header type 2 (CardBus) devices */ +#define PCIR_MAX_BAR_2 0 #define PCIR_CAP_PTR_2 0x14 #define PCIR_SECSTAT_2 0x16 Modified: stable/7/sys/sys/pciio.h ============================================================================== --- stable/7/sys/sys/pciio.h Thu Feb 26 18:46:22 2009 (r189079) +++ stable/7/sys/sys/pciio.h Thu Feb 26 18:54:24 2009 (r189080) @@ -108,9 +108,18 @@ struct pci_io { u_int32_t pi_data; /* data to write or result of read */ }; +struct pci_bar_io { + struct pcisel pbi_sel; /* device to operate on */ + int pbi_reg; /* starting address of BAR */ + int pbi_enabled; /* decoding enabled */ + uint64_t pbi_base; /* current value of BAR */ + uint64_t pbi_length; /* length of BAR */ +}; + #define PCIOCGETCONF _IOWR('p', 5, struct pci_conf_io) #define PCIOCREAD _IOWR('p', 2, struct pci_io) #define PCIOCWRITE _IOWR('p', 3, struct pci_io) #define PCIOCATTACHED _IOWR('p', 4, struct pci_io) +#define PCIOCGETBAR _IOWR('p', 6, struct pci_bar_io) #endif /* !_SYS_PCIIO_H_ */ Modified: stable/7/usr.sbin/pciconf/pciconf.8 ============================================================================== --- stable/7/usr.sbin/pciconf/pciconf.8 Thu Feb 26 18:46:22 2009 (r189079) +++ stable/7/usr.sbin/pciconf/pciconf.8 Thu Feb 26 18:54:24 2009 (r189080) @@ -33,7 +33,7 @@ .Nd diagnostic utility for the PCI bus .Sh SYNOPSIS .Nm -.Fl l Op Fl cv +.Fl l Op Fl bcv .Nm .Fl a Ar selector .Nm @@ -112,6 +112,32 @@ device, which contains several (similar one chip. .Pp If the +.Fl b +option is supplied, +.Nm +will list any base address registers +.Pq BARs +that are assigned resources for each device. +Each BAR will be enumerated via a line in the following format: +.Bd -literal + bar [10] = type Memory, range 32, base 0xda060000, size 131072, enabled +.Ed +.Pp +The first value after the +.Dq Li bar +prefix in the square brackets is the offset of the BAR in config space in +hexadecimal. +The type of a BAR is one of +.Dq Memory , +.Dq Prefetchable Memory , +or +.Dq I/O Port . +The range indicates the maximum address the BAR decodes. +The base and size indicate the start and length of the BAR's address window, +respectively. +Finally, the last flag indicates if the BAR is enabled or disabled. +.Pp +If the .Fl c option is supplied, .Nm Modified: stable/7/usr.sbin/pciconf/pciconf.c ============================================================================== --- stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:46:22 2009 (r189079) +++ stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:54:24 2009 (r189080) @@ -37,6 +37,7 @@ static const char rcsid[] = #include #include +#include #include #include #include @@ -66,7 +67,8 @@ struct pci_vendor_info TAILQ_HEAD(,pci_vendor_info) pci_vendors; -static void list_devs(int verbose, int caps); +static void list_bars(int fd, struct pci_conf *p); +static void list_devs(int verbose, int bars, int caps); static void list_verbose(struct pci_conf *p); static const char *guess_class(struct pci_conf *p); static const char *guess_subclass(struct pci_conf *p); @@ -81,7 +83,7 @@ static void usage(void) { fprintf(stderr, "%s\n%s\n%s\n%s\n", - "usage: pciconf -l [-cv]", + "usage: pciconf -l [-bcv]", " pciconf -a selector", " pciconf -r [-b | -h] selector addr[:addr2]", " pciconf -w [-b | -h] selector addr value"); @@ -92,10 +94,10 @@ int main(int argc, char **argv) { int c; - int listmode, readmode, writemode, attachedmode, caps, verbose; + int listmode, readmode, writemode, attachedmode, bars, caps, verbose; int byte, isshort; - listmode = readmode = writemode = attachedmode = caps = verbose = byte = isshort = 0; + listmode = readmode = writemode = attachedmode = bars = caps = verbose = byte = isshort = 0; while ((c = getopt(argc, argv, "abchlrwv")) != -1) { switch(c) { @@ -104,6 +106,7 @@ main(int argc, char **argv) break; case 'b': + bars = 1; byte = 1; break; @@ -143,7 +146,7 @@ main(int argc, char **argv) usage(); if (listmode) { - list_devs(verbose, caps); + list_devs(verbose, bars, caps); } else if (attachedmode) { chkattached(argv[optind], byte ? 1 : isshort ? 2 : 4); @@ -161,7 +164,7 @@ main(int argc, char **argv) } static void -list_devs(int verbose, int caps) +list_devs(int verbose, int bars, int caps) { int fd; struct pci_conf_io pc; @@ -217,6 +220,8 @@ list_devs(int verbose, int caps) p->pc_revid, p->pc_hdr); if (verbose) list_verbose(p); + if (bars) + list_bars(fd, p); if (caps) list_caps(fd, p); } @@ -226,6 +231,64 @@ list_devs(int verbose, int caps) } static void +list_bars(int fd, struct pci_conf *p) +{ + struct pci_bar_io bar; + uint64_t base; + const char *type; + int i, range, max; + + switch (p->pc_hdr & PCIM_HDRTYPE) { + case PCIM_HDRTYPE_NORMAL: + max = PCIR_MAX_BAR_0; + break; + case PCIM_HDRTYPE_BRIDGE: + max = PCIR_MAX_BAR_1; + break; + case PCIM_HDRTYPE_CARDBUS: + max = PCIR_MAX_BAR_2; + break; + default: + return; + } + + for (i = 0; i <= max; i++) { + bar.pbi_sel = p->pc_sel; + bar.pbi_reg = PCIR_BAR(i); + if (ioctl(fd, PCIOCGETBAR, &bar) < 0) + continue; + if (PCI_BAR_IO(bar.pbi_base)) { + type = "I/O Port"; + range = 32; + base = bar.pbi_base & PCIM_BAR_IO_BASE; + } else { + if (bar.pbi_base & PCIM_BAR_MEM_PREFETCH) + type = "Prefetchable Memory"; + else + type = "Memory"; + switch (bar.pbi_base & PCIM_BAR_MEM_TYPE) { + case PCIM_BAR_MEM_32: + range = 32; + break; + case PCIM_BAR_MEM_1MB: + range = 20; + break; + case PCIM_BAR_MEM_64: + range = 64; + break; + default: + range = -1; + } + base = bar.pbi_base & ~((uint64_t)0xf); + } + printf(" bar [%02x] = type %s, range %2d, base %#jx, ", + PCIR_BAR(i), type, range, (uintmax_t)base); + printf("size %2d, %s\n", (int)bar.pbi_length, + bar.pbi_enabled ? "enabled" : "disabled"); + } +} + +static void list_verbose(struct pci_conf *p) { struct pci_vendor_info *vi; From jhb at FreeBSD.org Thu Feb 26 10:55:58 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 26 10:56:10 2009 Subject: svn commit: r189081 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb nfsclient Message-ID: <200902261855.n1QIttgE035518@svn.freebsd.org> Author: jhb Date: Thu Feb 26 18:55:55 2009 New Revision: 189081 URL: http://svn.freebsd.org/changeset/base/189081 Log: MFC: Don't clear the attribute cache of a file when it is closed. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/nfsclient/nfs_vnops.c Modified: stable/7/sys/nfsclient/nfs_vnops.c ============================================================================== --- stable/7/sys/nfsclient/nfs_vnops.c Thu Feb 26 18:54:24 2009 (r189080) +++ stable/7/sys/nfsclient/nfs_vnops.c Thu Feb 26 18:55:55 2009 (r189081) @@ -594,13 +594,6 @@ nfs_close(struct vop_close_args *ap) error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1); mtx_lock(&np->n_mtx); } - /* - * Invalidate the attribute cache in all cases. - * An open is going to fetch fresh attrs any way, other procs - * on this node that have file open will be forced to do an - * otw attr fetch, but this is safe. - */ - np->n_attrstamp = 0; if (np->n_flag & NWRITEERR) { np->n_flag &= ~NWRITEERR; error = np->n_error; From jhb at FreeBSD.org Thu Feb 26 11:37:50 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 26 11:37:56 2009 Subject: svn commit: r189079 - stable/7/usr.sbin/pciconf Message-ID: <200902261846.n1QIkMZp035219@svn.freebsd.org> Author: jhb Date: Thu Feb 26 18:46:22 2009 New Revision: 189079 URL: http://svn.freebsd.org/changeset/base/189079 Log: MFC: Sort getopt options alphabetically. Modified: stable/7/usr.sbin/pciconf/ (props changed) stable/7/usr.sbin/pciconf/pciconf.c Modified: stable/7/usr.sbin/pciconf/pciconf.c ============================================================================== --- stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:01:07 2009 (r189078) +++ stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:46:22 2009 (r189079) @@ -97,16 +97,24 @@ main(int argc, char **argv) listmode = readmode = writemode = attachedmode = caps = verbose = byte = isshort = 0; - while ((c = getopt(argc, argv, "aclrwbhv")) != -1) { + while ((c = getopt(argc, argv, "abchlrwv")) != -1) { switch(c) { case 'a': attachedmode = 1; break; + case 'b': + byte = 1; + break; + case 'c': caps = 1; break; + case 'h': + isshort = 1; + break; + case 'l': listmode = 1; break; @@ -119,14 +127,6 @@ main(int argc, char **argv) writemode = 1; break; - case 'b': - byte = 1; - break; - - case 'h': - isshort = 1; - break; - case 'v': verbose = 1; break; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" From jhb at FreeBSD.org Thu Feb 26 11:38:21 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 26 11:38:38 2009 Subject: svn commit: r189079 - stable/7/usr.sbin/pciconf Message-ID: <200902261846.n1QIkMZp035219@svn.freebsd.org> Author: jhb Date: Thu Feb 26 18:46:22 2009 New Revision: 189079 URL: http://svn.freebsd.org/changeset/base/189079 Log: MFC: Sort getopt options alphabetically. Modified: stable/7/usr.sbin/pciconf/ (props changed) stable/7/usr.sbin/pciconf/pciconf.c Modified: stable/7/usr.sbin/pciconf/pciconf.c ============================================================================== --- stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:01:07 2009 (r189078) +++ stable/7/usr.sbin/pciconf/pciconf.c Thu Feb 26 18:46:22 2009 (r189079) @@ -97,16 +97,24 @@ main(int argc, char **argv) listmode = readmode = writemode = attachedmode = caps = verbose = byte = isshort = 0; - while ((c = getopt(argc, argv, "aclrwbhv")) != -1) { + while ((c = getopt(argc, argv, "abchlrwv")) != -1) { switch(c) { case 'a': attachedmode = 1; break; + case 'b': + byte = 1; + break; + case 'c': caps = 1; break; + case 'h': + isshort = 1; + break; + case 'l': listmode = 1; break; @@ -119,14 +127,6 @@ main(int argc, char **argv) writemode = 1; break; - case 'b': - byte = 1; - break; - - case 'h': - isshort = 1; - break; - case 'v': verbose = 1; break; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" From jhb at FreeBSD.org Thu Feb 26 11:39:34 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 26 11:40:00 2009 Subject: svn commit: r189075 - in stable/7: lib/libc lib/libc/string lib/libc/sys share/man/man9 sys sys/amd64/amd64 sys/amd64/include sys/arm/arm sys/arm/include sys/conf sys/contrib/pf sys/dev/ath/ath_hal... Message-ID: <200902261559.n1QFxMwT031876@svn.freebsd.org> Author: jhb Date: Thu Feb 26 15:59:22 2009 New Revision: 189075 URL: http://svn.freebsd.org/changeset/base/189075 Log: MFC: Add support for "superpages" on amd64 and i386. This includes adding the superpage reservation system to the machine-independent VM system as well as changes to the pmap code for amd64 and i386 to support superpages. Reviewed by: alc Tested by: ps Added: stable/7/sys/vm/vm_reserv.c - copied, changed from r174982, head/sys/vm/vm_reserv.c stable/7/sys/vm/vm_reserv.h - copied, changed from r174982, head/sys/vm/vm_reserv.h Deleted: stable/7/sys/vm/vm_pageq.c Modified: stable/7/lib/libc/ (props changed) stable/7/lib/libc/string/ffsll.c (props changed) stable/7/lib/libc/string/flsll.c (props changed) stable/7/lib/libc/sys/mincore.2 stable/7/share/man/man9/ (props changed) stable/7/share/man/man9/vm_map_find.9 stable/7/sys/ (props changed) stable/7/sys/amd64/amd64/pmap.c stable/7/sys/amd64/include/pmap.h stable/7/sys/amd64/include/vmparam.h stable/7/sys/arm/arm/pmap.c stable/7/sys/arm/include/vmparam.h stable/7/sys/conf/files stable/7/sys/conf/options stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/i386/i386/pmap.c stable/7/sys/i386/include/pmap.h stable/7/sys/i386/include/vmparam.h stable/7/sys/ia64/ia64/pmap.c stable/7/sys/ia64/include/vmparam.h stable/7/sys/kern/kern_exec.c stable/7/sys/kern/kern_malloc.c stable/7/sys/powerpc/include/vmparam.h stable/7/sys/powerpc/powerpc/pmap_dispatch.c stable/7/sys/sparc64/include/vmparam.h stable/7/sys/sparc64/sparc64/pmap.c stable/7/sys/sun4v/include/vmparam.h stable/7/sys/sun4v/sun4v/pmap.c stable/7/sys/sys/mman.h stable/7/sys/vm/device_pager.c stable/7/sys/vm/memguard.c stable/7/sys/vm/pmap.h stable/7/sys/vm/vm.h stable/7/sys/vm/vm_extern.h stable/7/sys/vm/vm_fault.c stable/7/sys/vm/vm_init.c stable/7/sys/vm/vm_kern.c stable/7/sys/vm/vm_map.c stable/7/sys/vm/vm_map.h stable/7/sys/vm/vm_mmap.c stable/7/sys/vm/vm_object.c stable/7/sys/vm/vm_object.h stable/7/sys/vm/vm_page.c stable/7/sys/vm/vm_page.h stable/7/sys/vm/vm_pageout.c stable/7/sys/vm/vm_phys.c stable/7/sys/vm/vm_phys.h stable/7/sys/vm/vnode_pager.c Modified: stable/7/lib/libc/sys/mincore.2 ============================================================================== --- stable/7/lib/libc/sys/mincore.2 Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/lib/libc/sys/mincore.2 Thu Feb 26 15:59:22 2009 (r189075) @@ -72,6 +72,8 @@ Page has been modified by us. Page has been referenced. .It Dv MINCORE_MODIFIED_OTHER Page has been modified. +.It Dv MINCORE_SUPER +Page is part of a "super" page. (only i386 & amd64) .El .Pp The information returned by Modified: stable/7/share/man/man9/vm_map_find.9 ============================================================================== --- stable/7/share/man/man9/vm_map_find.9 Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/share/man/man9/vm_map_find.9 Thu Feb 26 15:59:22 2009 (r189075) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 19, 2003 +.Dd May 10, 2008 .Dt VM_MAP_FIND 9 .Os .Sh NAME @@ -38,7 +38,7 @@ .Ft int .Fo vm_map_find .Fa "vm_map_t map" "vm_object_t object" "vm_ooffset_t offset" -.Fa "vm_offset_t *addr" "vm_size_t length" "boolean_t find_space" +.Fa "vm_offset_t *addr" "vm_size_t length" "int find_space" .Fa "vm_prot_t prot" "vm_prot_t max" "int cow" .Fc .Sh DESCRIPTION @@ -70,11 +70,25 @@ by the caller before calling this functi .Pp If .Fa find_space -is -.Dv TRUE , +is either +.Dv VMFS_ALIGNED_SPACE +or +.Dv VMFS_ANY_SPACE , the function will call .Xr vm_map_findspace 9 to discover a free region. +Moreover, if +.Fa find_space +is +.Dv VMFS_ALIGNED_SPACE , +the address of the free region will be optimized for the use of superpages. +Otherwise, if +.Fa find_space +is +.Dv VMFS_NO_SPACE , +.Xr vm_map_insert 9 +is called with the given address, +.Fa addr . .Sh IMPLEMENTATION NOTES This function acquires a lock on .Fa map @@ -90,9 +104,14 @@ The .Fn vm_map_find function returns .Dv KERN_SUCCESS -if space for the mapping could be found and -the mapping was successfully created. -If space could not be found in the map, +if the mapping was successfully created. +If space could not be found or +.Fa find_space +was +.Dv VMFS_NO_SPACE +and the given address, +.Fa addr , +was already mapped, .Dv KERN_NO_SPACE will be returned. If the discovered range turned out to be bogus, Modified: stable/7/sys/amd64/amd64/pmap.c ============================================================================== --- stable/7/sys/amd64/amd64/pmap.c Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/sys/amd64/amd64/pmap.c Thu Feb 26 15:59:22 2009 (r189075) @@ -7,7 +7,7 @@ * All rights reserved. * Copyright (c) 2003 Peter Wemm * All rights reserved. - * Copyright (c) 2005 Alan L. Cox + * Copyright (c) 2005-2008 Alan L. Cox * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -107,10 +107,12 @@ __FBSDID("$FreeBSD$"); #include "opt_msgbuf.h" #include "opt_pmap.h" +#include "opt_vm.h" #include #include #include +#include #include #include #include @@ -134,6 +136,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -149,11 +152,7 @@ __FBSDID("$FreeBSD$"); #define PMAP_SHPGPERPROC 200 #endif -#if defined(DIAGNOSTIC) -#define PMAP_DIAGNOSTIC -#endif - -#if !defined(PMAP_DIAGNOSTIC) +#if !defined(DIAGNOSTIC) #define PMAP_INLINE __gnu89_inline #else #define PMAP_INLINE @@ -166,6 +165,9 @@ __FBSDID("$FreeBSD$"); #define PV_STAT(x) do { } while (0) #endif +#define pa_index(pa) ((pa) >> PDRSHIFT) +#define pa_to_pvh(pa) (&pv_table[pa_index(pa)]) + struct pmap kernel_pmap_store; vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ @@ -176,6 +178,12 @@ static vm_paddr_t dmaplimit; vm_offset_t kernel_vm_end = VM_MIN_KERNEL_ADDRESS; pt_entry_t pg_nx; +SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); + +static int pg_ps_enabled; +SYSCTL_INT(_vm_pmap, OID_AUTO, pg_ps_enabled, CTLFLAG_RD, &pg_ps_enabled, 0, + "Are large page mappings enabled?"); + static u_int64_t KPTphys; /* phys addr of kernel level 1 */ static u_int64_t KPDphys; /* phys addr of kernel level 2 */ u_int64_t KPDPphys; /* phys addr of kernel level 3 */ @@ -188,6 +196,7 @@ static u_int64_t DMPDPphys; /* phys addr * Data for the pv entry allocation mechanism */ static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0; +static struct md_page *pv_table; static int shpgperproc = PMAP_SHPGPERPROC; /* @@ -204,11 +213,29 @@ static caddr_t crashdumpmap; static void free_pv_entry(pmap_t pmap, pv_entry_t pv); static pv_entry_t get_pv_entry(pmap_t locked_pmap, int try); - +static void pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static boolean_t pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static void pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); +static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, + vm_offset_t va); + +static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); +static boolean_t pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, + vm_prot_t prot); static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte); +static void pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); +static boolean_t pmap_is_modified_pvh(struct md_page *pvh); +static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va); +static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); +static boolean_t pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, + vm_prot_t prot); +static int pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, + vm_page_t *free); static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t sva, pd_entry_t ptepde, vm_page_t *free); +static void pmap_remove_pt_page(pmap_t pmap, vm_page_t mpte); static void pmap_remove_page(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, vm_page_t *free); static void pmap_remove_entry(struct pmap *pmap, vm_page_t m, @@ -362,21 +389,6 @@ pmap_pte(pmap_t pmap, vm_offset_t va) } -static __inline pt_entry_t * -pmap_pte_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *ptepde) -{ - pd_entry_t *pde; - - pde = pmap_pde(pmap, va); - if (pde == NULL || (*pde & PG_V) == 0) - return NULL; - *ptepde = *pde; - if ((*pde & PG_PS) != 0) /* compat with i386 pmap_pte() */ - return ((pt_entry_t *)pde); - return (pmap_pde_to_pte(pde, va)); -} - - PMAP_INLINE pt_entry_t * vtopte(vm_offset_t va) { @@ -511,6 +523,7 @@ pmap_bootstrap(vm_paddr_t *firstaddr) */ PMAP_LOCK_INIT(kernel_pmap); kernel_pmap->pm_pml4 = (pdp_entry_t *) (KERNBASE + KPML4phys); + kernel_pmap->pm_root = NULL; kernel_pmap->pm_active = -1; /* don't allow deactivation */ TAILQ_INIT(&kernel_pmap->pm_pvchunk); @@ -609,6 +622,26 @@ pmap_page_init(vm_page_t m) void pmap_init(void) { + pd_entry_t *pd; + vm_page_t mpte; + vm_size_t s; + int i, pv_npg; + + /* + * Initialize the vm page array entries for the kernel pmap's + * page table pages. + */ + pd = pmap_pde(kernel_pmap, VM_MIN_KERNEL_ADDRESS); + for (i = 0; i < NKPT; i++) { + if ((pd[i] & (PG_PS | PG_V)) == (PG_PS | PG_V)) + continue; + mpte = PHYS_TO_VM_PAGE(pd[i] & PG_FRAME); + KASSERT(mpte >= vm_page_array && + mpte < &vm_page_array[vm_page_array_size], + ("pmap_init: page table page is out of range")); + mpte->pindex = pmap_pde_pindex(VM_MIN_KERNEL_ADDRESS) + i; + mpte->phys_addr = pd[i] & PG_FRAME; + } /* * Initialize the address space (zone) for the pv entries. Set a @@ -619,9 +652,28 @@ pmap_init(void) pv_entry_max = shpgperproc * maxproc + cnt.v_page_count; TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max); pv_entry_high_water = 9 * (pv_entry_max / 10); + + /* + * Are large page mappings enabled? + */ + TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled); + + /* + * Calculate the size of the pv head table for superpages. + */ + for (i = 0; phys_avail[i + 1]; i += 2); + pv_npg = round_2mpage(phys_avail[(i - 2) + 1]) / NBPDR; + + /* + * Allocate memory for the pv head table for superpages. + */ + s = (vm_size_t)(pv_npg * sizeof(struct md_page)); + s = round_page(s); + pv_table = (struct md_page *)kmem_alloc(kernel_map, s); + for (i = 0; i < pv_npg; i++) + TAILQ_INIT(&pv_table[i].pv_list); } -SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); static int pmap_pventry_proc(SYSCTL_HANDLER_ARGS) { @@ -652,6 +704,25 @@ pmap_shpgperproc_proc(SYSCTL_HANDLER_ARG SYSCTL_PROC(_vm_pmap, OID_AUTO, shpgperproc, CTLTYPE_INT|CTLFLAG_RW, &shpgperproc, 0, pmap_shpgperproc_proc, "IU", "Page share factor per proc"); +SYSCTL_NODE(_vm_pmap, OID_AUTO, pde, CTLFLAG_RD, 0, + "2MB page mapping counters"); + +static u_long pmap_pde_demotions; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, demotions, CTLFLAG_RD, + &pmap_pde_demotions, 0, "2MB page demotions"); + +static u_long pmap_pde_mappings; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, mappings, CTLFLAG_RD, + &pmap_pde_mappings, 0, "2MB page mappings"); + +static u_long pmap_pde_p_failures; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, p_failures, CTLFLAG_RD, + &pmap_pde_p_failures, 0, "2MB page promotion failures"); + +static u_long pmap_pde_promotions; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, promotions, CTLFLAG_RD, + &pmap_pde_promotions, 0, "2MB page promotions"); + /*************************************************** * Low level helper routines..... @@ -953,17 +1024,25 @@ pmap_extract_and_hold(pmap_t pmap, vm_of vm_paddr_t pmap_kextract(vm_offset_t va) { - pd_entry_t *pde; + pd_entry_t pde; vm_paddr_t pa; if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) { pa = DMAP_TO_PHYS(va); } else { - pde = vtopde(va); - if (*pde & PG_PS) { - pa = (*pde & PG_PS_FRAME) | (va & PDRMASK); + pde = *vtopde(va); + if (pde & PG_PS) { + pa = (pde & PG_PS_FRAME) | (va & PDRMASK); } else { - pa = *vtopte(va); + /* + * Beware of a concurrent promotion that changes the + * PDE at this point! For example, vtopte() must not + * be used to access the PTE because it would use the + * new PDE. It is, however, safe to use the old PDE + * because the page table page is preserved by the + * promotion. + */ + pa = *pmap_pde_to_pte(&pde, va); pa = (pa & PG_FRAME) | (va & PAGE_MASK); } } @@ -1085,8 +1164,105 @@ pmap_free_zero_pages(vm_page_t free) while (free != NULL) { m = free; free = m->right; - vm_page_free_zero(m); + /* Preserve the page's PG_ZERO setting. */ + vm_page_free_toq(m); + } +} + +/* + * Schedule the specified unused page table page to be freed. Specifically, + * add the page to the specified list of pages that will be released to the + * physical memory manager after the TLB has been updated. + */ +static __inline void +pmap_add_delayed_free_list(vm_page_t m, vm_page_t *free, boolean_t set_PG_ZERO) +{ + + if (set_PG_ZERO) + m->flags |= PG_ZERO; + else + m->flags &= ~PG_ZERO; + m->right = *free; + *free = m; +} + +/* + * Inserts the specified page table page into the specified pmap's collection + * of idle page table pages. Each of a pmap's page table pages is responsible + * for mapping a distinct range of virtual addresses. The pmap's collection is + * ordered by this virtual address range. + */ +static void +pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte) +{ + vm_page_t root; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + root = pmap->pm_root; + if (root == NULL) { + mpte->left = NULL; + mpte->right = NULL; + } else { + root = vm_page_splay(mpte->pindex, root); + if (mpte->pindex < root->pindex) { + mpte->left = root->left; + mpte->right = root; + root->left = NULL; + } else if (mpte->pindex == root->pindex) + panic("pmap_insert_pt_page: pindex already inserted"); + else { + mpte->right = root->right; + mpte->left = root; + root->right = NULL; + } + } + pmap->pm_root = mpte; +} + +/* + * Looks for a page table page mapping the specified virtual address in the + * specified pmap's collection of idle page table pages. Returns NULL if there + * is no page table page corresponding to the specified virtual address. + */ +static vm_page_t +pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va) +{ + vm_page_t mpte; + vm_pindex_t pindex = pmap_pde_pindex(va); + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if ((mpte = pmap->pm_root) != NULL && mpte->pindex != pindex) { + mpte = vm_page_splay(pindex, mpte); + if ((pmap->pm_root = mpte)->pindex != pindex) + mpte = NULL; } + return (mpte); +} + +/* + * Removes the specified page table page from the specified pmap's collection + * of idle page table pages. The specified page table page must be a member of + * the pmap's collection. + */ +static void +pmap_remove_pt_page(pmap_t pmap, vm_page_t mpte) +{ + vm_page_t root; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if (mpte != pmap->pm_root) { + root = vm_page_splay(mpte->pindex, pmap->pm_root); + KASSERT(mpte == root, + ("pmap_remove_pt_page: mpte %p is missing from pmap %p", + mpte, pmap)); + } + if (mpte->left == NULL) + root = mpte->right; + else { + root = vm_page_splay(mpte->pindex, mpte->left); + root->right = mpte->right; + } + pmap->pm_root = root; } /* @@ -1165,8 +1341,7 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_of * Put page on a list so that it is released after * *ALL* TLB shootdown is done */ - m->right = *free; - *free = m; + pmap_add_delayed_free_list(m, free, TRUE); return 1; } @@ -1193,6 +1368,7 @@ pmap_pinit0(pmap_t pmap) PMAP_LOCK_INIT(pmap); pmap->pm_pml4 = (pml4_entry_t *)(KERNBASE + KPML4phys); + pmap->pm_root = NULL; pmap->pm_active = 0; TAILQ_INIT(&pmap->pm_pvchunk); bzero(&pmap->pm_stats, sizeof pmap->pm_stats); @@ -1229,6 +1405,7 @@ pmap_pinit(pmap_t pmap) /* install self-referential address mapping entry(s) */ pmap->pm_pml4[PML4PML4I] = VM_PAGE_TO_PHYS(pml4pg) | PG_V | PG_RW | PG_A | PG_M; + pmap->pm_root = NULL; pmap->pm_active = 0; TAILQ_INIT(&pmap->pm_pvchunk); bzero(&pmap->pm_stats, sizeof pmap->pm_stats); @@ -1404,7 +1581,7 @@ pmap_allocpte(pmap_t pmap, vm_offset_t v { vm_pindex_t ptepindex; pd_entry_t *pd; - vm_page_t m, free; + vm_page_t m; KASSERT((flags & (M_NOWAIT | M_WAITOK)) == M_NOWAIT || (flags & (M_NOWAIT | M_WAITOK)) == M_WAITOK, @@ -1424,21 +1601,21 @@ retry: * This supports switching from a 2MB page to a * normal 4K page. */ - if (pd != 0 && (*pd & (PG_PS | PG_V)) == (PG_PS | PG_V)) { - *pd = 0; - pd = 0; - pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; - free = NULL; - pmap_unuse_pt(pmap, va, *pmap_pdpe(pmap, va), &free); - pmap_invalidate_all(kernel_pmap); - pmap_free_zero_pages(free); + if (pd != NULL && (*pd & (PG_PS | PG_V)) == (PG_PS | PG_V)) { + if (!pmap_demote_pde(pmap, pd, va)) { + /* + * Invalidation of the 2MB page mapping may have caused + * the deallocation of the underlying PD page. + */ + pd = NULL; + } } /* * If the page table page is mapped, we just increment the * hold count, and activate it. */ - if (pd != 0 && (*pd & PG_V) != 0) { + if (pd != NULL && (*pd & PG_V) != 0) { m = PHYS_TO_VM_PAGE(*pd & PG_FRAME); m->wire_count++; } else { @@ -1471,6 +1648,8 @@ pmap_release(pmap_t pmap) KASSERT(pmap->pm_stats.resident_count == 0, ("pmap_release: pmap resident count %ld != 0", pmap->pm_stats.resident_count)); + KASSERT(pmap->pm_root == NULL, + ("pmap_release: pmap has reserved page table page(s)")); m = PHYS_TO_VM_PAGE(pmap->pm_pml4[PML4PML4I] & PG_FRAME); @@ -1645,11 +1824,16 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pmap_coll * drastic measures to free some pages so we can allocate * another pv entry chunk. This is normally called to * unmap inactive pages, and if necessary, active pages. + * + * We do not, however, unmap 2mpages because subsequent accesses will + * allocate per-page pv entries until repromotion occurs, thereby + * exacerbating the shortage of free pv entries. */ static void pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq) { - pd_entry_t ptepde; + struct md_page *pvh; + pd_entry_t *pde; pmap_t pmap; pt_entry_t *pte, tpte; pv_entry_t next_pv, pv; @@ -1668,28 +1852,27 @@ pmap_collect(pmap_t locked_pmap, struct else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) continue; pmap->pm_stats.resident_count--; - pte = pmap_pte_pde(pmap, va, &ptepde); - if (pte == NULL) { - panic("null pte in pmap_collect"); - } + pde = pmap_pde(pmap, va); + KASSERT((*pde & PG_PS) == 0, ("pmap_collect: found" + " a 2mpage in page %p's pv list", m)); + pte = pmap_pde_to_pte(pde, va); tpte = pte_load_clear(pte); KASSERT((tpte & PG_W) == 0, ("pmap_collect: wired pte %#lx", tpte)); if (tpte & PG_A) vm_page_flag_set(m, PG_REFERENCED); - if (tpte & PG_M) { - KASSERT((tpte & PG_RW), - ("pmap_collect: modified page not writable: va: %#lx, pte: %#lx", - va, tpte)); + if ((tpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) vm_page_dirty(m); - } free = NULL; - pmap_unuse_pt(pmap, va, ptepde, &free); + pmap_unuse_pt(pmap, va, *pde, &free); pmap_invalidate_page(pmap, va); pmap_free_zero_pages(free); TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (TAILQ_EMPTY(&m->md.pv_list)) - vm_page_flag_clear(m, PG_WRITEABLE); + if (TAILQ_EMPTY(&m->md.pv_list)) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + if (TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } free_pv_entry(pmap, pv); if (pmap != locked_pmap) PMAP_UNLOCK(pmap); @@ -1824,24 +2007,133 @@ retry: return (pv); } -static void -pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va) +/* + * First find and then remove the pv entry for the specified pmap and virtual + * address from the specified pv list. Returns the pv entry if found and NULL + * otherwise. This operation can be performed on pv lists for either 4KB or + * 2MB page mappings. + */ +static __inline pv_entry_t +pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va) { pv_entry_t pv; - PMAP_LOCK_ASSERT(pmap, MA_OWNED); mtx_assert(&vm_page_queue_mtx, MA_OWNED); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { - if (pmap == PV_PMAP(pv) && va == pv->pv_va) + TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { + if (pmap == PV_PMAP(pv) && va == pv->pv_va) { + TAILQ_REMOVE(&pvh->pv_list, pv, pv_list); break; + } } - KASSERT(pv != NULL, ("pmap_remove_entry: pv not found")); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (TAILQ_EMPTY(&m->md.pv_list)) - vm_page_flag_clear(m, PG_WRITEABLE); + return (pv); +} + +/* + * After demotion from a 2MB page mapping to 512 4KB page mappings, + * destroy the pv entry for the 2MB page mapping and reinstantiate the pv + * entries for each of the 4KB page mappings. + */ +static void +pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + vm_offset_t va_last; + vm_page_t m; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + KASSERT((pa & PDRMASK) == 0, + ("pmap_pv_demote_pde: pa is not 2mpage aligned")); + + /* + * Transfer the 2mpage's pv entry for this mapping to the first + * page's pv list. + */ + pvh = pa_to_pvh(pa); + va = trunc_2mpage(va); + pv = pmap_pvh_remove(pvh, pmap, va); + KASSERT(pv != NULL, ("pmap_pv_demote_pde: pv not found")); + m = PHYS_TO_VM_PAGE(pa); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); + /* Instantiate the remaining NPTEPG - 1 pv entries. */ + va_last = va + NBPDR - PAGE_SIZE; + do { + m++; + KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0, + ("pmap_pv_demote_pde: page %p is not managed", m)); + va += PAGE_SIZE; + pmap_insert_entry(pmap, va, m); + } while (va < va_last); +} + +/* + * After promotion from 512 4KB page mappings to a single 2MB page mapping, + * replace the many pv entries for the 4KB page mappings by a single pv entry + * for the 2MB page mapping. + */ +static void +pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + vm_offset_t va_last; + vm_page_t m; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + KASSERT((pa & PDRMASK) == 0, + ("pmap_pv_promote_pde: pa is not 2mpage aligned")); + + /* + * Transfer the first page's pv entry for this mapping to the + * 2mpage's pv list. Aside from avoiding the cost of a call + * to get_pv_entry(), a transfer avoids the possibility that + * get_pv_entry() calls pmap_collect() and that pmap_collect() + * removes one of the mappings that is being promoted. + */ + m = PHYS_TO_VM_PAGE(pa); + va = trunc_2mpage(va); + pv = pmap_pvh_remove(&m->md, pmap, va); + KASSERT(pv != NULL, ("pmap_pv_promote_pde: pv not found")); + pvh = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list); + /* Free the remaining NPTEPG - 1 pv entries. */ + va_last = va + NBPDR - PAGE_SIZE; + do { + m++; + va += PAGE_SIZE; + pmap_pvh_free(&m->md, pmap, va); + } while (va < va_last); +} + +/* + * First find and then destroy the pv entry for the specified pmap and virtual + * address. This operation can be performed on pv lists for either 4KB or 2MB + * page mappings. + */ +static void +pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va) +{ + pv_entry_t pv; + + pv = pmap_pvh_remove(pvh, pmap, va); + KASSERT(pv != NULL, ("pmap_pvh_free: pv not found")); free_pv_entry(pmap, pv); } +static void +pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va) +{ + struct md_page *pvh; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + pmap_pvh_free(&m->md, pmap, va); + if (TAILQ_EMPTY(&m->md.pv_list)) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + if (TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } +} + /* * Create a pv entry for page at pa for * (pmap, va). @@ -1878,6 +2170,170 @@ pmap_try_insert_pv_entry(pmap_t pmap, vm } /* + * Create the pv entry for a 2MB page mapping. + */ +static boolean_t +pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + if (pv_entry_count < pv_entry_high_water && + (pv = get_pv_entry(pmap, TRUE)) != NULL) { + pv->pv_va = va; + pvh = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list); + return (TRUE); + } else + return (FALSE); +} + +/* + * Tries to demote a 2MB page mapping. + */ +static boolean_t +pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) +{ + pd_entry_t newpde, oldpde; + pt_entry_t *firstpte, newpte, *pte; + vm_paddr_t mptepa; + vm_page_t free, mpte; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + mpte = pmap_lookup_pt_page(pmap, va); + if (mpte != NULL) + pmap_remove_pt_page(pmap, mpte); + else { + KASSERT((*pde & PG_W) == 0, + ("pmap_demote_pde: page table page for a wired mapping" + " is missing")); + free = NULL; + pmap_remove_pde(pmap, pde, trunc_2mpage(va), &free); + pmap_invalidate_page(pmap, trunc_2mpage(va)); + pmap_free_zero_pages(free); + CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#lx" + " in pmap %p", va, pmap); + return (FALSE); + } + mptepa = VM_PAGE_TO_PHYS(mpte); + firstpte = (pt_entry_t *)PHYS_TO_DMAP(mptepa); + oldpde = *pde; + newpde = mptepa | PG_M | PG_A | (oldpde & PG_U) | PG_RW | PG_V; + KASSERT((oldpde & (PG_A | PG_V)) == (PG_A | PG_V), + ("pmap_demote_pde: oldpde is missing PG_A and/or PG_V")); + KASSERT((oldpde & (PG_M | PG_RW)) != PG_RW, + ("pmap_demote_pde: oldpde is missing PG_M")); + KASSERT((oldpde & PG_PS) != 0, + ("pmap_demote_pde: oldpde is missing PG_PS")); + newpte = oldpde & ~PG_PS; + if ((newpte & PG_PDE_PAT) != 0) + newpte ^= PG_PDE_PAT | PG_PTE_PAT; + + /* + * If the mapping has changed attributes, update the page table + * entries. + */ + KASSERT((*firstpte & PG_FRAME) == (newpte & PG_FRAME), + ("pmap_demote_pde: firstpte and newpte map different physical" + " addresses")); + if ((*firstpte & PG_PTE_PROMOTE) != (newpte & PG_PTE_PROMOTE)) + for (pte = firstpte; pte < firstpte + NPTEPG; pte++) { + *pte = newpte; + newpte += PAGE_SIZE; + } + + /* + * Demote the mapping. This pmap is locked. The old PDE has + * PG_A set. If the old PDE has PG_RW set, it also has PG_M + * set. Thus, there is no danger of a race with another + * processor changing the setting of PG_A and/or PG_M between + * the read above and the store below. + */ + pde_store(pde, newpde); + + /* + * Invalidate a stale mapping of the page table page. + */ + pmap_invalidate_page(pmap, (vm_offset_t)vtopte(va)); + + /* + * Demote the pv entry. This depends on the earlier demotion + * of the mapping. Specifically, the (re)creation of a per- + * page pv entry might trigger the execution of pmap_collect(), + * which might reclaim a newly (re)created per-page pv entry + * and destroy the associated mapping. In order to destroy + * the mapping, the PDE must have already changed from mapping + * the 2mpage to referencing the page table page. + */ + if ((oldpde & PG_MANAGED) != 0) + pmap_pv_demote_pde(pmap, va, oldpde & PG_PS_FRAME); + + pmap_pde_demotions++; + CTR2(KTR_PMAP, "pmap_demote_pde: success for va %#lx" + " in pmap %p", va, pmap); + return (TRUE); +} + +/* + * pmap_remove_pde: do the things to unmap a superpage in a process + */ +static int +pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, + vm_page_t *free) +{ + struct md_page *pvh; + pd_entry_t oldpde; + vm_offset_t eva, va; + vm_page_t m, mpte; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT((sva & PDRMASK) == 0, + ("pmap_remove_pde: sva is not 2mpage aligned")); + oldpde = pte_load_clear(pdq); + if (oldpde & PG_W) + pmap->pm_stats.wired_count -= NBPDR / PAGE_SIZE; + + /* + * Machines that don't support invlpg, also don't support + * PG_G. + */ + if (oldpde & PG_G) + pmap_invalidate_page(kernel_pmap, sva); + pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; + if (oldpde & PG_MANAGED) { + pvh = pa_to_pvh(oldpde & PG_PS_FRAME); + pmap_pvh_free(pvh, pmap, sva); + eva = sva + NBPDR; + for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME); + va < eva; va += PAGE_SIZE, m++) { + if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW)) + vm_page_dirty(m); + if (oldpde & PG_A) + vm_page_flag_set(m, PG_REFERENCED); + if (TAILQ_EMPTY(&m->md.pv_list) && + TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } + } + if (pmap == kernel_pmap) { + if (!pmap_demote_pde(pmap, pdq, sva)) + panic("pmap_remove_pde: failed demotion"); + } else { + mpte = pmap_lookup_pt_page(pmap, sva); + if (mpte != NULL) { + pmap_remove_pt_page(pmap, mpte); + KASSERT(mpte->wire_count == NPTEPG, + ("pmap_remove_pde: pte page wire count error")); + mpte->wire_count = 0; + pmap_add_delayed_free_list(mpte, free, FALSE); + atomic_subtract_int(&cnt.v_wire_count, 1); + } + } + return (pmap_unuse_pt(pmap, sva, *pmap_pdpe(pmap, sva), free)); +} + +/* * pmap_remove_pte: do the things to unmap a page in a process */ static int @@ -1900,12 +2356,8 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t pmap->pm_stats.resident_count -= 1; if (oldpte & PG_MANAGED) { m = PHYS_TO_VM_PAGE(oldpte & PG_FRAME); - if (oldpte & PG_M) { - KASSERT((oldpte & PG_RW), - ("pmap_remove_pte: modified page not writable: va: %#lx, pte: %#lx", - va, oldpte)); + if ((oldpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) vm_page_dirty(m); - } if (oldpte & PG_A) vm_page_flag_set(m, PG_REFERENCED); pmap_remove_entry(pmap, m, va); @@ -2013,11 +2465,24 @@ pmap_remove(pmap_t pmap, vm_offset_t sva * Check for large page. */ if ((ptpaddr & PG_PS) != 0) { - *pde = 0; - pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; - pmap_unuse_pt(pmap, sva, *pdpe, &free); - anyvalid = 1; - continue; + /* + * Are we removing the entire large page? If not, + * demote the mapping and fall through. + */ + if (sva + NBPDR == va_next && eva >= va_next) { + /* + * The TLB entry for a PG_G mapping is + * invalidated by pmap_remove_pde(). + */ + if ((ptpaddr & PG_G) == 0) + anyvalid = 1; + pmap_remove_pde(pmap, pde, sva, &free); + continue; + } else if (!pmap_demote_pde(pmap, pde, sva)) { + /* The large page mapping was destroyed. */ + continue; + } else + ptpaddr = *pde; } /* @@ -2067,30 +2532,34 @@ out: void pmap_remove_all(vm_page_t m) { + struct md_page *pvh; pv_entry_t pv; pmap_t pmap; pt_entry_t *pte, tpte; - pd_entry_t ptepde; + pd_entry_t *pde; + vm_offset_t va; vm_page_t free; -#if defined(PMAP_DIAGNOSTIC) - /* - * XXX This makes pmap_remove_all() illegal for non-managed pages! - */ - if (m->flags & PG_FICTITIOUS) { - panic("pmap_remove_all: illegal for unmanaged page, va: 0x%lx", - VM_PAGE_TO_PHYS(m)); - } -#endif + KASSERT((m->flags & PG_FICTITIOUS) == 0, + ("pmap_remove_all: page %p is fictitious", m)); mtx_assert(&vm_page_queue_mtx, MA_OWNED); + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) { + va = pv->pv_va; + pmap = PV_PMAP(pv); + PMAP_LOCK(pmap); + pde = pmap_pde(pmap, va); + (void)pmap_demote_pde(pmap, pde, va); + PMAP_UNLOCK(pmap); + } while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { pmap = PV_PMAP(pv); PMAP_LOCK(pmap); pmap->pm_stats.resident_count--; - pte = pmap_pte_pde(pmap, pv->pv_va, &ptepde); - if (pte == NULL) { - panic("null pte in pmap_remove_all"); - } + pde = pmap_pde(pmap, pv->pv_va); + KASSERT((*pde & PG_PS) == 0, ("pmap_remove_all: found" + " a 2mpage in page %p's pv list", m)); + pte = pmap_pde_to_pte(pde, pv->pv_va); tpte = pte_load_clear(pte); if (tpte & PG_W) pmap->pm_stats.wired_count--; @@ -2100,14 +2569,10 @@ pmap_remove_all(vm_page_t m) /* * Update the vm_page_t clean and reference bits. */ - if (tpte & PG_M) { - KASSERT((tpte & PG_RW), - ("pmap_remove_all: modified page not writable: va: %#lx, pte: %#lx", - pv->pv_va, tpte)); + if ((tpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) vm_page_dirty(m); - } free = NULL; - pmap_unuse_pt(pmap, pv->pv_va, ptepde, &free); + pmap_unuse_pt(pmap, pv->pv_va, *pde, &free); pmap_invalidate_page(pmap, pv->pv_va); pmap_free_zero_pages(free); TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); @@ -2118,6 +2583,54 @@ pmap_remove_all(vm_page_t m) } /* + * pmap_protect_pde: do the things to protect a 2mpage in a process + */ +static boolean_t +pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot) *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" From jhb at FreeBSD.org Thu Feb 26 11:42:06 2009 From: jhb at FreeBSD.org (John Baldwin) Date: Thu Feb 26 11:42:13 2009 Subject: svn commit: r189075 - in stable/7: lib/libc lib/libc/string lib/libc/sys share/man/man9 sys sys/amd64/amd64 sys/amd64/include sys/arm/arm sys/arm/include sys/conf sys/contrib/pf sys/dev/ath/ath_hal... Message-ID: <200902261559.n1QFxMwT031876@svn.freebsd.org> Author: jhb Date: Thu Feb 26 15:59:22 2009 New Revision: 189075 URL: http://svn.freebsd.org/changeset/base/189075 Log: MFC: Add support for "superpages" on amd64 and i386. This includes adding the superpage reservation system to the machine-independent VM system as well as changes to the pmap code for amd64 and i386 to support superpages. Reviewed by: alc Tested by: ps Added: stable/7/sys/vm/vm_reserv.c - copied, changed from r174982, head/sys/vm/vm_reserv.c stable/7/sys/vm/vm_reserv.h - copied, changed from r174982, head/sys/vm/vm_reserv.h Deleted: stable/7/sys/vm/vm_pageq.c Modified: stable/7/lib/libc/ (props changed) stable/7/lib/libc/string/ffsll.c (props changed) stable/7/lib/libc/string/flsll.c (props changed) stable/7/lib/libc/sys/mincore.2 stable/7/share/man/man9/ (props changed) stable/7/share/man/man9/vm_map_find.9 stable/7/sys/ (props changed) stable/7/sys/amd64/amd64/pmap.c stable/7/sys/amd64/include/pmap.h stable/7/sys/amd64/include/vmparam.h stable/7/sys/arm/arm/pmap.c stable/7/sys/arm/include/vmparam.h stable/7/sys/conf/files stable/7/sys/conf/options stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/i386/i386/pmap.c stable/7/sys/i386/include/pmap.h stable/7/sys/i386/include/vmparam.h stable/7/sys/ia64/ia64/pmap.c stable/7/sys/ia64/include/vmparam.h stable/7/sys/kern/kern_exec.c stable/7/sys/kern/kern_malloc.c stable/7/sys/powerpc/include/vmparam.h stable/7/sys/powerpc/powerpc/pmap_dispatch.c stable/7/sys/sparc64/include/vmparam.h stable/7/sys/sparc64/sparc64/pmap.c stable/7/sys/sun4v/include/vmparam.h stable/7/sys/sun4v/sun4v/pmap.c stable/7/sys/sys/mman.h stable/7/sys/vm/device_pager.c stable/7/sys/vm/memguard.c stable/7/sys/vm/pmap.h stable/7/sys/vm/vm.h stable/7/sys/vm/vm_extern.h stable/7/sys/vm/vm_fault.c stable/7/sys/vm/vm_init.c stable/7/sys/vm/vm_kern.c stable/7/sys/vm/vm_map.c stable/7/sys/vm/vm_map.h stable/7/sys/vm/vm_mmap.c stable/7/sys/vm/vm_object.c stable/7/sys/vm/vm_object.h stable/7/sys/vm/vm_page.c stable/7/sys/vm/vm_page.h stable/7/sys/vm/vm_pageout.c stable/7/sys/vm/vm_phys.c stable/7/sys/vm/vm_phys.h stable/7/sys/vm/vnode_pager.c Modified: stable/7/lib/libc/sys/mincore.2 ============================================================================== --- stable/7/lib/libc/sys/mincore.2 Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/lib/libc/sys/mincore.2 Thu Feb 26 15:59:22 2009 (r189075) @@ -72,6 +72,8 @@ Page has been modified by us. Page has been referenced. .It Dv MINCORE_MODIFIED_OTHER Page has been modified. +.It Dv MINCORE_SUPER +Page is part of a "super" page. (only i386 & amd64) .El .Pp The information returned by Modified: stable/7/share/man/man9/vm_map_find.9 ============================================================================== --- stable/7/share/man/man9/vm_map_find.9 Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/share/man/man9/vm_map_find.9 Thu Feb 26 15:59:22 2009 (r189075) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 19, 2003 +.Dd May 10, 2008 .Dt VM_MAP_FIND 9 .Os .Sh NAME @@ -38,7 +38,7 @@ .Ft int .Fo vm_map_find .Fa "vm_map_t map" "vm_object_t object" "vm_ooffset_t offset" -.Fa "vm_offset_t *addr" "vm_size_t length" "boolean_t find_space" +.Fa "vm_offset_t *addr" "vm_size_t length" "int find_space" .Fa "vm_prot_t prot" "vm_prot_t max" "int cow" .Fc .Sh DESCRIPTION @@ -70,11 +70,25 @@ by the caller before calling this functi .Pp If .Fa find_space -is -.Dv TRUE , +is either +.Dv VMFS_ALIGNED_SPACE +or +.Dv VMFS_ANY_SPACE , the function will call .Xr vm_map_findspace 9 to discover a free region. +Moreover, if +.Fa find_space +is +.Dv VMFS_ALIGNED_SPACE , +the address of the free region will be optimized for the use of superpages. +Otherwise, if +.Fa find_space +is +.Dv VMFS_NO_SPACE , +.Xr vm_map_insert 9 +is called with the given address, +.Fa addr . .Sh IMPLEMENTATION NOTES This function acquires a lock on .Fa map @@ -90,9 +104,14 @@ The .Fn vm_map_find function returns .Dv KERN_SUCCESS -if space for the mapping could be found and -the mapping was successfully created. -If space could not be found in the map, +if the mapping was successfully created. +If space could not be found or +.Fa find_space +was +.Dv VMFS_NO_SPACE +and the given address, +.Fa addr , +was already mapped, .Dv KERN_NO_SPACE will be returned. If the discovered range turned out to be bogus, Modified: stable/7/sys/amd64/amd64/pmap.c ============================================================================== --- stable/7/sys/amd64/amd64/pmap.c Thu Feb 26 15:51:54 2009 (r189074) +++ stable/7/sys/amd64/amd64/pmap.c Thu Feb 26 15:59:22 2009 (r189075) @@ -7,7 +7,7 @@ * All rights reserved. * Copyright (c) 2003 Peter Wemm * All rights reserved. - * Copyright (c) 2005 Alan L. Cox + * Copyright (c) 2005-2008 Alan L. Cox * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -107,10 +107,12 @@ __FBSDID("$FreeBSD$"); #include "opt_msgbuf.h" #include "opt_pmap.h" +#include "opt_vm.h" #include #include #include +#include #include #include #include @@ -134,6 +136,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -149,11 +152,7 @@ __FBSDID("$FreeBSD$"); #define PMAP_SHPGPERPROC 200 #endif -#if defined(DIAGNOSTIC) -#define PMAP_DIAGNOSTIC -#endif - -#if !defined(PMAP_DIAGNOSTIC) +#if !defined(DIAGNOSTIC) #define PMAP_INLINE __gnu89_inline #else #define PMAP_INLINE @@ -166,6 +165,9 @@ __FBSDID("$FreeBSD$"); #define PV_STAT(x) do { } while (0) #endif +#define pa_index(pa) ((pa) >> PDRSHIFT) +#define pa_to_pvh(pa) (&pv_table[pa_index(pa)]) + struct pmap kernel_pmap_store; vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ @@ -176,6 +178,12 @@ static vm_paddr_t dmaplimit; vm_offset_t kernel_vm_end = VM_MIN_KERNEL_ADDRESS; pt_entry_t pg_nx; +SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); + +static int pg_ps_enabled; +SYSCTL_INT(_vm_pmap, OID_AUTO, pg_ps_enabled, CTLFLAG_RD, &pg_ps_enabled, 0, + "Are large page mappings enabled?"); + static u_int64_t KPTphys; /* phys addr of kernel level 1 */ static u_int64_t KPDphys; /* phys addr of kernel level 2 */ u_int64_t KPDPphys; /* phys addr of kernel level 3 */ @@ -188,6 +196,7 @@ static u_int64_t DMPDPphys; /* phys addr * Data for the pv entry allocation mechanism */ static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0; +static struct md_page *pv_table; static int shpgperproc = PMAP_SHPGPERPROC; /* @@ -204,11 +213,29 @@ static caddr_t crashdumpmap; static void free_pv_entry(pmap_t pmap, pv_entry_t pv); static pv_entry_t get_pv_entry(pmap_t locked_pmap, int try); - +static void pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static boolean_t pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static void pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); +static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); +static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, + vm_offset_t va); + +static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); +static boolean_t pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, + vm_prot_t prot); static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte); +static void pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte); +static boolean_t pmap_is_modified_pvh(struct md_page *pvh); +static vm_page_t pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va); +static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); +static boolean_t pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, + vm_prot_t prot); +static int pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, + vm_page_t *free); static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t sva, pd_entry_t ptepde, vm_page_t *free); +static void pmap_remove_pt_page(pmap_t pmap, vm_page_t mpte); static void pmap_remove_page(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, vm_page_t *free); static void pmap_remove_entry(struct pmap *pmap, vm_page_t m, @@ -362,21 +389,6 @@ pmap_pte(pmap_t pmap, vm_offset_t va) } -static __inline pt_entry_t * -pmap_pte_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *ptepde) -{ - pd_entry_t *pde; - - pde = pmap_pde(pmap, va); - if (pde == NULL || (*pde & PG_V) == 0) - return NULL; - *ptepde = *pde; - if ((*pde & PG_PS) != 0) /* compat with i386 pmap_pte() */ - return ((pt_entry_t *)pde); - return (pmap_pde_to_pte(pde, va)); -} - - PMAP_INLINE pt_entry_t * vtopte(vm_offset_t va) { @@ -511,6 +523,7 @@ pmap_bootstrap(vm_paddr_t *firstaddr) */ PMAP_LOCK_INIT(kernel_pmap); kernel_pmap->pm_pml4 = (pdp_entry_t *) (KERNBASE + KPML4phys); + kernel_pmap->pm_root = NULL; kernel_pmap->pm_active = -1; /* don't allow deactivation */ TAILQ_INIT(&kernel_pmap->pm_pvchunk); @@ -609,6 +622,26 @@ pmap_page_init(vm_page_t m) void pmap_init(void) { + pd_entry_t *pd; + vm_page_t mpte; + vm_size_t s; + int i, pv_npg; + + /* + * Initialize the vm page array entries for the kernel pmap's + * page table pages. + */ + pd = pmap_pde(kernel_pmap, VM_MIN_KERNEL_ADDRESS); + for (i = 0; i < NKPT; i++) { + if ((pd[i] & (PG_PS | PG_V)) == (PG_PS | PG_V)) + continue; + mpte = PHYS_TO_VM_PAGE(pd[i] & PG_FRAME); + KASSERT(mpte >= vm_page_array && + mpte < &vm_page_array[vm_page_array_size], + ("pmap_init: page table page is out of range")); + mpte->pindex = pmap_pde_pindex(VM_MIN_KERNEL_ADDRESS) + i; + mpte->phys_addr = pd[i] & PG_FRAME; + } /* * Initialize the address space (zone) for the pv entries. Set a @@ -619,9 +652,28 @@ pmap_init(void) pv_entry_max = shpgperproc * maxproc + cnt.v_page_count; TUNABLE_INT_FETCH("vm.pmap.pv_entries", &pv_entry_max); pv_entry_high_water = 9 * (pv_entry_max / 10); + + /* + * Are large page mappings enabled? + */ + TUNABLE_INT_FETCH("vm.pmap.pg_ps_enabled", &pg_ps_enabled); + + /* + * Calculate the size of the pv head table for superpages. + */ + for (i = 0; phys_avail[i + 1]; i += 2); + pv_npg = round_2mpage(phys_avail[(i - 2) + 1]) / NBPDR; + + /* + * Allocate memory for the pv head table for superpages. + */ + s = (vm_size_t)(pv_npg * sizeof(struct md_page)); + s = round_page(s); + pv_table = (struct md_page *)kmem_alloc(kernel_map, s); + for (i = 0; i < pv_npg; i++) + TAILQ_INIT(&pv_table[i].pv_list); } -SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); static int pmap_pventry_proc(SYSCTL_HANDLER_ARGS) { @@ -652,6 +704,25 @@ pmap_shpgperproc_proc(SYSCTL_HANDLER_ARG SYSCTL_PROC(_vm_pmap, OID_AUTO, shpgperproc, CTLTYPE_INT|CTLFLAG_RW, &shpgperproc, 0, pmap_shpgperproc_proc, "IU", "Page share factor per proc"); +SYSCTL_NODE(_vm_pmap, OID_AUTO, pde, CTLFLAG_RD, 0, + "2MB page mapping counters"); + +static u_long pmap_pde_demotions; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, demotions, CTLFLAG_RD, + &pmap_pde_demotions, 0, "2MB page demotions"); + +static u_long pmap_pde_mappings; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, mappings, CTLFLAG_RD, + &pmap_pde_mappings, 0, "2MB page mappings"); + +static u_long pmap_pde_p_failures; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, p_failures, CTLFLAG_RD, + &pmap_pde_p_failures, 0, "2MB page promotion failures"); + +static u_long pmap_pde_promotions; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, promotions, CTLFLAG_RD, + &pmap_pde_promotions, 0, "2MB page promotions"); + /*************************************************** * Low level helper routines..... @@ -953,17 +1024,25 @@ pmap_extract_and_hold(pmap_t pmap, vm_of vm_paddr_t pmap_kextract(vm_offset_t va) { - pd_entry_t *pde; + pd_entry_t pde; vm_paddr_t pa; if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) { pa = DMAP_TO_PHYS(va); } else { - pde = vtopde(va); - if (*pde & PG_PS) { - pa = (*pde & PG_PS_FRAME) | (va & PDRMASK); + pde = *vtopde(va); + if (pde & PG_PS) { + pa = (pde & PG_PS_FRAME) | (va & PDRMASK); } else { - pa = *vtopte(va); + /* + * Beware of a concurrent promotion that changes the + * PDE at this point! For example, vtopte() must not + * be used to access the PTE because it would use the + * new PDE. It is, however, safe to use the old PDE + * because the page table page is preserved by the + * promotion. + */ + pa = *pmap_pde_to_pte(&pde, va); pa = (pa & PG_FRAME) | (va & PAGE_MASK); } } @@ -1085,8 +1164,105 @@ pmap_free_zero_pages(vm_page_t free) while (free != NULL) { m = free; free = m->right; - vm_page_free_zero(m); + /* Preserve the page's PG_ZERO setting. */ + vm_page_free_toq(m); + } +} + +/* + * Schedule the specified unused page table page to be freed. Specifically, + * add the page to the specified list of pages that will be released to the + * physical memory manager after the TLB has been updated. + */ +static __inline void +pmap_add_delayed_free_list(vm_page_t m, vm_page_t *free, boolean_t set_PG_ZERO) +{ + + if (set_PG_ZERO) + m->flags |= PG_ZERO; + else + m->flags &= ~PG_ZERO; + m->right = *free; + *free = m; +} + +/* + * Inserts the specified page table page into the specified pmap's collection + * of idle page table pages. Each of a pmap's page table pages is responsible + * for mapping a distinct range of virtual addresses. The pmap's collection is + * ordered by this virtual address range. + */ +static void +pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte) +{ + vm_page_t root; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + root = pmap->pm_root; + if (root == NULL) { + mpte->left = NULL; + mpte->right = NULL; + } else { + root = vm_page_splay(mpte->pindex, root); + if (mpte->pindex < root->pindex) { + mpte->left = root->left; + mpte->right = root; + root->left = NULL; + } else if (mpte->pindex == root->pindex) + panic("pmap_insert_pt_page: pindex already inserted"); + else { + mpte->right = root->right; + mpte->left = root; + root->right = NULL; + } + } + pmap->pm_root = mpte; +} + +/* + * Looks for a page table page mapping the specified virtual address in the + * specified pmap's collection of idle page table pages. Returns NULL if there + * is no page table page corresponding to the specified virtual address. + */ +static vm_page_t +pmap_lookup_pt_page(pmap_t pmap, vm_offset_t va) +{ + vm_page_t mpte; + vm_pindex_t pindex = pmap_pde_pindex(va); + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if ((mpte = pmap->pm_root) != NULL && mpte->pindex != pindex) { + mpte = vm_page_splay(pindex, mpte); + if ((pmap->pm_root = mpte)->pindex != pindex) + mpte = NULL; } + return (mpte); +} + +/* + * Removes the specified page table page from the specified pmap's collection + * of idle page table pages. The specified page table page must be a member of + * the pmap's collection. + */ +static void +pmap_remove_pt_page(pmap_t pmap, vm_page_t mpte) +{ + vm_page_t root; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + if (mpte != pmap->pm_root) { + root = vm_page_splay(mpte->pindex, pmap->pm_root); + KASSERT(mpte == root, + ("pmap_remove_pt_page: mpte %p is missing from pmap %p", + mpte, pmap)); + } + if (mpte->left == NULL) + root = mpte->right; + else { + root = vm_page_splay(mpte->pindex, mpte->left); + root->right = mpte->right; + } + pmap->pm_root = root; } /* @@ -1165,8 +1341,7 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_of * Put page on a list so that it is released after * *ALL* TLB shootdown is done */ - m->right = *free; - *free = m; + pmap_add_delayed_free_list(m, free, TRUE); return 1; } @@ -1193,6 +1368,7 @@ pmap_pinit0(pmap_t pmap) PMAP_LOCK_INIT(pmap); pmap->pm_pml4 = (pml4_entry_t *)(KERNBASE + KPML4phys); + pmap->pm_root = NULL; pmap->pm_active = 0; TAILQ_INIT(&pmap->pm_pvchunk); bzero(&pmap->pm_stats, sizeof pmap->pm_stats); @@ -1229,6 +1405,7 @@ pmap_pinit(pmap_t pmap) /* install self-referential address mapping entry(s) */ pmap->pm_pml4[PML4PML4I] = VM_PAGE_TO_PHYS(pml4pg) | PG_V | PG_RW | PG_A | PG_M; + pmap->pm_root = NULL; pmap->pm_active = 0; TAILQ_INIT(&pmap->pm_pvchunk); bzero(&pmap->pm_stats, sizeof pmap->pm_stats); @@ -1404,7 +1581,7 @@ pmap_allocpte(pmap_t pmap, vm_offset_t v { vm_pindex_t ptepindex; pd_entry_t *pd; - vm_page_t m, free; + vm_page_t m; KASSERT((flags & (M_NOWAIT | M_WAITOK)) == M_NOWAIT || (flags & (M_NOWAIT | M_WAITOK)) == M_WAITOK, @@ -1424,21 +1601,21 @@ retry: * This supports switching from a 2MB page to a * normal 4K page. */ - if (pd != 0 && (*pd & (PG_PS | PG_V)) == (PG_PS | PG_V)) { - *pd = 0; - pd = 0; - pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; - free = NULL; - pmap_unuse_pt(pmap, va, *pmap_pdpe(pmap, va), &free); - pmap_invalidate_all(kernel_pmap); - pmap_free_zero_pages(free); + if (pd != NULL && (*pd & (PG_PS | PG_V)) == (PG_PS | PG_V)) { + if (!pmap_demote_pde(pmap, pd, va)) { + /* + * Invalidation of the 2MB page mapping may have caused + * the deallocation of the underlying PD page. + */ + pd = NULL; + } } /* * If the page table page is mapped, we just increment the * hold count, and activate it. */ - if (pd != 0 && (*pd & PG_V) != 0) { + if (pd != NULL && (*pd & PG_V) != 0) { m = PHYS_TO_VM_PAGE(*pd & PG_FRAME); m->wire_count++; } else { @@ -1471,6 +1648,8 @@ pmap_release(pmap_t pmap) KASSERT(pmap->pm_stats.resident_count == 0, ("pmap_release: pmap resident count %ld != 0", pmap->pm_stats.resident_count)); + KASSERT(pmap->pm_root == NULL, + ("pmap_release: pmap has reserved page table page(s)")); m = PHYS_TO_VM_PAGE(pmap->pm_pml4[PML4PML4I] & PG_FRAME); @@ -1645,11 +1824,16 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pmap_coll * drastic measures to free some pages so we can allocate * another pv entry chunk. This is normally called to * unmap inactive pages, and if necessary, active pages. + * + * We do not, however, unmap 2mpages because subsequent accesses will + * allocate per-page pv entries until repromotion occurs, thereby + * exacerbating the shortage of free pv entries. */ static void pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq) { - pd_entry_t ptepde; + struct md_page *pvh; + pd_entry_t *pde; pmap_t pmap; pt_entry_t *pte, tpte; pv_entry_t next_pv, pv; @@ -1668,28 +1852,27 @@ pmap_collect(pmap_t locked_pmap, struct else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) continue; pmap->pm_stats.resident_count--; - pte = pmap_pte_pde(pmap, va, &ptepde); - if (pte == NULL) { - panic("null pte in pmap_collect"); - } + pde = pmap_pde(pmap, va); + KASSERT((*pde & PG_PS) == 0, ("pmap_collect: found" + " a 2mpage in page %p's pv list", m)); + pte = pmap_pde_to_pte(pde, va); tpte = pte_load_clear(pte); KASSERT((tpte & PG_W) == 0, ("pmap_collect: wired pte %#lx", tpte)); if (tpte & PG_A) vm_page_flag_set(m, PG_REFERENCED); - if (tpte & PG_M) { - KASSERT((tpte & PG_RW), - ("pmap_collect: modified page not writable: va: %#lx, pte: %#lx", - va, tpte)); + if ((tpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) vm_page_dirty(m); - } free = NULL; - pmap_unuse_pt(pmap, va, ptepde, &free); + pmap_unuse_pt(pmap, va, *pde, &free); pmap_invalidate_page(pmap, va); pmap_free_zero_pages(free); TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (TAILQ_EMPTY(&m->md.pv_list)) - vm_page_flag_clear(m, PG_WRITEABLE); + if (TAILQ_EMPTY(&m->md.pv_list)) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + if (TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } free_pv_entry(pmap, pv); if (pmap != locked_pmap) PMAP_UNLOCK(pmap); @@ -1824,24 +2007,133 @@ retry: return (pv); } -static void -pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va) +/* + * First find and then remove the pv entry for the specified pmap and virtual + * address from the specified pv list. Returns the pv entry if found and NULL + * otherwise. This operation can be performed on pv lists for either 4KB or + * 2MB page mappings. + */ +static __inline pv_entry_t +pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va) { pv_entry_t pv; - PMAP_LOCK_ASSERT(pmap, MA_OWNED); mtx_assert(&vm_page_queue_mtx, MA_OWNED); - TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) { - if (pmap == PV_PMAP(pv) && va == pv->pv_va) + TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) { + if (pmap == PV_PMAP(pv) && va == pv->pv_va) { + TAILQ_REMOVE(&pvh->pv_list, pv, pv_list); break; + } } - KASSERT(pv != NULL, ("pmap_remove_entry: pv not found")); - TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); - if (TAILQ_EMPTY(&m->md.pv_list)) - vm_page_flag_clear(m, PG_WRITEABLE); + return (pv); +} + +/* + * After demotion from a 2MB page mapping to 512 4KB page mappings, + * destroy the pv entry for the 2MB page mapping and reinstantiate the pv + * entries for each of the 4KB page mappings. + */ +static void +pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + vm_offset_t va_last; + vm_page_t m; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + KASSERT((pa & PDRMASK) == 0, + ("pmap_pv_demote_pde: pa is not 2mpage aligned")); + + /* + * Transfer the 2mpage's pv entry for this mapping to the first + * page's pv list. + */ + pvh = pa_to_pvh(pa); + va = trunc_2mpage(va); + pv = pmap_pvh_remove(pvh, pmap, va); + KASSERT(pv != NULL, ("pmap_pv_demote_pde: pv not found")); + m = PHYS_TO_VM_PAGE(pa); + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); + /* Instantiate the remaining NPTEPG - 1 pv entries. */ + va_last = va + NBPDR - PAGE_SIZE; + do { + m++; + KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0, + ("pmap_pv_demote_pde: page %p is not managed", m)); + va += PAGE_SIZE; + pmap_insert_entry(pmap, va, m); + } while (va < va_last); +} + +/* + * After promotion from 512 4KB page mappings to a single 2MB page mapping, + * replace the many pv entries for the 4KB page mappings by a single pv entry + * for the 2MB page mapping. + */ +static void +pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + vm_offset_t va_last; + vm_page_t m; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + KASSERT((pa & PDRMASK) == 0, + ("pmap_pv_promote_pde: pa is not 2mpage aligned")); + + /* + * Transfer the first page's pv entry for this mapping to the + * 2mpage's pv list. Aside from avoiding the cost of a call + * to get_pv_entry(), a transfer avoids the possibility that + * get_pv_entry() calls pmap_collect() and that pmap_collect() + * removes one of the mappings that is being promoted. + */ + m = PHYS_TO_VM_PAGE(pa); + va = trunc_2mpage(va); + pv = pmap_pvh_remove(&m->md, pmap, va); + KASSERT(pv != NULL, ("pmap_pv_promote_pde: pv not found")); + pvh = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list); + /* Free the remaining NPTEPG - 1 pv entries. */ + va_last = va + NBPDR - PAGE_SIZE; + do { + m++; + va += PAGE_SIZE; + pmap_pvh_free(&m->md, pmap, va); + } while (va < va_last); +} + +/* + * First find and then destroy the pv entry for the specified pmap and virtual + * address. This operation can be performed on pv lists for either 4KB or 2MB + * page mappings. + */ +static void +pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va) +{ + pv_entry_t pv; + + pv = pmap_pvh_remove(pvh, pmap, va); + KASSERT(pv != NULL, ("pmap_pvh_free: pv not found")); free_pv_entry(pmap, pv); } +static void +pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va) +{ + struct md_page *pvh; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + pmap_pvh_free(&m->md, pmap, va); + if (TAILQ_EMPTY(&m->md.pv_list)) { + pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); + if (TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } +} + /* * Create a pv entry for page at pa for * (pmap, va). @@ -1878,6 +2170,170 @@ pmap_try_insert_pv_entry(pmap_t pmap, vm } /* + * Create the pv entry for a 2MB page mapping. + */ +static boolean_t +pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa) +{ + struct md_page *pvh; + pv_entry_t pv; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + if (pv_entry_count < pv_entry_high_water && + (pv = get_pv_entry(pmap, TRUE)) != NULL) { + pv->pv_va = va; + pvh = pa_to_pvh(pa); + TAILQ_INSERT_TAIL(&pvh->pv_list, pv, pv_list); + return (TRUE); + } else + return (FALSE); +} + +/* + * Tries to demote a 2MB page mapping. + */ +static boolean_t +pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) +{ + pd_entry_t newpde, oldpde; + pt_entry_t *firstpte, newpte, *pte; + vm_paddr_t mptepa; + vm_page_t free, mpte; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + mpte = pmap_lookup_pt_page(pmap, va); + if (mpte != NULL) + pmap_remove_pt_page(pmap, mpte); + else { + KASSERT((*pde & PG_W) == 0, + ("pmap_demote_pde: page table page for a wired mapping" + " is missing")); + free = NULL; + pmap_remove_pde(pmap, pde, trunc_2mpage(va), &free); + pmap_invalidate_page(pmap, trunc_2mpage(va)); + pmap_free_zero_pages(free); + CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#lx" + " in pmap %p", va, pmap); + return (FALSE); + } + mptepa = VM_PAGE_TO_PHYS(mpte); + firstpte = (pt_entry_t *)PHYS_TO_DMAP(mptepa); + oldpde = *pde; + newpde = mptepa | PG_M | PG_A | (oldpde & PG_U) | PG_RW | PG_V; + KASSERT((oldpde & (PG_A | PG_V)) == (PG_A | PG_V), + ("pmap_demote_pde: oldpde is missing PG_A and/or PG_V")); + KASSERT((oldpde & (PG_M | PG_RW)) != PG_RW, + ("pmap_demote_pde: oldpde is missing PG_M")); + KASSERT((oldpde & PG_PS) != 0, + ("pmap_demote_pde: oldpde is missing PG_PS")); + newpte = oldpde & ~PG_PS; + if ((newpte & PG_PDE_PAT) != 0) + newpte ^= PG_PDE_PAT | PG_PTE_PAT; + + /* + * If the mapping has changed attributes, update the page table + * entries. + */ + KASSERT((*firstpte & PG_FRAME) == (newpte & PG_FRAME), + ("pmap_demote_pde: firstpte and newpte map different physical" + " addresses")); + if ((*firstpte & PG_PTE_PROMOTE) != (newpte & PG_PTE_PROMOTE)) + for (pte = firstpte; pte < firstpte + NPTEPG; pte++) { + *pte = newpte; + newpte += PAGE_SIZE; + } + + /* + * Demote the mapping. This pmap is locked. The old PDE has + * PG_A set. If the old PDE has PG_RW set, it also has PG_M + * set. Thus, there is no danger of a race with another + * processor changing the setting of PG_A and/or PG_M between + * the read above and the store below. + */ + pde_store(pde, newpde); + + /* + * Invalidate a stale mapping of the page table page. + */ + pmap_invalidate_page(pmap, (vm_offset_t)vtopte(va)); + + /* + * Demote the pv entry. This depends on the earlier demotion + * of the mapping. Specifically, the (re)creation of a per- + * page pv entry might trigger the execution of pmap_collect(), + * which might reclaim a newly (re)created per-page pv entry + * and destroy the associated mapping. In order to destroy + * the mapping, the PDE must have already changed from mapping + * the 2mpage to referencing the page table page. + */ + if ((oldpde & PG_MANAGED) != 0) + pmap_pv_demote_pde(pmap, va, oldpde & PG_PS_FRAME); + + pmap_pde_demotions++; + CTR2(KTR_PMAP, "pmap_demote_pde: success for va %#lx" + " in pmap %p", va, pmap); + return (TRUE); +} + +/* + * pmap_remove_pde: do the things to unmap a superpage in a process + */ +static int +pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, + vm_page_t *free) +{ + struct md_page *pvh; + pd_entry_t oldpde; + vm_offset_t eva, va; + vm_page_t m, mpte; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT((sva & PDRMASK) == 0, + ("pmap_remove_pde: sva is not 2mpage aligned")); + oldpde = pte_load_clear(pdq); + if (oldpde & PG_W) + pmap->pm_stats.wired_count -= NBPDR / PAGE_SIZE; + + /* + * Machines that don't support invlpg, also don't support + * PG_G. + */ + if (oldpde & PG_G) + pmap_invalidate_page(kernel_pmap, sva); + pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; + if (oldpde & PG_MANAGED) { + pvh = pa_to_pvh(oldpde & PG_PS_FRAME); + pmap_pvh_free(pvh, pmap, sva); + eva = sva + NBPDR; + for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME); + va < eva; va += PAGE_SIZE, m++) { + if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW)) + vm_page_dirty(m); + if (oldpde & PG_A) + vm_page_flag_set(m, PG_REFERENCED); + if (TAILQ_EMPTY(&m->md.pv_list) && + TAILQ_EMPTY(&pvh->pv_list)) + vm_page_flag_clear(m, PG_WRITEABLE); + } + } + if (pmap == kernel_pmap) { + if (!pmap_demote_pde(pmap, pdq, sva)) + panic("pmap_remove_pde: failed demotion"); + } else { + mpte = pmap_lookup_pt_page(pmap, sva); + if (mpte != NULL) { + pmap_remove_pt_page(pmap, mpte); + KASSERT(mpte->wire_count == NPTEPG, + ("pmap_remove_pde: pte page wire count error")); + mpte->wire_count = 0; + pmap_add_delayed_free_list(mpte, free, FALSE); + atomic_subtract_int(&cnt.v_wire_count, 1); + } + } + return (pmap_unuse_pt(pmap, sva, *pmap_pdpe(pmap, sva), free)); +} + +/* * pmap_remove_pte: do the things to unmap a page in a process */ static int @@ -1900,12 +23