Import 4.4BSD-Lite2 onto the vendor branch, note that in the kernel, all
files are off the vendor branch, so this should not change anything. A "U" marker generally means that the file was not changed in between the 4.4Lite and Lite-2 releases, and does not need a merge. "C" generally means that there was a change.
This commit is contained in:
parent
5e5861b9c6
commit
e47db3d2f2
566
sys/nfs/nfs.h
Normal file
566
sys/nfs/nfs.h
Normal file
@ -0,0 +1,566 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs.h 8.4 (Berkeley) 5/1/95
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
#define _NFS_NFS_H_
|
||||
|
||||
/*
|
||||
* Tunable constants for nfs
|
||||
*/
|
||||
|
||||
#define NFS_MAXIOVEC 34
|
||||
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
|
||||
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
|
||||
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
|
||||
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
|
||||
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
|
||||
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
|
||||
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
|
||||
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
|
||||
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
|
||||
#define NFS_MAXGRPS 16 /* Max. size of groups list */
|
||||
#ifndef NFS_MINATTRTIMO
|
||||
#define NFS_MINATTRTIMO 5 /* Attribute cache timeout in sec */
|
||||
#endif
|
||||
#ifndef NFS_MAXATTRTIMO
|
||||
#define NFS_MAXATTRTIMO 60
|
||||
#endif
|
||||
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
|
||||
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
|
||||
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
|
||||
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
|
||||
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
|
||||
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
|
||||
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
|
||||
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
|
||||
#ifndef NFS_GATHERDELAY
|
||||
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
|
||||
#endif
|
||||
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
|
||||
|
||||
/*
|
||||
* Oddballs
|
||||
*/
|
||||
#define NMOD(a) ((a) % nfs_asyncdaemons)
|
||||
#define NFS_CMPFH(n, f, s) \
|
||||
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
|
||||
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
|
||||
#define NFS_SRVMAXDATA(n) \
|
||||
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
|
||||
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* The B_INVAFTERWRITE flag should be set to whatever is required by the
|
||||
* buffer cache code to say "Invalidate the block after it is written back".
|
||||
*/
|
||||
#define B_INVAFTERWRITE B_INVAL
|
||||
|
||||
/*
|
||||
* The IO_METASYNC flag should be implemented for local file systems.
|
||||
* (Until then, it is nothin at all.)
|
||||
*/
|
||||
#ifndef IO_METASYNC
|
||||
#define IO_METASYNC 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the attribute timeout based on how recently the file has been modified.
|
||||
*/
|
||||
#define NFS_ATTRTIMEO(np) \
|
||||
((((np)->n_flag & NMODIFIED) || \
|
||||
(time.tv_sec - (np)->n_mtime) / 10 < NFS_MINATTRTIMO) ? NFS_MINATTRTIMO : \
|
||||
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
|
||||
(time.tv_sec - (np)->n_mtime) / 10))
|
||||
|
||||
/*
|
||||
* Expected allocation sizes for major data structures. If the actual size
|
||||
* of the structure exceeds these sizes, then malloc() will be allocating
|
||||
* almost twice the memory required. This is used in nfs_init() to warn
|
||||
* the sysadmin that the size of a structure should be reduced.
|
||||
* (These sizes are always a power of 2. If the kernel malloc() changes
|
||||
* to one that does not allocate space in powers of 2 size, then this all
|
||||
* becomes bunk!)
|
||||
*/
|
||||
#define NFS_NODEALLOC 256
|
||||
#define NFS_MNTALLOC 512
|
||||
#define NFS_SVCALLOC 256
|
||||
#define NFS_UIDALLOC 128
|
||||
|
||||
/*
|
||||
* Arguments to mount NFS
|
||||
*/
|
||||
#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
|
||||
struct nfs_args {
|
||||
int version; /* args structure version number */
|
||||
struct sockaddr *addr; /* file server address */
|
||||
int addrlen; /* length of address */
|
||||
int sotype; /* Socket type */
|
||||
int proto; /* and Protocol */
|
||||
u_char *fh; /* File handle to be mounted */
|
||||
int fhsize; /* Size, in bytes, of fh */
|
||||
int flags; /* flags */
|
||||
int wsize; /* write size in bytes */
|
||||
int rsize; /* read size in bytes */
|
||||
int readdirsize; /* readdir size in bytes */
|
||||
int timeo; /* initial timeout in .1 secs */
|
||||
int retrans; /* times to retry send */
|
||||
int maxgrouplist; /* Max. size of group list */
|
||||
int readahead; /* # of blocks to readahead */
|
||||
int leaseterm; /* Term (sec) of lease */
|
||||
int deadthresh; /* Retrans threshold */
|
||||
char *hostname; /* server's name */
|
||||
};
|
||||
|
||||
/*
|
||||
* NFS mount option flags
|
||||
*/
|
||||
#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
|
||||
#define NFSMNT_WSIZE 0x00000002 /* set write size */
|
||||
#define NFSMNT_RSIZE 0x00000004 /* set read size */
|
||||
#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
|
||||
#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
|
||||
#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
|
||||
#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
|
||||
#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
|
||||
#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
|
||||
#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
|
||||
#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
|
||||
#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
|
||||
#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
|
||||
#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
|
||||
#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
|
||||
#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
|
||||
#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
|
||||
#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
|
||||
#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
|
||||
#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
|
||||
#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
|
||||
#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
|
||||
#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
|
||||
#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
|
||||
#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
|
||||
#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
|
||||
#define NFSMNT_WANTSND 0x02000000 /* Want above */
|
||||
#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
|
||||
#define NFSMNT_WANTRCV 0x08000000 /* Want above */
|
||||
#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
|
||||
#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
|
||||
#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
|
||||
#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
|
||||
|
||||
/*
|
||||
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
|
||||
* should ever try and use it.
|
||||
*/
|
||||
struct nfsd_args {
|
||||
int sock; /* Socket to serve */
|
||||
caddr_t name; /* Client addr for connection based sockets */
|
||||
int namelen; /* Length of name */
|
||||
};
|
||||
|
||||
struct nfsd_srvargs {
|
||||
struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */
|
||||
uid_t nsd_uid; /* Effective uid mapped to cred */
|
||||
u_long nsd_haddr; /* Ip address of client */
|
||||
struct ucred nsd_cr; /* Cred. uid maps to */
|
||||
int nsd_authlen; /* Length of auth string (ret) */
|
||||
u_char *nsd_authstr; /* Auth string (ret) */
|
||||
int nsd_verflen; /* and the verfier */
|
||||
u_char *nsd_verfstr;
|
||||
struct timeval nsd_timestamp; /* timestamp from verifier */
|
||||
u_long nsd_ttl; /* credential ttl (sec) */
|
||||
NFSKERBKEY_T nsd_key; /* Session key */
|
||||
};
|
||||
|
||||
struct nfsd_cargs {
|
||||
char *ncd_dirp; /* Mount dir path */
|
||||
uid_t ncd_authuid; /* Effective uid */
|
||||
int ncd_authtype; /* Type of authenticator */
|
||||
int ncd_authlen; /* Length of authenticator string */
|
||||
u_char *ncd_authstr; /* Authenticator string */
|
||||
int ncd_verflen; /* and the verifier */
|
||||
u_char *ncd_verfstr;
|
||||
NFSKERBKEY_T ncd_key; /* Session key */
|
||||
};
|
||||
|
||||
/*
|
||||
* Stats structure
|
||||
*/
|
||||
struct nfsstats {
|
||||
int attrcache_hits;
|
||||
int attrcache_misses;
|
||||
int lookupcache_hits;
|
||||
int lookupcache_misses;
|
||||
int direofcache_hits;
|
||||
int direofcache_misses;
|
||||
int biocache_reads;
|
||||
int read_bios;
|
||||
int read_physios;
|
||||
int biocache_writes;
|
||||
int write_bios;
|
||||
int write_physios;
|
||||
int biocache_readlinks;
|
||||
int readlink_bios;
|
||||
int biocache_readdirs;
|
||||
int readdir_bios;
|
||||
int rpccnt[NFS_NPROCS];
|
||||
int rpcretries;
|
||||
int srvrpccnt[NFS_NPROCS];
|
||||
int srvrpc_errs;
|
||||
int srv_errs;
|
||||
int rpcrequests;
|
||||
int rpctimeouts;
|
||||
int rpcunexpected;
|
||||
int rpcinvalid;
|
||||
int srvcache_inproghits;
|
||||
int srvcache_idemdonehits;
|
||||
int srvcache_nonidemdonehits;
|
||||
int srvcache_misses;
|
||||
int srvnqnfs_leases;
|
||||
int srvnqnfs_maxleases;
|
||||
int srvnqnfs_getleases;
|
||||
int srvvop_writes;
|
||||
};
|
||||
|
||||
/*
|
||||
* Flags for nfssvc() system call.
|
||||
*/
|
||||
#define NFSSVC_BIOD 0x002
|
||||
#define NFSSVC_NFSD 0x004
|
||||
#define NFSSVC_ADDSOCK 0x008
|
||||
#define NFSSVC_AUTHIN 0x010
|
||||
#define NFSSVC_GOTAUTH 0x040
|
||||
#define NFSSVC_AUTHINFAIL 0x080
|
||||
#define NFSSVC_MNTD 0x100
|
||||
|
||||
/*
|
||||
* fs.nfs sysctl(3) identifiers
|
||||
*/
|
||||
#define NFS_NFSSTATS 1 /* struct: struct nfsstats */
|
||||
|
||||
#define FS_NFS_NAMES { \
|
||||
{ 0, 0 }, \
|
||||
{ "nfsstats", CTLTYPE_STRUCT }, \
|
||||
}
|
||||
|
||||
/*
|
||||
* The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
|
||||
* What should be in this set is open to debate, but I believe that since
|
||||
* I/O system calls on ufs are never interrupted by signals the set should
|
||||
* be minimal. My reasoning is that many current programs that use signals
|
||||
* such as SIGALRM will not expect file I/O system calls to be interrupted
|
||||
* by them and break.
|
||||
*/
|
||||
#ifdef KERNEL
|
||||
|
||||
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
|
||||
|
||||
#define NFSINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \
|
||||
sigmask(SIGHUP)|sigmask(SIGQUIT))
|
||||
|
||||
/*
|
||||
* Socket errors ignored for connectionless sockets??
|
||||
* For now, ignore them all
|
||||
*/
|
||||
#define NFSIGNORE_SOERROR(s, e) \
|
||||
((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
|
||||
((s) & PR_CONNREQUIRED) == 0)
|
||||
|
||||
/*
|
||||
* Nfs outstanding request list element
|
||||
*/
|
||||
struct nfsreq {
|
||||
TAILQ_ENTRY(nfsreq) r_chain;
|
||||
struct mbuf *r_mreq;
|
||||
struct mbuf *r_mrep;
|
||||
struct mbuf *r_md;
|
||||
caddr_t r_dpos;
|
||||
struct nfsmount *r_nmp;
|
||||
struct vnode *r_vp;
|
||||
u_long r_xid;
|
||||
int r_flags; /* flags on request, see below */
|
||||
int r_retry; /* max retransmission count */
|
||||
int r_rexmit; /* current retrans count */
|
||||
int r_timer; /* tick counter on reply */
|
||||
int r_procnum; /* NFS procedure number */
|
||||
int r_rtt; /* RTT for rpc */
|
||||
struct proc *r_procp; /* Proc that did I/O system call */
|
||||
};
|
||||
|
||||
/*
|
||||
* Queue head for nfsreq's
|
||||
*/
|
||||
TAILQ_HEAD(, nfsreq) nfs_reqq;
|
||||
|
||||
/* Flag values for r_flags */
|
||||
#define R_TIMING 0x01 /* timing request (in mntp) */
|
||||
#define R_SENT 0x02 /* request has been sent */
|
||||
#define R_SOFTTERM 0x04 /* soft mnt, too many retries */
|
||||
#define R_INTR 0x08 /* intr mnt, signal pending */
|
||||
#define R_SOCKERR 0x10 /* Fatal error on socket */
|
||||
#define R_TPRINTFMSG 0x20 /* Did a tprintf msg. */
|
||||
#define R_MUSTRESEND 0x40 /* Must resend request */
|
||||
#define R_GETONEREP 0x80 /* Probe for one reply only */
|
||||
|
||||
/*
|
||||
* A list of nfssvc_sock structures is maintained with all the sockets
|
||||
* that require service by the nfsd.
|
||||
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
|
||||
* and uid hash lists.
|
||||
*/
|
||||
#ifndef NFS_UIDHASHSIZ
|
||||
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
|
||||
#endif
|
||||
#define NUIDHASH(sock, uid) \
|
||||
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
|
||||
#ifndef NFS_WDELAYHASHSIZ
|
||||
#define NFS_WDELAYHASHSIZ 16 /* and with this */
|
||||
#endif
|
||||
#define NWDELAYHASH(sock, f) \
|
||||
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
|
||||
#ifndef NFS_MUIDHASHSIZ
|
||||
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
|
||||
#endif
|
||||
#define NMUIDHASH(nmp, uid) \
|
||||
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
|
||||
#define NFSNOHASH(fhsum) \
|
||||
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
|
||||
|
||||
/*
|
||||
* Network address hash list element
|
||||
*/
|
||||
union nethostaddr {
|
||||
u_long had_inetaddr;
|
||||
struct mbuf *had_nam;
|
||||
};
|
||||
|
||||
struct nfsuid {
|
||||
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
|
||||
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
|
||||
int nu_flag; /* Flags */
|
||||
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
|
||||
struct ucred nu_cr; /* Cred uid mapped to */
|
||||
int nu_expire; /* Expiry time (sec) */
|
||||
struct timeval nu_timestamp; /* Kerb. timestamp */
|
||||
u_long nu_nickname; /* Nickname on server */
|
||||
NFSKERBKEY_T nu_key; /* and session key */
|
||||
};
|
||||
|
||||
#define nu_inetaddr nu_haddr.had_inetaddr
|
||||
#define nu_nam nu_haddr.had_nam
|
||||
/* Bits for nu_flag */
|
||||
#define NU_INETADDR 0x1
|
||||
#define NU_NAM 0x2
|
||||
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
struct nfssvc_sock {
|
||||
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
|
||||
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
|
||||
struct file *ns_fp;
|
||||
struct socket *ns_so;
|
||||
struct mbuf *ns_nam;
|
||||
struct mbuf *ns_raw;
|
||||
struct mbuf *ns_rawend;
|
||||
struct mbuf *ns_rec;
|
||||
struct mbuf *ns_recend;
|
||||
struct mbuf *ns_frag;
|
||||
int ns_flag;
|
||||
int ns_solock;
|
||||
int ns_cc;
|
||||
int ns_reclen;
|
||||
int ns_numuids;
|
||||
u_long ns_sref;
|
||||
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
|
||||
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
|
||||
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
|
||||
};
|
||||
|
||||
/* Bits for "ns_flag" */
|
||||
#define SLP_VALID 0x01
|
||||
#define SLP_DOREC 0x02
|
||||
#define SLP_NEEDQ 0x04
|
||||
#define SLP_DISCONN 0x08
|
||||
#define SLP_GETSTREAM 0x10
|
||||
#define SLP_LASTFRAG 0x20
|
||||
#define SLP_ALLFLAGS 0xff
|
||||
|
||||
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
|
||||
int nfssvc_sockhead_flag;
|
||||
#define SLP_INIT 0x01
|
||||
#define SLP_WANTINIT 0x02
|
||||
|
||||
/*
|
||||
* One of these structures is allocated for each nfsd.
|
||||
*/
|
||||
struct nfsd {
|
||||
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
|
||||
int nfsd_flag; /* NFSD_ flags */
|
||||
struct nfssvc_sock *nfsd_slp; /* Current socket */
|
||||
int nfsd_authlen; /* Authenticator len */
|
||||
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
|
||||
int nfsd_verflen; /* and the Verifier */
|
||||
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
|
||||
struct proc *nfsd_procp; /* Proc ptr */
|
||||
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
|
||||
};
|
||||
|
||||
/* Bits for "nfsd_flag" */
|
||||
#define NFSD_WAITING 0x01
|
||||
#define NFSD_REQINPROG 0x02
|
||||
#define NFSD_NEEDAUTH 0x04
|
||||
#define NFSD_AUTHFAIL 0x08
|
||||
|
||||
/*
|
||||
* This structure is used by the server for describing each request.
|
||||
* Some fields are used only when write request gathering is performed.
|
||||
*/
|
||||
struct nfsrv_descript {
|
||||
u_quad_t nd_time; /* Write deadline (usec) */
|
||||
off_t nd_off; /* Start byte offset */
|
||||
off_t nd_eoff; /* and end byte offset */
|
||||
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
|
||||
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
|
||||
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
|
||||
struct mbuf *nd_mrep; /* Request mbuf list */
|
||||
struct mbuf *nd_md; /* Current dissect mbuf */
|
||||
struct mbuf *nd_mreq; /* Reply mbuf list */
|
||||
struct mbuf *nd_nam; /* and socket addr */
|
||||
struct mbuf *nd_nam2; /* return socket addr */
|
||||
caddr_t nd_dpos; /* Current dissect pos */
|
||||
int nd_procnum; /* RPC # */
|
||||
int nd_stable; /* storage type */
|
||||
int nd_flag; /* nd_flag */
|
||||
int nd_len; /* Length of this write */
|
||||
int nd_repstat; /* Reply status */
|
||||
u_long nd_retxid; /* Reply xid */
|
||||
u_long nd_duration; /* Lease duration */
|
||||
struct timeval nd_starttime; /* Time RPC initiated */
|
||||
fhandle_t nd_fh; /* File handle */
|
||||
struct ucred nd_cr; /* Credentials */
|
||||
};
|
||||
|
||||
/* Bits for "nd_flag" */
|
||||
#define ND_READ LEASE_READ
|
||||
#define ND_WRITE LEASE_WRITE
|
||||
#define ND_CHECK 0x04
|
||||
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
|
||||
#define ND_NFSV3 0x08
|
||||
#define ND_NQNFS 0x10
|
||||
#define ND_KERBNICK 0x20
|
||||
#define ND_KERBFULL 0x40
|
||||
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
|
||||
|
||||
TAILQ_HEAD(, nfsd) nfsd_head;
|
||||
int nfsd_head_flag;
|
||||
#define NFSD_CHECKSLP 0x01
|
||||
|
||||
/*
|
||||
* These macros compare nfsrv_descript structures.
|
||||
*/
|
||||
#define NFSW_CONTIG(o, n) \
|
||||
((o)->nd_eoff >= (n)->nd_off && \
|
||||
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
|
||||
|
||||
#define NFSW_SAMECRED(o, n) \
|
||||
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
|
||||
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
|
||||
sizeof (struct ucred)))
|
||||
|
||||
int nfs_reply __P((struct nfsreq *));
|
||||
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
|
||||
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
|
||||
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_sndlock __P((int *,struct nfsreq *));
|
||||
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
|
||||
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
|
||||
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
|
||||
int nfs_asyncio __P((struct buf *,struct ucred *));
|
||||
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
|
||||
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
|
||||
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
|
||||
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
|
||||
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
|
||||
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
|
||||
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
|
||||
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
|
||||
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
|
||||
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
|
||||
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
|
||||
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
|
||||
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
|
||||
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
|
||||
void nfsm_adj __P((struct mbuf *,int,int));
|
||||
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
|
||||
void nfsrv_initcache __P((void));
|
||||
int nfs_rcvlock __P((struct nfsreq *));
|
||||
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
|
||||
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
|
||||
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
|
||||
int nfs_msg __P((struct proc *,char *,char *));
|
||||
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
|
||||
int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
void nfs_nhinit __P((void));
|
||||
void nfs_timer __P((void*));
|
||||
u_long nfs_hash __P((nfsfh_t *,int));
|
||||
int nfssvc_iod __P((struct proc *));
|
||||
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
|
||||
int nfssvc_addsock __P((struct file *,struct mbuf *));
|
||||
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
|
||||
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
|
||||
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
|
||||
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
|
||||
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
|
||||
int nfs_getattrcache __P((struct vnode *,struct vattr *));
|
||||
int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
|
||||
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
|
||||
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
|
||||
void nfsrv_init __P((int));
|
||||
void nfs_clearcommit __P((struct mount *));
|
||||
int nfsrv_errmap __P((struct nfsrv_descript *, int));
|
||||
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
|
||||
void nfsrvw_sort __P((gid_t [],int));
|
||||
void nfsrv_setcred __P((struct ucred *,struct ucred *));
|
||||
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
|
||||
int nfs_writebp __P((struct buf *,int));
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif
|
903
sys/nfs/nfs_bio.c
Normal file
903
sys/nfs/nfs_bio.c
Normal file
@ -0,0 +1,903 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/trace.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
|
||||
struct buf *nfs_getcacheblk();
|
||||
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
|
||||
extern int nfs_numasync;
|
||||
extern struct nfsstats nfsstats;
|
||||
|
||||
/*
|
||||
* Vnode op for read using bio
|
||||
* Any similarity to readip() is purely coincidental
|
||||
*/
|
||||
int
|
||||
nfs_bioread(vp, uio, ioflag, cred)
|
||||
register struct vnode *vp;
|
||||
register struct uio *uio;
|
||||
int ioflag;
|
||||
struct ucred *cred;
|
||||
{
|
||||
register struct nfsnode *np = VTONFS(vp);
|
||||
register int biosize, diff, i;
|
||||
struct buf *bp = 0, *rabp;
|
||||
struct vattr vattr;
|
||||
struct proc *p;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
daddr_t lbn, bn, bn2, rabn;
|
||||
caddr_t baddr;
|
||||
int got_buf = 0, nra, error = 0, n = 0, on = 0, not_readin;
|
||||
nfsquad_t tquad;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (uio->uio_rw != UIO_READ)
|
||||
panic("nfs_read mode");
|
||||
#endif
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
if (uio->uio_offset < 0)
|
||||
return (EINVAL);
|
||||
p = uio->uio_procp;
|
||||
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
biosize = nmp->nm_rsize;
|
||||
/*
|
||||
* For nfs, cache consistency can only be maintained approximately.
|
||||
* Although RFC1094 does not specify the criteria, the following is
|
||||
* believed to be compatible with the reference port.
|
||||
* For nqnfs, full cache consistency is maintained within the loop.
|
||||
* For nfs:
|
||||
* If the file's modify time on the server has changed since the
|
||||
* last read rpc or you have written to the file,
|
||||
* you may have lost data cache consistency with the
|
||||
* server, so flush all of the file's data out of the cache.
|
||||
* Then force a getattr rpc to ensure that you have up to date
|
||||
* attributes.
|
||||
* NB: This implies that cache data can be read when up to
|
||||
* NFS_ATTRTIMEO seconds out of date. If you find that you need current
|
||||
* attributes this could be forced by setting n_attrstamp to 0 before
|
||||
* the VOP_GETATTR() call.
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) == 0 && vp->v_type != VLNK) {
|
||||
if (np->n_flag & NMODIFIED) {
|
||||
if (vp->v_type != VREG) {
|
||||
if (vp->v_type != VDIR)
|
||||
panic("nfs: bioread, not dir");
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
np->n_attrstamp = 0;
|
||||
error = VOP_GETATTR(vp, &vattr, cred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_mtime = vattr.va_mtime.ts_sec;
|
||||
} else {
|
||||
error = VOP_GETATTR(vp, &vattr, cred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_mtime != vattr.va_mtime.ts_sec) {
|
||||
if (vp->v_type == VDIR)
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_mtime = vattr.va_mtime.ts_sec;
|
||||
}
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
||||
/*
|
||||
* Get a valid lease. If cached data is stale, flush it.
|
||||
*/
|
||||
if (nmp->nm_flag & NFSMNT_NQNFS) {
|
||||
if (NQNFS_CKINVALID(vp, np, ND_READ)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, ND_READ, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_lrev != np->n_brev ||
|
||||
(np->n_flag & NQNFSNONCACHE) ||
|
||||
((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
|
||||
if (vp->v_type == VDIR)
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_brev = np->n_lrev;
|
||||
}
|
||||
} else if (vp->v_type == VDIR && (np->n_flag & NMODIFIED)) {
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
if (np->n_flag & NQNFSNONCACHE) {
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
return (nfs_readrpc(vp, uio, cred));
|
||||
case VLNK:
|
||||
return (nfs_readlinkrpc(vp, uio, cred));
|
||||
case VDIR:
|
||||
break;
|
||||
default:
|
||||
printf(" NQNFSNONCACHE: type %x unexpected\n",
|
||||
vp->v_type);
|
||||
};
|
||||
}
|
||||
baddr = (caddr_t)0;
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
nfsstats.biocache_reads++;
|
||||
lbn = uio->uio_offset / biosize;
|
||||
on = uio->uio_offset & (biosize - 1);
|
||||
bn = lbn * (biosize / DEV_BSIZE);
|
||||
not_readin = 1;
|
||||
|
||||
/*
|
||||
* Start the read ahead(s), as required.
|
||||
*/
|
||||
if (nfs_numasync > 0 && nmp->nm_readahead > 0) {
|
||||
for (nra = 0; nra < nmp->nm_readahead &&
|
||||
(lbn + 1 + nra) * biosize < np->n_size; nra++) {
|
||||
rabn = (lbn + 1 + nra) * (biosize / DEV_BSIZE);
|
||||
if (!incore(vp, rabn)) {
|
||||
rabp = nfs_getcacheblk(vp, rabn, biosize, p);
|
||||
if (!rabp)
|
||||
return (EINTR);
|
||||
if ((rabp->b_flags & (B_DELWRI | B_DONE)) == 0) {
|
||||
rabp->b_flags |= (B_READ | B_ASYNC);
|
||||
if (nfs_asyncio(rabp, cred)) {
|
||||
rabp->b_flags |= B_INVAL;
|
||||
brelse(rabp);
|
||||
}
|
||||
} else
|
||||
brelse(rabp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the block is in the cache and has the required data
|
||||
* in a valid region, just copy it out.
|
||||
* Otherwise, get the block and write back/read in,
|
||||
* as required.
|
||||
*/
|
||||
if ((bp = incore(vp, bn)) &&
|
||||
(bp->b_flags & (B_BUSY | B_WRITEINPROG)) ==
|
||||
(B_BUSY | B_WRITEINPROG))
|
||||
got_buf = 0;
|
||||
else {
|
||||
again:
|
||||
bp = nfs_getcacheblk(vp, bn, biosize, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
got_buf = 1;
|
||||
if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) {
|
||||
bp->b_flags |= B_READ;
|
||||
not_readin = 0;
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
}
|
||||
n = min((unsigned)(biosize - on), uio->uio_resid);
|
||||
diff = np->n_size - uio->uio_offset;
|
||||
if (diff < n)
|
||||
n = diff;
|
||||
if (not_readin && n > 0) {
|
||||
if (on < bp->b_validoff || (on + n) > bp->b_validend) {
|
||||
if (!got_buf) {
|
||||
bp = nfs_getcacheblk(vp, bn, biosize, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
got_buf = 1;
|
||||
}
|
||||
bp->b_flags |= B_INVAFTERWRITE;
|
||||
if (bp->b_dirtyend > 0) {
|
||||
if ((bp->b_flags & B_DELWRI) == 0)
|
||||
panic("nfsbioread");
|
||||
if (VOP_BWRITE(bp) == EINTR)
|
||||
return (EINTR);
|
||||
} else
|
||||
brelse(bp);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
vp->v_lastr = lbn;
|
||||
diff = (on >= bp->b_validend) ? 0 : (bp->b_validend - on);
|
||||
if (diff < n)
|
||||
n = diff;
|
||||
break;
|
||||
case VLNK:
|
||||
nfsstats.biocache_readlinks++;
|
||||
bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
if ((bp->b_flags & B_DONE) == 0) {
|
||||
bp->b_flags |= B_READ;
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
n = min(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
|
||||
got_buf = 1;
|
||||
on = 0;
|
||||
break;
|
||||
case VDIR:
|
||||
nfsstats.biocache_readdirs++;
|
||||
lbn = uio->uio_offset / NFS_DIRBLKSIZ;
|
||||
on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
|
||||
bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
if ((bp->b_flags & B_DONE) == 0) {
|
||||
bp->b_flags |= B_READ;
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
while (error == NFSERR_BAD_COOKIE) {
|
||||
nfs_invaldir(vp);
|
||||
error = nfs_vinvalbuf(vp, 0, cred, p, 1);
|
||||
/*
|
||||
* Yuck! The directory has been modified on the
|
||||
* server. The only way to get the block is by
|
||||
* reading from the beginning to get all the
|
||||
* offset cookies.
|
||||
*/
|
||||
for (i = 0; i <= lbn && !error; i++) {
|
||||
bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
if ((bp->b_flags & B_DONE) == 0) {
|
||||
bp->b_flags |= B_READ;
|
||||
error = nfs_doio(bp, cred, p);
|
||||
if (error)
|
||||
brelse(bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If not eof and read aheads are enabled, start one.
|
||||
* (You need the current block first, so that you have the
|
||||
* directory offset cookie of the next block.)
|
||||
*/
|
||||
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
|
||||
(np->n_direofoffset == 0 ||
|
||||
(lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
|
||||
!(np->n_flag & NQNFSNONCACHE) &&
|
||||
!incore(vp, lbn + 1)) {
|
||||
rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, p);
|
||||
if (rabp) {
|
||||
if ((rabp->b_flags & (B_DONE | B_DELWRI)) == 0) {
|
||||
rabp->b_flags |= (B_READ | B_ASYNC);
|
||||
if (nfs_asyncio(rabp, cred)) {
|
||||
rabp->b_flags |= B_INVAL;
|
||||
brelse(rabp);
|
||||
}
|
||||
} else
|
||||
brelse(rabp);
|
||||
}
|
||||
}
|
||||
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on);
|
||||
got_buf = 1;
|
||||
break;
|
||||
default:
|
||||
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
|
||||
break;
|
||||
};
|
||||
|
||||
if (n > 0) {
|
||||
if (!baddr)
|
||||
baddr = bp->b_data;
|
||||
error = uiomove(baddr + on, (int)n, uio);
|
||||
}
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
break;
|
||||
case VLNK:
|
||||
n = 0;
|
||||
break;
|
||||
case VDIR:
|
||||
if (np->n_flag & NQNFSNONCACHE)
|
||||
bp->b_flags |= B_INVAL;
|
||||
break;
|
||||
default:
|
||||
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
|
||||
}
|
||||
if (got_buf)
|
||||
brelse(bp);
|
||||
} while (error == 0 && uio->uio_resid > 0 && n > 0);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Vnode op for write using bio
|
||||
*/
|
||||
int
|
||||
nfs_write(ap)
|
||||
struct vop_write_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct uio *a_uio;
|
||||
int a_ioflag;
|
||||
struct ucred *a_cred;
|
||||
} */ *ap;
|
||||
{
|
||||
register int biosize;
|
||||
register struct uio *uio = ap->a_uio;
|
||||
struct proc *p = uio->uio_procp;
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
struct nfsnode *np = VTONFS(vp);
|
||||
register struct ucred *cred = ap->a_cred;
|
||||
int ioflag = ap->a_ioflag;
|
||||
struct buf *bp;
|
||||
struct vattr vattr;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
daddr_t lbn, bn;
|
||||
int n, on, error = 0, iomode, must_commit;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (uio->uio_rw != UIO_WRITE)
|
||||
panic("nfs_write mode");
|
||||
if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
|
||||
panic("nfs_write proc");
|
||||
#endif
|
||||
if (vp->v_type != VREG)
|
||||
return (EIO);
|
||||
if (np->n_flag & NWRITEERR) {
|
||||
np->n_flag &= ~NWRITEERR;
|
||||
return (np->n_error);
|
||||
}
|
||||
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
if (ioflag & (IO_APPEND | IO_SYNC)) {
|
||||
if (np->n_flag & NMODIFIED) {
|
||||
np->n_attrstamp = 0;
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
if (ioflag & IO_APPEND) {
|
||||
np->n_attrstamp = 0;
|
||||
error = VOP_GETATTR(vp, &vattr, cred, p);
|
||||
if (error)
|
||||
return (error);
|
||||
uio->uio_offset = np->n_size;
|
||||
}
|
||||
}
|
||||
if (uio->uio_offset < 0)
|
||||
return (EINVAL);
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
/*
|
||||
* Maybe this should be above the vnode op call, but so long as
|
||||
* file servers have no limits, i don't think it matters
|
||||
*/
|
||||
if (p && uio->uio_offset + uio->uio_resid >
|
||||
p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
|
||||
psignal(p, SIGXFSZ);
|
||||
return (EFBIG);
|
||||
}
|
||||
/*
|
||||
* I use nm_rsize, not nm_wsize so that all buffer cache blocks
|
||||
* will be the same size within a filesystem. nfs_writerpc will
|
||||
* still use nm_wsize when sizing the rpc's.
|
||||
*/
|
||||
biosize = nmp->nm_rsize;
|
||||
do {
|
||||
|
||||
/*
|
||||
* XXX make sure we aren't cached in the VM page cache
|
||||
*/
|
||||
(void)vnode_pager_uncache(vp);
|
||||
|
||||
/*
|
||||
* Check for a valid write lease.
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_lrev != np->n_brev ||
|
||||
(np->n_flag & NQNFSNONCACHE)) {
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_brev = np->n_lrev;
|
||||
}
|
||||
}
|
||||
if ((np->n_flag & NQNFSNONCACHE) && uio->uio_iovcnt == 1) {
|
||||
iomode = NFSV3WRITE_FILESYNC;
|
||||
error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit);
|
||||
if (must_commit)
|
||||
nfs_clearcommit(vp->v_mount);
|
||||
return (error);
|
||||
}
|
||||
nfsstats.biocache_writes++;
|
||||
lbn = uio->uio_offset / biosize;
|
||||
on = uio->uio_offset & (biosize-1);
|
||||
n = min((unsigned)(biosize - on), uio->uio_resid);
|
||||
bn = lbn * (biosize / DEV_BSIZE);
|
||||
again:
|
||||
bp = nfs_getcacheblk(vp, bn, biosize, p);
|
||||
if (!bp)
|
||||
return (EINTR);
|
||||
if (bp->b_wcred == NOCRED) {
|
||||
crhold(cred);
|
||||
bp->b_wcred = cred;
|
||||
}
|
||||
np->n_flag |= NMODIFIED;
|
||||
if (uio->uio_offset + n > np->n_size) {
|
||||
np->n_size = uio->uio_offset + n;
|
||||
vnode_pager_setsize(vp, (u_long)np->n_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the new write will leave a contiguous dirty
|
||||
* area, just update the b_dirtyoff and b_dirtyend,
|
||||
* otherwise force a write rpc of the old dirty area.
|
||||
*/
|
||||
if (bp->b_dirtyend > 0 &&
|
||||
(on > bp->b_dirtyend || (on + n) < bp->b_dirtyoff)) {
|
||||
bp->b_proc = p;
|
||||
if (VOP_BWRITE(bp) == EINTR)
|
||||
return (EINTR);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for valid write lease and get one as required.
|
||||
* In case getblk() and/or bwrite() delayed us.
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
|
||||
do {
|
||||
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
|
||||
} while (error == NQNFS_EXPIRED);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
if (np->n_lrev != np->n_brev ||
|
||||
(np->n_flag & NQNFSNONCACHE)) {
|
||||
brelse(bp);
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
np->n_brev = np->n_lrev;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
error = uiomove((char *)bp->b_data + on, n, uio);
|
||||
if (error) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
if (bp->b_dirtyend > 0) {
|
||||
bp->b_dirtyoff = min(on, bp->b_dirtyoff);
|
||||
bp->b_dirtyend = max((on + n), bp->b_dirtyend);
|
||||
} else {
|
||||
bp->b_dirtyoff = on;
|
||||
bp->b_dirtyend = on + n;
|
||||
}
|
||||
if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
|
||||
bp->b_validoff > bp->b_dirtyend) {
|
||||
bp->b_validoff = bp->b_dirtyoff;
|
||||
bp->b_validend = bp->b_dirtyend;
|
||||
} else {
|
||||
bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
|
||||
bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
|
||||
}
|
||||
/*
|
||||
* If the lease is non-cachable or IO_SYNC do bwrite().
|
||||
*/
|
||||
if ((np->n_flag & NQNFSNONCACHE) || (ioflag & IO_SYNC)) {
|
||||
bp->b_proc = p;
|
||||
error = VOP_BWRITE(bp);
|
||||
if (error)
|
||||
return (error);
|
||||
if (np->n_flag & NQNFSNONCACHE) {
|
||||
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
} else if ((n + on) == biosize &&
|
||||
(nmp->nm_flag & NFSMNT_NQNFS) == 0) {
|
||||
bp->b_proc = (struct proc *)0;
|
||||
bp->b_flags |= B_ASYNC;
|
||||
(void)nfs_writebp(bp, 0);
|
||||
} else
|
||||
bdwrite(bp);
|
||||
} while (uio->uio_resid > 0 && n > 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get an nfs cache block.
|
||||
* Allocate a new one if the block isn't currently in the cache
|
||||
* and return the block marked busy. If the calling process is
|
||||
* interrupted by a signal for an interruptible mount point, return
|
||||
* NULL.
|
||||
*/
|
||||
struct buf *
|
||||
nfs_getcacheblk(vp, bn, size, p)
|
||||
struct vnode *vp;
|
||||
daddr_t bn;
|
||||
int size;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct buf *bp;
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
|
||||
if (nmp->nm_flag & NFSMNT_INT) {
|
||||
bp = getblk(vp, bn, size, PCATCH, 0);
|
||||
while (bp == (struct buf *)0) {
|
||||
if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
|
||||
return ((struct buf *)0);
|
||||
bp = getblk(vp, bn, size, 0, 2 * hz);
|
||||
}
|
||||
} else
|
||||
bp = getblk(vp, bn, size, 0, 0);
|
||||
return (bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush and invalidate all dirty buffers. If another process is already
|
||||
* doing the flush, just wait for completion.
|
||||
*/
|
||||
int
|
||||
nfs_vinvalbuf(vp, flags, cred, p, intrflg)
|
||||
struct vnode *vp;
|
||||
int flags;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
int intrflg;
|
||||
{
|
||||
register struct nfsnode *np = VTONFS(vp);
|
||||
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
int error = 0, slpflag, slptimeo;
|
||||
|
||||
if ((nmp->nm_flag & NFSMNT_INT) == 0)
|
||||
intrflg = 0;
|
||||
if (intrflg) {
|
||||
slpflag = PCATCH;
|
||||
slptimeo = 2 * hz;
|
||||
} else {
|
||||
slpflag = 0;
|
||||
slptimeo = 0;
|
||||
}
|
||||
/*
|
||||
* First wait for any other process doing a flush to complete.
|
||||
*/
|
||||
while (np->n_flag & NFLUSHINPROG) {
|
||||
np->n_flag |= NFLUSHWANT;
|
||||
error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "nfsvinval",
|
||||
slptimeo);
|
||||
if (error && intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, p))
|
||||
return (EINTR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, flush as required.
|
||||
*/
|
||||
np->n_flag |= NFLUSHINPROG;
|
||||
error = vinvalbuf(vp, flags, cred, p, slpflag, 0);
|
||||
while (error) {
|
||||
if (intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, p)) {
|
||||
np->n_flag &= ~NFLUSHINPROG;
|
||||
if (np->n_flag & NFLUSHWANT) {
|
||||
np->n_flag &= ~NFLUSHWANT;
|
||||
wakeup((caddr_t)&np->n_flag);
|
||||
}
|
||||
return (EINTR);
|
||||
}
|
||||
error = vinvalbuf(vp, flags, cred, p, 0, slptimeo);
|
||||
}
|
||||
np->n_flag &= ~(NMODIFIED | NFLUSHINPROG);
|
||||
if (np->n_flag & NFLUSHWANT) {
|
||||
np->n_flag &= ~NFLUSHWANT;
|
||||
wakeup((caddr_t)&np->n_flag);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate asynchronous I/O. Return an error if no nfsiods are available.
|
||||
* This is mainly to avoid queueing async I/O requests when the nfsiods
|
||||
* are all hung on a dead server.
|
||||
*/
|
||||
int
|
||||
nfs_asyncio(bp, cred)
|
||||
register struct buf *bp;
|
||||
struct ucred *cred;
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (nfs_numasync == 0)
|
||||
return (EIO);
|
||||
for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
|
||||
if (nfs_iodwant[i]) {
|
||||
if (bp->b_flags & B_READ) {
|
||||
if (bp->b_rcred == NOCRED && cred != NOCRED) {
|
||||
crhold(cred);
|
||||
bp->b_rcred = cred;
|
||||
}
|
||||
} else {
|
||||
bp->b_flags |= B_WRITEINPROG;
|
||||
if (bp->b_wcred == NOCRED && cred != NOCRED) {
|
||||
crhold(cred);
|
||||
bp->b_wcred = cred;
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&nfs_bufq, bp, b_freelist);
|
||||
nfs_iodwant[i] = (struct proc *)0;
|
||||
wakeup((caddr_t)&nfs_iodwant[i]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it is a read or a write already marked B_WRITEINPROG or B_NOCACHE
|
||||
* return EIO so the process will call nfs_doio() and do it
|
||||
* synchronously.
|
||||
*/
|
||||
if (bp->b_flags & (B_READ | B_WRITEINPROG | B_NOCACHE))
|
||||
return (EIO);
|
||||
|
||||
/*
|
||||
* Just turn the async write into a delayed write, instead of
|
||||
* doing in synchronously. Hopefully, at least one of the nfsiods
|
||||
* is currently doing a write for this file and will pick up the
|
||||
* delayed writes before going back to sleep.
|
||||
*/
|
||||
bp->b_flags |= B_DELWRI;
|
||||
reassignbuf(bp, bp->b_vp);
|
||||
biodone(bp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an I/O operation to/from a cache block. This may be called
|
||||
* synchronously or from an nfsiod.
|
||||
*/
|
||||
int
|
||||
nfs_doio(bp, cr, p)
|
||||
register struct buf *bp;
|
||||
struct ucred *cr;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct uio *uiop;
|
||||
register struct vnode *vp;
|
||||
struct nfsnode *np;
|
||||
struct nfsmount *nmp;
|
||||
int error = 0, diff, len, iomode, must_commit = 0;
|
||||
struct uio uio;
|
||||
struct iovec io;
|
||||
nfsquad_t tquad;
|
||||
|
||||
vp = bp->b_vp;
|
||||
np = VTONFS(vp);
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
uiop = &uio;
|
||||
uiop->uio_iov = &io;
|
||||
uiop->uio_iovcnt = 1;
|
||||
uiop->uio_segflg = UIO_SYSSPACE;
|
||||
uiop->uio_procp = p;
|
||||
|
||||
/*
|
||||
* Historically, paging was done with physio, but no more.
|
||||
*/
|
||||
if (bp->b_flags & B_PHYS) {
|
||||
/*
|
||||
* ...though reading /dev/drum still gets us here.
|
||||
*/
|
||||
io.iov_len = uiop->uio_resid = bp->b_bcount;
|
||||
/* mapping was done by vmapbuf() */
|
||||
io.iov_base = bp->b_data;
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
|
||||
if (bp->b_flags & B_READ) {
|
||||
uiop->uio_rw = UIO_READ;
|
||||
nfsstats.read_physios++;
|
||||
error = nfs_readrpc(vp, uiop, cr);
|
||||
} else
|
||||
panic("physio write");
|
||||
if (error) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = error;
|
||||
}
|
||||
} else if (bp->b_flags & B_READ) {
|
||||
io.iov_len = uiop->uio_resid = bp->b_bcount;
|
||||
io.iov_base = bp->b_data;
|
||||
uiop->uio_rw = UIO_READ;
|
||||
switch (vp->v_type) {
|
||||
case VREG:
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
|
||||
nfsstats.read_bios++;
|
||||
error = nfs_readrpc(vp, uiop, cr);
|
||||
if (!error) {
|
||||
bp->b_validoff = 0;
|
||||
if (uiop->uio_resid) {
|
||||
/*
|
||||
* If len > 0, there is a hole in the file and
|
||||
* no writes after the hole have been pushed to
|
||||
* the server yet.
|
||||
* Just zero fill the rest of the valid area.
|
||||
*/
|
||||
diff = bp->b_bcount - uiop->uio_resid;
|
||||
len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE
|
||||
+ diff);
|
||||
if (len > 0) {
|
||||
len = min(len, uiop->uio_resid);
|
||||
bzero((char *)bp->b_data + diff, len);
|
||||
bp->b_validend = diff + len;
|
||||
} else
|
||||
bp->b_validend = diff;
|
||||
} else
|
||||
bp->b_validend = bp->b_bcount;
|
||||
}
|
||||
if (p && (vp->v_flag & VTEXT) &&
|
||||
(((nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
NQNFS_CKINVALID(vp, np, ND_READ) &&
|
||||
np->n_lrev != np->n_brev) ||
|
||||
(!(nmp->nm_flag & NFSMNT_NQNFS) &&
|
||||
np->n_mtime != np->n_vattr.va_mtime.ts_sec))) {
|
||||
uprintf("Process killed due to text file modification\n");
|
||||
psignal(p, SIGKILL);
|
||||
p->p_flag |= P_NOSWAP;
|
||||
}
|
||||
break;
|
||||
case VLNK:
|
||||
uiop->uio_offset = (off_t)0;
|
||||
nfsstats.readlink_bios++;
|
||||
error = nfs_readlinkrpc(vp, uiop, cr);
|
||||
break;
|
||||
case VDIR:
|
||||
nfsstats.readdir_bios++;
|
||||
uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ;
|
||||
if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
|
||||
error = nfs_readdirplusrpc(vp, uiop, cr);
|
||||
if (error == NFSERR_NOTSUPP)
|
||||
nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
|
||||
}
|
||||
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
|
||||
error = nfs_readdirrpc(vp, uiop, cr);
|
||||
break;
|
||||
default:
|
||||
printf("nfs_doio: type %x unexpected\n",vp->v_type);
|
||||
break;
|
||||
};
|
||||
if (error) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = error;
|
||||
}
|
||||
} else {
|
||||
io.iov_len = uiop->uio_resid = bp->b_dirtyend
|
||||
- bp->b_dirtyoff;
|
||||
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE
|
||||
+ bp->b_dirtyoff;
|
||||
io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
|
||||
uiop->uio_rw = UIO_WRITE;
|
||||
nfsstats.write_bios++;
|
||||
if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE)) == B_ASYNC)
|
||||
iomode = NFSV3WRITE_UNSTABLE;
|
||||
else
|
||||
iomode = NFSV3WRITE_FILESYNC;
|
||||
bp->b_flags |= B_WRITEINPROG;
|
||||
error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit);
|
||||
if (!error && iomode == NFSV3WRITE_UNSTABLE)
|
||||
bp->b_flags |= B_NEEDCOMMIT;
|
||||
else
|
||||
bp->b_flags &= ~B_NEEDCOMMIT;
|
||||
bp->b_flags &= ~B_WRITEINPROG;
|
||||
|
||||
/*
|
||||
* For an interrupted write, the buffer is still valid and the
|
||||
* write hasn't been pushed to the server yet, so we can't set
|
||||
* B_ERROR and report the interruption by setting B_EINTR. For
|
||||
* the B_ASYNC case, B_EINTR is not relevant, so the rpc attempt
|
||||
* is essentially a noop.
|
||||
* For the case of a V3 write rpc not being committed to stable
|
||||
* storage, the block is still dirty and requires either a commit
|
||||
* rpc or another write rpc with iomode == NFSV3WRITE_FILESYNC
|
||||
* before the block is reused. This is indicated by setting the
|
||||
* B_DELWRI and B_NEEDCOMMIT flags.
|
||||
*/
|
||||
if (error == EINTR || (!error && (bp->b_flags & B_NEEDCOMMIT))) {
|
||||
bp->b_flags |= B_DELWRI;
|
||||
|
||||
/*
|
||||
* Since for the B_ASYNC case, nfs_bwrite() has reassigned the
|
||||
* buffer to the clean list, we have to reassign it back to the
|
||||
* dirty one. Ugh.
|
||||
*/
|
||||
if (bp->b_flags & B_ASYNC)
|
||||
reassignbuf(bp, vp);
|
||||
else
|
||||
bp->b_flags |= B_EINTR;
|
||||
} else {
|
||||
if (error) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = np->n_error = error;
|
||||
np->n_flag |= NWRITEERR;
|
||||
}
|
||||
bp->b_dirtyoff = bp->b_dirtyend = 0;
|
||||
}
|
||||
}
|
||||
bp->b_resid = uiop->uio_resid;
|
||||
if (must_commit)
|
||||
nfs_clearcommit(vp->v_mount);
|
||||
biodone(bp);
|
||||
return (error);
|
||||
}
|
255
sys/nfs/nfs_node.c
Normal file
255
sys/nfs/nfs_node.c
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
|
||||
LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
|
||||
u_long nfsnodehash;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/*
|
||||
* Initialize hash links for nfsnodes
|
||||
* and build nfsnode free list.
|
||||
*/
|
||||
void
|
||||
nfs_nhinit()
|
||||
{
|
||||
|
||||
#ifndef lint
|
||||
if ((sizeof(struct nfsnode) - 1) & sizeof(struct nfsnode))
|
||||
printf("nfs_nhinit: bad size %d\n", sizeof(struct nfsnode));
|
||||
#endif /* not lint */
|
||||
nfsnodehashtbl = hashinit(desiredvnodes, M_NFSNODE, &nfsnodehash);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute an entry in the NFS hash table structure
|
||||
*/
|
||||
u_long
|
||||
nfs_hash(fhp, fhsize)
|
||||
register nfsfh_t *fhp;
|
||||
int fhsize;
|
||||
{
|
||||
register u_char *fhpp;
|
||||
register u_long fhsum;
|
||||
register int i;
|
||||
|
||||
fhpp = &fhp->fh_bytes[0];
|
||||
fhsum = 0;
|
||||
for (i = 0; i < fhsize; i++)
|
||||
fhsum += *fhpp++;
|
||||
return (fhsum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up a vnode/nfsnode by file handle.
|
||||
* Callers must check for mount points!!
|
||||
* In all cases, a pointer to a
|
||||
* nfsnode structure is returned.
|
||||
*/
|
||||
int
|
||||
nfs_nget(mntp, fhp, fhsize, npp)
|
||||
struct mount *mntp;
|
||||
register nfsfh_t *fhp;
|
||||
int fhsize;
|
||||
struct nfsnode **npp;
|
||||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct nfsnode *np;
|
||||
struct nfsnodehashhead *nhpp;
|
||||
register struct vnode *vp;
|
||||
extern int (**nfsv2_vnodeop_p)();
|
||||
struct vnode *nvp;
|
||||
int error;
|
||||
|
||||
nhpp = NFSNOHASH(nfs_hash(fhp, fhsize));
|
||||
loop:
|
||||
for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
|
||||
if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
|
||||
bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
|
||||
continue;
|
||||
vp = NFSTOV(np);
|
||||
if (vget(vp, LK_EXCLUSIVE, p))
|
||||
goto loop;
|
||||
*npp = np;
|
||||
return(0);
|
||||
}
|
||||
error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &nvp);
|
||||
if (error) {
|
||||
*npp = 0;
|
||||
return (error);
|
||||
}
|
||||
vp = nvp;
|
||||
MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
|
||||
bzero((caddr_t)np, sizeof *np);
|
||||
vp->v_data = np;
|
||||
np->n_vnode = vp;
|
||||
/*
|
||||
* Insert the nfsnode in the hash queue for its new file handle
|
||||
*/
|
||||
LIST_INSERT_HEAD(nhpp, np, n_hash);
|
||||
if (fhsize > NFS_SMALLFH) {
|
||||
MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK);
|
||||
} else
|
||||
np->n_fhp = &np->n_fh;
|
||||
bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
|
||||
np->n_fhsize = fhsize;
|
||||
*npp = np;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
nfs_inactive(ap)
|
||||
struct vop_inactive_args /* {
|
||||
struct vnode *a_vp;
|
||||
struct proc *a_p;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct nfsnode *np;
|
||||
register struct sillyrename *sp;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
extern int prtactive;
|
||||
|
||||
np = VTONFS(ap->a_vp);
|
||||
if (prtactive && ap->a_vp->v_usecount != 0)
|
||||
vprint("nfs_inactive: pushing active", ap->a_vp);
|
||||
if (ap->a_vp->v_type != VDIR)
|
||||
sp = np->n_sillyrename;
|
||||
else
|
||||
sp = (struct sillyrename *)0;
|
||||
np->n_sillyrename = (struct sillyrename *)0;
|
||||
if (sp) {
|
||||
/*
|
||||
* Remove the silly file that was rename'd earlier
|
||||
*/
|
||||
(void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
|
||||
nfs_removeit(sp);
|
||||
crfree(sp->s_cred);
|
||||
vrele(sp->s_dvp);
|
||||
FREE((caddr_t)sp, M_NFSREQ);
|
||||
}
|
||||
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
|
||||
NQNFSNONCACHE | NQNFSWRITE);
|
||||
VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim an nfsnode so that it can be used for other purposes.
|
||||
*/
|
||||
int
|
||||
nfs_reclaim(ap)
|
||||
struct vop_reclaim_args /* {
|
||||
struct vnode *a_vp;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
register struct nfsnode *np = VTONFS(vp);
|
||||
register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
||||
register struct nfsdmap *dp, *dp2;
|
||||
extern int prtactive;
|
||||
|
||||
if (prtactive && vp->v_usecount != 0)
|
||||
vprint("nfs_reclaim: pushing active", vp);
|
||||
|
||||
LIST_REMOVE(np, n_hash);
|
||||
|
||||
/*
|
||||
* For nqnfs, take it off the timer queue as required.
|
||||
*/
|
||||
if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
|
||||
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up any directory cookie structures and
|
||||
* large file handle structures that might be associated with
|
||||
* this nfs node.
|
||||
*/
|
||||
if (vp->v_type == VDIR) {
|
||||
dp = np->n_cookies.lh_first;
|
||||
while (dp) {
|
||||
dp2 = dp;
|
||||
dp = dp->ndm_list.le_next;
|
||||
FREE((caddr_t)dp2, M_NFSDIROFF);
|
||||
}
|
||||
}
|
||||
if (np->n_fhsize > NFS_SMALLFH) {
|
||||
FREE((caddr_t)np->n_fhp, M_NFSBIGFH);
|
||||
}
|
||||
|
||||
cache_purge(vp);
|
||||
FREE(vp->v_data, M_NFSNODE);
|
||||
vp->v_data = (void *)0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
|
||||
* done. Currently nothing to do.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
nfs_abortop(ap)
|
||||
struct vop_abortop_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
|
||||
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
|
||||
return (0);
|
||||
}
|
1244
sys/nfs/nfs_nqlease.c
Normal file
1244
sys/nfs/nfs_nqlease.c
Normal file
File diff suppressed because it is too large
Load Diff
3337
sys/nfs/nfs_serv.c
Normal file
3337
sys/nfs/nfs_serv.c
Normal file
File diff suppressed because it is too large
Load Diff
2182
sys/nfs/nfs_socket.c
Normal file
2182
sys/nfs/nfs_socket.c
Normal file
File diff suppressed because it is too large
Load Diff
336
sys/nfs/nfs_srvcache.c
Normal file
336
sys/nfs/nfs_srvcache.c
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_srvcache.c 8.3 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reference: Chet Juszczak, "Improving the Performance and Correctness
|
||||
* of an NFS Server", in Proc. Winter 1989 USENIX Conference,
|
||||
* pages 53-63. San Diego, February 1989.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#ifdef ISO
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsrvcache.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
|
||||
extern struct nfsstats nfsstats;
|
||||
extern int nfsv2_procid[NFS_NPROCS];
|
||||
long numnfsrvcache, desirednfsrvcache = NFSRVCACHESIZ;
|
||||
|
||||
#define NFSRCHASH(xid) \
|
||||
(&nfsrvhashtbl[((xid) + ((xid) >> 24)) & nfsrvhash])
|
||||
LIST_HEAD(nfsrvhash, nfsrvcache) *nfsrvhashtbl;
|
||||
TAILQ_HEAD(nfsrvlru, nfsrvcache) nfsrvlruhead;
|
||||
u_long nfsrvhash;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define NETFAMILY(rp) \
|
||||
(((rp)->rc_flag & RC_INETADDR) ? AF_INET : AF_ISO)
|
||||
|
||||
/*
|
||||
* Static array that defines which nfs rpc's are nonidempotent
|
||||
*/
|
||||
int nonidempotent[NFS_NPROCS] = {
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
};
|
||||
|
||||
/* True iff the rpc reply is an nfs status ONLY! */
|
||||
static int nfsv2_repstat[NFS_NPROCS] = {
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the server request cache list
|
||||
*/
|
||||
void
|
||||
nfsrv_initcache()
|
||||
{
|
||||
|
||||
nfsrvhashtbl = hashinit(desirednfsrvcache, M_NFSD, &nfsrvhash);
|
||||
TAILQ_INIT(&nfsrvlruhead);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the request in the cache
|
||||
* If found then
|
||||
* return action and optionally reply
|
||||
* else
|
||||
* insert it in the cache
|
||||
*
|
||||
* The rules are as follows:
|
||||
* - if in progress, return DROP request
|
||||
* - if completed within DELAY of the current time, return DROP it
|
||||
* - if completed a longer time ago return REPLY if the reply was cached or
|
||||
* return DOIT
|
||||
* Update/add new request at end of lru list
|
||||
*/
|
||||
int
|
||||
nfsrv_getcache(nd, slp, repp)
|
||||
register struct nfsrv_descript *nd;
|
||||
struct nfssvc_sock *slp;
|
||||
struct mbuf **repp;
|
||||
{
|
||||
register struct nfsrvcache *rp;
|
||||
struct mbuf *mb;
|
||||
struct sockaddr_in *saddr;
|
||||
caddr_t bpos;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Don't cache recent requests for reliable transport protocols.
|
||||
* (Maybe we should for the case of a reconnect, but..)
|
||||
*/
|
||||
if (!nd->nd_nam2)
|
||||
return (RC_DOIT);
|
||||
loop:
|
||||
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
|
||||
rp = rp->rc_hash.le_next) {
|
||||
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
|
||||
if ((rp->rc_flag & RC_LOCKED) != 0) {
|
||||
rp->rc_flag |= RC_WANTED;
|
||||
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
|
||||
goto loop;
|
||||
}
|
||||
rp->rc_flag |= RC_LOCKED;
|
||||
/* If not at end of LRU chain, move it there */
|
||||
if (rp->rc_lru.tqe_next) {
|
||||
TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
|
||||
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
|
||||
}
|
||||
if (rp->rc_state == RC_UNUSED)
|
||||
panic("nfsrv cache");
|
||||
if (rp->rc_state == RC_INPROG) {
|
||||
nfsstats.srvcache_inproghits++;
|
||||
ret = RC_DROPIT;
|
||||
} else if (rp->rc_flag & RC_REPSTATUS) {
|
||||
nfsstats.srvcache_nonidemdonehits++;
|
||||
nfs_rephead(0, nd, slp, rp->rc_status,
|
||||
0, (u_quad_t *)0, repp, &mb, &bpos);
|
||||
ret = RC_REPLY;
|
||||
} else if (rp->rc_flag & RC_REPMBUF) {
|
||||
nfsstats.srvcache_nonidemdonehits++;
|
||||
*repp = m_copym(rp->rc_reply, 0, M_COPYALL,
|
||||
M_WAIT);
|
||||
ret = RC_REPLY;
|
||||
} else {
|
||||
nfsstats.srvcache_idemdonehits++;
|
||||
rp->rc_state = RC_INPROG;
|
||||
ret = RC_DOIT;
|
||||
}
|
||||
rp->rc_flag &= ~RC_LOCKED;
|
||||
if (rp->rc_flag & RC_WANTED) {
|
||||
rp->rc_flag &= ~RC_WANTED;
|
||||
wakeup((caddr_t)rp);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
nfsstats.srvcache_misses++;
|
||||
if (numnfsrvcache < desirednfsrvcache) {
|
||||
rp = (struct nfsrvcache *)malloc((u_long)sizeof *rp,
|
||||
M_NFSD, M_WAITOK);
|
||||
bzero((char *)rp, sizeof *rp);
|
||||
numnfsrvcache++;
|
||||
rp->rc_flag = RC_LOCKED;
|
||||
} else {
|
||||
rp = nfsrvlruhead.tqh_first;
|
||||
while ((rp->rc_flag & RC_LOCKED) != 0) {
|
||||
rp->rc_flag |= RC_WANTED;
|
||||
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
|
||||
rp = nfsrvlruhead.tqh_first;
|
||||
}
|
||||
rp->rc_flag |= RC_LOCKED;
|
||||
LIST_REMOVE(rp, rc_hash);
|
||||
TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
|
||||
if (rp->rc_flag & RC_REPMBUF)
|
||||
m_freem(rp->rc_reply);
|
||||
if (rp->rc_flag & RC_NAM)
|
||||
MFREE(rp->rc_nam, mb);
|
||||
rp->rc_flag &= (RC_LOCKED | RC_WANTED);
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
|
||||
rp->rc_state = RC_INPROG;
|
||||
rp->rc_xid = nd->nd_retxid;
|
||||
saddr = mtod(nd->nd_nam, struct sockaddr_in *);
|
||||
switch (saddr->sin_family) {
|
||||
case AF_INET:
|
||||
rp->rc_flag |= RC_INETADDR;
|
||||
rp->rc_inetaddr = saddr->sin_addr.s_addr;
|
||||
break;
|
||||
case AF_ISO:
|
||||
default:
|
||||
rp->rc_flag |= RC_NAM;
|
||||
rp->rc_nam = m_copym(nd->nd_nam, 0, M_COPYALL, M_WAIT);
|
||||
break;
|
||||
};
|
||||
rp->rc_proc = nd->nd_procnum;
|
||||
LIST_INSERT_HEAD(NFSRCHASH(nd->nd_retxid), rp, rc_hash);
|
||||
rp->rc_flag &= ~RC_LOCKED;
|
||||
if (rp->rc_flag & RC_WANTED) {
|
||||
rp->rc_flag &= ~RC_WANTED;
|
||||
wakeup((caddr_t)rp);
|
||||
}
|
||||
return (RC_DOIT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update a request cache entry after the rpc has been done
|
||||
*/
|
||||
void
|
||||
nfsrv_updatecache(nd, repvalid, repmbuf)
|
||||
register struct nfsrv_descript *nd;
|
||||
int repvalid;
|
||||
struct mbuf *repmbuf;
|
||||
{
|
||||
register struct nfsrvcache *rp;
|
||||
|
||||
if (!nd->nd_nam2)
|
||||
return;
|
||||
loop:
|
||||
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
|
||||
rp = rp->rc_hash.le_next) {
|
||||
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
|
||||
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
|
||||
if ((rp->rc_flag & RC_LOCKED) != 0) {
|
||||
rp->rc_flag |= RC_WANTED;
|
||||
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
|
||||
goto loop;
|
||||
}
|
||||
rp->rc_flag |= RC_LOCKED;
|
||||
rp->rc_state = RC_DONE;
|
||||
/*
|
||||
* If we have a valid reply update status and save
|
||||
* the reply for non-idempotent rpc's.
|
||||
*/
|
||||
if (repvalid && nonidempotent[nd->nd_procnum]) {
|
||||
if ((nd->nd_flag & ND_NFSV3) == 0 &&
|
||||
nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
|
||||
rp->rc_status = nd->nd_repstat;
|
||||
rp->rc_flag |= RC_REPSTATUS;
|
||||
} else {
|
||||
rp->rc_reply = m_copym(repmbuf,
|
||||
0, M_COPYALL, M_WAIT);
|
||||
rp->rc_flag |= RC_REPMBUF;
|
||||
}
|
||||
}
|
||||
rp->rc_flag &= ~RC_LOCKED;
|
||||
if (rp->rc_flag & RC_WANTED) {
|
||||
rp->rc_flag &= ~RC_WANTED;
|
||||
wakeup((caddr_t)rp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean out the cache. Called when the last nfsd terminates.
|
||||
*/
|
||||
void
|
||||
nfsrv_cleancache()
|
||||
{
|
||||
register struct nfsrvcache *rp, *nextrp;
|
||||
|
||||
for (rp = nfsrvlruhead.tqh_first; rp != 0; rp = nextrp) {
|
||||
nextrp = rp->rc_lru.tqe_next;
|
||||
LIST_REMOVE(rp, rc_hash);
|
||||
TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
|
||||
free(rp, M_NFSD);
|
||||
}
|
||||
numnfsrvcache = 0;
|
||||
}
|
1851
sys/nfs/nfs_subs.c
Normal file
1851
sys/nfs/nfs_subs.c
Normal file
File diff suppressed because it is too large
Load Diff
1125
sys/nfs/nfs_syscalls.c
Normal file
1125
sys/nfs/nfs_syscalls.c
Normal file
File diff suppressed because it is too large
Load Diff
931
sys/nfs/nfs_vfsops.c
Normal file
931
sys/nfs/nfs_vfsops.c
Normal file
@ -0,0 +1,931 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfsnode.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/xdr_subs.h>
|
||||
#include <nfs/nfsm_subs.h>
|
||||
#include <nfs/nfsdiskless.h>
|
||||
#include <nfs/nqnfs.h>
|
||||
|
||||
struct nfsstats nfsstats;
|
||||
static int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
|
||||
struct proc *);
|
||||
extern int nfs_ticks;
|
||||
|
||||
/*
|
||||
* nfs vfs operations.
|
||||
*/
|
||||
struct vfsops nfs_vfsops = {
|
||||
nfs_mount,
|
||||
nfs_start,
|
||||
nfs_unmount,
|
||||
nfs_root,
|
||||
nfs_quotactl,
|
||||
nfs_statfs,
|
||||
nfs_sync,
|
||||
nfs_vget,
|
||||
nfs_fhtovp,
|
||||
nfs_vptofh,
|
||||
nfs_init,
|
||||
nfs_sysctl
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure must be filled in by a primary bootstrap or bootstrap
|
||||
* server for a diskless/dataless machine. It is initialized below just
|
||||
* to ensure that it is allocated to initialized data (.data not .bss).
|
||||
*/
|
||||
struct nfs_diskless nfs_diskless = { 0 };
|
||||
int nfs_diskless_valid = 0;
|
||||
|
||||
void nfs_disconnect __P((struct nfsmount *));
|
||||
void nfsargs_ntoh __P((struct nfs_args *));
|
||||
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
|
||||
struct proc *));
|
||||
static int nfs_mountdiskless __P((char *, char *, int, struct sockaddr_in *,
|
||||
struct nfs_args *, struct proc *, struct vnode **, struct mount **));
|
||||
|
||||
/*
|
||||
* nfs statfs call
|
||||
*/
|
||||
int
|
||||
nfs_statfs(mp, sbp, p)
|
||||
struct mount *mp;
|
||||
register struct statfs *sbp;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct vnode *vp;
|
||||
register struct nfs_statfs *sfp;
|
||||
register caddr_t cp;
|
||||
register u_long *tl;
|
||||
register long t1, t2;
|
||||
caddr_t bpos, dpos, cp2;
|
||||
struct nfsmount *nmp = VFSTONFS(mp);
|
||||
int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
|
||||
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
|
||||
struct ucred *cred;
|
||||
struct nfsnode *np;
|
||||
u_quad_t tquad;
|
||||
|
||||
#ifndef nolint
|
||||
sfp = (struct nfs_statfs *)0;
|
||||
#endif
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return (error);
|
||||
vp = NFSTOV(np);
|
||||
cred = crget();
|
||||
cred->cr_ngroups = 1;
|
||||
if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0)
|
||||
(void)nfs_fsinfo(nmp, vp, cred, p);
|
||||
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
|
||||
nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
|
||||
nfsm_fhtom(vp, v3);
|
||||
nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
|
||||
if (v3)
|
||||
nfsm_postop_attr(vp, retattr);
|
||||
if (!error)
|
||||
nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
|
||||
sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
|
||||
if (v3) {
|
||||
sbp->f_bsize = NFS_FABLKSIZE;
|
||||
fxdr_hyper(&sfp->sf_tbytes, &tquad);
|
||||
sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
fxdr_hyper(&sfp->sf_fbytes, &tquad);
|
||||
sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
fxdr_hyper(&sfp->sf_abytes, &tquad);
|
||||
sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
|
||||
sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1])
|
||||
& 0x7fffffff);
|
||||
sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1])
|
||||
& 0x7fffffff);
|
||||
} else {
|
||||
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
|
||||
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
|
||||
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
|
||||
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
|
||||
sbp->f_files = 0;
|
||||
sbp->f_ffree = 0;
|
||||
}
|
||||
if (sbp != &mp->mnt_stat) {
|
||||
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
|
||||
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
|
||||
}
|
||||
nfsm_reqdone;
|
||||
vrele(vp);
|
||||
crfree(cred);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* nfs version 3 fsinfo rpc call
|
||||
*/
|
||||
int
|
||||
nfs_fsinfo(nmp, vp, cred, p)
|
||||
register struct nfsmount *nmp;
|
||||
register struct vnode *vp;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct nfsv3_fsinfo *fsp;
|
||||
register caddr_t cp;
|
||||
register long t1, t2;
|
||||
register u_long *tl, pref, max;
|
||||
caddr_t bpos, dpos, cp2;
|
||||
int error = 0, retattr;
|
||||
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
|
||||
|
||||
nfsstats.rpccnt[NFSPROC_FSINFO]++;
|
||||
nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
|
||||
nfsm_fhtom(vp, 1);
|
||||
nfsm_request(vp, NFSPROC_FSINFO, p, cred);
|
||||
nfsm_postop_attr(vp, retattr);
|
||||
if (!error) {
|
||||
nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_wtpref);
|
||||
if (pref < nmp->nm_wsize)
|
||||
nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
|
||||
~(NFS_FABLKSIZE - 1);
|
||||
max = fxdr_unsigned(u_long, fsp->fs_wtmax);
|
||||
if (max < nmp->nm_wsize) {
|
||||
nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_wsize == 0)
|
||||
nmp->nm_wsize = max;
|
||||
}
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_rtpref);
|
||||
if (pref < nmp->nm_rsize)
|
||||
nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
|
||||
~(NFS_FABLKSIZE - 1);
|
||||
max = fxdr_unsigned(u_long, fsp->fs_rtmax);
|
||||
if (max < nmp->nm_rsize) {
|
||||
nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_rsize == 0)
|
||||
nmp->nm_rsize = max;
|
||||
}
|
||||
pref = fxdr_unsigned(u_long, fsp->fs_dtpref);
|
||||
if (pref < nmp->nm_readdirsize)
|
||||
nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
|
||||
~(NFS_DIRBLKSIZ - 1);
|
||||
if (max < nmp->nm_readdirsize) {
|
||||
nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
|
||||
if (nmp->nm_readdirsize == 0)
|
||||
nmp->nm_readdirsize = max;
|
||||
}
|
||||
nmp->nm_flag |= NFSMNT_GOTFSINFO;
|
||||
}
|
||||
nfsm_reqdone;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount a remote root fs via. nfs. This depends on the info in the
|
||||
* nfs_diskless structure that has been filled in properly by some primary
|
||||
* bootstrap.
|
||||
* It goes something like this:
|
||||
* - do enough of "ifconfig" by calling ifioctl() so that the system
|
||||
* can talk to the server
|
||||
* - If nfs_diskless.mygateway is filled in, use that address as
|
||||
* a default gateway.
|
||||
* - hand craft the swap nfs vnode hanging off a fake mount point
|
||||
* if swdevt[0].sw_dev == NODEV
|
||||
* - build the rootfs mount point and call mountnfs() to do the rest.
|
||||
*/
|
||||
int
|
||||
nfs_mountroot()
|
||||
{
|
||||
struct mount *mp, *swap_mp;
|
||||
struct nfs_diskless *nd = &nfs_diskless;
|
||||
struct socket *so;
|
||||
struct vnode *vp;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
int error, i;
|
||||
u_long l;
|
||||
char buf[128];
|
||||
|
||||
/*
|
||||
* XXX time must be non-zero when we init the interface or else
|
||||
* the arp code will wedge...
|
||||
*/
|
||||
if (time.tv_sec == 0)
|
||||
time.tv_sec = 1;
|
||||
|
||||
/*
|
||||
* XXX splnet, so networks will receive...
|
||||
*/
|
||||
splnet();
|
||||
|
||||
#ifdef notyet
|
||||
/* Set up swap credentials. */
|
||||
proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
|
||||
proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
|
||||
if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
|
||||
NGROUPS)
|
||||
proc0.p_ucred->cr_ngroups = NGROUPS;
|
||||
for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
|
||||
proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do enough of ifconfig(8) so that the critical net interface can
|
||||
* talk to the server.
|
||||
*/
|
||||
error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0);
|
||||
if (error) {
|
||||
printf("nfs_mountroot: socreate(%04x): %d",
|
||||
nd->myif.ifra_addr.sa_family, error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* We might not have been told the right interface, so we pass
|
||||
* over the first ten interfaces of the same kind, until we get
|
||||
* one of them configured.
|
||||
*/
|
||||
|
||||
for (i = strlen(nd->myif.ifra_name) - 1;
|
||||
nd->myif.ifra_name[i] >= '0' &&
|
||||
nd->myif.ifra_name[i] <= '9';
|
||||
nd->myif.ifra_name[i] ++) {
|
||||
error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p);
|
||||
if(!error)
|
||||
break;
|
||||
}
|
||||
if (error) {
|
||||
printf("nfs_mountroot: SIOCAIFADDR: %d", error);
|
||||
return (error);
|
||||
}
|
||||
soclose(so);
|
||||
|
||||
/*
|
||||
* If the gateway field is filled in, set it as the default route.
|
||||
*/
|
||||
if (nd->mygateway.sin_len != 0) {
|
||||
struct sockaddr_in mask, sin;
|
||||
|
||||
bzero((caddr_t)&mask, sizeof(mask));
|
||||
sin = mask;
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(sin);
|
||||
error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
|
||||
(struct sockaddr *)&nd->mygateway,
|
||||
(struct sockaddr *)&mask,
|
||||
RTF_UP | RTF_GATEWAY, (struct rtentry **)0);
|
||||
if (error) {
|
||||
printf("nfs_mountroot: RTM_ADD: %d", error);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
swap_mp = NULL;
|
||||
if (nd->swap_nblks) {
|
||||
/*
|
||||
* Create a fake mount point just for the swap vnode so that the
|
||||
* swap file can be on a different server from the rootfs.
|
||||
*/
|
||||
nd->swap_args.fh = nd->swap_fh;
|
||||
/*
|
||||
* If using nfsv3_diskless, replace NFSX_V2FH with
|
||||
* nd->swap_fhsize.
|
||||
*/
|
||||
nd->swap_args.fhsize = NFSX_V2FH;
|
||||
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
|
||||
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
|
||||
(l >> 24) & 0xff, (l >> 16) & 0xff,
|
||||
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam);
|
||||
printf("NFS SWAP: %s\n",buf);
|
||||
if (error = nfs_mountdiskless(buf, "/swap", 0,
|
||||
&nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp))
|
||||
return (error);
|
||||
vfs_unbusy(swap_mp, p);
|
||||
|
||||
for (i=0;swdevt[i].sw_dev != NODEV;i++) ;
|
||||
|
||||
/*
|
||||
* Since the swap file is not the root dir of a file system,
|
||||
* hack it to a regular file.
|
||||
*/
|
||||
vp->v_type = VREG;
|
||||
vp->v_flag = 0;
|
||||
swapdev_vp = vp;
|
||||
VREF(vp);
|
||||
swdevt[i].sw_vp = vp;
|
||||
swdevt[i].sw_nblks = nd->swap_nblks*2;
|
||||
|
||||
if (!swdevt[i].sw_nblks) {
|
||||
swdevt[i].sw_nblks = 2048;
|
||||
printf("defaulting to %d kbyte.\n",
|
||||
swdevt[i].sw_nblks/2);
|
||||
} else
|
||||
printf("using %d kbyte.\n",swdevt[i].sw_nblks/2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the rootfs mount point.
|
||||
*/
|
||||
nd->root_args.fh = nd->root_fh;
|
||||
/*
|
||||
* If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize.
|
||||
*/
|
||||
nd->root_args.fhsize = NFSX_V2FH;
|
||||
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
|
||||
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
|
||||
(l >> 24) & 0xff, (l >> 16) & 0xff,
|
||||
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
|
||||
printf("NFS ROOT: %s\n",buf);
|
||||
if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
|
||||
&nd->root_saddr, &nd->root_args, p, &vp, &mp)) {
|
||||
if (swap_mp) {
|
||||
mp->mnt_vfc->vfc_refcount--;
|
||||
free(swap_mp, M_MOUNT);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
simple_lock(&mountlist_slock);
|
||||
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
||||
simple_unlock(&mountlist_slock);
|
||||
rootvp = vp;
|
||||
vfs_unbusy(mp, p);
|
||||
|
||||
/*
|
||||
* This is not really an nfs issue, but it is much easier to
|
||||
* set hostname here and then let the "/etc/rc.xxx" files
|
||||
* mount the right /var based upon its preset value.
|
||||
*/
|
||||
bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
|
||||
hostname[MAXHOSTNAMELEN - 1] = '\0';
|
||||
for (i = 0; i < MAXHOSTNAMELEN; i++)
|
||||
if (hostname[i] == '\0')
|
||||
break;
|
||||
hostnamelen = i;
|
||||
inittodr(ntohl(nd->root_time));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal version of mount system call for diskless setup.
|
||||
*/
|
||||
static int
|
||||
nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp)
|
||||
char *path;
|
||||
char *which;
|
||||
int mountflag;
|
||||
struct sockaddr_in *sin;
|
||||
struct nfs_args *args;
|
||||
struct proc *p;
|
||||
struct vnode **vpp;
|
||||
struct mount **mpp;
|
||||
{
|
||||
struct mount *mp;
|
||||
struct mbuf *m;
|
||||
int error;
|
||||
|
||||
if (error = vfs_rootmountalloc("nfs", path, &mp)) {
|
||||
printf("nfs_mountroot: NFS not configured");
|
||||
return (error);
|
||||
}
|
||||
mp->mnt_flag = mountflag;
|
||||
MGET(m, MT_SONAME, M_WAITOK);
|
||||
bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len);
|
||||
m->m_len = sin->sin_len;
|
||||
if (error = mountnfs(args, mp, m, which, path, vpp)) {
|
||||
printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
|
||||
mp->mnt_vfc->vfc_refcount--;
|
||||
vfs_unbusy(mp, p);
|
||||
free(mp, M_MOUNT);
|
||||
return (error);
|
||||
}
|
||||
(void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
|
||||
*mpp = mp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* VFS Operations.
|
||||
*
|
||||
* mount system call
|
||||
* It seems a bit dumb to copyinstr() the host and path here and then
|
||||
* bcopy() them in mountnfs(), but I wanted to detect errors before
|
||||
* doing the sockargs() call because sockargs() allocates an mbuf and
|
||||
* an error after that means that I have to release the mbuf.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
nfs_mount(mp, path, data, ndp, p)
|
||||
struct mount *mp;
|
||||
char *path;
|
||||
caddr_t data;
|
||||
struct nameidata *ndp;
|
||||
struct proc *p;
|
||||
{
|
||||
int error;
|
||||
struct nfs_args args;
|
||||
struct mbuf *nam;
|
||||
struct vnode *vp;
|
||||
char pth[MNAMELEN], hst[MNAMELEN];
|
||||
u_int len;
|
||||
u_char nfh[NFSX_V3FHMAX];
|
||||
|
||||
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
|
||||
if (error)
|
||||
return (error);
|
||||
if (args.version != NFS_ARGSVERSION)
|
||||
return (EPROGMISMATCH);
|
||||
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
|
||||
if (error)
|
||||
return (error);
|
||||
error = copyinstr(path, pth, MNAMELEN-1, &len);
|
||||
if (error)
|
||||
return (error);
|
||||
bzero(&pth[len], MNAMELEN - len);
|
||||
error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
|
||||
if (error)
|
||||
return (error);
|
||||
bzero(&hst[len], MNAMELEN - len);
|
||||
/* sockargs() call must be after above copyin() calls */
|
||||
error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME);
|
||||
if (error)
|
||||
return (error);
|
||||
args.fh = nfh;
|
||||
error = mountnfs(&args, mp, nam, pth, hst, &vp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for mount and mountroot
|
||||
*/
|
||||
int
|
||||
mountnfs(argp, mp, nam, pth, hst, vpp)
|
||||
register struct nfs_args *argp;
|
||||
register struct mount *mp;
|
||||
struct mbuf *nam;
|
||||
char *pth, *hst;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
register struct nfsmount *nmp;
|
||||
struct nfsnode *np;
|
||||
int error, maxio;
|
||||
|
||||
if (mp->mnt_flag & MNT_UPDATE) {
|
||||
nmp = VFSTONFS(mp);
|
||||
/* update paths, file handles, etc, here XXX */
|
||||
m_freem(nam);
|
||||
return (0);
|
||||
} else {
|
||||
MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
|
||||
M_NFSMNT, M_WAITOK);
|
||||
bzero((caddr_t)nmp, sizeof (struct nfsmount));
|
||||
TAILQ_INIT(&nmp->nm_uidlruhead);
|
||||
mp->mnt_data = (qaddr_t)nmp;
|
||||
}
|
||||
vfs_getnewfsid(mp);
|
||||
nmp->nm_mountp = mp;
|
||||
nmp->nm_flag = argp->flags;
|
||||
if (nmp->nm_flag & NFSMNT_NQNFS)
|
||||
/*
|
||||
* We have to set mnt_maxsymlink to a non-zero value so
|
||||
* that COMPAT_43 routines will know that we are setting
|
||||
* the d_type field in directories (and can zero it for
|
||||
* unsuspecting binaries).
|
||||
*/
|
||||
mp->mnt_maxsymlinklen = 1;
|
||||
nmp->nm_timeo = NFS_TIMEO;
|
||||
nmp->nm_retry = NFS_RETRANS;
|
||||
nmp->nm_wsize = NFS_WSIZE;
|
||||
nmp->nm_rsize = NFS_RSIZE;
|
||||
nmp->nm_readdirsize = NFS_READDIRSIZE;
|
||||
nmp->nm_numgrps = NFS_MAXGRPS;
|
||||
nmp->nm_readahead = NFS_DEFRAHEAD;
|
||||
nmp->nm_leaseterm = NQ_DEFLEASE;
|
||||
nmp->nm_deadthresh = NQ_DEADTHRESH;
|
||||
CIRCLEQ_INIT(&nmp->nm_timerhead);
|
||||
nmp->nm_inprog = NULLVP;
|
||||
nmp->nm_fhsize = argp->fhsize;
|
||||
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
|
||||
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
|
||||
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
|
||||
nmp->nm_nam = nam;
|
||||
|
||||
if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
|
||||
nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
|
||||
if (nmp->nm_timeo < NFS_MINTIMEO)
|
||||
nmp->nm_timeo = NFS_MINTIMEO;
|
||||
else if (nmp->nm_timeo > NFS_MAXTIMEO)
|
||||
nmp->nm_timeo = NFS_MAXTIMEO;
|
||||
}
|
||||
|
||||
if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
|
||||
nmp->nm_retry = argp->retrans;
|
||||
if (nmp->nm_retry > NFS_MAXREXMIT)
|
||||
nmp->nm_retry = NFS_MAXREXMIT;
|
||||
}
|
||||
|
||||
if (argp->flags & NFSMNT_NFSV3) {
|
||||
if (argp->sotype == SOCK_DGRAM)
|
||||
maxio = NFS_MAXDGRAMDATA;
|
||||
else
|
||||
maxio = NFS_MAXDATA;
|
||||
} else
|
||||
maxio = NFS_V2MAXDATA;
|
||||
|
||||
if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
|
||||
nmp->nm_wsize = argp->wsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_wsize <= 0)
|
||||
nmp->nm_wsize = NFS_FABLKSIZE;
|
||||
}
|
||||
if (nmp->nm_wsize > maxio)
|
||||
nmp->nm_wsize = maxio;
|
||||
if (nmp->nm_wsize > MAXBSIZE)
|
||||
nmp->nm_wsize = MAXBSIZE;
|
||||
|
||||
if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
|
||||
nmp->nm_rsize = argp->rsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
|
||||
if (nmp->nm_rsize <= 0)
|
||||
nmp->nm_rsize = NFS_FABLKSIZE;
|
||||
}
|
||||
if (nmp->nm_rsize > maxio)
|
||||
nmp->nm_rsize = maxio;
|
||||
if (nmp->nm_rsize > MAXBSIZE)
|
||||
nmp->nm_rsize = MAXBSIZE;
|
||||
|
||||
if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
|
||||
nmp->nm_readdirsize = argp->readdirsize;
|
||||
/* Round down to multiple of blocksize */
|
||||
nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1);
|
||||
if (nmp->nm_readdirsize < NFS_DIRBLKSIZ)
|
||||
nmp->nm_readdirsize = NFS_DIRBLKSIZ;
|
||||
}
|
||||
if (nmp->nm_readdirsize > maxio)
|
||||
nmp->nm_readdirsize = maxio;
|
||||
|
||||
if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
|
||||
argp->maxgrouplist <= NFS_MAXGRPS)
|
||||
nmp->nm_numgrps = argp->maxgrouplist;
|
||||
if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 &&
|
||||
argp->readahead <= NFS_MAXRAHEAD)
|
||||
nmp->nm_readahead = argp->readahead;
|
||||
if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 &&
|
||||
argp->leaseterm <= NQ_MAXLEASE)
|
||||
nmp->nm_leaseterm = argp->leaseterm;
|
||||
if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 &&
|
||||
argp->deadthresh <= NQ_NEVERDEAD)
|
||||
nmp->nm_deadthresh = argp->deadthresh;
|
||||
/* Set up the sockets and per-host congestion */
|
||||
nmp->nm_sotype = argp->sotype;
|
||||
nmp->nm_soproto = argp->proto;
|
||||
|
||||
/*
|
||||
* For Connection based sockets (TCP,...) defer the connect until
|
||||
* the first request, in case the server is not responding.
|
||||
*/
|
||||
if (nmp->nm_sotype == SOCK_DGRAM &&
|
||||
(error = nfs_connect(nmp, (struct nfsreq *)0)))
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* This is silly, but it has to be set so that vinifod() works.
|
||||
* We do not want to do an nfs_statfs() here since we can get
|
||||
* stuck on a dead server and we are holding a lock on the mount
|
||||
* point.
|
||||
*/
|
||||
mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
|
||||
/*
|
||||
* A reference count is needed on the nfsnode representing the
|
||||
* remote root. If this object is not persistent, then backward
|
||||
* traversals of the mount point (i.e. "..") will not work if
|
||||
* the nfsnode gets flushed out of the cache. Ufs does not have
|
||||
* this problem, because one can identify root inodes by their
|
||||
* number == ROOTINO (2).
|
||||
*/
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
goto bad;
|
||||
*vpp = NFSTOV(np);
|
||||
|
||||
return (0);
|
||||
bad:
|
||||
nfs_disconnect(nmp);
|
||||
free((caddr_t)nmp, M_NFSMNT);
|
||||
m_freem(nam);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* unmount system call
|
||||
*/
|
||||
int
|
||||
nfs_unmount(mp, mntflags, p)
|
||||
struct mount *mp;
|
||||
int mntflags;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct nfsmount *nmp;
|
||||
struct nfsnode *np;
|
||||
struct vnode *vp;
|
||||
int error, flags = 0;
|
||||
|
||||
if (mntflags & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
nmp = VFSTONFS(mp);
|
||||
/*
|
||||
* Goes something like this..
|
||||
* - Check for activity on the root vnode (other than ourselves).
|
||||
* - Call vflush() to clear out vnodes for this file system,
|
||||
* except for the root vnode.
|
||||
* - Decrement reference on the vnode representing remote root.
|
||||
* - Close the socket
|
||||
* - Free up the data structures
|
||||
*/
|
||||
/*
|
||||
* We need to decrement the ref. count on the nfsnode representing
|
||||
* the remote root. See comment in mountnfs(). The VFS unmount()
|
||||
* has done vput on this vnode, otherwise we would get deadlock!
|
||||
*/
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return(error);
|
||||
vp = NFSTOV(np);
|
||||
if (vp->v_usecount > 2) {
|
||||
vput(vp);
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must handshake with nqnfs_clientd() if it is active.
|
||||
*/
|
||||
nmp->nm_flag |= NFSMNT_DISMINPROG;
|
||||
while (nmp->nm_inprog != NULLVP)
|
||||
(void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0);
|
||||
error = vflush(mp, vp, flags);
|
||||
if (error) {
|
||||
vput(vp);
|
||||
nmp->nm_flag &= ~NFSMNT_DISMINPROG;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* We are now committed to the unmount.
|
||||
* For NQNFS, let the server daemon free the nfsmount structure.
|
||||
*/
|
||||
if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB))
|
||||
nmp->nm_flag |= NFSMNT_DISMNT;
|
||||
|
||||
/*
|
||||
* There are two reference counts to get rid of here.
|
||||
*/
|
||||
vrele(vp);
|
||||
vrele(vp);
|
||||
vgone(vp);
|
||||
nfs_disconnect(nmp);
|
||||
m_freem(nmp->nm_nam);
|
||||
|
||||
if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
|
||||
free((caddr_t)nmp, M_NFSMNT);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return root of a filesystem
|
||||
*/
|
||||
int
|
||||
nfs_root(mp, vpp)
|
||||
struct mount *mp;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
register struct vnode *vp;
|
||||
struct nfsmount *nmp;
|
||||
struct nfsnode *np;
|
||||
int error;
|
||||
|
||||
nmp = VFSTONFS(mp);
|
||||
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
|
||||
if (error)
|
||||
return (error);
|
||||
vp = NFSTOV(np);
|
||||
vp->v_type = VDIR;
|
||||
vp->v_flag = VROOT;
|
||||
*vpp = vp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
extern int syncprt;
|
||||
|
||||
/*
|
||||
* Flush out the buffer cache
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
nfs_sync(mp, waitfor, cred, p)
|
||||
struct mount *mp;
|
||||
int waitfor;
|
||||
struct ucred *cred;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct vnode *vp;
|
||||
int error, allerror = 0;
|
||||
|
||||
/*
|
||||
* Force stale buffer cache information to be flushed.
|
||||
*/
|
||||
loop:
|
||||
for (vp = mp->mnt_vnodelist.lh_first;
|
||||
vp != NULL;
|
||||
vp = vp->v_mntvnodes.le_next) {
|
||||
/*
|
||||
* If the vnode that we are about to sync is no longer
|
||||
* associated with this mount point, start over.
|
||||
*/
|
||||
if (vp->v_mount != mp)
|
||||
goto loop;
|
||||
if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL)
|
||||
continue;
|
||||
if (vget(vp, LK_EXCLUSIVE, p))
|
||||
goto loop;
|
||||
error = VOP_FSYNC(vp, cred, waitfor, p);
|
||||
if (error)
|
||||
allerror = error;
|
||||
vput(vp);
|
||||
}
|
||||
return (allerror);
|
||||
}
|
||||
|
||||
/*
|
||||
* NFS flat namespace lookup.
|
||||
* Currently unsupported.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
nfs_vget(mp, ino, vpp)
|
||||
struct mount *mp;
|
||||
ino_t ino;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, this should never happen
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
|
||||
register struct mount *mp;
|
||||
struct fid *fhp;
|
||||
struct mbuf *nam;
|
||||
struct vnode **vpp;
|
||||
int *exflagsp;
|
||||
struct ucred **credanonp;
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Vnode pointer to File handle, should never happen either
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
nfs_vptofh(vp, fhp)
|
||||
struct vnode *vp;
|
||||
struct fid *fhp;
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Vfs start routine, a no-op.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
nfs_start(mp, flags, p)
|
||||
struct mount *mp;
|
||||
int flags;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do operations associated with quotas, not supported
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
nfs_quotactl(mp, cmd, uid, arg, p)
|
||||
struct mount *mp;
|
||||
int cmd;
|
||||
uid_t uid;
|
||||
caddr_t arg;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do that sysctl thang...
|
||||
*/
|
||||
static int
|
||||
nfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
|
||||
size_t newlen, struct proc *p)
|
||||
{
|
||||
int rv;
|
||||
|
||||
/*
|
||||
* All names at this level are terminal.
|
||||
*/
|
||||
if(namelen > 1)
|
||||
return ENOTDIR; /* overloaded */
|
||||
|
||||
switch(name[0]) {
|
||||
case NFS_NFSSTATS:
|
||||
if(!oldp) {
|
||||
*oldlenp = sizeof nfsstats;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(*oldlenp < sizeof nfsstats) {
|
||||
*oldlenp = sizeof nfsstats;
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
rv = copyout(&nfsstats, oldp, sizeof nfsstats);
|
||||
if(rv) return rv;
|
||||
|
||||
if(newp && newlen != sizeof nfsstats)
|
||||
return EINVAL;
|
||||
|
||||
if(newp) {
|
||||
return copyin(newp, &nfsstats, sizeof nfsstats);
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
3250
sys/nfs/nfs_vnops.c
Normal file
3250
sys/nfs/nfs_vnops.c
Normal file
File diff suppressed because it is too large
Load Diff
100
sys/nfs/nfsdiskless.h
Normal file
100
sys/nfs/nfsdiskless.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsdiskless.h 8.2 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_NFSDISKLESS_H_
|
||||
#define _NFS_NFSDISKLESS_H_
|
||||
|
||||
/*
|
||||
* Structure that must be initialized for a diskless nfs client.
|
||||
* This structure is used by nfs_mountroot() to set up the root and swap
|
||||
* vnodes plus do a partial ifconfig(8) and route(8) so that the critical net
|
||||
* interface can communicate with the server.
|
||||
* The primary bootstrap is expected to fill in the appropriate fields before
|
||||
* starting the kernel. Whether or not the swap area is nfs mounted is
|
||||
* determined by the value in swdevt[0]. (equal to NODEV --> swap over nfs)
|
||||
* Currently only works for AF_INET protocols.
|
||||
* NB: All fields are stored in net byte order to avoid hassles with
|
||||
* client/server byte ordering differences.
|
||||
*/
|
||||
|
||||
/*
|
||||
* I have defined a new structure that can handle an NFS Version 3 file handle
|
||||
* but the kernel still expects the old Version 2 one to be provided. The
|
||||
* changes required in nfs_vfsops.c for using the new are documented there in
|
||||
* comments. (I felt that breaking network booting code by changing this
|
||||
* structure would not be prudent at this time, since almost all servers are
|
||||
* still Version 2 anyhow.)
|
||||
*/
|
||||
struct nfsv3_diskless {
|
||||
struct ifaliasreq myif; /* Default interface */
|
||||
struct sockaddr_in mygateway; /* Default gateway */
|
||||
struct nfs_args swap_args; /* Mount args for swap file */
|
||||
int swap_fhsize; /* Size of file handle */
|
||||
u_char swap_fh[NFSX_V3FHMAX]; /* Swap file's file handle */
|
||||
struct sockaddr_in swap_saddr; /* Address of swap server */
|
||||
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
int swap_nblks; /* Size of server swap file */
|
||||
struct ucred swap_ucred; /* Swap credentials */
|
||||
struct nfs_args root_args; /* Mount args for root fs */
|
||||
int root_fhsize; /* Size of root file handle */
|
||||
u_char root_fh[NFSX_V3FHMAX]; /* File handle of root dir */
|
||||
struct sockaddr_in root_saddr; /* Address of root server */
|
||||
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
long root_time; /* Timestamp of root fs */
|
||||
char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
|
||||
};
|
||||
|
||||
struct nfs_diskless {
|
||||
struct ifaliasreq myif; /* Default interface */
|
||||
struct sockaddr_in mygateway; /* Default gateway */
|
||||
struct nfs_args swap_args; /* Mount args for swap file */
|
||||
u_char swap_fh[NFSX_V2FH]; /* Swap file's file handle */
|
||||
struct sockaddr_in swap_saddr; /* Address of swap server */
|
||||
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
int swap_nblks; /* Size of server swap file */
|
||||
struct ucred swap_ucred; /* Swap credentials */
|
||||
struct nfs_args root_args; /* Mount args for root fs */
|
||||
u_char root_fh[NFSX_V2FH]; /* File handle of root dir */
|
||||
struct sockaddr_in root_saddr; /* Address of root server */
|
||||
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
|
||||
long root_time; /* Timestamp of root fs */
|
||||
char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
|
||||
};
|
||||
|
||||
#endif
|
439
sys/nfs/nfsm_subs.h
Normal file
439
sys/nfs/nfsm_subs.h
Normal file
@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_NFSM_SUBS_H_
|
||||
#define _NFS_NFSM_SUBS_H_
|
||||
|
||||
|
||||
/*
|
||||
* These macros do strange and peculiar things to mbuf chains for
|
||||
* the assistance of the nfs code. To attempt to use them for any
|
||||
* other purpose will be dangerous. (they make weird assumptions)
|
||||
*/
|
||||
|
||||
/*
|
||||
* First define what the actual subs. return
|
||||
*/
|
||||
extern struct mbuf *nfsm_reqh();
|
||||
|
||||
#define M_HASCL(m) ((m)->m_flags & M_EXT)
|
||||
#define NFSMINOFF(m) \
|
||||
if (M_HASCL(m)) \
|
||||
(m)->m_data = (m)->m_ext.ext_buf; \
|
||||
else if ((m)->m_flags & M_PKTHDR) \
|
||||
(m)->m_data = (m)->m_pktdat; \
|
||||
else \
|
||||
(m)->m_data = (m)->m_dat
|
||||
#define NFSMADV(m, s) (m)->m_data += (s)
|
||||
#define NFSMSIZ(m) ((M_HASCL(m))?MCLBYTES: \
|
||||
(((m)->m_flags & M_PKTHDR)?MHLEN:MLEN))
|
||||
|
||||
/*
|
||||
* Now for the macros that do the simple stuff and call the functions
|
||||
* for the hard stuff.
|
||||
* These macros use several vars. declared in nfsm_reqhead and these
|
||||
* vars. must not be used elsewhere unless you are careful not to corrupt
|
||||
* them. The vars. starting with pN and tN (N=1,2,3,..) are temporaries
|
||||
* that may be used so long as the value is not expected to retained
|
||||
* after a macro.
|
||||
* I know, this is kind of dorkey, but it makes the actual op functions
|
||||
* fairly clean and deals with the mess caused by the xdr discriminating
|
||||
* unions.
|
||||
*/
|
||||
|
||||
#define nfsm_build(a,c,s) \
|
||||
{ if ((s) > M_TRAILINGSPACE(mb)) { \
|
||||
MGET(mb2, M_WAIT, MT_DATA); \
|
||||
if ((s) > MLEN) \
|
||||
panic("build > MLEN"); \
|
||||
mb->m_next = mb2; \
|
||||
mb = mb2; \
|
||||
mb->m_len = 0; \
|
||||
bpos = mtod(mb, caddr_t); \
|
||||
} \
|
||||
(a) = (c)(bpos); \
|
||||
mb->m_len += (s); \
|
||||
bpos += (s); }
|
||||
|
||||
#define nfsm_dissect(a, c, s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
(a) = (c)(dpos); \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} else { \
|
||||
(a) = (c)cp2; \
|
||||
} }
|
||||
|
||||
#define nfsm_fhtom(v, v3) \
|
||||
{ if (v3) { \
|
||||
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
|
||||
if (t2 <= M_TRAILINGSPACE(mb)) { \
|
||||
nfsm_build(tl, u_long *, t2); \
|
||||
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
|
||||
*(tl + ((t2>>2) - 2)) = 0; \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
|
||||
VTONFS(v)->n_fhsize); \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
|
||||
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvfhtom(f, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
} else { \
|
||||
nfsm_build(cp, caddr_t, NFSX_V2FH); \
|
||||
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvpostop_fh(f) \
|
||||
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
|
||||
*tl++ = nfs_true; \
|
||||
*tl++ = txdr_unsigned(NFSX_V3FH); \
|
||||
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_mtofh(d, v, v3, f) \
|
||||
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
} else \
|
||||
(f) = 1; \
|
||||
if (f) { \
|
||||
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
|
||||
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
|
||||
&ttnp)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = NFSTOV(ttnp); \
|
||||
} \
|
||||
if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
(f) = fxdr_unsigned(int, *tl); \
|
||||
else if (fxdr_unsigned(int, *tl)) \
|
||||
nfsm_adv(NFSX_V3FATTR); \
|
||||
} \
|
||||
if (f) \
|
||||
nfsm_loadattr((v), (struct vattr *)0); \
|
||||
}
|
||||
|
||||
#define nfsm_getfh(f, s, v3) \
|
||||
{ if (v3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
|
||||
(s) > NFSX_V3FHMAX) { \
|
||||
m_freem(mrep); \
|
||||
error = EBADRPC; \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
} else \
|
||||
(s) = NFSX_V2FH; \
|
||||
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
|
||||
|
||||
#define nfsm_loadattr(v, a) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = ttvp; }
|
||||
|
||||
#define nfsm_postop_attr(v, f) \
|
||||
{ struct vnode *ttvp = (v); \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if ((f) = fxdr_unsigned(int, *tl)) { \
|
||||
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
|
||||
(struct vattr *)0)) { \
|
||||
error = t1; \
|
||||
(f) = 0; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
(v) = ttvp; \
|
||||
} }
|
||||
|
||||
/* Used as (f) for nfsm_wcc_data() */
|
||||
#define NFSV3_WCCRATTR 0
|
||||
#define NFSV3_WCCCHK 1
|
||||
|
||||
#define nfsm_wcc_data(v, f) \
|
||||
{ int ttattrf, ttretf = 0; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
|
||||
if (f) \
|
||||
ttretf = (VTONFS(v)->n_mtime == \
|
||||
fxdr_unsigned(u_long, *(tl + 2))); \
|
||||
} \
|
||||
nfsm_postop_attr((v), ttattrf); \
|
||||
if (f) { \
|
||||
(f) = ttretf; \
|
||||
} else { \
|
||||
(f) = ttattrf; \
|
||||
} }
|
||||
|
||||
#define nfsm_v3sattr(s, a, u, g) \
|
||||
{ (s)->sa_modetrue = nfs_true; \
|
||||
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
|
||||
(s)->sa_uidtrue = nfs_true; \
|
||||
(s)->sa_uid = txdr_unsigned(u); \
|
||||
(s)->sa_gidtrue = nfs_true; \
|
||||
(s)->sa_gid = txdr_unsigned(g); \
|
||||
(s)->sa_sizefalse = nfs_false; \
|
||||
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
|
||||
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
|
||||
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
|
||||
}
|
||||
|
||||
#define nfsm_strsiz(s,m) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(long,*tl)) > (m)) { \
|
||||
m_freem(mrep); \
|
||||
error = EBADRPC; \
|
||||
goto nfsmout; \
|
||||
} }
|
||||
|
||||
#define nfsm_srvstrsiz(s,m) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(long,*tl)) > (m) || (s) <= 0) { \
|
||||
error = EBADRPC; \
|
||||
nfsm_reply(0); \
|
||||
} }
|
||||
|
||||
#define nfsm_srvnamesiz(s) \
|
||||
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
|
||||
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
|
||||
error = NFSERR_NAMETOL; \
|
||||
if ((s) <= 0) \
|
||||
error = EBADRPC; \
|
||||
if (error) \
|
||||
nfsm_reply(0); \
|
||||
}
|
||||
|
||||
#define nfsm_mtouio(p,s) \
|
||||
if ((s) > 0 && \
|
||||
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_uiotom(p,s) \
|
||||
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
|
||||
error = t1; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_reqhead(v,a,s) \
|
||||
mb = mreq = nfsm_reqh((v),(a),(s),&bpos)
|
||||
|
||||
#define nfsm_reqdone m_freem(mrep); \
|
||||
nfsmout:
|
||||
|
||||
#define nfsm_rndup(a) (((a)+3)&(~0x3))
|
||||
|
||||
#define nfsm_request(v, t, p, c) \
|
||||
if (error = nfs_request((v), mreq, (t), (p), \
|
||||
(c), &mrep, &md, &dpos)) { \
|
||||
if (error & NFSERR_RETERR) \
|
||||
error &= ~NFSERR_RETERR; \
|
||||
else \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_strtom(a,s,m) \
|
||||
if ((s) > (m)) { \
|
||||
m_freem(mreq); \
|
||||
error = ENAMETOOLONG; \
|
||||
goto nfsmout; \
|
||||
} \
|
||||
t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \
|
||||
if (t2 <= M_TRAILINGSPACE(mb)) { \
|
||||
nfsm_build(tl,u_long *,t2); \
|
||||
*tl++ = txdr_unsigned(s); \
|
||||
*(tl+((t2>>2)-2)) = 0; \
|
||||
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
|
||||
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
|
||||
error = t2; \
|
||||
m_freem(mreq); \
|
||||
goto nfsmout; \
|
||||
}
|
||||
|
||||
#define nfsm_srvdone \
|
||||
nfsmout: \
|
||||
return(error)
|
||||
|
||||
#define nfsm_reply(s) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
mrq, &mb, &bpos); \
|
||||
m_freem(mrep); \
|
||||
mreq = *mrq; \
|
||||
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
|
||||
error == EBADRPC)) \
|
||||
return(0); \
|
||||
}
|
||||
|
||||
#define nfsm_writereply(s, v3) \
|
||||
{ \
|
||||
nfsd->nd_repstat = error; \
|
||||
if (error && !(v3)) \
|
||||
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
else \
|
||||
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
|
||||
&mreq, &mb, &bpos); \
|
||||
}
|
||||
|
||||
#define nfsm_adv(s) \
|
||||
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
|
||||
if (t1 >= (s)) { \
|
||||
dpos += (s); \
|
||||
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
|
||||
error = t1; \
|
||||
m_freem(mrep); \
|
||||
goto nfsmout; \
|
||||
} }
|
||||
|
||||
#define nfsm_srvmtofh(f) \
|
||||
{ if (nfsd->nd_flag & ND_NFSV3) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
|
||||
error = EBADRPC; \
|
||||
nfsm_reply(0); \
|
||||
} \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
|
||||
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
|
||||
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
|
||||
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
|
||||
}
|
||||
|
||||
#define nfsm_clget \
|
||||
if (bp >= be) { \
|
||||
if (mp == mb) \
|
||||
mp->m_len += bp-bpos; \
|
||||
MGET(mp, M_WAIT, MT_DATA); \
|
||||
MCLGET(mp, M_WAIT); \
|
||||
mp->m_len = NFSMSIZ(mp); \
|
||||
mp2->m_next = mp; \
|
||||
mp2 = mp; \
|
||||
bp = mtod(mp, caddr_t); \
|
||||
be = bp+mp->m_len; \
|
||||
} \
|
||||
tl = (u_long *)bp
|
||||
|
||||
#define nfsm_srvfillattr(a, f) \
|
||||
nfsm_srvfattr(nfsd, (a), (f))
|
||||
|
||||
#define nfsm_srvwcc_data(br, b, ar, a) \
|
||||
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvpostop_attr(r, a) \
|
||||
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
|
||||
|
||||
#define nfsm_srvsattr(a) \
|
||||
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_mode = nfstov_mode(*tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
if (*tl == nfs_true) { \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_hyper(tl, &(a)->va_size); \
|
||||
} \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_atime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_atime.ts_sec = time.tv_sec; \
|
||||
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; \
|
||||
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
|
||||
switch (fxdr_unsigned(int, *tl)) { \
|
||||
case NFSV3SATTRTIME_TOCLIENT: \
|
||||
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
|
||||
fxdr_nfsv3time(tl, &(a)->va_mtime); \
|
||||
break; \
|
||||
case NFSV3SATTRTIME_TOSERVER: \
|
||||
(a)->va_mtime.ts_sec = time.tv_sec; \
|
||||
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
|
||||
break; \
|
||||
}; }
|
||||
|
||||
#endif
|
141
sys/nfs/nfsmount.h
Normal file
141
sys/nfs/nfsmount.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsmount.h 8.3 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_NFSMOUNT_H_
|
||||
#define _NFS_NFSMOUNT_H_
|
||||
|
||||
/*
|
||||
* Mount structure.
|
||||
* One allocated on every NFS mount.
|
||||
* Holds NFS specific information for mount.
|
||||
*/
|
||||
struct nfsmount {
|
||||
int nm_flag; /* Flags for soft/hard... */
|
||||
struct mount *nm_mountp; /* Vfs structure for this filesystem */
|
||||
int nm_numgrps; /* Max. size of groupslist */
|
||||
u_char nm_fh[NFSX_V3FHMAX]; /* File handle of root dir */
|
||||
int nm_fhsize; /* Size of root file handle */
|
||||
struct socket *nm_so; /* Rpc socket */
|
||||
int nm_sotype; /* Type of socket */
|
||||
int nm_soproto; /* and protocol */
|
||||
int nm_soflags; /* pr_flags for socket protocol */
|
||||
struct mbuf *nm_nam; /* Addr of server */
|
||||
int nm_timeo; /* Init timer for NFSMNT_DUMBTIMR */
|
||||
int nm_retry; /* Max retries */
|
||||
int nm_srtt[4]; /* Timers for rpcs */
|
||||
int nm_sdrtt[4];
|
||||
int nm_sent; /* Request send count */
|
||||
int nm_cwnd; /* Request send window */
|
||||
int nm_timeouts; /* Request timeouts */
|
||||
int nm_deadthresh; /* Threshold of timeouts-->dead server*/
|
||||
int nm_rsize; /* Max size of read rpc */
|
||||
int nm_wsize; /* Max size of write rpc */
|
||||
int nm_readdirsize; /* Size of a readdir rpc */
|
||||
int nm_readahead; /* Num. of blocks to readahead */
|
||||
int nm_leaseterm; /* Term (sec) for NQNFS lease */
|
||||
CIRCLEQ_HEAD(, nfsnode) nm_timerhead; /* Head of lease timer queue */
|
||||
struct vnode *nm_inprog; /* Vnode in prog by nqnfs_clientd() */
|
||||
uid_t nm_authuid; /* Uid for authenticator */
|
||||
int nm_authtype; /* Authenticator type */
|
||||
int nm_authlen; /* and length */
|
||||
char *nm_authstr; /* Authenticator string */
|
||||
char *nm_verfstr; /* and the verifier */
|
||||
int nm_verflen;
|
||||
u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */
|
||||
NFSKERBKEY_T nm_key; /* and the session key */
|
||||
int nm_numuids; /* Number of nfsuid mappings */
|
||||
TAILQ_HEAD(, nfsuid) nm_uidlruhead; /* Lists of nfsuid mappings */
|
||||
LIST_HEAD(, nfsuid) nm_uidhashtbl[NFS_MUIDHASHSIZ];
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
/*
|
||||
* Convert mount ptr to nfsmount ptr.
|
||||
*/
|
||||
#define VFSTONFS(mp) ((struct nfsmount *)((mp)->mnt_data))
|
||||
#endif /* KERNEL */
|
||||
|
||||
/*
|
||||
* Prototypes for NFS mount operations
|
||||
*/
|
||||
int nfs_mount __P((
|
||||
struct mount *mp,
|
||||
char *path,
|
||||
caddr_t data,
|
||||
struct nameidata *ndp,
|
||||
struct proc *p));
|
||||
int nfs_start __P((
|
||||
struct mount *mp,
|
||||
int flags,
|
||||
struct proc *p));
|
||||
int nfs_unmount __P((
|
||||
struct mount *mp,
|
||||
int mntflags,
|
||||
struct proc *p));
|
||||
int nfs_root __P((
|
||||
struct mount *mp,
|
||||
struct vnode **vpp));
|
||||
int nfs_quotactl __P((
|
||||
struct mount *mp,
|
||||
int cmds,
|
||||
uid_t uid,
|
||||
caddr_t arg,
|
||||
struct proc *p));
|
||||
int nfs_statfs __P((
|
||||
struct mount *mp,
|
||||
struct statfs *sbp,
|
||||
struct proc *p));
|
||||
int nfs_sync __P((
|
||||
struct mount *mp,
|
||||
int waitfor,
|
||||
struct ucred *cred,
|
||||
struct proc *p));
|
||||
int nfs_fhtovp __P((
|
||||
struct mount *mp,
|
||||
struct fid *fhp,
|
||||
struct mbuf *nam,
|
||||
struct vnode **vpp,
|
||||
int *exflagsp,
|
||||
struct ucred **credanonp));
|
||||
int nfs_vptofh __P((
|
||||
struct vnode *vp,
|
||||
struct fid *fhp));
|
||||
int nfs_init __P(());
|
||||
|
||||
#endif
|
220
sys/nfs/nfsnode.h
Normal file
220
sys/nfs/nfsnode.h
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsnode.h 8.9 (Berkeley) 5/14/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_NFSNODE_H_
|
||||
#define _NFS_NFSNODE_H_
|
||||
|
||||
#ifndef _NFS_NFS_H_
|
||||
#include <nfs/nfs.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Silly rename structure that hangs off the nfsnode until the name
|
||||
* can be removed by nfs_inactive()
|
||||
*/
|
||||
struct sillyrename {
|
||||
struct ucred *s_cred;
|
||||
struct vnode *s_dvp;
|
||||
long s_namlen;
|
||||
char s_name[20];
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure is used to save the logical directory offset to
|
||||
* NFS cookie mappings.
|
||||
* The mappings are stored in a list headed
|
||||
* by n_cookies, as required.
|
||||
* There is one mapping for each NFS_DIRBLKSIZ bytes of directory information
|
||||
* stored in increasing logical offset byte order.
|
||||
*/
|
||||
#define NFSNUMCOOKIES 31
|
||||
|
||||
struct nfsdmap {
|
||||
LIST_ENTRY(nfsdmap) ndm_list;
|
||||
int ndm_eocookie;
|
||||
nfsuint64 ndm_cookies[NFSNUMCOOKIES];
|
||||
};
|
||||
|
||||
/*
|
||||
* The nfsnode is the nfs equivalent to ufs's inode. Any similarity
|
||||
* is purely coincidental.
|
||||
* There is a unique nfsnode allocated for each active file,
|
||||
* each current directory, each mounted-on file, text file, and the root.
|
||||
* An nfsnode is 'named' by its file handle. (nget/nfs_node.c)
|
||||
* If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
|
||||
* type definitions), file handles of > 32 bytes should probably be split out
|
||||
* into a separate MALLOC()'d data structure. (Reduce the size of nfsfh_t by
|
||||
* changing the definition in sys/mount.h of NFS_SMALLFH.)
|
||||
* NB: Hopefully the current order of the fields is such that everything will
|
||||
* be well aligned and, therefore, tightly packed.
|
||||
*/
|
||||
struct nfsnode {
|
||||
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
|
||||
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
|
||||
u_quad_t n_size; /* Current size of file */
|
||||
u_quad_t n_brev; /* Modify rev when cached */
|
||||
u_quad_t n_lrev; /* Modify rev for lease */
|
||||
struct vattr n_vattr; /* Vnode attribute cache */
|
||||
time_t n_attrstamp; /* Attr. cache timestamp */
|
||||
time_t n_mtime; /* Prev modify time. */
|
||||
time_t n_ctime; /* Prev create time. */
|
||||
time_t n_expiry; /* Lease expiry time */
|
||||
nfsfh_t *n_fhp; /* NFS File Handle */
|
||||
struct vnode *n_vnode; /* associated vnode */
|
||||
struct lockf *n_lockf; /* Locking record of file */
|
||||
int n_error; /* Save write error value */
|
||||
union {
|
||||
struct timespec nf_atim; /* Special file times */
|
||||
nfsuint64 nd_cookieverf; /* Cookie verifier (dir only) */
|
||||
} n_un1;
|
||||
union {
|
||||
struct timespec nf_mtim;
|
||||
off_t nd_direof; /* Dir. EOF offset cache */
|
||||
} n_un2;
|
||||
union {
|
||||
struct sillyrename *nf_silly; /* Ptr to silly rename struct */
|
||||
LIST_HEAD(, nfsdmap) nd_cook; /* cookies */
|
||||
} n_un3;
|
||||
short n_fhsize; /* size in bytes, of fh */
|
||||
short n_flag; /* Flag for locking.. */
|
||||
nfsfh_t n_fh; /* Small File Handle */
|
||||
};
|
||||
|
||||
#define n_atim n_un1.nf_atim
|
||||
#define n_mtim n_un2.nf_mtim
|
||||
#define n_sillyrename n_un3.nf_silly
|
||||
#define n_cookieverf n_un1.nd_cookieverf
|
||||
#define n_direofoffset n_un2.nd_direof
|
||||
#define n_cookies n_un3.nd_cook
|
||||
|
||||
/*
|
||||
* Flags for n_flag
|
||||
*/
|
||||
#define NFLUSHWANT 0x0001 /* Want wakeup from a flush in prog. */
|
||||
#define NFLUSHINPROG 0x0002 /* Avoid multiple calls to vinvalbuf() */
|
||||
#define NMODIFIED 0x0004 /* Might have a modified buffer in bio */
|
||||
#define NWRITEERR 0x0008 /* Flag write errors so close will know */
|
||||
#define NQNFSNONCACHE 0x0020 /* Non-cachable lease */
|
||||
#define NQNFSWRITE 0x0040 /* Write lease */
|
||||
#define NQNFSEVICTED 0x0080 /* Has been evicted */
|
||||
#define NACC 0x0100 /* Special file accessed */
|
||||
#define NUPD 0x0200 /* Special file updated */
|
||||
#define NCHG 0x0400 /* Special file times changed */
|
||||
|
||||
/*
|
||||
* Convert between nfsnode pointers and vnode pointers
|
||||
*/
|
||||
#define VTONFS(vp) ((struct nfsnode *)(vp)->v_data)
|
||||
#define NFSTOV(np) ((struct vnode *)(np)->n_vnode)
|
||||
|
||||
/*
|
||||
* Queue head for nfsiod's
|
||||
*/
|
||||
TAILQ_HEAD(, buf) nfs_bufq;
|
||||
|
||||
#ifdef KERNEL
|
||||
/*
|
||||
* Prototypes for NFS vnode operations
|
||||
*/
|
||||
int nfs_lookup __P((struct vop_lookup_args *));
|
||||
int nfs_create __P((struct vop_create_args *));
|
||||
int nfs_mknod __P((struct vop_mknod_args *));
|
||||
int nfs_open __P((struct vop_open_args *));
|
||||
int nfs_close __P((struct vop_close_args *));
|
||||
int nfsspec_close __P((struct vop_close_args *));
|
||||
int nfsfifo_close __P((struct vop_close_args *));
|
||||
int nfs_access __P((struct vop_access_args *));
|
||||
int nfsspec_access __P((struct vop_access_args *));
|
||||
int nfs_getattr __P((struct vop_getattr_args *));
|
||||
int nfs_setattr __P((struct vop_setattr_args *));
|
||||
int nfs_read __P((struct vop_read_args *));
|
||||
int nfs_write __P((struct vop_write_args *));
|
||||
#define nfs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
|
||||
#define nqnfs_vop_lease_check lease_check
|
||||
int nfsspec_read __P((struct vop_read_args *));
|
||||
int nfsspec_write __P((struct vop_write_args *));
|
||||
int nfsfifo_read __P((struct vop_read_args *));
|
||||
int nfsfifo_write __P((struct vop_write_args *));
|
||||
#define nfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))enoioctl)
|
||||
#define nfs_select ((int (*) __P((struct vop_select_args *)))seltrue)
|
||||
#define nfs_revoke vop_revoke
|
||||
int nfs_mmap __P((struct vop_mmap_args *));
|
||||
int nfs_fsync __P((struct vop_fsync_args *));
|
||||
#define nfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
|
||||
int nfs_remove __P((struct vop_remove_args *));
|
||||
int nfs_link __P((struct vop_link_args *));
|
||||
int nfs_rename __P((struct vop_rename_args *));
|
||||
int nfs_mkdir __P((struct vop_mkdir_args *));
|
||||
int nfs_rmdir __P((struct vop_rmdir_args *));
|
||||
int nfs_symlink __P((struct vop_symlink_args *));
|
||||
int nfs_readdir __P((struct vop_readdir_args *));
|
||||
int nfs_readlink __P((struct vop_readlink_args *));
|
||||
int nfs_abortop __P((struct vop_abortop_args *));
|
||||
int nfs_inactive __P((struct vop_inactive_args *));
|
||||
int nfs_reclaim __P((struct vop_reclaim_args *));
|
||||
#define nfs_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
|
||||
#define nfs_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
|
||||
#define nfs_islocked ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
|
||||
int nfs_bmap __P((struct vop_bmap_args *));
|
||||
int nfs_strategy __P((struct vop_strategy_args *));
|
||||
int nfs_print __P((struct vop_print_args *));
|
||||
int nfs_pathconf __P((struct vop_pathconf_args *));
|
||||
int nfs_advlock __P((struct vop_advlock_args *));
|
||||
int nfs_blkatoff __P((struct vop_blkatoff_args *));
|
||||
int nfs_bwrite __P((struct vop_bwrite_args *));
|
||||
int nfs_vget __P((struct mount *, ino_t, struct vnode **));
|
||||
int nfs_valloc __P((struct vop_valloc_args *));
|
||||
#define nfs_reallocblks \
|
||||
((int (*) __P((struct vop_reallocblks_args *)))eopnotsupp)
|
||||
int nfs_vfree __P((struct vop_vfree_args *));
|
||||
int nfs_truncate __P((struct vop_truncate_args *));
|
||||
int nfs_update __P((struct vop_update_args *));
|
||||
|
||||
/* other stuff */
|
||||
int nfs_removeit __P((struct sillyrename *));
|
||||
int nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
|
||||
int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **));
|
||||
int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
|
||||
nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
|
||||
void nfs_invaldir __P((struct vnode *));
|
||||
#define nqnfs_lease_updatetime lease_updatetime
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif
|
441
sys/nfs/nfsproto.h
Normal file
441
sys/nfs/nfsproto.h
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsproto.h 8.2 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
#ifndef _NFS_NFSPROTO_H_
|
||||
#define _NFS_NFSPROTO_H_
|
||||
|
||||
|
||||
/*
|
||||
* nfs definitions as per the Version 2 and 3 specs
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants as defined in the Sun NFS Version 2 and 3 specs.
|
||||
* "NFS: Network File System Protocol Specification" RFC1094
|
||||
* and in the "NFS: Network File System Version 3 Protocol
|
||||
* Specification"
|
||||
*/
|
||||
|
||||
#define NFS_PORT 2049
|
||||
#define NFS_PROG 100003
|
||||
#define NFS_VER2 2
|
||||
#define NFS_VER3 3
|
||||
#define NFS_V2MAXDATA 8192
|
||||
#define NFS_MAXDGRAMDATA 16384
|
||||
#define NFS_MAXDATA 32768
|
||||
#define NFS_MAXPATHLEN 1024
|
||||
#define NFS_MAXNAMLEN 255
|
||||
#define NFS_MAXPKTHDR 404
|
||||
#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
|
||||
#define NFS_MINPACKET 20
|
||||
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
|
||||
|
||||
/* Stat numbers for rpc returns (version 2 and 3) */
|
||||
#define NFS_OK 0
|
||||
#define NFSERR_PERM 1
|
||||
#define NFSERR_NOENT 2
|
||||
#define NFSERR_IO 5
|
||||
#define NFSERR_NXIO 6
|
||||
#define NFSERR_ACCES 13
|
||||
#define NFSERR_EXIST 17
|
||||
#define NFSERR_XDEV 18 /* Version 3 only */
|
||||
#define NFSERR_NODEV 19
|
||||
#define NFSERR_NOTDIR 20
|
||||
#define NFSERR_ISDIR 21
|
||||
#define NFSERR_INVAL 22 /* Version 3 only */
|
||||
#define NFSERR_FBIG 27
|
||||
#define NFSERR_NOSPC 28
|
||||
#define NFSERR_ROFS 30
|
||||
#define NFSERR_MLINK 31 /* Version 3 only */
|
||||
#define NFSERR_NAMETOL 63
|
||||
#define NFSERR_NOTEMPTY 66
|
||||
#define NFSERR_DQUOT 69
|
||||
#define NFSERR_STALE 70
|
||||
#define NFSERR_REMOTE 71 /* Version 3 only */
|
||||
#define NFSERR_WFLUSH 99 /* Version 2 only */
|
||||
#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
|
||||
#define NFSERR_NOT_SYNC 10002
|
||||
#define NFSERR_BAD_COOKIE 10003
|
||||
#define NFSERR_NOTSUPP 10004
|
||||
#define NFSERR_TOOSMALL 10005
|
||||
#define NFSERR_SERVERFAULT 10006
|
||||
#define NFSERR_BADTYPE 10007
|
||||
#define NFSERR_JUKEBOX 10008
|
||||
#define NFSERR_TRYLATER NFSERR_JUKEBOX
|
||||
#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */
|
||||
|
||||
#define NFSERR_RETVOID 0x20000000 /* Return void, not error */
|
||||
#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */
|
||||
#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */
|
||||
|
||||
/* Sizes in bytes of various nfs rpc components */
|
||||
#define NFSX_UNSIGNED 4
|
||||
|
||||
/* specific to NFS Version 2 */
|
||||
#define NFSX_V2FH 32
|
||||
#define NFSX_V2FATTR 68
|
||||
#define NFSX_V2SATTR 32
|
||||
#define NFSX_V2COOKIE 4
|
||||
#define NFSX_V2STATFS 20
|
||||
|
||||
/* specific to NFS Version 3 */
|
||||
#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */
|
||||
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
|
||||
#define NFSX_V3FATTR 84
|
||||
#define NFSX_V3SATTR 60 /* max. all fields filled in */
|
||||
#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr))
|
||||
#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
|
||||
#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
|
||||
#define NFSX_V3COOKIEVERF 8
|
||||
#define NFSX_V3WRITEVERF 8
|
||||
#define NFSX_V3CREATEVERF 8
|
||||
#define NFSX_V3STATFS 52
|
||||
#define NFSX_V3FSINFO 48
|
||||
#define NFSX_V3PATHCONF 24
|
||||
|
||||
/* variants for both versions */
|
||||
#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
|
||||
NFSX_V2FH)
|
||||
#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH)
|
||||
#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
|
||||
#define NFSX_PREOPATTR(v3) ((v3) ? (7 * NFSX_UNSIGNED) : 0)
|
||||
#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
|
||||
#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
|
||||
NFSX_V2FATTR)
|
||||
#define NFSX_WCCDATA(v3) ((v3) ? NFSX_V3WCCDATA : 0)
|
||||
#define NFSX_WCCORFATTR(v3) ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR)
|
||||
#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
|
||||
#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0)
|
||||
#define NFSX_WRITEVERF(v3) ((v3) ? NFSX_V3WRITEVERF : 0)
|
||||
#define NFSX_READDIR(v3) ((v3) ? (5 * NFSX_UNSIGNED) : \
|
||||
(2 * NFSX_UNSIGNED))
|
||||
#define NFSX_STATFS(v3) ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS)
|
||||
|
||||
/* nfs rpc procedure numbers (before version mapping) */
|
||||
#define NFSPROC_NULL 0
|
||||
#define NFSPROC_GETATTR 1
|
||||
#define NFSPROC_SETATTR 2
|
||||
#define NFSPROC_LOOKUP 3
|
||||
#define NFSPROC_ACCESS 4
|
||||
#define NFSPROC_READLINK 5
|
||||
#define NFSPROC_READ 6
|
||||
#define NFSPROC_WRITE 7
|
||||
#define NFSPROC_CREATE 8
|
||||
#define NFSPROC_MKDIR 9
|
||||
#define NFSPROC_SYMLINK 10
|
||||
#define NFSPROC_MKNOD 11
|
||||
#define NFSPROC_REMOVE 12
|
||||
#define NFSPROC_RMDIR 13
|
||||
#define NFSPROC_RENAME 14
|
||||
#define NFSPROC_LINK 15
|
||||
#define NFSPROC_READDIR 16
|
||||
#define NFSPROC_READDIRPLUS 17
|
||||
#define NFSPROC_FSSTAT 18
|
||||
#define NFSPROC_FSINFO 19
|
||||
#define NFSPROC_PATHCONF 20
|
||||
#define NFSPROC_COMMIT 21
|
||||
|
||||
/* And leasing (nqnfs) procedure numbers (must be last) */
|
||||
#define NQNFSPROC_GETLEASE 22
|
||||
#define NQNFSPROC_VACATED 23
|
||||
#define NQNFSPROC_EVICTED 24
|
||||
|
||||
#define NFSPROC_NOOP 25
|
||||
#define NFS_NPROCS 26
|
||||
|
||||
/* Actual Version 2 procedure numbers */
|
||||
#define NFSV2PROC_NULL 0
|
||||
#define NFSV2PROC_GETATTR 1
|
||||
#define NFSV2PROC_SETATTR 2
|
||||
#define NFSV2PROC_NOOP 3
|
||||
#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */
|
||||
#define NFSV2PROC_LOOKUP 4
|
||||
#define NFSV2PROC_READLINK 5
|
||||
#define NFSV2PROC_READ 6
|
||||
#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */
|
||||
#define NFSV2PROC_WRITE 8
|
||||
#define NFSV2PROC_CREATE 9
|
||||
#define NFSV2PROC_REMOVE 10
|
||||
#define NFSV2PROC_RENAME 11
|
||||
#define NFSV2PROC_LINK 12
|
||||
#define NFSV2PROC_SYMLINK 13
|
||||
#define NFSV2PROC_MKDIR 14
|
||||
#define NFSV2PROC_RMDIR 15
|
||||
#define NFSV2PROC_READDIR 16
|
||||
#define NFSV2PROC_STATFS 17
|
||||
|
||||
/*
|
||||
* Constants used by the Version 3 protocol for various RPCs
|
||||
*/
|
||||
#define NFSV3SATTRTIME_DONTCHANGE 0
|
||||
#define NFSV3SATTRTIME_TOSERVER 1
|
||||
#define NFSV3SATTRTIME_TOCLIENT 2
|
||||
|
||||
#define NFSV3ACCESS_READ 0x01
|
||||
#define NFSV3ACCESS_LOOKUP 0x02
|
||||
#define NFSV3ACCESS_MODIFY 0x04
|
||||
#define NFSV3ACCESS_EXTEND 0x08
|
||||
#define NFSV3ACCESS_DELETE 0x10
|
||||
#define NFSV3ACCESS_EXECUTE 0x20
|
||||
|
||||
#define NFSV3WRITE_UNSTABLE 0
|
||||
#define NFSV3WRITE_DATASYNC 1
|
||||
#define NFSV3WRITE_FILESYNC 2
|
||||
|
||||
#define NFSV3CREATE_UNCHECKED 0
|
||||
#define NFSV3CREATE_GUARDED 1
|
||||
#define NFSV3CREATE_EXCLUSIVE 2
|
||||
|
||||
#define NFSV3FSINFO_LINK 0x01
|
||||
#define NFSV3FSINFO_SYMLINK 0x02
|
||||
#define NFSV3FSINFO_HOMOGENEOUS 0x08
|
||||
#define NFSV3FSINFO_CANSETTIME 0x10
|
||||
|
||||
/* Conversion macros */
|
||||
#define vtonfsv2_mode(t,m) \
|
||||
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
|
||||
MAKEIMODE((t), (m)))
|
||||
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
|
||||
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
|
||||
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((long)(a))])
|
||||
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((long)(a))])
|
||||
#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_long,(a))&0x7]
|
||||
|
||||
/* File types */
|
||||
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
|
||||
NFSOCK=6, NFFIFO=7 } nfstype;
|
||||
|
||||
/* Structs for common parts of the rpc's */
|
||||
/*
|
||||
* File Handle (32 bytes for version 2), variable up to 64 for version 3.
|
||||
* File Handles of up to NFS_SMALLFH in size are stored directly in the
|
||||
* nfs node, whereas larger ones are malloc'd. (This never happens when
|
||||
* NFS_SMALLFH is set to 64.)
|
||||
* NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4.
|
||||
*/
|
||||
#ifndef NFS_SMALLFH
|
||||
#define NFS_SMALLFH 64
|
||||
#endif
|
||||
union nfsfh {
|
||||
fhandle_t fh_generic;
|
||||
u_char fh_bytes[NFS_SMALLFH];
|
||||
};
|
||||
typedef union nfsfh nfsfh_t;
|
||||
|
||||
struct nfsv2_time {
|
||||
u_long nfsv2_sec;
|
||||
u_long nfsv2_usec;
|
||||
};
|
||||
typedef struct nfsv2_time nfstime2;
|
||||
|
||||
struct nfsv3_time {
|
||||
u_long nfsv3_sec;
|
||||
u_long nfsv3_nsec;
|
||||
};
|
||||
typedef struct nfsv3_time nfstime3;
|
||||
|
||||
/*
|
||||
* Quads are defined as arrays of 2 longs to ensure dense packing for the
|
||||
* protocol and to facilitate xdr conversion.
|
||||
*/
|
||||
struct nfs_uquad {
|
||||
u_long nfsuquad[2];
|
||||
};
|
||||
typedef struct nfs_uquad nfsuint64;
|
||||
|
||||
/*
|
||||
* Used to convert between two u_longs and a u_quad_t.
|
||||
*/
|
||||
union nfs_quadconvert {
|
||||
u_long lval[2];
|
||||
u_quad_t qval;
|
||||
};
|
||||
typedef union nfs_quadconvert nfsquad_t;
|
||||
|
||||
/*
|
||||
* NFS Version 3 special file number.
|
||||
*/
|
||||
struct nfsv3_spec {
|
||||
u_long specdata1;
|
||||
u_long specdata2;
|
||||
};
|
||||
typedef struct nfsv3_spec nfsv3spec;
|
||||
|
||||
/*
|
||||
* File attributes and setable attributes. These structures cover both
|
||||
* NFS version 2 and the version 3 protocol. Note that the union is only
|
||||
* used so that one pointer can refer to both variants. These structures
|
||||
* go out on the wire and must be densely packed, so no quad data types
|
||||
* are used. (all fields are longs or u_longs or structures of same)
|
||||
* NB: You can't do sizeof(struct nfs_fattr), you must use the
|
||||
* NFSX_FATTR(v3) macro.
|
||||
*/
|
||||
struct nfs_fattr {
|
||||
u_long fa_type;
|
||||
u_long fa_mode;
|
||||
u_long fa_nlink;
|
||||
u_long fa_uid;
|
||||
u_long fa_gid;
|
||||
union {
|
||||
struct {
|
||||
u_long nfsv2fa_size;
|
||||
u_long nfsv2fa_blocksize;
|
||||
u_long nfsv2fa_rdev;
|
||||
u_long nfsv2fa_blocks;
|
||||
u_long nfsv2fa_fsid;
|
||||
u_long nfsv2fa_fileid;
|
||||
nfstime2 nfsv2fa_atime;
|
||||
nfstime2 nfsv2fa_mtime;
|
||||
nfstime2 nfsv2fa_ctime;
|
||||
} fa_nfsv2;
|
||||
struct {
|
||||
nfsuint64 nfsv3fa_size;
|
||||
nfsuint64 nfsv3fa_used;
|
||||
nfsv3spec nfsv3fa_rdev;
|
||||
nfsuint64 nfsv3fa_fsid;
|
||||
nfsuint64 nfsv3fa_fileid;
|
||||
nfstime3 nfsv3fa_atime;
|
||||
nfstime3 nfsv3fa_mtime;
|
||||
nfstime3 nfsv3fa_ctime;
|
||||
} fa_nfsv3;
|
||||
} fa_un;
|
||||
};
|
||||
|
||||
/* and some ugly defines for accessing union components */
|
||||
#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size
|
||||
#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize
|
||||
#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev
|
||||
#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks
|
||||
#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid
|
||||
#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid
|
||||
#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime
|
||||
#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime
|
||||
#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime
|
||||
#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size
|
||||
#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used
|
||||
#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev
|
||||
#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid
|
||||
#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid
|
||||
#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime
|
||||
#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
|
||||
#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
|
||||
|
||||
struct nfsv2_sattr {
|
||||
u_long sa_mode;
|
||||
u_long sa_uid;
|
||||
u_long sa_gid;
|
||||
u_long sa_size;
|
||||
nfstime2 sa_atime;
|
||||
nfstime2 sa_mtime;
|
||||
};
|
||||
|
||||
/*
|
||||
* NFS Version 3 sattr structure for the new node creation case.
|
||||
*/
|
||||
struct nfsv3_sattr {
|
||||
u_long sa_modetrue;
|
||||
u_long sa_mode;
|
||||
u_long sa_uidtrue;
|
||||
u_long sa_uid;
|
||||
u_long sa_gidtrue;
|
||||
u_long sa_gid;
|
||||
u_long sa_sizefalse;
|
||||
u_long sa_atimetype;
|
||||
nfstime3 sa_atime;
|
||||
u_long sa_mtimetype;
|
||||
nfstime3 sa_mtime;
|
||||
};
|
||||
|
||||
struct nfs_statfs {
|
||||
union {
|
||||
struct {
|
||||
u_long nfsv2sf_tsize;
|
||||
u_long nfsv2sf_bsize;
|
||||
u_long nfsv2sf_blocks;
|
||||
u_long nfsv2sf_bfree;
|
||||
u_long nfsv2sf_bavail;
|
||||
} sf_nfsv2;
|
||||
struct {
|
||||
nfsuint64 nfsv3sf_tbytes;
|
||||
nfsuint64 nfsv3sf_fbytes;
|
||||
nfsuint64 nfsv3sf_abytes;
|
||||
nfsuint64 nfsv3sf_tfiles;
|
||||
nfsuint64 nfsv3sf_ffiles;
|
||||
nfsuint64 nfsv3sf_afiles;
|
||||
u_long nfsv3sf_invarsec;
|
||||
} sf_nfsv3;
|
||||
} sf_un;
|
||||
};
|
||||
|
||||
#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize
|
||||
#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize
|
||||
#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks
|
||||
#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree
|
||||
#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail
|
||||
#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes
|
||||
#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes
|
||||
#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes
|
||||
#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles
|
||||
#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles
|
||||
#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles
|
||||
#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec
|
||||
|
||||
struct nfsv3_fsinfo {
|
||||
u_long fs_rtmax;
|
||||
u_long fs_rtpref;
|
||||
u_long fs_rtmult;
|
||||
u_long fs_wtmax;
|
||||
u_long fs_wtpref;
|
||||
u_long fs_wtmult;
|
||||
u_long fs_dtpref;
|
||||
nfsuint64 fs_maxfilesize;
|
||||
nfstime3 fs_timedelta;
|
||||
u_long fs_properties;
|
||||
};
|
||||
|
||||
struct nfsv3_pathconf {
|
||||
u_long pc_linkmax;
|
||||
u_long pc_namemax;
|
||||
u_long pc_notrunc;
|
||||
u_long pc_chownrestricted;
|
||||
u_long pc_caseinsensitive;
|
||||
u_long pc_casepreserving;
|
||||
};
|
||||
|
||||
#endif
|
103
sys/nfs/nfsrtt.h
Normal file
103
sys/nfs/nfsrtt.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsrtt.h 8.2 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_NFSRTT_H_
|
||||
#define _NFS_NFSRTT_H_
|
||||
|
||||
/*
|
||||
* Definitions for performance monitor.
|
||||
* The client and server logging are turned on by setting the global
|
||||
* constant "nfsrtton" to 1.
|
||||
*/
|
||||
#define NFSRTTLOGSIZ 128
|
||||
|
||||
/*
|
||||
* Circular log of client side rpc activity. Each log entry is for one
|
||||
* rpc filled in upon completion. (ie. in order of completion)
|
||||
* The "pos" is the table index for the "next" entry, therefore the
|
||||
* list goes from nfsrtt.rttl[pos] --> nfsrtt.rttl[pos - 1] in
|
||||
* chronological order of completion.
|
||||
*/
|
||||
struct nfsrtt {
|
||||
int pos; /* Position in array for next entry */
|
||||
struct rttl {
|
||||
int proc; /* NFS procedure number */
|
||||
int rtt; /* Measured round trip time */
|
||||
int rto; /* Round Trip Timeout */
|
||||
int sent; /* # rpcs in progress */
|
||||
int cwnd; /* Send window */
|
||||
int srtt; /* Ave Round Trip Time */
|
||||
int sdrtt; /* Ave mean deviation of RTT */
|
||||
fsid_t fsid; /* Fsid for mount point */
|
||||
struct timeval tstamp; /* Timestamp of log entry */
|
||||
} rttl[NFSRTTLOGSIZ];
|
||||
};
|
||||
|
||||
/*
|
||||
* And definitions for server side performance monitor.
|
||||
* The log organization is the same as above except it is filled in at the
|
||||
* time the server sends the rpc reply.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bits for the flags field.
|
||||
*/
|
||||
#define DRT_NQNFS 0x01 /* Rpc used Nqnfs protocol */
|
||||
#define DRT_TCP 0x02 /* Client used TCP transport */
|
||||
#define DRT_CACHEREPLY 0x04 /* Reply was from recent request cache */
|
||||
#define DRT_CACHEDROP 0x08 /* Rpc request dropped, due to recent reply */
|
||||
#define DRT_NFSV3 0x10 /* Rpc used NFS Version 3 */
|
||||
|
||||
/*
|
||||
* Server log structure
|
||||
* NB: ipadr == INADDR_ANY indicates a client using a non IP protocol.
|
||||
* (ISO perhaps?)
|
||||
*/
|
||||
struct nfsdrt {
|
||||
int pos; /* Position of next log entry */
|
||||
struct drt {
|
||||
int flag; /* Bits as defined above */
|
||||
int proc; /* NFS procedure number */
|
||||
u_long ipadr; /* IP address of client */
|
||||
int resptime; /* Response time (usec) */
|
||||
struct timeval tstamp; /* Timestamp of log entry */
|
||||
} drt[NFSRTTLOGSIZ];
|
||||
};
|
||||
|
||||
#endif
|
88
sys/nfs/nfsrvcache.h
Normal file
88
sys/nfs/nfsrvcache.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nfsrvcache.h 8.3 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_NFSRVCACHE_H_
|
||||
#define _NFS_NFSRVCACHE_H_
|
||||
|
||||
/*
|
||||
* Definitions for the server recent request cache
|
||||
*/
|
||||
|
||||
#define NFSRVCACHESIZ 64
|
||||
|
||||
struct nfsrvcache {
|
||||
TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */
|
||||
LIST_ENTRY(nfsrvcache) rc_hash; /* Hash chain */
|
||||
u_long rc_xid; /* rpc id number */
|
||||
union {
|
||||
struct mbuf *ru_repmb; /* Reply mbuf list OR */
|
||||
int ru_repstat; /* Reply status */
|
||||
} rc_un;
|
||||
union nethostaddr rc_haddr; /* Host address */
|
||||
short rc_proc; /* rpc proc number */
|
||||
u_char rc_state; /* Current state of request */
|
||||
u_char rc_flag; /* Flag bits */
|
||||
};
|
||||
|
||||
#define rc_reply rc_un.ru_repmb
|
||||
#define rc_status rc_un.ru_repstat
|
||||
#define rc_inetaddr rc_haddr.had_inetaddr
|
||||
#define rc_nam rc_haddr.had_nam
|
||||
|
||||
/* Cache entry states */
|
||||
#define RC_UNUSED 0
|
||||
#define RC_INPROG 1
|
||||
#define RC_DONE 2
|
||||
|
||||
/* Return values */
|
||||
#define RC_DROPIT 0
|
||||
#define RC_REPLY 1
|
||||
#define RC_DOIT 2
|
||||
#define RC_CHECKIT 3
|
||||
|
||||
/* Flag bits */
|
||||
#define RC_LOCKED 0x01
|
||||
#define RC_WANTED 0x02
|
||||
#define RC_REPSTATUS 0x04
|
||||
#define RC_REPMBUF 0x08
|
||||
#define RC_NQNFS 0x10
|
||||
#define RC_INETADDR 0x20
|
||||
#define RC_NAM 0x40
|
||||
|
||||
#endif
|
213
sys/nfs/nqnfs.h
Normal file
213
sys/nfs/nqnfs.h
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)nqnfs.h 8.3 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_NQNFS_H_
|
||||
#define _NFS_NQNFS_H_
|
||||
|
||||
/*
|
||||
* Definitions for NQNFS (Not Quite NFS) cache consistency protocol.
|
||||
*/
|
||||
|
||||
/* Tunable constants */
|
||||
#define NQ_CLOCKSKEW 3 /* Clock skew factor (sec) */
|
||||
#define NQ_WRITESLACK 5 /* Delay for write cache flushing */
|
||||
#define NQ_MAXLEASE 60 /* Max lease duration (sec) */
|
||||
#define NQ_MINLEASE 5 /* Min lease duration (sec) */
|
||||
#define NQ_DEFLEASE 30 /* Default lease duration (sec) */
|
||||
#define NQ_RENEWAL 3 /* Time before expiry (sec) to renew */
|
||||
#define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */
|
||||
#define NQ_MAXNUMLEASE 2048 /* Upper bound on number of server leases */
|
||||
#define NQ_DEADTHRESH NQ_NEVERDEAD /* Default nm_deadthresh */
|
||||
#define NQ_NEVERDEAD 9 /* Greater than max. nm_timeouts */
|
||||
#define NQLCHSZ 256 /* Server hash table size */
|
||||
|
||||
#define NQNFS_PROG 300105 /* As assigned by Sun */
|
||||
#define NQNFS_VER3 3
|
||||
#define NQNFS_EVICTSIZ 156 /* Size of eviction request in bytes */
|
||||
|
||||
/*
|
||||
* Definitions used for saving the "last lease expires" time in Non-volatile
|
||||
* RAM on the server. The default definitions below assume that NOVRAM is not
|
||||
* available.
|
||||
*/
|
||||
#ifdef HASNVRAM
|
||||
# undef HASNVRAM
|
||||
#endif
|
||||
#define NQSTORENOVRAM(t)
|
||||
#define NQLOADNOVRAM(t)
|
||||
|
||||
/*
|
||||
* Defn and structs used on the server to maintain state for current leases.
|
||||
* The list of host(s) that hold the lease are kept as nqhost structures.
|
||||
* The first one lives in nqlease and any others are held in a linked
|
||||
* list of nqm structures hanging off of nqlease.
|
||||
*
|
||||
* Each nqlease structure is chained into two lists. The first is a list
|
||||
* ordered by increasing expiry time for nqsrv_timer() and the second is a chain
|
||||
* hashed on lc_fh.
|
||||
*/
|
||||
#define LC_MOREHOSTSIZ 10
|
||||
|
||||
struct nqhost {
|
||||
union {
|
||||
struct {
|
||||
u_short udp_flag;
|
||||
u_short udp_port;
|
||||
union nethostaddr udp_haddr;
|
||||
} un_udp;
|
||||
struct {
|
||||
u_short connless_flag;
|
||||
u_short connless_spare;
|
||||
union nethostaddr connless_haddr;
|
||||
} un_connless;
|
||||
struct {
|
||||
u_short conn_flag;
|
||||
u_short conn_spare;
|
||||
struct nfssvc_sock *conn_slp;
|
||||
} un_conn;
|
||||
} lph_un;
|
||||
};
|
||||
#define lph_flag lph_un.un_udp.udp_flag
|
||||
#define lph_port lph_un.un_udp.udp_port
|
||||
#define lph_haddr lph_un.un_udp.udp_haddr
|
||||
#define lph_inetaddr lph_un.un_udp.udp_haddr.had_inetaddr
|
||||
#define lph_claddr lph_un.un_connless.connless_haddr
|
||||
#define lph_nam lph_un.un_connless.connless_haddr.had_nam
|
||||
#define lph_slp lph_un.un_conn.conn_slp
|
||||
|
||||
struct nqlease {
|
||||
LIST_ENTRY(nqlease) lc_hash; /* Fhandle hash list */
|
||||
CIRCLEQ_ENTRY(nqlease) lc_timer; /* Timer queue list */
|
||||
time_t lc_expiry; /* Expiry time (sec) */
|
||||
struct nqhost lc_host; /* Host that got lease */
|
||||
struct nqm *lc_morehosts; /* Other hosts that share read lease */
|
||||
fsid_t lc_fsid; /* Fhandle */
|
||||
char lc_fiddata[MAXFIDSZ];
|
||||
struct vnode *lc_vp; /* Soft reference to associated vnode */
|
||||
};
|
||||
#define lc_flag lc_host.lph_un.un_udp.udp_flag
|
||||
|
||||
/* lc_flag bits */
|
||||
#define LC_VALID 0x0001 /* Host address valid */
|
||||
#define LC_WRITE 0x0002 /* Write cache */
|
||||
#define LC_NONCACHABLE 0x0004 /* Non-cachable lease */
|
||||
#define LC_LOCKED 0x0008 /* Locked */
|
||||
#define LC_WANTED 0x0010 /* Lock wanted */
|
||||
#define LC_EXPIREDWANTED 0x0020 /* Want lease when expired */
|
||||
#define LC_UDP 0x0040 /* Host address for udp socket */
|
||||
#define LC_CLTP 0x0080 /* Host address for other connectionless */
|
||||
#define LC_LOCAL 0x0100 /* Host is server */
|
||||
#define LC_VACATED 0x0200 /* Host has vacated lease */
|
||||
#define LC_WRITTEN 0x0400 /* Recently wrote to the leased file */
|
||||
#define LC_SREF 0x0800 /* Holds a nfssvc_sock reference */
|
||||
|
||||
struct nqm {
|
||||
struct nqm *lpm_next;
|
||||
struct nqhost lpm_hosts[LC_MOREHOSTSIZ];
|
||||
};
|
||||
|
||||
/*
|
||||
* Special value for slp for local server calls.
|
||||
*/
|
||||
#define NQLOCALSLP ((struct nfssvc_sock *) -1)
|
||||
|
||||
/*
|
||||
* Server side macros.
|
||||
*/
|
||||
#define nqsrv_getl(v, l) \
|
||||
(void) nqsrv_getlease((v), &nfsd->nd_duration, \
|
||||
((nfsd->nd_flag & ND_LEASE) ? (nfsd->nd_flag & ND_LEASE) : \
|
||||
((l) | ND_CHECK)), \
|
||||
slp, procp, nfsd->nd_nam, &cache, &frev, cred)
|
||||
|
||||
/*
|
||||
* Client side macros that check for a valid lease.
|
||||
*/
|
||||
#define NQNFS_CKINVALID(v, n, f) \
|
||||
((time.tv_sec > (n)->n_expiry && \
|
||||
VFSTONFS((v)->v_mount)->nm_timeouts < VFSTONFS((v)->v_mount)->nm_deadthresh) \
|
||||
|| ((f) == ND_WRITE && ((n)->n_flag & NQNFSWRITE) == 0))
|
||||
|
||||
#define NQNFS_CKCACHABLE(v, f) \
|
||||
((time.tv_sec <= VTONFS(v)->n_expiry || \
|
||||
VFSTONFS((v)->v_mount)->nm_timeouts >= VFSTONFS((v)->v_mount)->nm_deadthresh) \
|
||||
&& (VTONFS(v)->n_flag & NQNFSNONCACHE) == 0 && \
|
||||
((f) == ND_READ || (VTONFS(v)->n_flag & NQNFSWRITE)))
|
||||
|
||||
#define NQNFS_NEEDLEASE(v, p) \
|
||||
(time.tv_sec > VTONFS(v)->n_expiry ? \
|
||||
((VTONFS(v)->n_flag & NQNFSEVICTED) ? 0 : nqnfs_piggy[p]) : \
|
||||
(((time.tv_sec + NQ_RENEWAL) > VTONFS(v)->n_expiry && \
|
||||
nqnfs_piggy[p]) ? \
|
||||
((VTONFS(v)->n_flag & NQNFSWRITE) ? \
|
||||
ND_WRITE : nqnfs_piggy[p]) : 0))
|
||||
|
||||
/*
|
||||
* List head for timer queue.
|
||||
*/
|
||||
CIRCLEQ_HEAD(, nqlease) nqtimerhead;
|
||||
|
||||
/*
|
||||
* List head for the file handle hash table.
|
||||
*/
|
||||
#define NQFHHASH(f) \
|
||||
(&nqfhhashtbl[(*((u_long *)(f))) & nqfhhash])
|
||||
LIST_HEAD(nqfhhashhead, nqlease) *nqfhhashtbl;
|
||||
u_long nqfhhash;
|
||||
|
||||
/*
|
||||
* Nqnfs return status numbers.
|
||||
*/
|
||||
#define NQNFS_EXPIRED 500
|
||||
#define NQNFS_TRYLATER 501
|
||||
|
||||
#ifdef KERNEL
|
||||
void nqnfs_lease_updatetime __P((int));
|
||||
int nqsrv_cmpnam __P((struct nfssvc_sock *,struct mbuf *,struct nqhost *));
|
||||
int nqsrv_getlease __P((struct vnode *, u_long *, int,
|
||||
struct nfssvc_sock *, struct proc *, struct mbuf *, int *,
|
||||
u_quad_t *, struct ucred *));
|
||||
int nqnfs_getlease __P((struct vnode *, int, struct ucred *,struct proc *));
|
||||
int nqnfs_callback __P((struct nfsmount *, struct mbuf *, struct mbuf *,
|
||||
caddr_t));
|
||||
int nqnfs_clientd __P((struct nfsmount *, struct ucred *,
|
||||
struct nfsd_cargs *, int, caddr_t, struct proc *));
|
||||
#endif
|
||||
|
||||
#endif
|
141
sys/nfs/rpcv2.h
Normal file
141
sys/nfs/rpcv2.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rpcv2.h 8.2 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_RPCV2_H_
|
||||
#define _NFS_RPCV2_H_
|
||||
|
||||
/*
|
||||
* Definitions for Sun RPC Version 2, from
|
||||
* "RPC: Remote Procedure Call Protocol Specification" RFC1057
|
||||
*/
|
||||
|
||||
/* Version # */
|
||||
#define RPC_VER2 2
|
||||
|
||||
/* Authentication */
|
||||
#define RPCAUTH_NULL 0
|
||||
#define RPCAUTH_UNIX 1
|
||||
#define RPCAUTH_SHORT 2
|
||||
#define RPCAUTH_KERB4 4
|
||||
#define RPCAUTH_NQNFS 300000
|
||||
#define RPCAUTH_MAXSIZ 400
|
||||
#define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */
|
||||
#define RPCAUTH_UNIXGIDS 16
|
||||
|
||||
/*
|
||||
* Constants associated with authentication flavours.
|
||||
*/
|
||||
#define RPCAKN_FULLNAME 0
|
||||
#define RPCAKN_NICKNAME 1
|
||||
|
||||
/* Rpc Constants */
|
||||
#define RPC_CALL 0
|
||||
#define RPC_REPLY 1
|
||||
#define RPC_MSGACCEPTED 0
|
||||
#define RPC_MSGDENIED 1
|
||||
#define RPC_PROGUNAVAIL 1
|
||||
#define RPC_PROGMISMATCH 2
|
||||
#define RPC_PROCUNAVAIL 3
|
||||
#define RPC_GARBAGE 4 /* I like this one */
|
||||
#define RPC_MISMATCH 0
|
||||
#define RPC_AUTHERR 1
|
||||
|
||||
/* Authentication failures */
|
||||
#define AUTH_BADCRED 1
|
||||
#define AUTH_REJECTCRED 2
|
||||
#define AUTH_BADVERF 3
|
||||
#define AUTH_REJECTVERF 4
|
||||
#define AUTH_TOOWEAK 5 /* Give em wheaties */
|
||||
|
||||
/* Sizes of rpc header parts */
|
||||
#define RPC_SIZ 24
|
||||
#define RPC_REPLYSIZ 28
|
||||
|
||||
/* RPC Prog definitions */
|
||||
#define RPCPROG_MNT 100005
|
||||
#define RPCMNT_VER1 1
|
||||
#define RPCMNT_MOUNT 1
|
||||
#define RPCMNT_DUMP 2
|
||||
#define RPCMNT_UMOUNT 3
|
||||
#define RPCMNT_UMNTALL 4
|
||||
#define RPCMNT_EXPORT 5
|
||||
#define RPCMNT_NAMELEN 255
|
||||
#define RPCMNT_PATHLEN 1024
|
||||
#define RPCPROG_NFS 100003
|
||||
|
||||
/*
|
||||
* Structures used for RPCAUTH_KERB4.
|
||||
*/
|
||||
struct nfsrpc_fullverf {
|
||||
u_long t1;
|
||||
u_long t2;
|
||||
u_long w2;
|
||||
};
|
||||
|
||||
struct nfsrpc_fullblock {
|
||||
u_long t1;
|
||||
u_long t2;
|
||||
u_long w1;
|
||||
u_long w2;
|
||||
};
|
||||
|
||||
struct nfsrpc_nickverf {
|
||||
u_long kind;
|
||||
struct nfsrpc_fullverf verf;
|
||||
};
|
||||
|
||||
/*
|
||||
* and their sizes in bytes.. If sizeof (struct nfsrpc_xx) != these
|
||||
* constants, well then things will break in mount_nfs and nfsd.
|
||||
*/
|
||||
#define RPCX_FULLVERF 12
|
||||
#define RPCX_FULLBLOCK 16
|
||||
#define RPCX_NICKVERF 16
|
||||
|
||||
#ifdef NFSKERB
|
||||
XXX
|
||||
#else
|
||||
typedef u_char NFSKERBKEY_T[2];
|
||||
typedef u_char NFSKERBKEYSCHED_T[2];
|
||||
#endif
|
||||
#define NFS_KERBSRV "rcmd" /* Kerberos Service for NFS */
|
||||
#define NFS_KERBTTL (30 * 60) /* Credential ttl (sec) */
|
||||
#define NFS_KERBCLOCKSKEW (5 * 60) /* Clock skew (sec) */
|
||||
#define NFS_KERBW1(t) (*((u_long *)(&((t).dat[((t).length + 3) & ~0x3]))))
|
||||
#endif
|
90
sys/nfs/xdr_subs.h
Normal file
90
sys/nfs/xdr_subs.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Macklem at The University of Guelph.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)xdr_subs.h 8.3 (Berkeley) 3/30/95
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NFS_XDR_SUBS_H_
|
||||
#define _NFS_XDR_SUBS_H_
|
||||
|
||||
/*
|
||||
* Macros used for conversion to/from xdr representation by nfs...
|
||||
* These use the MACHINE DEPENDENT routines ntohl, htonl
|
||||
* As defined by "XDR: External Data Representation Standard" RFC1014
|
||||
*
|
||||
* To simplify the implementation, we use ntohl/htonl even on big-endian
|
||||
* machines, and count on them being `#define'd away. Some of these
|
||||
* might be slightly more efficient as quad_t copies on a big-endian,
|
||||
* but we cannot count on their alignment anyway.
|
||||
*/
|
||||
|
||||
#define fxdr_unsigned(t, v) ((t)ntohl((long)(v)))
|
||||
#define txdr_unsigned(v) (htonl((long)(v)))
|
||||
|
||||
#define fxdr_nfsv2time(f, t) { \
|
||||
(t)->ts_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \
|
||||
if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \
|
||||
(t)->ts_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \
|
||||
else \
|
||||
(t)->ts_nsec = 0; \
|
||||
}
|
||||
#define txdr_nfsv2time(f, t) { \
|
||||
((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->ts_sec); \
|
||||
if ((f)->ts_nsec != -1) \
|
||||
((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->ts_nsec / 1000); \
|
||||
else \
|
||||
((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \
|
||||
}
|
||||
|
||||
#define fxdr_nfsv3time(f, t) { \
|
||||
(t)->ts_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \
|
||||
(t)->ts_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \
|
||||
}
|
||||
#define txdr_nfsv3time(f, t) { \
|
||||
((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->ts_sec); \
|
||||
((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->ts_nsec); \
|
||||
}
|
||||
|
||||
#define fxdr_hyper(f, t) { \
|
||||
((long *)(t))[_QUAD_HIGHWORD] = ntohl(((long *)(f))[0]); \
|
||||
((long *)(t))[_QUAD_LOWWORD] = ntohl(((long *)(f))[1]); \
|
||||
}
|
||||
#define txdr_hyper(f, t) { \
|
||||
((long *)(t))[0] = htonl(((long *)(f))[_QUAD_HIGHWORD]); \
|
||||
((long *)(t))[1] = htonl(((long *)(f))[_QUAD_LOWWORD]); \
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user