RFS: remote file system (part 1 of 7)

sources-request at panda.UUCP sources-request at panda.UUCP
Wed Jan 8 08:55:54 AEST 1986


Mod.sources:  Volume 3, Issue 77
Submitted by: genrad!masscomp!tektronix!tekcrl!toddb
Subject: RFS: a Kernel-resident remote file system

RFS release 2.0+ (plus more fixes, easy installation w/ patch, etc.)

These seven shar files contain the software and documentation for
installation, maintenance and adjustment of RFS, a public domain,
kernel-resident distributed file system, written at Tektronix Computer
Research Laboratories* by me for partial fulfillment of the master's
degree program at the University of Denver.  It was designed to provide
complete transparency with respect to file access and protections for
all programs whether they use local or remote files and directories.
It has been installed on VAX BSD 4.2 and 4.3 UNIX, Pyramid 4.2/5.0
UNIX, version 2.5, and on a Tektronix internal proprietary workstation,
called Magnolia.  The instructions are designed in a way that keeps all
changes separate from your standard sources, in hope that it will
encourage sites to try the installation.

			Todd Brunhoff
			toddb%crl at tektronix.csnet
			decvax!tektronix!crl!toddb

* RFS should not be confused with another completely different (but
  excellent) implementation from Tektronix available on the 6000 series
  workstation, called DFS, and done by a separate product group.  The
  work on RFS was designed and written strictly by the author of this
  paper at about the same time as DFS, and draws none of its
  implementation details from DFS.  RFS is public domain, while DFS is
  proprietary.

#!/bin/sh
#
# RFS, a kernel-resident remote file system.  Shar 1 of 7
#
#
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	remote/README
#	remote/byteorder.c
#	remote/change.c
#	remote/debug.c
#	remote/doc
#	remote/doc/install.ms
#	remote/doc/paper
#	remote/doc/paper/Makefile
#	remote/doc/paper/appendixB
#	remote/doc/paper/fig1
#	remote/doc/paper/fig1.mag
#	remote/doc/paper/fig4
#	remote/doc/paper/fig5
#	remote/doc/paper/fig6

mkdir remote

#
# remote/README
#
if [ -f remote/README ]; then 
	echo -n 'Hit <return> to overwrite remote/README or ^C to quit' 
	read ans 
	rm -f remote/README 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/README
XStart with running off the following documents in the doc directory:
X
X	install.ms	(standard Berkeley ms macros)
X	remotename.2	\
X	remoteon.2	 \ (standard Berkeley man macros)
X	rfs_server.8	 /
X	rmtmnt.8	/
X
XThe directory doc/paper, contains a paper that contains most of the early
Xdesign considerations for RFS, but is written using some TEK-internal
Xms macros.
X
XRead the install.ms document first.
SHAREOF
chmod 664 remote/README
#
# remote/byteorder.c
#
if [ -f remote/byteorder.c ]; then 
	echo -n 'Hit <return> to overwrite remote/byteorder.c or ^C to quit' 
	read ans 
	rm -f remote/byteorder.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/byteorder.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Log:	byteorder.c,v $
X * Revision 2.0  85/12/07  18:20:50  toddb
X * First public release.
X * 
X */
Xstatic char	*rcsid = "$Header: byteorder.c,v 2.0 85/12/07 18:20:50 toddb Rel $";
Xlong	data = 0x03020100;
X
Xmain()
X{
X	char	*p = (char *)&data;
X
X	printf("bytes order=%d,%d,%d,%d\n", p[0],p[1],p[2],p[3]);
X}
SHAREOF
chmod 444 remote/byteorder.c
#
# remote/change.c
#
if [ -f remote/change.c ]; then 
	echo -n 'Hit <return> to overwrite remote/change.c or ^C to quit' 
	read ans 
	rm -f remote/change.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/change.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Log:	change.c,v $
X * Revision 2.0  85/12/07  18:20:57  toddb
X * First public release.
X * 
X */
Xstatic char	*rcsid = "$Header: change.c,v 2.0 85/12/07 18:20:57 toddb Rel $";
X#include	"server.h"
X#include	<stdio.h>
X#include	<sys/time.h>
X
Xextern short	current_uid;
Xextern short	current_pid;
Xextern short	current_umask;
Xextern short	current_server;
Xextern short	gateway_server;
Xextern long	fds_in_use;
Xextern long	to_gateway;
Xextern long	from_servers;
Xextern boolean	i_am_gateway;
Xextern boolean	i_have_control;
Xextern process	*wildcard;
Xextern syscallmap	smap[];
Xextern hosts	*host;
X
X/*
X * Given the user id # and the process id # in the message, we look up the
X * process (or allocate a new one).  If there are things to be accomplished
X * before the system call is performed, do them here.
X */
Xprocess *change_to_proc(msg)
X	register struct message	*msg;
X{
X	register rusers	*ruser;
X	register process	*proc = NULL;
X	register char	*p;
X	register long	syscall = msg->m_syscall,
X			syscalltype = smap[ syscall ].s_type;
X
X	/*
X	 * First, we check to see that the file is not really a local file
X	 * for the client.  A simple example of this is a pathname of '..'
X	 * while sitting in our root directory.  If it is local, islocal()
X	 * will compose a message and send it.  We simply return.
X	 *
X	 * Even if this is handled by another server, we may be able to serve
X	 * the request;  but only if:
X	 *	1. it is a system call using a path (NEED_CWD).
X	 *	2. The path is starts with a '/'.
X	 *	3. The system call does not generate a new file descriptor
X	 *	   (like open).
X	 *	4. This is not chdir().
X	 * The system calls that fall in this category, are stat, lstat,
X	 * rename, unlink, symlink, readlink, etc.
X	 * If the system call does not match these criterion, then we must
X	 * reroute it.
X	 */
X
X	proc = findprocess(msg->m_pid, msg->m_uid);
X	if (syscalltype & NEED_CWD) {
X		if (proc
X		&& proc->p_handler == current_pid
X		&& islocal(msg, syscalltype))
X			return(NULL);
X		if ((syscalltype & NEED_MYSERVER) == 0)
X		{
X			if (syscalltype & NEED_2PATH)
X				p = twopath2addr(msg);
X			else
X				p = path1addr(msg);
X			if (*p == '/')
X			{
X				setup_proc(proc = wildcard,
X					msg->m_uid, msg->m_pid);
X				debug0("using wildcard proc... ");
X			}
X		}
X	}
X
X	/*
X	 * A fork() (but not vfork()) generates two messages, one
X	 * from parent, one from the child.  If we know about it (no
X	 * matter if we are the server for the parent, the child or if
X	 * we are the gateway), then we already have received the
X	 * first notification.  Don't do a reroute for that, just
X	 * handle it locally (its redundant info).  If we don't know
X	 * about it, then this is the first anyone has heard of it,
X	 * so we use args[1] which is the parent pid of
X	 * the fork (in both messages).
X	 */
X	if (proc == NULL && (syscall == RSYS_fork || syscall == RSYS_vfork))
X		proc = findprocess(msg->m_args[ 1 ], msg->m_uid);
X
X	if (proc == NULL)
X	{
X		/*
X		 * If we are the gateway, and don't know about this process,
X		 * and it is an exit() call, then just ignore it; cause if we
X		 * don't know this guy, nobody does.  Otherwise,
X		 * allocate a new slot for it.
X		 */
X		if (i_am_gateway)
X		{
X			if (syscall == RSYS_exit)
X			{
X				debug0("discard exit call for pid %d\n",
X					msg->m_pid);
X				return(NULL);
X			}
X			else
X				proc = add_new_process(msg->m_uid, msg->m_pid);
X		}
X		/*
X		 * If we are'nt the gateway, then hand this request back to
X		 * the gateway.  Maybe he will know where to send the request.
X		 */
X		else
X		{
X			reroute(gateway_server, msg);
X			return(NULL);
X		}
X	}
X	/*
X	 * And if we just happen to know about this process (whether we
X	 * are the gateway or not), then just reroute it.
X	 */
X	else if (proc->p_handler != current_pid)
X	{
X		reroute(proc->p_handler, msg);
X		if (syscall == RSYS_exit && !i_am_gateway)
X		{
X			deletelist(&host->h_proclist, proc);
X			freeproc(proc);
X		}
X		return(NULL);
X	}
X
X	/*
X	 * At this point, the request is for us, and there is definitely
X	 * no mistake.
X	 */
X	if ((syscalltype & NEED_FD) || syscall == RSYS_chdir)
X	{
X		debug3("%d current file descriptors\n", fds_in_use);
X		/*
X		 * Here is where we reroute the opening of a file
X		 * or a chdir() to another server.
X		 */
X		if (need_to_fork())
X			if (! become_server(msg))
X				return(NULL);
X	}
X
X	if (syscalltype & NEED_PERM)
X		change_to_user( proc->p_ruser->r_user );
X
X	debug1("pid %d: ", proc->p_pid);
X	return(proc);
X}
X
X/*
X * change the current user id to 'uid'.
X * This is done with simply a setreuid
X */
Xchange_to_user(user)
X	register users	*user;
X{
X#ifdef RFSDEBUG
X	long	gids[ NGROUPS ], ngids, i;
X#endif RFSDEBUG
X
X	if (current_uid != user->u_local_uid)
X	{
X		debug2("set uid to %s(%d)\n",
X			user->u_name, user->u_local_uid);
X		change_to_uid(0);
X		if (setgroups(user->u_numgroups, user->u_local_groups) < 0)
X		{
X			register long	i;
X
X			log("cannot set gids\n");
X			for (i=1; i<user->u_numgroups; i++)
X				log(",%d", user->u_local_groups[i]);
X			return(FALSE);
X		}
X		change_to_uid(user->u_local_uid);
X	}
X	else
X		debug2("already at uid %d (uid=%d/%d)\n",
X			current_uid, getuid(), geteuid());
X#ifdef RFSDEBUG
X	if (remote_debug & 0x4)
X	{
X		log("%d gids should be", user->u_numgroups);
X		for (i=0; i<user->u_numgroups; i++)
X			log(" %d", user->u_local_groups[i]);
X		ngids = getgroups(NGROUPS, gids);
X		log("\n%d gids are=", ngids);
X		for (i=0; i<ngids; i++)
X			log(" %d", gids[i]);
X		log("\n");
X	}
X#endif RFSDEBUG
X	return (TRUE);
X}
X
X/*
X * Change to uid 'uid'.
X */
Xchange_to_uid(uid)
X	register long	uid;
X{
X	if (current_uid != uid)
X		if (setreuid(0, uid) < 0)
X			log("cannot set uid to %d\n", uid);
X		else
X		{
X			current_uid = uid;
X			debug2("uid now %d/%d\n", getuid(), geteuid());
X		}
X}
X
X/*
X * Change to umask 'mask'.
X */
Xchange_to_umask(mask)
X	register long	mask;
X{
X	register long	oldmask;
X
X	if (mask != current_umask)
X	{
X		oldmask = umask(current_umask = mask);
X		debug2("umask now 0%o, was 0%o\n", current_umask, oldmask);
X	}
X}
X
X/*
X * check to see if we need to fork.  We do this for two reasons:
X *	1. we are the gateway server.
X *	2. we are currently handling other processes (a chdir might mess
X *	   them up).
X * Note that we only have to ask ourselves "do we need to fork" when we are
X * opening a new file, accepting a new process (the client is doing a fork()
X * or vfork()), or changing directory.
X */
Xneed_to_fork()
X{
X	register char	*fds;
X	register process	*proc;
X	register long	myprocs = 0;
X
X	if (i_am_gateway)
X		return(TRUE);
X	for (proc = host->h_proclist; proc; proc = proc->p_next)
X		if(proc->p_handler == current_pid)
X			myprocs++;
X	return(myprocs > 1);
X}
SHAREOF
chmod 444 remote/change.c
#
# remote/debug.c
#
if [ -f remote/debug.c ]; then 
	echo -n 'Hit <return> to overwrite remote/debug.c or ^C to quit' 
	read ans 
	rm -f remote/debug.c 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/debug.c
X/*
X * Copyright 1985, Todd Brunhoff.
X *
X * This software was written at Tektronix Computer Research Laboratories
X * as partial fulfillment of a Master's degree at the University of Denver.
X * This is not Tektronix proprietary software and should not be
X * confused with any software product sold by Tektronix.  No warranty is
X * expressed or implied on the reliability of this software; the author,
X * the University of Denver, and Tektronix, inc. accept no liability for
X * any damage done directly or indirectly by this software.  This software
X * may be copied, modified or used in any way, without fee, provided this
X * notice remains an unaltered part of the software.
X *
X * $Log:	debug.c,v $
X * Revision 2.0  85/12/07  18:21:07  toddb
X * First public release.
X * 
X */
Xstatic char	*rcsid = "$Header: debug.c,v 2.0 85/12/07 18:21:07 toddb Rel $";
X#include	"server.h"
X
Xmain(argc, argv)
X	char	**argv;
X	int	argc;
X{
X	int	dbg;
X
X	dbg = atox(argv[1]);
X	printf("set debug to %x\n", dbg);
X	printf("remotename()=%d\n", remotename(NM_DEBUG, dbg));
X	perror("debug");
X}
X
X/*
X * ascii to hex
X */
Xatox(buf)
X	char    *buf;
X{
X	register char   *p;
X	register unsigned       num, nibble;
X
X	/*
X	 * now, take it out checking to make sure that the number is
X	 * valid.
X	 */
X	if (! buf)
X		return(0);
X	for(num=0, p = buf; *p; p++)
X	{
X		nibble = *p;
X		if (nibble >= 'A' && nibble <= 'F')
X			nibble -= 'A' - 10;
X		else if (nibble >= 'a' && nibble <= 'f')
X			nibble -= 'a' - 10;
X		else if (nibble >= '0' && nibble <= '9')
X			nibble -= '0';
X		else
X			return(0);
X		num = (num << 4) | nibble;
X	}
X	return(num);
X}
SHAREOF
chmod 444 remote/debug.c
#
# remote/doc
#
mkdir remote/doc
chmod 775 remote/doc
#
# remote/doc/install.ms
#
if [ -f remote/doc/install.ms ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/install.ms or ^C to quit' 
	read ans 
	rm -f remote/doc/install.ms 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/install.ms
X.ds Fi \\u\\s-4\\n+*\\s+4\\d
X.TL
XInstalling and Operating RFS
X.AU
XT. Brunhoff
Xtoddb%crl at tektronix.csnet
Xdecvax!tektronix!crl!toddb
X.AI
XUniversity of Denver
X.AB
XThis document describes
Xthe installation, maintenance and adjustment
Xof RFS, a public domain, kernel\-resident distributed file system,
Xwritten at
XTektronix Computer Research Laboratories* for partial
Xfulfillment of the master's degree program at the University of Denver.
XIt was designed to provide complete transparency with
Xrespect to file access and protections for all programs
Xwhether they use local or remote files and directories.
XIt has been installed on VAX BSD 4.2 and 4.3 UNIX,
XPyramid 4.2/5.0 UNIX, version 2.5,
Xand on a Tektronix internal proprietary workstation,
Xcalled Magnolia.
XThe instructions are designed in a way that keeps all changes
Xseparate from your standard sources, in hope that
Xit will encourage sites to try the installation.
X.AE
X.nr * 0 1
X.FS *
XRFS should not be confused with another completely different (but excellent)
Ximplementation
Xfrom Tektronix available on the 6000 series workstation, called DFS,
Xand done by a separate product group.
XThe work on RFS was designed and written
Xstrictly by the author of this paper at about the same
Xtime as DFS, and draws none of its implementation details from DFS.
XRFS is public domain, while DFS is proprietary.
X.FE
X.NH 1
XInstalling and Compiling
X.PP
XThese instructions assume that you are familiar with
Xthe C compiler, the commands \fImake(1)\fP, \fIvi\fP,
Xthe structure of the kernel source files,
Xhow to build a new kernel[1],
Xthe structure of \fI/etc/passwd, /etc/hosts, /etc/services, /etc/rc.local\fP.
XInstalling and compiling the software should take about two to four hours
Xwithout interruption and on a lightly loaded 11/750.
X.PP
XThe best way to install this at first, is to make everything in someone's
Xlogin directory, keeping all changes from being anywhere near permanent.
XIn this way
Xyou can gain confidence comfortably that the software really
Xworks.
XAll compiles can be done by an unprivilaged user that has read access
Xto the kernel source.
X.PP
XTo do this,
Xyou need the \fIremote\fP directory
X(this document came from \fIremote/doc/install.ms\fP)
Xwith all of its original contents.
XLet us say that you have allocated this project to a user named \fIrfs\fP,
Xand that he will be installing everything beneath his login directory,
X\fI~rfs\fP.
XIf you are reading this document,
Xthen you probably now have the following directories
Xunder \fI~rfs\fP:
X.DS
Xremote
Xremote/RCS
Xremote/doc
Xremote/doc/paper
Xremote/usr.include.{VAX4.2,VAX4.3,PYR2.5}
Xremote/usr.src.lib.libc
Xremote/usr.src.lib.libc/gen
Xremote/usr.src.lib.libc/{vax,pyr}
Xremote/usr.src.lib.libc/{vax,pyr}/sys
Xremote/usr.sys.VAX4.2/{conf,h,machine,sys}
Xremote/usr.sys.VAX4.3/{conf,h,machine,sys}
Xremote/usr.sys.PYR2.5/{conf,h,sys}
Xremote/usr.sys.remote
X.DE
X.PP
XIf not,
Xthey are easily obtained by mounting the tape (if that is the medium of this
Xrelease) or by placing the \fIshar\fP file in, say,
X\fI/tmp/rfs.shar\fP.
XTo extract them, you would type, respectively,
X.DS
X% cd ~rfs; tar x
X	or
X% cd ~rfs; sh < /tmp/rfs.shar
X.DE
X.NH 2
XBuilding the Kernel
X.PP
XA new kernel must be installed on the machine that is to have the
Xdistributed file system capability.
XThe machines that will be accessed through RFS
Xdo not need to have a new kernel if they are running
XBSD 4.3;
Xhowever, BSD 4.2 sites have a serious bug in sys_socket.c that
Xcauses infinite loops if there is any activity on a socket being
Xread using the \fIrecv(2)\fP system call.
XThe server uses this system call.
X.PP
XFirst,
Xyou must set up a local copy of the kernel sources
Xin \fI~rfs/sys\fP
Xusing symbolic links for most,
Xand copying and changing others (note that \fI~rfs/sys\fP does not
Xexist yet, so be patient).
XThe files new to the kernel are:
X.DS
X~rfs/sys/remote/remotefs.h
X~rfs/sys/remote/rmt_data_template	(used to build rmt_data.c)
X~rfs/sys/remote/remote_mkdata	(used to build rmt_data.c)
X~rfs/sys/remote/rmt_exec.c
X~rfs/sys/remote/rmt_final.c
X~rfs/sys/remote/rmt_general.c
X~rfs/sys/remote/rmt_generic.c
X~rfs/sys/remote/rmt_io.c
X~rfs/sys/remote/rmt_subr.c
X~rfs/sys/remote/rmt_syscall1.c
X~rfs/sys/remote/rmt_syscall2.c
X~rfs/sys/remote/rmt_syscall3.c
X.DE
XThe files that must be changed in the kernel are:
X.DS
X~rfs/sys/h/errno.h
X~rfs/sys/h/param.h
X~rfs/sys/h/user.h
X~rfs/sys/machine/trap.c
X~rfs/sys/sys/init_sysent.c
X~rfs/sys/sys/kern_exec.c
X~rfs/sys/sys/kern_exit.c
X~rfs/sys/sys/sys_inode.c		(a semantic bug; fixed in 4.3)
X~rfs/sys/sys/ufs_nami.c		(ufs_namei.c in 4.3)
X~rfs/sys/sys/ufs_syscalls.c
X~rfs/sys/sys/uipc_socket.c	(the \fIrecv(2)\fP bug; fixed in 4.3)
X.DE
XFor configuration, there are a few files which must be changed
Xslightly:
X.DS
X~rfs/sys/conf/files
X~rfs/sys/conf/makefile.vax	(Makefile.vax in 4.3)
X.DE
XFinally,
Xthe source files for building the new system calls (see 
X\fBBuilding the User Programs\fP)
Xmust know about the new system call numbers.
XThis requires a
X(local) change to a file normally found in \fI/usr/include\fP:
X.DS
X~rfs/usr.include/syscalls.h
X.DE
X.NH 3
XEditing in the Changes (about 15 minutes)
X.PP
XAll of these files, or the changes that need to be made to them
Xare found in files of the same name (plus a \fI.diff\fP for the
Xpatch files) under \fI~rfs/remote/usr.*\fP.
XA shell program named \fI~rfs/remote/shells/rfs_setup\fP
Xhas been provided for setting up the symbolic links,
Xcopying files,
Xand patching in all the changes to the kernel using the \fBpatch\fP
Xutility which has been posted publicly to newsgroups such as \fInet.sources\fP
Xby Larry Wall\*(Fi.
XSome of the added kernel
Xsoftware contains \fIifdef\fPs for 4.3 BSD differences
Xwhich only clutter the code and cause problems
Xwhen you run \fImake depend\fP on BSD 4.2.
X\fI~Rfs_setup\fP will remove these.
X.FS
XIf you have never heard of the \fBpatch\fP program, I don't know how you ever
Xfound out about RFS.
XSend me a note and I will mail the source to you.
X.FE
XRunning \fIremote/shells/rfs_setup\fP will work for 4.2 and 4.3 BSD Vax systems,
Xand for Pyramid 90x systems running 2.5,
Xbut for other systems, you must examine the shell
Xscript to infer what it accomplishes.
XLet me emphasize again that you are not (and should not be)
Xediting the standard kernel sources.
X.DS
X% cd ~rfs
X% ./remote/shells/rfs_setup	# several questions will be asked
X.DE
X.NH 3
XEnsuring that RFS Software Does Not Interfere with the Kernel
X.PP
XThere are four variables defined in \fI~rfs/sys/remote/remotefs.h\fP
Xwhich must be examined to be sure that they fit in correctly with
Xthe rest of the kernel.
XTheir values in the distributed software have been chosen
Xso as not to conflict
Xwith VAX BSD 4.2 or 4.3, and Pyramid 2.5 software.
XIt will have to be changed for other Unix versions.
X.IP FREMOTE
Xis a flag that must not conflict with any other flags associated
Xwith the kernel \fIfile\fP structure.
XCheck in \fI/usr/sys/h/file.h\fP.
X.IP DTYPE_REMOTE
Xshould not conflict with DTYPE_INODE or DTYPE_SOCKET in
X\fI/usr/sys/h/file.h\fP.
XThis new file descriptor type means the
Xfix to \fIino_close()\fP in \fI~rfs/sys/sys/sys_inode.c\fP must be installed.
X.IP SREMOTE
Xmarks a process as having used a remote file system at some time.
XIt must be a unique bit for the \fIproc\fP structure element \fIp_flag\fP
Xas defined in \fI/usr/sys/h/proc.h\fP.
X.IP SNOREMOTE
Xmust also be a unique bit for the \fIproc\fP structure element \fIp_flag\fP.
XThis flag bit prevents any processes having it from using any remote
Xfile system.
XIt is used primarily by \fIrfs_server\fP to prevent ``hopping''
Xacross more than one machine with the remote file system.
X.NH 3
XSetting up VAX\*(Fi Configuration (about 10 minutes)
X.PP
X.FS
XPyramid software does not have a configuration file.
Xconfiguration is done with command\-line shell script arguments.
X.FE
XThe configuration file for VAX machines should now be in \fI~/rfs/sys/conf\fP,
Xbut it is a symbolic link to the real one in \fI/usr/sys/conf\fP,
Xlet us say, FOOVAX.
XYou should remove the link and copy it to this directory so
Xthat you can add three lines to it\*(Fi:
X.FS
XThe RFSDEBUG option gives you the ability to 
Xenable selective portions of the RFS kernel to give out
Xinformation about activity and problems.
XSee the section on debugging.
XCompiling it in has a negligible performance impact (<< %1)
Xif it is not used.
XYou can compile it out later by removing \fIrmt*.o\fP,
Xremoving the RFSDEBUG option line from the config file,
Xrunning config again, and recompiling.
X.FE
X.DS
Xoptions		REMOTEFS	# to compile in REMOTEFS changes
Xoptions		RFSDEBUG	# to compile in debug software (optional)
Xpseudo-device	remotefs		# to include the rfs software in the makefile
X
X	so
X
X% cd ~rfs/sys/conf
X% rm FOOVAX
X% cp /usr/sys/conf/FOOVAX .
X% vi FOOVAX
X< add in the three new lines >
X% mkdir ../FOOVAX			# for the config directory
X% config FOOVAX
X.DE
X.NH 3
XCompiling the RFS Kernel (about 90-120 minutes)
X.PP
XIf you have installed everything correctly
Xand if I have told you all that I should,
Xthen you should now be able to compile the kernel.
XNote that compilation is different for VAX and Pyramid.
X.DS
X	VAX
X% cd ~rfs/sys/FOOVAX
X% make depend
X% make
X
X	PYRAMID
X% mkdir ~rfs/sys/FOOVAX	# not made yet
X% cd ~rfs/sys/FOOVAX
X% cp ../conf/* .		# copy in configuration scripts and makefiles
X% makesys 64 VER=01 N	# you better check with your pyramid rep.
X.DE
XYou should boot the kernel to assure yourself that
Xit won't crash and to prepare for the remaining software.
X.NH 2
XBuilding the User Programs
X.PP
X\fIRmtmnt\fP is to a remote file system what \fI/etc/mount\fP is
Xto a disk file system.
XIn addition,
Xit provides statistics on currently active remote file systems.
X\fIRfs_server\fP
Xprovides name translation to the kernel for pathnames
Xbelow a generic mount point, e.g. \fI/net/foovax/etc/passwd\fP,
Xand it is the system call server which a client talks to.
X.PP
XThere are three new system calls added to the kernel,
Xand there are three new error numbers defined in \fI<errno.h>\fP.
XThe system calls
X\fIremoteon(2)\fP and \fIremoteoff(2)\fP turn on and
Xoff the remote file system,
Xand \fIremotename(2)\fP allows the
Xserver and kernel to talk to each other.
XHence, you must first make a new libc,
Xso that \fIrfs_server\fP and \fIrmtmnt\fP compile and link
Xwithout any undefined symbols,
Xand any new programs that get relinked will be able to print
Xa reasonable message using the standard library call, \fIperror(3)\fP.
X.NH 3
XBuilding a new \fIlibc.a\fP (about 10 minutes)
X.PP
XThe new system calls and the new error messages for \fI/lib/libc.a\fP are:
X.DS
X~rfs/remote/usr.src.lib.libc/gen/errlst.c.diff
X~rfs/remote/usr.src.lib.libc/{vax,pyr}/sys/remoteon.c
X~rfs/remote/usr.src.lib.libc/{vax,pyr}/sys/remoteoff.c
X~rfs/remote/usr.src.lib.libc/{vax,pyr}/sys/remotename.c
X.DE
XThe contents of \fIerrlst.c.diff\fP is a patch file for
X\fI/usr/src/lib/libc/gen/errlst.c\fP\*(Fi.
X.FS
XThe \fIMakefile\fP assumes that general source is in \fI/usr/src\fP.
XThis can be overridden with an assignment on the command line:
X.sp 1
X	# make vax SRC=/usr/othersrcdir
X.sp 1
X.FE
XThe file \fI~rfs/remote/usr.src.lib.libc/Makefile\fP
Xknows how to build a C\-library from the sources and patch files provided.
XBy default, the \fIMakefile\fP will install the new libc in
X\fI/lib/libc.a\fP\*(Fi so you must be root.
X.FS
XYou can install it in \fI~rfs/remote\fP
Xby changing the \fIMakefile\fP variable LIBDIR,
Xor by assigning it on the command line
X.sp 1
X	# make vax LIBDIR=..
X.sp 1
Xbut then you must remember to change the \fIMakefile\fP
Xin ~rfs/remote
Xafter it is generated by \fI~rfs/remote/shells/makemake\fP.
X.FE
X.DS
X% su root
XPassword:
X# cd ~rfs/remote/usr.src.lib.libc
X# make vax	# for VAX BSD 4.2 or 4.3
X	or
X# make pyr	# for Pyramid 2.5
X.DE
X.NH 3
XBuilding a Makefile for \fIRfs_server\fP, and \fIRmtmnt\fP (about 5 minutes)
X.PP
XThere are a variety of makefiles for building the server, \fIrfs_server\fP,
Xand each is built with a command called \fIshells/makemake\fP.
XCurrently there is support for a makefile
Xon a Vax that will run the RFS kernel, for
Xa Pyramid that will run the RFS kernel and
Xfor a Vax that will only be a server (running an ordinary kernel).
XEach is created\*(Fi
X.FS
XThe last command run will leave that kind of makefile in \fI./remote\fP.
X.FE
Xwith one of the following commands\*(Fi:
X.FS
XIf none of these fit your needs,
Xyou must design your own from the files \fImake.base*\fP.
XAn important part of the makefile is the byte\-ordering
Xfor the machine on which the server will run.
XIf your architecture is neither Vax nor Pyramid,
Xyou should compile the program \fI~rfs/remote/byteorder.c\fP
Xand run it to get its opinion.
X.FE
X.DS
X% cd ~rfs/remote
X% shells/makemake vax		# Vax with RFS kernel
X	or
X% shells/makemake vaxnorfs	# Vax without RFS kernel
X	or
X% shells/makemake pyramid	# Pyramid with RFS kernel
X.DE
X.NH 3
XCompiling \fIRmtmnt\fP and \fIRfs_server\fP (about 30 minutes)
X.PP
XNow, compile the server and \fIrmtmnt\fP program\*(Fi,
Xinstalling the binaries as root:
X.FS
XIf you put the new libc.a in ~rfs/remote, instead
Xof following the reccomended procedure,
Xyou should edit the makefile at this point.
X.FE
X.DS
X% cd ~rfs/remote
X% make
X% su root
XPassword:
X# make install
X.DE
X.NH 2
XOther Chores
X.PP
XAt this point,
Xyou should have an RFS kernel running on one or more machines,
Xcall them \fIclient\fPs, and the
Xpotential to run the RFS server on one or more machines,
Xcall them \fIserver\fPs\*(Fi.
X.FS
XAny machine can be both client and server,
Xeven with respect to itself.
X.FE
XBefore starting up any connections,
Xthere are a few extra items that should be tended to.
X.IP \(bu .125i
XAdd the service \fIremotefs\fP to \fI/etc/services\fP,
Xon all server and client machines.
XIt should be a privileged port number, i.e. less than 1024,
Xbecause the server runs as root and does a \fIseteuid(2)\fP
Xto whatever user it thinks it should be.
XI have used port 556 on the machines where I installed RFS.
X.IP \(bu .125i
XAdd the user \fIguest\fP to \fI/etc/passwd\fP on
Xeach server machine.
XThe default permissions for any access to a server machine
Xare mapped to guest (so it shouldn't have wide access).
XThe server process will refuse to run without this user id installed.
X.IP \(bu .125i
XIf you are on a Pyramid,
Xthere is no easy way to turn on the debugging software in the kernel,
Xso there is a program provided;
Xyou should compile it now hand have it ready.
XMore on debugging later.
X.DS
X% cd ~rfs/remote
X% make debug
X.DE
X.NH 2
XStarting up the software
X.PP
XThe server should be started as root.
XFor now, you start it by hand,
Xand then arrange for it to be started automatically.
XThis should be done on all machines that will be servers or
Xclients.
XRemember that \fI/etc/rfs_server\fP is slightly different for
Xa machine running the RFS kernel; see section \fB1.2.2\fP.
X.DS
X% su root
XPassword:
X# /etc/rfs_server
X# vi /etc/rc.local
X< insert at an appropriate place, the lines... >
X	if [ -f /etc/rfs_server ]; then
X		/etc/rfs_server & echo -n ' rfs_server'	>/dev/console
X	fi
X.DE
X.PP
XNext we should set up for loop\-back RFS access just to make
Xsure that everything works.
XNote that the mount point is a file,
Xnot a directory.
XThis is very important.
XThe design decisions are discussed in a separate paper
Xunder \fI~rfs/remote/doc/paper\fP.
XIn a nutshell,
Xusing a file for a mount point
Xallows the natural syntax for file access
X.DS
X% cp /foovax/etc/passwd /feevax/tmp/x
X.DE
Xbut prevents programs like
X.DS
X% find / -print
X.DE
Xfrom finding every file on every remote host.
X.PP
XIf your host name is foovax, then create the file /foovax and
Xmount your host.
XThe use of the file /foovax is not required,
Xbut only suggested as a convention\*(Fi.
XFoovax must be defined in \fI/etc/hosts\fP and \fIrfs_server\fP
Xshould be running.
X.FS
XIt has been pointed out to me that this convention
Xis slightly restrictive for machines whose owners choose
Xinteresting names such as bin and tmp.
X.FE
X.DS
X% touch /foovax
X% /etc/rmtmnt foovax /foovax
X.DE
XIn all likelyhood,
Xyou should not have crashed by this time,
Xbut if there are any problems with the way you installed the software,
Xthey will be encountered now.
XTry the commands
X.DS
X% ls -ld /foovax/
X% ls -ld /foovax/etc
X% ls -l /foovax/etc
X% cd /foovax/etc
X% pwd
X% ls
X.DE
XIf the machine crashes
Xor the result is not what you expected,
Xyou should pull out the stops and start debugging.
XSee the section on debugging.
XIf all goes well,
Xthen try mounting another host, say foo2vax:
X.DS
X% touch /foo2vax
X% /etc/rmtmnt foo2vax /foo2vax
X% ls -l /foo2vax/etc
X% ....
X.DE
XTry a generic mount point:
X.DS
X% touch /net
X% /etc/rmtmnt -g /net
X% more /net/anotherhost/etc/passwd
X.DE
X.PP
XFinally,
Xwhen you are satisfied that everything is working,
Xyou should install the mount commands in \fI/etc/rc.local\fP.
XNote that you don't really need the generic mount point
Xunless you have many workstations that you don't want to explicitly
Xmount.
X.DS
X% su root
XPassword:
X# /etc/rfs_server
X# vi /etc/rc.local
X< insert at an appropriate place, the lines... >
X	if [ -f /foovax ]; then
X		/etc/rmtmnt foovax /foovax
X	fi
X	if [ -f /foo2vax ]; then
X		/etc/rmtmnt foovax /foovax
X	fi
X	if [ -f /net ]; then
X		/etc/rmtmnt -v /net
X	fi
X.DE
X.NH 1
XGeneral Portability
X.PP
XI consider RFS to be ``installable'', not necessarily portable.
X.PP
XRFS's server, \fIrfs_server\fP,
Xdepends very heavily on the BSD signal mechanism,
Xinheirited file descriptors (sockets to the client),
Xand the \fIrecv(2)\fP system call using the MSG_PEEK flag.
X.PP
XThe RFS kernel depends very heavily on mbuf structures, and the BSD
Xsocket paradigm.
X.NH 1
XAccess Permissions over RFS
X.PP
XFor a greater understanding of this discussion,
Xand the terms ``sentry server'', ``gateway server'',
XI suggest that the reader familiarize himself
Xwith the \fIrfs_server(8)\fP man page.
XThe terms ``client'' and ``server'' are described in section \fI1.3\fP.
X.PP
XA permission map is compiled by \fIrfs_server\fP
Xwhen it starts up
Xbased on \fI/etc/hosts\fP, \fI/etc/passwd\fP and \fI.rhosts\fP files
Xunder every user's login directory.
XIn addition,
Xwhenever a client does a \fIrmtmnt\fP command,
Xthat command sends its \fI/etc/passwd\fP file to the sentry server.
XSimilarly,
Xif a server receives a call from a client,
Xbut has not received an \fI/etc/passwd\fP file,
Xthe server calls the client's server,
Xand asks for it\*(Fi.
X.FS
XIf this fails,
Xthen the server will return EIO
Xon all \fIread(2)\fP calls where the file descriptor
Xis to a directory,
Xbecause it doesn't know the client architecture's byte order.
X.FE
X.PP
XWhen a server receives a message from a client process
Xwhose uid number is \fIn\fP,
Xit consults the client's \fI/etc/passwd\fP file.
XIf it finds a matching uid number,
Xthen it checks\*(Fi to see if
Xthat uid name is allowed login privileges in some
Xuser's \fI.rhosts\fP file on the server.
XIf a user allows it,
Xthen the server for that process sets
Xthe effective user id
Xto that user's uid number (with \fIseteuid(2)\fP)
Xand sets the groups associated with that
Xuser (with \fIsetgroups(2)\fP).
X.FS
XMost of this checking is done when \fIrfs_server\fP first starts up,
Xand is kept in LRU lists for fast access.
XMappings from client uid to server uid are already done
Xby the time a client makes a connection.
X.FE
X.PP
XIf more than one user on the server host
Xallows login access to that client's user,
Xthen the last user in the server's \fI/etc/passwd\fP takes precedence.
XHowever,
Xif the one of the users on the server hosts has the same uid name
Xas that on the client,
Xthat mapping takes precedence over all other mappings.
XNote that this means the user \fIx\fP on may have remote
Xlogin privileges for users \fIy\fP and \fIz\fP,
Xbut his access permissions over RFS will be for one or the other,
Xnever both.
X.PP
XIf a user changes his \fI.rhosts\fP file on a server,
Xthat change is not noticed until the server is restarted.
XFortunately,
Xrestarting the server is simple:
Xjust run \fIrfs_server\fP again.
XAs long as the primary log \fI/usr/tmp/rfs_log\fP
Xstill exists which contains the process id number of the running server,
Xit is intelligent enough to shutdown the old server.
X.PP
XIf the server host on which the user wanted to change his \fI.rhosts\fP file
Xis currently connected to the client,
Xthat connection must be severed and a new one started.
XThis can be done by killing all processes
Xhaving the SREMOTE bit set\(*Fi on the client machine.
XThe \fI/etc/rmtmnt\fP command with no arguments will tell
Xyou how many processes are connected to each server.
X.FS
XThe command \fIps axl\fP will show all commands and their per\-process
Xflag bits.
Xsimply examine the left\-most field of the \fIps\fP output
Xlooking for the SREMOTE bit.
XUnfortunately,
Xmultiple remote systems may be open,
Xand \fIps\fP output does not show which process is using which remote hosts
Xor even if it is using multiple hosts.
X.FE
X.PP
XSimilarly,
Xif a new user is added to a client's \fI/etc/passwd\fP file,
Xor an existing user's uid number changes on a client,
Xthe \fIrfs_server\fP must be started again on each of the server machines,
Xor the remote file systems can be unmounted and mounted again using
X\fI/etc/rmtmnt\fP.
XAgain, however,
Xif the client host where the change was made is currently connected
Xto a server,
Xthen that connection must be severed and a new one started
Xas described above.
X.NH 1
XDebugging
X.PP
XAll kernel debugging is accomplished by setting the
Xglobal variable \fIremote_debug\fP.
XThe bit definitions are briefly explained in the
Xfile \fI~rfs/sys/remote/remotefs.h\fP.
X.PP
XDebugging on the server is explained briefly in the
Xman page for \fIrfs_server(8)\fP.
X.NH 2
XPlaces to Look if RFS Does Not Work
X.PP
XIf the kernel gets hung in startup or does not seem to do
Xsome of the system calls correctly
Xcheck the code inserted into \fI~rfs/sys/machine/trap.c\fP for
Xone of the following problems:
X.IP \(bu .125i
XOn the Vax,
Xthe declarations at the top of the routine are very position
Xdependent.
XRFS has some register declarations that must appear last
Xor the register allocation that the code depends on will be
Xmessed up.
X.IP \(bu .125i
XOn the Pyramid,
Xsystem calls are made by passing the arguments as arguments
X(the Vax copies them to an array).
XCheck to make sure that the code inserted is doing this right,
Xbecause I only tested it for a week.
X.PP
XOn the Pyramid,
Xdeclarations of variables inside of local blocks
Xsometimes causes the value of other local variables in outer blocks to
Xbe corrupted.
XFor example:
X.DS
X	routinex(arg1, ...)
X	{
X		register long	a, b, c, ...;	/* lots of variables */
X		...
X		x = y;
X
X		{ /* start a local block */
X			register long	z;
X
X			z = 1;
X		}
X	}
X.DE
XThe declaration and use of z
Xwill probably clobber one of the earlier variables \fIa, b, c, ...\fP.
XThis is a pretty bad compiler bug, but I think they are aware of it.
XThis kind of code was completely removed at one time from the
XRFS source code, but may have crept back in;
Xbe sure that you don't add any.
X.PP
XIf you \fIcd\fP to a remote directory,
Xbut it always appears as if you are still in the root directory for
Xthat machine,
Xit almost certainly has to do with \fIfork(2)\fP or \fIvfork(2)\fP
Xsystem calls not being sent to the server.
XCheck the generated table at the end of 
X\fI~rfs/sys/remote/rmt_data.c\fP to ensure that there is a \fIRFS_\fP
Xentry for both \fIfork(2)\fP and \fIvfork(2)\fP.
XIf there isn't, change it by hand or try to fix the shell file
Xthat generates it in \fI~rfs/sys/remote/remote_mkdata\fP.
X.NH 1
XMaking the Software Permanent
X.PP
XFirst,
Xread in the distribution tape again, this
Xtime putting it in \fI/usr/src/etc\fP;
Xthis will be the proper resting place for the software that
Xlives in the directory immediately below the first\-level directory,
X\fIremote\fP,
Xbecause the two commands \fI/etc/rfs_server\fP and \fI/etc/rmtmnt\fP
Xreside there.
X.PP
XSecond,
Xrerun the installation procedure,
Xthis time instructing \fIrfs_setup\fP to make the installation permanent,
Xinstead of in the current directory.
XThe only exception is that the software in \fI~rfs/remote/usr.src.lib.libc\fP
Xmust be copied by hand to /usr/src/lib/libc and placed in
Xthe proper directories there, modifying the \fImakefile\fP accordingly.
X.NH 1
XCurrent Bugs and Needed Extensions
X.PP
XThe bugs listed have only proved irritating for our environment,
Xbut worthy of note, none the less.
X.IP \(bu .125i
XWhen a client fails to connect to a server,
Xthe internal count of how many processes there are sometimes
Xgoes awry,
Xand the kernel (as seen by \fIrmtmnt\fP)
Xwill insist that it is still closing
Xwaiting for processes to die that aren't there.
XThe bug is almost certainly in \fIremote_getconnection()\fP.
X.IP \(bu .125i
XWhenever a connection goes down,
Xthere may be processes still up ``using'' that connection.
XHowever,
Xif there are no open files or remote \fIchdir(2)\fP's,
Xthe kernel could just as well restart the connection
Xwithout waiting for those processes to die.
XThis fix would go into \fIremote_getconnection()\fP.
X.IP \(bu .125i
XThe server has the beginnings of capability to
Xdo an asynchronous system call (like reading 10k of data),
Xbut it has not been fully implemented.
XA much better solution would be to implement an
Xatomic \fIwrite(2)\fP system call where
Xthe writer is guarenteed that no one else
Xwill be able to write on the same file descriptor (socket,
Xin this case)
Xuntil he is done.
XThis would allow servers to perform system calls
Xat their own pace sending the results back at any time.
X.IP \(bu .125i
XAlong the same lines,
Ximplementing an atomic message reader system call
Xthat would allow all servers to be blocked on a read
Xof the single socket connected to the client.
XThe reading server would provide a list of process id's
Xthat he is handling as input arguments along with
Xfile descriptor, buffer and size.
XThe kernel would slice up all the messages, handing
Xeach out to the server that is serving that process.
XThe only reason it wasn't implemented so far, was to keep the
Xserver standard.
X.IP \(bu .125i
XThe server maps two user id names with the same
Xnumber on a client to one user id on a server.
XThe reason is that only the uid number is sent in the messages
Xto the server.
XThere is no real fix for this.
X.IP \(bu .125i
XThe sentry server has the information about every host in
Xits memory and hands all this information off to each \fIgateway\fP
Xserver and its children even though it is never used.
XIf this was freed when each \fIgateway\fP
Xserver starts up, the servers would consume fewer memory
Xand swap resources.
X.IP \(bu .125i
XThe server currently does not handle \fI.rhosts\fP
Xfiles that have entries uttering only a host name.
XIt also ignores \fI/etc/hosts.equiv\fP.
X.IP \(bu .125i
XThis implementation ignores the possibility that the kernel COMPAT
Xoption may have been used.
XOld system calls should just fail.
X.IP \(bu .125i
XThe \fIpwd\fP command (and library call) does not work
Xwhile your current directory is under \fI/net/host/somedirectory\fP.
XBasically, the \fIpwd\fP command discovers that its current directory
Xis \fI/net/somedirectory\fP
Xbecause the \fIhost\fP is really only a virtual pathname component.
XBut when it tries to do
Xa \fIchdir(2)\fP back to it, it fails.
XThis is an irritating problem,
Xbut the only easy solution is for a change in the implementation,
Xsuch that \fI/net\fP becomes a directory, and the nameserver
Xcreates files and
Xdoes an explicit mount for any hosts that the kernel asks about.
XSo far I have resisted this because it requires another change
Xto the kernel routine \fInamei()\fP,
Xand because \fIpwd\fP works just fine if a host explicitly mounted.
X.IP \(bu .125i
XI think that RFS may be responsible for dropping an mbuf when a connection
Xfails, but this is apparently infrequent.
X.IP \(bu .125i
X\fIChroot(2)\fP system call is only partially implemented.
Xand should not be used with a remote directory as an argument.
X.IP \(bu .125i
XThe \fIselect(2)\fP and \fIioctl(2)\fP system calls are not yet implemented.
XThe latter means that the \fItip\fP command won't work with remote
Xpointers to tty dialers.
X.IP \(bu .125i
XThe server allows any unknown user on a client to see
Xits file system through the guest
Xaccount.
XThis is a good default.
XBut an appropriate extension
Xwould be a table describing a restricted domain of access,
Xso that if machines \fIx\fP and \fIy\fP appear in the table,
Xthey are allowed access through the normal permission scheme
Xdescribed above.
XHowever, any machine not in the table would be denied access in general,
Xso that only users on the client that have been allowed remote logins
Xvia \fI.rhosts\fP files can have access.
X.IP \(bu .125i
XNo fixes have been provided for \fImv(1)\fP or \fIcp(1)\fP
Xto distinguish the triple device/inode/host for uniqueness.
XThe information is available:
Xfor a local file,
Xthe \fIstat(2)\fP, \fIfstat(2)\fP and \fIlstat(2)\fP
Xsystem calls return a stat structure whose
X\fIst_spare1\fP element is 0.
XIf the file is remote,
Xthe \fIst_spare1\fP element contains the value \fIn\fP+1
Xwhere \fIn\fP is the number of the remote host mount point,
Xas shown by \fI/etc/rmtmnt\fP.
X.IP \(bu .125i
XThe server, \fIrfs_server\fP, does not correctly handle situations where
Xa host has more than one internet address.
XWhat happens is that all of the user access privileges
X(distilled from all the .rhosts files)
Xgets attached to one address, and when a call is made using the
Xother address, everyone only has the access of the \fIguest\fP user.
X.IP \(bu .125i
XSome user commands,
Xlike \fIchgrp(1)\fP and \fIrn(1)\fP
Xtry to guess ahead of time whether the kernel will allow you write
Xpermission on a file.
XHence, they will fail sometimes where they should not.
XFor example,
Xif your user id number on one host is 5 and on
Xanother host it is 6,
X\fIchgrp(1)\fP on one host
Xwill tell you that you cannot change the group of a file that resides on
Xanother host, even though RFS would allow it.
X.NH 1
XConclusions and Plans for the Future
X.PP
XRFS is not production quality,
Xbut is very useful,
Xproviding reasonably fast file access:
XI consider rcp unreasonable.
XI have made this software publicly available in hopes that other
Xinterested parties might contribute some of the fixes to it.
XI have other responsibilities and cannot afford to spend the
Xmany hours necessary to get that last 5 or 10% of quality,
Xbut perhaps you can help.
X.PP
XThe only hope for this software is that it is free and easy
Xto install and debug.
XI am more than willing to accept bug reports and fixes for it
Xuntil this or something else becomes part of the Berkeley Software
XDistribution.
SHAREOF
chmod 664 remote/doc/install.ms
#
# remote/doc/paper
#
mkdir remote/doc/paper
chmod 775 remote/doc/paper
#
# remote/doc/paper/Makefile
#
if [ -f remote/doc/paper/Makefile ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/paper/Makefile or ^C to quit' 
	read ans 
	rm -f remote/doc/paper/Makefile 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/paper/Makefile
XRFS = remotefs fig1.mag fig2.mag fig3.mag fig4.mag fig5.mag fig6.mag \
X	appendixB.out
X
Xrfs: $(RFS)
X	troff $(ONLY) -Tmag -mstek remotefs > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xlgp: $(RFS)
X	ltroff -mstek $(ONLY) remotefs
X
X#
X# run off figure 1 or 2 or 3
X#
Xf1: fig1.mag
X	troff -Tmag -mstek fig1.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf2: fig2.mag
X	troff -Tmag -mstek fig2.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf3: fig3.mag
X	troff -Tmag -mstek fig3.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf4: fig4.mag
X	troff -Tmag -mstek fig4.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf5: fig5.mag
X	troff -Tmag -mstek fig5.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf5: fig5.mag
X	troff -Tmag -mstek fig5.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
Xf6: fig6.mag
X	troff -Tmag -mstek fig6.mag > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
XA: appendixA.out
X	troff -Tmag -mstek appendixA.out > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
XB: appendixB.out
X	troff -Tmag -mstek appendixB.out > image
X	@sh -c "echo -n Waiting... ; read x"
X	dmag -w$(WIND) < image
X
X#
X# generate figure 1
X#
Xfig1.mag: fig1
X	/lib/cpp -Dfigure1 fig1 | sed -e '/^#/d' | pic -T100 > fig1.mag
Xfig1.lgp: fig1
X	/lib/cpp -Dfigure1 fig1 | sed -e '/^#/d' | pic > fig1.lgp
X
X#
X# generate figure 2
X#
Xfig2.mag: fig1
X	/lib/cpp -Dfigure2 fig1 | sed -e '/^#/d' | pic -T100 > fig2.mag
Xfig2.lgp: fig1
X	/lib/cpp -Dfigure2 fig1 | sed -e '/^#/d' | pic > fig2.lgp
X
X#
X# generate figure 3
X#
Xfig3.mag: fig1
X	/lib/cpp -Dfigure3 fig1 | sed -e '/^#/d' | pic -T100 > fig3.mag
Xfig3.lgp: fig1
X	/lib/cpp -Dfigure3 fig1 | sed -e '/^#/d' | pic > fig3.lgp
X
X#
X# generate figure 4
X#
Xfig4.mag: fig4
X	pic -T100 fig4 > fig4.mag
Xfig4.lgp: fig4
X	pic fig4 > fig4.lgp
X
X#
X# generate figure 5
X#
Xfig5.mag: fig5
X	pic -T100 fig5 > fig5.mag
Xfig5.lgp: fig5
X	pic fig5 > fig5.lgp
X
X#
X# generate figure 6
X#
Xfig6.mag: fig6
X	pic -T100 fig6 > fig6.mag
Xfig6.lgp: fig6
X	pic fig6 > fig6.lgp
X
X#
X# generate appendix A
X#
XappendixA.out: appendixA
X	tbl appendixA > appendixA.out
X
X#
X# generate appendix B
X#
XappendixB.out: appendixB
X	tbl appendixB > appendixB.out
SHAREOF
chmod 664 remote/doc/paper/Makefile
#
# remote/doc/paper/appendixB
#
if [ -f remote/doc/paper/appendixB ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/paper/appendixB or ^C to quit' 
	read ans 
	rm -f remote/doc/paper/appendixB 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/paper/appendixB
X.if "\*(.T"mag" \{\
X.	nr PS 12
X.	nr VS 14
X.	ps \n(PS
X.	vs \n(VS
X.	pl 9.5i
X.\}
X.ds LH \fBAppendix B\fP
X.BP
X.NH 1
XAppendix B
X.PP
XThese two tables contain the functions that must be ``changed'' for a remote
Xor distributed file system to work.
XThe column headings have the same meaning for both tables,
Xbut since some system calls have no before and after necessities (column 4),
Xit is clearer to put them by themselves in \fITable 1\fP.
X\fITable 2\fP has the rest of the system calls.
XThe first column, \fBSystem Call\fP, is the name of the system call
Xas found in section 2 of the UNIX User's Manual.
X.PP
XThe second column,
X\fBInteresting Arguments\fP,
Xlists the arguments that we are particularly interested in.
XFor example, \fIaccess()\fP, has two arguments, one a flag and one is
Xa path.
XThe path is noteworthy because we must find out what portion of the path
Xis on a remote host, and what remote host it is on.
XOther interesting arguments are those with two path names and those
Xhaving file descriptors.
XSome may not have any arguments worth considering,
Xbut are included because of important side effects.
X.PP
X\fBFollow Symlinks\fP shows whether \fInamei()\fP must follow
Xsymbolic links when determining ``remoteness'' (and is not applicable
Xto system calls that do not deal with path names).
XThis is an important point,
Xbut only for an implementation like \fBRemotefs\fP.
X\fBRemotefs\fP uses another system call, \fIisremote()\fP,
Xwhen determining what remote host a file is on and what portion
Xof the path is on that host.
XNow, the authors of 4.2
Xdecided when \fInamei()\fP may or may not follow a symbolic link,
Xand \fIisremote()\fP must do the same for whatever system call is
Xin operation.
X.PP
XThe last column, \fBSpecial Considerations Before & After the Syscall\fP,
Xshows what preparation
Xthe local host must do before
Xsending the system call to a remote host,
Xsuch as doing a local open to allocate a file descriptor
Xfor a \fIdup()\fP system call.
XThe fourth column shows the followup steps that should be taken
Xafter a successful remote system call.
X.PP
XThese descriptions assume that the system call has already been identified
Xas one that needs to be sent to a remote host.
XThat is,
Xat least one of the path names (for those system calls that deal with paths)
Xis remote,
Xor that the file descriptor passed as an argument to a system call is
Xto a remote file,
Xor even that there has been one or more remote system call requests
Xof some kind
X(\fIfork()\fP, \fIvfork()\fP, \fIumask()\fP, \fIexit()\fP).
X.BP
X.TS
Xtab(+) center box;
Xc | c | c
Xc | c | c
Xl | l | c.
X\fBSystem+Interesting+Follow\fR
X\fBCall+Arguments+Symlinks\fR
X=
X\fIaccess()\fP+One Path Name+yes+
X\fIstat()\fP+\^+\^
X\fIutimes()\fP+\^+\^
X\fItruncate()\fP+\^+\^
X_
X\fIchmod()\fP+One Path Name+no
X\fIchown()\fP+\^+\^
X\fIlstat()\fP+\^+\^
X\fImkdir()\fP+\^+\^
X\fImknod()\fP+\^+\^
X\fIrmdir()\fP+\^+\^
X\fIunlink()\fP+\^+\^
X_
X\fIfchmod()\fP+File Descriptor+n/a+
X\fIfchown()\fP+\^+\^
X\fIfcntl()\fP+\^+\^
X\fIflock()\fP+\^+\^
X\fIfstat()\fP+\^+\^
X\fIfsync()\fP+\^+\^
X\fIftruncate()\fP+\^+\^
X\fIioctl()\fP+\^+\^
X\fIlseek()\fP+\^+\^
X_
X.TE
X.ce 1
X\fITable 1\fP
X.BP
X.TS
Xtab(+) center box expand;
Xc | c | c | cw(3.5i)
Xc | c | c | cw(3.5i)
Xl | l | c | lw(3.5i).
X\fBSystem+Interesting+Follow+Special Considerations\fR
X\fBCall+Arguments+Symlinks+Before & After the Syscall\fR
X=
X\fIchdir()\fP+One Path Name+yes+T{
X\fBAfter:\fP
XMake note of the system and path name of the \fIchdir()\fP argument.
XT}
X_
X\fIclose()\fP+File Descriptor+n/a+T{
X\fBAfter:\fP
XClose the local file descriptor
XT}
X_
X\fIcreat()\fP+One Path Name+yes+T{
X\fBBefore:\fP
XAllocate a local file descriptor as a place\-holder.
X\fIDup2()\fP always closes the file descriptor in
Xits second argument in anticipation
Xof putting the new file descriptor at that ordinate value.
XThat file descriptor must be closed locally before sending
Xthe request to the remote host.
X.sp 1
X\fBAfter:\fP
XIf the system call was not successful, close the local one.
XAlso,
Xthere may need to be some mapping of file descriptors.
XFor instance,
Xthe local file descriptor may be 5 while the remote may be 6.
XHence, every request on fd 5 must be mapped to 6.
XAlternatively,
Xthe server may take care of the mapping if the local host sends
Xthe local file descriptor number to the remote host.
XT}
X\fIopen()\fP+One Path Name+\^+\^
X\fIdup()\fP+File Descriptor+\^+\^
X\fIdup2()\fP+File Descriptor+\^+\^
X_
X\fIexecv()\fP+One Path Name+yes+T{
X\fBAfter:\fP
XThe text for the program to be run must be copied
Xto the local swap space and executed from there.
XIf it is just a shell file, then it could be run normally,
Xwith the shell causing a remote open.
XT}
X\fIexecve()\fP+\^+\^+\^
X_
X\fIexit()\fP+None+n/a+T{
X\fBAfter:\fP
XThe \fIexit()\fP must be also run locally.
XT}
X_
X\fIfork()\fP+None+n/a+T{
X\fBBefore:\fP
XThe \fIfork()\fP or \fIvfork()\fP should be run locally first
Xto determine if the resources are available.
XT}
X\fIvfork()\fP+\^+\^+\^
X_
X\fIlink()\fP+Two Path Names+no+T{
X\fBBefore:\fP
XBoth path names must be on the same remote (or local) host.
XIf not, we can simulate failure locally.
XT}
X_
X\fIread()\fP+File Descriptor++T{
X\fBAfter:\fP
XThe data that was actually read by the system call
Xmust be gotten from the remote host.
XT}
X\fIreadlink()\fP+One Path Name+no+\^
X\fIreadv()\fP+File Descriptor++\^
X_
X\fIrename()\fP+Two Path Names+yes+T{
X\fBBefore:\fP
XThe two path names must both be on the same remote (or local)
Xhost.
XT}
X_
X\fIsymlink()\fP+Two Path Names+yes+T{
X\fBBefore:\fP
XOnly the second path name should be checked for ``remoteness''.
XT}
X_
X\fIumask()\fP+None+n/a+T{
X\fBAfter:\fP
X\fIumask()\fP must also be run locally.
XT}
X_
X\fIwrite()\fP+File Descriptor+n/a+T{
X\fBBefore:\fP
XThe data to be written must be sent to the remote host.
XT}
X\fIwritev()\fP+\^+\^+\^
X.TE
X.ce 1
X\fITable 2\fP
SHAREOF
chmod 664 remote/doc/paper/appendixB
#
# remote/doc/paper/fig1
#
if [ -f remote/doc/paper/fig1 ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/paper/fig1 or ^C to quit' 
	read ans 
	rm -f remote/doc/paper/fig1 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/paper/fig1
X.KF
X.if "\*(.T"mag" \{\
X.	nr PS 12
X.	nr VS 14
X.	ps \n(PS
X.	vs \n(VS
X.\}
X.PP
X.PS
X#ifdef figure1
Xboxht = .3i
Xboxwid = .8i
Xmovewid = .2i
XSyscalls: [
X	A: box "read()"; move
X	B: box "open()"; move
X	C: box "stat()"; move
X	D: box "..."
X]
X
Xboxht = last [].ht+1.2i
Xboxwid = last [].wid+.1i
XUserlevel: box dashed with .n at last [].n + (0i, .3i)
Xline from Syscalls.A.s to Userlevel.s
Xline from Syscalls.B.s to Userlevel.s
Xline from Syscalls.C.s to Userlevel.s
Xline from Syscalls.D.s to Userlevel.s
X"\s+4A User's Program\s-4" at Userlevel.se + (0, .075i) rjust
X#endif
X
X#ifdef figure1
Xboxwid = boxwid + 1.5i
Xboxht = boxht + 1i
XSystem: box dashed with .n at last box.s - (0, .3i)
X
X#else
Xboxwid = 5.5i
Xboxht = 2i
XSystem: box dashed
X#endif
X"\s+4UNIX Kernel\s-4" at System.se + (0, .075i) rjust
X
X#ifdef figure1
Xarrow from Userlevel.s to System.n
X#else
Xarrow from System.n + (0, .3i) to System.n
X#endif
Xboxht = .3i
Xboxwid = 1.5i
XSysinterface: box "Syscall Interface" dashed .02i with .n at System.n
X
Xboxht = .3i
Xboxwid = .8i
Xmovewid = .2i
XRwuio: box "rwuio()" with .w at System.w + (.1i, 0); move
XCopen: box "copen()"
X
Xmovewid = (-.2i)
XEtc: box "..." with .e at System.e - (.1i, 0)
XStat1: box "stat1()" with .e at Etc.w - (.2i, 0)
X
Xarrow from Sysinterface.s to Copen.n
X#ifdef figure1
Xarrow from Sysinterface.s to Rwuio.n
Xarrow from Sysinterface.s to Etc.n
Xarrow from Sysinterface.s to Stat1.n
X#endif
X
X#ifdef figure1
XNamei: box "namei()" at System.c - (0, .4i)
X#endif
X#ifdef figure2
XNamei: box "namei()" at System.c - (0, .4i)
X#endif
X#ifdef figure3
XNamei: box wid 1.8*boxwid ht 2.5*boxht at System.c - (0, .5i)
X"namei()" at Namei above
XRemotecheck: box wid 1.15*boxwid ht 1.3*boxht with .se at Namei.se
X"check for" at Remotecheck above
X"``remoteness''" at Remotecheck below
X#endif
X
Xspline -> right .4i from Copen.e then to Namei.n - (.1i, 0)
X#ifdef figure1
Xspline -> left .4i from Stat1.w then to Namei.n + (.1i, 0)
Xspline -> down .2i from Etc.s + (.025i, 0) then to Namei.e
X#endif
Xboxht = 1i
Xboxwid = 3i
X
XDevices: box dashed with .n at System.s - (0, .3i)
X"\s+4Device Drivers\s-4" at Devices.se + (0, .075i) rjust
Xboxht = .5i
Xboxwid = 1i
X
X#ifdef figure1
XDisk: box dashed .02i with .n at Devices.n
X#endif
X
X#ifdef figure2
XDisk: box dashed .02i with .ne at Devices.ne - (.2i, 0)
XPseudo: box dashed .02i with .nw at Devices.nw + (.2i, 0)
X"Pseudo\-Disk" at Pseudo above
X"Interface" at Pseudo below
X#endif
X
X#ifdef figure3
XDisk: box dashed .02i with .ne at Devices.ne - (.2i, 0)
XNet: box dashed .02i with .nw at Devices.nw + (.2i, 0)
X"Network" at Net above
X"Connection" at Net below
X#endif
X
X"Disk" at Disk above
X"Interface" at Disk below
X
X#ifdef figure1
Xarrow from Rwuio.s to Disk.n - (.025, 0)
Xarrow from Namei.s to Disk.n + (.025, 0)
X#endif
X#ifdef figure2
Xarrow from Rwuio.s to Pseudo.n - (.025, 0)
Xarrow from Namei.s to Pseudo.n + (.025, 0)
X#endif
X#ifdef figure3
Xarrow from Rwuio.s to Net.n - (.033, 0)
Xarrow from Copen.s to Net.n
Xarrow from Namei.s to Disk.n + (.025, 0)
X#endif
X.PE
X.ce
X#ifdef figure1
X\fIFigure 1\fP
X#endif
X#ifdef figure2
X\fIFigure 2\fP
X#endif
X#ifdef figure3
X\fIFigure 3\fP
X#endif
X.SP
X.KE
SHAREOF
chmod 664 remote/doc/paper/fig1
#
# remote/doc/paper/fig1.mag
#
if [ -f remote/doc/paper/fig1.mag ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/paper/fig1.mag or ^C to quit' 
	read ans 
	rm -f remote/doc/paper/fig1.mag 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/paper/fig1.mag
SHAREOF
chmod 644 remote/doc/paper/fig1.mag
#
# remote/doc/paper/fig4
#
if [ -f remote/doc/paper/fig4 ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/paper/fig4 or ^C to quit' 
	read ans 
	rm -f remote/doc/paper/fig4 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/paper/fig4
X.KF
X.if "\*(.T"mag" \{\
X.	nr PS 12
X.	nr VS 14
X.	ps \n(PS
X.	vs \n(VS
X.\}
X.PP
X.PS
Xboxht = .3i
Xboxwid = .8i
Xmovewid = .2i
XSyscalls: [
X	A: box "read()"; move
X	B: box "open()"; move
X	C: box "stat()"; move
X	D: box "..."
X]
Xboxwid = last [].wid
XRemotecheck: box with .nw at Syscalls.A.sw - (0, .15i)
X"check for ``remoteness''" at Remotecheck
X
Xboxht = last [].ht+1.2i
Xboxwid = last [].wid+.1i
XUserlevel: box dashed with .n at last [].n + (0i, .3i)
Xarrow from Syscalls.A.s to (Syscalls.A.s.x, Remotecheck.n.y)
Xarrow from Syscalls.B.s to (Syscalls.B.s.x, Remotecheck.n.y)
Xarrow from Syscalls.C.s to (Syscalls.C.s.x, Remotecheck.n.y)
Xarrow from Syscalls.D.s to (Syscalls.D.s.x, Remotecheck.n.y)
Xarrow from Remotecheck.s to Userlevel.s - (0, .3i)
X"\s+4A User's Program\s-4" at Userlevel.se + (0, .075i) rjust
X.PE
X.ce
X\fIFigure 4\fP
X.SP
X.KE
SHAREOF
chmod 664 remote/doc/paper/fig4
#
# remote/doc/paper/fig5
#
if [ -f remote/doc/paper/fig5 ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/paper/fig5 or ^C to quit' 
	read ans 
	rm -f remote/doc/paper/fig5 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/paper/fig5
X.DS
X.if "\*(.T"mag" \{\
X.	nr PS 12
X.	nr VS 14
X.	ps \n(PS
X.	vs \n(VS
X.\}
X.PS
Xboxht = boxht/2
Xboxwid = boxwid*2
XProto: [
X	A: box "request"
X	B: box "response" with .n at last box.s - (0, .1)
X	C: box "request" with .n at last box.s - (0, .1)
X	D: box "response" with .n at last box.s - (0, .1)
X	E: box "..." with .n at last box.s - (0, .1)
X]
XLocal: box "Local Host" with .e at last [].w - (1i, 0)
XRemote: box "Remote Host" with .w at last [].e + (1i, 0)
Xarrow from Local.e to Proto.A.w
Xarrow from Local.e to Proto.C.w
Xarrow from Local.e to Proto.E.w
Xarrow from Remote.w to Proto.B.e
Xarrow from Remote.w to Proto.D.e
X.PE
X.DE
SHAREOF
chmod 664 remote/doc/paper/fig5
#
# remote/doc/paper/fig6
#
if [ -f remote/doc/paper/fig6 ]; then 
	echo -n 'Hit <return> to overwrite remote/doc/paper/fig6 or ^C to quit' 
	read ans 
	rm -f remote/doc/paper/fig6 
fi 
 
sed -e 's/^.//' << \SHAREOF > remote/doc/paper/fig6
X.DS
X.if "\*(.T"mag" \{\
X.	nr PS 12
X.	nr VS 14
X.	ps \n(PS
X.	vs \n(VS
X.\}
X.PS
Xboxht = boxht/2
Xboxwid = boxwid*2
XProto: [
X	A: box "read request"
X	B: box "read response" with .n at last box.s - (0, .1)
X	C: box "read request" with .n at last box.s - (0, .1)
X	D: box "read response" with .n at last box.s - (0, .1)
X	E: box "continue" with .n at last box.s - (0, .1)
X	F: box "read response" with .n at last box.s - (0, .1)
X	G: box "read response" with .n at last box.s - (0, .1)
X	H: box "..." invis with .n at last box.s - (0, .1)
X	I: box "stop \fIn\fP" with .n at last box.s - (0, .1)
X	J: box "read response" with .n at last box.s - (0, .1)
X	K: box "read response" with .n at last box.s - (0, .1)
X	L: box "..." invis with .n at last box.s - (0, .1)
X	M: box "acknowledge" with .n at last box.s - (0, .1)
X]
XLocal: box "Local Host" with .e at last [].w - (1i, 0)
XRemote: box "Remote Host" with .w at last [].e + (1i, 0)
Xarrow from Local.e to Proto.A.w
Xarrow from Local.e to Proto.C.w
Xarrow from Local.e to Proto.E.w
Xarrow from Local.e to Proto.I.w
Xarrow from Remote.w to Proto.B.e
Xarrow from Remote.w to Proto.D.e
Xarrow from Remote.w to Proto.F.e
Xarrow from Remote.w to Proto.G.e
Xarrow from Remote.w to Proto.J.e
Xarrow from Remote.w to Proto.K.e
Xarrow from Remote.w to Proto.M.e
X.PE
X.DE
SHAREOF
chmod 664 remote/doc/paper/fig6



More information about the Mod.sources mailing list