University of Michigan's Citi NFSv4 kernel client code.
Submitted by: Jim Rees <rees@umich.edu>
This commit is contained in:
parent
db049820e1
commit
1bf8720450
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=122698
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
260
sys/nfs4client/nfs4.h
Normal 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
451
sys/nfs4client/nfs4_dev.c
Normal 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
65
sys/nfs4client/nfs4_dev.h
Normal 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
513
sys/nfs4client/nfs4_idmap.c
Normal 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;
|
||||
}
|
64
sys/nfs4client/nfs4_idmap.h
Normal file
64
sys/nfs4client/nfs4_idmap.h
Normal 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__ */
|
340
sys/nfs4client/nfs4_socket.c
Normal file
340
sys/nfs4client/nfs4_socket.c
Normal 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
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
34
sys/nfs4client/nfs4_vfs.h
Normal 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 */
|
150
sys/nfs4client/nfs4_vfs_subs.c
Normal file
150
sys/nfs4client/nfs4_vfs_subs.c
Normal 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);
|
||||
}
|
||||
}
|
938
sys/nfs4client/nfs4_vfsops.c
Normal file
938
sys/nfs4client/nfs4_vfsops.c
Normal 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
33
sys/nfs4client/nfs4_vn.h
Normal 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 */
|
223
sys/nfs4client/nfs4_vn_subs.c
Normal file
223
sys/nfs4client/nfs4_vn_subs.c
Normal 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
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
498
sys/nfs4client/nfs4m_subs.h
Normal 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 */
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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 *);
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
2083
sys/rpc/rpcclnt.c
Normal file
File diff suppressed because it is too large
Load Diff
358
sys/rpc/rpcclnt.h
Normal file
358
sys/rpc/rpcclnt.h
Normal 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
133
sys/rpc/rpcm_subs.h
Normal 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
101
sys/rpc/rpcv2.h
Normal 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
|
Loading…
Reference in New Issue
Block a user