home *** CD-ROM | disk | FTP | other *** search
- Subject: RFS: remote file system (part 1 of 7)
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- 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@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@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
-
-