Date: Sat, 29 Oct 2011 06:55:58 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r226899 - in user/adrian/if_ath_tx: contrib/tzcode/stdtime etc etc/defaults etc/periodic/daily etc/rc.d games/fortune/datfiles lib/libc/gen sbin/geom/class/raid sbin/hastd share/mk sys/... Message-ID: <201110290655.p9T6twrP098676@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Sat Oct 29 06:55:57 2011 New Revision: 226899 URL: http://svn.freebsd.org/changeset/base/226899 Log: IFC Added: user/adrian/if_ath_tx/tools/regression/bin/sh/builtins/for1.0 - copied unchanged from r226898, head/tools/regression/bin/sh/builtins/for1.0 Modified: user/adrian/if_ath_tx/contrib/tzcode/stdtime/localtime.c user/adrian/if_ath_tx/etc/defaults/periodic.conf user/adrian/if_ath_tx/etc/devfs.conf user/adrian/if_ath_tx/etc/periodic/daily/800.scrub-zfs user/adrian/if_ath_tx/etc/rc.d/dhclient user/adrian/if_ath_tx/games/fortune/datfiles/fortunes user/adrian/if_ath_tx/lib/libc/gen/getutxent.3 user/adrian/if_ath_tx/lib/libc/gen/pututxline.c user/adrian/if_ath_tx/sbin/geom/class/raid/graid.8 user/adrian/if_ath_tx/sbin/hastd/hast.conf.5 user/adrian/if_ath_tx/sbin/hastd/parse.y user/adrian/if_ath_tx/sbin/hastd/primary.c user/adrian/if_ath_tx/sbin/hastd/secondary.c user/adrian/if_ath_tx/sys/amd64/amd64/pmap.c user/adrian/if_ath_tx/sys/amd64/amd64/trap.c user/adrian/if_ath_tx/sys/amd64/amd64/uma_machdep.c user/adrian/if_ath_tx/sys/amd64/conf/GENERIC user/adrian/if_ath_tx/sys/arm/at91/at91.c user/adrian/if_ath_tx/sys/arm/econa/econa.c user/adrian/if_ath_tx/sys/arm/xscale/i80321/iq80321.c user/adrian/if_ath_tx/sys/arm/xscale/i8134x/i81342.c user/adrian/if_ath_tx/sys/arm/xscale/ixp425/ixp425.c user/adrian/if_ath_tx/sys/arm/xscale/pxa/pxa_obio.c user/adrian/if_ath_tx/sys/boot/forth/loader.conf user/adrian/if_ath_tx/sys/conf/files.arm user/adrian/if_ath_tx/sys/conf/kern.mk user/adrian/if_ath_tx/sys/conf/newvers.sh user/adrian/if_ath_tx/sys/contrib/pf/net/if_pfsync.c user/adrian/if_ath_tx/sys/crypto/aesni/aesni_wrap.c user/adrian/if_ath_tx/sys/dev/ath/if_ath.c user/adrian/if_ath_tx/sys/dev/bge/if_bge.c user/adrian/if_ath_tx/sys/dev/bge/if_bgereg.h user/adrian/if_ath_tx/sys/dev/mfi/mfivar.h user/adrian/if_ath_tx/sys/dev/mii/brgphy.c user/adrian/if_ath_tx/sys/dev/mii/miidevs user/adrian/if_ath_tx/sys/dev/syscons/scterm-teken.c user/adrian/if_ath_tx/sys/dev/tws/tws_services.c user/adrian/if_ath_tx/sys/dev/tws/tws_services.h user/adrian/if_ath_tx/sys/dev/usb/controller/xhci.c user/adrian/if_ath_tx/sys/dev/usb/controller/xhcireg.h user/adrian/if_ath_tx/sys/dev/usb/usb.h user/adrian/if_ath_tx/sys/dev/usb/usb_hub.c user/adrian/if_ath_tx/sys/dev/xen/balloon/balloon.c user/adrian/if_ath_tx/sys/geom/eli/g_eli.c user/adrian/if_ath_tx/sys/geom/eli/g_eli.h user/adrian/if_ath_tx/sys/geom/part/g_part.c user/adrian/if_ath_tx/sys/geom/raid/md_intel.c user/adrian/if_ath_tx/sys/geom/raid/md_nvidia.c user/adrian/if_ath_tx/sys/geom/raid/md_promise.c user/adrian/if_ath_tx/sys/i386/conf/GENERIC user/adrian/if_ath_tx/sys/i386/i386/pmap.c user/adrian/if_ath_tx/sys/i386/i386/trap.c user/adrian/if_ath_tx/sys/i386/xen/pmap.c user/adrian/if_ath_tx/sys/ia64/conf/GENERIC user/adrian/if_ath_tx/sys/kern/init_main.c user/adrian/if_ath_tx/sys/kern/kern_malloc.c user/adrian/if_ath_tx/sys/kern/kern_sig.c user/adrian/if_ath_tx/sys/kern/subr_syscall.c user/adrian/if_ath_tx/sys/kern/vfs_bio.c user/adrian/if_ath_tx/sys/kern/vfs_subr.c user/adrian/if_ath_tx/sys/net/if_var.h user/adrian/if_ath_tx/sys/netgraph/netgraph.h user/adrian/if_ath_tx/sys/netgraph/ng_base.c user/adrian/if_ath_tx/sys/netinet/sctp_output.c user/adrian/if_ath_tx/sys/netinet/sctp_pcb.c user/adrian/if_ath_tx/sys/pc98/conf/GENERIC user/adrian/if_ath_tx/sys/powerpc/conf/GENERIC user/adrian/if_ath_tx/sys/sparc64/conf/GENERIC user/adrian/if_ath_tx/sys/sys/fcntl.h user/adrian/if_ath_tx/sys/vm/vm_contig.c user/adrian/if_ath_tx/sys/vm/vm_extern.h user/adrian/if_ath_tx/sys/vm/vm_kern.c user/adrian/if_ath_tx/sys/vm/vm_page.c user/adrian/if_ath_tx/usr.bin/getent/getent.c user/adrian/if_ath_tx/usr.bin/sed/sed.1 user/adrian/if_ath_tx/usr.bin/who/who.1 user/adrian/if_ath_tx/usr.bin/who/who.c Directory Properties: user/adrian/if_ath_tx/ (props changed) user/adrian/if_ath_tx/cddl/contrib/opensolaris/ (props changed) user/adrian/if_ath_tx/contrib/com_err/ (props changed) user/adrian/if_ath_tx/contrib/compiler-rt/ (props changed) user/adrian/if_ath_tx/contrib/ee/ (props changed) user/adrian/if_ath_tx/contrib/expat/ (props changed) user/adrian/if_ath_tx/contrib/file/ (props changed) user/adrian/if_ath_tx/contrib/gdb/ (props changed) user/adrian/if_ath_tx/contrib/gnu-sort/ (props changed) user/adrian/if_ath_tx/contrib/groff/ (props changed) user/adrian/if_ath_tx/contrib/less/ (props changed) user/adrian/if_ath_tx/contrib/libpcap/ (props changed) user/adrian/if_ath_tx/contrib/ncurses/ (props changed) user/adrian/if_ath_tx/contrib/one-true-awk/ (props changed) user/adrian/if_ath_tx/contrib/openbsm/ (props changed) user/adrian/if_ath_tx/contrib/openpam/ (props changed) user/adrian/if_ath_tx/contrib/openresolv/ (props changed) user/adrian/if_ath_tx/contrib/pf/ (props changed) user/adrian/if_ath_tx/contrib/tcpdump/ (props changed) user/adrian/if_ath_tx/contrib/tcsh/ (props changed) user/adrian/if_ath_tx/contrib/tnftp/ (props changed) user/adrian/if_ath_tx/contrib/tzcode/stdtime/ (props changed) user/adrian/if_ath_tx/contrib/tzcode/zic/ (props changed) user/adrian/if_ath_tx/contrib/tzdata/ (props changed) user/adrian/if_ath_tx/contrib/wpa/ (props changed) user/adrian/if_ath_tx/crypto/heimdal/ (props changed) user/adrian/if_ath_tx/lib/libutil/ (props changed) user/adrian/if_ath_tx/lib/libz/ (props changed) user/adrian/if_ath_tx/sbin/ (props changed) user/adrian/if_ath_tx/sbin/ipfw/ (props changed) user/adrian/if_ath_tx/share/mk/bsd.arch.inc.mk (props changed) user/adrian/if_ath_tx/sys/contrib/dev/acpica/ (props changed) user/adrian/if_ath_tx/usr.bin/csup/ (props changed) user/adrian/if_ath_tx/usr.bin/procstat/ (props changed) user/adrian/if_ath_tx/usr.sbin/rtadvctl/ (props changed) user/adrian/if_ath_tx/usr.sbin/rtadvd/ (props changed) user/adrian/if_ath_tx/usr.sbin/rtsold/ (props changed) Modified: user/adrian/if_ath_tx/contrib/tzcode/stdtime/localtime.c ============================================================================== --- user/adrian/if_ath_tx/contrib/tzcode/stdtime/localtime.c Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/contrib/tzcode/stdtime/localtime.c Sat Oct 29 06:55:57 2011 (r226899) @@ -450,6 +450,7 @@ register const int doextend; _close(fid); return -1; } + free(fullname); } u = malloc(sizeof(*u)); if (u == NULL) Modified: user/adrian/if_ath_tx/etc/defaults/periodic.conf ============================================================================== --- user/adrian/if_ath_tx/etc/defaults/periodic.conf Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/etc/defaults/periodic.conf Sat Oct 29 06:55:57 2011 (r226899) @@ -150,8 +150,8 @@ daily_submit_queuerun="YES" # Also su # 800.scrub-zfs daily_scrub_zfs_enable="NO" daily_scrub_zfs_pools="" # empty string selects all pools -daily_scrub_zfs_default_threshold="30" # days between scrubs -#daily_scrub_zfs_${poolname}_threshold="30" # pool specific threshold +daily_scrub_zfs_default_threshold="35" # days between scrubs +#daily_scrub_zfs_${poolname}_threshold="35" # pool specific threshold # 999.local daily_local="/etc/daily.local" # Local scripts Modified: user/adrian/if_ath_tx/etc/devfs.conf ============================================================================== --- user/adrian/if_ath_tx/etc/devfs.conf Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/etc/devfs.conf Sat Oct 29 06:55:57 2011 (r226899) @@ -31,11 +31,9 @@ # # Examples: -# Historically X depended on this, but version 4.3.0 doesn't seem to anymore -#link ttyv0 vga - # Commonly used by many ports -#link acd0 cdrom +#link cd0 cdrom +#link cd0 dvd # Allow a user in the wheel group to query the smb0 device #perm smb0 0660 Modified: user/adrian/if_ath_tx/etc/periodic/daily/800.scrub-zfs ============================================================================== --- user/adrian/if_ath_tx/etc/periodic/daily/800.scrub-zfs Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/etc/periodic/daily/800.scrub-zfs Sat Oct 29 06:55:57 2011 (r226899) @@ -15,7 +15,7 @@ then source_periodic_confs fi -: ${daily_scrub_zfs_default_threshold=30} +: ${daily_scrub_zfs_default_threshold=35} case "$daily_scrub_zfs_enable" in [Yy][Ee][Ss]) Modified: user/adrian/if_ath_tx/etc/rc.d/dhclient ============================================================================== --- user/adrian/if_ath_tx/etc/rc.d/dhclient Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/etc/rc.d/dhclient Sat Oct 29 06:55:57 2011 (r226899) @@ -15,9 +15,21 @@ name="dhclient" rcvar= pidfile="/var/run/${name}.${ifn}.pid" start_precmd="dhclient_prestart" +stop_precmd="dhclient_pre_check" + +# rc_force check can only be done at the run_rc_command +# time, so we're testing it in the pre* hooks. +dhclient_pre_check() +{ + if [ -z "${rc_force}" ] && ! dhcpif $ifn; then + err 1 "'$ifn' is not a DHCP-enabled interface" + fi +} dhclient_prestart() { + dhclient_pre_check + # Interface-specific flags (see rc.subr for $flags setting) specific=$(get_if_var $ifn dhclient_flags_IF) if [ -z "$flags" -a -n "$specific" ]; then @@ -38,11 +50,8 @@ load_rc_config network if [ -z $ifn ] ; then # only complain if a command was specified but no interface if [ -n "$1" ] ; then - echo 1>&2 "$0: no interface specified" - return 1 + err 1 "$0: no interface specified" fi -elif [ -z "${rc_force}" ] && ! dhcpif $ifn; then - return 1 fi run_rc_command "$1" Modified: user/adrian/if_ath_tx/games/fortune/datfiles/fortunes ============================================================================== --- user/adrian/if_ath_tx/games/fortune/datfiles/fortunes Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/games/fortune/datfiles/fortunes Sat Oct 29 06:55:57 2011 (r226899) @@ -4942,25 +4942,37 @@ cats on the dinette table, etc. "That stop him?" "No, but it sure slowed him up." % - Youth is not a time of life, it is a state of mind; it is a temper of -the will, a quality of the imagination, a vigor of the emotions, a predominance -of courage over timidity, of the appetite for adventure over love of ease. - Nobody grows old by merely living a number of years; people grow -old only by deserting their ideals. Years wrinkle the skin, but to give up -enthusiasm wrinkles the soul. Worry, doubt, self-distrust, fear, and despair --- these are the long, long years that bow the head and turn the growing spirit -back to dust. - Whether seventy or sixteen, there is in every being's heart the love -of wonder, the sweet amazement at the stars and the starlike things and -thoughts, the undaunted challenge of events, the unfailing childlike appetite -for what next, and the joy and the game of life. - You are as young as your faith, as old as your doubt; as young as your -self-confidence, as old as your fear, as young as your hope, as old as your -despair. - So long as your heart receives messages of beauty, cheer, courage, -grandeur and power from the earth, from man, and from the Infinite, so long -you are young. - -- Samuel Ullman + Youth is not a time of life--it is a state of mind. It is not a +matter of red cheeks, red lips and supple knees. It is a temper of the +will; a quality of the imagination; a vigor of the emotions; it is a +freshness of the deep springs of life. Youth means a tempermental +predominance of courage over timidity, of the appetite for adventure +over a life of ease. This often exists in a man of fifty, more than in +a boy of twenty. Nobody grows old by merely living a number of years; +people grow old by deserting their ideals. + + Years may wrinkle the skin, but to give up enthusiasm wrinkles +the soul. Worry, doubt, self-distrust, fear and despair--these are the +long, long years that bow the head and turn the growing spirit back to +dust. + + Whether seventy or sixteen, there is in every being’s heart a +love of wonder; the sweet amazement at the stars and starlike things and +thoughts; the undaunted challenge of events, the unfailing childlike +appetite for what comes next, and the joy in the game of life. + + You are as young as your faith, as old as your doubt; as young +as your self-confidence, as old as your fear, as young as your hope, as +old as your despair. + + In the central place of your heart there is a wireless station. +So long as it receives messages of beauty, hope, cheer, grandeur, +courage, and power from the earth, from men and from the Infinite--so +long are you young. When the wires are all down and the central places +of your heart are covered with the snows of pessimism and the ice of +cynicism, then are you grown old, indeed! + -- Samuel Ullman, "Youth" (1934), as published in + The Silver Treasury, Prose and Verse for Every Mood % " " -- Charlie Chaplin Modified: user/adrian/if_ath_tx/lib/libc/gen/getutxent.3 ============================================================================== --- user/adrian/if_ath_tx/lib/libc/gen/getutxent.3 Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/lib/libc/gen/getutxent.3 Sat Oct 29 06:55:57 2011 (r226899) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 19, 2011 +.Dd October 27, 2011 .Dt GETUTXENT 3 .Os .Sh NAME @@ -301,7 +301,6 @@ The value of determines which databases are modified. .Pp Entries of type -.Dv BOOT_TIME , .Dv SHUTDOWN_TIME , .Dv OLD_TIME and @@ -335,7 +334,7 @@ In addition, entries of type .Dv BOOT_TIME and .Dv SHUTDOWN_TIME -will cause all entries in +will cause all existing entries in .Pa /var/run/utx.active to be discarded. .Pp @@ -386,10 +385,10 @@ Otherwise, -1 is returned and the global is set to indicate the error. .Sh ERRORS In addition to the error conditions described in +.Xr open 2 , .Xr fdopen 3 , .Xr fopen 3 , .Xr fseek 3 , -.Xr open 3 , the .Fn pututxline function can generate the following errors: Modified: user/adrian/if_ath_tx/lib/libc/gen/pututxline.c ============================================================================== --- user/adrian/if_ath_tx/lib/libc/gen/pututxline.c Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/lib/libc/gen/pututxline.c Sat Oct 29 06:55:57 2011 (r226899) @@ -86,6 +86,9 @@ utx_active_add(const struct futx *fu) return (-1); while (fread(&fe, sizeof(fe), 1, fp) == 1) { switch (fe.fu_type) { + case BOOT_TIME: + /* Leave these intact. */ + break; case USER_PROCESS: case INIT_PROCESS: case LOGIN_PROCESS: @@ -171,6 +174,19 @@ utx_active_remove(struct futx *fu) } static void +utx_active_init(const struct futx *fu) +{ + int fd; + + /* Initialize utx.active with a single BOOT_TIME record. */ + fd = _open(_PATH_UTX_ACTIVE, O_CREAT|O_RDWR|O_TRUNC, 0644); + if (fd < 0) + return; + _write(fd, fu, sizeof(*fu)); + _close(fd); +} + +static void utx_active_purge(void) { @@ -277,9 +293,11 @@ pututxline(const struct utmpx *utmpx) switch (fu.fu_type) { case BOOT_TIME: + utx_active_init(&fu); + utx_lastlogin_upgrade(); + break; case SHUTDOWN_TIME: utx_active_purge(); - utx_lastlogin_upgrade(); break; case OLD_TIME: case NEW_TIME: Modified: user/adrian/if_ath_tx/sbin/geom/class/raid/graid.8 ============================================================================== --- user/adrian/if_ath_tx/sbin/geom/class/raid/graid.8 Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sbin/geom/class/raid/graid.8 Sat Oct 29 06:55:57 2011 (r226899) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 22, 2011 +.Dd October 26, 2011 .Dt GRAID 8 .Os .Sh NAME @@ -250,6 +250,9 @@ If you started migration using BIOS or i complete it there. Do not run GEOM RAID class on migrating volumes under pain of possible data corruption! +.Sh 2TiB BARRIERS +Intel and Promise metadata formats do not support disks above 2TiB. +NVIDIA metadata format does not support volumes above 2TiB. .Sh EXIT STATUS Exit status is 0 on success, and non-zero if the command fails. .Sh SEE ALSO Modified: user/adrian/if_ath_tx/sbin/hastd/hast.conf.5 ============================================================================== --- user/adrian/if_ath_tx/sbin/hastd/hast.conf.5 Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sbin/hastd/hast.conf.5 Sat Oct 29 06:55:57 2011 (r226899) @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 20, 2011 +.Dd October 27, 2011 .Dt HAST.CONF 5 .Os .Sh NAME @@ -224,9 +224,6 @@ completes. This is the fastest and the most dangerous replication mode. This mode should be used when replicating to a distant node where latency is too high for other modes. -The -.Ic async -replication mode is currently not implemented. .El .It Ic checksum Aq algorithm .Pp Modified: user/adrian/if_ath_tx/sbin/hastd/parse.y ============================================================================== --- user/adrian/if_ath_tx/sbin/hastd/parse.y Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sbin/hastd/parse.y Sat Oct 29 06:55:57 2011 (r226899) @@ -301,11 +301,9 @@ yy_config_parse(const char *config, bool */ curres->hr_replication = depth0_replication; } - if (curres->hr_replication == HAST_REPLICATION_MEMSYNC || - curres->hr_replication == HAST_REPLICATION_ASYNC) { + if (curres->hr_replication == HAST_REPLICATION_MEMSYNC) { pjdlog_warning("Replication mode \"%s\" is not implemented, falling back to \"%s\".", - curres->hr_replication == HAST_REPLICATION_MEMSYNC ? - "memsync" : "async", "fullsync"); + "memsync", "fullsync"); curres->hr_replication = HAST_REPLICATION_FULLSYNC; } if (curres->hr_checksum == -1) { Modified: user/adrian/if_ath_tx/sbin/hastd/primary.c ============================================================================== --- user/adrian/if_ath_tx/sbin/hastd/primary.c Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sbin/hastd/primary.c Sat Oct 29 06:55:57 2011 (r226899) @@ -89,6 +89,15 @@ struct hio { * Structure used to communicate with GEOM Gate class. */ struct g_gate_ctl_io hio_ggio; + /* + * Request was already confirmed to GEOM Gate. + */ + bool hio_done; + /* + * Remember replication from the time the request was initiated, + * so we won't get confused when replication changes on reload. + */ + int hio_replication; TAILQ_ENTRY(hio) *hio_next; }; #define hio_free_next hio_next[0] @@ -1021,7 +1030,7 @@ remote_close(struct hast_resource *res, rw_wlock(&hio_remote_lock[ncomp]); /* - * A race is possible between dropping rlock and acquiring wlock - + * Check for a race between dropping rlock and acquiring wlock - * another thread can close connection in-between. */ if (!ISCONNECTED(res, ncomp)) { @@ -1056,6 +1065,42 @@ remote_close(struct hast_resource *res, } /* + * Acknowledge write completion to the kernel, but don't update activemap yet. + */ +static void +write_complete(struct hast_resource *res, struct hio *hio) +{ + struct g_gate_ctl_io *ggio; + unsigned int ncomp; + + PJDLOG_ASSERT(!hio->hio_done); + + ggio = &hio->hio_ggio; + PJDLOG_ASSERT(ggio->gctl_cmd == BIO_WRITE); + + /* + * Bump local count if this is first write after + * connection failure with remote node. + */ + ncomp = 1; + rw_rlock(&hio_remote_lock[ncomp]); + if (!ISCONNECTED(res, ncomp)) { + mtx_lock(&metadata_lock); + if (res->hr_primary_localcnt == res->hr_secondary_remotecnt) { + res->hr_primary_localcnt++; + pjdlog_debug(1, "Increasing localcnt to %ju.", + (uintmax_t)res->hr_primary_localcnt); + (void)metadata_write(res); + } + mtx_unlock(&metadata_lock); + } + rw_unlock(&hio_remote_lock[ncomp]); + if (ioctl(res->hr_ggatefd, G_GATE_CMD_DONE, ggio) < 0) + primary_exit(EX_OSERR, "G_GATE_CMD_DONE failed"); + hio->hio_done = true; +} + +/* * Thread receives ggate I/O requests from the kernel and passes them to * appropriate threads: * WRITE - always goes to both local_send and remote_send threads @@ -1075,8 +1120,6 @@ ggate_recv_thread(void *arg) unsigned int ii, ncomp, ncomps; int error; - ncomps = HAST_NCOMPONENTS; - for (;;) { pjdlog_debug(2, "ggate_recv: Taking free request."); QUEUE_TAKE2(hio, free); @@ -1085,6 +1128,8 @@ ggate_recv_thread(void *arg) ggio->gctl_unit = res->hr_ggateunit; ggio->gctl_length = MAXPHYS; ggio->gctl_error = 0; + hio->hio_done = false; + hio->hio_replication = res->hr_replication; pjdlog_debug(2, "ggate_recv: (%p) Waiting for request from the kernel.", hio); @@ -1117,11 +1162,16 @@ ggate_recv_thread(void *arg) primary_exitx(EX_OSERR, "G_GATE_CMD_START failed: %s.", strerror(error)); } + + ncomp = 0; + ncomps = HAST_NCOMPONENTS; + for (ii = 0; ii < ncomps; ii++) hio->hio_errors[ii] = EINVAL; reqlog(LOG_DEBUG, 2, ggio, "ggate_recv: (%p) Request received from the kernel: ", hio); + /* * Inform all components about new write request. * For read request prefer local component unless the given @@ -1130,10 +1180,7 @@ ggate_recv_thread(void *arg) switch (ggio->gctl_cmd) { case BIO_READ: res->hr_stat_read++; - pjdlog_debug(2, - "ggate_recv: (%p) Moving request to the send queue.", - hio); - refcount_init(&hio->hio_countdown, 1); + ncomps = 1; mtx_lock(&metadata_lock); if (res->hr_syncsrc == HAST_SYNCSRC_UNDEF || res->hr_syncsrc == HAST_SYNCSRC_PRIMARY) { @@ -1155,17 +1202,13 @@ ggate_recv_thread(void *arg) ncomp = 1; } mtx_unlock(&metadata_lock); - QUEUE_INSERT1(hio, send, ncomp); break; case BIO_WRITE: res->hr_stat_write++; - if (res->hr_resuid == 0) { - /* - * This is first write, initialize localcnt and - * resuid. - */ + if (res->hr_resuid == 0 && + res->hr_primary_localcnt == 0) { + /* This is first write. */ res->hr_primary_localcnt = 1; - (void)init_resuid(res); } for (;;) { mtx_lock(&range_lock); @@ -1201,25 +1244,19 @@ ggate_recv_thread(void *arg) (void)hast_activemap_flush(res); } mtx_unlock(&res->hr_amp_lock); - /* FALLTHROUGH */ + break; case BIO_DELETE: + res->hr_stat_delete++; + break; case BIO_FLUSH: - switch (ggio->gctl_cmd) { - case BIO_DELETE: - res->hr_stat_delete++; - break; - case BIO_FLUSH: - res->hr_stat_flush++; - break; - } - pjdlog_debug(2, - "ggate_recv: (%p) Moving request to the send queue.", - hio); - refcount_init(&hio->hio_countdown, ncomps); - for (ii = 0; ii < ncomps; ii++) - QUEUE_INSERT1(hio, send, ii); + res->hr_stat_flush++; break; } + pjdlog_debug(2, + "ggate_recv: (%p) Moving request to the send queues.", hio); + refcount_init(&hio->hio_countdown, ncomps); + for (ii = ncomp; ii < ncomps; ii++) + QUEUE_INSERT1(hio, send, ii); } /* NOTREACHED */ return (NULL); @@ -1288,6 +1325,11 @@ local_send_thread(void *arg) ret, (intmax_t)ggio->gctl_length); } else { hio->hio_errors[ncomp] = 0; + if (hio->hio_replication == + HAST_REPLICATION_ASYNC) { + ggio->gctl_error = 0; + write_complete(res, hio); + } } break; case BIO_DELETE: @@ -1322,18 +1364,18 @@ local_send_thread(void *arg) } break; } - if (refcount_release(&hio->hio_countdown)) { - if (ISSYNCREQ(hio)) { - mtx_lock(&sync_lock); - SYNCREQDONE(hio); - mtx_unlock(&sync_lock); - cv_signal(&sync_cond); - } else { - pjdlog_debug(2, - "local_send: (%p) Moving request to the done queue.", - hio); - QUEUE_INSERT2(hio, done); - } + if (!refcount_release(&hio->hio_countdown)) + continue; + if (ISSYNCREQ(hio)) { + mtx_lock(&sync_lock); + SYNCREQDONE(hio); + mtx_unlock(&sync_lock); + cv_signal(&sync_cond); + } else { + pjdlog_debug(2, + "local_send: (%p) Moving request to the done queue.", + hio); + QUEUE_INSERT2(hio, done); } } /* NOTREACHED */ @@ -1456,9 +1498,6 @@ remote_send_thread(void *arg) /* Move failed request immediately to the done queue. */ goto done_queue; } - pjdlog_debug(2, - "remote_send: (%p) Moving request to the recv queue.", - hio); /* * Protect connection from disappearing. */ @@ -1473,6 +1512,9 @@ remote_send_thread(void *arg) * in different order we can get reply before we move request * to recv queue. */ + pjdlog_debug(2, + "remote_send: (%p) Moving request to the recv queue.", + hio); mtx_lock(&hio_recv_list_lock[ncomp]); wakeup = TAILQ_EMPTY(&hio_recv_list[ncomp]); TAILQ_INSERT_TAIL(&hio_recv_list[ncomp], hio, hio_next[ncomp]); @@ -1492,7 +1534,8 @@ remote_send_thread(void *arg) * it immediately to the done queue. */ mtx_lock(&hio_recv_list_lock[ncomp]); - TAILQ_REMOVE(&hio_recv_list[ncomp], hio, hio_next[ncomp]); + TAILQ_REMOVE(&hio_recv_list[ncomp], hio, + hio_next[ncomp]); mtx_unlock(&hio_recv_list_lock[ncomp]); goto done_queue; } @@ -1558,6 +1601,7 @@ remote_recv_thread(void *arg) &hio_recv_list_lock[ncomp]); } mtx_unlock(&hio_recv_list_lock[ncomp]); + rw_rlock(&hio_remote_lock[ncomp]); if (!ISCONNECTED(res, ncomp)) { rw_unlock(&hio_remote_lock[ncomp]); @@ -1602,16 +1646,16 @@ remote_recv_thread(void *arg) nv_free(nv); continue; } + ggio = &hio->hio_ggio; error = nv_get_int16(nv, "error"); if (error != 0) { /* Request failed on remote side. */ hio->hio_errors[ncomp] = error; - reqlog(LOG_WARNING, 0, &hio->hio_ggio, + reqlog(LOG_WARNING, 0, ggio, "Remote request failed (%s): ", strerror(error)); nv_free(nv); goto done_queue; } - ggio = &hio->hio_ggio; switch (ggio->gctl_cmd) { case BIO_READ: rw_rlock(&hio_remote_lock[ncomp]); @@ -1642,18 +1686,18 @@ remote_recv_thread(void *arg) hio->hio_errors[ncomp] = 0; nv_free(nv); done_queue: - if (refcount_release(&hio->hio_countdown)) { - if (ISSYNCREQ(hio)) { - mtx_lock(&sync_lock); - SYNCREQDONE(hio); - mtx_unlock(&sync_lock); - cv_signal(&sync_cond); - } else { - pjdlog_debug(2, - "remote_recv: (%p) Moving request to the done queue.", - hio); - QUEUE_INSERT2(hio, done); - } + if (!refcount_release(&hio->hio_countdown)) + continue; + if (ISSYNCREQ(hio)) { + mtx_lock(&sync_lock); + SYNCREQDONE(hio); + mtx_unlock(&sync_lock); + cv_signal(&sync_cond); + } else { + pjdlog_debug(2, + "remote_recv: (%p) Moving request to the done queue.", + hio); + QUEUE_INSERT2(hio, done); } } /* NOTREACHED */ @@ -1669,7 +1713,7 @@ ggate_send_thread(void *arg) struct hast_resource *res = arg; struct g_gate_ctl_io *ggio; struct hio *hio; - unsigned int ii, ncomp, ncomps; + unsigned int ii, ncomps; ncomps = HAST_NCOMPONENTS; @@ -1719,28 +1763,14 @@ ggate_send_thread(void *arg) if (range_sync_wait) cv_signal(&range_sync_cond); mtx_unlock(&range_lock); - /* - * Bump local count if this is first write after - * connection failure with remote node. - */ - ncomp = 1; - rw_rlock(&hio_remote_lock[ncomp]); - if (!ISCONNECTED(res, ncomp)) { - mtx_lock(&metadata_lock); - if (res->hr_primary_localcnt == - res->hr_secondary_remotecnt) { - res->hr_primary_localcnt++; - pjdlog_debug(1, - "Increasing localcnt to %ju.", - (uintmax_t)res->hr_primary_localcnt); - (void)metadata_write(res); - } - mtx_unlock(&metadata_lock); + if (!hio->hio_done) + write_complete(res, hio); + } else { + if (ioctl(res->hr_ggatefd, G_GATE_CMD_DONE, ggio) < 0) { + primary_exit(EX_OSERR, + "G_GATE_CMD_DONE failed"); } - rw_unlock(&hio_remote_lock[ncomp]); } - if (ioctl(res->hr_ggatefd, G_GATE_CMD_DONE, ggio) < 0) - primary_exit(EX_OSERR, "G_GATE_CMD_DONE failed"); pjdlog_debug(2, "ggate_send: (%p) Moving request to the free queue.", hio); QUEUE_INSERT2(hio, free); @@ -1893,6 +1923,8 @@ sync_thread(void *arg __unused) ggio->gctl_offset = offset; ggio->gctl_length = length; ggio->gctl_error = 0; + hio->hio_done = false; + hio->hio_replication = res->hr_replication; for (ii = 0; ii < ncomps; ii++) hio->hio_errors[ii] = EINVAL; reqlog(LOG_DEBUG, 2, ggio, "sync: (%p) Sending sync request: ", @@ -1965,7 +1997,7 @@ sync_thread(void *arg __unused) } mtx_unlock(&metadata_lock); - pjdlog_debug(2, "sync: (%p) Moving request to the send queues.", + pjdlog_debug(2, "sync: (%p) Moving request to the send queue.", hio); refcount_init(&hio->hio_countdown, 1); QUEUE_INSERT1(hio, send, ncomp); @@ -2081,8 +2113,7 @@ primary_config_reload(struct hast_resour * Don't bother if we need to reconnect. */ if ((modified & MODIFIED_TIMEOUT) != 0 && - (modified & (MODIFIED_REMOTEADDR | MODIFIED_SOURCEADDR | - MODIFIED_REPLICATION)) == 0) { + (modified & (MODIFIED_REMOTEADDR | MODIFIED_SOURCEADDR)) == 0) { for (ii = 0; ii < ncomps; ii++) { if (!ISREMOTE(ii)) continue; @@ -2104,8 +2135,7 @@ primary_config_reload(struct hast_resour } } } - if ((modified & (MODIFIED_REMOTEADDR | MODIFIED_SOURCEADDR | - MODIFIED_REPLICATION)) != 0) { + if ((modified & (MODIFIED_REMOTEADDR | MODIFIED_SOURCEADDR)) != 0) { for (ii = 0; ii < ncomps; ii++) { if (!ISREMOTE(ii)) continue; Modified: user/adrian/if_ath_tx/sbin/hastd/secondary.c ============================================================================== --- user/adrian/if_ath_tx/sbin/hastd/secondary.c Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sbin/hastd/secondary.c Sat Oct 29 06:55:57 2011 (r226899) @@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$"); struct hio { uint64_t hio_seq; int hio_error; - struct nv *hio_nv; void *hio_data; uint8_t hio_cmd; uint64_t hio_offset; @@ -128,6 +127,17 @@ static void *send_thread(void *arg); } while (0) static void +hio_clear(struct hio *hio) +{ + + hio->hio_seq = 0; + hio->hio_error = 0; + hio->hio_cmd = HIO_UNDEF; + hio->hio_offset = 0; + hio->hio_length = 0; +} + +static void init_environment(void) { struct hio *hio; @@ -156,13 +166,13 @@ init_environment(void) "Unable to allocate memory (%zu bytes) for hio request.", sizeof(*hio)); } - hio->hio_error = 0; hio->hio_data = malloc(MAXPHYS); if (hio->hio_data == NULL) { pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory (%zu bytes) for gctl_data.", (size_t)MAXPHYS); } + hio_clear(hio); TAILQ_INSERT_HEAD(&hio_free_list, hio, hio_next); } } @@ -268,6 +278,7 @@ init_remote(struct hast_resource *res, s } else if (res->hr_resuid != resuid) { char errmsg[256]; + free(map); (void)snprintf(errmsg, sizeof(errmsg), "Resource unique ID mismatch (primary=%ju, secondary=%ju).", (uintmax_t)resuid, (uintmax_t)res->hr_resuid); @@ -280,13 +291,13 @@ init_remote(struct hast_resource *res, s nv_free(nvout); exit(EX_CONFIG); } else if ( - /* Is primary is out-of-date? */ + /* Is primary out-of-date? */ (res->hr_secondary_localcnt > res->hr_primary_remotecnt && res->hr_secondary_remotecnt == res->hr_primary_localcnt) || - /* Nodes are more or less in sync? */ + /* Are the nodes more or less in sync? */ (res->hr_secondary_localcnt == res->hr_primary_remotecnt && res->hr_secondary_remotecnt == res->hr_primary_localcnt) || - /* Is secondary is out-of-date? */ + /* Is secondary out-of-date? */ (res->hr_secondary_localcnt == res->hr_primary_remotecnt && res->hr_secondary_remotecnt < res->hr_primary_localcnt)) { /* @@ -315,11 +326,17 @@ init_remote(struct hast_resource *res, s /* * Not good, we have split-brain condition. */ + free(map); pjdlog_error("Split-brain detected, exiting."); nv_add_string(nvout, "Split-brain condition!", "errmsg"); - free(map); - map = NULL; - mapsize = 0; + if (hast_proto_send(res, res->hr_remotein, nvout, NULL, 0) < 0) { + pjdlog_exit(EX_TEMPFAIL, "Unable to send response to %s", + res->hr_remoteaddr); + } + nv_free(nvout); + /* Exit on split-brain. */ + event_send(res, EVENT_SPLITBRAIN); + exit(EX_CONFIG); } else /* if (res->hr_secondary_localcnt < res->hr_primary_remotecnt || res->hr_primary_localcnt < res->hr_secondary_remotecnt) */ { /* @@ -358,12 +375,6 @@ init_remote(struct hast_resource *res, s if (proto_recv(res->hr_remotein, NULL, 0) == -1) pjdlog_errno(LOG_WARNING, "Unable to set connection direction"); #endif - if (res->hr_secondary_localcnt > res->hr_primary_remotecnt && - res->hr_primary_localcnt > res->hr_secondary_remotecnt) { - /* Exit on split-brain. */ - event_send(res, EVENT_SPLITBRAIN); - exit(EX_CONFIG); - } } void @@ -508,15 +519,23 @@ reqlog(int loglevel, int debuglevel, int } static int -requnpack(struct hast_resource *res, struct hio *hio) +requnpack(struct hast_resource *res, struct hio *hio, struct nv *nv) { - hio->hio_cmd = nv_get_uint8(hio->hio_nv, "cmd"); + hio->hio_cmd = nv_get_uint8(nv, "cmd"); if (hio->hio_cmd == 0) { pjdlog_error("Header contains no 'cmd' field."); hio->hio_error = EINVAL; goto end; } + if (hio->hio_cmd != HIO_KEEPALIVE) { + hio->hio_seq = nv_get_uint64(nv, "seq"); + if (hio->hio_seq == 0) { + pjdlog_error("Header contains no 'seq' field."); + hio->hio_error = EINVAL; + goto end; + } + } switch (hio->hio_cmd) { case HIO_FLUSH: case HIO_KEEPALIVE: @@ -524,14 +543,14 @@ requnpack(struct hast_resource *res, str case HIO_READ: case HIO_WRITE: case HIO_DELETE: - hio->hio_offset = nv_get_uint64(hio->hio_nv, "offset"); - if (nv_error(hio->hio_nv) != 0) { + hio->hio_offset = nv_get_uint64(nv, "offset"); + if (nv_error(nv) != 0) { pjdlog_error("Header is missing 'offset' field."); hio->hio_error = EINVAL; goto end; } - hio->hio_length = nv_get_uint64(hio->hio_nv, "length"); - if (nv_error(hio->hio_nv) != 0) { + hio->hio_length = nv_get_uint64(nv, "length"); + if (nv_error(nv) != 0) { pjdlog_error("Header is missing 'length' field."); hio->hio_error = EINVAL; goto end; @@ -600,16 +619,18 @@ recv_thread(void *arg) { struct hast_resource *res = arg; struct hio *hio; + struct nv *nv; for (;;) { pjdlog_debug(2, "recv: Taking free request."); QUEUE_TAKE(free, hio); pjdlog_debug(2, "recv: (%p) Got request.", hio); - if (hast_proto_recv_hdr(res->hr_remotein, &hio->hio_nv) < 0) { + if (hast_proto_recv_hdr(res->hr_remotein, &nv) < 0) { secondary_exit(EX_TEMPFAIL, "Unable to receive request header"); } - if (requnpack(res, hio) != 0) { + if (requnpack(res, hio, nv) != 0) { + nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the send queue.", hio); @@ -629,23 +650,30 @@ recv_thread(void *arg) case HIO_FLUSH: res->hr_stat_flush++; break; + case HIO_KEEPALIVE: + break; + default: + PJDLOG_ABORT("Unexpected command (cmd=%hhu).", + hio->hio_cmd); } reqlog(LOG_DEBUG, 2, -1, hio, "recv: (%p) Got request header: ", hio); if (hio->hio_cmd == HIO_KEEPALIVE) { + nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the free queue.", hio); - nv_free(hio->hio_nv); + hio_clear(hio); QUEUE_INSERT(free, hio); continue; } else if (hio->hio_cmd == HIO_WRITE) { - if (hast_proto_recv_data(res, res->hr_remotein, - hio->hio_nv, hio->hio_data, MAXPHYS) < 0) { + if (hast_proto_recv_data(res, res->hr_remotein, nv, + hio->hio_data, MAXPHYS) < 0) { secondary_exit(EX_TEMPFAIL, "Unable to receive request data"); } } + nv_free(nv); pjdlog_debug(2, "recv: (%p) Moving request to the disk queue.", hio); QUEUE_INSERT(disk, hio); @@ -752,6 +780,9 @@ disk_thread(void *arg) hio->hio_error = 0; } break; + default: + PJDLOG_ABORT("Unexpected command (cmd=%hhu).", + hio->hio_cmd); } if (logerror && hio->hio_error != 0) { reqlog(LOG_ERR, 0, hio->hio_error, hio, @@ -783,7 +814,7 @@ send_thread(void *arg) reqlog(LOG_DEBUG, 2, -1, hio, "send: (%p) Got request: ", hio); nvout = nv_alloc(); /* Copy sequence number. */ - nv_add_uint64(nvout, nv_get_uint64(hio->hio_nv, "seq"), "seq"); + nv_add_uint64(nvout, hio->hio_seq, "seq"); switch (hio->hio_cmd) { case HIO_READ: if (hio->hio_error == 0) { @@ -814,8 +845,7 @@ send_thread(void *arg) nv_free(nvout); pjdlog_debug(2, "send: (%p) Moving request to the free queue.", hio); - nv_free(hio->hio_nv); - hio->hio_error = 0; + hio_clear(hio); QUEUE_INSERT(free, hio); } /* NOTREACHED */ Modified: user/adrian/if_ath_tx/sys/amd64/amd64/pmap.c ============================================================================== --- user/adrian/if_ath_tx/sys/amd64/amd64/pmap.c Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sys/amd64/amd64/pmap.c Sat Oct 29 06:55:57 2011 (r226899) @@ -1635,7 +1635,6 @@ int pmap_pinit(pmap_t pmap) { vm_page_t pml4pg; - static vm_pindex_t color; int i; PMAP_LOCK_INIT(pmap); @@ -1643,8 +1642,8 @@ pmap_pinit(pmap_t pmap) /* * allocate the page directory page */ - while ((pml4pg = vm_page_alloc(NULL, color++, VM_ALLOC_NOOBJ | - VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL) + while ((pml4pg = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | + VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL) VM_WAIT; pmap->pm_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pml4pg)); @@ -2188,7 +2187,6 @@ get_pv_entry(pmap_t pmap, int try) { static const struct timeval printinterval = { 60, 0 }; static struct timeval lastprint; - static vm_pindex_t colour; struct vpgqueues *pq; int bit, field; pv_entry_t pv; @@ -2228,7 +2226,7 @@ retry: } } /* No free items, allocate another chunk */ - m = vm_page_alloc(NULL, colour, (pq == &vm_page_queues[PQ_ACTIVE] ? + m = vm_page_alloc(NULL, 0, (pq == &vm_page_queues[PQ_ACTIVE] ? VM_ALLOC_SYSTEM : VM_ALLOC_NORMAL) | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED); if (m == NULL) { @@ -2255,7 +2253,6 @@ retry: } PV_STAT(pc_chunk_count++); PV_STAT(pc_chunk_allocs++); - colour++; dump_add_page(m->phys_addr); pc = (void *)PHYS_TO_DMAP(m->phys_addr); pc->pc_pmap = pmap; Modified: user/adrian/if_ath_tx/sys/amd64/amd64/trap.c ============================================================================== --- user/adrian/if_ath_tx/sys/amd64/amd64/trap.c Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sys/amd64/amd64/trap.c Sat Oct 29 06:55:57 2011 (r226899) @@ -104,13 +104,6 @@ dtrace_trap_func_t dtrace_trap_func; dtrace_doubletrap_func_t dtrace_doubletrap_func; /* - * This is a hook which is initialised by the systrace module - * when it is loaded. This keeps the DTrace syscall provider - * implementation opaque. - */ -systrace_probe_func_t systrace_probe_func; - -/* * These hooks are necessary for the pid, usdt and fasttrap providers. */ dtrace_fasttrap_probe_ptr_t dtrace_fasttrap_probe_ptr; Modified: user/adrian/if_ath_tx/sys/amd64/amd64/uma_machdep.c ============================================================================== --- user/adrian/if_ath_tx/sys/amd64/amd64/uma_machdep.c Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sys/amd64/amd64/uma_machdep.c Sat Oct 29 06:55:57 2011 (r226899) @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); void * uma_small_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) { - static vm_pindex_t colour; vm_page_t m; vm_paddr_t pa; void *va; @@ -50,13 +49,13 @@ uma_small_alloc(uma_zone_t zone, int byt *flags = UMA_SLAB_PRIV; if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT) - pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED; + pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED; else - pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED; + pflags = VM_ALLOC_SYSTEM | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED; if (wait & M_ZERO) pflags |= VM_ALLOC_ZERO; for (;;) { - m = vm_page_alloc(NULL, colour++, pflags | VM_ALLOC_NOOBJ); + m = vm_page_alloc(NULL, 0, pflags); if (m == NULL) { if (wait & M_NOWAIT) return (NULL); Modified: user/adrian/if_ath_tx/sys/amd64/conf/GENERIC ============================================================================== --- user/adrian/if_ath_tx/sys/amd64/conf/GENERIC Sat Oct 29 06:33:12 2011 (r226898) +++ user/adrian/if_ath_tx/sys/amd64/conf/GENERIC Sat Oct 29 06:55:57 2011 (r226899) @@ -65,8 +65,11 @@ options MAC # TrustedBSD MAC Framewor #options KDTRACE_HOOKS # Kernel DTrace hooks options INCLUDE_CONFIG_FILE # Include this file in kernel *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201110290655.p9T6twrP098676>