tvarious bug fixes - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 1a8f27c35024af7b4ed857a388d20f0a4a560db0
 (DIR) parent a796abef1632f379ced703b1b2e691d8f63436e2
 (HTM) Author: rsc <devnull@localhost>
       Date:   Fri, 14 May 2004 15:14:21 +0000
       
       various bug fixes
       
       Diffstat:
         A man/man1/graph.1                    |     148 +++++++++++++++++++++++++++++++
         A man/man1/plot.1                     |      61 +++++++++++++++++++++++++++++++
         A man/man5/venti.conf.5               |      87 +++++++++++++++++++++++++++++++
         A man/man8/venti.8                    |     232 ++++++++++++++++++++++++++++++
         A man/man8/ventiaux.8                 |     504 +++++++++++++++++++++++++++++++
         A sky/.cvsignore                      |       2 ++
         M src/cmd/acme/exec.c                 |       2 +-
         M src/cmd/acme/rows.c                 |       4 +++-
         M src/cmd/acme/text.c                 |       5 ++++-
         A src/lib9/rendez-futex.c             |     167 +++++++++++++++++++++++++++++++
         M src/libdraw/md-alloc.c              |       8 +++++++-
         M src/libfs/fs.c                      |      14 +++++++++++---
         M src/libfs/ns.c                      |       3 +++
         M src/libthread/fdwait.c              |       8 ++++++--
       
       14 files changed, 1236 insertions(+), 9 deletions(-)
       ---
 (DIR) diff --git a/man/man1/graph.1 b/man/man1/graph.1
       t@@ -0,0 +1,148 @@
       +.TH GRAPH 1
       +.CT 1 numbers graphics
       +.SH NAME
       +graph \- draw a graph
       +.SH SYNOPSIS
       +.B graph
       +[
       +.I option ...
       +]
       +.SH DESCRIPTION
       +.I Graph
       +with no options takes pairs of numbers from the
       +standard input as abscissas
       +.RI ( x -values)
       +and ordinates
       +.RI ( y -values)
       +of a graph.
       +Successive points are connected by straight lines.
       +The graph is encoded on the standard output
       +for display by
       +.IR  plot (1)
       +filters.
       +.PP
       +If an ordinate is followed by
       +a nonnumeric string, that string is printed as a
       +label beginning on the point.
       +Labels may be surrounded with quotes
       +.L
       +" "
       +in which case they may be empty or contain blanks
       +and numbers;
       +labels never contain newlines.
       +.PP
       +The following options are recognized,
       +each as a separate argument.
       +.TP
       +.B  -a
       +Supply abscissas automatically; no
       +.IR x -values
       +appear in the input.
       +Spacing is given by the next
       +argument (default 1).
       +A second optional argument is the starting point for
       +automatic abscissas (default 0, or 1
       +with a log scale in
       +.IR x ,
       +or the lower limit given by
       +.BR -x ).
       +.TP
       +.B  -b
       +Break (disconnect) the graph after each label in the input.
       +.TP
       +.B  -c
       +Character string given by next argument
       +is default label for each point.
       +.TP
       +.B  -g
       +Next argument is grid style,
       +0 no grid, 1 frame with ticks, 2 full grid (default).
       +.TP
       +.B  -l
       +Next argument is a legend to title the graph.
       +Grid ranges
       +are automatically printed as part
       +of the title unless a
       +.B -s
       +option is present.
       +.TP
       +.B  -m
       +Next argument is mode (style)
       +of connecting lines:
       +0 disconnected, 1 connected.
       +Some devices give distinguishable line styles
       +for other small integers.
       +Mode \-1 (default) begins with style 1 and
       +rotates styles for successive curves under option
       +.BR -o .
       +.TP
       +.B -o
       +(Overlay.)
       +The ordinates for
       +.I n
       +superposed curves appear in the input
       +with each abscissa value.
       +The next argument is
       +.IR n .
       +.TP
       +.B  -s
       +Save screen; no new page for this graph.
       +.TP
       +.B -x l
       +If
       +.B l
       +is present,
       +.IR x -axis
       +is logarithmic.
       +Next 1 (or 2) arguments are lower (and upper)
       +.I x
       +limits.
       +Third argument, if present, is grid spacing on
       +.I x
       +axis.
       +Normally these quantities are determined automatically.
       +.TP
       +.B -y l
       +Similarly for
       +.IR y .
       +.TP
       +.B -e
       +Make automatically determined
       +.I x
       +and
       +.I y
       +scales equal.
       +.TP
       +.B  -h
       +Next argument is fraction of space for height.
       +.TP
       +.B  -w
       +Similarly for width.
       +.TP
       +.B  -r
       +Next argument is fraction of space to move right before plotting.
       +.TP
       +.B  -u
       +Similarly to move up before plotting.
       +.TP
       +.B  -t
       +Transpose horizontal and vertical axes.
       +(Option
       +.B -a
       +now applies to the vertical axis.)
       +.PP
       +If a specified lower limit exceeds the upper limit,
       +the axis
       +is reversed.
       +.SH SOURCE
       +.B /sys/src/cmd/graph
       +.SH "SEE ALSO"
       +.IR plot (1), 
       +.IR grap (1)
       +.SH BUGS
       +Segments that run out of bounds are dropped, not windowed.
       +Logarithmic axes may not be reversed.
       +Option
       +.B -e
       +actually makes automatic limits, rather than automatic scaling,
       +equal.
 (DIR) diff --git a/man/man1/plot.1 b/man/man1/plot.1
       t@@ -0,0 +1,61 @@
       +.TH PLOT 1
       +.SH NAME
       +plot \- graphics filter
       +.SH SYNOPSIS
       +.B plot
       +[
       +.I file ...
       +]
       +.SH DESCRIPTION
       +.I Plot
       +interprets plotting instructions (see
       +.IR  plot (6))
       +from the
       +.I files
       +or standard input,
       +drawing the results in a newly created
       +.IR rio (1)
       +window.
       +Plot persists until a newline is typed in the window.
       +Various options may be interspersed with the
       +.I file
       +arguments; they take effect at the given point in processing.
       +Options are:
       +.TP "\w'\fL-g \fIgrade\fLXX'u"
       +.B -d
       +Double buffer: accumulate the plot off-screen and write to the screen all at once
       +when an erase command is encountered or at end of file.
       +.TP
       +.B -e
       +Erase the screen.
       +.TP
       +.BI -c " col"
       +Set the foreground color (see
       +.IR plot (6)
       +for color names).
       +.TP
       +.BI -f " fill"
       +Set the background color.
       +.TP
       +.BI -g " grade"
       +Set the quality factor for arcs.
       +Higher grades give better quality.
       +.TP
       +.BI -p " col"
       +Set the pen color.
       +.TP
       +.BI -w
       +Pause until a newline is typed on standard input.
       +.TP
       +.B -C
       +Close the current plot.
       +.TP
       +.B -W " x0,y0,x1,y1"
       +Specify the bounding rectangle of plot's window.
       +By default it uses a 512×512 window in the
       +middle of the screen.
       +.SH SOURCE
       +.B /sys/src/cmd/plot
       +.SH "SEE ALSO"
       +.IR rio (1),
       +.IR plot (6)
 (DIR) diff --git a/man/man5/venti.conf.5 b/man/man5/venti.conf.5
       t@@ -0,0 +1,87 @@
       +.TH VENTI.CONF 6
       +.SH NAME
       +venti.conf  \- a venti configuration file
       +.SH DESCRIPTION
       +A venti configuration file enumerates the various index sections and
       +arenas that constitute a venti system.
       +The components are indicated by the name of the file, typically
       +a disk partition, in which they reside.  The configuration
       +file is the only location that file names are used.  Internally,
       +venti uses the names assigned when the components were formatted
       +with 
       +.I fmtarenas
       +or 
       +.I fmtisect
       +(see
       +.IR ventiaux (8)).
       +In particular, by changing the configuration a
       +component can be copied to a different file.
       +.PP
       +The configuration file consists of lines in the form described below.
       +Lines starting with
       +.B #
       +are comments.
       +.TP
       +.BI index " name
       +Names the index for the system.
       +.TP
       +.BI arenas " file
       +.I File
       +contains a collection of arenas, formatted using
       +.IR fmtarenas .
       +.TP
       +.BI isect " file
       +.I File
       +contains an index section, formatted using
       +.IR fmtisect .
       +.PP
       +After formatting a venti system using
       +.IR fmtindex ,
       +the order of arenas and index sections should not be changed.
       +Additional arenas can be appended to the configuration.
       +.PP
       +The configuration file optionally holds configuration parameters
       +for the venti server itself.
       +These are:
       +.TP
       +.BI mem " cachesize
       +.TP
       +.BI bcmem " blockcachesize
       +.TP
       +.BI icmem " indexcachesize
       +.TP
       +.BI addr " ventiaddress
       +.TP
       +.BI httpaddr " httpaddress
       +.TP
       +.B queuewrites
       +.PD
       +See 
       +.IR venti (8)
       +for descriptions of these variables.
       +.SH EXAMPLE
       +.EX
       +# a sample venti configuration file
       +#
       +# formatted with
       +#        venti/fmtarenas arena. /tmp/disks/arenas
       +#         venti/fmtisect isect0 /tmp/disks/isect0
       +#         venti/fmtisect isect1 /tmp/disks/isect1
       +#        venti/fmtindex venti.conf
       +#
       +# server is started with
       +#        venti/venti
       +
       +# the name of the index
       +index main
       +
       +# the index sections
       +isect /tmp/disks/isect0
       +isect /tmp/disks/isect1
       +
       +# the arenas
       +arenas /tmp/disks/arenas
       +.EE
       +.SH "SEE ALSO"
       +.IR venti (8),
       +.IR ventiaux (8)
 (DIR) diff --git a/man/man8/venti.8 b/man/man8/venti.8
       t@@ -0,0 +1,232 @@
       +.TH VENTI 8
       +.SH NAME
       +venti \- an archival block storage server
       +.SH SYNOPSIS
       +.B venti/venti
       +[
       +.B -dsw
       +]
       +[
       +.B -a
       +.I ventiaddress
       +]
       +[
       +.B -B
       +.I blockcachesize
       +]
       +[
       +.B -c
       +.I config
       +]
       +[
       +.B -C
       +.I cachesize
       +]
       +[
       +.B -h
       +.I httpaddress
       +]
       +[
       +.B -I
       +.I icachesize
       +]
       +.PP
       +.B venti/sync
       +[
       +.B -h
       +.I host
       +]
       +.SH DESCRIPTION
       +.I Venti
       +is a block storage server intended for archival data.
       +In a Venti server,
       +the SHA1 hash of a block's contents acts as the block
       +identifier for read and write operations.
       +This approach enforces a write-once policy, preventing accidental or
       +malicious destruction of data.  In addition, duplicate copies of a
       +block are coalesced, reducing the consumption of storage and
       +simplifying the implementation of clients.
       +.PP
       +Storage for
       +.I venti
       +consists of a data log and an index, both of which
       +can be spread across multiple files.
       +The files containing the data log are themselves divided into self-contained sections called arenas.
       +Each arena contains a large number of data blocks and is sized to
       +facilitate operations such as copying to removable media.
       +The index provides a mapping between the a Sha1 fingerprint and
       +the location of the corresponding block in the data log.
       +.PP
       +The index and data log are typically stored on raw disk partitions.
       +To improve the robustness, the data log should be stored on
       +a device that provides RAID functionality.  The index does
       +not require such protection, since if necessary, it can
       +can be regenerated from the data log.
       +The performance of
       +.I venti
       +is typically limited to the random access performance
       +of the index.  This performance can be improved by spreading the
       +index accross multiple disks.  
       +.PP
       +The storage for
       +.I venti
       +is initialized using
       +.IR fmtarenas ,
       +.IR fmtisect ,
       +and
       +.I fmtindex
       +(see
       +.IR ventiaux (8)).
       +A configuration file,
       +.IR venti.conf (6),
       +ties the index sections and data arenas together.
       +.PP
       +A Venti
       +server is accessed via an undocumented network protocol.
       +Two client applications are included in this distribution:
       +.IR vac (1)
       +and
       +.IR vacfs (4).
       +.I Vac
       +copies files from a Plan 9 file system to Venti, creating an
       +archive and returning the fingerprint of the root.
       +This archive can be mounted in Plan 9 using 
       +.IR vacfs .
       +These two commands enable a rudimentary backup system.
       +A future release will include a Plan 9 file system that uses
       +Venti as a replacement for the WORM device of 
       +.IR fs (4).
       +.PP
       +The
       +.I venti
       +server provides rudimentary status information via
       +a built-in http server.  The URL files it serves are:
       +.TP
       +.B stats
       +Various internal statistics.
       +.TP
       +.B index
       +An enumeration of the index sections and all non empty arenas, including various statistics.
       +.TP
       +.B storage
       +A summary of the state of the data log.
       +.TP
       +.B xindex
       +An enumeration of the index sections and all non empty arenas, in XML format.
       +.PP
       +Several auxiliary utilities (see
       +.IR ventiaux (8))
       +aid in maintaining the storage for Venti.
       +With the exception of
       +.I rdarena ,
       +these utilities should generally be run after killing the
       +.I venti
       +server.
       +The utilities are:
       +.TP
       +.I checkarenas
       +Check the integrity, and optionally fix, Venti arenas.
       +.TP
       +.I checkindex
       +Check the integrity, and optionally fix, a Venti index.
       +.TP
       +.I buildindex
       +Rebuild a Venti index from scratch.
       +.TP
       +.I rdarena
       +Extract a Venti arena and write to standard output.
       +.PD
       +.PP
       +Options to 
       +.I venti
       +are:
       +.TP
       +.BI -a " ventiaddress
       +The network address on which the server listens for incoming connections.
       +The default is
       +.LR tcp!*!venti .
       +.TP
       +.BI -B " blockcachesize
       +The size, in bytes, of memory allocated to caching raw disk blocks.
       +.TP
       +.BI -c " config
       +Specifies the
       +Venti
       +configuration file.
       +Defaults to
       +.LR venti.conf .
       +.TP
       +.BI -C " cachesize
       +The size, in bytes, of memory allocated to caching 
       +Venti
       +blocks.
       +.TP
       +.BI -d
       +Produce various debugging information on standard error.
       +.TP
       +.BI -h " httpaddress
       +The network address of Venti's built-in
       +http
       +server.
       +The default is
       +.LR tcp!*!http .
       +.TP
       +.BI -I " icachesize
       +The size, in bytes, of memory allocated to caching the index mapping fingerprints
       +to locations in 
       +.IR venti 's
       +data log.
       +.TP
       +.B -s
       +Do not run in the background.
       +Normally,
       +the foreground process will exit once the Venti server
       +is initialized and ready for connections.
       +.TP
       +.B -w
       +Enable write buffering.  This option increase the performance of writes to
       +.I venti
       +at the cost of returning success to the client application before the
       +data has been written to disk.
       +The server implements a
       +.I sync
       +rpc that waits for completion of all the writes buffered at the time
       +the rpc was received.
       +Applications such as
       +.IR vac (1)
       +and the
       +.I sync
       +command described below
       +use this rpc to make sure that the data is correctly written to disk.
       +Use of this option is recommended.
       +.PD
       +.PP
       +The units for the various cache sizes above can be specified by appending a
       +.LR k ,
       +.LR m ,
       +or
       +.LR g
       +to indicate kilobytes, megabytes, or gigabytes respectively.
       +The command line options override options found in the
       +.IR venti.conf (6)
       +file.
       +.PP
       +.I Sync
       +connects to a running Venti server and executes a sync rpc
       +(described with the
       +.B -w
       +option above). 
       +If sync exits successfully, it means that all writes buffered at the
       +time the command was issued are now on disk.
       +.SH SOURCE
       +.B /sys/src/cmd/venti
       +.SH "SEE ALSO"
       +.IR venti.conf (6),
       +.IR ventiaux (8),
       +.IR vac (1),
       +.IR vacfs (4).
       +.br
       +Sean Quinlan and Sean Dorward,
       +``Venti: a new approach to archival storage'',
       +.I "Usenix Conference on File and Storage Technologies" ,
       +2002.
 (DIR) diff --git a/man/man8/ventiaux.8 b/man/man8/ventiaux.8
       t@@ -0,0 +1,504 @@
       +.TH VENTIAUX 8
       +.SH NAME
       +buildindex,
       +checkarenas,
       +checkindex,
       +conf,
       +copy,
       +fmtarenas,
       +fmtindex,
       +fmtisect,
       +rdarena,
       +rdarenablocks,
       +read,
       +wrarenablocks,
       +write \- Venti maintenance and debugging commands
       +.SH SYNOPSIS
       +.B venti/buildindex
       +[
       +.B -B
       +.I blockcachesize
       +]
       +[
       +.B -Z
       +]
       +.I venti.config
       +.I tmp
       +.PP
       +.B venti/checkarenas
       +[
       +.B -afv 
       +]
       +.I file
       +.PP
       +.B venti/checkindex
       +[
       +.B -f
       +]
       +[
       +.B -B
       +.I blockcachesize
       +]
       +.I venti.config
       +.I tmp
       +.PP
       +.B venti/conf
       +[
       +.B -w
       +]
       +.I partition
       +[
       +.I configfile
       +]
       +.PP
       +.B venti/copy
       +[
       +.B -f
       +]
       +.I src
       +.I dst
       +.I score
       +[
       +.I type
       +]
       +.PP
       +.B venti/fmtarenas
       +[
       +.B -Z
       +]
       +[
       +.B -a
       +.I arenasize
       +]
       +[
       +.B -b
       +.I blocksize
       +]
       +.I name
       +.I file
       +.PP
       +.B venti/fmtindex
       +[
       +.B -a
       +]
       +.I venti.config
       +.PP
       +.B venti/fmtisect
       +[
       +.B -Z
       +]
       +[
       +.B -b
       +.I blocksize
       +]
       +.I name
       +.I file
       +.PP
       +.B venti/rdarena
       +[
       +.B -v
       +]
       +.I arenapart
       +.I arenaname
       +.PP
       +.B venti/read
       +[
       +.B -h
       +.I host
       +]
       +.I score
       +[
       +.I type
       +]
       +.PP
       +.B venti/wrarena
       +[
       +.B -o
       +.I fileoffset
       +]
       +[
       +.B -h
       +.I host
       +]
       +.I arenafile
       +[
       +.I clumpoffset
       +]
       +.PP
       +.B venti/write
       +[
       +.B -h
       +.I host
       +]
       +[
       +.B -t
       +.I type
       +]
       +[
       +.B -z
       +]
       +.SH DESCRIPTION
       +These commands aid in the setup, maintenance, and debugging of
       +Venti servers.
       +See
       +.IR venti (8)
       +and
       +.IR venti.conf (6)
       +for an overview of the data structures stored by Venti.
       +.PP
       +Note that the units for the various sizes in the following
       +commands can be specified by appending
       +.LR k ,
       +.LR m ,
       +or
       +.LR g
       +to indicate kilobytes, megabytes, or gigabytes respectively.
       +.PP
       +.I Buildindex
       +populates the index for the Venti system described in
       +.IR venti.config .
       +The index must have previously been formatted using
       +.IR fmtindex .
       +This command is typically used to build a new index for a Venti
       +system when the old index becomes too small, or to rebuild
       +an index after media failure.
       +Small errors in an index can usually be fixed with
       +.IR checkindex .
       +.PP
       +The
       +.I tmp
       +file, usually a disk partition, must be large enough to store a copy of the index.
       +This temporary space is used to perform a merge sort of index entries
       +generated by reading the arenas.
       +.PP
       +Options to 
       +.I buildindex
       +are:
       +.TP
       +.BI -B " blockcachesize
       +The amount of memory, in bytes, to use for caching raw disk accesses while running
       +.IR buildindex .
       +(This is not a property of the created index.)
       +The default is 8k.
       +.TP
       +.B -Z
       +Do not zero the index.
       +This option should only be used when it is known that the index was already zeroed.
       +.PD
       +.PP
       +.I Checkarenas
       +examines the Venti arenas contained in the given
       +.IR file .
       +The program detects various error conditions, and optionally attempts
       +to fix any errors that are found.
       +.PP
       +Options to 
       +.I checkarenas
       +are:
       +.TP
       +.B -a
       +For each arena, scan the entire data section.
       +If this option is omitted, only the end section of
       +the arena is examined.
       +.TP
       +.B -f
       +Attempt to fix any errors that are found.
       +.TP
       +.B -v
       +Increase the verbosity of output.
       +.PD
       +.PP
       +.I Checkindex
       +examines the Venti index described in
       +.IR venti.config .
       +The program detects various error conditions including:
       +blocks that are not indexed, index entries for blocks that do not exist,
       +and duplicate index entries.
       +If requested, an attempt can be made to fix errors that are found.
       +.PP
       +The
       +.I tmp
       +file, usually a disk partition, must be large enough to store a copy of the index.
       +This temporary space is used to perform a merge sort of index entries
       +generated by reading the arenas.
       +.PP
       +Options to 
       +.I checkindex
       +are:
       +.TP
       +.BI -B " blockcachesize
       +The amount of memory, in bytes, to use for caching raw disk accesses while running
       +.IR checkindex .
       +The default is 8k.
       +.TP
       +.B -f
       +Attempt to fix any errors that are found.
       +.PD
       +.PP
       +.I Fmtarenas
       +formats the given
       +.IR file ,
       +typically a disk partition, into a number of
       +Venti
       +arenas.
       +The arenas are given names of the form
       +.IR name%d ,
       +where
       +.I %d
       +is replaced with a sequential number starting at 0.
       +.PP
       +Options to 
       +.I fmtarenas
       +are:
       +.TP
       +.BI -a " arenasize
       +The arenas are of
       +.I arenasize
       +bytes.  The default is 512 megabytes, which was selected to provide a balance
       +between the number of arenas and the ability to copy an arena to external
       +media such as recordable CDs and tapes.
       +.TP
       +.BI -b " blocksize
       +The size, in bytes, for read and write operations to the file.
       +The size is recorded in the file, and is used by applications that access the arenas.
       +The default is 8k.
       +.TP
       +.B -Z
       +Do not zero the data sections of the arenas.
       +Using this option reduces the formatting time
       +but should only be used when it is known that the file was already zeroed.
       +.PD
       +.I Fmtindex
       +takes the
       +.IR venti.conf (6)
       +file
       +.I venti.config
       +and initializes the index sections to form a usable index structure.
       +The arena files and index sections must have previously been formatted
       +using 
       +.I fmtarenas
       +and 
       +.I fmtisect
       +respectively.
       +.PP
       +The function of a Venti index is to map a SHA1 fingerprint to a location
       +in the data section of one of the arenas.  The index is composed of
       +blocks, each of which contains the mapping for a fixed range of possible
       +fingerprint values.
       +.I Fmtindex
       +determines the mapping between SHA1 values and the blocks
       +of the collection of index sections.  Once this mapping has been determined,
       +it cannot be changed without rebuilding the index. 
       +The basic assumption in the current implementation is that the index
       +structure is sufficiently empty that individual blocks of the index will rarely
       +overflow.  The total size of the index should be about 2% to 10% of
       +the total size of the arenas, but the exact depends both the index block size
       +and the compressed size of block stored to Venti.
       +.PP
       +.I Fmtindex
       +also computes a mapping between a linear address space and
       +the data section of the collection of arenas.  The
       +.B -a
       +option can be used to add additional arenas to an index.
       +To use this feature,
       +add the new arenas to
       +.I venti.config
       +after the existing arenas and then run
       +.I fmtindex
       +.BR -a .
       +.PP
       +A copy of the above mappings is stored in the header for each of the index sections.
       +These copies enable
       +.I buildindex
       +to restore a single index section without rebuilding the entire index.
       +.PP
       +.I Fmtisect
       +formats the given
       +.IR file ,
       +typically a disk partition, as a Venti index section with the specified
       +.IR name .
       +One or more formatted index sections are combined into a Venti
       +index using 
       +.IR fmtindex .
       +Each of the index sections within an index must have a unique name.
       +.PP
       +Options to 
       +.I fmtisect
       +are:
       +.TP
       +.BI -b " blocksize
       +The size, in bytes, for read and write operations to the file.
       +All the index sections within a index must have the same block size.
       +The default is 8k.
       +.TP
       +.B -Z
       +Do not zero the index.
       +Using this option reduces the formatting time
       +but should only be used when it is known that the file was already zeroed.
       +.PD
       +.PP
       +.I Rdarena
       +extracts the named
       +.I arena
       +from the arena partition
       +.I arenapart
       +and writes this arena to standard output.
       +This command is typically used to back up an arena to external media.
       +The
       +.B -v
       +option generates more verbose output on standard error.
       +.PP
       +.I Wrarena
       +writes the blocks contained in the arena
       +.I arenafile
       +(typically, the output of
       +.IR rdarena )
       +to a Venti server.
       +It is typically used to reinitialize a Venti server from backups of the arenas.
       +For example,
       +.IP
       +.EX
       +venti/rdarena /dev/sdC0/arenas arena.0 >external.media
       +venti/wrarena -h venti2 external.media
       +.EE
       +.LP
       +writes the blocks contained in
       +.B arena.0
       +to the Venti server
       +.B venti2
       +(typically not the one using
       +.BR /dev/sdC0/arenas ).
       +.PP
       +The
       +.B -o
       +option specifies that the arena starts at byte
       +.I fileoffset
       +(default
       +.BR 0 )
       +in
       +.I arenafile .
       +This is useful for reading directly from
       +the Venti arena partition:
       +.IP
       +.EX
       +venti/wrarena -h venti2 -o 335872 /dev/sdC0/arenas
       +.EE
       +.LP
       +(In this example, 335872 is the offset shown in the Venti
       +server's index list (344064) minus one block (8192).
       +You will need to substitute your own arena offsets
       +and block size.)
       +.PP
       +Finally, the optional
       +.I offset
       +argument specifies that the writing should begin with the
       +clump starting at
       +.I offset
       +within the arena.
       +.I Wrarena
       +prints the offset it stopped at (because there were no more data blocks).
       +This could be used to incrementally back up a Venti server
       +to another Venti server:
       +.IP
       +.EX
       +last=`{cat last}
       +venti/wrarena -h venti2 -o 335872 /dev/sdC0/arenas $last >output
       +awk '/^end offset/ { print $3 }' offset >last
       +.EE
       +.LP
       +Of course, one would need to add wrapper code to keep track
       +of which arenas have been processed.
       +See
       +.B /sys/src/cmd/venti/backup.example
       +for a version that does this.
       +.PP
       +.I Read
       +and
       +.I write
       +read and write blocks from a running Venti server.
       +They are intended to ease debugging of the server.
       +The default
       +.I host
       +is the environment variable
       +.BR $venti ,
       +followed by the network metaname
       +.BR $venti .
       +The
       +.I type
       +is the decimal type of block to be read or written.
       +If no 
       +.I type
       +is specified for
       +.I read ,
       +all types are tried, and a command-line is printed to
       +show the type that eventually worked.
       +If no
       +.I type
       +is specified for
       +.I write ,
       +.B VtDataType
       +(13)
       +is used.
       +.I Read
       +reads the block named by
       +.I score
       +(a SHA1 hash)
       +from the Venti server and writes it to standard output.
       +.I Write
       +reads a block from standard input and attempts to write
       +it to the Venti server.
       +If successful, it prints the score of the block on the server.
       +.PP
       +.I Copy
       +walks the entire tree of blocks rooted at
       +.I score ,
       +copying all the blocks visited during the walk from
       +the Venti server at network address
       +.I src
       +to the Venti server at network address
       +.I dst .
       +If
       +.I type
       +(a decimal block type for
       +.IR score )
       +is omitted, all types will be tried in sequence
       +until one is found that works.
       +The
       +.B -f
       +flag runs the copy in ``fast'' mode: if a block is already on
       +.IR dst ,
       +the walk does not descend below it, on the assumption that all its
       +children are also already on
       +.IR dst .
       +Without this flag, the copy often transfers many times more
       +data than necessary.
       +.PP
       +To make it easier to bootstrap servers, the configuration
       +file can be stored at the beginning of any Venti partitions using
       +.IR conf .
       +A partition so branded with a configuration file can
       +be used in place of a configuration file when invoking any
       +of the venti commands.
       +By default,
       +.I conf
       +prints the configuration stored in
       +.IR partition .
       +When invoked with the
       +.B -w
       +flag,
       +.I conf
       +reads a configuration file from 
       +.I configfile
       +(or else standard input)
       +and stores it in
       +.IR partition .
       +.SH SOURCE
       +.B /sys/src/cmd/venti
       +.SH "SEE ALSO"
       +.IR venti (8),
       +.IR venti.conf (6)
       +.SH BUGS
       +.I Buildindex
       +should allow an individual index section to be rebuilt.
       +The merge sort could be performed in the space used to store the
       +index rather than requiring a temporary file.
 (DIR) diff --git a/sky/.cvsignore b/sky/.cvsignore
       t@@ -0,0 +1,2 @@
       +*.scat
       +constelnames
 (DIR) diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c
       t@@ -1308,7 +1308,7 @@ runproc(void *argvp)
                name[e-t] = 0;
                e = utfrrune(name, '/');
                if(e)
       -                strcpy(name, e+1);
       +                memmove(name, e+1, strlen(e+1)+1);        /* strcpy but overlaps */
                strcat(name, " ");        /* add blank here for ease in waittask */
                c->name = bytetorune(name, &c->nname);
                free(name);
 (DIR) diff --git a/src/cmd/acme/rows.c b/src/cmd/acme/rows.c
       t@@ -663,12 +663,12 @@ rowload(Row *row, char *file, int initing)
                                        break;
                        wincleartag(w);
                        textinsert(&w->tag, w->tag.file->b.nc, r+n+1, nr-(n+1), TRUE);
       -                free(r);
                        if(ndumped >= 0){
                                /* simplest thing is to put it in a file and load that */
                                sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser());
                                fd = create(buf, OWRITE|ORCLOSE, 0600);
                                if(fd < 0){
       +                                free(r);
                                        warning(nil, "can't create temp file: %r\n");
                                        goto Rescue2;
                                }
       t@@ -679,6 +679,7 @@ rowload(Row *row, char *file, int initing)
                                        if(rune == '\n')
                                                line++;
                                        if(rune == (Rune)Beof){
       +                                        free(r);
                                                Bterm(bout);
                                                free(bout);
                                                close(fd);
       t@@ -696,6 +697,7 @@ rowload(Row *row, char *file, int initing)
                                winsettag(w);
                        }else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-')
                                get(&w->body, nil, nil, FALSE, XXX, nil, 0);
       +                free(r);
                        if(fontr){
                                fontx(&w->body, nil, nil, 0, 0, fontr, nfontr);
                                free(fontr);
 (DIR) diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c
       t@@ -963,8 +963,11 @@ textshow(Text *t, uint q0, uint q1, int doselect)
                int nl;
                uint q;
        
       -        if(t->what != Body)
       +        if(t->what != Body){
       +                if(doselect)
       +                        textsetselect(t, q0, q1);
                        return;
       +        }
                if(t->w!=nil && t->fr.maxlines==0)
                        colgrow(t->col, t->w, 1);
                if(doselect)
 (DIR) diff --git a/src/lib9/rendez-futex.c b/src/lib9/rendez-futex.c
       t@@ -0,0 +1,167 @@
       +/*
       +     NAME
       +          rendezvous - user level process synchronization
       +
       +     SYNOPSIS
       +          ulong rendezvous(ulong tag, ulong value)
       +
       +     DESCRIPTION
       +          The rendezvous system call allows two processes to synchro-
       +          nize and exchange a value.  In conjunction with the shared
       +          memory system calls (see segattach(2) and fork(2)), it
       +          enables parallel programs to control their scheduling.
       +
       +          Two processes wishing to synchronize call rendezvous with a
       +          common tag, typically an address in memory they share.  One
       +          process will arrive at the rendezvous first; it suspends
       +          execution until a second arrives.  When a second process
       +          meets the rendezvous the value arguments are exchanged
       +          between the processes and returned as the result of the
       +          respective rendezvous system calls.  Both processes are
       +          awakened when the rendezvous succeeds.
       +
       +          The set of tag values which two processes may use to
       +          rendezvous-their tag space-is inherited when a process
       +          forks, unless RFREND is set in the argument to rfork; see
       +          fork(2).
       +
       +          If a rendezvous is interrupted the return value is ~0, so
       +          that value should not be used in normal communication.
       +
       + * This simulates rendezvous with shared memory, pause, and SIGUSR1.
       + */
       +
       +#include <u.h>
       +typedef u32int u32;
       +#include <errno.h>
       +#include <sys/time.h>
       +#define __user
       +#include <linux/linkage.h>
       +#include <linux/futex.h>
       +#include <libc.h>
       +
       +enum
       +{
       +        VOUSHASH = 257,
       +};
       +
       +typedef struct Vous Vous;
       +struct Vous
       +{
       +        Vous *link;
       +        Lock lk;
       +        int pid;
       +        ulong val;
       +        ulong tag;
       +};
       +
       +static Vous vouspool[2048];
       +static int nvousused;
       +static Vous *vousfree;
       +static Vous *voushash[VOUSHASH];
       +static Lock vouslock;
       +
       +static Vous*
       +getvous(void)
       +{
       +        Vous *v;
       +
       +        if(vousfree){
       +                v = vousfree;
       +                vousfree = v->link;
       +        }else if(nvousused < nelem(vouspool))
       +                v = &vouspool[nvousused++];
       +        else
       +                abort();
       +        return v;
       +}
       +
       +static void
       +putvous(Vous *v)
       +{
       +        lock(&vouslock);
       +        v->link = vousfree;
       +        vousfree = v;
       +        unlock(&vouslock);
       +}
       +
       +static Vous*
       +findvous(ulong tag, ulong val, int pid)
       +{
       +        int h;
       +        Vous *v, **l;
       +
       +        lock(&vouslock);
       +        h = tag%VOUSHASH;
       +        for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
       +                if(v->tag == tag){
       +                        *l = v->link;
       +                        unlock(&vouslock);
       +                        return v;
       +                }
       +        }
       +        v = getvous();
       +        v->pid = pid;
       +        v->link = voushash[h];
       +        v->val = val;
       +        v->tag = tag;
       +        lock(&v->lk);
       +        voushash[h] = v;
       +        unlock(&vouslock);
       +        return v;
       +}
       +
       +#define DBG 0
       +ulong
       +rendezvous(ulong tag, ulong val)
       +{
       +        int me, vpid;
       +        ulong rval;
       +        Vous *v;
       +
       +        me = getpid();
       +        v = findvous(tag, val, me);
       +        if(v->pid == me){
       +                if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag);
       +                /*
       +                 * No rendezvous partner was found; the next guy
       +                 * through will find v and wake us, so we must go
       +                 * to sleep.
       +                 *
       +                 * To go to sleep:
       +                 *        1. disable USR1 signals.
       +                 *        2. unlock v->lk (tells waker okay to signal us).
       +                 *        3. atomically suspend and enable USR1 signals.
       +                 *
       +                 * The call to ignusr1() could be done once at 
       +                 * process creation instead of every time through rendezvous.
       +                 */
       +                v->val = val;
       +                unlock(&v->lk);
       +                while(sys_futex((u32int*)&v->tag, FUTEX_WAIT, tag, nil, nil) < 0 && errno==EINTR)
       +                        ;
       +                rval = v->val;
       +                if(DBG)fprint(2, "pid is %d, awake\n", me);
       +                putvous(v);
       +        }else{
       +                /*
       +                 * Found someone to meet.  Wake him:
       +                 *
       +                 *        A. lock v->lk (waits for him to get to his step 2)
       +                 *        B. send a USR1
       +                 *
       +                 * He won't get the USR1 until he suspends, which
       +                 * means it must wake him up (it can't get delivered
       +                 * before he sleeps).
       +                 */
       +                vpid = v->pid;
       +                lock(&v->lk);
       +                rval = v->val;
       +                v->val = val;
       +                v->tag++;
       +                unlock(&v->lk);
       +                sys_futex((u32int*)&v->tag, FUTEX_WAKE, 1, nil, nil);
       +        }
       +        return rval;
       +}
       +
 (DIR) diff --git a/src/libdraw/md-alloc.c b/src/libdraw/md-alloc.c
       t@@ -86,7 +86,13 @@ _allocmemimage(Rectangle r, u32int chan)
                        return nil;
        
                md->ref = 1;
       -        md->base = poolalloc(imagmem, (2+nw)*sizeof(u32int));
       +        /*
       +         * The first two words are the md and the callerpc.
       +         * Then nw words of data.
       +         * The final word lets the drawing routines be a little
       +         * sloppy about reading past the end of the block.
       +         */
       +        md->base = poolalloc(imagmem, (2+nw+1)*sizeof(u32int));
                if(md->base == nil){
                        free(md);
                        return nil;
 (DIR) diff --git a/src/libfs/fs.c b/src/libfs/fs.c
       t@@ -86,19 +86,27 @@ fsunmount(Fsys *fs)
        void
        _fsdecref(Fsys *fs)
        {
       -        Fid *f, *next;
       +        Fid *f, **l, *next;
        
                qlock(&fs->lk);
                --fs->ref;
                //fprint(2, "fsdecref %p to %d\n", fs, fs->ref);
                if(fs->ref == 0){
                        close(fs->fd);
       +                /* trim the list down to just the first in each chunk */
       +                for(l=&fs->freefid; *l; ){
       +                        if((*l)->fid%Fidchunk == 0)
       +                                l = &(*l)->next;
       +                        else
       +                                *l = (*l)->next;
       +                }
       +                /* now free the list */
                        for(f=fs->freefid; f; f=next){
                                next = f->next;
       -                        if(f->fid%Fidchunk == 0)
       -                                free(f);
       +                        free(f);
                        }
                        free(fs);
       +                return;
                }
                qunlock(&fs->lk);
        }
 (DIR) diff --git a/src/libfs/ns.c b/src/libfs/ns.c
       t@@ -23,8 +23,11 @@ nsmount(char *name, char *aname)
                fd = dial(addr, 0, 0, 0);
                if(fd < 0){
                        werrstr("dial %s: %r", addr);
       +                free(addr);
                        return nil;
                }
       +        free(addr);
       +
                fcntl(fd, F_SETFL, FD_CLOEXEC);
        
                fs = fsmount(fd, aname);
 (DIR) diff --git a/src/libthread/fdwait.c b/src/libthread/fdwait.c
       t@@ -174,8 +174,8 @@ _threadfdwait(int fd, int rw, ulong pc)
        
                struct {
                        Channel c;
       -                Alt *qentry[2];
                        ulong x;
       +                Alt *qentry[2];
                } s;
        
                threadfdwaitsetup();
       t@@ -214,11 +214,15 @@ threadsleep(int ms)
                struct {
                        Channel c;
                        ulong x;
       +                Alt *qentry[2];
                } s;
        
                threadfdwaitsetup();
                chaninit(&s.c, sizeof(ulong), 1);
       -
       +        s.c.qentry = (volatile Alt**)s.qentry;
       +        s.c.nentry = 2;
       +        memset(s.qentry, 0, sizeof s.qentry);
       +        
                sleepchan[nsleep] = &s.c;
                sleeptime[nsleep++] = p9nsec()/1000000+ms;
                recvul(&s.c);