This file describes various indirection tables used in the file system. I hope that this will be useful when trying to follow the control flow through function tables. The things here are ripped out of various source files. --Ken Shirriff 7/90 ****************************************************************************** But before we get to that, here is a map of what happens on an Fs_Open call. This traces the path through the different switch tables. The Fs_Open call has three main components, as numbered below. The two most important, the lookup (and name open) and io open sections, are traced separately, as numbered. --Mary Baker 9/91 Here is the format of this map: if procedure A calls procedures B and C, they as listed as Procedure A Procedure B Procedure C If a procedure D makes a function call through a switch table, switching on something called "type" to call procedure E, it is listed as Procedure D || type=x || Procedure E RPC's are shown with arrows: || \/ Enjoy Fs_Open 1) Fsprefix_LookupOperation(name, operation, ..., &openResults, ...) 2) streamPtr = Fsio_StreamAddClient(&openResults.streamID, ...) 3) fsio_StreamOpTable[type].ioOpen(openResults and streamData) 1) Fsprefix_LookupOperation(operation) domainType = GetPrefix(fileName) fs_DomainLookup[domainType][operation] // \\ op=FS_DOMAIN_OPEN, domainType=FS_LOCAL_DOMAIN REMOTE // \\ FslclOpen FsrmtOpen (see below) FslclLookup() fsio_OpenOpTable[descPtr->fileType].nameOpen // \\ type=FS_FILE type=FS_DEVICE // \\ Fsio_FileNameOpen Fsio_DeviceNameOpen Does some "ioOpen" Sets up ioServerID and whether stuff to avoid doing device is remote or local to extra rpc for files: client. This is for later cache consistency. ioOpen operation. FsrmtOpen (continued) RPC to Fsrmt_RpcOpen || \/ Fsrmt_RpcOpen prefixHandlePtr = fsio_StreamOpTable[prefixID.type].clientVerify(..., &domainType, ..) fs_DomainLookup[domainType][operation] // op=FS_DOMAIN_OPEN, domainType=FS_LOCAL_DOMAIN // FslclOpen (as above) 3) fsio_StreamOpTable[type].ioOpen // || \\ type=FSIO_LCL_FILE_STREAM FSIO_RMT_FILE_STREAM FSIO_RMT_DEVICE_STREAM // || \\ Fsio_FileIoOpen FsrmtFileIoOpen FsrmtDeviceIoOpen Sets up stream for local Set up a stream Sets type to LCL. disk file. Consistency for a remote file. Fsrmt_DeviceOpen and stuff was done in This means setting (see below) name open, above. up the recovery use counts. Fsrmt_DeviceOpen (continued) RPC to Fsrmt_RpcDevOpen || \/ Fsrmt_RpcDevOpen Maps rmt to lcl type. fsio_StreamOpTable[type].ioOpen // type=FSIO_LCL_DEVICE_STREAM // Fsio_DeviceIoOpen devFsOpTable[devHandlePtr->device.type].open to device-specific open proc. consistency ****************************************************************************** And now back to our regularly-scheduled programming: /* * OPEN SWITCH * The nameOpen procedure is used on the file server when opening streams or * setting up an I/O fileID for a file or device. It is keyed on * disk file descriptor types( i.e. FS_FILE, FS_DIRECTORY, FS_DEVICE, * FS_PSEUDO_DEVICE). The nameOpen procedure returns an ioFileID * used for I/O on the file, plus other data needed for the client's * stream. The streamIDPtr is NIL during set/get attributes, which * indicates that the extra stream information isn't needed. */ typedef struct Fsio_OpenOps { int type; /* One of the file descriptor types */ /* * The calling sequence for the nameOpen routine is: * FooNameOpen(handlePtr, clientID, useFlags, ioFileIDPtr, streamIDPtr, * sizePtr, dataPtr) * Fsio_FileIOHandle *handlePtr; * int clientID; * int useFlags; (From the stream) * Fs_FileID ioFileIDPtr; (Returned to client) * (The following arguments are ignored during set/get attrs) * (This case is indicated by a NIL streamIDPtr) * Fs_FileID streamIDPtr; (Returned to client,) * int *sizePtr; (Return size of data) * ClientData *dataPtr; (Extra return data) */ ReturnStatus (*nameOpen)(); } Fsio_OpenOps; /* * The OpenOps are called to do preliminary open-time processing. They * are called after pathname resolution has obtained a local file I/O handle * that represents a name of some object. The NameOpen routine maps * the attributes kept with the local file into an objectID (Fs_FileID) * and any other information needed to create an I/O stream to the object. */ This goes into fsio_OpenOpTable static Fsio_OpenOps ioOpenOps[] = { /* * FILE through SYMBOLIC_LINK are all the same. */ { FS_FILE, Fsio_FileNameOpen }, { FS_DIRECTORY, Fsio_FileNameOpen }, { FS_SYMBOLIC_LINK, Fsio_FileNameOpen }, /* * Remote devices are opened like ordinary devices, so the old * remote-device type is unused. */ { FS_DEVICE, Fsio_DeviceNameOpen }, /* * Local pipes. */ { FS_LOCAL_PIPE, Fsio_NoProc}, /* * Named pipes. Unimplemented, treat like a regular file. */ { FS_NAMED_PIPE, Fsio_FileNameOpen }, /* * Special file type for testing new kinds of files. */ { FS_XTRA_FILE, Fsio_FileNameOpen}, }; /* * Pseudo devices. */ static Fsio_OpenOps pdevOpenOps[] = { /* * Pseudo devices. */ {FS_PSEUDO_DEV, FspdevNameOpen}, { FS_PSEUDO_FS, Fsio_NoProc}, /* * A remote link can either be treated like a regular file, * or opened by a pseudo-filesystem server. */ { FS_REMOTE_LINK, FspdevRmtLinkNameOpen }, }; /* * Stream Types: * FSIO_STREAM Top level type for stream with offset. Streams * have an ID and are in the handle table to * support migration and shared stream offsets. * The remaining types are for I/O handles * FSIO_LCL_FILE_STREAM For a regular disk file stored locally. * FSIO_RMT_FILE_STREAM For a remote Sprite file. * FSIO_LCL_DEVICE_STREAM For a device on this host. * FSIO_RMT_DEVICE_STREAM For a remote device. * FSIO_LCL_PIPE_STREAM For an anonymous pipe buffered on this host. * FSIO_RMT_PIPE_STREAM For an anonymous pipe bufferd on a remote host. * This type arises from process migration. * FSIO_CONTROL_STREAM This is the stream used by the server for * a pseudo device to listen for new clients. * FSIO_SERVER_STREAM The main state for a pdev request-response * connection. Refereneced by the server's stream. * FSIO_LCL_PSEUDO_STREAM A client's handle on a request-response * connection to a local pdev server. * FSIO_RMT_PSEUDO_STREAM As above, but when the pdev server is remote. * FSIO_PFS_CONTROL_STREAM Control stream for pseudo-filesystems. * FSIO_PFS_NAMING_STREAM The request-response stream used for naming * operations in a pseudo-filesystem. This * I/O handle is hung off the prefix table. * FSIO_LCL_PFS_STREAM A clients' handle on a request-response * connection to a local pfs server. * FSIO_RMT_PFS_STREAM As above, but when the pfs server is remote. * FSIO_RMT_CONTROL_STREAM Needed only during get/set I/O attributes of * a pseudo-device whose server is remote. * FSIO_PASSING_STREAM Used to pass streams from a pseudo-device * server to its client in response to an open. * Internet Protocols (Not implemented in the kernel (yet?)) * FSIO_RAW_IP_STREAM Raw Internet Protocol stream. * FSIO_UDP_STREAM UDP protocol stream. * FSIO_TCP_STREAM TCP protocol stream. * * The following streams are not implemented * FS_RMT_NFS_STREAM NFS access implemented in kernel. * FS_RMT_UNIX_STREAM For files on the old hybrid unix/sprite server. * FS_LCL_NAMED_PIPE_STREAM Stream to a named pipe whose backing file * is on the local host. * FS_RMT_NAMED_PIPE_STREAM Stream to a named pipe whose backing file * is remote. */ /* * STREAM SWITCH * These procedures are called by top-level procedures (i.e. Fs_Read, * or Fs_Select) to do stream-type specific processing. */ typedef struct Fsio_StreamTypeOps { int type; /* Stream types defined in fs.h */ /* **************** Setup operation for clients. ************************* * This routine sets up an I/O handle for a stream. It uses streamData * that was genereated by the nameOpen routine on the file server. As * a side effect it fills in the nameInfoPtr->fileID for use later * when getting/setting attributes. * * FooIoOpen(ioFileIDPtr, flagsPtr, clientID, data, name, hdrPtrPtr) * Fs_FileID *ioFileIDPtr; (indicates object) * int *flagsPtr; (from the stream) * int clientID; (who's opening it) * ClientData data; (stream data from nameOpen) * char *name; (name for error messages) * Fs_HandleHeader **hdrPtrPtr; (Returned I/O handle) */ ReturnStatus (*ioOpen)(); /* **************** Regular I/O operations. ****************************** * These are the standard read/write routines. Note: they are passed * a stream pointer to support streams shared accross the network. * A shared stream is indicated by FS_RMT_SHARED in the ioPtr->flags. * Note that only the fileID and the ioHandlePtr of the streamPtr * is guaranteed to be valid. The stream-specific routine should ignore * the flags and offset kept (or not kept) in the stream structure. * * FooRead(streamPtr, ioPtr, waitPtr, replyPtr) * FooWrite(streamPtr, ioPtr, waitPtr, replyPtr) * Fs_Stream *streamPtr; (See above about valid fields ) * Fs_IOParam *ioPtr; (Standard parameter block) * Sync_RemoteWaiter *waitPtr; (For remote waiting) * Fs_IOReply *reply; (For return length and signal) */ ReturnStatus (*read)(); ReturnStatus (*write)(); /* **************** VM I/O operations. ****************************** * These are the read/write routines used by VM during paging. * The interface is the same as the regular read and write routines, * so those routines can be re-used, if appropriate. * * FooPageRead(streamPtr, ioPtr, waitPtr, replyPtr) * FoPageoWrite(streamPtr, ioPtr, waitPtr, replyPtr) * Fs_Stream *streamPtr; (See above about valid fields) * Fs_IOParam *ioPtr; (Standard parameter block) * Sync_RemoteWaiter *waitPtr; (For remote waiting) * Fs_IOReply *reply; (For return length and signal) */ ReturnStatus (*pageRead)(); ReturnStatus (*pageWrite)(); /* ***************** I/O Control. **************************************** * Stream-specific I/O controls. The main procedure Fs_IOControl * handles some generic I/O controls, and then passes the I/O control * down to the stream-specific handler. * * FooIOControl(hdrPtr, command, byteOrder, inBufSize, inBuf, outBufSize, outBuf) * Fs_HandleHeader *hdrPtr; (File handle) * int command; (Special operation) * int byteOrder; (client's byte order) * int inBufSize; (Size of inBuf) * Address inBuf; (Input data) * int outBufSize; (Size of outBuf) * Address outBuf; (Return data) */ ReturnStatus (*ioControl)(); /* ***************** Select. ********************************************* * The select interface includes three In/Out bit words. There is * at most one bit set in each, and the selectability can be easily * turned off by clearing the word. Never do anything to these * words other than leave them alone or clear them. * * FooSelect(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr) * Fs_HandleHeader *hdrPtr; (File handle) * Sync_RemoteWaiter *waitPtr; (Remote waiting info) * int *readPtr; (In/Out read bit) * int *writePtr; (In/Out write bit) * int *exceptPtr; (In/Out except bit) */ ReturnStatus (*select)(); /* **************** Attribute operations on open streams. ***************** * These just operate on the few attributes cached at the I/O server. * The name server is first contacted to set/initialize the attributes, * (either via the DOMAIN switch with pathnames, * or via the ATTRIBUTE switch with open streams) * and then these routines are called to complete the attributes from * ones cached on the I/O server, or to update the ones cached there. * * FooGetIOAttr(fileIDPtr, clientID, attrPtr) * FooSetIOAttr(fileIDPtr, attrPtr, flags) * Fs_FileID *fileIDPtr; (Identfies file) * int clientID; (Client getting attrs) * Fs_Attributes *attrPtr; (Attrs to set/update) * int flags; (which attrs to set) */ ReturnStatus (*getIOAttr)(); ReturnStatus (*setIOAttr)(); /* **************** Server verification of remote handle. ***************** * This returns the server's file handle given a client's fileID. * There are two parts to this task. The first is to map from the * client's fileID.type (i.e. FSIO_RMT_DEVICE_STREAM) to the server's * (i.e. FSIO_LCL_DEVICE_STREAM). The second step is to check that the * client is recorded in the clientList of the I/O handle. The domain * type is returned for use in naming operations. * * Fs_HandleHeader * * FooClientVerify(fileIDPtr, clientID, domainTypePtr) * Fs_FileID *fileIDPtr; (Client's handle) * int clientID; (The client hostID) * int *domainTypePtr; (may be NIL) */ Fs_HandleHeader *(*clientVerify)(); /* *************** Migration calls. ************************************** * * The 'release' is called on the source client of migration via an RPC * from the I/O server. Its job is to release any referneces * on the I/O handle that were due to a stream which has * now migrated away from the source client. * The 'migrate' is called from Fsio_DeencapStream to update client * book-keeping to reflect the migration. The version on * remote clients just does an RPC to the I/O server to * invoke the appropriate migrate routine there. * Important: If the FS_RMT_SHARED flag is present it means * that there is still a stream on the original client and its * references should not be removed from the I/O handle. * Also, if the FS_NEW_STREAM flag is present it means that * the stream is newly migrated to the client so references * should be added for the dstClient. * The 'migEnd' is called from Fsio_DeencapStream after the call to the * migrate procedure, but only the first time the stream * is migrated to the host. (After that it suffices to * add references to the existing stream.) * * FooRelease(hdrPtr, flags) * Fs_HandleHeader *hdrPtr; (File handle) * int flags; (From the stream) * FooMigEnd(migInfoPtr, size, data, hdrPtrPtr) * FsMigInfo migInfoPtr; (Migration state) * int size; (size of data) * ClientData data; (data from migrate) * Fs_HandleHeader **hdrPtrPtr; (Returned handle) * FooSrvMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr sizePtr, dataPtr) * FsMigInfo *migInfoPtr; (Migration state) * int dstClientID; (ID of target client) * int *flagsPtr; (In/Out Stream flags) * int *offsetPtr; (Return - new offset) * int *sizePtr; (Return - size of data) * Address *dataPtr; (Return data) */ ReturnStatus (*release)(); ReturnStatus (*migEnd)(); ReturnStatus (*migrate)(); /* *************** Recovery calls. **************************************** * This (should be) two routines, one called on client host's top * reopen at the server, and one called on the server in response * to a client's reopen request. * * FooReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr) * (The hdrPtr is only valid on clients.) * Fs_HandleHeader *hdrPtr; (Handle to re-open) * (The following are only valid on servers.) * int clientID; (client doing the re-open) * ClientData inData; (state from the client) * int *outSizePtr; (sizeof outData) * ClientData *outDataPtr; (state returned to client) */ ReturnStatus (*reopen)(); /* *************** Clean up operations. ********************************** * 'scavenge' is called periodically to clean up unneeded handles. * Important: the scavenge procedure must either remove or * unlock the handle it is still in use. * 'clientKill' is called to clean up after dead clients. This is * called before the scavenge routine if a periodic check * on the client fails, or called independently if some other * communication failure occurs. * 'close' is called when the last reference to a stream is closed. * This routine should clean up any use/reference counts * due to the stream as indicated by the flags argument. * * FooScavenge(hdrPtr) * Fs_HandleHeader *hdrPtr; (File handle) * FooClientKill(hdrPtr, clientID) * Fs_HandleHeader *hdrPtr; (File handle) * int clientID; (Client presumed down) * FooClose(hdrPtr, clientID, procID, flags, size, data) * Fs_HandleHeader *hdrPtr; (File handle) * int clientID; (Host ID of closer) * Proc_Pid procID; (ProcessID of closer) * int flags; (From the stream) * int size; (Size of data) * ClientData data; (Extra close data) */ Boolean (*scavenge)(); void (*clientKill)(); ReturnStatus (*close)(); } Fsio_StreamTypeOps; /* * Streams for Local files, device, and pipes */ This goes into fsio_StreamOpTable: static Fsio_StreamTypeOps ioStreamOps[] = { /* * Top level stream. This is created by Fs_Open and returned to clients. * This in turn references a I/O handle of a different stream type. The * main reason this exists as a handle is so that it can be found * during various cases of migration, although the reopen and scavenge * entry points in this table are used. */ { FSIO_STREAM, Fsio_NoProc, Fsio_NoProc, Fsio_NoProc,/* open, read, write */ Fsio_NoProc, Fsio_NoProc, /* pageRead, pageWrite */ Fsio_NoProc, Fsio_NoProc, /* iocontrol, select */ Fsio_NoProc, Fsio_NoProc, /* getIOAttr, setIOAttr */ Fsio_NoHandle, /* clientVerify */ Fsio_NoProc, Fsio_NoProc, /* release, migEnd */ Fsio_NoProc, /* migrate */ Fsio_StreamReopen, (Boolean (*)())NIL, /* scavenge */ Fsio_NullClientKill, Fsio_NoProc}, /* close */ /* * Local file stream. The file is on a local disk and blocks are * cached in the block cache. The GetIOAttr(SetIOAttr) routine * is Fsio_NullProc because all the work of getting(setting) cached attributes * is already done by FslclGetAttr(FslclSetAttr). */ { FSIO_LCL_FILE_STREAM, Fsio_FileIoOpen, Fsio_FileRead, Fsio_FileWrite, Fsio_FileRead, Fsio_FileWrite, /* Paging routines */ Fsio_FileIOControl, Fsio_FileSelect, Fsio_NullProc, Fsio_NullProc, /* Get/Set IO Attr */ Fsio_NoHandle, Fsio_FileMigClose, Fsio_FileMigOpen, Fsio_FileMigrate, Fsio_FileReopen, Fsio_FileScavenge, Fsio_FileClientKill, Fsio_FileClose}, /* * Local device stream. These routines branch to the device driver * for the particular device type. */ { FSIO_LCL_DEVICE_STREAM, Fsio_DeviceIoOpen, Fsio_DeviceRead, Fsio_DeviceWrite, Fsio_NoProc, Fsio_NoProc, /* Paging routines */ Fsio_DeviceIOControl, Fsio_DeviceSelect, Fsio_DeviceGetIOAttr, Fsio_DeviceSetIOAttr, Fsio_NoHandle, /* clientVerify */ Fsio_DeviceMigClose, Fsio_DeviceMigOpen, Fsio_DeviceMigrate, Fsrmt_DeviceReopen, Fsio_DeviceScavenge, Fsio_DeviceClientKill, Fsio_DeviceClose}, /* * Local anonymous pipe stream. */ { FSIO_LCL_PIPE_STREAM, Fsio_NoProc, Fsio_PipeRead, Fsio_PipeWrite, Fsio_NoProc, Fsio_NoProc, /* Paging routines */ Fsio_PipeIOControl, Fsio_PipeSelect, Fsio_PipeGetIOAttr, Fsio_PipeSetIOAttr, Fsio_NoHandle, /* clientVerify */ Fsio_PipeMigClose, Fsio_PipeMigOpen, Fsio_PipeMigrate, Fsio_PipeReopen, Fsio_PipeScavenge, Fsio_PipeClientKill, Fsio_PipeClose}, }; /* * File stream type ops for FSIO_RMT_FILE_STREAM, FSIO_RMT_DEVICE_STREAM, * and FSIO_RMT_PIPE_STREAM; */ static Fsio_StreamTypeOps rmtFileStreamOps[] = { /* * Remote file stream. The file is at a remote server but blocks might * be cached in the block cache. */ { FSIO_RMT_FILE_STREAM, FsrmtFileIoOpen, FsrmtFileRead, FsrmtFileWrite, FsrmtFilePageRead, FsrmtFilePageWrite, FsrmtFileIOControl, Fsio_FileSelect, FsrmtFileGetIOAttr, FsrmtFileSetIOAttr, FsrmtFileVerify, FsrmtFileMigClose, FsrmtFileMigOpen, FsrmtFileMigrate, FsrmtFileReopen, FsrmtFileScavenge, Fsio_NullClientKill, FsrmtFileClose}, /* * Remote device stream. Forward the operations to the remote I/O server. */ { FSIO_RMT_DEVICE_STREAM, FsrmtDeviceIoOpen, Fsrmt_Read, Fsrmt_Write, Fsio_NoProc, Fsio_NoProc, /* Paging routines */ Fsrmt_IOControl, Fsrmt_Select, Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, FsrmtDeviceVerify, Fsrmt_IOMigClose, Fsrmt_IOMigOpen, FsrmtDeviceMigrate, FsrmtDeviceReopen, Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose}, /* * Remote anonymous pipe stream. These arise because of migration. */ { FSIO_RMT_PIPE_STREAM, Fsio_NoProc, Fsrmt_Read, Fsrmt_Write, Fsio_NoProc, Fsio_NoProc, /* Paging routines */ Fsrmt_IOControl, Fsrmt_Select, Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, FsrmtPipeVerify, Fsrmt_IOMigClose, Fsrmt_IOMigOpen, FsrmtPipeMigrate, FsrmtPipeReopen, Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose}, }; /* * File stream type ops for FSIO_CONTROL_STREAM, FSIO_SERVER_STREAM, * and FSIO_LCL_PSEUDO_STREAM FSIO_RMT_PSEUDO_STREAM FSIO_PFS_CONTROL_STREAM * FSIO_PFS_NAMING_STREAM FSIO_LCL_PFS_STREAM FSIO_RMT_CONTROL_STREAM * FSIO_PASSING_STREAM */ static Fsio_StreamTypeOps pdevFileStreamOps[] = { /* * A control stream is what a pdev server process gets when it opens a * pseudo device file. This stream is used to notify the server * of new clients; the ID of the server stream set up for each * new client is passed over this control stream. */ { FSIO_CONTROL_STREAM, FspdevControlIoOpen, FspdevControlRead, Fsio_NoProc, Fsio_NoProc, Fsio_NoProc, /* Paging routines */ FspdevControlIOControl, FspdevControlSelect, FspdevControlGetIOAttr, FspdevControlSetIOAttr, FspdevControlVerify, Fsio_NoProc, Fsio_NoProc, /* migStart, migEnd */ Fsio_NoProc, FspdevControlReopen, /* migrate, reopen */ FspdevControlScavenge, FspdevControlClientKill, FspdevControlClose }, /* * A server stream gets set up for the server whenever a client opens * a pseudo device. The server reads the stream the learn about new * requests from the client. IOControls on the stream are used * to control the connection to the client. */ { FSIO_SERVER_STREAM, Fsio_NoProc, FspdevServerStreamRead, Fsio_NoProc, Fsio_NoProc, Fsio_NoProc, /* Paging I/O */ FspdevServerStreamIOControl, FspdevServerStreamSelect, Fsio_NullProc, Fsio_NullProc, /* Get/Set IO Attr */ Fsio_NoHandle, /* verify */ Fsio_NoProc, Fsio_NoProc, /* migStart, migEnd */ Fsio_NoProc, Fsio_NoProc, /* migrate, reopen */ (Boolean (*)())NIL, /* scavenge */ Fsio_NullClientKill, FspdevServerStreamClose }, /* * A pseudo stream with the server process running locally. */ { FSIO_LCL_PSEUDO_STREAM, FspdevPseudoStreamIoOpen, FspdevPseudoStreamRead, FspdevPseudoStreamWrite, FspdevPseudoStreamRead, FspdevPseudoStreamWrite, /* Paging */ FspdevPseudoStreamIOControl, FspdevPseudoStreamSelect, FspdevPseudoStreamGetIOAttr, FspdevPseudoStreamSetIOAttr, Fsio_NoHandle, /* verify */ FspdevPseudoStreamMigClose, FspdevPseudoStreamMigOpen, FspdevPseudoStreamMigrate, Fsio_NoProc, /* reopen */ (Boolean (*)())NIL, /* scavenge */ Fsio_NullClientKill, FspdevPseudoStreamClose }, /* * A pseudo stream with a remote server. */ { FSIO_RMT_PSEUDO_STREAM, FspdevRmtPseudoStreamIoOpen, Fsrmt_Read, Fsrmt_Write, Fsrmt_Read, Fsrmt_Write, /* Paging I/O */ Fsrmt_IOControl, Fsrmt_Select, Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, FspdevRmtPseudoStreamVerify, Fsrmt_IOMigClose, Fsrmt_IOMigOpen, FspdevRmtPseudoStreamMigrate, Fsio_NoProc, /* reopen */ Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose }, /* * A control stream used to mark the existence of a pseudo-filesystem. * The server doesn't do I/O to this stream; it is only used at * open and close time. */ { FSIO_PFS_CONTROL_STREAM, FspdevPfsIoOpen, Fsio_NoProc, Fsio_NoProc, /* read, write */ Fsio_NoProc, Fsio_NoProc, /* Paging I/O */ Fsio_NoProc, Fsio_NoProc, /* IOControl, select */ Fsio_NullProc, Fsio_NullProc, /* Get/Set IO Attr */ FspdevControlVerify, Fsio_NoProc, Fsio_NoProc, /* migStart, migEnd */ Fsio_NoProc, FspdevControlReopen, /* migrate, reopen */ FspdevControlScavenge, FspdevControlClientKill, FspdevControlClose }, /* * The 'naming stream' for a pseudo-filesystem is used to forward lookup * operations from the kernel up to the user-level server. It is like * a regular pdev request-response stream, except that extra connections * to it are established via the prefix table when remote Sprite hosts * import a pseudo-filesystem. The routines here are used to set this up. * This stream is only accessed locally. To remote hosts the domain is * a regular remote sprite domain, and the RPC stubs on the server then * switch out to either local-domain or pseudo-domain routines. */ { FSIO_PFS_NAMING_STREAM, FspdevPfsNamingIoOpen, Fsio_NoProc, Fsio_NoProc, /* read, write */ Fsio_NoProc, Fsio_NoProc, /* Paging I/O */ Fsio_NoProc, Fsio_NoProc, /* IOControl, select */ Fsio_NullProc, Fsio_NullProc, /* Get/Set IO Attr */ FspdevRmtPseudoStreamVerify, Fsio_NoProc, Fsio_NoProc, /* migStart, migEnd */ Fsio_NoProc, Fsio_NoProc, /* migrate, reopen */ Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose }, /* * A pseudo stream to a pseudo-filesystem server. This is just like * a pseudo stream to a pseudo-device server, except for the CltOpen * routine because setup is different. */ { FSIO_LCL_PFS_STREAM, FspdevPfsStreamIoOpen, FspdevPseudoStreamRead, FspdevPseudoStreamWrite, FspdevPseudoStreamRead, FspdevPseudoStreamWrite, /* Paging */ FspdevPseudoStreamIOControl, FspdevPseudoStreamSelect, FspdevPseudoStreamGetIOAttr, FspdevPseudoStreamSetIOAttr, Fsio_NoHandle, /* verify */ FspdevPseudoStreamMigClose, FspdevPseudoStreamMigOpen, FspdevPseudoStreamMigrate, Fsio_NoProc, /* reopen */ (Boolean (*)())NIL, /* scavenge */ Fsio_NullClientKill, FspdevPseudoStreamClose }, /* * A pseudo stream to a remote pseudo-filesystem server. This is * like the remote pseudo-device stream, except for setup because the * pseudo-device connection is already set up by the time the * CltOpen routine is called. */ { FSIO_RMT_PFS_STREAM, FspdevRmtPfsStreamIoOpen, Fsrmt_Read, Fsrmt_Write, Fsrmt_Read, Fsrmt_Write, /* Paging */ Fsrmt_IOControl, Fsrmt_Select, Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, FspdevRmtPseudoStreamVerify, Fsrmt_IOMigClose, Fsrmt_IOMigOpen, FspdevRmtPseudoStreamMigrate, Fsio_NoProc, /* reopen */ Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose }, /* * This stream type is only used during get/set I/O attributes when * the pseudo-device server is remote. No handles of this type are * actually created, only fileIDs that map to FSIO_CONTROL_STREAM. */ { FSIO_RMT_CONTROL_STREAM, Fsio_NoProc, /* ioOpen */ Fsio_NoProc, Fsio_NoProc, /* read, write */ Fsio_NoProc, Fsio_NoProc, /* Paging */ Fsio_NoProc, Fsio_NoProc, /* ioctl, select */ Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, (Fs_HandleHeader *(*)())Fsio_NoProc, /* verify */ Fsio_NoProc, Fsio_NoProc, /* release, migend */ Fsio_NoProc, Fsio_NoProc, /* migrate, reopen */ (Boolean (*)())NIL, /* scavenge */ (void (*)())Fsio_NoProc, Fsio_NoProc }, /* kill, close */ /* * Stream used to pass streams from a pseudo-device server to * a client in response to an open request. */ { FSIO_PASSING_STREAM, FspdevPassStream, Fsio_NoProc, Fsio_NoProc, /* read, write */ Fsio_NoProc, Fsio_NoProc, /* Paging */ Fsio_NoProc, Fsio_NoProc, /* ioctl, select */ Fsio_NoProc, Fsio_NoProc, /* get/set attr */ (Fs_HandleHeader *(*)())Fsio_NoProc, /* verify */ Fsio_NoProc, Fsio_NoProc, /* release, migend */ Fsio_NoProc, Fsio_NoProc, /* migrate, reopen */ (Boolean (*)())NIL, /* scavenge */ (void (*)())Fsio_NoProc, Fsio_NoProc }, /* kill, close */ }; /* * File stream type ops for FSIO_CONTROL_STREAM, FSIO_SERVER_STREAM, * and FSIO_LCL_PSEUDO_STREAM FSIO_RMT_PSEUDO_STREAM FSIO_PFS_CONTROL_STREAM * FSIO_PFS_NAMING_STREAM FSIO_LCL_PFS_STREAM FSIO_RMT_CONTROL_STREAM * FSIO_PASSING_STREAM */ static Fsio_StreamTypeOps pdevFileStreamOps[] = { /* * A control stream is what a pdev server process gets when it opens a * pseudo device file. This stream is used to notify the server * of new clients; the ID of the server stream set up for each * new client is passed over this control stream. */ { FSIO_CONTROL_STREAM, FspdevControlIoOpen, FspdevControlRead, Fsio_NoProc, Fsio_NoProc, Fsio_NoProc, /* Paging routines */ FspdevControlIOControl, FspdevControlSelect, FspdevControlGetIOAttr, FspdevControlSetIOAttr, FspdevControlVerify, Fsio_NoProc, Fsio_NoProc, /* migStart, migEnd */ Fsio_NoProc, FspdevControlReopen, /* migrate, reopen */ FspdevControlScavenge, FspdevControlClientKill, FspdevControlClose }, /* * A server stream gets set up for the server whenever a client opens * a pseudo device. The server reads the stream the learn about new * requests from the client. IOControls on the stream are used * to control the connection to the client. */ { FSIO_SERVER_STREAM, Fsio_NoProc, FspdevServerStreamRead, Fsio_NoProc, Fsio_NoProc, Fsio_NoProc, /* Paging I/O */ FspdevServerStreamIOControl, FspdevServerStreamSelect, Fsio_NullProc, Fsio_NullProc, /* Get/Set IO Attr */ Fsio_NoHandle, /* verify */ Fsio_NoProc, Fsio_NoProc, /* migStart, migEnd */ Fsio_NoProc, Fsio_NoProc, /* migrate, reopen */ (Boolean (*)())NIL, /* scavenge */ Fsio_NullClientKill, FspdevServerStreamClose }, /* * A pseudo stream with the server process running locally. */ { FSIO_LCL_PSEUDO_STREAM, FspdevPseudoStreamIoOpen, FspdevPseudoStreamRead, FspdevPseudoStreamWrite, FspdevPseudoStreamRead, FspdevPseudoStreamWrite, /* Paging */ FspdevPseudoStreamIOControl, FspdevPseudoStreamSelect, FspdevPseudoStreamGetIOAttr, FspdevPseudoStreamSetIOAttr, Fsio_NoHandle, /* verify */ FspdevPseudoStreamMigClose, FspdevPseudoStreamMigOpen, FspdevPseudoStreamMigrate, Fsio_NoProc, /* reopen */ (Boolean (*)())NIL, /* scavenge */ Fsio_NullClientKill, FspdevPseudoStreamClose }, /* * A pseudo stream with a remote server. */ { FSIO_RMT_PSEUDO_STREAM, FspdevRmtPseudoStreamIoOpen, Fsrmt_Read, Fsrmt_Write, Fsrmt_Read, Fsrmt_Write, /* Paging I/O */ Fsrmt_IOControl, Fsrmt_Select, Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, FspdevRmtPseudoStreamVerify, Fsrmt_IOMigClose, Fsrmt_IOMigOpen, FspdevRmtPseudoStreamMigrate, Fsio_NoProc, /* reopen */ Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose }, /* * A control stream used to mark the existence of a pseudo-filesystem. * The server doesn't do I/O to this stream; it is only used at * open and close time. */ { FSIO_PFS_CONTROL_STREAM, FspdevPfsIoOpen, Fsio_NoProc, Fsio_NoProc, /* read, write */ Fsio_NoProc, Fsio_NoProc, /* Paging I/O */ Fsio_NoProc, Fsio_NoProc, /* IOControl, select */ Fsio_NullProc, Fsio_NullProc, /* Get/Set IO Attr */ FspdevControlVerify, Fsio_NoProc, Fsio_NoProc, /* migStart, migEnd */ Fsio_NoProc, FspdevControlReopen, /* migrate, reopen */ FspdevControlScavenge, FspdevControlClientKill, FspdevControlClose }, /* * The 'naming stream' for a pseudo-filesystem is used to forward lookup * operations from the kernel up to the user-level server. It is like * a regular pdev request-response stream, except that extra connections * to it are established via the prefix table when remote Sprite hosts * import a pseudo-filesystem. The routines here are used to set this up. * This stream is only accessed locally. To remote hosts the domain is * a regular remote sprite domain, and the RPC stubs on the server then * switch out to either local-domain or pseudo-domain routines. */ { FSIO_PFS_NAMING_STREAM, FspdevPfsNamingIoOpen, Fsio_NoProc, Fsio_NoProc, /* read, write */ Fsio_NoProc, Fsio_NoProc, /* Paging I/O */ Fsio_NoProc, Fsio_NoProc, /* IOControl, select */ Fsio_NullProc, Fsio_NullProc, /* Get/Set IO Attr */ FspdevRmtPseudoStreamVerify, Fsio_NoProc, Fsio_NoProc, /* migStart, migEnd */ Fsio_NoProc, Fsio_NoProc, /* migrate, reopen */ Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose }, /* * A pseudo stream to a pseudo-filesystem server. This is just like * a pseudo stream to a pseudo-device server, except for the CltOpen * routine because setup is different. */ { FSIO_LCL_PFS_STREAM, FspdevPfsStreamIoOpen, FspdevPseudoStreamRead, FspdevPseudoStreamWrite, FspdevPseudoStreamRead, FspdevPseudoStreamWrite, /* Paging */ FspdevPseudoStreamIOControl, FspdevPseudoStreamSelect, FspdevPseudoStreamGetIOAttr, FspdevPseudoStreamSetIOAttr, Fsio_NoHandle, /* verify */ FspdevPseudoStreamMigClose, FspdevPseudoStreamMigOpen, FspdevPseudoStreamMigrate, Fsio_NoProc, /* reopen */ (Boolean (*)())NIL, /* scavenge */ Fsio_NullClientKill, FspdevPseudoStreamClose }, /* * A pseudo stream to a remote pseudo-filesystem server. This is * like the remote pseudo-device stream, except for setup because the * pseudo-device connection is already set up by the time the * CltOpen routine is called. */ { FSIO_RMT_PFS_STREAM, FspdevRmtPfsStreamIoOpen, Fsrmt_Read, Fsrmt_Write, Fsrmt_Read, Fsrmt_Write, /* Paging */ Fsrmt_IOControl, Fsrmt_Select, Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, FspdevRmtPseudoStreamVerify, Fsrmt_IOMigClose, Fsrmt_IOMigOpen, FspdevRmtPseudoStreamMigrate, Fsio_NoProc, /* reopen */ Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose }, /* * This stream type is only used during get/set I/O attributes when * the pseudo-device server is remote. No handles of this type are * actually created, only fileIDs that map to FSIO_CONTROL_STREAM. */ { FSIO_RMT_CONTROL_STREAM, Fsio_NoProc, /* ioOpen */ Fsio_NoProc, Fsio_NoProc, /* read, write */ Fsio_NoProc, Fsio_NoProc, /* Paging */ Fsio_NoProc, Fsio_NoProc, /* ioctl, select */ Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, (Fs_HandleHeader *(*)())Fsio_NoProc, /* verify */ Fsio_NoProc, Fsio_NoProc, /* release, migend */ Fsio_NoProc, Fsio_NoProc, /* migrate, reopen */ (Boolean (*)())NIL, /* scavenge */ (void (*)())Fsio_NoProc, Fsio_NoProc }, /* kill, close */ /* * Stream used to pass streams from a pseudo-device server to * a client in response to an open request. */ { FSIO_PASSING_STREAM, FspdevPassStream, Fsio_NoProc, Fsio_NoProc, /* read, write */ Fsio_NoProc, Fsio_NoProc, /* Paging */ Fsio_NoProc, Fsio_NoProc, /* ioctl, select */ Fsio_NoProc, Fsio_NoProc, /* get/set attr */ (Fs_HandleHeader *(*)())Fsio_NoProc, /* verify */ Fsio_NoProc, Fsio_NoProc, /* release, migend */ Fsio_NoProc, Fsio_NoProc, /* migrate, reopen */ (Boolean (*)())NIL, /* scavenge */ (void (*)())Fsio_NoProc, Fsio_NoProc }, /* kill, close */ }; /* * File stream type ops for FSIO_RMT_FILE_STREAM, FSIO_RMT_DEVICE_STREAM, * and FSIO_RMT_PIPE_STREAM; */ static Fsio_StreamTypeOps rmtFileStreamOps[] = { /* * Remote file stream. The file is at a remote server but blocks might * be cached in the block cache. */ { FSIO_RMT_FILE_STREAM, FsrmtFileIoOpen, FsrmtFileRead, FsrmtFileWrite, FsrmtFilePageRead, FsrmtFilePageWrite, FsrmtFileIOControl, Fsio_FileSelect, FsrmtFileGetIOAttr, FsrmtFileSetIOAttr, FsrmtFileVerify, FsrmtFileMigClose, FsrmtFileMigOpen, FsrmtFileMigrate, FsrmtFileReopen, FsrmtFileScavenge, Fsio_NullClientKill, FsrmtFileClose}, /* * Remote device stream. Forward the operations to the remote I/O server. */ { FSIO_RMT_DEVICE_STREAM, FsrmtDeviceIoOpen, Fsrmt_Read, Fsrmt_Write, Fsio_NoProc, Fsio_NoProc, /* Paging routines */ Fsrmt_IOControl, Fsrmt_Select, Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, FsrmtDeviceVerify, Fsrmt_IOMigClose, Fsrmt_IOMigOpen, FsrmtDeviceMigrate, FsrmtDeviceReopen, Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose}, /* * Remote anonymous pipe stream. These arise because of migration. */ { FSIO_RMT_PIPE_STREAM, Fsio_NoProc, Fsrmt_Read, Fsrmt_Write, Fsio_NoProc, Fsio_NoProc, /* Paging routines */ Fsrmt_IOControl, Fsrmt_Select, Fsrmt_GetIOAttr, Fsrmt_SetIOAttr, FsrmtPipeVerify, Fsrmt_IOMigClose, Fsrmt_IOMigOpen, FsrmtPipeMigrate, FsrmtPipeReopen, Fsutil_RemoteHandleScavenge, Fsio_NullClientKill, Fsrmt_IOClose}, }; /* * fs_DomainLookup: * Domain specific routine table for lookup operations. * The following operate on a single pathname. They are called via * Fsprefix_LookupOperation with arguments described in fsOpTable.h * DomainImport * DomainExport * DomainOpen * DomainGetAttrPath * DomainSetAttrPath * DomainMakeDevice * DomainMakeDir * DomainRemove * DomainRemoveDir * The following operate on two pathnames. * DomainRename * DomainHardLink */ /* * THIS ARRAY INDEXED BY DOMAIN TYPE. Do not arbitrarily insert entries. */ ReturnStatus (*fs_DomainLookup[FS_NUM_DOMAINS][FS_NUM_NAME_OPS])() = { /* FS_LOCAL_DOMAIN */ /* FS_REMOTE_SPRITE_DOMAIN */ /* FS_PSEUDO_DOMAIN */ /* FS_NFS_DOMAIN */ }; static ReturnStatus (*lclDomainLookup[FS_NUM_NAME_OPS])() = { Fsio_NoProc, FslclExport, FslclOpen, FslclGetAttrPath, FslclSetAttrPath, FslclMakeDevice, FslclMakeDir, FslclRemove, FslclRemoveDir, FslclRename, FslclHardLink, }; static ReturnStatus (*rmtDomainLookup[FS_NUM_NAME_OPS])() = { FsrmtImport, Fsio_NoProc, FsrmtOpen, FsrmtGetAttrPath, FsrmtSetAttrPath, FsrmtMakeDevice, FsrmtMakeDir, FsrmtRemove, FsrmtRemoveDir, FsrmtRename, FsrmtHardLink }; static ReturnStatus (*pdevDomainLookup[FS_NUM_NAME_OPS])() = { Fsio_NoProc, FspdevPfsExport, FspdevPfsOpen, FspdevPfsGetAttrPath, FspdevPfsSetAttrPath, FspdevPfsMakeDevice, FspdevPfsMakeDir, FspdevPfsRemove, FspdevPfsRemoveDir, FspdevPfsRename, FspdevPfsHardLink }; /* * Domain specific get/set attributes table. These routines are used * to get/set attributes on the name server given a fileID (not a pathname). */ Fs_AttrOps fs_AttrOpTable[FS_NUM_DOMAINS] = { /* FS_LOCAL_DOMAIN */ /* FS_REMOTE_SPRITE_DOMAIN */ /* FS_PSEUDO_DOMAIN */ /* FS_NFS_DOMAIN */ }; /* * Domain specific get/set attributes table. These routines are used * to get/set attributes on the name server given a fileID (not a pathname). */ static Fs_AttrOps rmtAttrOpTable = { FsrmtGetAttr, FsrmtSetAttr }; static Fs_AttrOps lclAttrOpTable = { FslclGetAttr, FslclSetAttr }; static Fs_AttrOps pdevAttrOpTable = { FspdevPseudoGetAttr, FspdevPseudoSetAttr }; static Fs_AttrOps rmtAttrOpTable = { FsrmtGetAttr, FsrmtSetAttr }; Cache backend routines: typedef struct Fscache_BackendRoutines { /* * FooAllocate(hdrPtr, offset, bytes, flags, blockAddrPtr, newBlockPtr) * Fs_HandleHeader *hdrPtr; (File handle) * int offset; (Byte offset) * int bytes; (Bytes to allocate) * int flags; (FSCACHE_DONT_BLOCK) * int *blockAddrPtr; (Returned block number) * Boolean *newBlockPtr; (TRUE if new block) * FooTruncate(hdrPtr, size, delete) * Fs_HandleHeader *hdrPtr; (File handle) * int size; (New size) * Boolean delete; (TRUE if file being * removed) * FooBlockRead(hdrPtr, blockPtr,remoteWaitPtr) * Fs_HandleHeader *hdrPtr; (File handle) * Fscache_Block *blockPtr; (Cache block to read) * Sync_RemoteWaiter *remoteWaitPtr; (For remote waiting) * FooBlockWrite(hdrPtr, blockPtr, lastDirtyBlock) * Boolean lastDirtyBlock; (Indicates last block) * FooReallocBlock(data, callInfoPtr) * ClientData data = blockPtr; (Cache block to realloc) * Proc_CallInfo *callInfoPtr; * FooStartWriteBack(backendPtr) * Fscache_Backend *backendPtr; (Backend to start writeback.) */ ReturnStatus (*allocate) _ARGS_((Fs_HandleHeader *hdrPtr, int offset, int numBytes, int flags, int *blockAddrPtr, Boolean *newBlockPtr)); ReturnStatus (*truncate) _ARGS_((Fs_HandleHeader *hdrPtr, int size, Boolean delete)); ReturnStatus (*blockRead) _ARGS_((Fs_HandleHeader *hdrPtr, Fscache_Block *blockPtr, Sync_RemoteWaiter *remoteWaitPtr)); ReturnStatus (*blockWrite) _ARGS_((Fs_HandleHeader *hdrPtr, Fscache_Block *blockPtr, int flags)); void (*reallocBlock) _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr)); ReturnStatus (*startWriteBack) _ARGS_((struct Fscache_Backend *backendPtr)); } Fscache_BackendRoutines; static Fscache_BackendRoutines ofsBackendRoutines = { Fsdm_BlockAllocate, Fsdm_FileTrunc, Fsdm_FileBlockRead, Fsdm_FileBlockWrite, Ofs_ReallocBlock, Ofs_StartWriteBack, } static Fscache_BackendRoutines fsrmtBackendRoutines = { FsrmtFileBlockAllocate, FsrmtFileTrunc, FsrmtFileBlockRead, FsrmtFileBlockWrite, FsrmtReallocBlock, FsrmtStartWriteBack, }; static Fscache_BackendRoutines lfsBackendRoutines = { Fsdm_BlockAllocate, Fsdm_FileTrunc, Fsdm_FileBlockRead, Fsdm_FileBlockWrite, Lfs_ReallocBlock, Lfs_StartWriteBack, };