diff options
author | Michael I. Bushnell <mib@gnu.org> | 1994-06-02 20:36:18 +0000 |
---|---|---|
committer | Michael I. Bushnell <mib@gnu.org> | 1994-06-02 20:36:18 +0000 |
commit | d1512b68d7f5bc9ef77b0ba73f65105029c3d2b6 (patch) | |
tree | 38f138fc360f09b10dadca85ff59fa16921f13cb | |
parent | 3041ad64ac920872650a5ea5cd782c61e10eb726 (diff) |
Initial revision
-rw-r--r-- | libdiskfs/diskfs.h | 775 |
1 files changed, 775 insertions, 0 deletions
diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h new file mode 100644 index 00000000..70af633f --- /dev/null +++ b/libdiskfs/diskfs.h @@ -0,0 +1,775 @@ +/* Definitions for fileserver helper functions + Copyright (C) 1994 Free Software Foundation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _HURD_DISKFS +#define _HURD_DISKFS + +#ifdef MAKING_DISKFS +#include "../machine/diskfs_machdep.h" +#else +#include <hurd/machine/diskfs_machdep.h> +#endif + +/* Each user port referring to a file points to one of these + (with the aid of the ports library. */ +struct protid +{ + struct port_info pi; /* libports info block */ + + /* User identification */ + uid_t *uids, *gids; + int nuids, ngids; + + /* Object this refers to */ + struct peropen *po; + + /* Shared memory I/O information. */ + memory_object_t shared_object; + struct shared_io *mapped; +}; + +/* One of these is created for each node opened by dir_pathtrans. */ +struct peropen +{ + int filepointer; + int lock_status; + int refcnt; + int openstat; + struct node *np; +}; + +/* A unique one of these exists for each node currently in use (and + possibly for some not currently in use, but with links) in the + filesystem. */ +struct node +{ + struct node *next, **prevp; + + struct disknode *dn; + + struct stat dn_stat; + + /* Stat has been modified if one of the following four fields + is nonzero. Also, if one of the dn_set_?time fields is nonzero, + the appropriate dn_stat.st_?time field needs to be updated. */ + int dn_set_ctime; + int dn_set_atime; + int dn_set_mtime; + int dn_stat_dirty; + + struct mutex lock; + + int references; /* hard references */ + int light_references; /* light references */ + + int owner; + + struct trans_link translator; + + struct lock_box userlock; + + struct conch conch; + + off_t allocsize; +}; + +/* Possibly lookup types for diskfs_lookup call */ +enum lookup_type +{ + LOOKUP, + CREATE, + REMOVE, + RENAME, +}; + +/* Special flag for diskfs_lookup. */ +#define SPEC_DOTDOT 0x10000000 + + +/* Declarations of variables the library sets. */ + +extern mach_port_t diskfs_host_priv; /* send right */ +extern mach_port_t diskfs_master_device; /* send right */ +extern mach_port_t diskfs_default_pager; /* send right */ +extern mach_port_t diskfs_exec_ctl; /* send right */ +extern mach_port_t diskfs_exec; /* send right */ +extern auth_t diskfs_auth_server_port; /* send right */ + + +extern struct port_info *diskfs_control_port; + +extern volatile struct mapped_time_value *diskfs_mtime; + +extern int diskfs_bootflags; +extern char *diskfs_bootflagarg; + +extern spin_lock_t diskfs_node_refcnt_lock; + +extern int pager_port_type; + + +struct pager; + + + +/* Declarations of things the user must or may define. */ + +/* The user must define this type. This should hold information + between calls to diskfs_lookup and diskfs_dir{enter,rewrite,rename} + so that those calls work as described below. */ +struct dirstat; + +/* The user must define this variable; it should be the size in bytes + of a struct dirstat. */ +extern size_t diskfs_dirstat_size; + +/* The user must define this variable; it is the maximum number of + links to any one file. The implementation of dir_rename does not know + how to succeed if this is only one; on such formats you need to + reimplement dir_rename yourself. */ +extern int diskfs_link_max; + +/* The user must define this variable; it is the maximum number of + symlinks to be traversed within a single call to dir_pathtrans. + If this is exceeded, dir_pathtrans will return ELOOP. */ +extern int diskfs_maxsymlinks; + +/* The user must define this variable and set it if the filesystem + should be readonly. */ +extern int diskfs_readonly; + +/* The user must define this variable. Set this to be an unauthenticated + port to the directory which should be `..' from root. If this is + *the* root, then set this to MACH_PORT_NULL. */ +extern file_t diskfs_dotdot_file; + +/* The user must define this variable. Set this to be the node + of root of the filesystem. */ +extern struct node *diskfs_root_node; + +/* The user must define this variable. Set this to the name of the + filesystem server. */ +extern char *diskfs_server_name; + +/* The user must define these variables. Set these to be the major, minor, + and edit version numbers. */ +extern int diskfs_major_version; +extern int diskfs_minor_version; +extern int diskfs_edit_version; + +/* The user may define this variable. This should be nonzero iff the + filesystem format supports shortcutting symlink translation. */ +int diskfs_shortcut_symlink; + +/* The user may define this variable. This should be nonzero iff the + filesystem format supports shortcutting chrdev translation. */ +int diskfs_shortcut_chrdev; + +/* The user may define this variable. This should be nonzero iff the + filesystem format supports shortcutting blkdev translation. */ +int diskfs_shortcut_blkdev; + +/* The user may define this variable. This should be nonzero iff the + filesystem format supports shortcutting fifo translation. */ +int diskfs_shortcut_fifo; + +/* The user may define this variable. This should be nonzero iff the + filesystem format supports shortcutting ifsock translation. */ +int diskfs_shortcut_ifsock; + +/* The user must define this function. Set *STATFSBUF with + appropriate values to reflect the current state of the filesystem. */ +error_t diskfs_set_statfs (fsys_statfsbuf_t *statfsbuf); + +/* The user must define this function. Lookup in directory DP (which + is locked) the name NAME. TYPE will either be LOOKUP, CREATE, + RENAME, or REMOVE. CRED identifies the user making the call. + + If the name is found, return zero, and (if NP is nonzero) set *NP + to point to the node for it, locked. If the name is not found, + return ENOENT, and (if NP is nonzero) set *NP to zero. + + If DS is nonzero then: + For LOOKUP: set *DS to be ignored by diskfs_drop_dirstat. + For CREATE: on success, set *DS to be ignored by diskfs_drop_dirstat. + on failure, set *DS for a future call to diskfs_direnter. + For RENAME: on success, set *DS for a future call to diskfs_dirrewrite. + on failure, set *DS for a future call to diskfs_direnter. + For REMOVE: on success, set *DS for a future call to diskfs_dirremove. + on failure, set *DS to be ignored by diskfs_drop_dirstat. + The caller of this function guarantees that if DS is nonzero, then + either the appropriate call listed above or diskfs_drop_dirstat will + be called with DS before the directory DP is unlocked, and guarantees + that no lookup calls will be made on this directory between this + lookup and the use (or descruction) of *DS. + + If you use the library's versions of diskfs_rename_dir, + diskfs_clear_directory, and diskfs_init_dir, then lookups for `..' + might have the flag SPEC_DOTDOT or'd in. This has the following special + meaning: + For LOOKUP: DP should be unlocked and its reference dropped before + returning. + For RENAME and REMOVE: The node being found (*NP) is already held + locked, so don't lock it or add a reference to it. + (SPEC_DOTDOT will not be given with CREATE.) + + Return ENOTDIR if DP is not a directory. + Return EACCES if CRED isn't allowed to search DP. + Return EACCES if completing the operation will require writing + the directory and diskfs_checkdirmod won't allow the modification. + Return ENOENT if NAME isn't in the directory. + Return EAGAIN if NAME refers to the `..' of this filesystem's root. + Return EIO if appropriate. +*/ +error_t diskfs_lookup (struct node *dp, char *name, enum lookup_type type, + struct node **np, struct dirstat *ds, + struct protid *cred); + +/* The user must define this function. Add NP to directory DP + under the name NAME. This will only be called after an + unsuccessful call to diskfs_lookup of type CREATE or RENAME; DP + has been locked continuously since that call and DS is as that call + set it, NP is locked. CRED identifies the user responsible + for the call (to be used only to validate directory growth). */ +error_t diskfs_direnter (struct node *dp, char *name, + struct node *np, struct dirstat *ds, + struct protid *cred); + +/* The user must define this function. This will only be called after + a successful call to diskfs_lookup of type RENAME; this call should change + the name found in directory DP to point to node NP instead of its previous + referent. DP has been locked continuously since the call to diskfs_lookup + and DS is as that call set it; NP is locked. */ +error_t diskfs_dirrewrite (struct node *dp, struct node *np, + struct dirstat *ds); + +/* The user must define this function. This will only be called after a + successful call to diskfs_lookup of type REMOVE; this call should remove + the name found from the directory DS. DP has been locked continuously since + the call to diskfs_lookup and DS is as that call set it. */ +error_t diskfs_dirremove (struct node *dp, struct dirstat *ds); + +/* The user must define this function. DS has been set by a previous + call to diskfs_lookup on directory DP; this function is + guaranteed to be called if none of + diskfs_dir{enter,rename,rewrite} is, and should free any state + retained by a struct dirstat. DP has been locked continuously since + the call to diskfs_lookup. */ +error_t diskfs_drop_dirstat (struct node *dp, struct dirstat *ds); + +/* The user must define this function. For locked node NP, return nonzero + iff there is a translator program defined for the node. */ +int diskfs_node_translated (struct node *np); + +/* The user must define this function. For locked node NP (for which + diskfs_node_translated is true) look up the name of its translator. + If the length is <= *NAMELEN, then store the name into **NAMEP; otherwise + set *NAMEP to newly vm_allocate'd storage holding the name. Set + *NAMELEN to the length of the name. */ +error_t diskfs_get_translator (struct node *np, char **namep, u_int *namelen); + +/* The user must define this function. For locked node NP, set + the name of the translating program to be NAME, length NAMELEN. CRED + identifies the user responsible for the call. */ +error_t diskfs_set_translator (struct node *np, char *name, u_int namelen, + struct protid *cred); + +/* The user must define this function. Truncate locked node NP to be SIZE + bytes long. (If NP is already less than or equal to SIZE bytes + long, do nothing.) */ +error_t diskfs_truncate (struct node *np, off_t size); + +/* The user must define this function. Grow the disk allocated to locked node + NP to be at least SIZE bytes, and set NP->allocsize to the actual + allocated size. (If the allocated size is already SIZE bytes, do + nothing.) CRED identifies the user responsible for the call. */ +error_t diskfs_grow (struct node *np, off_t size, struct protid *cred); + +/* The user must define this function. Write to disk (synchronously + iff WAIT is nonzero) from format-specific buffers any non-paged + metadata. If CLEAN is nonzero, then after this is written the + filesystem will be absolutely clean, and the non-paged metadata can + so indicate. */ +void diskfs_set_hypermetadata (int wait, int clean); + +/* The user must define this function. Allocate a new node to be of + mode MODE in locked directory DP (don't actually set the mode or + modify the dir, that will be done by the caller); the user + responsible for the request can be identified with CRED. Set *NP + to be the newly allocated node. */ +error_t diskfs_alloc_node (struct node *dp, mode_t mode, struct node **np); + +/* Free node NP; the on disk copy has already been synced with + diskfs_node_update (where NP->dn_stat.st_mode was 0). It's + mode used to be MODE. */ +void diskfs_free_node (struct node *np, mode_t mode); + +/* Node NP has no more references; free local state, including *NP + if it isn't to be retained. diskfs_node_refcnt_lock is held. */ +void diskfs_node_norefs (struct node *np); + +/* The user must define this function. Node NP has some light + references, but has just lost its last hard references. Take steps + so that if any light references can be freed, they are. NP might + or might not be locked; this routine should not attempt to gain the lock. */ +void diskfs_lost_hardrefs (struct node *np); + +/* The user must define this function. Node NP has just acquired + a hard reference where it had none previously. It is thus now + OK again to have light references without real users. NP might or + might not be locked; this routine should not attempt to gain the lock. */ +void diskfs_new_hardrefs (struct node *np); + +/* The user must define this function. Return non-zero if locked + directory DP is empty. If the user does not redefine + diskfs_clear_directory and diskfs_init_directory, then `empty' + means `possesses entries labelled . and .. only'. CRED + identifies the user making the call (if this user can't search + the directory, then this routine should fail). */ +int diskfs_dirempty (struct node *dp, struct protid *cred); + +/* The user must define this function. Sync the info in NP->dn_stat + and any associated format-specific information to disk. If WAIT is true, + then return only after the physicial media has been completely updated. */ +void diskfs_write_disknode (struct node *np, int wait); + +/* The user must define this function. Sync the file contents and all + associated meta data of file NP to disk (generally this will involve + calling diskfs_node_update for much of the metadata). If WAIT is true, + then return only after the physical media has been completely updated. */ +void diskfs_file_update (struct node *np, int wait); + +/* The user must define this function. Sync all the pagers and any + data belonging on disk except for the hypermetadata. If WAIT is true, + then return only after the physicial media has been completely updated. */ +void diskfs_sync_everything (int wait); + +/* Shutdown all pagers; this is done when the filesystem is exiting and is + irreversable. */ +void diskfs_shutdown_pager (); + +/* The user must define this function. Return a memory object port (send + right) for the file contents of NP. */ +mach_port_t diskfs_get_filemap (struct node *np); + +/* The user must define this function. Return a `struct pager *' suitable + for use as an argument to diskfs_register_memory_fault_area that + refers to the pager returned by diskfs_get_filemap for node NP. */ +struct pager *diskfs_get_filemap_pager_struct (struct node *np); + +/* The user must define this function if she calls diskfs_start_bootstrap. + It is called by the library after the filesystem has a normal + environment (complete with auth and proc ports). */ +void diskfs_init_completed (); + +/* It is assumed that the user will use the Hurd pager library; if not + you need to redefine ports_demuxer and + diskfs_do_seqnos_mach_notify_no_senders. */ + +/* The library exports the following functions for general use */ + +/* Call this if the bootstrap port is null and you want to support + being a bootstrap filesystem. ARGC and ARGV should be as passed + to main. If the arguments are not in the proper format, an + error message will be printed on stderr and exit called. Otherwise, + diskfs_priv_host, diskfs_master_device, and diskfs_bootflags will be + set and the Mach kernel name of the bootstrap device will be + returned. */ +char *diskfs_parse_bootargs (int argc, char **argv); + +/* Call this after arguments have been parsed to initialize the + library. */ +void diskfs_init_diskfs (void); + +/* Call this after all format-specific initialization is done (except + for setting diskfs_root_node); at this point the pagers should be + ready to go. */ +void diskfs_spawn_first_thread (void); + +/* Once diskfs_root_node is set, call this if we are a bootstrap + filesystem. If you call this, then the library will call + diskfs_init_completed once it has a valid proc and auth port.*/ +void diskfs_start_bootstrap (void); + +/* Last step of init is to call this, which never returns. */ +void diskfs_main_request_loop (void); + +/* Node NP now has no more references; clean all state. The + _diskfs_node_refcnt_lock must be held, and will be released + upon return. NP must be locked. */ +void diskfs_drop_node (struct node *np); + +/* Set on disk fields from NP->dn_stat; update ctime, atime, and mtime + if necessary. If WAIT is true, then return only after the physical + media has been completely updated. */ +void diskfs_node_update (struct node *np, int wait); + +/* Add a hard reference to a node. */ +extern inline void +diskfs_nref (struct node *np) +{ + int new_hardref; + spin_lock (&diskfs_node_refcnt_lock); + np->references++; + new_hardref = (np->references == 1); + spin_unlock (&diskfs_node_refcnt_lock); + if (new_hardref) + diskfs_new_hardrefs (np); +} + +/* Unlock node NP and release a hard reference; if this is the last + hard reference and there are no links to the file then request + soft references to be dropped. */ +extern inline void +diskfs_nput (struct node *np) +{ + int nlinks; + + spin_lock (&diskfs_node_refcnt_lock); + np->references--; + if (np->references + np->light_references == 0) + diskfs_drop_node (np); + else if (np->references == 0) + { + spin_unlock (&diskfs_node_refcnt_lock); + nlinks = np->dn_stat.st_nlink; + mutex_unlock (&np->lock); + if (!nlinks) + diskfs_lost_hardrefs (np); + } + else + { + spin_unlock (&diskfs_node_refcnt_lock); + mutex_unlock (&np->lock); + } +} + +/* Release a hard reference on NP. If NP is locked by anyone, then + this cannot be the last hard reference (because you must hold a + hard reference in order to hold the lock). If this is the last + hard reference and there are no links, then request soft references + to be dropped. */ +extern inline void +diskfs_nrele (struct node *np) +{ + int nlinks; + + spin_lock (&diskfs_node_refcnt_lock); + np->references--; + if (np->references + np->light_references == 0) + { + mutex_lock (&np->lock); + diskfs_drop_node (np); + } + else if (np->references == 0) + { + mutex_lock (&np->lock); + nlinks = np->dn_stat.st_nlink; + mutex_unlock (&np->lock); + spin_unlock (&diskfs_node_refcnt_lock); + if (!nlinks) + diskfs_lost_hardrefs (np); + } + else + spin_unlock (&diskfs_node_refcnt_lock); +} + +/* Add a light reference to a node. */ +extern inline void +diskfs_nref_light (struct node *np) +{ + spin_lock (&diskfs_node_refcnt_lock); + np->light_references++; + spin_unlock (&diskfs_node_refcnt_lock); +} + +/* Unlock node NP and release a light reference */ +extern inline void +diskfs_nput_light (struct node *np) +{ + spin_lock (&diskfs_node_refcnt_lock); + np->light_references--; + if (np->references + np->light_references == 0) + diskfs_drop_node (np); + else + { + spin_unlock (&diskfs_node_refcnt_lock); + mutex_unlock (&np->lock); + } +} + +/* Release a light reference on NP. If NP is locked by anyone, then + this cannot be the last reference (because you must hold a + hard reference in order to hold the lock). */ +extern inline void +diskfs_nrele_light (struct node *np) +{ + spin_lock (&diskfs_node_refcnt_lock); + np->light_references--; + if (np->references + np->light_references == 0) + { + mutex_lock (&np->lock); + diskfs_drop_node (np); + } + else + spin_unlock (&diskfs_node_refcnt_lock); +} + +/* Return nonzero iff the user identified by CRED has uid UID. */ +extern inline int +diskfs_isuid (uid_t uid, struct protid *cred) +{ + int i; + for (i = 0; i < cred->nuids; i++) + if (cred->uids[i] == uid) + return 1; + return 0; +} + +/* Return nonzero iff the user identified by CRED has group GRP. */ +extern inline int +diskfs_groupmember (uid_t grp, struct protid *cred) +{ + int i; + for (i = 0; i < cred->ngids; i++) + if (cred->gids[i] == grp) + return 1; + return 0; +} + +/* Check to see if the user identified by CRED is permitted to do + owner-only operations on node NP; if so, return 0; if not, return + EPERM. */ +extern inline error_t +diskfs_isowner (struct node *np, struct protid *cred) +{ + /* Permitted if the user is the owner, superuser, or if the user + is in the group of the file and has the group ID as their user + ID. (This last is colloquially known as `group leader'.) */ + if (diskfs_isuid (np->dn_stat.st_uid, cred) || diskfs_isuid (0, cred) + || (diskfs_groupmember (np->dn_stat.st_gid, cred) + && diskfs_isuid (np->dn_stat.st_gid, cred))) + return 0; + else + return EPERM; +} + +/* Check to see is the user identified by CRED is permitted to do + operation OP on node NP. Op is one of S_IREAD, S_IWRITE, or S_IEXEC. + Return 0 if the operation is permitted and EACCES if not. */ +extern inline error_t +diskfs_access (struct node *np, int op, struct protid *cred) +{ + int gotit; + if (diskfs_isuid (0, cred)) + gotit = 1; + else if (cred->nuids == 0 && (np->dn_stat.st_mode & S_IUSEUNK)) + gotit = np->dn_stat.st_mode & (op << S_IUNKSHIFT); + else if (!diskfs_isowner (np, cred)) + gotit = np->dn_stat.st_mode & op; + else if (diskfs_groupmember (np->dn_stat.st_gid, cred)) + gotit = np->dn_stat.st_mode & (op >> 3); + else + gotit = np->dn_stat.st_mode & (op >> 6); + return gotit ? 0 : EACCES; +} + +/* Check to see if the user identified by CRED is allowed to modify + directory DP with respect to existing file NP. This is the same + as diskfs_access (dp, S_IWRITE, cred), except when the directory + has the sticky bit set. (If there is no existing file NP, then + 0 can be passed.) */ +extern inline error_t +diskfs_checkdirmod (struct node *dp, struct node *np, + struct protid *cred) +{ + /* The user must be able to write the directory, but if the directory + is sticky, then the user must also be either the owner of the directory + or the file. */ + return (diskfs_access (dp, S_IWRITE, cred) + && (!(dp->dn_stat.st_mode & S_ISVTX) || !np || diskfs_isuid (0,cred) + || diskfs_isowner (dp, cred) || diskfs_isowner (np, cred))); +} + +/* Reading and writing of files. this is called by other filesystem + routines and handles extension of files automatically. NP is the + node to be read or written, and must be locked. DATA will be + written or filled. OFF identifies where in thi fel the I/O is to + take place (-1 is not allowed). AMT is the size of DATA and tells + how much to copy. DIR is 1 for writing and 0 for reading. CRED is + the user doing the access (only used to validate attempted file + extension). For reads, *AMTREAD is filled with the amount actually + read. */ +error_t +diskfs_node_rdwr (struct node *np, char *data, off_t off, + int amt, int dir, struct protid *cred, + int *amtread); + + +/* Create a new node structure with DS as its physical disknode. + The new node will have one hard reference and no light references. */ +struct node *diskfs_make_node (struct disknode *dn); + +/* The following two calls are actually macros. */ +/* Begin executing code which might fault. This contains a call + to setjmp and so callers must be careful with register variables. + The first time through, this returns 0. If the code faults + accessing a region of memory registered with + diskfs_register_memory_fault_area, then this routine will return + again with the error number as reported by the pager. */ +/* int diskfs_catch_exception (void); */ + +/* After calling diskfs_catch_exception, this routine must be called + before exiting the function which called diskfs_catch_exception. + It will cancel the fault protection installed by diskfs_catch_exception. */ +/* void diskfs_end_catch_exception (void); */ + +/* Register a region of memory for protected fault status as described + above for diskfs_catch_exception. This should generally be done + for any vm_map of the filesystem's own data. This will mark memory + at ADDR continuing for LEN bytes to be mapped from pager P at offset + OFF. Any memory exceptions in this region will be looked up with + pager_get_error (until the XP interface is fixed); this is the only + use made of arguments P and OFF. */ +void diskfs_register_memory_fault_area (struct pager *p, vm_address_t off, + void *addr, long len); + +/* Remove the registration of a region registered with + diskfs_register_memory_fault_area; the region is that at ADDR + continuing for LEN bytes. */ +void diskfs_unregister_memory_fault_area (void *addr, long len); + + +/* The library also exports the following functions; they are not generally + useful unless you are redefining other functions the library provides. */ + +/* Create a new node. Give it MODE; if that includes IFDIR, also + initialize `.' and `..' in the new directory. Return the node in NPP. + CRED identifies the user responsible for the call. If NAME is nonzero, + then link the new node into DIR with name NAME; DS is the result of a + prior diskfs_lookup for creation (and DIR has been held locked since). + DIR must always be provided as at least a hint for disk allocation + strategies. */ +error_t +diskfs_create_node (struct node *dir, char *name, mode_t mode, + struct node **newnode, struct protid *cred, + struct dirstat *ds); + +/* Start the translator on node IP; the directory we found IP in + is DIP; both are locked. */ +error_t diskfs_start_translator (struct node *np, struct node *dnp); + +/* Create and return a protid for an existing peropen. The uid set is + UID (length NUIDS); the gid set is GID (length NGIDS). The node + PO->np must be locked. */ +struct protid *diskfs_make_protid (struct peropen *cred, uid_t *uids, + int nuids, uid_t *gids, int ngids); + +/* Build and return a protid which has no user identification for + peropen PO. The node PO->np must be locked. */ +struct protid *diskfs_start_protid (struct peropen *po); + +/* Finish building protid CRED started with diskfs_start_protid; + the uid set is UID (length NUIDS); the gid set is GID (length NGIDS). */ +void diskfs_finish_protid (struct protid *cred, uid_t *uids, int nuids, + gid_t *gids, int nguds); + +/* Create and return a new peropen structure on node NP with open + flags FLAGS. */ +struct peropen *diskfs_make_peropen (struct node *np, int flags); + +/* Called when a protid CRED has no more references. (Because references\ + to protids are maintained by the port management library, this is + installed in the clean routines list.) The ports library will + free the structure for us. */ +void diskfs_protid_rele (void *arg); + +/* Decrement the reference count on a peropen structure. */ +void diskfs_release_peropen (struct peropen *po); + +/* Rename directory node FNP (whose parent is FDP, and which has name + FROMNAME in that directory) to have name TONAME inside directory + TDP. None of these nodes are locked, and none should be locked + upon return. This routine is serialized, so it doesn't have to be + reentrant. Directories will never be renamed except by this + routine. FROMCRED and TOCRED are the users responsible for + FDP/FNP and TDP respectively. This routine assumes the usual + convention where `.' and `..' are represented by ordinary links; + if that is not true for your format, you have to redefine this + function.*/ +error_t +diskfs_rename_dir (struct node *fdp, struct node *fnp, char *fromname, + struct node *tdp, char *toname, struct protid *fromcred, + struct protid *tocred); + +/* Clear the `.' and `..' entries from directory DP. Its parent is + PDP, and the user responsible for this is identified by CRED. Both + directories must be locked. This routine assumes the usual + convention where `.' and `..' are represented by ordinary links; if + that is not true for your format, you have to redefine this + function. */ +error_t diskfs_clear_directory (struct node *dp, struct node *pdp, + struct protid *cred); + +/* Locked node DP is a new directory; add whatever links are necessary + to give it structure; its parent is the (locked) node PDP. + This routine may not call diskfs_lookup on PDP. The new directory + must be clear within the meaning of diskfs_dirempty. This routine + assumes the usual convention where `.' and `..' are represented by + ordinary links; if that is not true for your format, you have to + redefine this function. CRED identifies the user making the call. */ +error_t +diskfs_init_dir (struct node *dp, struct node *pdp, struct protid *cred); + +/* Get rid of any translator running on the file NP; FLAGS + (from the set FSYS_GOAWAY_*) describes details of shutting + down the child filesystem. */ +void diskfs_destroy_translator (struct node *np, int flags); + +/* Sync all the running translators. Wait for them to complete if + WAIT is nonzero. */ +void diskfs_sync_translators (int wait); + +/* If NP->dn_set_ctime is set, then modify NP->dn_stat.st_ctime + appropriately; do the analogous operation for atime and mtime as well. */ +void diskfs_set_node_times (struct node *np); + +/* Shutdown the filesystem; flags are as for fsys_shutdown. */ +error_t diskfs_shutdown (int flags); + +/* Called by S_fsys_startup for execserver bootstrap. The execserver + is able to function without a real node, hence this fraud. Arguments + are all as for fsys_startup in <hurd/fsys.defs>. */ +error_t diskfs_execboot_fsys_startup (mach_port_t port, mach_port_t ctl, + mach_port_t *real, + mach_msg_type_name_t *realpoly, + mach_port_t *dotdot_node, + mach_msg_type_name_t *dotdot_node_poly); + +/* The ports library requires the following to be defined; the diskfs + library provides a definition. See <hurd/ports.h> for the + interface description. The library assumes you use the pager + library (and calls pager_demuxer). If you don't, then you need + to redefine this function as well as the no_senders notify stub. */ +int ports_demuxer (mach_msg_header_t *, mach_msg_header_t *); + +/* The diskfs library provides functions to demultiplex the fs, io, fsys, + memory_object, interrupt, and notify interfaces. All the server + routines have the prefix `diskfs_S_'; `in' arguments of type + file_t or io_t appear as `struct protid *' to the stub. */ + +#endif |