diff options
author | Michael I. Bushnell <mib@gnu.org> | 1996-07-18 04:35:29 +0000 |
---|---|---|
committer | Michael I. Bushnell <mib@gnu.org> | 1996-07-18 04:35:29 +0000 |
commit | 94cef36797600d11a50d09828fa80df8a73dfd1c (patch) | |
tree | b7cba9afef95489eedef534d3e6946eb13f595ba /nfs | |
parent | 88dbbbf9e48e24f1ac007c1e4eeffd9caf8e2fad (diff) |
*** empty log message ***
Diffstat (limited to 'nfs')
-rw-r--r-- | nfs/pager.c | 448 | ||||
-rw-r--r-- | nfs/rpcsvc/mount.h | 81 | ||||
-rw-r--r-- | nfs/rpcsvc/nfs_prot.h | 343 |
3 files changed, 872 insertions, 0 deletions
diff --git a/nfs/pager.c b/nfs/pager.c new file mode 100644 index 00000000..687a0e2f --- /dev/null +++ b/nfs/pager.c @@ -0,0 +1,448 @@ +/* + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Written by Michael I. Bushnell, p/BSG. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + + +#include "nfs.h" +#include <unistd.h> +#include <hurd/pager.h> +#include <netinet/in.h> +#include <string.h> + +struct user_pager_info +{ + struct node *np; + struct pager *p; + int max_prot; +}; + +struct pager_cache_rec +{ + struct pager_cache_rec *next; + vm_offset_t offset; + struct pager *p; + time_t fetched; +}; + +static struct pager_cache_rec *pager_cache_recs; +static spin_lock_t pager_cache_rec_lock = SPIN_LOCK_INITIALIZER; +static spin_lock_t node2pagelock = SPIN_LOCK_INITIALIZER; +static struct port_bucket *pager_bucket; + +void +register_new_page (struct pager *p, vm_offset_t offset) +{ + struct pager_cache_rec *pc; + + pc = malloc (sizeof (struct pager_cache_rec)); + pc->offset = offset; + pc->p = p; + ports_port_ref (p); + pc->fetched = mapped_time->seconds; + + spin_lock (&pager_cache_rec_lock); + pc->next = pager_cache_recs; + pager_cache_recs = pc; + spin_unlock (&pager_cache_rec_lock); +} + +any_t +flush_pager_cache_thread (any_t foo2) +{ + struct pager_cache_rec *pc, *next, **ppc, *list; + + for (;;) + { + sleep (1); + + /* Dequeue from the main list and queue locally the recs + for expired pages. */ + list = 0; + spin_lock (&pager_cache_rec_lock); + for (pc = pager_cache_recs, ppc = &pager_cache_recs; + pc; + ppc = &pc->next, pc = next) + { + next = pc->next; + if (mapped_time->seconds - pc->fetched > cache_timeout) + { + *ppc = pc->next; + pc->next = list; + list = pc; + } + } + spin_unlock (&pager_cache_rec_lock); + + /* And now, one at a time, expire them */ + for (pc = list; pc; pc = next) + { + pager_return_some (pc->p, pc->offset, vm_page_size, 0); + next = pc->next; + ports_port_deref (pc->p); + free (pc); + } + } +} + +error_t +pager_read_page (struct user_pager_info *pager, + vm_offset_t page, + vm_address_t *buf, + int *writelock) +{ + error_t err; + int *p; + void *rpcbuf; + struct node *np; + size_t amt, thisamt, trans_len; + void *data; + off_t offset; + + np = pager->np; + + mutex_lock (&np->lock); + + vm_allocate (mach_task_self (), buf, vm_page_size, 1); + data = (char *) *buf; + amt = vm_page_size; + offset = page; + + while (amt) + { + thisamt = amt; + if (thisamt > read_size) + thisamt = read_size; + + p = nfs_initialize_rpc (NFSPROC_READ, (struct netcred *)-1, 0, + &rpcbuf, np, -1); + p = xdr_encode_fhandle (p, &np->nn->handle); + *p++ = htonl (offset); + *p++ = htonl (vm_page_size); + *p++ = 0; + + err = conduct_rpc (&rpcbuf, &p); + if (!err) + err = nfs_error_trans (ntohl (*p++)); + if (err) + { + mutex_unlock (&np->lock); + free (rpcbuf); + vm_deallocate (mach_task_self (), *buf, vm_page_size); + return err; + } + + p = register_fresh_stat (np, p); + trans_len = ntohl (*p++); + if (trans_len > thisamt) + trans_len = thisamt; /* ??? */ + + bcopy (p, data, trans_len); + + free (rpcbuf); + + data += trans_len; + offset += trans_len; + amt -= trans_len; + + /* If we got a short count, we're all done. */ + if (trans_len < thisamt) + break; + } + + register_new_page (pager->p, page); + mutex_unlock (&np->lock); + return 0; +} + + +error_t +pager_write_page (struct user_pager_info *pager, + vm_offset_t page, + vm_address_t buf) +{ + int *p; + void *rpcbuf; + error_t err; + size_t amt, thisamt; + off_t offset; + struct node *np; + void *data; + + np = pager->np; + mutex_lock (&np->lock); + + amt = vm_page_size; + offset = page; + data = (void *) buf; + + while (amt) + { + thisamt = amt; + if (amt > write_size) + amt = write_size; + + p = nfs_initialize_rpc (NFSPROC_WRITE, (struct netcred *) -1, + amt, &rpcbuf, np, -1); + p = xdr_encode_fhandle (p, &np->nn->handle); + *p++ = 0; + *p++ = htonl (offset); + *p++ = 0; + p = xdr_encode_data (p, data, thisamt); + + err = conduct_rpc (&rpcbuf, &p); + if (!err) + err = nfs_error_trans (ntohl (*p++)); + if (err) + { + free (rpcbuf); + vm_deallocate (mach_task_self (), buf, vm_page_size); + return err; + } + register_fresh_stat (np, p); + free (rpcbuf); + amt -= thisamt; + data += thisamt; + offset += thisamt; + } + + vm_deallocate (mach_task_self (), buf, vm_page_size); + mutex_unlock (&np->lock); + return 0; +} + +error_t +pager_unlock_page (struct user_pager_info *pager, + vm_offset_t address) +{ + abort (); +} + +error_t +pager_report_extent (struct user_pager_info *pager, + vm_address_t *offset, + vm_size_t *size) +{ + struct node *np; + error_t err; + + np = pager->np; + mutex_lock (&np->lock); + + err = netfs_validate_stat (np, 0); + if (!err) + *size = round_page (np->nn_stat.st_size); + mutex_unlock (&np->lock); + return err; +} + +void +pager_clear_user_data (struct user_pager_info *upi) +{ + spin_lock (&node2pagelock); + if (upi->np->nn->fileinfo == upi) + upi->np->nn->fileinfo = 0; + spin_unlock (&node2pagelock); + netfs_nrele (upi->np); + free (upi); +} + +void +pager_dropweak (struct user_pager_info *upi) +{ + abort (); +} + +mach_port_t +netfs_get_filemap (struct node *np, vm_prot_t prot) +{ + struct user_pager_info *upi; + mach_port_t right; + + spin_lock (&node2pagelock); + do + if (!np->nn->fileinfo) + { + upi = malloc (sizeof (struct user_pager_info)); + upi->np = np; + netfs_nref (np); + upi->max_prot = prot; + upi->p = pager_create (upi, pager_bucket, 1, MEMORY_OBJECT_COPY_NONE); + np->nn->fileinfo = upi; + right = pager_get_port (np->nn->fileinfo->p); + ports_port_deref (np->nn->fileinfo->p); + } + else + { + np->nn->fileinfo->max_prot |= prot; + /* Because NP->dn->fileinfo->p is not a real reference, + this might be nearly deallocated. If that's so, then + the port right will be null. In that case, clear here + and loop. The deallocation will complete separately. */ + right = pager_get_port (np->nn->fileinfo->p); + if (right == MACH_PORT_NULL) + np->nn->fileinfo = 0; + } + while (right == MACH_PORT_NULL); + + spin_unlock (&node2pagelock); + + mach_port_insert_right (mach_task_self (), right, right, + MACH_MSG_TYPE_MAKE_SEND); + return right; +} + +void +drop_pager_softrefs (struct node *np) +{ + struct user_pager_info *upi; + + spin_lock (&node2pagelock); + upi = np->nn->fileinfo; + if (upi) + ports_port_ref (upi->p); + spin_unlock (&node2pagelock); + + if (upi) + { + pager_change_attributes (upi->p, 0, MEMORY_OBJECT_COPY_NONE, 0); + ports_port_deref (upi->p); + } +} + +void +allow_pager_softrefs (struct node *np) +{ + struct user_pager_info *upi; + + spin_lock (&node2pagelock); + upi = np->nn->fileinfo; + if (upi) + ports_port_ref (upi->p); + spin_unlock (&node2pagelock); + + if (upi) + { + pager_change_attributes (upi->p, 1, MEMORY_OBJECT_COPY_NONE, 0); + ports_port_deref (upi->p); + } +} + +void +block_caching () +{ + error_t block_cache (void *arg) + { + struct pager *p = arg; + pager_change_attributes (p, 0, MEMORY_OBJECT_COPY_NONE, 1); + return 0; + } + ports_bucket_iterate (pager_bucket, block_cache); +} + +void +enable_caching () +{ + error_t enable_cache (void *arg) + { + struct pager *p = arg; + struct user_pager_info *upi = pager_get_upi (p); + + pager_change_attributes (p, 1, MEMORY_OBJECT_COPY_NONE, 0); + return 0; + } + + ports_bucket_iterate (pager_bucket, enable_cache); +} + +int +netfs_pager_users () +{ + int npagers = ports_count_bucket (pager_bucket); + + if (!npagers) + return 0; + + block_caching (); + /* Give it a sec; the kernel doesn't issue the shutdown right away */ + sleep (1); + npagers = ports_count_bucket (pager_bucket); + if (!npagers) + return 0; + + enable_caching (); + + ports_enable_bucket (pager_bucket); +} + +vm_prot_t +netfs_max_user_pager_prot () +{ + vm_prot_t max_prot; + int npagers = ports_count_bucket (pager_bucket); + + if (npagers) + { + error_t add_pager_max_prot (void *v_p) + { + struct pager *p = v_p; + struct user_pager_info *upi = pager_get_upi (p); + max_prot |= upi->max_prot; + return max_prot == (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); + } + + block_caching (); + sleep (1); + + ports_bucket_iterate (pager_bucket, add_pager_max_prot); + enable_caching (); + } + + ports_enable_bucket (pager_bucket); + return max_prot; +} + +void +netfs_shutdown_pager () +{ + error_t shutdown_one (void *arg) + { + pager_shutdown ((struct pager *) arg); + return 0; + } + + ports_bucket_iterate (pager_bucket, shutdown_one); +} + +void +netfs_sync_everything (int wait) +{ + error_t sync_one (void *arg) + { + pager_sync ((struct pager *) arg, wait); + return 0; + } + ports_bucket_iterate (pager_bucket, sync_one); +} + +void +pager_initialize (void) +{ + pager_bucket = ports_create_bucket (); + cthread_detach (cthread_fork (flush_pager_cache_thread, 0)); + diff --git a/nfs/rpcsvc/mount.h b/nfs/rpcsvc/mount.h new file mode 100644 index 00000000..2dc3dc88 --- /dev/null +++ b/nfs/rpcsvc/mount.h @@ -0,0 +1,81 @@ +#define MNTPATHLEN 1024 +#define MNTNAMLEN 255 +#define FHSIZE 32 + +typedef char fhandle[FHSIZE]; +bool_t xdr_fhandle(); + + +struct fhstatus { + u_int fhs_status; + union { + fhandle fhs_fhandle; + } fhstatus_u; +}; +typedef struct fhstatus fhstatus; +bool_t xdr_fhstatus(); + + +typedef char *dirpath; +bool_t xdr_dirpath(); + + +typedef char *name; +bool_t xdr_name(); + + +typedef struct mountbody *mountlist; +bool_t xdr_mountlist(); + + +struct mountbody { + name ml_hostname; + dirpath ml_directory; + mountlist ml_next; +}; +typedef struct mountbody mountbody; +bool_t xdr_mountbody(); + + +typedef struct groupnode *groups; +bool_t xdr_groups(); + + +struct groupnode { + name gr_name; + groups gr_next; +}; +typedef struct groupnode groupnode; +bool_t xdr_groupnode(); + + +typedef struct exportnode *exports; +bool_t xdr_exports(); + + +struct exportnode { + dirpath ex_dir; + groups ex_groups; + exports ex_next; +}; +typedef struct exportnode exportnode; +bool_t xdr_exportnode(); + + +#define MOUNTPROG ((u_long)100005) +#define MOUNTVERS ((u_long)1) +#define MOUNTPROC_NULL ((u_long)0) +extern void *mountproc_null_1(); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus *mountproc_mnt_1(); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist *mountproc_dump_1(); +#define MOUNTPROC_UMNT ((u_long)3) +extern void *mountproc_umnt_1(); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void *mountproc_umntall_1(); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports *mountproc_export_1(); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports *mountproc_exportall_1(); + diff --git a/nfs/rpcsvc/nfs_prot.h b/nfs/rpcsvc/nfs_prot.h new file mode 100644 index 00000000..7f974930 --- /dev/null +++ b/nfs/rpcsvc/nfs_prot.h @@ -0,0 +1,343 @@ +#define NFS_PORT 2049 +#define NFS_MAXDATA 8192 +#define NFS_MAXPATHLEN 1024 +#define NFS_MAXNAMLEN 255 +#define NFS_FHSIZE 32 +#define NFS_COOKIESIZE 4 +#define NFS_FIFO_DEV -1 +#define NFSMODE_FMT 0170000 +#define NFSMODE_DIR 0040000 +#define NFSMODE_CHR 0020000 +#define NFSMODE_BLK 0060000 +#define NFSMODE_REG 0100000 +#define NFSMODE_LNK 0120000 +#define NFSMODE_SOCK 0140000 +#define NFSMODE_FIFO 0010000 + +enum nfsstat { + NFS_OK = 0, + NFSERR_PERM = 1, + NFSERR_NOENT = 2, + NFSERR_IO = 5, + NFSERR_NXIO = 6, + NFSERR_ACCES = 13, + NFSERR_EXIST = 17, + NFSERR_NODEV = 19, + NFSERR_NOTDIR = 20, + NFSERR_ISDIR = 21, + NFSERR_FBIG = 27, + NFSERR_NOSPC = 28, + NFSERR_ROFS = 30, + NFSERR_NAMETOOLONG = 63, + NFSERR_NOTEMPTY = 66, + NFSERR_DQUOT = 69, + NFSERR_STALE = 70, + NFSERR_WFLUSH = 99, +}; +typedef enum nfsstat nfsstat; +bool_t xdr_nfsstat(); + + +enum ftype { + NFNON = 0, + NFREG = 1, + NFDIR = 2, + NFBLK = 3, + NFCHR = 4, + NFLNK = 5, + NFSOCK = 6, + NFBAD = 7, + NFFIFO = 8, +}; +typedef enum ftype ftype; +bool_t xdr_ftype(); + + +struct nfs_fh { + char data[NFS_FHSIZE]; +}; +typedef struct nfs_fh nfs_fh; +bool_t xdr_nfs_fh(); + + +struct nfstime { + u_int seconds; + u_int useconds; +}; +typedef struct nfstime nfstime; +bool_t xdr_nfstime(); + + +struct fattr { + ftype type; + u_int mode; + u_int nlink; + u_int uid; + u_int gid; + u_int size; + u_int blocksize; + u_int rdev; + u_int blocks; + u_int fsid; + u_int fileid; + nfstime atime; + nfstime mtime; + nfstime ctime; +}; +typedef struct fattr fattr; +bool_t xdr_fattr(); + + +struct sattr { + u_int mode; + u_int uid; + u_int gid; + u_int size; + nfstime atime; + nfstime mtime; +}; +typedef struct sattr sattr; +bool_t xdr_sattr(); + + +typedef char *filename; +bool_t xdr_filename(); + + +typedef char *nfspath; +bool_t xdr_nfspath(); + + +struct attrstat { + nfsstat status; + union { + fattr attributes; + } attrstat_u; +}; +typedef struct attrstat attrstat; +bool_t xdr_attrstat(); + + +struct sattrargs { + nfs_fh file; + sattr attributes; +}; +typedef struct sattrargs sattrargs; +bool_t xdr_sattrargs(); + + +struct diropargs { + nfs_fh dir; + filename name; +}; +typedef struct diropargs diropargs; +bool_t xdr_diropargs(); + + +struct diropokres { + nfs_fh file; + fattr attributes; +}; +typedef struct diropokres diropokres; +bool_t xdr_diropokres(); + + +struct diropres { + nfsstat status; + union { + diropokres diropres; + } diropres_u; +}; +typedef struct diropres diropres; +bool_t xdr_diropres(); + + +struct readlinkres { + nfsstat status; + union { + nfspath data; + } readlinkres_u; +}; +typedef struct readlinkres readlinkres; +bool_t xdr_readlinkres(); + + +struct readargs { + nfs_fh file; + u_int offset; + u_int count; + u_int totalcount; +}; +typedef struct readargs readargs; +bool_t xdr_readargs(); + + +struct readokres { + fattr attributes; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct readokres readokres; +bool_t xdr_readokres(); + + +struct readres { + nfsstat status; + union { + readokres reply; + } readres_u; +}; +typedef struct readres readres; +bool_t xdr_readres(); + + +struct writeargs { + nfs_fh file; + u_int beginoffset; + u_int offset; + u_int totalcount; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct writeargs writeargs; +bool_t xdr_writeargs(); + + +struct createargs { + diropargs where; + sattr attributes; +}; +typedef struct createargs createargs; +bool_t xdr_createargs(); + + +struct renameargs { + diropargs from; + diropargs to; +}; +typedef struct renameargs renameargs; +bool_t xdr_renameargs(); + + +struct linkargs { + nfs_fh from; + diropargs to; +}; +typedef struct linkargs linkargs; +bool_t xdr_linkargs(); + + +struct symlinkargs { + diropargs from; + nfspath to; + sattr attributes; +}; +typedef struct symlinkargs symlinkargs; +bool_t xdr_symlinkargs(); + + +typedef char nfscookie[NFS_COOKIESIZE]; +bool_t xdr_nfscookie(); + + +struct readdirargs { + nfs_fh dir; + nfscookie cookie; + u_int count; +}; +typedef struct readdirargs readdirargs; +bool_t xdr_readdirargs(); + + +struct entry { + u_int fileid; + filename name; + nfscookie cookie; + struct entry *nextentry; +}; +typedef struct entry entry; +bool_t xdr_entry(); + + +struct dirlist { + entry *entries; + bool_t eof; +}; +typedef struct dirlist dirlist; +bool_t xdr_dirlist(); + + +struct readdirres { + nfsstat status; + union { + dirlist reply; + } readdirres_u; +}; +typedef struct readdirres readdirres; +bool_t xdr_readdirres(); + + +struct statfsokres { + u_int tsize; + u_int bsize; + u_int blocks; + u_int bfree; + u_int bavail; +}; +typedef struct statfsokres statfsokres; +bool_t xdr_statfsokres(); + + +struct statfsres { + nfsstat status; + union { + statfsokres reply; + } statfsres_u; +}; +typedef struct statfsres statfsres; +bool_t xdr_statfsres(); + + +#define NFS_PROGRAM ((u_long)100003) +#define NFS_VERSION ((u_long)2) +#define NFSPROC_NULL ((u_long)0) +extern void *nfsproc_null_2(); +#define NFSPROC_GETATTR ((u_long)1) +extern attrstat *nfsproc_getattr_2(); +#define NFSPROC_SETATTR ((u_long)2) +extern attrstat *nfsproc_setattr_2(); +#define NFSPROC_ROOT ((u_long)3) +extern void *nfsproc_root_2(); +#define NFSPROC_LOOKUP ((u_long)4) +extern diropres *nfsproc_lookup_2(); +#define NFSPROC_READLINK ((u_long)5) +extern readlinkres *nfsproc_readlink_2(); +#define NFSPROC_READ ((u_long)6) +extern readres *nfsproc_read_2(); +#define NFSPROC_WRITECACHE ((u_long)7) +extern void *nfsproc_writecache_2(); +#define NFSPROC_WRITE ((u_long)8) +extern attrstat *nfsproc_write_2(); +#define NFSPROC_CREATE ((u_long)9) +extern diropres *nfsproc_create_2(); +#define NFSPROC_REMOVE ((u_long)10) +extern nfsstat *nfsproc_remove_2(); +#define NFSPROC_RENAME ((u_long)11) +extern nfsstat *nfsproc_rename_2(); +#define NFSPROC_LINK ((u_long)12) +extern nfsstat *nfsproc_link_2(); +#define NFSPROC_SYMLINK ((u_long)13) +extern nfsstat *nfsproc_symlink_2(); +#define NFSPROC_MKDIR ((u_long)14) +extern diropres *nfsproc_mkdir_2(); +#define NFSPROC_RMDIR ((u_long)15) +extern nfsstat *nfsproc_rmdir_2(); +#define NFSPROC_READDIR ((u_long)16) +extern readdirres *nfsproc_readdir_2(); +#define NFSPROC_STATFS ((u_long)17) +extern statfsres *nfsproc_statfs_2(); + |