Relay-Version: version B 2.10.3 beta 11/15/85; site seismo.CSS.GOV Posting-Version: version B 2.10.2 9/3/84; site panda.UUCP Path: seismo!harvard!talcott!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: RFS: remote file system (part 1 of 7) Message-ID: <1272@panda.UUCP> Date: 7 Jan 86 22:55:54 GMT Sender: jpn@panda.UUCP Lines: 2027 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 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 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 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 X#include 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; iu_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; iu_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; ih_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 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 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\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 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 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 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 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 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 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 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