University of Michigan's Citi NFSv4 kernel client code.

Submitted by: Jim Rees <rees@umich.edu>
This commit is contained in:
Alfred Perlstein 2003-11-14 20:54:10 +00:00
parent db049820e1
commit 1bf8720450
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=122698
37 changed files with 11249 additions and 22 deletions

View File

@ -1562,6 +1562,15 @@ nfsclient/nfs_nfsiod.c optional nfsclient
nfsclient/nfs_vfsops.c optional nfsclient
nfsclient/nfs_vnops.c optional nfsclient
nfsclient/nfs_lock.c optional nfsclient
nfs4client/nfs4_socket.c optional nfsclient
nfs4client/nfs4_vfsops.c optional nfsclient
nfs4client/nfs4_vnops.c optional nfsclient
nfs4client/nfs4_subs.c optional nfsclient
nfs4client/nfs4_vfs_subs.c optional nfsclient
nfs4client/nfs4_vn_subs.c optional nfsclient
nfs4client/nfs4_dev.c optional nfsclient
nfs4client/nfs4_idmap.c optional nfsclient
rpc/rpcclnt.c optional nfsclient
nfsserver/nfs_serv.c optional nfsserver
nfsserver/nfs_srvsock.c optional nfsserver
nfsserver/nfs_srvcache.c optional nfsserver

View File

@ -55,17 +55,19 @@
#define NFS_PROG 100003
#define NFS_VER2 2
#define NFS_VER3 3
#define NFS_VER4 4
#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_MAXPKTHDR 404 /* XXXv4 this needs to be adjust for v4 */
#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) */
/* Stat numbers for rpc returns (version 2, 3 and 4) */
#define NFS_OK 0
#define NFSERR_PERM 1
#define NFSERR_NOENT 2
@ -88,7 +90,7 @@
#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_BADHANDLE 10001 /* The rest Version 3, 4 only */
#define NFSERR_NOT_SYNC 10002
#define NFSERR_BAD_COOKIE 10003
#define NFSERR_NOTSUPP 10004
@ -97,8 +99,48 @@
#define NFSERR_BADTYPE 10007
#define NFSERR_JUKEBOX 10008
#define NFSERR_TRYLATER NFSERR_JUKEBOX
#define NFSERR_SAME 10009 /* The rest Version 4 only */
#define NFSERR_DENIED 10010
#define NFSERR_EXPIRED 10011
#define NFSERR_LOCKED 10012
#define NFSERR_GRACE 10013
#define NFSERR_FHEXPIRED 10014
#define NFSERR_SHARDE_DENIED 10015
#define NFSERR_WRONGSEC 10016
#define NFSERR_CLID_INUSE 10017
#define NFSERR_RESOURCE 10018
#define NFSERR_MOVED 10019
#define NFSERR_NOFILEHANDLE 10020
#define NFSERR_MINOR_VERS_MISMATCH 10021
#define NFSERR_STALE_CLIENTID 10022
#define NFSERR_STALE_STATEID 10023
#define NFSERR_OLD_STATEID 10024
#define NFSERR_BAD_STATEID 10025
#define NFSERR_BAD_SEQID 10026
#define NFSERR_NOT_SAME 10027
#define NFSERR_LOCK_RANGE 10028
#define NFSERR_SYMLINK 10029
#define NFSERR_READDIR_NOSPC 10030
#define NFSERR_LEASE_MOVED 10031
#define NFSERR_ATTRNOTSUPP 10032
#define NFSERR_NO_GRACE 10033
#define NFSERR_RECLAIM_BAD 10034
#define NFSERR_RECLAIM_CONFLICT 10035
#define NFSERR_BADXDR 10036
#define NFSERR_LOCKS_HELD 10037
#define NFSERR_OPENMODE 10038
#define NFSERR_BADOWNER 10039
#define NFSERR_BADCHAR 10040
#define NFSERR_BADNAME 10041
#define NFSERR_BAD_RANGE 10042
#define NFSERR_LOCK_NOTSUPP 10043
#define NFSERR_OP_ILLEGAL 10044
#define NFSERR_DEADLOCK 10045
#define NFSERR_FILE_OPEN 10046
#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 */
@ -128,6 +170,11 @@
#define NFSX_V3FSINFO 48
#define NFSX_V3PATHCONF 24
/* specific to NFS Version 4 */
#define NFSX_V4VERF 8
#define NFSX_V4FH 128
#define NFSX_V4STATEID 16
/* variants for both versions */
#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
NFSX_V2FH)
@ -193,6 +240,48 @@
#define NFSV2PROC_READDIR 16
#define NFSV2PROC_STATFS 17
/* Version 4 procedure numbers */
#define NFSV4PROC_NULL 0
#define NFSV4PROC_COMPOUND 1
/* Version 4 operation numbers */
#define NFSV4OP_ACCESS 3
#define NFSV4OP_CLOSE 4
#define NFSV4OP_COMMIT 5
#define NFSV4OP_CREATE 6
#define NFSV4OP_DELEGPURGE 7
#define NFSV4OP_DELEGRETURN 8
#define NFSV4OP_GETATTR 9
#define NFSV4OP_GETFH 10
#define NFSV4OP_LINK 11
#define NFSV4OP_LOCK 12
#define NFSV4OP_LOCKT 13
#define NFSV4OP_LOCKU 14
#define NFSV4OP_LOOKUP 15
#define NFSV4OP_LOOKUPP 16
#define NFSV4OP_NVERIFY 17
#define NFSV4OP_OPEN 18
#define NFSV4OP_OPENATTR 19
#define NFSV4OP_OPEN_CONFIRM 20
#define NFSV4OP_OPEN_DOWNGRADE 21
#define NFSV4OP_PUTFH 22
#define NFSV4OP_PUTPUBFH 23
#define NFSV4OP_PUTROOTFH 24
#define NFSV4OP_READ 25
#define NFSV4OP_READDIR 26
#define NFSV4OP_READLINK 27
#define NFSV4OP_REMOVE 28
#define NFSV4OP_RENAME 29
#define NFSV4OP_RENEW 30
#define NFSV4OP_RESTOREFH 31
#define NFSV4OP_SAVEFH 32
#define NFSV4OP_SECINFO 33
#define NFSV4OP_SETATTR 34
#define NFSV4OP_SETCLIENTID 35
#define NFSV4OP_SETCLIENTID_CONFIRM 36
#define NFSV4OP_VERIFY 37
#define NFSV4OP_WRITE 38
/*
* Constants used by the Version 3 protocol for various RPCs
*/
@ -220,11 +309,65 @@
#define NFSV3FSINFO_HOMOGENEOUS 0x08
#define NFSV3FSINFO_CANSETTIME 0x10
/*
* Constants used by the Version 4 protocol for various RPCs
*/
#define NFSV4ACCESS_READ 0x01
#define NFSV4ACCESS_LOOKUP 0x02
#define NFSV4ACCESS_MODIFY 0x04
#define NFSV4ACCESS_EXTEND 0x08
#define NFSV4ACCESS_DELETE 0x10
#define NFSV4ACCESS_EXECUTE 0x20
#define NFSV4OPENRES_MLOCK 0x01
#define NFSV4OPENRES_CONFIRM 0x02
#define NFSV4OPENSHARE_ACCESS_READ 0x01
#define NFSV4OPENSHARE_ACCESS_WRITE 0x02
#define NFSV4OPENSHARE_ACCESS_BOTH 0x03
#define NFSV4OPENSHARE_DENY_NONE 0x00
#define NFSV4OPENSHARE_DENY_READ 0x01
#define NFSV4OPENSHARE_DENY_WRITE 0x02
#define NFSV4OPENSHARE_DENY_BOTH 0x03
/* File types */
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
NFSOCK=6, NFFIFO=7 } nfstype;
typedef enum {
NFNON=0,
NFREG=1,
NFDIR=2,
NFBLK=3,
NFCHR=4,
NFLNK=5,
NFSOCK=6,
NFFIFO=7,
NFATTRDIR = 8,
NFNAMEDATTR = 9,
NFBAD = 10,
} nfstype;
/* NFSv4 claim type */
typedef enum {
NCLNULL = 0,
NCLPREV = 1,
NCLDELEGCUR = 2,
NCLDELEGPREV = 3,
} nfsv4cltype;
/* Other NFSv4 types */
typedef enum {
NSHUNSTABLE = 0,
NSHDATASYNC = 1,
NSHFILESYNC = 2,
} nfsv4stablehow;
typedef enum { OTNOCREATE = 0, OTCREATE = 1 } nfsv4opentype;
typedef enum { CMUNCHECKED = 0, CMGUARDED = 1, CMEXCLUSIVE = 2 } nfsv4createmode;
typedef enum { THSERVERTIME = 0, THCLIENTTIME = 1 } nfsv4timehow;
typedef enum { ODNONE = 0, ODREAD = 1, ODWRITE = 2 } nfsv4opendelegtype;
/* 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
@ -233,7 +376,7 @@ typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
* NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4.
*/
#ifndef NFS_SMALLFH
#define NFS_SMALLFH 64
#define NFS_SMALLFH 128
#endif
union nfsfh {
fhandle_t fh_generic;
@ -280,6 +423,22 @@ struct nfsv3_spec {
};
typedef struct nfsv3_spec nfsv3spec;
/*
* NFS Version 4 bitmap.
*/
struct nfsv4_bitmap {
uint32_t bmlen;
uint32_t *bmval;
};
typedef struct nfsv4_bitmap nfsv4bitmap;
struct nfsv4_changeinfo {
u_int ciatomic;
uint64_t cibefore;
uint64_t ciafter;
};
typedef struct nfsv4_changeinfo nfsv4changeinfo;
/*
* File attributes and setable attributes. These structures cover both
* NFS version 2 and the version 3 protocol. Note that the union is only
@ -339,6 +498,126 @@ struct nfs_fattr {
#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
struct nfsv4_fattr {
u_int fa4_valid;
nfstype fa4_type;
off_t fa4_size;
uint64_t fa4_fsid_major;
uint64_t fa4_fsid_minor;
uint64_t fa4_fileid;
mode_t fa4_mode;
nlink_t fa4_nlink;
uid_t fa4_uid;
gid_t fa4_gid;
uint32_t fa4_rdev_major;
uint32_t fa4_rdev_minor;
struct timespec fa4_atime;
struct timespec fa4_ctime;
struct timespec fa4_mtime;
uint64_t fa4_maxread;
uint64_t fa4_maxwrite;
uint64_t fa4_ffree;
uint64_t fa4_ftotal;
uint32_t fa4_maxname;
uint64_t fa4_savail;
uint64_t fa4_sfree;
uint64_t fa4_stotal;
uint64_t fa4_changeid;
uint32_t fa4_lease_time;
uint64_t fa4_maxfilesize;
};
/* Flags for fa4_valid */
#define FA4V_SIZE 0x00000001
#define FA4V_FSID 0x00000002
#define FA4V_FILEID 0x00000004
#define FA4V_MODE 0x00000008
#define FA4V_NLINK 0x00000010
#define FA4V_UID 0x00000020
#define FA4V_GID 0x00000040
#define FA4V_RDEV 0x00000080
#define FA4V_ATIME 0x00000100
#define FA4V_CTIME 0x00000200
#define FA4V_MTIME 0x00000400
#define FA4V_MAXREAD 0x00000800
#define FA4V_MAXWRITE 0x00001000
#define FA4V_TYPE 0x00002000
#define FA4V_FFREE 0x00004000
#define FA4V_FTOTAL 0x00008000
#define FA4V_MAXNAME 0x00010000
#define FA4V_SAVAIL 0x00020000
#define FA4V_SFREE 0x00040000
#define FA4V_STOTAL 0x00080000
#define FA4V_CHANGEID 0x00100000
#define FA4V_LEASE_TIME 0x00200000
#define FA4V_MAXFILESIZE 0x00400000
#define FA4V_ACL 0x00800000
/* Offsets into bitmask */
#define FA4_SUPPORTED_ATTRS 0
#define FA4_TYPE 1
#define FA4_FH_EXPIRE_TYPE 2
#define FA4_CHANGE 3
#define FA4_SIZE 4
#define FA4_LINK_SUPPORT 5
#define FA4_SYMLINK_SUPPORT 6
#define FA4_NAMED_ATTR 7
#define FA4_FSID 8
#define FA4_UNIQUE_HANDLES 9
#define FA4_LEASE_TIME 10
#define FA4_RDATTR_ERROR 11
#define FA4_ACL 12
#define FA4_ACLSUPPORT 13
#define FA4_ARCHIVE 14
#define FA4_CANSETTIME 15
#define FA4_CASE_INSENSITIVE 16
#define FA4_CASE_PRESERVING 17
#define FA4_CHOWN_RESTRICTED 18
#define FA4_FILEHANDLE 19
#define FA4_FILEID 20
#define FA4_FILES_AVAIL 21
#define FA4_FILES_FREE 22
#define FA4_FILES_TOTAL 23
#define FA4_FS_LOCATIONS 24
#define FA4_HIDDEN 25
#define FA4_HOMOGENEOUS 26
#define FA4_MAXFILESIZE 27
#define FA4_MAXLINK 28
#define FA4_MAXNAME 29
#define FA4_MAXREAD 30
#define FA4_MAXWRITE 31
#define FA4_MIMETYPE 32
#define FA4_MODE 33
#define FA4_NO_TRUNC 34
#define FA4_NUMLINKS 35
#define FA4_OWNER 36
#define FA4_OWNER_GROUP 37
#define FA4_QUOTA_HARD 38
#define FA4_QUOTA_SOFT 39
#define FA4_QUOTA_USED 40
#define FA4_RAWDEV 41
#define FA4_SPACE_AVAIL 42
#define FA4_SPACE_FREE 43
#define FA4_SPACE_TOTAL 44
#define FA4_SPACE_USED 45
#define FA4_SYSTEM 46
#define FA4_TIME_ACCESS 47
#define FA4_TIME_ACCESS_SET 48
#define FA4_TIME_BACKUP 49
#define FA4_TIME_CREATE 50
#define FA4_TIME_DELTA 51
#define FA4_TIME_METADATA 52
#define FA4_TIME_MODIFY 53
#define FA4_TIME_MODIFY_SET 54
#define FA4_ATTR_MAX 55
/* Macros for v4 fattr manipulation */
#define FA4_SET(n, p) ((p)[(n)/32] |= (1 << ((n) % 32)))
#define FA4_CLR(n, p) ((p)[(n)/32] &= ~(1 << ((n) % 32)))
#define FA4_ISSET(n, p) ((p)[(n)/32] & (1 << ((n) % 32)))
#define FA4_ZERO(p) bzero((p), 8)
#define FA4_SKIP(p) ((p) += 2)
struct nfsv2_sattr {
u_int32_t sa_mode;
u_int32_t sa_uid;

View File

@ -53,6 +53,7 @@
#define RPCAUTH_NULL 0
#define RPCAUTH_UNIX 1
#define RPCAUTH_SHORT 2
#define RPCAUTH_KERB4 4
#define RPCAUTH_MAXSIZ 400
#define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */
#define RPCAUTH_UNIXGIDS 16
@ -63,19 +64,28 @@
#define RPCAKN_FULLNAME 0
#define RPCAKN_NICKNAME 1
/* Rpc Constants */
/* msg type */
#define RPC_CALL 0
#define RPC_REPLY 1
/* reply status */
#define RPC_MSGACCEPTED 0
#define RPC_MSGDENIED 1
/* accepted status */
#define RPC_SUCCESS 0
#define RPC_PROGUNAVAIL 1
#define RPC_PROGMISMATCH 2
#define RPC_PROCUNAVAIL 3
#define RPC_GARBAGE 4 /* I like this one */
#define RPC_SYSTEMERR 5
/* rejected status */
#define RPC_MISMATCH 0
#define RPC_AUTHERR 1
/* Authentication failures */
#define AUTH_OK 0
#define AUTH_BADCRED 1
#define AUTH_REJECTCRED 2
#define AUTH_BADVERF 3

260
sys/nfs4client/nfs4.h Normal file
View File

@ -0,0 +1,260 @@
/* $FreeBSD$ */
/* $Id: nfs4.h,v 1.25 2003/11/05 14:58:58 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#ifndef _NFS4CLIENT_NFS4_H
#define _NFS4CLIENT_NFS4_H
#define NFS4_USE_RPCCLNT
#define NFS4_MINOR_VERSION 0
#define NFS_PORT 2049
#define NFS4_DEF_FILE_IO_BUFFER_SIZE 4096
#define NFS4_MAX_FILE_IO_BUFFER_SIZE 32768
#define NFS4_DEF_MAXFILESIZE 0xffffffff
#define NFS4_SUPER_MAGIC 0xF00BA4
#define NFS4FS_SILLY_RENAME 1
#define NFS4FS_STRICT_LOCKING 1
#define NFS4FS_RETRY_OLD_STATEID 1
#define NFS4FS_MIN_LEASE (1 * hz)
#define NFS4FS_DEFAULT_LEASE (30 * hz)
#define NFS4FS_MAX_LEASE (120 * hz)
#define NFS4FS_RETRY_MIN_DELAY (hz >> 4)
#define NFS4FS_RETRY_MAX_DELAY (hz << 3)
#define NFS4FS_SEMAPHORE_DELAY (hz >> 4)
#define NFS4FS_GRACE_DELAY (hz * 5)
#define NFS4FS_OLD_STATEID_DELAY (hz >> 3)
#define NFS4FS_OP_MAX 10
#define NFS4_BUFSIZE 8192
#define NFS4FS_MAX_IOV 10
#define NFS4_SETCLIENTID_MAXTRIES 5
#define NFS4_READDIR_MAXTRIES 5
#define NFS4_MAXIO 4
#define NFS4_MAX_REQUEST_SOFT 192
#define NFS4_MAX_REQUEST_HARD 256
#define NFS4_MAXCOMMIT 64
#define NFS4_READ_DELAY (2 * HZ)
#define NFS4_WRITEBACK_DELAY (5 * HZ)
#define NFS4_WRITEBACK_LOCKDELAY (60 * HZ)
#define NFS4_COMMIT_DELAY (5 * HZ)
#define RPC_SLACK_SPACE 512
struct nfs4_compound {
char *tag;
int req_nops;
uint32_t *req_nopsp;
uint32_t *req_seqidp;
uint32_t *req_stateidp[NFS4_MAXIO];
uint32_t req_nstateid;
u_int seqidused;
int rep_status;
int rep_nops;
struct nfs4_fctx *fcp;
struct vnode *curvp;
struct vnode *savevp;
struct nfsmount *nmp;
};
struct nfs4_fdata {
struct nfsnode *fd_n;
pid_t fd_pid;
};
struct nfs4_oparg_putfh {
/* filled in by caller */
/* struct dentry *dentry;*/
/* filled in by setup routine */
/* nfs_opnum4 op;*/
uint32_t fh_len;
nfsfh_t fh_val;
int nlookups;
};
struct nfs4_oparg_getattr {
struct vnode *vp;
nfsv4bitmap *bm;
struct nfsv4_fattr fa;
};
struct nfs4_oparg_getfh {
uint32_t fh_len;
nfsfh_t fh_val;
struct vnode *vp;
};
struct nfs4_oparg_lookup {
const char *name;
uint32_t namelen;
struct vnode *vp;
};
struct nfs4_oparg_setclientid {
struct nfsmount *np;
uint32_t namelen;
char *name;
char *cb_netid;
uint32_t cb_netidlen;
char *cb_univaddr;
uint32_t cb_univaddrlen;
uint32_t cb_prog;
uint64_t clientid;
u_char verf[NFSX_V4VERF];
};
struct nfs4_oparg_access {
uint32_t mode;
uint32_t rmode;
uint32_t supported;
};
struct nfs4_oparg_open {
uint32_t flags;
uint32_t rflags;
nfsv4cltype ctype;
struct vattr *vap;
struct componentname *cnp;
struct nfs4_fctx *fcp;
char stateid[NFSX_V4STATEID];
};
struct nfs4_oparg_read {
uint64_t off;
uint32_t maxcnt;
uint32_t eof;
uint32_t retlen;
struct uio *uiop;
struct nfs4_fctx *fcp;
};
struct nfs4_oparg_write {
uint64_t off;
uint32_t stable;
uint32_t cnt;
uint32_t retlen;
uint32_t committed;
struct uio *uiop;
u_char wverf[NFSX_V4VERF];
struct nfs4_fctx *fcp;
};
struct nfs4_oparg_commit {
uint32_t len;
off_t start;
u_char verf[NFSX_V4VERF];
};
struct nfs4_oparg_readdir {
uint32_t cnt;
nfsv4bitmap *bm;
uint64_t cookie;
u_char verf[NFSX_V4VERF];
};
struct nfs4_oparg_create {
nfstype type;
char *linktext;
char *name;
uint32_t namelen;
struct vattr *vap;
};
struct nfs4_oparg_rename {
const char *fname;
uint32_t fnamelen;
const char *tname;
uint32_t tnamelen;
};
struct nfs4_oparg_link {
const char *name;
uint32_t namelen;
};
/*
* Lockowner
*/
struct nfs4_lowner {
uint32_t lo_cnt;
uint32_t lo_seqid;
uint32_t lo_id;
};
#define NFS4_SEQIDMUTATINGERROR(err) \
(((err) != NFSERR_STALE_CLIENTID) && \
((err) != NFSERR_BAD_SEQID) && \
((err) != NFSERR_STALE_STATEID) && \
((err) != NFSERR_BAD_STATEID))
/* Standard bitmasks */
extern nfsv4bitmap nfsv4_fsinfobm;
extern nfsv4bitmap nfsv4_fsattrbm;
extern nfsv4bitmap nfsv4_getattrbm;
extern nfsv4bitmap nfsv4_readdirbm;
vfs_init_t nfs4_init;
vfs_uninit_t nfs4_uninit;
uint32_t nfs_v4fileid4_to_fileid(uint64_t);
int nfs4_readrpc(struct vnode *, struct uio *, struct ucred *);
int nfs4_writerpc(struct vnode *, struct uio *, struct ucred *, int *,
int *);
int nfs4_commit(struct vnode *vp, u_quad_t offset, int cnt,
struct ucred *cred, struct thread *td);
int nfs4_readdirrpc(struct vnode *, struct uio *, struct ucred *);
int nfs4_readlinkrpc(struct vnode *, struct uio *, struct ucred *);
int nfs4_sigintr(struct nfsmount *, struct nfsreq *, struct thread *);
int nfs4_writebp(struct buf *, int, struct thread *);
int nfs4_request(struct vnode *, struct mbuf *, int, struct thread *,
struct ucred *, struct mbuf **, struct mbuf **, caddr_t *);
int nfs4_request_mnt(struct nfsmount *, struct mbuf *, int, struct thread *,
struct ucred *, struct mbuf **, struct mbuf **, caddr_t *);
int nfs4_connect(struct nfsmount *);
void nfs4_disconnect(struct nfsmount *);
void nfs4_safedisconnect(struct nfsmount *);
int nfs4_nmcancelreqs(struct nfsmount *);
void nfs_v4initcompound(struct nfs4_compound *);
int nfs_v4postop(struct nfs4_compound *, int);
int nfs_v4handlestatus(int, struct nfs4_compound *);
#endif /* _NFS4CLIENT_NFS4_H */

451
sys/nfs4client/nfs4_dev.c Normal file
View File

@ -0,0 +1,451 @@
/* $FreeBSD$ */
/* $Id: nfs4_dev.c,v 1.10 2003/11/05 14:58:59 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/queue.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/poll.h>
#include <sys/mutex.h>
#include <sys/stat.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/wait.h>
#include <sys/signalvar.h>
#include <nfs4client/nfs4_dev.h>
#ifdef NFS4DEVVERBOSE
#define NFS4DEV_DEBUG(X...) printf(X)
#else
#define NFS4DEV_DEBUG(X...)
#endif
#define NFS4DEV_NAME "nfs4"
#define CDEV_MAJOR 29 /* XXX where are these numbers assigned!?!? */
#define CDEV_MINOR 1
MALLOC_DEFINE(M_NFS4DEV, "NFS4 dev", "NFS4 device");
struct nfs4dev_upcall {
/* request msg */
struct nfs4dev_msg up_reqmsg;
size_t up_reqmsglen;
/* reply (payload only) */
caddr_t up_rep;
size_t * up_replen;
int up_copied; /* non-zero when reply has been copied to
'*up_rep' */
int up_error; /* non-zero if an error occured */
TAILQ_ENTRY(nfs4dev_upcall) up_entry;
};
#define nfs4dev_upcall_get(MP) MALLOC((MP), struct nfs4dev_upcall *, sizeof(struct nfs4dev_upcall), M_NFS4DEV, M_WAITOK | M_ZERO)
#define nfs4dev_upcall_put(MP) FREE((MP), M_NFS4DEV)
static int nfs4dev_nopen = 0;
static struct thread * nfs4dev_reader = NULL;
static dev_t nfs4device = 0;
static struct mtx nfs4dev_daemon_mtx;
static int nfs4dev_xid = 0;
/* queue of pending upcalls */
TAILQ_HEAD(, nfs4dev_upcall) nfs4dev_newq;
static struct mtx nfs4dev_newq_mtx;
/* queue of upcalls waiting for replys */
TAILQ_HEAD(, nfs4dev_upcall) nfs4dev_waitq;
static struct mtx nfs4dev_waitq_mtx;
/* dev hooks */
static d_open_t nfs4dev_open;
static d_close_t nfs4dev_close;
static d_ioctl_t nfs4dev_ioctl;
static d_poll_t nfs4dev_poll;
static struct cdevsw nfs4dev_cdevsw = {
.d_open = nfs4dev_open,
.d_close = nfs4dev_close,
.d_ioctl = nfs4dev_ioctl,
.d_poll = nfs4dev_poll,
.d_name = NFS4DEV_NAME,
.d_maj = CDEV_MAJOR
};
static int nfs4dev_reply(caddr_t);
static int nfs4dev_request(caddr_t);
/* Userland requests a new operation to service */
static int
nfs4dev_request(caddr_t addr)
{
struct nfs4dev_upcall * u;
struct nfs4dev_msg * m = (struct nfs4dev_msg *) addr;
mtx_lock(&nfs4dev_newq_mtx);
if (TAILQ_EMPTY(&nfs4dev_newq)) {
mtx_unlock(&nfs4dev_newq_mtx);
return EAGAIN;
}
u = TAILQ_FIRST(&nfs4dev_newq);
TAILQ_REMOVE(&nfs4dev_newq, u, up_entry);
mtx_unlock(&nfs4dev_newq_mtx);
bcopy(&u->up_reqmsg, m, sizeof(struct nfs4dev_msg));
mtx_lock(&nfs4dev_waitq_mtx);
TAILQ_INSERT_TAIL(&nfs4dev_waitq, u, up_entry);
mtx_unlock(&nfs4dev_waitq_mtx);
return 0;
}
static int
nfs4dev_reply(caddr_t addr)
{
struct nfs4dev_upcall * u;
struct nfs4dev_msg * m = (struct nfs4dev_msg *) addr;
int error;
if (m->msg_vers != NFS4DEV_VERSION) {
printf("nfs4dev version mismatch\n");
return EINVAL;
}
if (m->msg_type > NFS4DEV_MAX_TYPE) {
NFS4DEV_DEBUG("nfs4dev: unsupported message type\n");
return EINVAL;
}
if (m->msg_len == 0 || m->msg_len > NFS4DEV_MSG_MAX_DATALEN) {
NFS4DEV_DEBUG("bad message length\n");
return EINVAL;
}
/* match the reply with a request */
mtx_lock(&nfs4dev_waitq_mtx);
TAILQ_FOREACH(u, &nfs4dev_waitq, up_entry) {
if (m->msg_xid == u->up_reqmsg.msg_xid) {
if (m->msg_type == u->up_reqmsg.msg_type)
goto found;
NFS4DEV_DEBUG("nfs4dev: op type mismatch!\n");
break;
}
}
mtx_unlock(&nfs4dev_waitq_mtx);
NFS4DEV_DEBUG("nfs4dev msg op: %d xid: %x not found.\n",
m->msg_type, m->msg_xid);
error = EIO;
goto bad;
found:
TAILQ_REMOVE(&nfs4dev_waitq, u, up_entry);
mtx_unlock(&nfs4dev_waitq_mtx);
if (m->msg_error) {
error = m->msg_error;
goto bad;
}
if (m->msg_len > *u->up_replen) {
error = EFAULT;
goto bad;
}
bcopy(m->msg_data, u->up_rep, m->msg_len);
*u->up_replen = m->msg_len;
u->up_copied = m->msg_len;
wakeup(u);
return 0;
bad:
u->up_error = error;
wakeup(u);
return error;
}
void
nfs4dev_init(void)
{
nfs4dev_xid = arc4random();
TAILQ_INIT(&nfs4dev_newq);
TAILQ_INIT(&nfs4dev_waitq);
mtx_init(&nfs4dev_newq_mtx, "nfs4dev newq", NULL, MTX_DEF);
mtx_init(&nfs4dev_waitq_mtx, "nfs4dev waitq", NULL, MTX_DEF);
mtx_init(&nfs4dev_daemon_mtx, "nfs4dev state", NULL, MTX_DEF);
nfs4device = make_dev(&nfs4dev_cdevsw, CDEV_MINOR, (uid_t)0, (gid_t)0,
S_IRUSR | S_IWUSR, "nfs4");
}
void
nfs4dev_uninit(void)
{
struct proc * dead = NULL;
mtx_lock(&nfs4dev_daemon_mtx);
if (nfs4dev_nopen) {
if (nfs4dev_reader == NULL) {
NFS4DEV_DEBUG("nfs4dev uninit(): unregistered reader\n");
} else {
dead = nfs4dev_reader->td_proc;
}
}
mtx_unlock(&nfs4dev_daemon_mtx);
if (dead != NULL) {
NFS4DEV_DEBUG("nfs4dev_uninit(): you forgot to kill attached daemon (pid: %u)\n",
dead->p_pid);
PROC_LOCK(dead);
psignal(dead, SIGTERM);
PROC_UNLOCK(dead);
}
/* XXX moot? */
nfs4dev_purge();
mtx_destroy(&nfs4dev_newq_mtx);
mtx_destroy(&nfs4dev_waitq_mtx);
mtx_destroy(&nfs4dev_daemon_mtx);
destroy_dev(nfs4device);
}
/* device interface functions */
static int
nfs4dev_open(dev_t dev, int flags, int fmt, d_thread_t *td)
{
if (dev != nfs4device)
return ENODEV;
mtx_lock(&nfs4dev_daemon_mtx);
if (nfs4dev_nopen) {
mtx_unlock(&nfs4dev_daemon_mtx);
return EBUSY;
}
nfs4dev_nopen++;
nfs4dev_reader = curthread;
mtx_unlock(&nfs4dev_daemon_mtx);
return (0);
}
static int
nfs4dev_close(dev_t dev, int flags, int fmt, d_thread_t *td)
{
struct nfs4dev_upcall * u;
if (dev != nfs4device)
return ENODEV;
mtx_lock(&nfs4dev_daemon_mtx);
if (!nfs4dev_nopen) {
mtx_unlock(&nfs4dev_daemon_mtx);
return ENOENT;
}
nfs4dev_nopen--;
nfs4dev_reader = NULL;
mtx_unlock(&nfs4dev_daemon_mtx);
mtx_lock(&nfs4dev_waitq_mtx);
while (!TAILQ_EMPTY(&nfs4dev_waitq)) {
u = TAILQ_FIRST(&nfs4dev_waitq);
TAILQ_REMOVE(&nfs4dev_waitq, u, up_entry);
u->up_error = EINTR;
wakeup(u);
}
mtx_unlock(&nfs4dev_waitq_mtx);
return 0;
}
static int
nfs4dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
{
int error;
if (dev != nfs4device)
return ENODEV;
if (data == NULL)
return EFAULT;
if (nfs4dev_reader != curthread)
nfs4dev_reader = curthread;
switch (cmd) {
case NFS4DEVIOCGET:
error = nfs4dev_request(data);
break;
case NFS4DEVIOCPUT:
error = nfs4dev_reply(data);
break;
default:
NFS4DEV_DEBUG("nfs4dev_ioctl: unkown ioctl cmd %d\n", (int)cmd);
error = EOPNOTSUPP;
break;
}
return error;
}
static int
nfs4dev_poll(dev_t dev, int events, struct thread *td)
{
int revents;
if (dev != nfs4device)
return EINVAL;
mtx_lock(&nfs4dev_daemon_mtx);
if (nfs4dev_nopen == 0) {
mtx_unlock(&nfs4dev_daemon_mtx);
return 0;
}
mtx_unlock(&nfs4dev_daemon_mtx);
revents = 0;
/* check readable data */
mtx_lock(&nfs4dev_newq_mtx);
if (!TAILQ_EMPTY(&nfs4dev_newq))
revents |= POLLIN;
mtx_unlock(&nfs4dev_newq_mtx);
mtx_lock(&nfs4dev_waitq_mtx);
if (!TAILQ_EMPTY(&nfs4dev_waitq))
revents |= POLLOUT;
mtx_unlock(&nfs4dev_waitq_mtx);
return revents;
}
int
nfs4dev_call(uint32_t type, caddr_t req_data, size_t req_len, caddr_t rep_data, size_t * rep_lenp)
{
struct nfs4dev_upcall * u;
int error = 0;
unsigned int xtmp;
mtx_lock(&nfs4dev_daemon_mtx);
if (nfs4dev_nopen == 0) {
mtx_unlock(&nfs4dev_daemon_mtx);
return EINVAL;
}
mtx_unlock(&nfs4dev_daemon_mtx);
if (type > NFS4DEV_MAX_TYPE)
return EOPNOTSUPP;
NFS4DEV_DEBUG("upcall %d/%d:%d\n", type, req_len, *rep_lenp);
nfs4dev_upcall_get(u);
u->up_error = 0;
u->up_rep = rep_data;
u->up_replen = rep_lenp;
u->up_copied = 0;
u->up_reqmsg.msg_vers = NFS4DEV_VERSION;
/* XXX efficient copying */
bcopy(req_data, u->up_reqmsg.msg_data, req_len);
u->up_reqmsg.msg_len = req_len;
mtx_lock(&nfs4dev_newq_mtx);
/* get new XID */
while ((xtmp = arc4random() % 256) == 0);
nfs4dev_xid += xtmp;
u->up_reqmsg.msg_xid = nfs4dev_xid;
TAILQ_INSERT_TAIL(&nfs4dev_newq, u, up_entry);
mtx_unlock(&nfs4dev_newq_mtx);
NFS4DEV_DEBUG("nfs4dev op: %d xid: %x sleeping\n", u->up_reqmsg.msg_type, u->up_reqmsg.msg_xid);
do {
tsleep(u, PLOCK, "nfs4dev", 0);
} while (u->up_copied == 0 && u->up_error == 0);
/* upcall now removed from the queue */
NFS4DEV_DEBUG("nfs4dev prog: %d xid: %x continues...\n",
u->up_reqmsg.msg_type, u->up_reqmsg.msg_xid);
if (u->up_error) {
error = u->up_error;
NFS4DEV_DEBUG("nfs4dev prog: %d xid: %x error: %d\n",
u->up_reqmsg.msg_type, u->up_reqmsg.msg_xid, u->up_error);
goto out;
}
out:
nfs4dev_upcall_put(u);
return error;
}
void
nfs4dev_purge(void)
{
struct nfs4dev_upcall * u;
mtx_lock(&nfs4dev_newq_mtx);
while (!TAILQ_EMPTY(&nfs4dev_newq)) {
u = TAILQ_FIRST(&nfs4dev_newq);
TAILQ_REMOVE(&nfs4dev_newq, u, up_entry);
u->up_error = EINTR;
wakeup(u);
}
mtx_unlock(&nfs4dev_newq_mtx);
mtx_lock(&nfs4dev_waitq_mtx);
while (!TAILQ_EMPTY(&nfs4dev_waitq)) {
u = TAILQ_FIRST(&nfs4dev_waitq);
TAILQ_REMOVE(&nfs4dev_waitq, u, up_entry);
u->up_error = EINTR;
wakeup(u);
}
mtx_unlock(&nfs4dev_waitq_mtx);
}

65
sys/nfs4client/nfs4_dev.h Normal file
View File

@ -0,0 +1,65 @@
/* $FreeBSD$ */
/* $Id: nfs4_dev.h,v 1.3 2003/11/05 14:58:59 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#ifndef _NFS3_DEV_H_
#define _NFS4_DEV_H_
#include <sys/ioccom.h>
/* type of upcall */
#define NFS4DEV_TYPE_IDMAP 0
#define NFS4DEV_TYPE_GSS 1
#define NFS4DEV_MAX_TYPE 1
struct nfs4dev_msg {
unsigned int msg_vers;
unsigned int msg_type;
unsigned int msg_xid;
unsigned int msg_error;
#define NFS4DEV_MSG_MAX_DATALEN 350
size_t msg_len;
uint8_t msg_data[NFS4DEV_MSG_MAX_DATALEN];
};
#define NFS4DEV_VERSION (0x3 << 16 | sizeof(struct nfs4dev_msg))
/* ioctl commands */
#define NFS4DEVIOCGET _IOR('A', 0x200, struct nfs4dev_msg)
#define NFS4DEVIOCPUT _IOW('A', 0x201, struct nfs4dev_msg)
#ifdef _KERNEL
int nfs4dev_call(uint32_t type, caddr_t req_data, size_t req_len, caddr_t rep_datap, size_t * rep_lenp);
void nfs4dev_purge(void);
void nfs4dev_init(void);
void nfs4dev_uninit(void);
#endif
#endif /* _NFS4_DEV_H_ */

513
sys/nfs4client/nfs4_idmap.c Normal file
View File

@ -0,0 +1,513 @@
/* $FreeBSD$ */
/* $Id: nfs4_idmap.c,v 1.4 2003/11/05 14:58:59 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
/* TODO:
* o validate ascii
* */
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/lockmgr.h>
#include <sys/fnv_hash.h>
#include <sys/proc.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <sys/libkern.h>
#include <rpc/rpcclnt.h>
#include <nfs4client/nfs4_dev.h>
#include <nfs4client/nfs4_idmap.h>
#ifdef IDMAPVERBOSE
#define IDMAP_DEBUG(X...) printf(X);
#else
#define IDMAP_DEBUG(X...)
#endif
#define IDMAP_HASH_SIZE 37
MALLOC_DEFINE(M_IDMAP, "idmap", "idmap");
#define idmap_entry_get(ID) MALLOC((ID), struct idmap_entry, sizeof(struct idmap_entry), M_IDMAP, M_WAITOK | M_ZERO)
#define idmap_entry_put(ID) FREE((ID), M_IDMAP)
struct idmap_entry {
struct idmap_msg id_info;
TAILQ_ENTRY(idmap_entry) id_entry_id;
TAILQ_ENTRY(idmap_entry) id_entry_name;
};
struct idmap_hash {
TAILQ_HEAD(, idmap_entry) hash_name[IDMAP_HASH_SIZE];
TAILQ_HEAD(, idmap_entry) hash_id[IDMAP_HASH_SIZE];
struct lock hash_lock;
};
#define IDMAP_RLOCK(lock) lockmgr(lock, LK_SHARED, NULL, curthread)
#define IDMAP_WLOCK(lock) lockmgr(lock, LK_EXCLUSIVE, NULL, curthread)
#define IDMAP_UNLOCK(lock) lockmgr(lock, LK_RELEASE, NULL, curthread)
static struct idmap_hash idmap_uid_hash;
static struct idmap_hash idmap_gid_hash;
static struct idmap_entry * idmap_name_lookup(uint32_t, char *);
static struct idmap_entry * idmap_id_lookup(uint32_t, ident_t);
static int idmap_upcall_name(uint32_t, char *, struct idmap_entry **);
static int idmap_upcall_id(uint32_t , ident_t, struct idmap_entry ** );
static int idmap_add(struct idmap_entry *);
static int
idmap_upcall_name(uint32_t type, char * name, struct idmap_entry ** found)
{
int error;
struct idmap_entry * e;
size_t len, siz;
if (type > IDMAP_MAX_TYPE || type == 0) {
IDMAP_DEBUG("bad type %d\n", type);
return EINVAL; /* XXX */
}
if (name == NULL || (len = strlen(name)) == 0 || len > IDMAP_MAXNAMELEN) {
IDMAP_DEBUG("idmap_upcall_name: bad name\n");
return EFAULT; /* XXX */
}
MALLOC(e, struct idmap_entry *, sizeof(struct idmap_entry), M_IDMAP,
M_WAITOK | M_ZERO);
e->id_info.id_type = type;
bcopy(name, e->id_info.id_name, len);
e->id_info.id_namelen = len;
siz = sizeof(struct idmap_msg);
error = nfs4dev_call(NFS4DEV_TYPE_IDMAP, (caddr_t)&e->id_info, siz,
(caddr_t)&e->id_info, &siz);
if (error) {
IDMAP_DEBUG("error %d in nfs4dev_upcall()\n", error);
*found = NULL;
return error;
}
if (siz != sizeof(struct idmap_msg)) {
IDMAP_DEBUG("bad size of returned message\n");
*found = NULL;
return EFAULT;
}
*found = e;
return 0;
}
static int
idmap_upcall_id(uint32_t type, ident_t id, struct idmap_entry ** found)
{
int error;
struct idmap_entry * e;
size_t siz;
if (type > IDMAP_MAX_TYPE)
panic("bad type"); /* XXX */
MALLOC(e, struct idmap_entry *, sizeof(struct idmap_entry), M_IDMAP,
M_WAITOK | M_ZERO);
e->id_info.id_type = type;
e->id_info.id_namelen = 0; /* should already */
e->id_info.id_id = id;
siz = sizeof(struct idmap_msg);
error = nfs4dev_call(NFS4DEV_TYPE_IDMAP, (caddr_t)&e->id_info, siz,
(caddr_t)&e->id_info, &siz);
if (error) {
IDMAP_DEBUG("error %d in nfs4dev_upcall()\n", error);
*found = NULL;
return error;
}
if (siz != sizeof(struct idmap_msg)) {
IDMAP_DEBUG("bad size of returned message\n");
*found = NULL;
return EFAULT;
}
*found = e;
return 0;
}
static int
idmap_hashf(struct idmap_entry *e, uint32_t * hval_id, uint32_t * hval_name)
{
switch (e->id_info.id_type) {
case IDMAP_TYPE_UID:
*hval_id = e->id_info.id_id.uid % IDMAP_HASH_SIZE;
break;
case IDMAP_TYPE_GID:
*hval_id = e->id_info.id_id.gid % IDMAP_HASH_SIZE;
break;
default:
/* XXX yikes! */
panic("hashf: bad type!");
break;
}
if (e->id_info.id_namelen == 0)
/* XXX */ panic("hashf: bad name");
*hval_name = fnv_32_str(e->id_info.id_name, FNV1_32_INIT) % IDMAP_HASH_SIZE;
return 0;
}
static int
idmap_add(struct idmap_entry * e)
{
struct idmap_hash * hash;
uint32_t hval_id, hval_name;
if (e == NULL)
panic("idmap_add null");
if (e->id_info.id_namelen == 0)
panic("idmap_add name of len 0");
switch (e->id_info.id_type) {
case IDMAP_TYPE_UID:
hash = &idmap_uid_hash;
break;
case IDMAP_TYPE_GID:
hash = &idmap_gid_hash;
break;
default:
/* XXX yikes */
panic("idmap add: bad type!");
break;
}
if (idmap_hashf(e, &hval_id, &hval_name) != 0) {
IDMAP_DEBUG("idmap_hashf fails!\n");
return -1;
}
IDMAP_WLOCK(&hash->hash_lock);
TAILQ_INSERT_TAIL(&hash->hash_id[hval_id], e, id_entry_id);
TAILQ_INSERT_TAIL(&hash->hash_name[hval_name], e, id_entry_name);
IDMAP_UNLOCK(&hash->hash_lock);
return 0;
}
static struct idmap_entry *
idmap_id_lookup(uint32_t type, ident_t id)
{
struct idmap_hash * hash;
uint32_t hval;
struct idmap_entry * e;
switch (type) {
case IDMAP_TYPE_UID:
hash = &idmap_uid_hash;
hval = id.uid % IDMAP_HASH_SIZE;
break;
case IDMAP_TYPE_GID:
hash = &idmap_gid_hash;
hval = id.gid % IDMAP_HASH_SIZE;
break;
default:
/* XXX yikes */
panic("lookup: bad type!");
break;
}
IDMAP_RLOCK(&hash->hash_lock);
TAILQ_FOREACH(e, &hash->hash_id[hval], id_entry_name) {
if ((type == IDMAP_TYPE_UID && e->id_info.id_id.uid == id.uid)||
(type == IDMAP_TYPE_GID && e->id_info.id_id.gid == id.gid)) {
IDMAP_UNLOCK(&hash->hash_lock);
return e;
}
}
IDMAP_UNLOCK(&hash->hash_lock);
return NULL;
}
static struct idmap_entry *
idmap_name_lookup(uint32_t type, char * name)
{
struct idmap_hash * hash;
uint32_t hval;
struct idmap_entry * e;
size_t len;
switch (type) {
case IDMAP_TYPE_UID:
hash = &idmap_uid_hash;
break;
case IDMAP_TYPE_GID:
hash = &idmap_gid_hash;
break;
default:
/* XXX yikes */
panic("lookup: bad type!");
break;
}
len = strlen(name);
if (len == 0 || len > IDMAP_MAXNAMELEN) {
IDMAP_DEBUG("bad name length %d\n", len);
return NULL;
}
hval = fnv_32_str(name, FNV1_32_INIT) % IDMAP_HASH_SIZE;
IDMAP_RLOCK(&hash->hash_lock);
TAILQ_FOREACH(e, &hash->hash_name[hval], id_entry_name) {
if ((strlen(e->id_info.id_name) == strlen(name)) && strncmp(e->id_info.id_name, name, strlen(name)) == 0) {
IDMAP_UNLOCK(&hash->hash_lock);
return e;
}
}
IDMAP_UNLOCK(&hash->hash_lock);
return NULL;
}
void
idmap_init(void)
{
unsigned int i;
for (i=0; i<IDMAP_HASH_SIZE; i++) {
TAILQ_INIT(&idmap_uid_hash.hash_name[i]);
TAILQ_INIT(&idmap_uid_hash.hash_id[i]);
TAILQ_INIT(&idmap_gid_hash.hash_name[i]);
TAILQ_INIT(&idmap_gid_hash.hash_id[i]);
}
lockinit(&idmap_uid_hash.hash_lock, PLOCK, "idmap uid hash table", 0,0);
lockinit(&idmap_gid_hash.hash_lock, PLOCK, "idmap gid hash table", 0,0);
}
void idmap_uninit(void)
{
struct idmap_entry * e;
int i;
lockdestroy(&idmap_uid_hash.hash_lock);
lockdestroy(&idmap_gid_hash.hash_lock);
for (i=0; i<IDMAP_HASH_SIZE; i++) {
while(!TAILQ_EMPTY(&idmap_uid_hash.hash_name[i])) {
e = TAILQ_FIRST(&idmap_uid_hash.hash_name[i]);
TAILQ_REMOVE(&idmap_uid_hash.hash_name[i], e, id_entry_name);
TAILQ_REMOVE(&idmap_uid_hash.hash_id[i], e, id_entry_id);
FREE(e, M_IDMAP);
}
while(!TAILQ_EMPTY(&idmap_gid_hash.hash_name[i])) {
e = TAILQ_FIRST(&idmap_gid_hash.hash_name[i]);
TAILQ_REMOVE(&idmap_gid_hash.hash_name[i], e, id_entry_name);
TAILQ_REMOVE(&idmap_gid_hash.hash_id[i], e, id_entry_id);
FREE(e, M_IDMAP);
}
}
}
int
idmap_uid_to_name(uid_t uid, char ** name, size_t * len)
{
struct idmap_entry * e;
int error = 0;
ident_t id;
id.uid = uid;
if ((e = idmap_id_lookup(IDMAP_TYPE_UID, id)) == NULL) {
if ((error = idmap_upcall_id(IDMAP_TYPE_UID, id, &e)) != 0) {
IDMAP_DEBUG("error in upcall\n");
return error;
}
if (e == NULL) {
IDMAP_DEBUG("no error from upcall, but no data returned\n");
return EFAULT;
}
if (idmap_add(e) != 0) {
IDMAP_DEBUG("idmap_add failed\n");
FREE(e, M_IDMAP);
}
}
*name = e->id_info.id_name;
*len = e->id_info.id_namelen;
return 0;
}
int
idmap_gid_to_name(gid_t gid, char ** name, size_t * len)
{
struct idmap_entry * e;
int error = 0;
ident_t id;
id.gid = gid;
if ((e = idmap_id_lookup(IDMAP_TYPE_GID, id)) == NULL) {
if ((error = idmap_upcall_id(IDMAP_TYPE_GID, (ident_t)id, &e))) {
IDMAP_DEBUG("error in upcall\n");
return error;
}
if (e == NULL) {
IDMAP_DEBUG("no error from upcall, but no data returned\n");
return EFAULT;
}
if (idmap_add(e) != 0) {
IDMAP_DEBUG("idmap_add failed\n");
FREE(e, M_IDMAP);
}
}
*name = e->id_info.id_name;
*len = e->id_info.id_namelen;
return 0;
}
int
idmap_name_to_uid(char * name, size_t len, uid_t * id)
{
struct idmap_entry * e;
int error = 0;
char * namestr;
if (name == NULL )
return EFAULT;
if (len == 0 || len > IDMAP_MAXNAMELEN) {
IDMAP_DEBUG("idmap_name_to_uid: bad len\n");
return EINVAL;
}
/* XXX hack */
MALLOC(namestr, char *, len + 1, M_TEMP, M_WAITOK);
bcopy(name, namestr, len);
namestr[len] = '\0';
if ((e = idmap_name_lookup(IDMAP_TYPE_UID, namestr)) == NULL) {
if ((error = idmap_upcall_name(IDMAP_TYPE_UID, namestr, &e))) {
FREE(namestr, M_TEMP);
return error;
}
if (e == NULL) {
IDMAP_DEBUG("no error from upcall, but no data returned\n");
FREE(namestr, M_TEMP);
return EFAULT;
}
if (idmap_add(e) != 0) {
IDMAP_DEBUG("idmap_add failed\n");
FREE(e, M_IDMAP);
}
}
*id = e->id_info.id_id.uid;
FREE(namestr, M_TEMP);
return 0;
}
int
idmap_name_to_gid(char * name, size_t len, gid_t * id)
{
struct idmap_entry * e;
int error = 0;
char * namestr;
if (name == NULL )
return EFAULT;
if (len == 0 || len > IDMAP_MAXNAMELEN) {
IDMAP_DEBUG("idmap_name_to_uid: bad len\n");
return EINVAL;
}
/* XXX hack */
MALLOC(namestr, char *, len + 1, M_TEMP, M_WAITOK);
bcopy(name, namestr, len);
namestr[len] = '\0';
if ((e = idmap_name_lookup(IDMAP_TYPE_GID, namestr)) == NULL) {
if ((error = idmap_upcall_name(IDMAP_TYPE_GID, namestr, &e)) != 0) {
IDMAP_DEBUG("error in upcall\n");
FREE(namestr, M_TEMP);
return error;
}
if (e == NULL) {
IDMAP_DEBUG("no error from upcall, but no data returned\n");
FREE(namestr, M_TEMP);
return EFAULT;
}
if (idmap_add(e) != 0) {
IDMAP_DEBUG("idmap_add failed\n");
FREE(e, M_IDMAP);
}
}
*id = e->id_info.id_id.gid;
FREE(namestr, M_TEMP);
return 0;
}

View File

@ -0,0 +1,64 @@
/* $FreeBSD$ */
/* $Id: nfs4_idmap.h,v 1.2 2003/11/05 14:58:59 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#ifndef __NFS4_IDMAP_H__
#define __NFS4_IDMAP_H__
#define IDMAP_TYPE_GID 1
#define IDMAP_TYPE_UID 2
#define IDMAP_MAX_TYPE 2
typedef union {
uid_t uid;
gid_t gid;
} ident_t;
#define IDMAP_MAXNAMELEN 249
struct idmap_msg {
uint32_t id_type;
ident_t id_id;
size_t id_namelen;
char id_name[IDMAP_MAXNAMELEN + 1];
};
#ifdef _KERNEL
MALLOC_DECLARE(M_IDMAP);
void idmap_init(void);
void idmap_uninit(void);
int idmap_gid_to_name(gid_t id, char ** name, size_t * len);
int idmap_uid_to_name(uid_t id, char ** name, size_t * len);
int idmap_name_to_gid(char *, size_t len, gid_t *);
int idmap_name_to_uid(char *, size_t len, uid_t *);
#endif /* _KERNEL */
#endif /* __NFS4_GSS_H__ */

View File

@ -0,0 +1,340 @@
/* $FreeBSD$ */
/* $Id: nfs_socket.c,v 1.12 2003/11/05 14:59:01 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
/*
* Copyright (c) 1989, 1991, 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_socket.c 8.5 (Berkeley) 3/30/95
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Socket operations for use by nfs
*/
#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/syslog.h>
#include <sys/vnode.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfs4client/nfs4.h>
#include <nfs/xdr_subs.h>
#include <nfsclient/nfsm_subs.h>
#include <nfsclient/nfsmount.h>
#ifdef NFS4_USE_RPCCLNT
#include <rpc/rpcclnt.h>
#include <rpc/rpcm_subs.h>
#endif
#ifdef NFS4_USE_RPCCLNT
static struct rpc_program nfs_program = {
NFS_PROG, NFS_VER4, "NFSv4"
};
#endif
int
nfs4_connect(struct nfsmount *nmp)
{
struct rpcclnt * rpc = &nmp->nm_rpcclnt;
struct rpc_auth * auth;
int flag = 0;
int error;
/* XXX hack! */
#ifdef __OpenBSD__
struct proc * td = curproc;
#else
struct thread * td = curthread;
#endif
MALLOC(auth, struct rpc_auth *, sizeof(struct rpc_auth), M_TEMP, M_WAITOK);
auth->auth_type = RPCAUTH_UNIX;
/* translate nfs flags -> rpcclnt flags */
if (nmp->nm_flag & NFSMNT_SOFT)
flag |= RPCCLNT_SOFT;
if (nmp->nm_flag & NFSMNT_INT)
flag |= RPCCLNT_INT;
if (nmp->nm_flag & NFSMNT_NOCONN)
flag |= RPCCLNT_NOCONN;
if (nmp->nm_flag & NFSMNT_DUMBTIMR)
flag |= RPCCLNT_DUMBTIMR;
/* rpc->rc_servername = nmp->nm_mountp->mnt_stat.f_mntfromname; */
error = rpcclnt_setup(rpc, &nfs_program, nmp->nm_nam, nmp->nm_sotype,
nmp->nm_soproto, auth,
/* XXX: check nmp->nm_flag to make sure these are set */
(nmp->nm_rsize > nmp->nm_readdirsize) ? nmp->nm_rsize : nmp->nm_readdirsize,
nmp->nm_wsize, flag);
/* set deadthresh, timeo, retry */
rpc->rc_deadthresh = nmp->nm_deadthresh;
rpc->rc_timeo = nmp->nm_timeo;
rpc->rc_retry = nmp->nm_retry;
if (error)
return error;
return rpcclnt_connect(rpc, td);
}
/*
* NFS disconnect. Clean up and unlink.
*/
void
nfs4_disconnect(struct nfsmount *nmp)
{
rpcclnt_disconnect(&nmp->nm_rpcclnt);
}
void
nfs4_safedisconnect(struct nfsmount *nmp)
{
rpcclnt_safedisconnect(&nmp->nm_rpcclnt);
}
/*
* nfs_request - goes something like this
* - fill in request struct
* - links it into list
* - calls nfs_send() for first transmit
* - calls nfs_receive() to get reply
* - break down rpc header and return with nfs reply pointed to
* by mrep or error
* nb: always frees up mreq mbuf list
*/
/* XXX overloaded before */
#define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */
int
nfs4_request(struct vnode *vp, struct mbuf *mrest, int procnum,
struct thread *td, struct ucred *cred, struct mbuf **mrp,
struct mbuf **mdp, caddr_t *dposp)
{
int error;
u_int32_t *tl;
struct nfsmount * nmp = VFSTONFS(vp->v_mount);
struct rpcclnt * clnt = &nmp->nm_rpcclnt;
struct mbuf *md, *mrep;
caddr_t dpos;
struct rpc_reply reply;
if ((error = rpcclnt_request(clnt, mrest, procnum, td, cred,
&reply)) != 0) {
goto out;
}
/* XXX: don't free mrest if an error occured, to allow caller to retry*/
m_freem(mrest);
mrep = reply.mrep;
md = reply.result_md;
dpos = reply.result_dpos;
tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
if (*tl != 0) {
error = fxdr_unsigned(int, *tl);
#if 0
if ((nmp->nm_flag & NFSMNT_NFSV3) &&
error == NFSERR_TRYLATER) {
m_freem(mrep);
error = 0;
waituntil = time_second + trylater_delay;
while (time_second < waituntil)
(void) tsleep(&lbolt, PSOCK, "nqnfstry", 0);
trylater_delay *= nfs_backoff[trylater_cnt];
if (trylater_cnt < NFS_NBACKOFF - 1)
trylater_cnt++;
goto tryagain;
}
#endif
/*
** If the File Handle was stale, invalidate the
** lookup cache, just in case.
**/
if (error == ESTALE)
cache_purge(vp);
goto out;
}
*mrp = mrep;
*mdp = md;
*dposp = dpos;
return (0);
nfsmout:
out:
m_freem(reply.mrep);
*mrp = NULL;
*mdp = NULL;
return (error);
}
int
nfs4_request_mnt(struct nfsmount *nmp, struct mbuf *mrest, int procnum,
struct thread *td, struct ucred *cred, struct mbuf **mrp,
struct mbuf **mdp, caddr_t *dposp)
{
int error;
u_int32_t *tl;
struct rpcclnt * clnt = &nmp->nm_rpcclnt;
struct mbuf *md, *mrep;
caddr_t dpos;
struct rpc_reply reply;
if ((error = rpcclnt_request(clnt, mrest, procnum, td, cred,
&reply)) != 0) {
goto out;
}
/* XXX: don't free mrest if an error occured, to allow caller to retry*/
m_freem(mrest);
mrep = reply.mrep;
md = reply.result_md;
dpos = reply.result_dpos;
tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
if (*tl != 0) {
error = fxdr_unsigned(int, *tl);
#if 0
if ((nmp->nm_flag & NFSMNT_NFSV3) &&
error == NFSERR_TRYLATER) {
m_freem(mrep);
error = 0;
waituntil = time_second + trylater_delay;
while (time_second < waituntil)
(void) tsleep(&lbolt, PSOCK, "nqnfstry", 0);
trylater_delay *= nfs_backoff[trylater_cnt];
if (trylater_cnt < NFS_NBACKOFF - 1)
trylater_cnt++;
goto tryagain;
}
#endif
goto out;
}
*mrp = mrep;
*mdp = md;
*dposp = dpos;
return (0);
nfsmout:
out:
m_freem(reply.mrep);
*mrp = NULL;
*mdp = NULL;
return (error);
}
/*
* Mark all of an nfs mount's outstanding requests with R_SOFTTERM and
* wait for all requests to complete. This is used by forced unmounts
* to terminate any outstanding RPCs.
*/
int
nfs4_nmcancelreqs(nmp)
struct nfsmount *nmp;
{
return rpcclnt_cancelreqs(&nmp->nm_rpcclnt);
}
/*
* Test for a termination condition pending on the process.
* This is used for NFSMNT_INT mounts.
*/
int
nfs4_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td)
{
if (rep != NULL) {
printf("nfs_sigintr: attempting to use nfsreq != NULL\n");
return EINTR;
}
return rpcclnt_sigintr(&nmp->nm_rpcclnt, NULL, td);
}

1352
sys/nfs4client/nfs4_subs.c Normal file

File diff suppressed because it is too large Load Diff

34
sys/nfs4client/nfs4_vfs.h Normal file
View File

@ -0,0 +1,34 @@
/* $FreeBSD$ */
/* $Id: nfs4_vfs.h,v 1.4 2003/11/05 14:59:00 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#ifndef _NFS4CLIENT_NFS4_VFS_H
#define _NFS4CLIENT_NFS4_VFS_H
void nfs4_vfsop_fsinfo(struct nfsv4_fattr *, struct nfsmount *);
void nfs4_vfsop_statfs(struct nfsv4_fattr *, struct statfs *, struct mount *);
#endif /* _NFS4CLIENT_NFS4_VFS_H */

View File

@ -0,0 +1,150 @@
/* $FreeBSD$ */
/* $Id: nfs4_vfs_subs.c,v 1.5 2003/11/05 14:59:00 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sockio.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/uma.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsmount.h>
#include <nfs/xdr_subs.h>
#include <nfsclient/nfsm_subs.h>
#include <nfsclient/nfsdiskless.h>
/* NFSv4 */
#include <nfs4client/nfs4.h>
#include <nfs4client/nfs4m_subs.h>
#include <nfs4client/nfs4_vfs.h>
#include <nfsclient/nfsnode.h>
static int nfs_iosize(struct nfsmount *nmp);
static int
nfs_iosize(struct nfsmount *nmp)
{
int iosize;
/*
* Calculate the size used for io buffers. Use the larger
* of the two sizes to minimise nfs requests but make sure
* that it is at least one VM page to avoid wasting buffer
* space.
*/
iosize = max(nmp->nm_rsize, nmp->nm_wsize);
if (iosize < PAGE_SIZE) iosize = PAGE_SIZE;
return iosize;
}
void
nfs4_vfsop_fsinfo(struct nfsv4_fattr *fap, struct nfsmount *nmp)
{
uint32_t max;
if (fap->fa4_valid & FA4V_FSID) {
nmp->nm_fsid.val[0] = fap->fa4_fsid_major;
nmp->nm_fsid.val[1] = fap->fa4_fsid_minor;
}
if (fap->fa4_valid & FA4V_MAXREAD) {
max = fap->fa4_maxread;
if (max < nmp->nm_rsize) {
nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
if (nmp->nm_rsize == 0)
nmp->nm_rsize = max;
}
if (max < nmp->nm_readdirsize) {
nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
if (nmp->nm_readdirsize == 0)
nmp->nm_readdirsize = max;
}
}
if (fap->fa4_valid & FA4V_MAXWRITE) {
max = fap->fa4_maxwrite;
if (max < nmp->nm_wsize) {
nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
if (nmp->nm_wsize == 0)
nmp->nm_wsize = max;
}
}
if (fap->fa4_valid & FA4V_LEASE_TIME)
nmp->nm_lease_time = fap->fa4_lease_time;
/* nmp->nm_flag |= NFSMNT_GOTFSINFO; */
}
void
nfs4_vfsop_statfs(struct nfsv4_fattr *fap, struct statfs *sbp, struct mount *mp)
{
struct nfsmount *nmp = VFSTONFS(mp);
sbp->f_flags = nmp->nm_flag;
sbp->f_iosize = nfs_iosize(nmp);
sbp->f_bsize = NFS_FABLKSIZE;
if (fap->fa4_valid & FA4V_FSID) {
sbp->f_fsid.val[0] = fap->fa4_fsid_major;
sbp->f_fsid.val[1] = fap->fa4_fsid_minor;
}
sbp->f_ffree = fap->fa4_valid & FA4V_FFREE ? fap->fa4_ffree : 0;
/* sbp->f_ftotal = fa->fa4_valid & FA4_FTOTAL ? fa->fa4_ftotal : 0; */
sbp->f_bavail = fap->fa4_valid & FA4V_SAVAIL ?
fap->fa4_savail / NFS_FABLKSIZE : 500000;
sbp->f_bfree = fap->fa4_valid & FA4V_SFREE ?
fap->fa4_sfree / NFS_FABLKSIZE : 500000;
sbp->f_blocks = fap->fa4_valid & FA4V_STOTAL ?
fap->fa4_stotal / NFS_FABLKSIZE : 1000000;
if (sbp != &mp->mnt_stat) {
sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
}

View File

@ -0,0 +1,938 @@
/* $FreeBSD$ */
/* $Id: nfs_vfsops.c,v 1.38 2003/11/05 14:59:01 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
/*
* 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/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_bootp.h"
#include "opt_nfsroot.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/uma.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfs4client/nfs4.h>
#include <nfsclient/nfsnode.h>
#include <nfsclient/nfsmount.h>
#include <nfs/xdr_subs.h>
#include <nfsclient/nfsm_subs.h>
#include <nfsclient/nfsdiskless.h>
#include <nfs4client/nfs4m_subs.h>
#include <nfs4client/nfs4_vfs.h>
#include <nfs4client/nfs4_dev.h>
#include <nfs4client/nfs4_idmap.h>
SYSCTL_NODE(_vfs, OID_AUTO, nfs4, CTLFLAG_RW, 0, "NFS4 filesystem");
SYSCTL_STRUCT(_vfs_nfs4, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
&nfsstats, nfsstats, "S,nfsstats");
#ifdef NFS_DEBUG
int nfs_debug;
SYSCTL_INT(_vfs_nfs4, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
#endif
static void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp);
static void nfs4_daemon(void *arg);
static int mountnfs(struct nfs_args *, struct mount *,
struct sockaddr *, char *, char *, struct vnode **,
struct ucred *cred);
static int nfs4_do_setclientid(struct nfsmount *nmp, struct ucred *cred);
static vfs_mount_t nfs_mount;
static vfs_unmount_t nfs_unmount;
static vfs_root_t nfs_root;
static vfs_statfs_t nfs_statfs;
static vfs_sync_t nfs_sync;
/*
* nfs vfs operations.
*/
static struct vfsops nfs_vfsops = {
.vfs_init = nfs4_init,
.vfs_mount = nfs_mount,
.vfs_root = nfs_root,
.vfs_statfs = nfs_statfs,
.vfs_sync = nfs_sync,
.vfs_uninit = nfs4_uninit,
.vfs_unmount = nfs_unmount,
};
VFS_SET(nfs_vfsops, nfs4, VFCF_NETWORK);
/* So that loader and kldload(2) can find us, wherever we are.. */
MODULE_VERSION(nfs4, 1);
void nfsargs_ntoh(struct nfs_args *);
#ifdef NFS4DISKLESS
/*
* 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 } } };
struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
int nfs_diskless_valid = 0;
SYSCTL_INT(_vfs_nfs4, OID_AUTO, diskless_valid, CTLFLAG_RD,
&nfs_diskless_valid, 0, "");
SYSCTL_STRING(_vfs_nfs4, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
nfsv3_diskless.root_hostnam, 0, "");
SYSCTL_OPAQUE(_vfs_nfs4, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
&nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
"%Ssockaddr_in", "");
SYSCTL_STRING(_vfs_nfs4, OID_AUTO, diskless_swappath, CTLFLAG_RD,
nfsv3_diskless.swap_hostnam, 0, "");
SYSCTL_OPAQUE(_vfs_nfs4, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
&nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr,
"%Ssockaddr_in","");
static int nfs_mountdiskless(char *, char *, int,
struct sockaddr_in *, struct nfs_args *,
struct thread *, struct vnode **, struct mount **);
static void nfs_convert_diskless(void);
static void nfs_convert_oargs(struct nfs_args *args,
struct onfs_args *oargs);
static void
nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
{
args->version = NFS_ARGSVERSION;
args->addr = oargs->addr;
args->addrlen = oargs->addrlen;
args->sotype = oargs->sotype;
args->proto = oargs->proto;
args->fh = oargs->fh;
args->fhsize = oargs->fhsize;
args->flags = oargs->flags;
args->wsize = oargs->wsize;
args->rsize = oargs->rsize;
args->readdirsize = oargs->readdirsize;
args->timeo = oargs->timeo;
args->retrans = oargs->retrans;
args->maxgrouplist = oargs->maxgrouplist;
args->readahead = oargs->readahead;
args->deadthresh = oargs->deadthresh;
args->hostname = oargs->hostname;
}
static void
nfs_convert_diskless(void)
{
bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
sizeof(struct ifaliasreq));
bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
sizeof(struct sockaddr_in));
nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
nfsv3_diskless.root_fhsize = NFSX_V2FH;
bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
sizeof(struct sockaddr_in));
bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
nfsv3_diskless.root_time = nfs_diskless.root_time;
bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
MAXHOSTNAMELEN);
nfs_diskless_valid = 3;
}
#endif
int
nfs4_init(struct vfsconf *vfsp)
{
rpcclnt_init();
nfs4dev_init();
idmap_init();
nfsm_v4init();
return (0);
}
int
nfs4_uninit(struct vfsconf *vfsp)
{
rpcclnt_uninit();
nfs4dev_uninit();
idmap_uninit();
return (0);
}
/*
* nfs statfs call
*/
static int
nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
{
struct vnode *vp;
struct nfs_statfs *sfp;
caddr_t bpos, dpos;
struct nfsmount *nmp = VFSTONFS(mp);
int error = 0;
struct mbuf *mreq, *mrep = NULL, *md, *mb;
struct nfsnode *np;
struct nfs4_compound cp;
struct nfs4_oparg_getattr ga;
struct nfsv4_fattr *fap = &ga.fa;
#ifndef nolint
sfp = NULL;
#endif
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
return (error);
vp = NFSTOV(np);
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, NFSX_FH(1));
mb = mreq;
bpos = mtod(mb, caddr_t);
ga.bm = &nfsv4_fsattrbm;
nfs_v4initcompound(&cp);
nfsm_v4build_compound(&cp, "statfs()");
nfsm_v4build_putfh(&cp, vp);
nfsm_v4build_getattr(&cp, &ga);
nfsm_v4build_finalize(&cp);
nfsm_request(vp, NFSV4PROC_COMPOUND, td, td->td_ucred);
if (error != 0)
goto nfsmout;
nfsm_v4dissect_compound(&cp);
nfsm_v4dissect_putfh(&cp);
nfsm_v4dissect_getattr(&cp, &ga);
nfs4_vfsop_statfs(fap, sbp, mp);
nfsmout:
error = nfs_v4postop(&cp, error);
vput(vp);
if (mrep != NULL)
m_freem(mrep);
return (error);
}
static void
nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp)
{
int s;
int adjsock;
int maxio;
s = splnet();
/*
* Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
* no sense in that context.
*/
if (argp->sotype == SOCK_STREAM)
nmp->nm_flag &= ~NFSMNT_NOCONN;
nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
/* Re-bind if rsrvd port requested and wasn't on one */
adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
&& (argp->flags & NFSMNT_RESVPORT);
/* Also re-bind if we're switching to/from a connected UDP socket */
adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
(argp->flags & NFSMNT_NOCONN));
/* Update flags atomically. Don't change the lock bits. */
nmp->nm_flag = argp->flags | nmp->nm_flag;
splx(s);
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;
}
if (nmp->nm_readdirsize > maxio)
nmp->nm_readdirsize = maxio;
if (nmp->nm_readdirsize > nmp->nm_rsize)
nmp->nm_readdirsize = nmp->nm_rsize;
if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
nmp->nm_acregmin = argp->acregmin;
else
nmp->nm_acregmin = NFS_MINATTRTIMO;
if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
nmp->nm_acregmax = argp->acregmax;
else
nmp->nm_acregmax = NFS_MAXATTRTIMO;
if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
nmp->nm_acdirmin = argp->acdirmin;
else
nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
nmp->nm_acdirmax = argp->acdirmax;
else
nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
if (nmp->nm_acdirmin > nmp->nm_acdirmax)
nmp->nm_acdirmin = nmp->nm_acdirmax;
if (nmp->nm_acregmin > nmp->nm_acregmax)
nmp->nm_acregmin = nmp->nm_acregmax;
if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
if (argp->maxgrouplist <= NFS_MAXGRPS)
nmp->nm_numgrps = argp->maxgrouplist;
else
nmp->nm_numgrps = NFS_MAXGRPS;
}
if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
if (argp->readahead <= NFS_MAXRAHEAD)
nmp->nm_readahead = argp->readahead;
else
nmp->nm_readahead = NFS_MAXRAHEAD;
}
if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
if (argp->deadthresh <= NFS_MAXDEADTHRESH)
nmp->nm_deadthresh = argp->deadthresh;
else
nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
}
adjsock |= ((nmp->nm_sotype != argp->sotype) ||
(nmp->nm_soproto != argp->proto));
nmp->nm_sotype = argp->sotype;
nmp->nm_soproto = argp->proto;
if (nmp->nm_rpcclnt.rc_so && adjsock) {
nfs_safedisconnect(nmp);
if (nmp->nm_sotype == SOCK_DGRAM) {
while (nfs4_connect(nmp)) {
printf("nfs_args: retrying connect\n");
(void) tsleep((caddr_t)&lbolt,
PSOCK, "nfscon", 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 */
static int
nfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
struct thread *td)
{
int error;
struct nfs_args args;
struct sockaddr *nam;
struct vnode *vp;
char hst[MNAMELEN];
size_t len;
if (path == NULL) {
printf("NFSv4: nfs_mountroot not supported\n");
return EINVAL;
}
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
if (args.version != NFS_ARGSVERSION)
return (EPROGMISMATCH);
if (mp->mnt_flag & MNT_UPDATE) {
struct nfsmount *nmp = VFSTONFS(mp);
if (nmp == NULL)
return (EIO);
/*
* When doing an update, we can't change from or to
* v3, switch lockd strategies or change cookie translation
*/
args.flags = (args.flags &
~(NFSMNT_NFSV3 | NFSMNT_NFSV4 | NFSMNT_NOLOCKD)) |
(nmp->nm_flag &
(NFSMNT_NFSV3 | NFSMNT_NFSV4 | NFSMNT_NOLOCKD));
nfs_decode_args(nmp, &args);
return (0);
}
if (error)
return (error);
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 = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
if (error)
return (error);
error = mountnfs(&args, mp, nam, path, hst, &vp, td->td_ucred);
return (error);
}
/*
* renew should be done async
* should re-scan mount queue each time
*/
struct proc *nfs4_daemonproc;
static int
nfs4_do_renew(struct nfsmount *nmp, struct ucred *cred)
{
struct nfs4_compound cp;
struct mbuf *mreq, *mrep = NULL, *md, *mb;
caddr_t bpos, dpos;
int error;
mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, sizeof(uint64_t));
mb = mreq;
bpos = mtod(mb, caddr_t);
nfs_v4initcompound(&cp);
nfsm_v4build_compound(&cp, "nfs4_do_renew()");
nfsm_v4build_renew(&cp, nmp->nm_clientid);
nfsm_v4build_finalize(&cp);
nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred);
if (error != 0)
goto nfsmout;
nfsm_v4dissect_compound(&cp);
nfsm_v4dissect_renew(&cp);
nmp->nm_last_renewal = time_second;
return (0);
nfsmout:
error = nfs_v4postop(&cp, error);
/* XXX */
if (mrep != NULL)
m_freem(mrep);
return (error);
}
static void
nfs4_daemon(void *arg)
{
struct mount *mp;
struct nfsmount *nmp;
int nmounts;
while (1) {
nmounts = 0;
mtx_lock(&mountlist_mtx);
TAILQ_FOREACH(mp, &mountlist, mnt_list) {
if (strcmp(mp->mnt_vfc->vfc_name, "nfs4") != 0)
continue;
nmounts++;
nmp = VFSTONFS(mp);
if (time_second < nmp->nm_last_renewal + nmp->nm_lease_time - 4)
continue;
mtx_unlock(&mountlist_mtx);
mtx_lock(&Giant);
nfs4_do_renew(nmp, (struct ucred *) arg);
mtx_unlock(&Giant);
mtx_lock(&mountlist_mtx);
}
mtx_unlock(&mountlist_mtx);
/* Must kill the daemon here, or module unload will cause a panic */
if (nmounts == 0) {
mtx_lock(&Giant);
nfs4_daemonproc = NULL;
printf("nfsv4 renewd exiting\n");
kthread_exit(0);
}
tsleep(&nfs4_daemonproc, PVFS, "nfs4", 2 * hz);
}
}
/*
* Common code for mount and mountroot
*/
static int
mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
char *pth, char *hst, struct vnode **vpp, struct ucred *cred)
{
struct nfsmount *nmp;
char *rpth, *cp1, *cp2;
int nlkup = 0, error;
struct nfs4_compound cp;
struct mbuf *mreq, *mrep = NULL, *md, *mb;
caddr_t bpos, dpos;
struct nfs4_oparg_lookup lkup;
struct nfs4_oparg_getfh gfh;
struct nfs4_oparg_getattr ga;
struct thread *td = curthread; /* XXX */
if (mp->mnt_flag & MNT_UPDATE) {
nmp = VFSTONFS(mp);
/* update paths, file handles, etc, here XXX */
FREE(nam, M_SONAME);
return (0);
} else {
nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
bzero((caddr_t)nmp, sizeof (struct nfsmount));
TAILQ_INIT(&nmp->nm_bufq);
mp->mnt_data = (qaddr_t)nmp;
}
vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
nmp->nm_maxfilesize = 0xffffffffLL;
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_deadthresh = NFS_MAXDEADTHRESH;
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
/* Set up the sockets and per-host congestion */
nmp->nm_sotype = argp->sotype;
nmp->nm_soproto = argp->proto;
/* XXX */
mp->mnt_stat.f_iosize = PAGE_SIZE;
/* XXX - this is to make some other code work. Sort of ugly. */
argp->flags |= (NFSMNT_NFSV3 | NFSMNT_NFSV4);
nfs_decode_args(nmp, argp);
if ((error = nfs4_connect(nmp)))
goto bad;
mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1));
mb = mreq;
bpos = mtod(mb, caddr_t);
ga.bm = &nfsv4_fsinfobm;
nfs_v4initcompound(&cp);
/* Get remote path */
rpth = hst;
strsep(&rpth, ":");
nfsm_v4build_compound(&cp, "mountnfs()");
nfsm_v4build_putrootfh(&cp);
for (cp1 = rpth; cp1 && *cp1; cp1 = cp2) {
while (*cp1 == '/')
cp1++;
if (!*cp1)
break;
for (cp2 = cp1; *cp2 && *cp2 != '/'; cp2++)
;
lkup.name = cp1;
lkup.namelen = cp2 - cp1;
nfsm_v4build_lookup(&cp, &lkup);
nlkup++;
}
nfsm_v4build_getfh(&cp, &gfh);
nfsm_v4build_getattr(&cp, &ga);
nfsm_v4build_finalize(&cp);
nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, td, cred);
if (error != 0)
goto nfsmout;
nfsm_v4dissect_compound(&cp);
nfsm_v4dissect_putrootfh(&cp);
while (nlkup--)
nfsm_v4dissect_lookup(&cp);
nfsm_v4dissect_getfh(&cp, &gfh);
nfsm_v4dissect_getattr(&cp, &ga);
nfs4_vfsop_fsinfo(&ga.fa, nmp);
nmp->nm_state |= NFSSTA_GOTFSINFO;
/* Copy root fh into nfsmount. */
nmp->nm_fhsize = gfh.fh_len;
bcopy(&gfh.fh_val, nmp->nm_fh, nmp->nm_fhsize);
nmp->nm_last_renewal = time_second;
if ((error = nfs4_do_setclientid(nmp, cred)) != 0)
goto nfsmout;
/* Start renewd if it isn't already running */
if (nfs4_daemonproc == NULL)
kthread_create(nfs4_daemon, crdup(cred), &nfs4_daemonproc,
(RFPROC|RFMEM), 0, "nfs4rd");
return (0);
nfsmout:
error = nfs_v4postop(&cp, error);
/* XXX */
if (mrep != NULL)
m_freem(mrep);
bad:
nfs_disconnect(nmp);
uma_zfree(nfsmount_zone, nmp);
FREE(nam, M_SONAME);
return (error);
}
/*
* unmount system call
*/
static int
nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
{
struct nfsmount *nmp;
int error, flags = 0;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
nmp = VFSTONFS(mp);
/*
* Goes something like this..
* - Call vflush() to clear out vnodes for this filesystem
* - Close the socket
* - Free up the data structures
*/
/* In the forced case, cancel any outstanding requests. */
if (flags & FORCECLOSE) {
error = nfs_nmcancelreqs(nmp);
if (error)
return (error);
nfs4dev_purge();
}
error = vflush(mp, 0, flags);
if (error)
return (error);
/*
* We are now committed to the unmount.
*/
nfs_disconnect(nmp);
FREE(nmp->nm_nam, M_SONAME);
/* XXX there's a race condition here for SMP */
wakeup(&nfs4_daemonproc);
uma_zfree(nfsmount_zone, nmp);
return (0);
}
/*
* Return root of a filesystem
*/
static int
nfs_root(struct mount *mp, struct vnode **vpp)
{
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);
if (vp->v_type == VNON)
vp->v_type = VDIR;
vp->v_vflag |= VV_ROOT;
*vpp = vp;
return (0);
}
/*
* Flush out the buffer cache
*/
/* ARGSUSED */
static int
nfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct thread *td)
{
struct vnode *vp, *vnp;
int error, allerror = 0;
/*
* Force stale buffer cache information to be flushed.
*/
MNT_ILOCK(mp);
loop:
for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
vp != NULL;
vp = vnp) {
/*
* 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;
vnp = TAILQ_NEXT(vp, v_nmntvnodes);
VI_LOCK(vp);
MNT_IUNLOCK(mp);
if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
waitfor == MNT_LAZY) {
VI_UNLOCK(vp);
MNT_ILOCK(mp);
continue;
}
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
goto loop;
}
error = VOP_FSYNC(vp, cred, waitfor, td);
if (error)
allerror = error;
VOP_UNLOCK(vp, 0, td);
vrele(vp);
MNT_ILOCK(mp);
}
MNT_IUNLOCK(mp);
return (allerror);
}
static int
nfs4_do_setclientid(struct nfsmount *nmp, struct ucred *cred)
{
struct nfs4_oparg_setclientid scid;
struct nfs4_compound cp;
struct mbuf *mreq, *mrep = NULL, *md, *mb;
caddr_t bpos, dpos;
struct route ro;
char *ipsrc = NULL, uaddr[24], name[24];
int try = 0;
static int seq;
int error;
#ifndef NFS4_USE_RPCCLNT
return (0);
#endif
if (nmp->nm_clientid) {
printf("nfs4_do_setclientid: already have clientid!\n");
error = 0;
goto nfsmout;
}
/* Try not to re-use clientids */
if (seq == 0)
seq = time_second & 0xffffff;
#ifdef NFS4_USE_RPCCLNT
scid.cb_netid = (nmp->nm_rpcclnt.rc_sotype == SOCK_STREAM) ? "tcp" : "udp";
#endif
scid.cb_netid = "tcp";
scid.cb_netidlen = 3;
scid.cb_prog = 0x1234; /* XXX */
/* Do a route lookup to find our source address for talking to this server */
bzero(&ro, sizeof ro);
#ifdef NFS4_USE_RPCCLNT
ro.ro_dst = *nmp->nm_rpcclnt.rc_name;
#endif
rtalloc(&ro);
if (ro.ro_rt == NULL) {
error = EHOSTUNREACH;
goto nfsmout;
}
ipsrc = inet_ntoa(IA_SIN(ifatoia(ro.ro_rt->rt_ifa))->sin_addr);
sprintf(uaddr, "%s.12.48", ipsrc);
scid.cb_univaddr = uaddr;
scid.cb_univaddrlen = strlen(uaddr);
RTFREE(ro.ro_rt);
try_again:
sprintf(name, "%s-%d", ipsrc, seq++);
scid.namelen = strlen(name);
scid.name = name;
nfs_v4initcompound(&cp);
mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1));
mb = mreq;
bpos = mtod(mb, caddr_t);
nfsm_v4build_compound(&cp, "nfs4_do_setclientid()");
nfsm_v4build_setclientid(&cp, &scid);
nfsm_v4build_finalize(&cp);
nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred);
if (error != 0)
goto nfsmout;
nfsm_v4dissect_compound(&cp);
nfsm_v4dissect_setclientid(&cp, &scid);
nmp->nm_clientid = scid.clientid;
error = nfs_v4postop(&cp, error);
/* Confirm */
m_freem(mrep);
mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1));
mb = mreq;
bpos = mtod(mb, caddr_t);
nfs_v4initcompound(&cp);
nfsm_v4build_compound(&cp, "nfs4_do_setclientid() (confirm)");
nfsm_v4build_setclientid_confirm(&cp, &scid);
nfsm_v4build_finalize(&cp);
nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred);
if (error != 0)
goto nfsmout;
nfsm_v4dissect_compound(&cp);
nfsm_v4dissect_setclientid_confirm(&cp);
nfsmout:
error = nfs_v4postop(&cp, error);
if (mrep)
m_freem(mrep);
if (error == NFSERR_CLID_INUSE && (++try < NFS4_SETCLIENTID_MAXTRIES))
goto try_again;
return (error);
}

33
sys/nfs4client/nfs4_vn.h Normal file
View File

@ -0,0 +1,33 @@
/* $FreeBSD$ */
/* $Id: nfs4_vn.h,v 1.5 2003/11/05 14:59:00 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#ifndef _NFS4CLIENT_NFS4_VFS_H
#define _NFS4CLIENT_NFS4_VFS_H
void nfs4_vnop_loadattrcache(struct vnode *, struct nfsv4_fattr *, struct vattr *);
#endif /* _NFS4CLIENT_NFS4_VFS_H */

View File

@ -0,0 +1,223 @@
/* $FreeBSD$ */
/* $Id: nfs4_vn_subs.c,v 1.9 2003/11/05 14:59:00 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sockio.h>
#include <sys/vnode.h>
#include <sys/types.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/uma.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsmount.h>
#include <nfs/xdr_subs.h>
#include <nfsclient/nfsm_subs.h>
#include <nfsclient/nfsdiskless.h>
/* NFSv4 */
#include <nfs4client/nfs4.h>
#include <nfs4client/nfs4m_subs.h>
#include <nfs4client/nfs4_vn.h>
#include <nfsclient/nfsnode.h>
void
nfs4_vnop_loadattrcache(struct vnode *vp, struct nfsv4_fattr *fap,
struct vattr *vaper)
{
struct vattr *vap;
struct nfsnode *np;
int32_t rdev;
enum vtype vtyp;
u_short vmode;
struct timespec mtime;
struct timeval tv;
microtime(&tv);
vtyp = nv3tov_type[fap->fa4_type & 0x7];
vmode = (fap->fa4_valid & FA4V_MODE) ? fap->fa4_mode : 0777;
rdev = (fap->fa4_valid & FA4V_RDEV) ?
makeudev(fap->fa4_rdev_major, fap->fa4_rdev_minor) : 0;
if (fap->fa4_valid & FA4V_MTIME)
mtime = fap->fa4_mtime;
else
bzero(&mtime, sizeof mtime);
/*
* If v_type == VNON it is a new node, so fill in the v_type,
* n_mtime fields. Check to see if it represents a special
* device, and if so, check for a possible alias. Once the
* correct vnode has been obtained, fill in the rest of the
* information.
*/
np = VTONFS(vp);
vap = &np->n_vattr;
if (vp->v_type != vtyp || np->n_mtime == 0) {
bzero(vap, sizeof *vap);
vp->v_type = vtyp;
np->n_mtime = mtime.tv_sec;
}
vap->va_type = vtyp;
vap->va_mode = (vmode & 07777);
vap->va_rdev = rdev;
vap->va_mtime = mtime;
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
if (fap->fa4_valid & FA4V_NLINK)
vap->va_nlink = fap->fa4_nlink;
if (fap->fa4_valid & FA4V_UID)
vap->va_uid = fap->fa4_uid;
if (fap->fa4_valid & FA4V_GID)
vap->va_gid = fap->fa4_gid;
vap->va_size = fap->fa4_size;
vap->va_blocksize = NFS_FABLKSIZE;
vap->va_bytes = fap->fa4_size;
if (fap->fa4_valid & FA4V_FILEID)
vap->va_fileid = nfs_v4fileid4_to_fileid(fap->fa4_fileid);
if (fap->fa4_valid & FA4V_ATIME)
vap->va_atime = fap->fa4_atime;
if (fap->fa4_valid & FA4V_CTIME)
vap->va_ctime = fap->fa4_ctime;
vap->va_flags = 0;
vap->va_filerev = 0;
/* XXX dontshrink flag? */
if (vap->va_size != np->n_size) {
if (vap->va_type == VREG) {
if (np->n_flag & NMODIFIED) {
if (vap->va_size < np->n_size)
vap->va_size = np->n_size;
else
np->n_size = vap->va_size;
} else
np->n_size = vap->va_size;
vnode_pager_setsize(vp, np->n_size);
} else
np->n_size = vap->va_size;
}
np->n_attrstamp = tv.tv_sec;
if (vaper != NULL) {
bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
if (np->n_flag & NCHG) {
if (np->n_flag & NACC)
vaper->va_atime = np->n_atim;
if (np->n_flag & NUPD)
vaper->va_mtime = np->n_mtim;
}
}
}
static uint64_t nfs_nullcookie = 0;
/*
* This function finds the directory cookie that corresponds to the
* logical byte offset given.
*/
uint64_t *
nfs4_getcookie(struct nfsnode *np, off_t off, int add)
{
struct nfsdmap *dp, *dp2;
int pos;
pos = (uoff_t)off / NFS_DIRBLKSIZ;
if (pos == 0 || off < 0) {
#ifdef DIAGNOSTIC
if (add)
panic("nfs getcookie add at <= 0");
#endif
return (&nfs_nullcookie);
}
pos--;
dp = LIST_FIRST(&np->n_cookies);
if (!dp) {
if (add) {
MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap),
M_NFSDIROFF, M_WAITOK);
dp->ndm_eocookie = 0;
LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
} else
return (NULL);
}
while (pos >= NFSNUMCOOKIES) {
pos -= NFSNUMCOOKIES;
if (LIST_NEXT(dp, ndm_list)) {
if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
pos >= dp->ndm_eocookie)
return (NULL);
dp = LIST_NEXT(dp, ndm_list);
} else if (add) {
MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap),
M_NFSDIROFF, M_WAITOK);
dp2->ndm_eocookie = 0;
LIST_INSERT_AFTER(dp, dp2, ndm_list);
dp = dp2;
} else
return (NULL);
}
if (pos >= dp->ndm_eocookie) {
if (add)
dp->ndm_eocookie = pos + 1;
else
return (NULL);
}
return (&dp->ndm4_cookies[pos]);
}
/*
* Invalidate cached directory information, except for the actual directory
* blocks (which are invalidated separately).
* Done mainly to avoid the use of stale offset cookies.
*/
void
nfs4_invaldir(struct vnode *vp)
{
struct nfsnode *np = VTONFS(vp);
np->n_direofoffset = 0;
bzero(np->n4_cookieverf, NFSX_V4VERF);
if (LIST_FIRST(&np->n_cookies))
LIST_FIRST(&np->n_cookies)->ndm_eocookie = 0;
}

3200
sys/nfs4client/nfs4_vnops.c Normal file

File diff suppressed because it is too large Load Diff

498
sys/nfs4client/nfs4m_subs.h Normal file
View File

@ -0,0 +1,498 @@
/* $FreeBSD$ */
/* $Id: nfs4m_subs.h,v 1.36 2003/11/05 14:59:01 rees Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
#ifndef _NFS4CLIENT_NFSM4_SUBS_H
#define _NFS4CLIENT_NFSM4_SUBS_H
void nfsm_v4init(void);
void nfsm_buildf_xx(struct mbuf **mb, caddr_t *bpos, char *fmt, ...);
int nfsm_dissectf_xx(struct mbuf **md, caddr_t *dpos, char *fmt, ...);
int nfsm_v4build_compound_xx(struct nfs4_compound *, char *,
struct mbuf **, caddr_t *);
int nfsm_v4build_putfh_xx(struct nfs4_compound *, struct vnode *,
struct mbuf **, caddr_t *);
int nfsm_v4build_putfh_nv_xx(struct nfs4_compound *, struct nfs4_oparg_getfh *,
struct mbuf **, caddr_t *);
int nfsm_v4build_getattr_xx(struct nfs4_compound *, struct nfs4_oparg_getattr *,
struct mbuf **, caddr_t *);
int nfsm_v4build_finalize_xx(struct nfs4_compound *, struct mbuf **, caddr_t *);
int nfsm_v4build_getfh_xx(struct nfs4_compound *, struct nfs4_oparg_getfh *,
struct mbuf **, caddr_t *);
int nfsm_v4build_lookup_xx(struct nfs4_compound *, struct nfs4_oparg_lookup *,
struct mbuf **, caddr_t *);
int nfsm_v4build_setclientid_xx(struct nfs4_compound *,
struct nfs4_oparg_setclientid *, struct mbuf **, caddr_t *);
int nfsm_v4build_setclientid_confirm_xx(struct nfs4_compound *,
struct nfs4_oparg_setclientid *, struct mbuf **, caddr_t *);
int nfsm_v4build_close_xx(struct nfs4_compound *, struct nfs4_fctx *,
struct mbuf **, caddr_t *);
int nfsm_v4build_access_xx(struct nfs4_compound *, struct nfs4_oparg_access *,
struct mbuf **, caddr_t *);
int nfsm_v4build_open_xx(struct nfs4_compound *, struct nfs4_oparg_open *,
struct mbuf **, caddr_t *);
int nfsm_v4build_open_confirm_xx(struct nfs4_compound *, struct nfs4_oparg_open *,
struct mbuf **, caddr_t *);
int nfsm_v4build_read_xx(struct nfs4_compound *, struct nfs4_oparg_read *,
struct mbuf **, caddr_t *);
int nfsm_v4build_write_xx(struct nfs4_compound *, struct nfs4_oparg_write *,
struct mbuf **, caddr_t *);
int nfsm_v4build_commit_xx(struct nfs4_compound *, struct nfs4_oparg_commit *,
struct mbuf **, caddr_t *);
int nfsm_v4build_readdir_xx(struct nfs4_compound *, struct nfs4_oparg_readdir *,
struct mbuf **, caddr_t *);
int nfsm_v4build_renew_xx(struct nfs4_compound *, uint64_t,
struct mbuf **, caddr_t *);
int nfsm_v4build_setattr_xx(struct nfs4_compound *, struct vattr *,
struct nfs4_fctx *, struct mbuf **, caddr_t *);
int nfsm_v4build_create_xx(struct nfs4_compound *, struct nfs4_oparg_create *,
struct mbuf **, caddr_t *);
int nfsm_v4build_rename_xx(struct nfs4_compound *, struct nfs4_oparg_rename *,
struct mbuf **, caddr_t *);
int nfsm_v4build_link_xx(struct nfs4_compound *, struct nfs4_oparg_link *,
struct mbuf **, caddr_t *);
int nfsm_v4build_remove_xx(struct nfs4_compound *, const char *, u_int,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_compound_xx(struct nfs4_compound *, struct mbuf **, caddr_t *);
int nfsm_v4dissect_getattr_xx(struct nfs4_compound *, struct nfs4_oparg_getattr *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_getfh_xx(struct nfs4_compound *, struct nfs4_oparg_getfh *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_setclientid_xx(struct nfs4_compound *,
struct nfs4_oparg_setclientid *, struct mbuf **, caddr_t *);
int nfsm_v4dissect_close_xx(struct nfs4_compound *, struct nfs4_fctx *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_access_xx(struct nfs4_compound *, struct nfs4_oparg_access *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_open_xx(struct nfs4_compound *, struct nfs4_oparg_open *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_open_confirm_xx(struct nfs4_compound *, struct nfs4_oparg_open *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_read_xx(struct nfs4_compound *, struct nfs4_oparg_read *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_write_xx(struct nfs4_compound *, struct nfs4_oparg_write *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_commit_xx(struct nfs4_compound *, struct nfs4_oparg_commit *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_setattr_xx(struct nfs4_compound *, struct mbuf **, caddr_t *);
int nfsm_v4dissect_create_xx(struct nfs4_compound *, struct nfs4_oparg_create *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_readlink_xx(struct nfs4_compound *, struct uio *,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_attrs_xx(struct nfsv4_fattr *, struct mbuf **, caddr_t *);
int nfsm_v4build_simple_xx(struct nfs4_compound *, uint32_t,
struct mbuf **, caddr_t *);
int nfsm_v4dissect_simple_xx(struct nfs4_compound *, uint32_t,
uint32_t, struct mbuf **, caddr_t *);
#define nfsm_v4build_putrootfh_xx(cp, mb, bpos) \
nfsm_v4build_simple_xx((cp), NFSV4OP_PUTROOTFH, (mb), (bpos))
#define nfsm_v4build_lookupp_xx(cp, mb, bpos) \
nfsm_v4build_simple_xx((cp), NFSV4OP_LOOKUPP, (mb), (bpos))
#define nfsm_v4build_savefh_xx(cp, mb, bpos) \
nfsm_v4build_simple_xx((cp), NFSV4OP_SAVEFH, (mb), (bpos))
#define nfsm_v4build_readlink_xx(cp, mb, bpos) \
nfsm_v4build_simple_xx((cp), NFSV4OP_READLINK, (mb), (bpos))
#define nfsm_v4dissect_putrootfh_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_PUTROOTFH, 0, (mb), (bpos))
#define nfsm_v4dissect_lookup_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_LOOKUP, 0, (mb), (bpos))
#define nfsm_v4dissect_lookupp_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_LOOKUPP, 0, (mb), (bpos))
#define nfsm_v4dissect_putfh_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_PUTFH, 0, (mb), (bpos))
#define nfsm_v4dissect_renew_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_RENEW, 0, (mb), (bpos))
#define nfsm_v4dissect_setclientid_confirm_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_SETCLIENTID_CONFIRM, 0, (mb), (bpos))
#define nfsm_v4dissect_rename_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_RENAME, 0, (mb), (bpos))
#define nfsm_v4dissect_link_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_LINK, 0, (mb), (bpos))
#define nfsm_v4dissect_savefh_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_SAVEFH, 0, (mb), (bpos))
#define nfsm_v4dissect_remove_xx(cp, mb, bpos) \
nfsm_v4dissect_simple_xx((cp), NFSV4OP_REMOVE, 0, (mb), (bpos))
#define nfsm_v4build_compound(cp, tag) do { \
int32_t t1; \
t1 = nfsm_v4build_compound_xx((cp), (tag), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_finalize(cp) do { \
int32_t t1; \
t1 = nfsm_v4build_finalize_xx((cp), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_putfh(cp, vp) do { \
int32_t t1; \
t1 = nfsm_v4build_putfh_xx((cp), (vp), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_putfh_nv(cp, gfh) do { \
int32_t t1; \
t1 = nfsm_v4build_putfh_nv_xx((cp), (gfh), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_putrootfh(cp) do { \
int32_t t1; \
t1 = nfsm_v4build_putrootfh_xx((cp), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_getattr(cp, ga) do { \
int32_t t1; \
t1 = nfsm_v4build_getattr_xx((cp), (ga), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_setattr(cp, vap, fcp) do { \
int32_t t1; \
t1 = nfsm_v4build_setattr_xx((cp), (vap), (fcp), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_lookup(cp, l) do { \
int32_t t1; \
t1 = nfsm_v4build_lookup_xx((cp), (l), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_lookupp(cp) do { \
int32_t t1; \
t1 = nfsm_v4build_lookupp_xx((cp), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_getfh(cp, gfh) do { \
int32_t t1; \
t1 = nfsm_v4build_getfh_xx((cp), (gfh), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_close(cp, fcp) do { \
int32_t t1; \
t1 = nfsm_v4build_close_xx((cp), (fcp), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_access(cp, acc) do { \
int32_t t1; \
t1 = nfsm_v4build_access_xx((cp), (acc), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_open(cp, o) do { \
int32_t t1; \
t1 = nfsm_v4build_open_xx((cp), (o), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_open_confirm(cp, o) do { \
int32_t t1; \
t1 = nfsm_v4build_open_confirm_xx((cp), (o), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_read(cp, r) do { \
int32_t t1; \
t1 = nfsm_v4build_read_xx((cp), (r), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_write(cp, w) do { \
int32_t t1; \
t1 = nfsm_v4build_write_xx((cp), (w), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_commit(cp, c) do { \
int32_t t1; \
t1 = nfsm_v4build_commit_xx((cp), (c), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_readdir(cp, r) do { \
int32_t t1; \
t1 = nfsm_v4build_readdir_xx((cp), (r), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_renew(cp, cid) do { \
int32_t t1; \
t1 = nfsm_v4build_renew_xx((cp), (cid), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_setclientid(cp, cid) do { \
int32_t t1; \
t1 = nfsm_v4build_setclientid_xx((cp), (cid), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_setclientid_confirm(cp, cid) do { \
int32_t t1; \
t1 = nfsm_v4build_setclientid_confirm_xx((cp), (cid), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_create(cp, c) do { \
int32_t t1; \
t1 = nfsm_v4build_create_xx((cp), (c), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_rename(cp, r) do { \
int32_t t1; \
t1 = nfsm_v4build_rename_xx((cp), (r), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_link(cp, r) do { \
int32_t t1; \
t1 = nfsm_v4build_link_xx((cp), (r), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_savefh(cp) do { \
int32_t t1; \
t1 = nfsm_v4build_savefh_xx((cp), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_readlink(cp) do { \
int32_t t1; \
t1 = nfsm_v4build_readlink_xx((cp), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
#define nfsm_v4build_remove(cp, name, namelen) do { \
int32_t t1; \
t1 = nfsm_v4build_remove_xx((cp), (name), (namelen), &mb, &bpos); \
nfsm_bcheck(t1, mreq); \
} while (0)
/* --- */
#define nfsm_v4dissect_compound(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_compound_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_putfh(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_putfh_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_putrootfh(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_putrootfh_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_getattr(cp, ga) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_getattr_xx((cp), (ga), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_setattr(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_setattr_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_lookup(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_lookup_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_lookupp(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_lookupp_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_getfh(cp, gfh) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_getfh_xx((cp), (gfh), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_setclientid(cp, sci) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_setclientid_xx((cp), (sci), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_setclientid_confirm(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_setclientid_confirm_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_close(cp, fcp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_close_xx((cp), (fcp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_access(cp, acc) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_access_xx((cp), (acc), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_open(cp, openp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_open_xx((cp), (openp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_open_confirm(cp, openp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_open_confirm_xx((cp), (openp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_read(cp, r) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_read_xx((cp), (r), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_write(cp, w) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_write_xx((cp), (w), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_commit(cp, c) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_commit_xx((cp), (c), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_attrs(fattr) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_attrs_xx((fattr), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_renew(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_renew_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_create(cp, c) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_create_xx((cp), (c), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_rename(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_rename_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_link(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_link_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_savefh(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_savefh_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_readlink(cp, uiop) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_readlink_xx((cp), (uiop), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#define nfsm_v4dissect_remove(cp) \
do { \
int32_t t1; \
t1 = nfsm_v4dissect_remove_xx((cp), &md, &dpos); \
nfsm_dcheck(t1, mrep); \
} while (0)
#endif /* _NFS4CLIENT_NFSM4_SUBS_H */

View File

@ -65,6 +65,8 @@ __FBSDID("$FreeBSD$");
#include <net/if_types.h>
#include <net/if_dl.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>

View File

@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <netinet/in.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfsclient/krpc.h>
#include <nfs/xdr_subs.h>

View File

@ -242,13 +242,31 @@ extern int nfs_debug;
#endif
/*
* File context information for nfsv4. Currently, there is only one
* lockowner for the whole machine "0."
*/
struct nfs4_fctx {
TAILQ_ENTRY(nfs4_fstate) next;
pid_t pid;
uint32_t refcnt;
struct nfs4_lowner *lop;
struct nfsnode *np;
char stateid[NFSX_V4STATEID];
};
vfs_init_t nfs_init;
vfs_uninit_t nfs_uninit;
int nfs_mountroot(struct mount *mp, struct thread *td);
#ifndef NFS4_USE_RPCCLNT
int nfs_send(struct socket *, struct sockaddr *, struct mbuf *,
struct nfsreq *);
int nfs_sndlock(struct nfsreq *);
void nfs_sndunlock(struct nfsreq *);
#endif /* ! NFS4_USE_RPCCLNT */
int nfs_vinvalbuf(struct vnode *, int, struct ucred *, struct thread *,
int);
int nfs_readrpc(struct vnode *, struct uio *, struct ucred *);
@ -271,6 +289,7 @@ int nfsm_mbuftouio(struct mbuf **, struct uio *, int, caddr_t *);
void nfs_nhinit(void);
int nfs_nmcancelreqs(struct nfsmount *);
void nfs_timer(void*);
int nfs_connect(struct nfsmount *, struct nfsreq *);
void nfs_disconnect(struct nfsmount *);
void nfs_safedisconnect(struct nfsmount *);

View File

@ -58,17 +58,28 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_pager.h>
#include <vm/vnode_pager.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsmount.h>
#include <nfsclient/nfsnode.h>
#include <nfs4client/nfs4.h>
/*
* Just call nfs_writebp() with the force argument set to 1.
*
* NOTE: B_DONE may or may not be set in a_bp on call.
*/
static int
nfs4_bwrite(struct buf *bp)
{
return (nfs4_writebp(bp, 1, curthread));
}
static int
nfs_bwrite(struct buf *bp)
{
@ -76,6 +87,11 @@ nfs_bwrite(struct buf *bp)
return (nfs_writebp(bp, 1, curthread));
}
struct buf_ops buf_ops_nfs4 = {
"buf_ops_nfs4",
nfs4_bwrite
};
struct buf_ops buf_ops_nfs = {
"buf_ops_nfs",
nfs_bwrite
@ -118,6 +134,7 @@ nfs_getpages(struct vop_getpages_args *ap)
if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
(nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
/* We'll never get here for v4, because we always have fsinfo */
(void)nfs_fsinfo(nmp, vp, cred, td);
}
@ -170,7 +187,10 @@ nfs_getpages(struct vop_getpages_args *ap)
uio.uio_rw = UIO_READ;
uio.uio_td = td;
error = nfs_readrpc(vp, &uio, cred);
if ((nmp->nm_flag & NFSMNT_NFSV4) != 0)
error = nfs4_readrpc(vp, &uio, cred);
else
error = nfs_readrpc(vp, &uio, cred);
pmap_qremove(kva, npages);
relpbuf(bp, &nfs_pbuf_freecnt);
@ -332,7 +352,10 @@ nfs_putpages(struct vop_putpages_args *ap)
else
iomode = NFSV3WRITE_FILESYNC;
error = nfs_writerpc(vp, &uio, cred, &iomode, &must_commit);
if ((nmp->nm_flag & NFSMNT_NFSV4) != 0)
error = nfs4_writerpc(vp, &uio, cred, &iomode, &must_commit);
else
error = nfs_writerpc(vp, &uio, cred, &iomode, &must_commit);
pmap_qremove(kva, npages);
relpbuf(bp, &nfs_pbuf_freecnt);
@ -837,7 +860,10 @@ nfs_write(struct vop_write_args *ap)
allocbuf(bp, bcount);
bp->b_flags |= save;
bp->b_magic = B_MAGIC_NFS;
bp->b_op = &buf_ops_nfs;
if ((nmp->nm_flag & NFSMNT_NFSV4) != 0)
bp->b_op = &buf_ops_nfs4;
else
bp->b_op = &buf_ops_nfs;
}
} else {
/*
@ -996,7 +1022,10 @@ nfs_write(struct vop_write_args *ap)
break;
} else if ((n + on) == biosize) {
bp->b_flags |= B_ASYNC;
(void)nfs_writebp(bp, 0, 0);
if ((nmp->nm_flag & NFSMNT_NFSV4) != 0)
(void)nfs4_writebp(bp, 0, 0);
else
(void)nfs_writebp(bp, 0, 0);
} else {
bdwrite(bp);
}
@ -1339,13 +1368,17 @@ nfs_doio(struct buf *bp, struct ucred *cr, struct thread *td)
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_NFSV4) != 0)
error = nfs4_readdirrpc(vp, uiop, cr);
else {
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) != 0) {
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);
}
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
error = nfs_readdirrpc(vp, uiop, cr);
/*
* end-of-directory sets B_INVAL but does not generate an
* error.

View File

@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_var.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>

View File

@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>

View File

@ -66,6 +66,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <rpc/rpcclnt.h>
#include <nfs/xdr_subs.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>

View File

@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
@ -182,7 +184,7 @@ nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp)
/*
* Calculate nfs mount point and figure out whether the rslock should
* be interruptable or not.
* be interruptible or not.
*/
nmp = VFSTONFS(mntp);
if (nmp->nm_flag & NFSMNT_INT)
@ -226,7 +228,10 @@ nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp)
*/
np = uma_zalloc(nfsnode_zone, M_WAITOK);
error = getnewvnode("nfs", mntp, nfs_vnodeop_p, &nvp);
if (nmp->nm_flag & NFSMNT_NFSV4)
error = getnewvnode("nfs4", mntp, nfs4_vnodeop_p, &nvp);
else
error = getnewvnode("nfs", mntp, nfs_vnodeop_p, &nvp);
if (error) {
if (nfs_node_hash_lock < 0)
wakeup(&nfs_node_hash_lock);
@ -295,7 +300,7 @@ nfs_inactive(struct vop_inactive_args *ap)
/*
* Remove the silly file that was rename'd earlier
*/
nfs_removeit(sp);
(sp->s_removeit)(sp);
crfree(sp->s_cred);
vrele(sp->s_dvp);
FREE((caddr_t)sp, M_NFSREQ);

View File

@ -65,6 +65,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
@ -73,6 +75,8 @@ __FBSDID("$FreeBSD$");
#include <nfsclient/nfsmount.h>
#include <nfsclient/nfsnode.h>
#include <nfs4client/nfs4.h>
#define TRUE 1
#define FALSE 0
@ -874,6 +878,8 @@ nfs_request(struct vnode *vp, struct mbuf *mrest, int procnum,
return (ESTALE);
}
nmp = VFSTONFS(vp->v_mount);
if ((nmp->nm_flag & NFSMNT_NFSV4) != 0)
return nfs4_request(vp, mrest, procnum, td, cred, mrp, mdp, dposp);
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
rep->r_nmp = nmp;
rep->r_vp = vp;
@ -1235,6 +1241,8 @@ nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td)
struct proc *p;
sigset_t tmpset;
if ((nmp->nm_flag & NFSMNT_NFSV4) != 0)
return nfs4_sigintr(nmp, rep, td);
if (rep && (rep->r_flags & R_SOFTTERM))
return (EINTR);
/* Terminate all requests while attempting a forced unmount. */

View File

@ -67,6 +67,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <vm/uma.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
@ -761,6 +763,10 @@ nfs_invaldir(struct vnode *vp)
if (vp->v_type != VDIR)
panic("nfs: invaldir not dir");
#endif
if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NFSV4) != 0) {
nfs4_invaldir(vp);
return;
}
np->n_direofoffset = 0;
np->n_cookieverf.nfsuquad[0] = 0;
np->n_cookieverf.nfsuquad[1] = 0;

View File

@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$");
#include <net/route.h>
#include <netinet/in.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>

View File

@ -69,6 +69,8 @@ __FBSDID("$FreeBSD$");
#include <fs/fifofs/fifo.h>
#include <rpc/rpcclnt.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
@ -2397,6 +2399,7 @@ nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
M_NFSREQ, M_WAITOK);
sp->s_cred = crhold(cnp->cn_cred);
sp->s_dvp = dvp;
sp->s_removeit = nfs_removeit;
VREF(dvp);
/* Fudge together a funny name */

View File

@ -95,5 +95,7 @@ struct nfs_args {
#define NFSMNT_ACDIRMIN 0x00100000
#define NFSMNT_ACDIRMAX 0x00200000
#define NFSMNT_NOLOCKD 0x00400000 /* Locks are local */
#define NFSMNT_NFSV4 0x00800000 /* Use NFS Version 4 protocol */
#define NFSMNT_HASWRITEVERF 0x01000000 /* NFSv4 Write verifier */
#endif

View File

@ -147,6 +147,17 @@ do { \
} \
} while (0)
#define nfsm_request_mnt(n, t, p, c) \
do { \
error = nfs4_request_mnt((n), mreq, (t), (p), (c), &mrep, &md, &dpos); \
if (error != 0) { \
if (error & NFSERR_RETERR) \
error &= ~NFSERR_RETERR; \
else \
goto nfsmout; \
} \
} while (0)
/* *********************************** */
/* Reply interpretation phase macros */

View File

@ -50,8 +50,9 @@ struct nfsmount {
int nm_state; /* Internal state flags */
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 */
u_char nm_fh[NFSX_V4FH]; /* File handle of root dir */
int nm_fhsize; /* Size of root file handle */
struct rpcclnt nm_rpcclnt; /* rpc state */
struct socket *nm_so; /* Rpc socket */
int nm_sotype; /* Type of socket */
int nm_soproto; /* and protocol */
@ -79,6 +80,12 @@ struct nfsmount {
short nm_bufqwant; /* process wants to add to the queue */
int nm_bufqiods; /* number of iods processing queue */
u_int64_t nm_maxfilesize; /* maximum file size */
/* NFSv4 */
uint64_t nm_clientid;
fsid_t nm_fsid;
u_int nm_lease_time;
time_t nm_last_renewal;
};
#if defined(_KERNEL)

View File

@ -51,6 +51,7 @@
struct sillyrename {
struct ucred *s_cred;
struct vnode *s_dvp;
int (*s_removeit)(struct sillyrename *sp);
long s_namlen;
char s_name[20];
};
@ -68,9 +69,15 @@ struct sillyrename {
struct nfsdmap {
LIST_ENTRY(nfsdmap) ndm_list;
int ndm_eocookie;
nfsuint64 ndm_cookies[NFSNUMCOOKIES];
union {
nfsuint64 ndmu3_cookies[NFSNUMCOOKIES];
uint64_t ndmu4_cookies[NFSNUMCOOKIES];
} ndm_un1;
};
#define ndm_cookies ndm_un1.ndmu3_cookies
#define ndm4_cookies ndm_un1.ndmu4_cookies
/*
* The nfsnode is the nfs equivalent to ufs's inode. Any similarity
* is purely coincidental.
@ -99,11 +106,13 @@ struct nfsnode {
time_t n_expiry; /* Lease expiry time */
nfsfh_t *n_fhp; /* NFS File Handle */
struct vnode *n_vnode; /* associated vnode */
struct vnode *n_dvp; /* parent 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) */
u_char nd4_cookieverf[NFSX_V4VERF];
} n_un1;
union {
struct timespec nf_mtim;
@ -117,12 +126,21 @@ struct nfsnode {
short n_flag; /* Flag for locking.. */
nfsfh_t n_fh; /* Small File Handle */
struct lock n_rslock;
struct nfs4_fctx n_rfc;
struct nfs4_fctx n_wfc;
/*
* The last component name is needed for the NFSv4 OPEN
* operation.
*/
u_char *n_name;
uint32_t n_namelen;
};
#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 n4_cookieverf n_un1.nd4_cookieverf
#define n_direofoffset n_un2.nd_direof
#define n_cookies n_un3.nd_cook
@ -137,6 +155,8 @@ struct nfsnode {
#define NACC 0x0100 /* Special file accessed */
#define NUPD 0x0200 /* Special file updated */
#define NCHG 0x0400 /* Special file times changed */
#define NCREATED 0x0800 /* Opened by nfs_create() */
#define NTRUNCATE 0x1000 /* Opened by nfs_setattr() */
/*
* Convert between nfsnode pointers and vnode pointers
@ -182,6 +202,10 @@ extern vop_t **fifo_nfsnodeop_p;
extern vop_t **nfs_vnodeop_p;
extern vop_t **spec_nfsnodeop_p;
extern vop_t **fifo_nfs4nodeop_p;
extern vop_t **nfs4_vnodeop_p;
extern vop_t **spec_nfs4nodeop_p;
/*
* Prototypes for NFS vnode operations
*/
@ -193,9 +217,12 @@ int nfs_reclaim(struct vop_reclaim_args *);
/* other stuff */
int nfs_removeit(struct sillyrename *);
int nfs4_removeit(struct sillyrename *);
int nfs_nget(struct mount *, nfsfh_t *, int, struct nfsnode **);
nfsuint64 *nfs_getcookie(struct nfsnode *, off_t, int);
uint64_t *nfs4_getcookie(struct nfsnode *, off_t, int);
void nfs_invaldir(struct vnode *);
void nfs4_invaldir(struct vnode *);
#endif /* _KERNEL */

2083
sys/rpc/rpcclnt.c Normal file

File diff suppressed because it is too large Load Diff

358
sys/rpc/rpcclnt.h Normal file
View File

@ -0,0 +1,358 @@
/* $FreeBSD$ */
/* $OpenBSD: nfsmount.h,v 1.11 2002/03/14 01:27:13 millert Exp $ */
/* $NetBSD: nfsmount.h,v 1.10 1996/02/18 11:54:03 fvdl Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
/*
* 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 _RPCCLNT_H_
#define _RPCCLNT_H_
#include <sys/types.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#ifdef __OpenBSD__
#define RPC_EXEC_CTX struct proc *
#else
#define RPC_EXEC_CTX struct thread *
#endif
#ifdef RPCCLNT_DEBUG
#define RPCDEBUG(args...) do{ \
if(rpcdebugon != 0){ \
printf("%s(): ", __FUNCTION__);\
printf(args); \
printf("\n"); \
}}while(0)
#else
#define RPCDEBUG(args...)
#endif
/* from nfs/nfs.h */
#define RPC_TICKINTVL 5
/* from nfs/nfsproto.h */
#define RPC_MAXDATA 32768
#define RPC_MAXPKTHDR 404
#define RPC_MAXPACKET (RPC_MAXPKTHDR + RPC_MAXDATA)
#define RPCX_UNSIGNED 4
/* defines for rpcclnt's rc_flags
XXX these flags came from the NFSMNT_* flags in OpenBSD's sys/mount.h */
#define RPCCLNT_SOFT 0x001 /* soft mount (hard is details) */
#define RPCCLNT_INT 0x002 /* allow interrupts on hard mounts */
#define RPCCLNT_NOCONN 0x004 /* dont connect the socket (udp) */
#define RPCCLNT_DUMBTIMR 0x010
#define RPCCLNT_SNDLOCK 0x100
#define RPCCLNT_WANTSND 0x200
#define RPCCLNT_RCVLOCK 0x400
#define RPCCLNT_WANTRCV 0x800
/* 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 */
#define RPC_HZ (hz / rpcclnt_ticks) /* Ticks/sec */
#define RPC_TIMEO (1 * RPC_HZ) /* Default timeout = 1 second */
#define RPC_MAXREXMIT 100 /* Stop counting after this many */
#define RPCIGNORE_SOERROR(s, e) \
((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
((s) & PR_CONNREQUIRED) == 0)
#define RPCINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \
sigmask(SIGHUP)|sigmask(SIGQUIT))
#define RPCMADV(m, s) (m)->m_data += (s)
#define RPCAUTH_ROOTCREDS NULL
#define RPCCLNTINT_SIGMASK(set) \
(SIGISMEMBER(set, SIGINT) || SIGISMEMBER(set, SIGTERM) || \
SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \
SIGISMEMBER(set, SIGQUIT))
#define fxdr_unsigned(t, v) ((t)ntohl((int32_t)(v)))
#define txdr_unsigned(v) (htonl((int32_t)(v)))
/* global rpcstats
* XXX should be per rpcclnt */
struct rpcstats {
int rpcretries;
int rpcrequests;
int rpctimeouts;
int rpcunexpected;
int rpcinvalid;
};
struct rpc_program {
u_int32_t prog_id;
u_int32_t prog_version;
char * prog_name;
};
struct rpc_auth {
unsigned int auth_type;
};
struct rpctask {
TAILQ_ENTRY(rpctask) r_chain;
struct mbuf *r_mreq;
struct mbuf *r_mrep;
struct mbuf *r_md;
caddr_t r_dpos;
struct rpcclnt *r_rpcclnt;
u_int32_t 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 */
RPC_EXEC_CTX r_td;
};
struct rpc_reply {
struct {
u_int32_t type;
u_int32_t status;
/* used only when reply == RPC_MSGDENIED and
* status == RPC_AUTHERR */
u_int32_t autherr;
/* rpc mismatch info if reply == RPC_MSGDENIED and
* status == RPC_MISMATCH */
struct {
u_int32_t low;
u_int32_t high;
} mismatch_info;
} stat;
/* head of the mbuf chain */
struct mbuf * mrep;
/* mbuf and position of the verification opaque data
* note that this is only valid when stat.reply == RPC_MSGACCEPTED */
u_int32_t verf_type;
u_int32_t verf_size;
struct mbuf * verf_md;
caddr_t verf_dpos;
/* mbuf and postion of the result of the rpc request */
struct mbuf * result_md;
caddr_t result_dpos;
};
/*
* RPC Client connection context.
* One allocated on every NFS mount.
* Holds RPC specific information for mount.
*/
/* XXX: please note that all pointer type variables are just set (not copied),
* so it is up to the user to free these values */
struct rpcclnt {
int rc_flag; /* For RPCCLNT_* flags */
int rc_wsize; /* Max size of the request data */
int rc_rsize; /* Max size of the response data */
struct sockaddr *rc_name;
struct socket *rc_so; /* Rpc socket */
int rc_sotype; /* Type of socket */
int rc_soproto; /* and protocol */
int rc_soflags; /* pr_flags for socket protocol */
int rc_timeo; /* Init timer for NFSMNT_DUMBTIMR */
int rc_retry; /* Max retries */
int rc_srtt[4]; /* Timers for rpcs */
int rc_sdrtt[4];
int rc_sent; /* Request send count */
int rc_cwnd; /* Request send window */
int rc_timeouts; /* Request timeouts */
/* XXX: this is not being set!!!! */
int rc_deadthresh; /* Threshold of timeouts-->dead server*/
/* authentication: */
/* currently can be RPCAUTH_NULL, RPCAUTH_KERBV4, RPCAUTH_UNIX */
/* should be kept in XDR form */
int rc_authtype; /* Authenticator type */
#if 0
/* RPCAUTH_KERB4 */
int rc_authlen; /* and length */
char *rc_authstr; /* Authenticator string */
int rc_verflen;
char *rc_verfstr; /* and the verifier */
#endif
/* RPCAUTH_UNIX*/
struct rpc_auth * rc_auth; /* authentication */
#if 0
/* stored in XDR form (network byte order) */
unsigned int rc_progid; /* program id */
unsigned int rc_progvers; /* program version */
/* name of server for log messages */
const char *rc_servername; /* for printing error messages */
#else
struct rpc_program * rc_prog;
#endif
/* XXX: this should be removed */
int rc_proctlen; /* if == 0 then rc_proct == NULL */
int * rc_proct;
};
#ifdef __OpenBSD__
extern struct pool rpcreply_pool;
extern struct pool rpcclnt_pool;
#else
/* MALLOC_DECLARE(M_RPC); */
#endif
extern int rpcdebugon;
#ifdef __OpenBSD__
#define rpcclnt_get(X) \
do { \
(X) = pool_get(&rpcclnt_pool, PR_WAITOK); \
bzero((X), sizeof(struct rpcclnt)); \
}while(0)
#define rpcclnt_put(X) \
do { \
if ((X) != NULL){ \
pool_put(&rpcclnt_pool, (X)); \
}}while(0)
#else /* !__OpenBSD__ */
/* usage count for module (un)loading */
extern unsigned int rpcclnt_usage;
extern struct mtx rpcclnt_usage_mutex;
void rpcclnt_create(struct rpcclnt ** rpc);
void rpcclnt_destroy(struct rpcclnt * rpc);
#define rpcclnt_get(X) rpcclnt_create(&(X))
#define rpcclnt_put(X) rpcclnt_destroy(X)
#ifdef RPCCLNT_TEST
struct rpcclnt_test_args {
int nothing;
};
int rpcclnt_test(struct thread *, struct rpcclnt_test_args *);
#define RPC_RETURN(X) do { RPCDEBUG("returning %d", X); return X; }while(0)
#endif /* RPCCLNT_TEST */
#endif /* !__OpenBSD__ */
void rpcclnt_init(void);
void rpcclnt_uninit(void);
#if 0
int rpcclnt_setup(struct rpcclnt *, int, struct sockaddr *, int, int, int, int, const char *, int, int);
#endif
int rpcclnt_setup(struct rpcclnt *, struct rpc_program *, struct sockaddr *, int, int, struct rpc_auth *, int, int, int);
int rpcclnt_connect(struct rpcclnt *, RPC_EXEC_CTX td);
int rpcclnt_reconnect(struct rpctask *, RPC_EXEC_CTX td);
void rpcclnt_disconnect(struct rpcclnt *);
void rpcclnt_safedisconnect(struct rpcclnt *);
void rpcclnt_setauth(struct rpcclnt *, u_int32_t, u_int32_t, char *, u_int32_t, char *, struct ucred *);
int rpcclnt_request(struct rpcclnt *, struct mbuf *, int, RPC_EXEC_CTX, struct ucred *, struct rpc_reply *);
int rpcclnt_err(struct rpc_reply *);
int rpcclnt_cancelreqs(struct rpcclnt *);
int rpcclnt_sigintr(struct rpcclnt *, struct rpctask *, RPC_EXEC_CTX);
#endif /* _RPCCLNT_H_ */

133
sys/rpc/rpcm_subs.h Normal file
View File

@ -0,0 +1,133 @@
/* $FreeBSD$ */
/* $OpenBSD: nfsm_subs.h,v 1.11 2000/01/05 20:50:52 millert Exp $ */
/* $NetBSD: nfsm_subs.h,v 1.10 1996/03/20 21:59:56 fvdl Exp $ */
/*
* copyright (c) 2003
* the regents of the university of michigan
* all rights reserved
*
* permission is granted to use, copy, create derivative works and redistribute
* this software and such derivative works for any purpose, so long as the name
* of the university of michigan is not used in any advertising or publicity
* pertaining to the use or distribution of this software without specific,
* written prior authorization. if the above copyright notice or any other
* identification of the university of michigan is included in any copy of any
* portion of this software, then the disclaimer below must also be included.
*
* this software is provided as is, without representation from the university
* of michigan as to its fitness for any purpose, and without warranty by the
* university of michigan of any kind, either express or implied, including
* without limitation the implied warranties of merchantability and fitness for
* a particular purpose. the regents of the university of michigan shall not be
* liable for any damages, including special, indirect, incidental, or
* consequential damages, with respect to any claim arising out of or in
* connection with the use of the software, even if it has been or is hereafter
* advised of the possibility of such damages.
*/
/*
* 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 _RPC_RPCM_SUBS_H_
#define _RPC_RPCM_SUBS_H_
/*
* Now for the macros that do the simple stuff and call the functions
* for the hard stuff.
* These macros use several vars. declared in rpcm_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 rpcm_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 rpcm_dissect(a, c, s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
(a) = (c)(dpos); \
dpos += (s); \
} else if ((t1 = rpcm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \
error = t1; \
goto rpcmout; \
} else { \
(a) = (c)cp2; \
} }
#if 0
#define rpcm_mtouio(p,s) \
if ((s) > 0 && \
(t1 = rpcm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \
error = t1; \
goto rpcmout; \
}
#endif
#define rpcm_rndup(a) (((a)+3)&(~0x3))
#define rpcm_adv(s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else if ((t1 = rpc_adv(&md, &dpos, (s), t1)) != 0) { \
error = t1; \
goto rpcmout; \
} }
#define RPCMADV(m, s) (m)->m_data += (s)
#endif /* _RPC_RPCM_SUBS_H_ */

101
sys/rpc/rpcv2.h Normal file
View File

@ -0,0 +1,101 @@
/* $FreeBSD$ */
/* $OpenBSD: rpcv2.h,v 1.5 2002/06/11 15:45:44 hin Exp $ */
/* $NetBSD: rpcv2.h,v 1.8 1996/02/18 11:54:11 fvdl Exp $ */
/*
* 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_MAXSIZ 400
#define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */
#define RPCAUTH_UNIXGIDS 16
/* Rpc Constants */
/* msg type */
#define RPC_CALL 0
#define RPC_REPLY 1
/* reply stat */
#define RPC_MSGACCEPTED 0
#define RPC_MSGDENIED 1
/* accepted stat: */
#define RPC_SUCCESS 0
#define RPC_PROGUNAVAIL 1
#define RPC_PROGMISMATCH 2
#define RPC_PROCUNAVAIL 3
#define RPC_GARBAGE 4 /* I like this one */
#define RPC_SYSTEMERR 5
/* reject stat */
#define RPC_MISMATCH 0
#define RPC_AUTHERR 1
/* Authentication failures */
#define AUTH_OK 0
#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
typedef u_char NFSKERBKEY_T[2];
#endif