Browse Source

Plan 9 from Bell Labs 2003-02-06

David du Colombier 21 years ago
parent
commit
7f87129eaa

+ 19 - 16
dist/replica/plan9.db

@@ -3188,7 +3188,7 @@ sys/games - 20000000775 sys sys 952648872 0
 sys/games/lib - 20000000775 sys sys 952648879 0
 sys/games/lib/fortunes - 664 sys sys 1043697004 238254
 sys/include - 20000000775 sys sys 1016902416 0
-sys/include/9p.h - 664 sys sys 1032324435 4127
+sys/include/9p.h - 664 sys sys 1044429947 4264
 sys/include/String.h - 664 sys sys 1014929061 1133
 sys/include/a.out.h - 664 sys sys 1032058165 1144
 sys/include/ape - 20000000775 sys sys 1014927784 0
@@ -3281,7 +3281,7 @@ sys/include/realtime.h - 664 sys sys 1037669237 869
 sys/include/regexp.h - 664 sys sys 1014929066 1308
 sys/include/scribble.h - 664 sys sys 1014929066 679
 sys/include/stdio.h - 664 sys sys 1014929066 4145
-sys/include/thread.h - 664 sys sys 1030537960 3553
+sys/include/thread.h - 664 sys sys 1044429947 3582
 sys/include/venti.h - 664 sys sys 1036470166 6630
 sys/lib - 20000000775 sys sys 1018580948 0
 sys/lib/acid - 20000000775 sys sys 1016926088 0
@@ -4544,7 +4544,8 @@ sys/man/1/yacc - 664 sys sys 944959676 3273
 sys/man/1/yesterday - 664 sys sys 959299265 2045
 sys/man/2 - 20000000775 sys sys 1017423721 0
 sys/man/2/0intro - 664 sys sys 958249500 11777
-sys/man/2/9p - 664 sys sys 1044050898 14553
+sys/man/2/9p - 664 sys sys 1044430182 15044
+sys/man/2/9pcmdbuf - 664 sys sys 1044430197 2057
 sys/man/2/9pfid - 664 sys sys 1030451710 3644
 sys/man/2/9pfile - 664 sys sys 1017423719 4426
 sys/man/2/INDEX - 664 sys sys 1041971549 20120
@@ -4833,7 +4834,7 @@ sys/man/8/cpurc - 664 sys sys 971455510 1275
 sys/man/8/cron - 664 sys sys 944959679 1750
 sys/man/8/dhcpd - 664 sys sys 1032654987 5237
 sys/man/8/drawterm - 664 sys sys 958419689 2458
-sys/man/8/fossilcons - 664 sys sys 1042312265 12639
+sys/man/8/fossilcons - 664 sys sys 1044478450 13360
 sys/man/8/fs - 664 sys sys 1037805200 13843
 sys/man/8/fsconfig - 664 sys sys 1037805200 7966
 sys/man/8/httpd - 664 sys sys 1037690024 4516
@@ -8835,7 +8836,7 @@ sys/src/cmd/gzip/unzip.c - 664 sys sys 1014924864 13591
 sys/src/cmd/gzip/zip.c - 664 sys sys 1033183074 7054
 sys/src/cmd/gzip/zip.h - 664 sys sys 954778719 1428
 sys/src/cmd/hget.c - 664 sys sys 1042940715 21870
-sys/src/cmd/history.c - 664 sys sys 1018721429 4868
+sys/src/cmd/history.c - 664 sys sys 1044498757 5157
 sys/src/cmd/hoc - 20000000775 sys sys 954036932 0
 sys/src/cmd/hoc/code.c - 664 sys sys 944961000 10041
 sys/src/cmd/hoc/hoc.h - 664 sys sys 944960999 2358
@@ -10435,6 +10436,7 @@ sys/src/cmd/venti/unwhack.c - 664 sys sys 1019678881 3191
 sys/src/cmd/venti/utils.c - 664 sys sys 1019678881 4567
 sys/src/cmd/venti/venti.c - 664 sys sys 1036470211 4000
 sys/src/cmd/venti/venti.conf - 664 sys sys 1019867537 397
+sys/src/cmd/venti/ventifs.c - 664 sys sys 1044475553 6160
 sys/src/cmd/venti/verifyarena.c - 664 sys sys 1019678881 2705
 sys/src/cmd/venti/whack.c - 664 sys sys 1019678881 6375
 sys/src/cmd/venti/whack.h - 664 sys sys 1019678881 966
@@ -10663,7 +10665,7 @@ sys/src/fs/sony/mkfile - 664 sys sys 1037805175 1583
 sys/src/fs/words - 664 sys sys 1015110099 661
 sys/src/fs/worms - 664 sys sys 1015110031 2806
 sys/src/lib9p - 20000000775 sys sys 1015023311 0
-sys/src/lib9p/_post.c - 664 sys sys 1030450928 735
+sys/src/lib9p/_post.c - 664 sys sys 1044429936 843
 sys/src/lib9p/dirread.c - 664 sys sys 1015023310 641
 sys/src/lib9p/fid.c - 664 sys sys 1015023310 1051
 sys/src/lib9p/file.c - 664 sys sys 1015023310 5585
@@ -10672,12 +10674,12 @@ sys/src/lib9p/intmap.c - 664 sys sys 1016833881 2255
 sys/src/lib9p/mem.c - 664 sys sys 1015023310 765
 sys/src/lib9p/mkfile - 664 sys sys 1035389775 371
 sys/src/lib9p/parse.c - 664 sys sys 1032324435 2050
-sys/src/lib9p/post.c - 664 sys sys 1030450929 370
+sys/src/lib9p/post.c - 664 sys sys 1044429937 364
 sys/src/lib9p/post.h - 664 sys sys 1029850260 201
 sys/src/lib9p/ramfs.c - 664 sys sys 1030450927 2534
-sys/src/lib9p/req.c - 664 sys sys 1015023311 1515
-sys/src/lib9p/srv.c - 664 sys sys 1030450929 14523
-sys/src/lib9p/tpost.c - 664 sys sys 1030450930 330
+sys/src/lib9p/req.c - 664 sys sys 1044429938 1551
+sys/src/lib9p/srv.c - 664 sys sys 1044429938 16932
+sys/src/lib9p/tpost.c - 664 sys sys 1044429939 324
 sys/src/lib9p/uid.c - 664 sys sys 1015023311 517
 sys/src/lib9p/util.c - 664 sys sys 1017679319 465
 sys/src/libString - 20000000775 sys sys 984754301 0
@@ -11031,7 +11033,7 @@ sys/src/libc/port/cistrstr.c - 664 sys sys 1014927395 357
 sys/src/libc/port/cleanname.c - 664 sys sys 1014927395 1199
 sys/src/libc/port/crypt.c - 664 sys sys 1014927396 1045
 sys/src/libc/port/ctype.c - 664 sys sys 1014927396 834
-sys/src/libc/port/encodefmt.c - 664 sys sys 1015275100 942
+sys/src/libc/port/encodefmt.c - 664 sys sys 1044430909 986
 sys/src/libc/port/execl.c - 664 sys sys 1014927396 86
 sys/src/libc/port/exp.c - 664 sys sys 1014927396 912
 sys/src/libc/port/fabs.c - 664 sys sys 1014927396 104
@@ -11666,27 +11668,28 @@ sys/src/libthread/debug.c - 664 sys sys 1014928157 832
 sys/src/libthread/example.c - 664 sys sys 1041440306 1402
 sys/src/libthread/exec.c - 664 sys sys 1014928157 1844
 sys/src/libthread/exit.c - 664 sys sys 1015701273 1209
-sys/src/libthread/id.c - 664 sys sys 1043788754 1330
-sys/src/libthread/iocall.c - 664 sys sys 1030537962 364
+sys/src/libthread/id.c - 664 sys sys 1044429928 1872
+sys/src/libthread/iocall.c - 664 sys sys 1044429928 877
 sys/src/libthread/ioclose.c - 664 sys sys 1030537962 242
 sys/src/libthread/iodial.c - 664 sys sys 1030537988 438
 sys/src/libthread/ioopen.c - 664 sys sys 1030537962 314
-sys/src/libthread/ioproc.c - 664 sys sys 1043788755 928
+sys/src/libthread/ioproc.c - 664 sys sys 1044429929 1215
 sys/src/libthread/ioread.c - 664 sys sys 1030537963 338
 sys/src/libthread/ioreadn.c - 664 sys sys 1030537988 342
+sys/src/libthread/iosleep.c - 664 sys sys 1044429929 240
 sys/src/libthread/iowrite.c - 664 sys sys 1030537963 342
 sys/src/libthread/kill.c - 664 sys sys 1014928157 1336
 sys/src/libthread/lib.c - 664 sys sys 1014928158 709
 sys/src/libthread/main.c - 664 sys sys 1017679321 3079
 sys/src/libthread/mips.c - 664 sys sys 1014928158 583
-sys/src/libthread/mkfile - 664 sys sys 1030538037 973
+sys/src/libthread/mkfile - 664 sys sys 1044429931 986
 sys/src/libthread/note.c - 664 sys sys 1018029975 2273
 sys/src/libthread/power.c - 664 sys sys 1014928159 585
 sys/src/libthread/ref.c - 664 sys sys 1014928159 168
 sys/src/libthread/rendez.c - 664 sys sys 1014928159 1895
 sys/src/libthread/sched.c - 664 sys sys 1032633301 3099
 sys/src/libthread/test.c - 664 sys sys 1014928159 228
-sys/src/libthread/threadimpl.h - 664 sys sys 1030537961 4601
+sys/src/libthread/threadimpl.h - 664 sys sys 1044429930 4628
 sys/src/libthread/tprimes.c - 664 sys sys 1014928160 798
 sys/src/libthread/xinc386.s - 664 sys sys 1014928160 417
 sys/src/libthread/xincalpha.s - 664 sys sys 1015088758 344

+ 19 - 0
dist/replica/plan9.log

@@ -17142,3 +17142,22 @@
 1044052234 0 c sys/man/2/9p - 664 sys sys 1044050898 14553
 1044291726 0 c sys/src/fs/emelie/mkfile - 664 sys sys 1044290928 1691
 1044291726 1 c sys/src/fs/port/9p2.c - 664 sys sys 1044290935 36142
+1044430373 0 c sys/include/9p.h - 664 sys sys 1044429947 4264
+1044430373 1 c sys/include/thread.h - 664 sys sys 1044429947 3582
+1044430373 2 c sys/man/2/9p - 664 sys sys 1044430182 15044
+1044430373 3 a sys/man/2/9pcmdbuf - 664 sys sys 1044430197 2057
+1044430373 4 c sys/src/lib9p/_post.c - 664 sys sys 1044429936 843
+1044430373 5 c sys/src/lib9p/post.c - 664 sys sys 1044429937 364
+1044430373 6 c sys/src/lib9p/req.c - 664 sys sys 1044429938 1551
+1044430373 7 c sys/src/lib9p/srv.c - 664 sys sys 1044429938 16932
+1044430373 8 c sys/src/lib9p/tpost.c - 664 sys sys 1044429939 324
+1044430373 9 c sys/src/libthread/id.c - 664 sys sys 1044429928 1872
+1044430373 10 c sys/src/libthread/iocall.c - 664 sys sys 1044429928 877
+1044430373 11 c sys/src/libthread/ioproc.c - 664 sys sys 1044429929 1215
+1044430373 12 a sys/src/libthread/iosleep.c - 664 sys sys 1044429929 240
+1044430373 13 c sys/src/libthread/mkfile - 664 sys sys 1044429931 986
+1044430373 14 c sys/src/libthread/threadimpl.h - 664 sys sys 1044429930 4628
+1044432174 0 c sys/src/libc/port/encodefmt.c - 664 sys sys 1044430909 986
+1044477173 0 a sys/src/cmd/venti/ventifs.c - 664 sys sys 1044475553 6160
+1044478974 0 c sys/man/8/fossilcons - 664 sys sys 1044478450 13360
+1044500463 0 c sys/src/cmd/history.c - 664 sys sys 1044498757 5157

+ 5 - 0
sys/include/9p.h

@@ -57,6 +57,7 @@ struct Req
 	Srv*		srv;
 
 /* below is implementation-specific; don't use */
+	QLock	lk;
 	Ref		ref;
 	Reqpool*	pool;
 	uchar*	buf;
@@ -64,6 +65,8 @@ struct Req
 	uchar	responded;
 	char*	error;
 	void*	rbuf;
+	Req**	flush;
+	int		nflush;
 };
 
 /*
@@ -221,3 +224,5 @@ enum {
 
 void readstr(Req*, char*);
 void readbuf(Req*, void*, long);
+void	walkandclone(Req*, char*(*walk1)(Fid*,char*,void*), char*(*clone)(Fid*,Fid*,void*), void*);
+

+ 1 - 0
sys/include/thread.h

@@ -118,6 +118,7 @@ int		ioopen(Ioproc*, char*, int);
 long		ioread(Ioproc*, int, void*, long);
 long		ioreadn(Ioproc*, int, void*, long);
 long		iowrite(Ioproc*, int, void*, long);
+int		iosleep(Ioproc*, long);
 
 long		iocall(Ioproc*, long (*)(va_list*), ...);
 void		ioret(Ioproc*, int);

+ 33 - 12
sys/man/2/9p

@@ -67,6 +67,8 @@ ulong	readstr(Req *r, char *src)
 ulong	readbuf(Req *r, void *src, ulong nsrc)
 typedef int Dirgen(int n, Dir *dir, void *aux)
 void		dirread9p(Req *r, Dirgen *gen, void *aux)
+void	walkandclone(Req *r, char *(*walk1)(Fid *old, char *name, void *v),
+          char *(*clone)(Fid *old, Fid *new, void *v), void *v)
 .fi
 .PP
 .nf
@@ -385,13 +387,14 @@ demands an error
 .RI ( e.g. ,
 in the case of a short walk);
 the library detects error conditions and handles them appropriately.
-.TP
-.I Walk1\fR, \fPClone
-Because implementing the full walk message is 
-intricate and prone to error, the client may instead provide functions
-.IB srv -> walk1
+.IP
+Because implementing the full walk message is intricate and
+prone to error, the helper routine
+.I walkandclone
+will handle the request given pointers to two functions
+.I walk1
 and (optionally)
-.IB srv -> clone \fR.
+.I clone .
 .IR Clone ,
 if non-nil, is called to signal the creation of
 .I newfid
@@ -408,15 +411,33 @@ should walk
 .I fid
 to
 .IR name ,
-initializing both
+initializing
 .IB fid -> qid
-and
-.BI * qid
 to the new path's qid.
-Rather than calling 
-.IR respond ,
-both should return nil
+Both should return nil
 on success or an error message on error.
+.I Walkandclone
+will call
+.I respond
+after handling the request.
+.TP
+.I Walk1\fR, \fPClone
+If the client provides functions
+.IB srv -> walk1
+and (optionally)
+.IB srv -> clone \fR,
+the 9P service loop will call
+.I walkandclone
+with these functions to handle the request.
+Unlike the
+.I walk1
+above,
+.IB srv -> walk1
+must fill in both
+.IB fid -> qid
+and
+.BI * qid
+with the new qid on a successful walk.
 .TP
 .I Open
 If file trees are in use, the file

+ 116 - 0
sys/man/2/9pcmdbuf

@@ -0,0 +1,116 @@
+.TH 9PCMDBUF 2
+.SH NAME
+Cmdbuf, parsecmd, respondcmderror, lookupcmd \- control message parsing
+.SH SYNOPSIS
+.ft L
+.nf
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+.fi
+.PP
+.ft L
+.nf
+.ta \w'\fL1234'u +\w'\fL12345678'u
+typedef struct Cmdbuf
+{
+	char	*buf;
+	char	**f;
+	int	nf;
+} Cmdbuf;
+
+typedef struct Cmdtab
+{
+	int	index;
+	char	*cmd;
+	int	narg;
+};
+
+Cmdbuf	*parsecmd(char *p, int n)
+Cmdtab	*lookupcmd(Cmdbuf *cb, Cmdtab *tab, int ntab)
+void	respondcmderror(Req *r, Cmdbuf *cb, char *fmt, ...)
+.fi
+.SH DESCRIPTION
+These data structures and functions provide parsing of textual control messages.
+.PP
+.I Parsecmd
+treats the
+.I n
+bytes at
+.I p
+(which need not be NUL-terminated) as a UTF string and splits it
+using
+.IR tokenize (2).
+It returns a
+.B Cmdbuf
+structure holding pointers to each field in the message.
+.PP
+.I Lookupcmd
+walks through the array
+.IR ctab ,
+which has
+.I ntab
+entries,
+looking for the first
+.B Cmdtab
+that matches the parsed command.
+(If the parsed command is empty,
+.I lookupcmd
+returns nil immediately.)
+A
+.B Cmdtab
+matches the command if
+.I cmd
+is equal to
+.IB cb -> f [0]
+or if
+.I cmd
+is 
+.LR * .
+Once a matching
+.B Cmdtab
+has been found, if
+.I narg
+is not zero, then the parsed command
+must have exactly
+.I narg
+fields (including the command string itself).
+If the command has the wrong number of arguments,
+.I lookupcmd
+returns nil.
+Otherwise, it returns a pointer to the
+.B Cmdtab
+entry.
+If
+.I lookupcmd
+does not find a matching command at all,
+it returns nil.
+Whenever
+.I lookupcmd
+returns nil, it sets the system error string.
+.PP
+.I Respondcmderror
+resoponds to request
+.I r
+with an error of the form
+`\fIfmt\fB:\fI cmd\fR,'
+where
+.I fmt
+is the formatted string and
+.I cmd
+is a reconstruction of the parsed command.
+Fmt
+is often simply
+.B "%r" .
+.SH EXAMPLES
+This interface is not used in any distributed 9P servers.
+It was lifted from the Plan 9 kernel.
+Almost any kernel driver
+.RB ( /sys/src/9/*/dev*.c )
+is a good example.
+.SH SOURCE
+.B /sys/src/lib9p/parse.c
+.SH SEE ALSO
+.IR 9p (2)

+ 112 - 52
sys/man/8/fossilcons

@@ -43,11 +43,11 @@ con /srv/fscons
 ]
 .PP
 .B uname
-.I uname
+.I name
 [
-.I uid
+.I id
 |
-.BI : uid
+.BI : id
 |
 .BI % newname
 |
@@ -326,75 +326,112 @@ and
 options set the two variables.
 .PP
 .I Uname
-displays or edits one entry the in-memory user table.
-If the in-memory table was read from a file
-(see the
-.I users
-command below),
-the new table is written to that file.
+manipulates entries in the user table.
 There is no distinction between users and groups:
 a user is a group with one member.
-The user table records a mapping between
-uids and unames, as well as recording the
-leader and members of each group.
-A
-.I uid
-is a string naming a user or group
-and stored in the on-disk data structures.
-A
-.I uname
-is the string naming a user or group and
-used in 9P protocol messages.
-There is a distinction so that unames can be
-safely reused, even though uids cannot.
+For each user, the user table records:
+.TP
+.I id
+the string used to represent this user in the on-disk structures
+.TP
+.I name
+the string used to represent this user in the 9P protocol
+.TP
+.I leader
+the group's leader (see
+.IR stat (5)
+for a description of the special privileges held by a group leader)
+.TP
+.I members
+a comma-separated list of members in this group
+.PP
+The
+.I id
+and
+.I name
+are usually the same string, but need not be.
+Once an
+.I id
+is used in file system structures archived to Venti,
+it is impossible to change those disk structures,
+and thus impossible to rename the
+.IR id .
+The translation from
+.I name
+to
+.I id
+allows the appearance of renaming the user even
+though the on-disk structures still record the old name.
+(In a conventional Unix file system, the
+.I id
+is stored as a small integer rather than a string.)
+.I Leader
+and
+.I members
+are names, not ids.
+.PP
 The first argument to
 .I uname
-is (confusingly) a
-uname
-.RI ` uname .'
-The second argument is an optional verb, one of:
+is the
+.I name
+of a user.
+The second argument is a verb, one of:
 .TP
-.I uid
-add the user with uname
-.RI ` uname '
-and uid
-.RI ` uid ,'
-creating a home directory
-.BI /active/usr/ uname \fR.
+.I id
+create a user with name
+.RI ` name '
+and id
+.RI ` id ;'
+also create a home directory
+.BI /active/usr/ uname \fR
 .TP
-.BI : uid
-add the user but do not create the home directory
+.BI : id
+create a user with name
+.RI ` name '
+and id
+.RI ` id ,'
+but do not create a home directory
 .TP
 .BI % newname
-rename
-.RI ` uname '
+rename user
+.RI ` name '
 to
 .RI ` newname ,'
 throughout the user table
 .TP
 .BI = leader
-set the group leader to the uname
+set
+.IR name 's
+group leader
+to
 .IR leader .
 .TP
+.BI =
+remove
+.IR name 's
+group leader; then all members will be
+considered leaders
+.TP
 .BI + member
-add the uname
-.RI ` member '
-to the group
+add
+.I member
+to
+.IR name 's
+list of members
 .TP
 .BI - member
-remove the uname
-.RI ` member '
-from the group
+remove
+.I member
+from
+.IR name 's
+list of members
 .LP
 If the verb is omitted, the entire entry for
-.I uname
-is printed, in the form:
-.IP
-.IB uid : uname : leader :\fImembers
+.I name
+is printed, in the form
+`\fIid\fL:\fIname\fL:\fIleader\fL:\fImembers\fR.'
 .LP
-where
-.I members
-is a comma-separated list of unames.
+The end of this manual page gives examples.
 .PP
 .I Users
 reads
@@ -774,7 +811,7 @@ or
 bits in the
 .I perm
 are silently ignored.
-.SH EXAMPLE
+.SH EXAMPLES
 .IR Sources ,
 the Plan 9 distribution file server,
 uses the following configuration file:
@@ -794,3 +831,26 @@ snaptime -a 0000 -s 15
 .LP
 The second console is used by the daemon
 that creates new accounts.
+.PP
+To add a new user with
+.I name
+and
+.I id
+.B rob
+and create his home directory:
+.IP
+.EX
+uname rob rob
+.EE
+.PP
+To create a new group
+.B sys
+(with no home directory)
+and add
+.B rob
+to it:
+.IP
+.EX
+uname sys :sys
+uname sys +rob
+.EE

+ 28 - 10
sys/src/cmd/history.c

@@ -7,6 +7,7 @@
 
 int	verb;
 int	uflag;
+int	force;
 int	diff;
 int	diffb;
 char*	ndump;
@@ -32,6 +33,9 @@ main(int argc, char *argv[])
 	case 'v':
 		verb = 1;
 		break;
+	case 'f':
+		force = 1;
+		break;
 	case 'd':
 		ndump = ARGF();
 		break;
@@ -51,7 +55,7 @@ main(int argc, char *argv[])
 
 	if(argc == 0) {
 	usage:
-		fprint(2, "usage: history [-vuD] [-d 9fsname] [-s yyyymmdd] files\n");
+		fprint(2, "usage: history [-vufD] [-d 9fsname] [-s yyyymmdd] files\n");
 		exits(0);
 	}
 
@@ -85,9 +89,9 @@ void
 ysearch(char *file)
 {
 	char fil[400], buf[500], pair[2][500];
-	Dir *dir;
+	Dir *dir, *d;
 	ulong otime, dt;
-	int toggle, started;
+	int toggle, started, missing;
 
 	started = 0;
 	dir = dirstat(file);
@@ -110,17 +114,30 @@ ysearch(char *file)
 	for(;;) {
 		lastbefore(otime, fil, buf);
 		dir = dirstat(buf);
-		if(dir == nil)
-			return;
+		if(dir == nil) {
+			if(!force)
+				return;
+			dir = malloc(sizeof(Dir));
+			nulldir(dir);
+			dir->mtime = otime + 1;
+		}
 		dt = HOUR(12);
-		while(otime <= dir->mtime) {
+		missing = 0;
+		while(otime <= dir->mtime){
 			if(verb)
 				print("backup %ld, %ld\n", dir->mtime, otime-dt);
 			lastbefore(otime-dt, fil, buf);
-			free(dir);
-			dir = dirstat(buf);
-			if(dir == nil)
-				return;
+			d = dirstat(buf);
+			if(d == nil){
+				if(!force)
+					return;
+				if(!missing)
+					print("removed %s\n", buf);
+				missing = 1;
+			}else{
+				free(dir);
+				dir = d;
+			}
 			dt += HOUR(12);
 		}
 		strcpy(pair[toggle], buf);
@@ -146,6 +163,7 @@ ysearch(char *file)
 		toggle ^= 1;
 		started = 1;
 		otime = dir->mtime;
+		free(dir);
 	}
 }
 

+ 340 - 0
sys/src/cmd/venti/ventifs.c

@@ -0,0 +1,340 @@
+/*
+ * Present venti hash tree as file system for debugging.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <venti.h>
+#include <vac.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+VtFile *rootf;
+
+void
+responderrstr(Req *r)
+{
+	char e[ERRMAX];
+
+	rerrstr(e, sizeof e);
+	respond(r, e);
+}
+
+void
+mkqide(Qid *q, VtEntry *e)
+{
+	if(e->flags&VtEntryDir)
+		q->type = QTDIR;
+	else
+		q->type = 0;
+	q->path = *(uvlong*)e->score;
+	q->vers = *(ulong*)(e->score+8);
+}
+
+void
+mkqid(Qid *q, VtFile *f)
+{
+	VtEntry e;
+
+	vtFileLock(f, VtOReadOnly);
+	vtFileGetEntry(f, &e);
+	vtFileUnlock(f);
+	mkqide(q, &e);
+}
+
+void
+fsdestroyfid(Fid *fid)
+{
+	if(fid->aux)
+		vtFileClose(fid->aux);
+}
+
+void
+fsattach(Req *r)
+{
+	r->fid->aux = rootf;
+	vtFileIncRef(rootf);
+	mkqid(&r->ofcall.qid, rootf);
+	r->fid->qid = r->ofcall.qid;
+	respond(r, nil);
+}
+
+void
+fsopen(Req *r)
+{
+	if(r->ifcall.mode != OREAD){
+		respond(r, "read-only file system");
+		return;
+	}
+	r->ofcall.qid = r->fid->qid;
+	respond(r, nil);
+}
+
+void
+fsreaddir(Req *r)
+{
+	Dir d;
+	int dsize, nn;
+	char score[2*VtScoreSize+1];
+	uchar edata[VtEntrySize], *p, *ep;
+	u32int i, n, epb;
+	u64int o;
+	VtFile *f;
+	VtEntry e;
+
+	memset(&d, 0, sizeof d);
+	d.name = "0123456789012345678901234567890123456789";
+	d.uid = "venti";
+	d.gid = "venti";
+	d.muid = "";
+	d.atime = time(0);
+	d.mtime = time(0);
+	d.mode = 0444;
+	dsize = sizeD2M(&d);
+
+	p = (uchar*)r->ofcall.data;
+	ep = p+r->ifcall.count;
+	f = r->fid->aux;
+	vtFileLock(f, VtOReadOnly);
+	vtFileGetEntry(f, &e);
+	epb = e.dsize / VtEntrySize;
+	n = vtFileGetDirSize(f);
+fprint(2, "dirsize %d\n", n);
+	i = r->ifcall.offset / dsize;
+	for(; i<n; i++){
+fprint(2, "%d...", i);
+		if(p+dsize > ep)
+{
+fprint(2, "done %p %d %p\n", p, dsize, ep);
+			break;
+}
+		o = (i/epb)*e.dsize+(i%epb)*VtEntrySize;
+		if(vtFileRead(f, edata, VtEntrySize, o) != VtEntrySize){
+			vtFileUnlock(f);
+			responderrstr(r);
+			return;
+		}
+		if(!vtEntryUnpack(&e, edata, 0)){
+			fprint(2, "entryunpack: %R\n");
+			continue;
+		}
+		if(!(e.flags&VtEntryActive)){
+			strcpy(score, "________________________________________");
+			d.qid.type = 0;
+		}else{
+			snprint(score, sizeof score, "%V", e.score);
+			mkqide(&d.qid, &e);
+		}
+		d.name = score;
+		if(e.flags&VtEntryDir){
+			d.mode = DMDIR|0555;
+			d.qid.type = QTDIR;
+		}else{
+			d.mode = 0444;
+			d.qid.type = 0;
+		}
+		d.length = e.size;
+		nn = convD2M(&d, p, dsize);
+		if(nn != dsize)
+			fprint(2, "oops: dsize mismatch\n");
+		p += dsize;
+	}
+	r->ofcall.count = p - (uchar*)r->ofcall.data;
+	vtFileUnlock(f);
+	respond(r, nil);
+}
+
+void
+fsread(Req *r)
+{
+	long n;
+
+	if(r->fid->qid.type&QTDIR){
+		fsreaddir(r);
+		return;
+	}
+	vtFileLock(r->fid->aux, VtOReadOnly);
+	n = vtFileRead(r->fid->aux, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
+	vtFileUnlock(r->fid->aux);
+	if(n < 0){
+		responderrstr(r);
+		return;
+	}
+	r->ofcall.count = n;
+	respond(r, nil);
+}
+
+void
+fsstat(Req *r)
+{
+	VtEntry e;
+
+	vtFileLock(r->fid->aux, VtOReadOnly);
+	if(!vtFileGetEntry(r->fid->aux, &e)){
+		vtFileUnlock(r->fid->aux);
+		responderrstr(r);
+		return;
+	}
+	vtFileUnlock(r->fid->aux);
+	memset(&r->d, 0, sizeof r->d);
+	r->d.name = smprint("%V", e.score);
+	r->d.qid = r->fid->qid;
+	r->d.mode = 0444;
+	if(r->d.qid.type&QTDIR)
+		r->d.mode |= DMDIR|0111;
+	r->d.uid = estrdup9p("venti");
+	r->d.gid = estrdup9p("venti");
+	r->d.muid = estrdup9p("");
+	r->d.atime = time(0);
+	r->d.mtime = time(0);
+	r->d.length = e.size;
+	respond(r, nil);
+}
+
+char*
+fswalk1(Fid *fid, char *name, void*)
+{
+	uchar score[VtScoreSize], edata[VtEntrySize];
+	u32int i, n, epb;
+	u64int o;
+	VtFile *f, *ff;
+	VtEntry e;
+
+	if(dec16(score, sizeof score, name, strlen(name)) != VtScoreSize)
+		return "file not found";
+
+	f = fid->aux;
+	vtFileGetEntry(f, &e);
+	epb = e.dsize / VtEntrySize;
+	n = vtFileGetDirSize(f);
+	o = 0;
+	for(i=0; i<n; i++){
+		o = (i/epb)*e.dsize+(i%epb)*VtEntrySize;
+		if(vtFileRead(f, edata, VtEntrySize, o) != VtEntrySize)
+			return "error in vtfileread";
+		if(!vtEntryUnpack(&e, edata, 0))
+			continue;
+		if(!(e.flags&VtEntryActive))
+			continue;
+		if(memcmp(e.score, score, VtScoreSize) == 0)
+			break;
+	}
+	if(i == n)
+		return "entry not found";
+	ff = vtFileOpen(f, i, VtOReadOnly);
+	if(ff == nil)
+		return "error in vtfileopen";
+	vtFileClose(f);
+	fid->aux = ff;
+	mkqid(&fid->qid, ff);
+	return nil;
+}		
+
+char*
+fsclone(Fid *fid, Fid *newfid, void*)
+{
+	newfid->aux = fid->aux;
+	vtFileIncRef(fid->aux);
+	return nil;
+}
+
+void
+fswalk(Req *r)
+{
+	VtFile *f;
+
+	f = r->fid->aux;
+	vtFileLock(f, VtOReadOnly);
+	walkandclone(r, fswalk1, fsclone, nil);
+	vtFileUnlock(f);
+}
+
+Srv fs = 
+{
+.destroyfid=	fsdestroyfid,
+.attach=		fsattach,
+.open=		fsopen,
+.read=		fsread,
+.stat=		fsstat,
+.walk=		fswalk
+};
+
+void
+usage(void)
+{
+	fprint(2, "usage: ventifs score\n");
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	VtSession *z;
+	VtCache *c;
+	VtBlock *b;
+	VtRoot root;
+	VtEntry e;
+	int bsize;
+	uchar score[VtScoreSize];
+
+	bsize = 16384;
+	ARGBEGIN{
+	case 'D':
+		chatty9p++;
+		break;
+	case 'b':
+		bsize = atoi(EARGF(usage()));
+		break;
+	default:
+		usage();
+	}ARGEND
+
+	if(argc != 1)
+		usage();
+
+	fmtinstall('V', vtScoreFmt);
+	fmtinstall('R', vtErrFmt);
+
+	vtAttach();
+	if((z = vtDial(nil, 0)) == nil)
+		vtFatal("vtDial: %r");
+	if(!vtConnect(z, nil))
+		vtFatal("vtConnect: %r");
+
+	c = vtCacheAlloc(z, bsize, 50, VtOReadWrite);
+
+	if(dec16(score, sizeof score, argv[0], strlen(argv[0])) != VtScoreSize)
+		vtFatal("bad score: %R");
+	b = vtCacheGlobal(c, score, VtRootType);
+	if(b){
+		if(!vtRootUnpack(&root, b->data))
+			vtFatal("bad root: %R");
+		memmove(score, root.score, VtScoreSize);
+		vtBlockPut(b);
+	}
+	b = vtCacheGlobal(c, score, VtDirType);
+	if(b == nil)
+		sysfatal("vtCacheGlobal %V: %R", score);
+	if(!vtEntryUnpack(&e, b->data, 0))
+		sysfatal("%V: vtEntryUnpack failed", score);
+	fprint(2, "entry: size %llud psize %d dsize %d\n",
+		e.size, e.psize, e.dsize);
+	vtBlockPut(b);
+
+	if(!(e.flags&VtEntryDir)){
+		b = vtCacheAllocBlock(c, VtDirType);
+		vtEntryPack(&e, b->data, 0);
+		memmove(e.score, b->score, VtScoreSize);
+		e.flags |= VtEntryDir;
+		e.size = VtEntrySize;
+		e.depth = 0;
+		vtBlockPut(b);
+	}
+
+	rootf = vtFileOpenRoot(c, &e);
+	if(rootf == nil)
+		vtFatal("vtFileOpenRoot: %R");
+
+	postmountsrv(&fs, nil, "/n/kremvax", MBEFORE);
+}

+ 6 - 0
sys/src/lib9p/_post.c

@@ -33,6 +33,8 @@ _post2(void *v)
 	Srv *s;
 
 	s = v;
+	rfork(RFNOTEG);
+	rendezvous((ulong)s, 0);
 	close(s->srvfd);
 	srv(s);
 }
@@ -40,6 +42,10 @@ _post2(void *v)
 void
 _post3(Postcrud *p)
 {
+	rfork(RFFDG);
+	rendezvous((ulong)p->s, 0);
+	close(p->s->infd);
+
 	if(p->mtpt){
 		if(amount(p->s->srvfd, p->mtpt, p->flag, "") == -1)
 			sysfatal("mount %s: %r", p->mtpt);

+ 1 - 1
sys/src/lib9p/post.c

@@ -11,7 +11,7 @@ postmountsrv(Srv *s, char *name, char *mtpt, int flag)
 	Postcrud *p;
 
 	p = _post1(s, name, mtpt, flag);
-	switch(rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM)){
+	switch(rfork(RFPROC|RFNOTEG|RFNAMEG|RFMEM)){
 	case -1:
 		sysfatal("rfork: %r");
 	case 0:

+ 2 - 0
sys/src/lib9p/req.c

@@ -77,6 +77,8 @@ if(chatty9p > 1)
 			closefid(r->fid);
 		if(r->newfid)
 			closefid(r->newfid);
+		if(r->afid)
+			closefid(r->afid);
 		if(r->oldreq)
 			closereq(r->oldreq);
 		switch(r->ifcall.type){

File diff suppressed because it is too large
+ 570 - 436
sys/src/lib9p/srv.c


+ 1 - 1
sys/src/lib9p/tpost.c

@@ -11,7 +11,7 @@ threadpostmountsrv(Srv *s, char *name, char *mtpt, int flag)
 	Postcrud *p;
 
 	p = _post1(s, name, mtpt, flag);
-	if(procrfork(_post2, s, 32*1024, RFNAMEG|RFFDG|RFNOTEG) < 0)
+	if(procrfork(_post2, s, 32*1024, RFNAMEG|RFNOTEG) < 0)
 		sysfatal("procrfork: %r");
 	_post3(p);
 }

+ 2 - 0
sys/src/libc/port/encodefmt.c

@@ -16,6 +16,8 @@ encodefmt(Fmt *f)
 		goto error;
 
 	b = va_arg(f->args, uchar*);
+	if(b == 0)
+		return fmtstrcpy(f, "<nil>");
 
 	ilen = f->prec;
 	f->prec = 0;

+ 42 - 4
sys/src/libthread/id.c

@@ -57,8 +57,8 @@ threadgetgrp(void)
 void
 threadsetname(char *name)
 {
-	int fd;
-	char buf[40];
+	int fd, n;
+	char buf[128], *s;
 	Proc *p;
 	Thread *t;
 
@@ -70,7 +70,12 @@ threadsetname(char *name)
 	if(p->nthreads == 1){
 		snprint(buf, sizeof buf, "#p/%d/args", getpid());
 		if((fd = open(buf, OWRITE)) >= 0){
-			write(fd, name, strlen(name));
+			snprint(buf, sizeof buf, "%s [%s]", argv0, name);
+			n = strlen(buf)+1;
+			s = strchr(buf, ' ');
+			if(s)
+				*s = '\0';
+			write(fd, buf, n);
 			close(fd);
 		}
 	}
@@ -85,7 +90,7 @@ threadgetname(void)
 void**
 threaddata(void)
 {
-	return &_threadgetproc()->thread->udata;
+	return &_threadgetproc()->thread->udata[0];
 }
 
 void**
@@ -94,3 +99,36 @@ procdata(void)
 	return &_threadgetproc()->udata;
 }
 
+static Lock privlock;
+static int privmask = 1;
+
+int
+tprivalloc(void)
+{
+	int i;
+
+	lock(&privlock);
+	for(i=0; i<NPRIV; i++)
+		if(!(privmask&(1<<i))){
+			privmask |= 1<<i;
+			unlock(&privlock);
+			return i;
+		}
+	unlock(&privlock);
+	return -1;
+}
+
+void
+tprivfree(int i)
+{
+	if(i < 0 || i >= NPRIV)
+		abort();
+	lock(&privlock);
+	privmask &= ~(1<<i);
+}
+
+void**
+tprivaddr(int i)
+{
+	return &_threadgetproc()->thread->udata[i];
+}

+ 32 - 3
sys/src/libthread/iocall.c

@@ -6,18 +6,47 @@
 long
 iocall(Ioproc *io, long (*op)(va_list*), ...)
 {
-	int ret;
+	int ret, inted;
+	Ioproc *msg;
 
+	if(send(io->c, &io) == -1){
+		werrstr("interrupted");
+		return -1;
+	}
 	assert(!io->inuse);
 	io->inuse = 1;
 	io->op = op;
 	va_start(io->arg, op);
-	sendp(io->c, io);
-	recvp(io->c);
+	msg = io;
+	inted = 0;
+	while(send(io->creply, &msg) == -1){
+		msg = nil;
+		inted = 1;
+	}
+	if(inted){
+		werrstr("interrupted");
+		return -1;
+	}
+
+	/*
+	 * If we get interrupted, we have stick around so that
+	 * the IO proc has someone to talk to.  Send it an interrupt
+	 * and try again.
+	 */
+	inted = 0;
+	while(recv(io->creply, nil) == -1){
+		inted = 1;
+		iointerrupt(io);
+	}
+	USED(inted);
 	va_end(io->arg);
 	ret = io->ret;
 	if(ret < 0)
 		errstr(io->err, sizeof io->err);
 	io->inuse = 0;
+
+	/* release resources */
+	while(send(io->creply, &io) == -1)
+		;
 	return ret;
 }

+ 31 - 20
sys/src/libthread/ioproc.c

@@ -8,32 +8,45 @@ enum
 	STACK = 8192,
 };
 
-static Ioproc *iofree;
-
 void
 iointerrupt(Ioproc *io)
 {
 	if(!io->inuse)
 		return;
-	postnote(PNPROC, io->pid, "threadint");
+	threadint(io->tid);
 }
 
 static void
 xioproc(void *a)
 {
-	Ioproc *io;
-
+	Ioproc *io, *x;
 	io = a;
-	io->pid = getpid();
-	sendp(io->c, nil);
-	while(recvp(io->c) == io){
+	/*
+	 * first recvp acquires the ioproc.
+	 * second tells us that the data is ready.
+	 */
+	for(;;){
+		while(recv(io->c, &x) == -1)
+			;
+		if(x == 0)	/* our cue to leave */
+			break;
+		assert(x == io);
+
+		/* caller is now committed -- even if interrupted he'll return */
+		while(recv(io->creply, &x) == -1)
+			;
+		if(x == 0)	/* caller backed out */
+			continue;
+		assert(x == io);
+
 		io->ret = io->op(&io->arg);
 		if(io->ret < 0)
 			rerrstr(io->err, sizeof io->err);
-		sendp(io->c, io);
+		while(send(io->creply, &io) == -1)
+			;
+		while(recv(io->creply, &x) == -1)
+			;
 	}
-	chanfree(io->c);
-	free(io);
 }
 
 Ioproc*
@@ -41,17 +54,12 @@ ioproc(void)
 {
 	Ioproc *io;
 
-	if((io = iofree) != nil){
-		iofree = io->next;
-		return io;
-	}
 	io = mallocz(sizeof(*io), 1);
 	if(io == nil)
 		sysfatal("ioproc malloc: %r");
 	io->c = chancreate(sizeof(void*), 0);
-	if(proccreate(xioproc, io, STACK) < 0)
-		sysfatal("ioproc proccreate: %r");
-	recvp(io->c);
+	io->creply = chancreate(sizeof(void*), 0);
+	io->tid = proccreate(xioproc, io, STACK);
 	return io;
 }
 
@@ -61,6 +69,9 @@ closeioproc(Ioproc *io)
 	if(io == nil)
 		return;
 	iointerrupt(io);
-	io->next = iofree;
-	iofree = io;
+	while(send(io->c, 0) == -1)
+		;
+	chanfree(io->c);
+	chanfree(io->creply);
+	free(io);
 }

+ 19 - 0
sys/src/libthread/iosleep.c

@@ -0,0 +1,19 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include "threadimpl.h"
+
+static long
+_iosleep(va_list *arg)
+{
+	long n;
+
+	n = va_arg(*arg, long);
+	return sleep(n);
+}
+
+int
+iosleep(Ioproc *io, long n)
+{
+	return iocall(io, _iosleep, n);
+}

+ 1 - 0
sys/src/libthread/mkfile

@@ -19,6 +19,7 @@ OFILES=\
 	ioproc.$O\
 	ioread.$O\
 	ioreadn.$O\
+	iosleep.$O\
 	iowrite.$O\
 	kill.$O\
 	lib.$O\

+ 4 - 3
sys/src/libthread/threadimpl.h

@@ -47,6 +47,7 @@ enum
 {
 	RENDHASH = 13,
 	Printsize = 2048,
+	NPRIV = 8,
 };
 
 struct Rgrp
@@ -90,7 +91,7 @@ struct Thread
 	Chanstate	chan;		/* which channel operation is current */
 	Alt		*alt;			/* pointer to current alt structure (debugging) */
 
-	void*	udata;		/* User per-thread data pointer */
+	void*	udata[NPRIV];	/* User per-thread data pointer */
 };
 
 struct Execargs
@@ -140,8 +141,8 @@ struct Pqueue {		/* Proc queue */
 
 struct Ioproc
 {
-	int pid;
-	Channel *c;
+	int tid;
+	Channel *c, *creply;
 	int inuse;
 	long (*op)(va_list*);
 	va_list arg;

Some files were not shown because too many files changed in this diff