summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/head/rpcsvc/nfs4_prot.x2932
-rw-r--r--usr/src/uts/common/Makefile.files6
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_attr.c3
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_dispatch.c100
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv.c422
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv_attr.c62
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_state.c170
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_xdr.c227
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4x_dispatch.c177
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4x_srv.c1250
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4x_state.c576
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4x_xdr.c2935
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_server.c5
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_stats.c21
-rw-r--r--usr/src/uts/common/fs/nfs/nfs_subr.c10
-rw-r--r--usr/src/uts/common/nfs/Makefile2
-rw-r--r--usr/src/uts/common/nfs/nfs.h2
-rw-r--r--usr/src/uts/common/nfs/nfs4.h79
-rw-r--r--usr/src/uts/common/nfs/nfs4_attr.h17
-rw-r--r--usr/src/uts/common/nfs/nfs4_kprot.h2072
-rw-r--r--usr/src/uts/common/nfs/nfs4x.h195
21 files changed, 10518 insertions, 745 deletions
diff --git a/usr/src/head/rpcsvc/nfs4_prot.x b/usr/src/head/rpcsvc/nfs4_prot.x
index 24460cca7b..2618150477 100644
--- a/usr/src/head/rpcsvc/nfs4_prot.x
+++ b/usr/src/head/rpcsvc/nfs4_prot.x
@@ -1,12 +1,12 @@
/*
- * This file was machine generated for [RFC7530].
+ * This file was machine generated for [RFC7862].
*
- * Last updated Tue Mar 10 11:51:21 PDT 2015.
+ * Last updated Sun Mar 13 10:58:40 PDT 2016
*/
/*
- * Copyright (c) 2015 IETF Trust and the persons identified
- * as authors of the code. All rights reserved.
+ * Copyright (c) 2016 IETF Trust and the persons identified
+ * as the authors. All rights reserved.
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
@@ -41,23 +41,30 @@
* 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.
+
*/
/*
- * This code was derived from RFC 7531.
+ * This code was derived from RFC 7863.
*/
/*
- * nfs4_prot.x
- *
+ * nfsv42.x
*/
+%#ifndef _AUTH_SYS_DEFINE_FOR_NFSv42
+%#define _AUTH_SYS_DEFINE_FOR_NFSv42
+%#include <rpc/auth_sys.h>
+%typedef struct authsys_parms authsys_parms;
+%#endif /* _AUTH_SYS_DEFINE_FOR_NFSv42 */
+
/*
* Basic typedefs for RFC 1832 data type definitions
*/
+
/*
- * typedef int int32_t;
- * typedef unsigned int uint32_t;
+ * typedef int int32_t;
+ * typedef unsigned int uint32_t;
* typedef hyper int64_t;
* typedef unsigned hyper uint64_t;
*/
@@ -69,101 +76,164 @@ const NFS4_FHSIZE = 128;
const NFS4_VERIFIER_SIZE = 8;
const NFS4_OTHER_SIZE = 12;
const NFS4_OPAQUE_LIMIT = 1024;
+const NFS4_SESSIONID_SIZE = 16;
const NFS4_INT64_MAX = 0x7fffffffffffffff;
const NFS4_UINT64_MAX = 0xffffffffffffffff;
const NFS4_INT32_MAX = 0x7fffffff;
const NFS4_UINT32_MAX = 0xffffffff;
+const NFS4_MAXFILELEN = 0xffffffffffffffff;
+const NFS4_MAXFILEOFF = 0xfffffffffffffffe;
+
/*
* File types
*/
enum nfs_ftype4 {
- NF4REG = 1, /* Regular File */
- NF4DIR = 2, /* Directory */
- NF4BLK = 3, /* Special File - block device */
- NF4CHR = 4, /* Special File - character device */
- NF4LNK = 5, /* Symbolic Link */
- NF4SOCK = 6, /* Special File - socket */
- NF4FIFO = 7, /* Special File - fifo */
- NF4ATTRDIR
- = 8, /* Attribute Directory */
- NF4NAMEDATTR
- = 9 /* Named Attribute */
+ NF4REG = 1, /* Regular File */
+ NF4DIR = 2, /* Directory */
+ NF4BLK = 3, /* Special File -- block device */
+ NF4CHR = 4, /* Special File -- character device */
+ NF4LNK = 5, /* Symbolic Link */
+ NF4SOCK = 6, /* Special File -- socket */
+ NF4FIFO = 7, /* Special File -- fifo */
+ NF4ATTRDIR = 8, /* Attribute Directory */
+ NF4NAMEDATTR = 9 /* Named Attribute */
};
/*
* Error status
*/
enum nfsstat4 {
- NFS4_OK = 0, /* everything is okay */
- NFS4ERR_PERM = 1, /* caller not privileged */
- NFS4ERR_NOENT = 2, /* no such file/directory */
- NFS4ERR_IO = 5, /* hard I/O error */
- NFS4ERR_NXIO = 6, /* no such device */
- NFS4ERR_ACCESS = 13, /* access denied */
- NFS4ERR_EXIST = 17, /* file already exists */
- NFS4ERR_XDEV = 18, /* different file systems */
- /* Unused/reserved 19 */
- NFS4ERR_NOTDIR = 20, /* should be a directory */
- NFS4ERR_ISDIR = 21, /* should not be directory */
- NFS4ERR_INVAL = 22, /* invalid argument */
- NFS4ERR_FBIG = 27, /* file exceeds server max */
- NFS4ERR_NOSPC = 28, /* no space on file system */
- NFS4ERR_ROFS = 30, /* read-only file system */
- NFS4ERR_MLINK = 31, /* too many hard links */
- NFS4ERR_NAMETOOLONG = 63, /* name exceeds server max */
- NFS4ERR_NOTEMPTY = 66, /* directory not empty */
- NFS4ERR_DQUOT = 69, /* hard quota limit reached */
- NFS4ERR_STALE = 70, /* file no longer exists */
- NFS4ERR_BADHANDLE = 10001,/* Illegal filehandle */
- NFS4ERR_BAD_COOKIE = 10003,/* READDIR cookie is stale */
- NFS4ERR_NOTSUPP = 10004,/* operation not supported */
- NFS4ERR_TOOSMALL = 10005,/* response limit exceeded */
- NFS4ERR_SERVERFAULT = 10006,/* undefined server error */
- NFS4ERR_BADTYPE = 10007,/* type invalid for CREATE */
- NFS4ERR_DELAY = 10008,/* file "busy" - retry */
- NFS4ERR_SAME = 10009,/* nverify says attrs same */
- NFS4ERR_DENIED = 10010,/* lock unavailable */
- NFS4ERR_EXPIRED = 10011,/* lock lease expired */
- NFS4ERR_LOCKED = 10012,/* I/O failed due to lock */
- NFS4ERR_GRACE = 10013,/* in grace period */
- NFS4ERR_FHEXPIRED = 10014,/* filehandle expired */
- NFS4ERR_SHARE_DENIED = 10015,/* share reserve denied */
- NFS4ERR_WRONGSEC = 10016,/* wrong security flavor */
- NFS4ERR_CLID_INUSE = 10017,/* clientid in use */
- NFS4ERR_RESOURCE = 10018,/* resource exhaustion */
- NFS4ERR_MOVED = 10019,/* file system relocated */
- NFS4ERR_NOFILEHANDLE = 10020,/* current FH is not set */
- NFS4ERR_MINOR_VERS_MISMATCH = 10021,/* minor vers not supp */
- NFS4ERR_STALE_CLIENTID = 10022,/* server has rebooted */
- NFS4ERR_STALE_STATEID = 10023,/* server has rebooted */
- NFS4ERR_OLD_STATEID = 10024,/* state is out of sync */
- NFS4ERR_BAD_STATEID = 10025,/* incorrect stateid */
- NFS4ERR_BAD_SEQID = 10026,/* request is out of seq. */
- NFS4ERR_NOT_SAME = 10027,/* verify - attrs not same */
- NFS4ERR_LOCK_RANGE = 10028,/* lock range not supported */
- NFS4ERR_SYMLINK = 10029,/* should be file/directory */
- NFS4ERR_RESTOREFH = 10030,/* no saved filehandle */
- NFS4ERR_LEASE_MOVED = 10031,/* some file system moved */
- NFS4ERR_ATTRNOTSUPP = 10032,/* recommended attr not sup */
- NFS4ERR_NO_GRACE = 10033,/* reclaim outside of grace */
- NFS4ERR_RECLAIM_BAD = 10034,/* reclaim error at server */
- NFS4ERR_RECLAIM_CONFLICT = 10035,/* conflict on reclaim */
- NFS4ERR_BADXDR = 10036,/* XDR decode failed */
- NFS4ERR_LOCKS_HELD = 10037,/* file locks held at CLOSE */
- NFS4ERR_OPENMODE = 10038,/* conflict in OPEN and I/O */
- NFS4ERR_BADOWNER = 10039,/* owner translation bad */
- NFS4ERR_BADCHAR = 10040,/* UTF-8 char not supported */
- NFS4ERR_BADNAME = 10041,/* name not supported */
- NFS4ERR_BAD_RANGE = 10042,/* lock range not supported */
- NFS4ERR_LOCK_NOTSUPP = 10043,/* no atomic up/downgrade */
- NFS4ERR_OP_ILLEGAL = 10044,/* undefined operation */
- NFS4ERR_DEADLOCK = 10045,/* file locking deadlock */
- NFS4ERR_FILE_OPEN = 10046,/* open file blocks op. */
- NFS4ERR_ADMIN_REVOKED = 10047,/* lock-owner state revoked */
- NFS4ERR_CB_PATH_DOWN = 10048 /* callback path down */
+ NFS4_OK = 0, /* everything is okay */
+ NFS4ERR_PERM = 1, /* caller not privileged */
+ NFS4ERR_NOENT = 2, /* no such file/directory */
+ NFS4ERR_IO = 5, /* hard I/O error */
+ NFS4ERR_NXIO = 6, /* no such device */
+ NFS4ERR_ACCESS = 13, /* access denied */
+ NFS4ERR_EXIST = 17, /* file already exists */
+ NFS4ERR_XDEV = 18, /* different file systems */
+
+/*
+ * Please do not allocate value 19; it was used in NFSv3,
+ * and we do not want a value in NFSv3 to have a different
+ * meaning in NFSv4.x.
+ */
+
+ NFS4ERR_NOTDIR = 20, /* should be a directory */
+ NFS4ERR_ISDIR = 21, /* should not be a directory */
+ NFS4ERR_INVAL = 22, /* invalid argument */
+ NFS4ERR_FBIG = 27, /* file exceeds server max */
+ NFS4ERR_NOSPC = 28, /* no space on file system */
+ NFS4ERR_ROFS = 30, /* read-only file system */
+ NFS4ERR_MLINK = 31, /* too many hard links */
+ NFS4ERR_NAMETOOLONG = 63, /* name exceeds server max */
+ NFS4ERR_NOTEMPTY = 66, /* directory not empty */
+ NFS4ERR_DQUOT = 69, /* hard quota limit reached */
+ NFS4ERR_STALE = 70, /* file no longer exists */
+ NFS4ERR_BADHANDLE = 10001, /* illegal filehandle */
+ NFS4ERR_BAD_COOKIE = 10003, /* READDIR cookie is stale */
+ NFS4ERR_NOTSUPP = 10004, /* operation not supported */
+ NFS4ERR_TOOSMALL = 10005, /* response limit exceeded */
+ NFS4ERR_SERVERFAULT = 10006, /* undefined server error */
+ NFS4ERR_BADTYPE = 10007, /* type invalid for CREATE */
+ NFS4ERR_DELAY = 10008, /* file "busy" -- retry */
+ NFS4ERR_SAME = 10009, /* nverify says attrs same */
+ NFS4ERR_DENIED = 10010, /* lock unavailable */
+ NFS4ERR_EXPIRED = 10011, /* lock lease expired */
+ NFS4ERR_LOCKED = 10012, /* I/O failed due to lock */
+ NFS4ERR_GRACE = 10013, /* in grace period */
+ NFS4ERR_FHEXPIRED = 10014, /* filehandle expired */
+ NFS4ERR_SHARE_DENIED = 10015, /* share reserve denied */
+ NFS4ERR_WRONGSEC = 10016, /* wrong security flavor */
+ NFS4ERR_CLID_INUSE = 10017, /* client ID in use */
+
+ /* NFS4ERR_RESOURCE is not a valid error in NFSv4.1. */
+ NFS4ERR_RESOURCE = 10018, /* resource exhaustion */
+
+ NFS4ERR_MOVED = 10019, /* file system relocated */
+ NFS4ERR_NOFILEHANDLE = 10020, /* current FH is not set */
+ NFS4ERR_MINOR_VERS_MISMATCH= 10021, /* minor vers not supp */
+ NFS4ERR_STALE_CLIENTID = 10022, /* server has rebooted */
+ NFS4ERR_STALE_STATEID = 10023, /* server has rebooted */
+ NFS4ERR_OLD_STATEID = 10024, /* state is out of sync */
+ NFS4ERR_BAD_STATEID = 10025, /* incorrect stateid */
+ NFS4ERR_BAD_SEQID = 10026, /* request is out of seq. */
+ NFS4ERR_NOT_SAME = 10027, /* verify -- attrs not same */
+ NFS4ERR_LOCK_RANGE = 10028, /* overlapping lock range */
+ NFS4ERR_SYMLINK = 10029, /* should be file/directory */
+ NFS4ERR_RESTOREFH = 10030, /* no saved filehandle */
+ NFS4ERR_LEASE_MOVED = 10031, /* some file system moved */
+ NFS4ERR_ATTRNOTSUPP = 10032, /* recommended attr not supp */
+ NFS4ERR_NO_GRACE = 10033, /* reclaim outside of grace */
+ NFS4ERR_RECLAIM_BAD = 10034, /* reclaim error at server */
+ NFS4ERR_RECLAIM_CONFLICT= 10035, /* conflict on reclaim */
+ NFS4ERR_BADXDR = 10036, /* XDR decode failed */
+ NFS4ERR_LOCKS_HELD = 10037, /* file locks held at CLOSE */
+ NFS4ERR_OPENMODE = 10038, /* conflict in OPEN and I/O */
+ NFS4ERR_BADOWNER = 10039, /* owner translation bad */
+ NFS4ERR_BADCHAR = 10040, /* UTF-8 char not supported */
+ NFS4ERR_BADNAME = 10041, /* name not supported */
+ NFS4ERR_BAD_RANGE = 10042, /* lock range not supported */
+ NFS4ERR_LOCK_NOTSUPP = 10043, /* no atomic up/downgrade */
+ NFS4ERR_OP_ILLEGAL = 10044, /* undefined operation */
+ NFS4ERR_DEADLOCK = 10045, /* file-locking deadlock */
+ NFS4ERR_FILE_OPEN = 10046, /* open file blocks op */
+ NFS4ERR_ADMIN_REVOKED = 10047, /* lock-owner state revoked */
+ NFS4ERR_CB_PATH_DOWN = 10048, /* callback path down */
+
+ /* NFSv4.1 errors start here. */
+
+ NFS4ERR_BADIOMODE = 10049,
+ NFS4ERR_BADLAYOUT = 10050,
+ NFS4ERR_BAD_SESSION_DIGEST = 10051,
+ NFS4ERR_BADSESSION = 10052,
+ NFS4ERR_BADSLOT = 10053,
+ NFS4ERR_COMPLETE_ALREADY = 10054,
+ NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
+ NFS4ERR_DELEG_ALREADY_WANTED = 10056,
+ NFS4ERR_BACK_CHAN_BUSY = 10057, /* backchan reqs outstanding */
+ NFS4ERR_LAYOUTTRYLATER = 10058,
+ NFS4ERR_LAYOUTUNAVAILABLE = 10059,
+ NFS4ERR_NOMATCHING_LAYOUT = 10060,
+ NFS4ERR_RECALLCONFLICT = 10061,
+ NFS4ERR_UNKNOWN_LAYOUTTYPE = 10062,
+ NFS4ERR_SEQ_MISORDERED = 10063, /* unexpected seq. ID in req */
+ NFS4ERR_SEQUENCE_POS = 10064, /* [CB_]SEQ. op not 1st op */
+ NFS4ERR_REQ_TOO_BIG = 10065, /* request too big */
+ NFS4ERR_REP_TOO_BIG = 10066, /* reply too big */
+ NFS4ERR_REP_TOO_BIG_TO_CACHE =10067, /* rep. not all cached */
+ NFS4ERR_RETRY_UNCACHED_REP =10068, /* retry + rep. uncached */
+ NFS4ERR_UNSAFE_COMPOUND =10069, /* retry/recovery too hard */
+ NFS4ERR_TOO_MANY_OPS = 10070, /* too many ops in [CB_]COMP */
+ NFS4ERR_OP_NOT_IN_SESSION =10071, /* op needs [CB_]SEQ. op */
+ NFS4ERR_HASH_ALG_UNSUPP = 10072, /* hash alg. not supp */
+ /* Error 10073 is unused. */
+ NFS4ERR_CLIENTID_BUSY = 10074, /* client ID has state */
+ NFS4ERR_PNFS_IO_HOLE = 10075, /* IO to _SPARSE file hole */
+ NFS4ERR_SEQ_FALSE_RETRY= 10076, /* retry != original req */
+ NFS4ERR_BAD_HIGH_SLOT = 10077, /* req has bad highest_slot */
+ NFS4ERR_DEADSESSION = 10078, /* new req sent to dead sess */
+ NFS4ERR_ENCR_ALG_UNSUPP= 10079, /* encr alg. not supp */
+ NFS4ERR_PNFS_NO_LAYOUT = 10080, /* I/O without a layout */
+ NFS4ERR_NOT_ONLY_OP = 10081, /* addl ops not allowed */
+ NFS4ERR_WRONG_CRED = 10082, /* op done by wrong cred */
+ NFS4ERR_WRONG_TYPE = 10083, /* op on wrong type object */
+ NFS4ERR_DIRDELEG_UNAVAIL=10084, /* delegation not avail. */
+ NFS4ERR_REJECT_DELEG = 10085, /* cb rejected delegation */
+ NFS4ERR_RETURNCONFLICT = 10086, /* layout get before return */
+ NFS4ERR_DELEG_REVOKED = 10087, /* deleg./layout revoked */
+
+ /* NFSv4.2 errors start here. */
+
+ NFS4ERR_PARTNER_NOTSUPP= 10088, /* s2s not supported */
+ NFS4ERR_PARTNER_NO_AUTH= 10089, /* s2s not authorized */
+ NFS4ERR_UNION_NOTSUPP = 10090, /* arm of union not supp */
+ NFS4ERR_OFFLOAD_DENIED = 10091, /* dest not allowing copy */
+ NFS4ERR_WRONG_LFS = 10092, /* LFS not supported */
+ NFS4ERR_BADLABEL = 10093, /* incorrect label */
+ NFS4ERR_OFFLOAD_NO_REQS= 10094 /* dest not meeting reqs */
};
/*
@@ -178,11 +248,13 @@ typedef uint64_t length4;
typedef uint32_t mode4;
typedef uint64_t nfs_cookie4;
typedef opaque nfs_fh4<NFS4_FHSIZE>;
-typedef uint32_t nfs_lease4;
typedef uint64_t offset4;
typedef uint32_t qop4;
typedef opaque sec_oid4<>;
+typedef uint32_t sequenceid4;
typedef uint32_t seqid4;
+typedef opaque sessionid4[NFS4_SESSIONID_SIZE];
+typedef uint32_t slotid4;
typedef opaque utf8string<>;
typedef utf8string utf8str_cis;
typedef utf8string utf8str_cs;
@@ -191,9 +263,9 @@ typedef utf8str_cs component4;
typedef opaque linktext4<>;
typedef utf8string ascii_REQUIRED4;
typedef component4 pathname4<>;
-typedef uint64_t nfs_lockid4;
typedef opaque verifier4[NFS4_VERIFIER_SIZE];
-
+typedef string secret4<>;
+typedef uint32_t policy4;
/*
* Timeval
@@ -216,22 +288,30 @@ union settime4 switch (time_how4 set_it) {
};
+typedef uint32_t nfs_lease4;
+
/*
* File attribute definitions
*/
/*
- * FSID structure for major/minor
+ * File System ID (FSID) structure for major/minor
*/
struct fsid4 {
uint64_t major;
uint64_t minor;
};
-
/*
- * File system locations attribute for relocation/migration
+ * File system locations attribute
+ * for relocation/migration and
+ * related attributes
*/
+struct change_policy4 {
+ uint64_t cp_major;
+ uint64_t cp_minor;
+};
+
struct fs_location4 {
utf8str_cis server<>;
pathname4 rootpath;
@@ -242,14 +322,13 @@ struct fs_locations4 {
fs_location4 locations<>;
};
-
/*
- * Various Access Control Entry definitions
+ * Various Access Control Entry (ACE) definitions
*/
/*
- * Mask that indicates which Access Control Entries
- * are supported. Values for the fattr4_aclsupport attribute.
+ * Mask that indicates which ACEs are supported.
+ * Values for the fattr4_aclsupport attribute.
*/
const ACL4_SUPPORT_ALLOW_ACL = 0x00000001;
const ACL4_SUPPORT_DENY_ACL = 0x00000002;
@@ -261,7 +340,7 @@ typedef uint32_t acetype4;
/*
- * acetype4 values; others can be added as needed.
+ * acetype4 values. Others can be added as needed.
*/
const ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000;
const ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001;
@@ -273,7 +352,7 @@ const ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003;
/*
* ACE flag
*/
-typedef uint32_t aceflag4;
+typedef uint32_t aceflag4;
/*
@@ -286,6 +365,7 @@ const ACE4_INHERIT_ONLY_ACE = 0x00000008;
const ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010;
const ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020;
const ACE4_IDENTIFIER_GROUP = 0x00000040;
+const ACE4_INHERITED_ACE = 0x00000080;
@@ -310,6 +390,8 @@ const ACE4_EXECUTE = 0x00000020;
const ACE4_DELETE_CHILD = 0x00000040;
const ACE4_READ_ATTRIBUTES = 0x00000080;
const ACE4_WRITE_ATTRIBUTES = 0x00000100;
+const ACE4_WRITE_RETENTION = 0x00000200;
+const ACE4_WRITE_RETENTION_HOLD = 0x00000400;
const ACE4_DELETE = 0x00010000;
const ACE4_READ_ACL = 0x00020000;
@@ -319,7 +401,7 @@ const ACE4_SYNCHRONIZE = 0x00100000;
/*
- * ACE4_GENERIC_READ - defined as a combination of
+ * ACE4_GENERIC_READ -- defined as a combination of
* ACE4_READ_ACL |
* ACE4_READ_DATA |
* ACE4_READ_ATTRIBUTES |
@@ -329,7 +411,7 @@ const ACE4_SYNCHRONIZE = 0x00100000;
const ACE4_GENERIC_READ = 0x00120081;
/*
- * ACE4_GENERIC_WRITE - defined as a combination of
+ * ACE4_GENERIC_WRITE -- defined as a combination of
* ACE4_READ_ACL |
* ACE4_WRITE_DATA |
* ACE4_WRITE_ATTRIBUTES |
@@ -341,28 +423,52 @@ const ACE4_GENERIC_WRITE = 0x00160106;
/*
- * ACE4_GENERIC_EXECUTE - defined as a combination of
- * ACE4_READ_ACL
- * ACE4_READ_ATTRIBUTES
- * ACE4_EXECUTE
+ * ACE4_GENERIC_EXECUTE -- defined as a combination of
+ * ACE4_READ_ACL |
+ * ACE4_READ_ATTRIBUTES |
+ * ACE4_EXECUTE |
* ACE4_SYNCHRONIZE
*/
const ACE4_GENERIC_EXECUTE = 0x001200A0;
/*
- * Access Control Entry definition
+ * ACE definition
*/
struct nfsace4 {
- acetype4 type;
- aceflag4 flag;
- acemask4 access_mask;
- utf8str_mixed who;
+ acetype4 type;
+ aceflag4 flag;
+ acemask4 access_mask;
+ utf8str_mixed who;
};
/*
- * Field definitions for the fattr4_mode attribute
+ * Access Control List (ACL) flag
+ */
+
+typedef uint32_t aclflag4;
+
+/*
+ * ACL flag values
+ */
+const ACL4_AUTO_INHERIT = 0x00000001;
+const ACL4_PROTECTED = 0x00000002;
+const ACL4_DEFAULTED = 0x00000004;
+
+
+/*
+ * Version 4.1 ACL definition
+ */
+struct nfsacl41 {
+ aclflag4 na41_flag;
+ nfsace4 na41_aces<>;
+};
+
+
+/*
+ * Field definitions for the fattr4_mode
+ * and fattr4_mode_set_masked attributes
*/
const MODE4_SUID = 0x800; /* set user id on execution */
const MODE4_SGID = 0x400; /* set group id on execution */
@@ -379,15 +485,27 @@ const MODE4_XOTH = 0x001; /* execute permission: other */
/*
+ * Masked mode for the mode_set_masked attribute
+ */
+struct mode_masked4 {
+ mode4 mm_value_to_set; /* Values of bits
+ to set or reset
+ in mode */
+
+ mode4 mm_mask_bits; /* Mask of bits to
+ set or reset
+ in mode */
+};
+
+/*
* Special data/attribute associated with
- * file types NF4BLK and NF4CHR.
+ * file types NF4BLK and NF4CHR
*/
struct specdata4 {
- uint32_t specdata1; /* major device number */
- uint32_t specdata2; /* minor device number */
+ uint32_t specdata1; /* Major device number */
+ uint32_t specdata2; /* Minor device number */
};
-
/*
* Values for fattr4_fh_expire_type
*/
@@ -398,68 +516,366 @@ const FH4_VOL_MIGRATION = 0x00000004;
const FH4_VOL_RENAME = 0x00000008;
-typedef bitmap4 fattr4_supported_attrs;
-typedef nfs_ftype4 fattr4_type;
-typedef uint32_t fattr4_fh_expire_type;
-typedef changeid4 fattr4_change;
-typedef uint64_t fattr4_size;
-typedef bool fattr4_link_support;
-typedef bool fattr4_symlink_support;
-typedef bool fattr4_named_attr;
-typedef fsid4 fattr4_fsid;
-typedef bool fattr4_unique_handles;
-typedef nfs_lease4 fattr4_lease_time;
-typedef nfsstat4 fattr4_rdattr_error;
-
-typedef nfsace4 fattr4_acl<>;
-typedef uint32_t fattr4_aclsupport;
-typedef bool fattr4_archive;
-typedef bool fattr4_cansettime;
-typedef bool fattr4_case_insensitive;
-typedef bool fattr4_case_preserving;
-typedef bool fattr4_chown_restricted;
-typedef uint64_t fattr4_fileid;
-typedef uint64_t fattr4_files_avail;
-typedef nfs_fh4 fattr4_filehandle;
-typedef uint64_t fattr4_files_free;
-typedef uint64_t fattr4_files_total;
-typedef fs_locations4 fattr4_fs_locations;
-typedef bool fattr4_hidden;
-typedef bool fattr4_homogeneous;
-typedef uint64_t fattr4_maxfilesize;
-typedef uint32_t fattr4_maxlink;
-typedef uint32_t fattr4_maxname;
-typedef uint64_t fattr4_maxread;
-typedef uint64_t fattr4_maxwrite;
-typedef ascii_REQUIRED4 fattr4_mimetype;
-typedef mode4 fattr4_mode;
-typedef uint64_t fattr4_mounted_on_fileid;
-typedef bool fattr4_no_trunc;
-typedef uint32_t fattr4_numlinks;
-typedef utf8str_mixed fattr4_owner;
-typedef utf8str_mixed fattr4_owner_group;
-typedef uint64_t fattr4_quota_avail_hard;
-typedef uint64_t fattr4_quota_avail_soft;
-typedef uint64_t fattr4_quota_used;
-typedef specdata4 fattr4_rawdev;
-typedef uint64_t fattr4_space_avail;
-typedef uint64_t fattr4_space_free;
-typedef uint64_t fattr4_space_total;
-typedef uint64_t fattr4_space_used;
-typedef bool fattr4_system;
-typedef nfstime4 fattr4_time_access;
-typedef settime4 fattr4_time_access_set;
-typedef nfstime4 fattr4_time_backup;
-typedef nfstime4 fattr4_time_create;
-typedef nfstime4 fattr4_time_delta;
-typedef nfstime4 fattr4_time_metadata;
-typedef nfstime4 fattr4_time_modify;
-typedef settime4 fattr4_time_modify_set;
-
-
-/*
- * Mandatory attributes
+struct netaddr4 {
+ /* See struct rpcb in RFC 1833. */
+ string na_r_netid<>; /* Network id */
+ string na_r_addr<>; /* Universal address */
+};
+
+
+/*
+ * Data structures new to NFSv4.1
+ */
+
+struct nfs_impl_id4 {
+ utf8str_cis nii_domain;
+ utf8str_cs nii_name;
+ nfstime4 nii_date;
+};
+
+
+/*
+ * Stateid
+ */
+struct stateid4 {
+ uint32_t seqid;
+ opaque other[NFS4_OTHER_SIZE];
+};
+
+enum layouttype4 {
+ LAYOUT4_NFSV4_1_FILES = 0x1,
+ LAYOUT4_OSD2_OBJECTS = 0x2,
+ LAYOUT4_BLOCK_VOLUME = 0x3
+};
+
+struct layout_content4 {
+ layouttype4 loc_type;
+ opaque loc_body<>;
+};
+
+
+%/*
+% * LAYOUT4_OSD2_OBJECTS loc_body description
+% * is in a separate .x file.
+% */
+%
+%/*
+% * LAYOUT4_BLOCK_VOLUME loc_body description
+% * is in a separate .x file.
+% */
+
+struct layouthint4 {
+ layouttype4 loh_type;
+ opaque loh_body<>;
+};
+
+enum layoutiomode4 {
+ LAYOUTIOMODE4_READ = 1,
+ LAYOUTIOMODE4_RW = 2,
+ LAYOUTIOMODE4_ANY = 3
+};
+
+struct layout4 {
+ offset4 lo_offset;
+ length4 lo_length;
+ layoutiomode4 lo_iomode;
+ layout_content4 lo_content;
+};
+
+const NFS4_DEVICEID4_SIZE = 16;
+
+typedef opaque deviceid4[NFS4_DEVICEID4_SIZE];
+
+struct device_addr4 {
+ layouttype4 da_layout_type;
+ opaque da_addr_body<>;
+};
+
+
+struct layoutupdate4 {
+ layouttype4 lou_type;
+ opaque lou_body<>;
+};
+
+%
+/* Constants used for LAYOUTRETURN and CB_LAYOUTRECALL */
+const LAYOUT4_RET_REC_FILE = 1;
+const LAYOUT4_RET_REC_FSID = 2;
+const LAYOUT4_RET_REC_ALL = 3;
+%
+enum layoutreturn_type4 {
+ LAYOUTRETURN4_FILE = LAYOUT4_RET_REC_FILE,
+ LAYOUTRETURN4_FSID = LAYOUT4_RET_REC_FSID,
+ LAYOUTRETURN4_ALL = LAYOUT4_RET_REC_ALL
+};
+
+struct layoutreturn_file4 {
+ offset4 lrf_offset;
+ length4 lrf_length;
+ stateid4 lrf_stateid;
+% /* layouttype4 specific data */
+ opaque lrf_body<>;
+};
+
+union layoutreturn4 switch (layoutreturn_type4 lr_returntype) {
+ case LAYOUTRETURN4_FILE:
+ layoutreturn_file4 lr_layout;
+ default:
+ void;
+};
+%
+
+enum fs4_status_type {
+ STATUS4_FIXED = 1,
+ STATUS4_UPDATED = 2,
+ STATUS4_VERSIONED = 3,
+ STATUS4_WRITABLE = 4,
+ STATUS4_REFERRAL = 5
+};
+
+struct fs4_status {
+ bool fss_absent;
+ fs4_status_type fss_type;
+ utf8str_cs fss_source;
+ utf8str_cs fss_current;
+ int32_t fss_age;
+ nfstime4 fss_version;
+};
+
+
+const TH4_READ_SIZE = 0;
+const TH4_WRITE_SIZE = 1;
+const TH4_READ_IOSIZE = 2;
+const TH4_WRITE_IOSIZE = 3;
+
+typedef length4 threshold4_read_size;
+typedef length4 threshold4_write_size;
+typedef length4 threshold4_read_iosize;
+typedef length4 threshold4_write_iosize;
+
+struct threshold_item4 {
+ layouttype4 thi_layout_type;
+ bitmap4 thi_hintset;
+ opaque thi_hintlist<>;
+};
+
+struct mdsthreshold4 {
+ threshold_item4 mth_hints<>;
+};
+
+const RET4_DURATION_INFINITE = 0xffffffffffffffff;
+struct retention_get4 {
+ uint64_t rg_duration;
+ nfstime4 rg_begin_time<1>;
+};
+
+struct retention_set4 {
+ bool rs_enable;
+ uint64_t rs_duration<1>;
+};
+
+const FSCHARSET_CAP4_CONTAINS_NON_UTF8 = 0x1;
+const FSCHARSET_CAP4_ALLOWS_ONLY_UTF8 = 0x2;
+
+typedef uint32_t fs_charset_cap4;
+
+
+/*
+ * Data structures new to NFSv4.2
*/
+
+enum netloc_type4 {
+ NL4_NAME = 1,
+ NL4_URL = 2,
+ NL4_NETADDR = 3
+};
+union netloc4 switch (netloc_type4 nl_type) {
+ case NL4_NAME: utf8str_cis nl_name;
+ case NL4_URL: utf8str_cis nl_url;
+ case NL4_NETADDR: netaddr4 nl_addr;
+};
+
+enum change_attr_type4 {
+ NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR = 0,
+ NFS4_CHANGE_TYPE_IS_VERSION_COUNTER = 1,
+ NFS4_CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS = 2,
+ NFS4_CHANGE_TYPE_IS_TIME_METADATA = 3,
+ NFS4_CHANGE_TYPE_IS_UNDEFINED = 4
+};
+
+struct labelformat_spec4 {
+ policy4 lfs_lfs;
+ policy4 lfs_pi;
+};
+
+struct sec_label4 {
+ labelformat_spec4 slai_lfs;
+ opaque slai_data<>;
+};
+
+
+struct copy_from_auth_priv {
+ secret4 cfap_shared_secret;
+ netloc4 cfap_destination;
+ /* The NFSv4 user name that the user principal maps to */
+ utf8str_mixed cfap_username;
+};
+
+struct copy_to_auth_priv {
+ /* Equal to cfap_shared_secret */
+ secret4 ctap_shared_secret;
+ netloc4 ctap_source<>;
+ /* The NFSv4 user name that the user principal maps to */
+ utf8str_mixed ctap_username;
+};
+
+struct copy_confirm_auth_priv {
+ /* Equal to GSS_GetMIC() of cfap_shared_secret */
+ opaque ccap_shared_secret_mic<>;
+ /* The NFSv4 user name that the user principal maps to */
+ utf8str_mixed ccap_username;
+};
+
+
+struct app_data_block4 {
+ offset4 adb_offset;
+ length4 adb_block_size;
+ length4 adb_block_count;
+ length4 adb_reloff_blocknum;
+ count4 adb_block_num;
+ length4 adb_reloff_pattern;
+ opaque adb_pattern<>;
+};
+
+
+struct data4 {
+ offset4 d_offset;
+ opaque d_data<>;
+};
+
+struct data_info4 {
+ offset4 di_offset;
+ length4 di_length;
+};
+
+
+enum data_content4 {
+ NFS4_CONTENT_DATA = 0,
+ NFS4_CONTENT_HOLE = 1
+};
+
+
+
+enum stable_how4 {
+ UNSTABLE4 = 0,
+ DATA_SYNC4 = 1,
+ FILE_SYNC4 = 2
+};
+
+
+
+struct write_response4 {
+ stateid4 wr_callback_id<1>;
+ length4 wr_count;
+ stable_how4 wr_committed;
+ verifier4 wr_writeverf;
+};
+
+
+/*
+ * NFSv4.1 attributes
+ */
+typedef bitmap4 fattr4_supported_attrs;
+typedef nfs_ftype4 fattr4_type;
+typedef uint32_t fattr4_fh_expire_type;
+typedef changeid4 fattr4_change;
+typedef uint64_t fattr4_size;
+typedef bool fattr4_link_support;
+typedef bool fattr4_symlink_support;
+typedef bool fattr4_named_attr;
+typedef fsid4 fattr4_fsid;
+typedef bool fattr4_unique_handles;
+typedef nfs_lease4 fattr4_lease_time;
+typedef nfsstat4 fattr4_rdattr_error;
+typedef nfsace4 fattr4_acl<>;
+typedef uint32_t fattr4_aclsupport;
+typedef bool fattr4_archive;
+typedef bool fattr4_cansettime;
+typedef bool fattr4_case_insensitive;
+typedef bool fattr4_case_preserving;
+typedef bool fattr4_chown_restricted;
+typedef uint64_t fattr4_fileid;
+typedef uint64_t fattr4_files_avail;
+typedef nfs_fh4 fattr4_filehandle;
+typedef uint64_t fattr4_files_free;
+typedef uint64_t fattr4_files_total;
+typedef fs_locations4 fattr4_fs_locations;
+typedef bool fattr4_hidden;
+typedef bool fattr4_homogeneous;
+typedef uint64_t fattr4_maxfilesize;
+typedef uint32_t fattr4_maxlink;
+typedef uint32_t fattr4_maxname;
+typedef uint64_t fattr4_maxread;
+typedef uint64_t fattr4_maxwrite;
+typedef ascii_REQUIRED4 fattr4_mimetype;
+typedef mode4 fattr4_mode;
+typedef mode_masked4 fattr4_mode_set_masked;
+typedef uint64_t fattr4_mounted_on_fileid;
+typedef bool fattr4_no_trunc;
+typedef uint32_t fattr4_numlinks;
+typedef utf8str_mixed fattr4_owner;
+typedef utf8str_mixed fattr4_owner_group;
+typedef uint64_t fattr4_quota_avail_hard;
+typedef uint64_t fattr4_quota_avail_soft;
+typedef uint64_t fattr4_quota_used;
+typedef specdata4 fattr4_rawdev;
+typedef uint64_t fattr4_space_avail;
+typedef length4 fattr4_space_free;
+typedef uint64_t fattr4_space_total;
+typedef uint64_t fattr4_space_used;
+typedef bool fattr4_system;
+typedef nfstime4 fattr4_time_access;
+typedef settime4 fattr4_time_access_set;
+typedef nfstime4 fattr4_time_backup;
+typedef nfstime4 fattr4_time_create;
+typedef nfstime4 fattr4_time_delta;
+typedef nfstime4 fattr4_time_metadata;
+typedef nfstime4 fattr4_time_modify;
+typedef settime4 fattr4_time_modify_set;
+/*
+ * Attributes new to NFSv4.1
+ */
+typedef bitmap4 fattr4_suppattr_exclcreat;
+typedef nfstime4 fattr4_dir_notif_delay;
+typedef nfstime4 fattr4_dirent_notif_delay;
+typedef layouttype4 fattr4_fs_layout_types<>;
+typedef fs4_status fattr4_fs_status;
+typedef fs_charset_cap4 fattr4_fs_charset_cap;
+typedef uint32_t fattr4_layout_alignment;
+typedef uint32_t fattr4_layout_blksize;
+typedef layouthint4 fattr4_layout_hint;
+typedef layouttype4 fattr4_layout_types<>;
+typedef mdsthreshold4 fattr4_mdsthreshold;
+typedef retention_get4 fattr4_retention_get;
+typedef retention_set4 fattr4_retention_set;
+typedef retention_get4 fattr4_retentevt_get;
+typedef retention_set4 fattr4_retentevt_set;
+typedef uint64_t fattr4_retention_hold;
+typedef nfsacl41 fattr4_dacl;
+typedef nfsacl41 fattr4_sacl;
+typedef change_policy4 fattr4_change_policy;
+/*
+ * Attributes new to NFSv4.2
+ */
+typedef uint64_t fattr4_space_freed;
+typedef change_attr_type4
+ fattr4_change_attr_type;
+typedef sec_label4 fattr4_sec_label;
+typedef uint32_t fattr4_clone_blksize;
+
+%/*
+% * REQUIRED attributes
+% */
const FATTR4_SUPPORTED_ATTRS = 0;
const FATTR4_TYPE = 1;
const FATTR4_FH_EXPIRE_TYPE = 2;
@@ -474,9 +890,14 @@ const FATTR4_LEASE_TIME = 10;
const FATTR4_RDATTR_ERROR = 11;
const FATTR4_FILEHANDLE = 19;
-/*
- * Recommended attributes
- */
+%/*
+% * New to NFSv4.1
+% */
+const FATTR4_SUPPATTR_EXCLCREAT = 75;
+
+%/*
+% * RECOMMENDED attributes
+% */
const FATTR4_ACL = 12;
const FATTR4_ACLSUPPORT = 13;
const FATTR4_ARCHIVE = 14;
@@ -521,6 +942,38 @@ const FATTR4_TIME_MODIFY = 53;
const FATTR4_TIME_MODIFY_SET = 54;
const FATTR4_MOUNTED_ON_FILEID = 55;
+%/*
+% * New to NFSv4.1
+% */
+const FATTR4_DIR_NOTIF_DELAY = 56;
+const FATTR4_DIRENT_NOTIF_DELAY = 57;
+const FATTR4_DACL = 58;
+const FATTR4_SACL = 59;
+const FATTR4_CHANGE_POLICY = 60;
+const FATTR4_FS_STATUS = 61;
+const FATTR4_FS_LAYOUT_TYPES = 62;
+const FATTR4_LAYOUT_HINT = 63;
+const FATTR4_LAYOUT_TYPES = 64;
+const FATTR4_LAYOUT_BLKSIZE = 65;
+const FATTR4_LAYOUT_ALIGNMENT = 66;
+const FATTR4_FS_LOCATIONS_INFO = 67;
+const FATTR4_MDSTHRESHOLD = 68;
+const FATTR4_RETENTION_GET = 69;
+const FATTR4_RETENTION_SET = 70;
+const FATTR4_RETENTEVT_GET = 71;
+const FATTR4_RETENTEVT_SET = 72;
+const FATTR4_RETENTION_HOLD = 73;
+const FATTR4_MODE_SET_MASKED = 74;
+const FATTR4_FS_CHARSET_CAP = 76;
+
+%/*
+% * New to NFSv4.2
+% */
+const FATTR4_CLONE_BLKSIZE = 77;
+const FATTR4_SPACE_FREED = 78;
+const FATTR4_CHANGE_ATTR_TYPE = 79;
+const FATTR4_SEC_LABEL = 80;
+
/*
* File attribute container
*/
@@ -529,7 +982,6 @@ struct fattr4 {
attrlist4 attr_vals;
};
-
/*
* Change info for the client
*/
@@ -539,66 +991,336 @@ struct change_info4 {
changeid4 after;
};
-
-struct clientaddr4 {
- /* see struct rpcb in RFC 1833 */
- string r_netid<>; /* network id */
- string r_addr<>; /* universal address */
-};
-
+typedef netaddr4 clientaddr4;
/*
* Callback program info as provided by the client
*/
struct cb_client4 {
- unsigned int cb_program;
- clientaddr4 cb_location;
+ uint32_t cb_program;
+ netaddr4 cb_location;
};
-
/*
- * Stateid
+ * NFSv4.0 long-hand client ID
*/
-struct stateid4 {
- uint32_t seqid;
- opaque other[NFS4_OTHER_SIZE];
+struct nfs_client_id4 {
+ verifier4 verifier;
+ opaque id<NFS4_OPAQUE_LIMIT>;
};
/*
- * Client ID
+ * NFSv4.1 client owner (aka long-hand client ID)
*/
-struct nfs_client_id4 {
- verifier4 verifier;
- opaque id<NFS4_OPAQUE_LIMIT>;
+struct client_owner4 {
+ verifier4 co_verifier;
+ opaque co_ownerid<NFS4_OPAQUE_LIMIT>;
};
-struct open_owner4 {
- clientid4 clientid;
- opaque owner<NFS4_OPAQUE_LIMIT>;
+/*
+ * NFSv4.1 server owner
+ */
+struct server_owner4 {
+ uint64_t so_minor_id;
+ opaque so_major_id<NFS4_OPAQUE_LIMIT>;
};
-struct lock_owner4 {
+struct state_owner4 {
clientid4 clientid;
opaque owner<NFS4_OPAQUE_LIMIT>;
};
+typedef state_owner4 open_owner4;
+typedef state_owner4 lock_owner4;
+
enum nfs_lock_type4 {
READ_LT = 1,
WRITE_LT = 2,
- READW_LT = 3, /* blocking read */
- WRITEW_LT = 4 /* blocking write */
+ READW_LT = 3, /* Blocking read */
+ WRITEW_LT = 4 /* Blocking write */
+};
+
+
+%
+%/* Input for computing subkeys */
+enum ssv_subkey4 {
+ SSV4_SUBKEY_MIC_I2T = 1,
+ SSV4_SUBKEY_MIC_T2I = 2,
+ SSV4_SUBKEY_SEAL_I2T = 3,
+ SSV4_SUBKEY_SEAL_T2I = 4
+};
+%
+
+%
+%/* Input for computing smt_hmac */
+struct ssv_mic_plain_tkn4 {
+ uint32_t smpt_ssv_seq;
+ opaque smpt_orig_plain<>;
+};
+%
+
+%
+%/*
+% * Secret State Verifier Generic Security Service (SSV GSS)
+% * PerMsgToken token
+% */
+struct ssv_mic_tkn4 {
+ uint32_t smt_ssv_seq;
+ opaque smt_hmac<>;
+};
+%
+
+%
+%/* Input for computing ssct_encr_data and ssct_hmac */
+struct ssv_seal_plain_tkn4 {
+ opaque sspt_confounder<>;
+ uint32_t sspt_ssv_seq;
+ opaque sspt_orig_plain<>;
+ opaque sspt_pad<>;
+};
+%
+
+%
+%/* SSV GSS SealedMessage token */
+struct ssv_seal_cipher_tkn4 {
+ uint32_t ssct_ssv_seq;
+ opaque ssct_iv<>;
+ opaque ssct_encr_data<>;
+ opaque ssct_hmac<>;
+};
+%
+
+/*
+ * Defines an individual server replica
+ */
+struct fs_locations_server4 {
+ int32_t fls_currency;
+ opaque fls_info<>;
+ utf8str_cis fls_server;
+};
+
+/*
+ * Byte indices of items within
+ * fls_info: flag fields, class numbers,
+ * bytes indicating ranks and orders
+ */
+const FSLI4BX_GFLAGS = 0;
+const FSLI4BX_TFLAGS = 1;
+
+const FSLI4BX_CLSIMUL = 2;
+const FSLI4BX_CLHANDLE = 3;
+const FSLI4BX_CLFILEID = 4;
+const FSLI4BX_CLWRITEVER = 5;
+const FSLI4BX_CLCHANGE = 6;
+const FSLI4BX_CLREADDIR = 7;
+
+const FSLI4BX_READRANK = 8;
+const FSLI4BX_WRITERANK = 9;
+const FSLI4BX_READORDER = 10;
+const FSLI4BX_WRITEORDER = 11;
+
+/*
+ * Bits defined within the general flag byte
+ */
+const FSLI4GF_WRITABLE = 0x01;
+const FSLI4GF_CUR_REQ = 0x02;
+const FSLI4GF_ABSENT = 0x04;
+const FSLI4GF_GOING = 0x08;
+const FSLI4GF_SPLIT = 0x10;
+
+/*
+ * Bits defined within the transport flag byte
+ */
+const FSLI4TF_RDMA = 0x01;
+
+/*
+ * Defines a set of replicas sharing
+ * a common value of the root path
+ * within the corresponding
+ * single-server namespaces
+ */
+struct fs_locations_item4 {
+ fs_locations_server4 fli_entries<>;
+ pathname4 fli_rootpath;
+};
+
+/*
+ * Defines the overall structure of
+ * the fs_locations_info attribute
+ */
+struct fs_locations_info4 {
+ uint32_t fli_flags;
+ int32_t fli_valid_for;
+ pathname4 fli_fs_root;
+ fs_locations_item4 fli_items<>;
};
+/*
+ * Flag bits in fli_flags
+ */
+const FSLI4IF_VAR_SUB = 0x00000001;
+
+typedef fs_locations_info4 fattr4_fs_locations_info;
+
+const NFL4_UFLG_MASK = 0x0000003F;
+const NFL4_UFLG_DENSE = 0x00000001;
+const NFL4_UFLG_COMMIT_THRU_MDS = 0x00000002;
+const NFL42_UFLG_IO_ADVISE_THRU_MDS = 0x00000004;
+const NFL4_UFLG_STRIPE_UNIT_SIZE_MASK = 0xFFFFFFC0;
+
+typedef uint32_t nfl_util4;
+
+%
+
+enum filelayout_hint_care4 {
+ NFLH4_CARE_DENSE = NFL4_UFLG_DENSE,
-const ACCESS4_READ = 0x00000001;
-const ACCESS4_LOOKUP = 0x00000002;
-const ACCESS4_MODIFY = 0x00000004;
-const ACCESS4_EXTEND = 0x00000008;
-const ACCESS4_DELETE = 0x00000010;
-const ACCESS4_EXECUTE = 0x00000020;
+ NFLH4_CARE_COMMIT_THRU_MDS
+ = NFL4_UFLG_COMMIT_THRU_MDS,
+
+ NFL42_CARE_IO_ADVISE_THRU_MDS
+ = NFL42_UFLG_IO_ADVISE_THRU_MDS,
+
+ NFLH4_CARE_STRIPE_UNIT_SIZE
+ = 0x00000040,
+
+ NFLH4_CARE_STRIPE_COUNT = 0x00000080
+};
+%
+%/*
+% * Encoded in the loh_body field of data type layouthint4:
+% */
+%
+struct nfsv4_1_file_layouthint4 {
+ uint32_t nflh_care;
+ nfl_util4 nflh_util;
+ count4 nflh_stripe_count;
+};
+
+%
+
+%
+typedef netaddr4 multipath_list4<>;
+%
+%/*
+% * Encoded in the da_addr_body field of data type device_addr4:
+% */
+struct nfsv4_1_file_layout_ds_addr4 {
+ uint32_t nflda_stripe_indices<>;
+ multipath_list4 nflda_multipath_ds_list<>;
+};
+
+%
+
+%
+%/*
+% * Encoded in the loc_body field of data type layout_content4:
+% */
+struct nfsv4_1_file_layout4 {
+ deviceid4 nfl_deviceid;
+ nfl_util4 nfl_util;
+ uint32_t nfl_first_stripe_index;
+ offset4 nfl_pattern_offset;
+ nfs_fh4 nfl_fh_list<>;
+};
+
+%
+
+
+/*
+ * Operation arrays (the opnum first)
+ */
+
+enum nfs_opnum4 {
+ OP_ACCESS = 3,
+ OP_CLOSE = 4,
+ OP_COMMIT = 5,
+ OP_CREATE = 6,
+ OP_DELEGPURGE = 7,
+ OP_DELEGRETURN = 8,
+ OP_GETATTR = 9,
+ OP_GETFH = 10,
+ OP_LINK = 11,
+ OP_LOCK = 12,
+ OP_LOCKT = 13,
+ OP_LOCKU = 14,
+ OP_LOOKUP = 15,
+ OP_LOOKUPP = 16,
+ OP_NVERIFY = 17,
+ OP_OPEN = 18,
+ OP_OPENATTR = 19,
+ OP_OPEN_CONFIRM = 20, /* Mandatory not-to-implement */
+ OP_OPEN_DOWNGRADE = 21,
+ OP_PUTFH = 22,
+ OP_PUTPUBFH = 23,
+ OP_PUTROOTFH = 24,
+ OP_READ = 25,
+ OP_READDIR = 26,
+ OP_READLINK = 27,
+ OP_REMOVE = 28,
+ OP_RENAME = 29,
+ OP_RENEW = 30, /* Mandatory not-to-implement */
+ OP_RESTOREFH = 31,
+ OP_SAVEFH = 32,
+ OP_SECINFO = 33,
+ OP_SETATTR = 34,
+ OP_SETCLIENTID = 35, /* Mandatory not-to-implement */
+ OP_SETCLIENTID_CONFIRM = 36, /* Mandatory not-to-implement */
+ OP_VERIFY = 37,
+ OP_WRITE = 38,
+ OP_RELEASE_LOCKOWNER = 39, /* Mandatory not-to-implement */
+%
+%/* New operations for NFSv4.1 */
+%
+ OP_BACKCHANNEL_CTL = 40,
+ OP_BIND_CONN_TO_SESSION = 41,
+ OP_EXCHANGE_ID = 42,
+ OP_CREATE_SESSION = 43,
+ OP_DESTROY_SESSION = 44,
+ OP_FREE_STATEID = 45,
+ OP_GET_DIR_DELEGATION = 46,
+ OP_GETDEVICEINFO = 47,
+ OP_GETDEVICELIST = 48,
+ OP_LAYOUTCOMMIT = 49,
+ OP_LAYOUTGET = 50,
+ OP_LAYOUTRETURN = 51,
+ OP_SECINFO_NO_NAME = 52,
+ OP_SEQUENCE = 53,
+ OP_SET_SSV = 54,
+ OP_TEST_STATEID = 55,
+ OP_WANT_DELEGATION = 56,
+ OP_DESTROY_CLIENTID = 57,
+ OP_RECLAIM_COMPLETE = 58,
+%
+%/* New operations for NFSv4.2 */
+%
+ OP_ALLOCATE = 59,
+ OP_COPY = 60,
+ OP_COPY_NOTIFY = 61,
+ OP_DEALLOCATE = 62,
+ OP_IO_ADVISE = 63,
+ OP_LAYOUTERROR = 64,
+ OP_LAYOUTSTATS = 65,
+ OP_OFFLOAD_CANCEL = 66,
+ OP_OFFLOAD_STATUS = 67,
+ OP_READ_PLUS = 68,
+ OP_SEEK = 69,
+ OP_WRITE_SAME = 70,
+ OP_CLONE = 71,
+ OP_ILLEGAL = 10044
+};
+
+
+
+const ACCESS4_READ = 0x00000001;
+const ACCESS4_LOOKUP = 0x00000002;
+const ACCESS4_MODIFY = 0x00000004;
+const ACCESS4_EXTEND = 0x00000008;
+const ACCESS4_DELETE = 0x00000010;
+const ACCESS4_EXECUTE = 0x00000020;
struct ACCESS4args {
/* CURRENT_FH: object */
@@ -612,11 +1334,24 @@ struct ACCESS4resok {
union ACCESS4res switch (nfsstat4 status) {
case NFS4_OK:
- ACCESS4resok resok4;
+ ACCESS4resok resok4;
default:
void;
};
+struct CLONE4args {
+ /* SAVED_FH: source file */
+ /* CURRENT_FH: destination file */
+ stateid4 cl_src_stateid;
+ stateid4 cl_dst_stateid;
+ offset4 cl_src_offset;
+ offset4 cl_dst_offset;
+ length4 cl_count;
+};
+
+struct CLONE4res {
+ nfsstat4 cl_status;
+};
struct CLOSE4args {
/* CURRENT_FH: object */
seqid4 seqid;
@@ -658,7 +1393,7 @@ union createtype4 switch (nfs_ftype4 type) {
case NF4DIR:
void;
default:
- void; /* server should return NFS4ERR_BADTYPE */
+ void; /* Server should return NFS4ERR_BADTYPE. */
};
struct CREATE4args {
@@ -670,11 +1405,12 @@ struct CREATE4args {
struct CREATE4resok {
change_info4 cinfo;
- bitmap4 attrset; /* attributes set */
+ bitmap4 attrset; /* Attributes set */
};
union CREATE4res switch (nfsstat4 status) {
case NFS4_OK:
+ /* New CURRENTFH: created object */
CREATE4resok resok4;
default:
void;
@@ -689,7 +1425,7 @@ struct DELEGPURGE4res {
};
struct DELEGRETURN4args {
- /* CURRENT_FH: delegated file */
+ /* CURRENT_FH: delegated object */
stateid4 deleg_stateid;
};
@@ -698,7 +1434,7 @@ struct DELEGRETURN4res {
};
struct GETATTR4args {
- /* CURRENT_FH: directory or file */
+ /* CURRENT_FH: object */
bitmap4 attr_request;
};
@@ -742,7 +1478,8 @@ union LINK4res switch (nfsstat4 status) {
};
/*
- * For LOCK, transition from open_owner to new lock_owner
+ * For LOCK, transition from open_stateid and lock_owner
+ * to a lock stateid.
*/
struct open_to_lock_owner4 {
seqid4 open_seqid;
@@ -752,7 +1489,8 @@ struct open_to_lock_owner4 {
};
/*
- * For LOCK, existing lock_owner continues to request file locks
+ * For LOCK, existing lock stateid continues to request new
+ * file lock for the same lock_owner and open_stateid.
*/
struct exist_lock_owner4 {
stateid4 lock_stateid;
@@ -837,12 +1575,12 @@ struct LOOKUP4args {
};
struct LOOKUP4res {
- /* CURRENT_FH: object */
+ /* New CURRENT_FH: object */
nfsstat4 status;
};
struct LOOKUPP4res {
- /* CURRENT_FH: directory */
+ /* New CURRENT_FH: parent directory */
nfsstat4 status;
};
@@ -855,21 +1593,25 @@ struct NVERIFY4res {
nfsstat4 status;
};
-const OPEN4_SHARE_ACCESS_READ = 0x00000001;
-const OPEN4_SHARE_ACCESS_WRITE = 0x00000002;
-const OPEN4_SHARE_ACCESS_BOTH = 0x00000003;
-
-const OPEN4_SHARE_DENY_NONE = 0x00000000;
-const OPEN4_SHARE_DENY_READ = 0x00000001;
-const OPEN4_SHARE_DENY_WRITE = 0x00000002;
-const OPEN4_SHARE_DENY_BOTH = 0x00000003;
/*
* Various definitions for OPEN
*/
enum createmode4 {
UNCHECKED4 = 0,
GUARDED4 = 1,
- EXCLUSIVE4 = 2
+ /* Deprecated in NFSv4.1 */
+ EXCLUSIVE4 = 2,
+ /*
+ * New to NFSv4.1. If session is persistent,
+ * GUARDED4 MUST be used. Otherwise, use
+ * EXCLUSIVE4_1 instead of EXCLUSIVE4.
+ */
+ EXCLUSIVE4_1 = 3
+};
+
+struct creatverfattr {
+ verifier4 cva_verf;
+ fattr4 cva_attrs;
};
union createhow4 switch (createmode4 mode) {
@@ -878,6 +1620,8 @@ union createhow4 switch (createmode4 mode) {
fattr4 createattrs;
case EXCLUSIVE4:
verifier4 createverf;
+ case EXCLUSIVE4_1:
+ creatverfattr ch_createboth;
};
enum opentype4 {
@@ -896,7 +1640,7 @@ union openflag4 switch (opentype4 opentype) {
enum limit_by4 {
NFS_LIMIT_SIZE = 1,
NFS_LIMIT_BLOCKS = 2
- /* others as needed */
+ /* Others as needed */
};
struct nfs_modified_limit4 {
@@ -905,25 +1649,80 @@ struct nfs_modified_limit4 {
};
union nfs_space_limit4 switch (limit_by4 limitby) {
- /* limit specified as file size */
+ /* Limit specified as file size */
case NFS_LIMIT_SIZE:
uint64_t filesize;
- /* limit specified by number of blocks */
+ /* Limit specified by number of blocks */
case NFS_LIMIT_BLOCKS:
nfs_modified_limit4 mod_blocks;
-} ;
+};
+
+/*
+ * Share Access and Deny constants for open argument
+ */
+const OPEN4_SHARE_ACCESS_READ = 0x00000001;
+const OPEN4_SHARE_ACCESS_WRITE = 0x00000002;
+const OPEN4_SHARE_ACCESS_BOTH = 0x00000003;
+
+const OPEN4_SHARE_DENY_NONE = 0x00000000;
+const OPEN4_SHARE_DENY_READ = 0x00000001;
+const OPEN4_SHARE_DENY_WRITE = 0x00000002;
+const OPEN4_SHARE_DENY_BOTH = 0x00000003;
+
+
+/* New flags for share_access field of OPEN4args */
+const OPEN4_SHARE_ACCESS_WANT_DELEG_MASK = 0xFF00;
+const OPEN4_SHARE_ACCESS_WANT_NO_PREFERENCE = 0x0000;
+const OPEN4_SHARE_ACCESS_WANT_READ_DELEG = 0x0100;
+const OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG = 0x0200;
+const OPEN4_SHARE_ACCESS_WANT_ANY_DELEG = 0x0300;
+const OPEN4_SHARE_ACCESS_WANT_NO_DELEG = 0x0400;
+const OPEN4_SHARE_ACCESS_WANT_CANCEL = 0x0500;
+
+const
+ OPEN4_SHARE_ACCESS_WANT_SIGNAL_DELEG_WHEN_RESRC_AVAIL
+ = 0x10000;
+
+const
+ OPEN4_SHARE_ACCESS_WANT_PUSH_DELEG_WHEN_UNCONTENDED
+ = 0x20000;
enum open_delegation_type4 {
OPEN_DELEGATE_NONE = 0,
OPEN_DELEGATE_READ = 1,
- OPEN_DELEGATE_WRITE = 2
+ OPEN_DELEGATE_WRITE = 2,
+ OPEN_DELEGATE_NONE_EXT = 3 /* New to NFSv4.1 */
};
enum open_claim_type4 {
+ /*
+ * Not a reclaim
+ */
CLAIM_NULL = 0,
+
CLAIM_PREVIOUS = 1,
CLAIM_DELEGATE_CUR = 2,
- CLAIM_DELEGATE_PREV = 3
+ CLAIM_DELEGATE_PREV = 3,
+
+ /*
+ * Not a reclaim
+ *
+ * Like CLAIM_NULL, but object identified
+ * by the current filehandle
+ */
+ CLAIM_FH = 4, /* New to NFSv4.1 */
+
+ /*
+ * Like CLAIM_DELEGATE_CUR, but object identified
+ * by current filehandle
+ */
+ CLAIM_DELEG_CUR_FH = 5, /* New to NFSv4.1 */
+
+ /*
+ * Like CLAIM_DELEGATE_PREV, but object identified
+ * by current filehandle
+ */
+ CLAIM_DELEG_PREV_FH = 6 /* New to NFSv4.1 */
};
struct open_claim_delegate_cur4 {
@@ -964,12 +1763,41 @@ union open_claim4 switch (open_claim_type4 claim) {
* of the client. File is specified by name.
*/
case CLAIM_DELEGATE_PREV:
- /* CURRENT_FH: directory */
+ /* CURRENT_FH: directory */
component4 file_delegate_prev;
+
+ /*
+ * Like CLAIM_NULL. No special rights
+ * to file. Ordinary OPEN of the
+ * specified file by current filehandle.
+ */
+ case CLAIM_FH: /* New to NFSv4.1 */
+ /* CURRENT_FH: regular file to open */
+ void;
+
+ /*
+ * Like CLAIM_DELEGATE_PREV. Right to file based on a
+ * delegation granted to a previous boot
+ * instance of the client. File is identified
+ * by filehandle.
+ */
+ case CLAIM_DELEG_PREV_FH: /* New to NFSv4.1 */
+ /* CURRENT_FH: file being opened */
+ void;
+
+ /*
+ * Like CLAIM_DELEGATE_CUR. Right to file based on
+ * a delegation granted by the server.
+ * File is identified by filehandle.
+ */
+ case CLAIM_DELEG_CUR_FH: /* New to NFSv4.1 */
+ /* CURRENT_FH: file being opened */
+ stateid4 oc_delegate_stateid;
+
};
/*
- * OPEN: Open a file, potentially receiving an open delegation
+ * OPEN: Open a file, potentially receiving an open delegation.
*/
struct OPEN4args {
seqid4 seqid;
@@ -984,11 +1812,11 @@ struct open_read_delegation4 {
stateid4 stateid; /* Stateid for delegation */
bool recall; /* Pre-recalled flag for
delegations obtained
- by reclaim (CLAIM_PREVIOUS). */
+ by reclaim (CLAIM_PREVIOUS) */
nfsace4 permissions; /* Defines users who don't
need an ACCESS call to
- open for read. */
+ open for read */
};
struct open_write_delegation4 {
@@ -996,52 +1824,85 @@ struct open_write_delegation4 {
bool recall; /* Pre-recalled flag for
delegations obtained
by reclaim
- (CLAIM_PREVIOUS). */
+ (CLAIM_PREVIOUS) */
nfs_space_limit4
space_limit; /* Defines condition that
the client must check to
determine whether the
file needs to be flushed
- to the server on close. */
+ to the server on close */
nfsace4 permissions; /* Defines users who don't
need an ACCESS call as
part of a delegated
- open. */
+ open */
+};
+
+
+enum why_no_delegation4 { /* New to NFSv4.1 */
+ WND4_NOT_WANTED = 0,
+ WND4_CONTENTION = 1,
+ WND4_RESOURCE = 2,
+ WND4_NOT_SUPP_FTYPE = 3,
+ WND4_WRITE_DELEG_NOT_SUPP_FTYPE = 4,
+ WND4_NOT_SUPP_UPGRADE = 5,
+ WND4_NOT_SUPP_DOWNGRADE = 6,
+ WND4_CANCELLED = 7,
+ WND4_IS_DIR = 8
+};
+
+union open_none_delegation4 /* New to NFSv4.1 */
+ switch (why_no_delegation4 ond_why) {
+ case WND4_CONTENTION:
+ bool ond_server_will_push_deleg;
+ case WND4_RESOURCE:
+ bool ond_server_will_signal_avail;
+ default:
+ void;
};
union open_delegation4
-switch (open_delegation_type4 delegation_type) {
- case OPEN_DELEGATE_NONE:
- void;
- case OPEN_DELEGATE_READ:
- open_read_delegation4 read;
- case OPEN_DELEGATE_WRITE:
- open_write_delegation4 write;
+ switch (open_delegation_type4 delegation_type) {
+ case OPEN_DELEGATE_NONE:
+ void;
+ case OPEN_DELEGATE_READ:
+ open_read_delegation4 read;
+ case OPEN_DELEGATE_WRITE:
+ open_write_delegation4 write;
+ case OPEN_DELEGATE_NONE_EXT: /* New to NFSv4.1 */
+ open_none_delegation4 od_whynone;
};
/*
* Result flags
*/
-/* Client must confirm open */
+/* Client must confirm open. */
const OPEN4_RESULT_CONFIRM = 0x00000002;
-/* Type of file locking behavior at the server */
+/* Type of file-locking behavior at the server */
const OPEN4_RESULT_LOCKTYPE_POSIX = 0x00000004;
+/* Server will preserve file if removed while open. */
+const OPEN4_RESULT_PRESERVE_UNLINKED = 0x00000008;
+
+/*
+ * Server may use CB_NOTIFY_LOCK on locks
+ * derived from this open.
+ */
+const OPEN4_RESULT_MAY_NOTIFY_LOCK = 0x00000020;
struct OPEN4resok {
- stateid4 stateid; /* Stateid for open */
- change_info4 cinfo; /* Directory change info */
- uint32_t rflags; /* Result flags */
- bitmap4 attrset; /* attribute set for create */
- open_delegation4 delegation; /* Info on any open
+ stateid4 stateid; /* Stateid for open */
+ change_info4 cinfo; /* Directory change info */
+ uint32_t rflags; /* Result flags */
+ bitmap4 attrset; /* Attribute set for create */
+ open_delegation4 delegation; /* Info on any open
delegation */
};
union OPEN4res switch (nfsstat4 status) {
case NFS4_OK:
- /* CURRENT_FH: opened file */
+ /* New CURRENT_FH: opened file */
OPEN4resok resok4;
default:
void;
@@ -1053,10 +1914,15 @@ struct OPENATTR4args {
};
struct OPENATTR4res {
- /* CURRENT_FH: named attr directory */
+ /*
+ * If status is NFS4_OK,
+ * New CURRENT_FH: named attribute
+ * directory
+ */
nfsstat4 status;
};
+/* Obsolete in NFSv4.1 */
struct OPEN_CONFIRM4args {
/* CURRENT_FH: opened file */
stateid4 open_stateid;
@@ -1098,17 +1964,26 @@ struct PUTFH4args {
};
struct PUTFH4res {
- /* CURRENT_FH: */
+ /*
+ * If status is NFS4_OK,
+ * New CURRENT_FH: argument to PUTFH
+ */
nfsstat4 status;
};
struct PUTPUBFH4res {
- /* CURRENT_FH: public fh */
+ /*
+ * If status is NFS4_OK,
+ * New CURRENT_FH: public fh
+ */
nfsstat4 status;
};
struct PUTROOTFH4res {
- /* CURRENT_FH: root fh */
+ /*
+ * If status is NFS4_OK,
+ * New CURRENT_FH: root fh
+ */
nfsstat4 status;
};
@@ -1212,6 +2087,7 @@ union RENAME4res switch (nfsstat4 status) {
void;
};
+/* Obsolete in NFSv4.1 */
struct RENEW4args {
clientid4 clientid;
};
@@ -1221,12 +2097,18 @@ struct RENEW4res {
};
struct RESTOREFH4res {
- /* CURRENT_FH: value of saved fh */
+ /*
+ * If status is NFS4_OK,
+ * New CURRENT_FH: value of saved fh
+ */
nfsstat4 status;
};
struct SAVEFH4res {
- /* SAVED_FH: value of current fh */
+ /*
+ * If status is NFS4_OK,
+ * New SAVED_FH: value of current fh
+ */
nfsstat4 status;
};
@@ -1250,7 +2132,7 @@ struct rpcsec_gss_info {
rpc_gss_svc_t service;
};
-/* RPCSEC_GSS has a value of '6'. See RFC 2203 */
+/* RPCSEC_GSS has a value of "6". See RFC 2203. */
union secinfo4 switch (uint32_t flavor) {
case RPCSEC_GSS:
rpcsec_gss_info flavor_info;
@@ -1262,6 +2144,7 @@ typedef secinfo4 SECINFO4resok<>;
union SECINFO4res switch (nfsstat4 status) {
case NFS4_OK:
+ /* CURRENTFH: consumed */
SECINFO4resok resok4;
default:
void;
@@ -1278,6 +2161,7 @@ struct SETATTR4res {
bitmap4 attrsset;
};
+/* Obsolete in NFSv4.1 */
struct SETCLIENTID4args {
nfs_client_id4 client;
cb_client4 callback;
@@ -1298,6 +2182,7 @@ union SETCLIENTID4res switch (nfsstat4 status) {
void;
};
+/* Obsolete in NFSv4.1 */
struct SETCLIENTID_CONFIRM4args {
clientid4 clientid;
verifier4 setclientid_confirm;
@@ -1316,12 +2201,6 @@ struct VERIFY4res {
nfsstat4 status;
};
-enum stable_how4 {
- UNSTABLE4 = 0,
- DATA_SYNC4 = 1,
- FILE_SYNC4 = 2
-};
-
struct WRITE4args {
/* CURRENT_FH: file */
stateid4 stateid;
@@ -1343,6 +2222,7 @@ union WRITE4res switch (nfsstat4 status) {
void;
};
+/* Obsolete in NFSv4.1 */
struct RELEASE_LOCKOWNER4args {
lock_owner4 lock_owner;
};
@@ -1355,153 +2235,1037 @@ struct ILLEGAL4res {
nfsstat4 status;
};
+typedef opaque gsshandle4_t<>;
+
+struct gss_cb_handles4 {
+ rpc_gss_svc_t gcbp_service; /* RFC 2203 */
+ gsshandle4_t gcbp_handle_from_server;
+ gsshandle4_t gcbp_handle_from_client;
+};
+
+union callback_sec_parms4 switch (uint32_t cb_secflavor) {
+ case AUTH_NONE:
+ void;
+ case AUTH_SYS:
+ authsys_parms cbsp_sys_cred; /* RFC 5531 */
+ case RPCSEC_GSS:
+ gss_cb_handles4 cbsp_gss_handles;
+};
+
+struct BACKCHANNEL_CTL4args {
+ uint32_t bca_cb_program;
+ callback_sec_parms4 bca_sec_parms<>;
+};
+
+struct BACKCHANNEL_CTL4res {
+ nfsstat4 bcr_status;
+};
+
+enum channel_dir_from_client4 {
+ CDFC4_FORE = 0x1,
+ CDFC4_BACK = 0x2,
+ CDFC4_FORE_OR_BOTH = 0x3,
+ CDFC4_BACK_OR_BOTH = 0x7
+};
+
+struct BIND_CONN_TO_SESSION4args {
+ sessionid4 bctsa_sessid;
+
+ channel_dir_from_client4
+ bctsa_dir;
+
+ bool bctsa_use_conn_in_rdma_mode;
+};
+
+enum channel_dir_from_server4 {
+ CDFS4_FORE = 0x1,
+ CDFS4_BACK = 0x2,
+ CDFS4_BOTH = 0x3
+};
+
+struct BIND_CONN_TO_SESSION4resok {
+ sessionid4 bctsr_sessid;
+
+ channel_dir_from_server4
+ bctsr_dir;
+
+ bool bctsr_use_conn_in_rdma_mode;
+};
+
+union BIND_CONN_TO_SESSION4res
+ switch (nfsstat4 bctsr_status) {
+ case NFS4_OK:
+ BIND_CONN_TO_SESSION4resok bctsr_resok4;
+ default:
+ void;
+};
+
+const EXCHGID4_FLAG_SUPP_MOVED_REFER = 0x00000001;
+const EXCHGID4_FLAG_SUPP_MOVED_MIGR = 0x00000002;
+const EXCHGID4_FLAG_SUPP_FENCE_OPS = 0x00000004;
+
+const EXCHGID4_FLAG_BIND_PRINC_STATEID = 0x00000100;
+
+const EXCHGID4_FLAG_USE_NON_PNFS = 0x00010000;
+const EXCHGID4_FLAG_USE_PNFS_MDS = 0x00020000;
+const EXCHGID4_FLAG_USE_PNFS_DS = 0x00040000;
+
+const EXCHGID4_FLAG_MASK_PNFS = 0x00070000;
+
+const EXCHGID4_FLAG_UPD_CONFIRMED_REC_A = 0x40000000;
+const EXCHGID4_FLAG_CONFIRMED_R = 0x80000000;
+
+struct state_protect_ops4 {
+ bitmap4 spo_must_enforce;
+ bitmap4 spo_must_allow;
+};
+
+struct ssv_sp_parms4 {
+ state_protect_ops4 ssp_ops;
+ sec_oid4 ssp_hash_algs<>;
+ sec_oid4 ssp_encr_algs<>;
+ uint32_t ssp_window;
+ uint32_t ssp_num_gss_handles;
+};
+
+enum state_protect_how4 {
+ SP4_NONE = 0,
+ SP4_MACH_CRED = 1,
+ SP4_SSV = 2
+};
+
+union state_protect4_a switch (state_protect_how4 spa_how) {
+ case SP4_NONE:
+ void;
+ case SP4_MACH_CRED:
+ state_protect_ops4 spa_mach_ops;
+ case SP4_SSV:
+ ssv_sp_parms4 spa_ssv_parms;
+};
+
+struct EXCHANGE_ID4args {
+ client_owner4 eia_clientowner;
+ uint32_t eia_flags;
+ state_protect4_a eia_state_protect;
+ nfs_impl_id4 eia_client_impl_id<1>;
+};
+
+struct ssv_prot_info4 {
+ state_protect_ops4 spi_ops;
+ uint32_t spi_hash_alg;
+ uint32_t spi_encr_alg;
+ uint32_t spi_ssv_len;
+ uint32_t spi_window;
+ gsshandle4_t spi_handles<>;
+};
+
+union state_protect4_r switch (state_protect_how4 spr_how) {
+ case SP4_NONE:
+ void;
+ case SP4_MACH_CRED:
+ state_protect_ops4 spr_mach_ops;
+ case SP4_SSV:
+ ssv_prot_info4 spr_ssv_info;
+};
+
+struct EXCHANGE_ID4resok {
+ clientid4 eir_clientid;
+ sequenceid4 eir_sequenceid;
+ uint32_t eir_flags;
+ state_protect4_r eir_state_protect;
+ server_owner4 eir_server_owner;
+ opaque eir_server_scope<NFS4_OPAQUE_LIMIT>;
+ nfs_impl_id4 eir_server_impl_id<1>;
+};
+
+union EXCHANGE_ID4res switch (nfsstat4 eir_status) {
+ case NFS4_OK:
+ EXCHANGE_ID4resok eir_resok4;
+
+ default:
+ void;
+};
+
+struct channel_attrs4 {
+ count4 ca_headerpadsize;
+ count4 ca_maxrequestsize;
+ count4 ca_maxresponsesize;
+ count4 ca_maxresponsesize_cached;
+ count4 ca_maxoperations;
+ count4 ca_maxrequests;
+ uint32_t ca_rdma_ird<1>;
+};
+
+const CREATE_SESSION4_FLAG_PERSIST = 0x00000001;
+const CREATE_SESSION4_FLAG_CONN_BACK_CHAN = 0x00000002;
+const CREATE_SESSION4_FLAG_CONN_RDMA = 0x00000004;
+
+struct CREATE_SESSION4args {
+ clientid4 csa_clientid;
+ sequenceid4 csa_sequence;
+
+ uint32_t csa_flags;
+
+ channel_attrs4 csa_fore_chan_attrs;
+ channel_attrs4 csa_back_chan_attrs;
+
+ uint32_t csa_cb_program;
+ callback_sec_parms4 csa_sec_parms<>;
+};
+
+struct CREATE_SESSION4resok {
+ sessionid4 csr_sessionid;
+ sequenceid4 csr_sequence;
+
+ uint32_t csr_flags;
+
+ channel_attrs4 csr_fore_chan_attrs;
+ channel_attrs4 csr_back_chan_attrs;
+};
+
+union CREATE_SESSION4res switch (nfsstat4 csr_status) {
+ case NFS4_OK:
+ CREATE_SESSION4resok csr_resok4;
+ default:
+ void;
+};
+
+struct DESTROY_SESSION4args {
+ sessionid4 dsa_sessionid;
+};
+
+struct DESTROY_SESSION4res {
+ nfsstat4 dsr_status;
+};
+
+struct FREE_STATEID4args {
+ stateid4 fsa_stateid;
+};
+
+struct FREE_STATEID4res {
+ nfsstat4 fsr_status;
+};
+
+
+typedef nfstime4 attr_notice4;
+
+struct GET_DIR_DELEGATION4args {
+ /* CURRENT_FH: delegated directory */
+ bool gdda_signal_deleg_avail;
+ bitmap4 gdda_notification_types;
+ attr_notice4 gdda_child_attr_delay;
+ attr_notice4 gdda_dir_attr_delay;
+ bitmap4 gdda_child_attributes;
+ bitmap4 gdda_dir_attributes;
+};
+struct GET_DIR_DELEGATION4resok {
+ verifier4 gddr_cookieverf;
+ /* Stateid for get_dir_delegation */
+ stateid4 gddr_stateid;
+ /* Which notifications can the server support? */
+ bitmap4 gddr_notification;
+ bitmap4 gddr_child_attributes;
+ bitmap4 gddr_dir_attributes;
+};
+
+enum gddrnf4_status {
+ GDD4_OK = 0,
+ GDD4_UNAVAIL = 1
+};
+
+union GET_DIR_DELEGATION4res_non_fatal
+ switch (gddrnf4_status gddrnf_status) {
+ case GDD4_OK:
+ GET_DIR_DELEGATION4resok gddrnf_resok4;
+ case GDD4_UNAVAIL:
+ bool gddrnf_will_signal_deleg_avail;
+};
+
+union GET_DIR_DELEGATION4res
+ switch (nfsstat4 gddr_status) {
+ case NFS4_OK:
+ GET_DIR_DELEGATION4res_non_fatal gddr_res_non_fatal4;
+ default:
+ void;
+};
+
+struct GETDEVICEINFO4args {
+ deviceid4 gdia_device_id;
+ layouttype4 gdia_layout_type;
+ count4 gdia_maxcount;
+ bitmap4 gdia_notify_types;
+};
+
+struct GETDEVICEINFO4resok {
+ device_addr4 gdir_device_addr;
+ bitmap4 gdir_notification;
+};
+
+union GETDEVICEINFO4res switch (nfsstat4 gdir_status) {
+ case NFS4_OK:
+ GETDEVICEINFO4resok gdir_resok4;
+ case NFS4ERR_TOOSMALL:
+ count4 gdir_mincount;
+ default:
+ void;
+};
+
+struct GETDEVICELIST4args {
+ /* CURRENT_FH: object belonging to the file system */
+ layouttype4 gdla_layout_type;
+
+ /* Number of device IDs to return */
+ count4 gdla_maxdevices;
+
+ nfs_cookie4 gdla_cookie;
+ verifier4 gdla_cookieverf;
+};
+
+struct GETDEVICELIST4resok {
+ nfs_cookie4 gdlr_cookie;
+ verifier4 gdlr_cookieverf;
+ deviceid4 gdlr_deviceid_list<>;
+ bool gdlr_eof;
+};
+
+union GETDEVICELIST4res switch (nfsstat4 gdlr_status) {
+ case NFS4_OK:
+ GETDEVICELIST4resok gdlr_resok4;
+ default:
+ void;
+};
+
+union newtime4 switch (bool nt_timechanged) {
+ case TRUE:
+ nfstime4 nt_time;
+ case FALSE:
+ void;
+};
+
+union newoffset4 switch (bool no_newoffset) {
+ case TRUE:
+ offset4 no_offset;
+ case FALSE:
+ void;
+};
+
+struct LAYOUTCOMMIT4args {
+ /* CURRENT_FH: file */
+ offset4 loca_offset;
+ length4 loca_length;
+ bool loca_reclaim;
+ stateid4 loca_stateid;
+ newoffset4 loca_last_write_offset;
+ newtime4 loca_time_modify;
+ layoutupdate4 loca_layoutupdate;
+};
+union newsize4 switch (bool ns_sizechanged) {
+ case TRUE:
+ length4 ns_size;
+ case FALSE:
+ void;
+};
+
+struct LAYOUTCOMMIT4resok {
+ newsize4 locr_newsize;
+};
+
+union LAYOUTCOMMIT4res switch (nfsstat4 locr_status) {
+ case NFS4_OK:
+ LAYOUTCOMMIT4resok locr_resok4;
+ default:
+ void;
+};
+
+struct LAYOUTGET4args {
+ /* CURRENT_FH: file */
+ bool loga_signal_layout_avail;
+ layouttype4 loga_layout_type;
+ layoutiomode4 loga_iomode;
+ offset4 loga_offset;
+ length4 loga_length;
+ length4 loga_minlength;
+ stateid4 loga_stateid;
+ count4 loga_maxcount;
+};
+struct LAYOUTGET4resok {
+ bool logr_return_on_close;
+ stateid4 logr_stateid;
+ layout4 logr_layout<>;
+};
+
+union LAYOUTGET4res switch (nfsstat4 logr_status) {
+ case NFS4_OK:
+ LAYOUTGET4resok logr_resok4;
+ case NFS4ERR_LAYOUTTRYLATER:
+ bool logr_will_signal_layout_avail;
+ default:
+ void;
+};
+
+
+struct LAYOUTRETURN4args {
+ /* CURRENT_FH: file */
+ bool lora_reclaim;
+ layouttype4 lora_layout_type;
+ layoutiomode4 lora_iomode;
+ layoutreturn4 lora_layoutreturn;
+};
+
+
+union layoutreturn_stateid switch (bool lrs_present) {
+ case TRUE:
+ stateid4 lrs_stateid;
+ case FALSE:
+ void;
+};
+
+union LAYOUTRETURN4res switch (nfsstat4 lorr_status) {
+ case NFS4_OK:
+ layoutreturn_stateid lorr_stateid;
+ default:
+ void;
+};
+
+enum secinfo_style4 {
+ SECINFO_STYLE4_CURRENT_FH = 0,
+ SECINFO_STYLE4_PARENT = 1
+};
+
+/* CURRENT_FH: object or child directory */
+typedef secinfo_style4 SECINFO_NO_NAME4args;
+
+/* CURRENTFH: consumed if status is NFS4_OK */
+typedef SECINFO4res SECINFO_NO_NAME4res;
+
+struct SEQUENCE4args {
+ sessionid4 sa_sessionid;
+ sequenceid4 sa_sequenceid;
+ slotid4 sa_slotid;
+ slotid4 sa_highest_slotid;
+ bool sa_cachethis;
+};
+
+const SEQ4_STATUS_CB_PATH_DOWN = 0x00000001;
+const SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING = 0x00000002;
+const SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED = 0x00000004;
+const SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED = 0x00000008;
+const SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED = 0x00000010;
+const SEQ4_STATUS_ADMIN_STATE_REVOKED = 0x00000020;
+const SEQ4_STATUS_RECALLABLE_STATE_REVOKED = 0x00000040;
+const SEQ4_STATUS_LEASE_MOVED = 0x00000080;
+const SEQ4_STATUS_RESTART_RECLAIM_NEEDED = 0x00000100;
+const SEQ4_STATUS_CB_PATH_DOWN_SESSION = 0x00000200;
+const SEQ4_STATUS_BACKCHANNEL_FAULT = 0x00000400;
+const SEQ4_STATUS_DEVID_CHANGED = 0x00000800;
+const SEQ4_STATUS_DEVID_DELETED = 0x00001000;
+
+struct SEQUENCE4resok {
+ sessionid4 sr_sessionid;
+ sequenceid4 sr_sequenceid;
+ slotid4 sr_slotid;
+ slotid4 sr_highest_slotid;
+ slotid4 sr_target_highest_slotid;
+ uint32_t sr_status_flags;
+};
+
+union SEQUENCE4res switch (nfsstat4 sr_status) {
+ case NFS4_OK:
+ SEQUENCE4resok sr_resok4;
+ default:
+ void;
+};
+
+struct ssa_digest_input4 {
+ SEQUENCE4args sdi_seqargs;
+};
+
+struct SET_SSV4args {
+ opaque ssa_ssv<>;
+ opaque ssa_digest<>;
+};
+
+struct ssr_digest_input4 {
+ SEQUENCE4res sdi_seqres;
+};
+
+struct SET_SSV4resok {
+ opaque ssr_digest<>;
+};
+
+union SET_SSV4res switch (nfsstat4 ssr_status) {
+ case NFS4_OK:
+ SET_SSV4resok ssr_resok4;
+ default:
+ void;
+};
+
+struct TEST_STATEID4args {
+ stateid4 ts_stateids<>;
+};
+
+struct TEST_STATEID4resok {
+ nfsstat4 tsr_status_codes<>;
+};
+
+union TEST_STATEID4res switch (nfsstat4 tsr_status) {
+ case NFS4_OK:
+ TEST_STATEID4resok tsr_resok4;
+ default:
+ void;
+};
+
+union deleg_claim4 switch (open_claim_type4 dc_claim) {
/*
- * Operation arrays
+ * No special rights to object. Ordinary delegation
+ * request of the specified object. Object identified
+ * by filehandle.
*/
+ case CLAIM_FH: /* New to NFSv4.1 */
+ /* CURRENT_FH: object being delegated */
+ void;
-enum nfs_opnum4 {
- OP_ACCESS = 3,
- OP_CLOSE = 4,
- OP_COMMIT = 5,
- OP_CREATE = 6,
- OP_DELEGPURGE = 7,
- OP_DELEGRETURN = 8,
- OP_GETATTR = 9,
- OP_GETFH = 10,
- OP_LINK = 11,
- OP_LOCK = 12,
- OP_LOCKT = 13,
- OP_LOCKU = 14,
- OP_LOOKUP = 15,
- OP_LOOKUPP = 16,
- OP_NVERIFY = 17,
- OP_OPEN = 18,
- OP_OPENATTR = 19,
- OP_OPEN_CONFIRM = 20,
- OP_OPEN_DOWNGRADE = 21,
- OP_PUTFH = 22,
- OP_PUTPUBFH = 23,
- OP_PUTROOTFH = 24,
- OP_READ = 25,
- OP_READDIR = 26,
- OP_READLINK = 27,
- OP_REMOVE = 28,
- OP_RENAME = 29,
- OP_RENEW = 30,
- OP_RESTOREFH = 31,
- OP_SAVEFH = 32,
- OP_SECINFO = 33,
- OP_SETATTR = 34,
- OP_SETCLIENTID = 35,
- OP_SETCLIENTID_CONFIRM = 36,
- OP_VERIFY = 37,
- OP_WRITE = 38,
- OP_RELEASE_LOCKOWNER = 39,
- OP_ILLEGAL = 10044
+/*
+ * Right to file based on a delegation granted
+ * to a previous boot instance of the client.
+ * File is specified by filehandle.
+ */
+ case CLAIM_DELEG_PREV_FH: /* New to NFSv4.1 */
+ /* CURRENT_FH: object being delegated */
+ void;
+
+/*
+ * Right to the file established by an open previous
+ * to server reboot. File identified by filehandle.
+ * Used during server reclaim grace period.
+ */
+ case CLAIM_PREVIOUS:
+ /* CURRENT_FH: object being reclaimed */
+ open_delegation_type4 dc_delegate_type;
+};
+
+struct WANT_DELEGATION4args {
+ uint32_t wda_want;
+ deleg_claim4 wda_claim;
+};
+
+union WANT_DELEGATION4res switch (nfsstat4 wdr_status) {
+ case NFS4_OK:
+ open_delegation4 wdr_resok4;
+ default:
+ void;
+};
+
+struct DESTROY_CLIENTID4args {
+ clientid4 dca_clientid;
+};
+
+struct DESTROY_CLIENTID4res {
+ nfsstat4 dcr_status;
+};
+
+struct RECLAIM_COMPLETE4args {
+ /*
+ * If rca_one_fs TRUE,
+ *
+ * CURRENT_FH: object in
+ * file system for which the
+ * reclaim is complete.
+ */
+ bool rca_one_fs;
+};
+
+struct RECLAIM_COMPLETE4res {
+ nfsstat4 rcr_status;
+};
+
+struct COPY4args {
+ /* SAVED_FH: source file */
+ /* CURRENT_FH: destination file */
+ stateid4 ca_src_stateid;
+ stateid4 ca_dst_stateid;
+ offset4 ca_src_offset;
+ offset4 ca_dst_offset;
+ length4 ca_count;
+ bool ca_consecutive;
+ bool ca_synchronous;
+ netloc4 ca_source_server<>;
+};
+
+
+struct copy_requirements4 {
+ bool cr_consecutive;
+ bool cr_synchronous;
+};
+
+struct COPY4resok {
+ write_response4 cr_response;
+ copy_requirements4 cr_requirements;
+};
+
+union COPY4res switch (nfsstat4 cr_status) {
+ case NFS4_OK:
+ COPY4resok cr_resok4;
+ case NFS4ERR_OFFLOAD_NO_REQS:
+ copy_requirements4 cr_requirements;
+ default:
+ void;
+};
+
+struct COPY_NOTIFY4args {
+ /* CURRENT_FH: source file */
+ stateid4 cna_src_stateid;
+ netloc4 cna_destination_server;
+};
+
+struct COPY_NOTIFY4resok {
+ nfstime4 cnr_lease_time;
+ stateid4 cnr_stateid;
+ netloc4 cnr_source_server<>;
+};
+
+union COPY_NOTIFY4res switch (nfsstat4 cnr_status) {
+ case NFS4_OK:
+ COPY_NOTIFY4resok resok4;
+ default:
+ void;
+};
+
+struct OFFLOAD_CANCEL4args {
+ /* CURRENT_FH: file to cancel */
+ stateid4 oca_stateid;
+};
+
+struct OFFLOAD_CANCEL4res {
+ nfsstat4 ocr_status;
+};
+
+
+struct OFFLOAD_STATUS4args {
+ /* CURRENT_FH: destination file */
+ stateid4 osa_stateid;
+};
+
+struct OFFLOAD_STATUS4resok {
+ length4 osr_count;
+ nfsstat4 osr_complete<1>;
+};
+
+union OFFLOAD_STATUS4res switch (nfsstat4 osr_status) {
+ case NFS4_OK:
+ OFFLOAD_STATUS4resok osr_resok4;
+ default:
+ void;
+};
+
+struct ALLOCATE4args {
+ /* CURRENT_FH: file */
+ stateid4 aa_stateid;
+ offset4 aa_offset;
+ length4 aa_length;
+};
+struct ALLOCATE4res {
+ nfsstat4 ar_status;
+};
+
+struct DEALLOCATE4args {
+ /* CURRENT_FH: file */
+ stateid4 da_stateid;
+ offset4 da_offset;
+ length4 da_length;
+};
+
+
+struct DEALLOCATE4res {
+ nfsstat4 dr_status;
+};
+enum IO_ADVISE_type4 {
+ IO_ADVISE4_NORMAL = 0,
+ IO_ADVISE4_SEQUENTIAL = 1,
+ IO_ADVISE4_SEQUENTIAL_BACKWARDS = 2,
+ IO_ADVISE4_RANDOM = 3,
+ IO_ADVISE4_WILLNEED = 4,
+ IO_ADVISE4_WILLNEED_OPPORTUNISTIC = 5,
+ IO_ADVISE4_DONTNEED = 6,
+ IO_ADVISE4_NOREUSE = 7,
+ IO_ADVISE4_READ = 8,
+ IO_ADVISE4_WRITE = 9,
+ IO_ADVISE4_INIT_PROXIMITY = 10
+};
+
+struct IO_ADVISE4args {
+ /* CURRENT_FH: file */
+ stateid4 iaa_stateid;
+ offset4 iaa_offset;
+ length4 iaa_count;
+ bitmap4 iaa_hints;
+};
+
+struct IO_ADVISE4resok {
+ bitmap4 ior_hints;
+};
+
+union IO_ADVISE4res switch (nfsstat4 ior_status) {
+ case NFS4_OK:
+ IO_ADVISE4resok resok4;
+ default:
+ void;
};
+
+struct device_error4 {
+ deviceid4 de_deviceid;
+ nfsstat4 de_status;
+ nfs_opnum4 de_opnum;
+};
+
+
+struct LAYOUTERROR4args {
+ /* CURRENT_FH: file */
+ offset4 lea_offset;
+ length4 lea_length;
+ stateid4 lea_stateid;
+ device_error4 lea_errors<>;
+};
+
+struct LAYOUTERROR4res {
+ nfsstat4 ler_status;
+};
+
+struct io_info4 {
+ uint64_t ii_count;
+ uint64_t ii_bytes;
+};
+
+struct LAYOUTSTATS4args {
+ /* CURRENT_FH: file */
+ offset4 lsa_offset;
+ length4 lsa_length;
+ stateid4 lsa_stateid;
+ io_info4 lsa_read;
+ io_info4 lsa_write;
+ deviceid4 lsa_deviceid;
+ layoutupdate4 lsa_layoutupdate;
+};
+
+struct LAYOUTSTATS4res {
+ nfsstat4 lsr_status;
+};
+
+struct READ_PLUS4args {
+ /* CURRENT_FH: file */
+ stateid4 rpa_stateid;
+ offset4 rpa_offset;
+ count4 rpa_count;
+};
+union read_plus_content switch (data_content4 rpc_content) {
+ case NFS4_CONTENT_DATA:
+ data4 rpc_data;
+ case NFS4_CONTENT_HOLE:
+ data_info4 rpc_hole;
+ default:
+ void;
+};
+
+/*
+ * Allow a return of an array of contents.
+ */
+struct read_plus_res4 {
+ bool rpr_eof;
+ read_plus_content rpr_contents<>;
+};
+
+union READ_PLUS4res switch (nfsstat4 rp_status) {
+ case NFS4_OK:
+ read_plus_res4 rp_resok4;
+ default:
+ void;
+};
+
+struct SEEK4args {
+ /* CURRENT_FH: file */
+ stateid4 sa_stateid;
+ offset4 sa_offset;
+ data_content4 sa_what;
+};
+struct seek_res4 {
+ bool sr_eof;
+ offset4 sr_offset;
+};
+union SEEK4res switch (nfsstat4 sa_status) {
+ case NFS4_OK:
+ seek_res4 resok4;
+ default:
+ void;
+};
+
+struct WRITE_SAME4args {
+ /* CURRENT_FH: file */
+ stateid4 wsa_stateid;
+ stable_how4 wsa_stable;
+ app_data_block4 wsa_adb;
+};
+
+
+union WRITE_SAME4res switch (nfsstat4 wsr_status) {
+ case NFS4_OK:
+ write_response4 resok4;
+ default:
+ void;
+};
+
+
+/*
+ * Operation arrays (the rest)
+ */
+
union nfs_argop4 switch (nfs_opnum4 argop) {
- case OP_ACCESS: ACCESS4args opaccess;
- case OP_CLOSE: CLOSE4args opclose;
- case OP_COMMIT: COMMIT4args opcommit;
- case OP_CREATE: CREATE4args opcreate;
- case OP_DELEGPURGE: DELEGPURGE4args opdelegpurge;
- case OP_DELEGRETURN: DELEGRETURN4args opdelegreturn;
- case OP_GETATTR: GETATTR4args opgetattr;
- case OP_GETFH: void;
- case OP_LINK: LINK4args oplink;
- case OP_LOCK: LOCK4args oplock;
- case OP_LOCKT: LOCKT4args oplockt;
- case OP_LOCKU: LOCKU4args oplocku;
- case OP_LOOKUP: LOOKUP4args oplookup;
- case OP_LOOKUPP: void;
- case OP_NVERIFY: NVERIFY4args opnverify;
- case OP_OPEN: OPEN4args opopen;
- case OP_OPENATTR: OPENATTR4args opopenattr;
- case OP_OPEN_CONFIRM: OPEN_CONFIRM4args opopen_confirm;
- case OP_OPEN_DOWNGRADE:
- OPEN_DOWNGRADE4args opopen_downgrade;
- case OP_PUTFH: PUTFH4args opputfh;
- case OP_PUTPUBFH: void;
- case OP_PUTROOTFH: void;
- case OP_READ: READ4args opread;
- case OP_READDIR: READDIR4args opreaddir;
- case OP_READLINK: void;
- case OP_REMOVE: REMOVE4args opremove;
- case OP_RENAME: RENAME4args oprename;
- case OP_RENEW: RENEW4args oprenew;
- case OP_RESTOREFH: void;
- case OP_SAVEFH: void;
- case OP_SECINFO: SECINFO4args opsecinfo;
- case OP_SETATTR: SETATTR4args opsetattr;
- case OP_SETCLIENTID: SETCLIENTID4args opsetclientid;
- case OP_SETCLIENTID_CONFIRM: SETCLIENTID_CONFIRM4args
- opsetclientid_confirm;
- case OP_VERIFY: VERIFY4args opverify;
- case OP_WRITE: WRITE4args opwrite;
+ case OP_ACCESS: ACCESS4args opaccess;
+ case OP_CLOSE: CLOSE4args opclose;
+ case OP_COMMIT: COMMIT4args opcommit;
+ case OP_CREATE: CREATE4args opcreate;
+ case OP_DELEGPURGE: DELEGPURGE4args opdelegpurge;
+ case OP_DELEGRETURN: DELEGRETURN4args opdelegreturn;
+ case OP_GETATTR: GETATTR4args opgetattr;
+ case OP_GETFH: void;
+ case OP_LINK: LINK4args oplink;
+ case OP_LOCK: LOCK4args oplock;
+ case OP_LOCKT: LOCKT4args oplockt;
+ case OP_LOCKU: LOCKU4args oplocku;
+ case OP_LOOKUP: LOOKUP4args oplookup;
+ case OP_LOOKUPP: void;
+ case OP_NVERIFY: NVERIFY4args opnverify;
+ case OP_OPEN: OPEN4args opopen;
+ case OP_OPENATTR: OPENATTR4args opopenattr;
+
+ /* Not for NFSv4.1 */
+ case OP_OPEN_CONFIRM: OPEN_CONFIRM4args opopen_confirm;
+
+ case OP_OPEN_DOWNGRADE: OPEN_DOWNGRADE4args opopen_downgrade;
+
+ case OP_PUTFH: PUTFH4args opputfh;
+ case OP_PUTPUBFH: void;
+ case OP_PUTROOTFH: void;
+ case OP_READ: READ4args opread;
+ case OP_READDIR: READDIR4args opreaddir;
+ case OP_READLINK: void;
+ case OP_REMOVE: REMOVE4args opremove;
+ case OP_RENAME: RENAME4args oprename;
+
+ /* Not for NFSv4.1 */
+ case OP_RENEW: RENEW4args oprenew;
+
+ case OP_RESTOREFH: void;
+ case OP_SAVEFH: void;
+ case OP_SECINFO: SECINFO4args opsecinfo;
+ case OP_SETATTR: SETATTR4args opsetattr;
+
+ /* Not for NFSv4.1 */
+ case OP_SETCLIENTID: SETCLIENTID4args opsetclientid;
+
+ /* Not for NFSv4.1 */
+ case OP_SETCLIENTID_CONFIRM:
+ SETCLIENTID_CONFIRM4args
+ opsetclientid_confirm;
+
+ case OP_VERIFY: VERIFY4args opverify;
+ case OP_WRITE: WRITE4args opwrite;
+
+ /* Not for NFSv4.1 */
case OP_RELEASE_LOCKOWNER:
- RELEASE_LOCKOWNER4args
- oprelease_lockowner;
- case OP_ILLEGAL: void;
+ RELEASE_LOCKOWNER4args
+ oprelease_lockowner;
+
+ /* Operations new to NFSv4.1 */
+ case OP_BACKCHANNEL_CTL:
+ BACKCHANNEL_CTL4args opbackchannel_ctl;
+
+ case OP_BIND_CONN_TO_SESSION:
+ BIND_CONN_TO_SESSION4args
+ opbind_conn_to_session;
+
+ case OP_EXCHANGE_ID: EXCHANGE_ID4args opexchange_id;
+
+ case OP_CREATE_SESSION: CREATE_SESSION4args opcreate_session;
+
+ case OP_DESTROY_SESSION:
+ DESTROY_SESSION4args opdestroy_session;
+
+ case OP_FREE_STATEID: FREE_STATEID4args opfree_stateid;
+
+ case OP_GET_DIR_DELEGATION:
+ GET_DIR_DELEGATION4args
+ opget_dir_delegation;
+
+ case OP_GETDEVICEINFO: GETDEVICEINFO4args opgetdeviceinfo;
+ case OP_GETDEVICELIST: GETDEVICELIST4args opgetdevicelist;
+ case OP_LAYOUTCOMMIT: LAYOUTCOMMIT4args oplayoutcommit;
+ case OP_LAYOUTGET: LAYOUTGET4args oplayoutget;
+ case OP_LAYOUTRETURN: LAYOUTRETURN4args oplayoutreturn;
+
+ case OP_SECINFO_NO_NAME:
+ SECINFO_NO_NAME4args opsecinfo_no_name;
+
+ case OP_SEQUENCE: SEQUENCE4args opsequence;
+ case OP_SET_SSV: SET_SSV4args opset_ssv;
+ case OP_TEST_STATEID: TEST_STATEID4args optest_stateid;
+
+ case OP_WANT_DELEGATION:
+ WANT_DELEGATION4args opwant_delegation;
+
+ case OP_DESTROY_CLIENTID:
+ DESTROY_CLIENTID4args
+ opdestroy_clientid;
+
+ case OP_RECLAIM_COMPLETE:
+ RECLAIM_COMPLETE4args
+ opreclaim_complete;
+
+ /* Operations new to NFSv4.2 */
+ case OP_ALLOCATE: ALLOCATE4args opallocate;
+ case OP_COPY: COPY4args opcopy;
+ case OP_COPY_NOTIFY: COPY_NOTIFY4args opoffload_notify;
+ case OP_DEALLOCATE: DEALLOCATE4args opdeallocate;
+ case OP_IO_ADVISE: IO_ADVISE4args opio_advise;
+ case OP_LAYOUTERROR: LAYOUTERROR4args oplayouterror;
+ case OP_LAYOUTSTATS: LAYOUTSTATS4args oplayoutstats;
+ case OP_OFFLOAD_CANCEL: OFFLOAD_CANCEL4args opoffload_cancel;
+ case OP_OFFLOAD_STATUS: OFFLOAD_STATUS4args opoffload_status;
+ case OP_READ_PLUS: READ_PLUS4args opread_plus;
+ case OP_SEEK: SEEK4args opseek;
+ case OP_WRITE_SAME: WRITE_SAME4args opwrite_same;
+ case OP_CLONE: CLONE4args opclone;
+
+ /* Operations not new to NFSv4.1 */
+ case OP_ILLEGAL: void;
};
union nfs_resop4 switch (nfs_opnum4 resop) {
- case OP_ACCESS: ACCESS4res opaccess;
- case OP_CLOSE: CLOSE4res opclose;
- case OP_COMMIT: COMMIT4res opcommit;
- case OP_CREATE: CREATE4res opcreate;
- case OP_DELEGPURGE: DELEGPURGE4res opdelegpurge;
- case OP_DELEGRETURN: DELEGRETURN4res opdelegreturn;
- case OP_GETATTR: GETATTR4res opgetattr;
- case OP_GETFH: GETFH4res opgetfh;
- case OP_LINK: LINK4res oplink;
- case OP_LOCK: LOCK4res oplock;
- case OP_LOCKT: LOCKT4res oplockt;
- case OP_LOCKU: LOCKU4res oplocku;
- case OP_LOOKUP: LOOKUP4res oplookup;
- case OP_LOOKUPP: LOOKUPP4res oplookupp;
- case OP_NVERIFY: NVERIFY4res opnverify;
- case OP_OPEN: OPEN4res opopen;
- case OP_OPENATTR: OPENATTR4res opopenattr;
- case OP_OPEN_CONFIRM: OPEN_CONFIRM4res opopen_confirm;
- case OP_OPEN_DOWNGRADE:
- OPEN_DOWNGRADE4res
- opopen_downgrade;
- case OP_PUTFH: PUTFH4res opputfh;
- case OP_PUTPUBFH: PUTPUBFH4res opputpubfh;
- case OP_PUTROOTFH: PUTROOTFH4res opputrootfh;
- case OP_READ: READ4res opread;
- case OP_READDIR: READDIR4res opreaddir;
- case OP_READLINK: READLINK4res opreadlink;
- case OP_REMOVE: REMOVE4res opremove;
- case OP_RENAME: RENAME4res oprename;
- case OP_RENEW: RENEW4res oprenew;
- case OP_RESTOREFH: RESTOREFH4res oprestorefh;
- case OP_SAVEFH: SAVEFH4res opsavefh;
- case OP_SECINFO: SECINFO4res opsecinfo;
- case OP_SETATTR: SETATTR4res opsetattr;
- case OP_SETCLIENTID: SETCLIENTID4res opsetclientid;
+ case OP_ACCESS: ACCESS4res opaccess;
+ case OP_CLOSE: CLOSE4res opclose;
+ case OP_COMMIT: COMMIT4res opcommit;
+ case OP_CREATE: CREATE4res opcreate;
+ case OP_DELEGPURGE: DELEGPURGE4res opdelegpurge;
+ case OP_DELEGRETURN: DELEGRETURN4res opdelegreturn;
+ case OP_GETATTR: GETATTR4res opgetattr;
+ case OP_GETFH: GETFH4res opgetfh;
+ case OP_LINK: LINK4res oplink;
+ case OP_LOCK: LOCK4res oplock;
+ case OP_LOCKT: LOCKT4res oplockt;
+ case OP_LOCKU: LOCKU4res oplocku;
+ case OP_LOOKUP: LOOKUP4res oplookup;
+ case OP_LOOKUPP: LOOKUPP4res oplookupp;
+ case OP_NVERIFY: NVERIFY4res opnverify;
+ case OP_OPEN: OPEN4res opopen;
+ case OP_OPENATTR: OPENATTR4res opopenattr;
+ /* Not for NFSv4.1 */
+ case OP_OPEN_CONFIRM: OPEN_CONFIRM4res opopen_confirm;
+
+ case OP_OPEN_DOWNGRADE: OPEN_DOWNGRADE4res opopen_downgrade;
+
+ case OP_PUTFH: PUTFH4res opputfh;
+ case OP_PUTPUBFH: PUTPUBFH4res opputpubfh;
+ case OP_PUTROOTFH: PUTROOTFH4res opputrootfh;
+ case OP_READ: READ4res opread;
+ case OP_READDIR: READDIR4res opreaddir;
+ case OP_READLINK: READLINK4res opreadlink;
+ case OP_REMOVE: REMOVE4res opremove;
+ case OP_RENAME: RENAME4res oprename;
+ /* Not for NFSv4.1 */
+ case OP_RENEW: RENEW4res oprenew;
+ case OP_RESTOREFH: RESTOREFH4res oprestorefh;
+ case OP_SAVEFH: SAVEFH4res opsavefh;
+ case OP_SECINFO: SECINFO4res opsecinfo;
+ case OP_SETATTR: SETATTR4res opsetattr;
+ /* Not for NFSv4.1 */
+ case OP_SETCLIENTID: SETCLIENTID4res opsetclientid;
+
+ /* Not for NFSv4.1 */
case OP_SETCLIENTID_CONFIRM:
- SETCLIENTID_CONFIRM4res
- opsetclientid_confirm;
- case OP_VERIFY: VERIFY4res opverify;
- case OP_WRITE: WRITE4res opwrite;
+ SETCLIENTID_CONFIRM4res
+ opsetclientid_confirm;
+ case OP_VERIFY: VERIFY4res opverify;
+ case OP_WRITE: WRITE4res opwrite;
+
+ /* Not for NFSv4.1 */
case OP_RELEASE_LOCKOWNER:
- RELEASE_LOCKOWNER4res
- oprelease_lockowner;
- case OP_ILLEGAL: ILLEGAL4res opillegal;
+ RELEASE_LOCKOWNER4res
+ oprelease_lockowner;
+
+ /* Operations new to NFSv4.1 */
+ case OP_BACKCHANNEL_CTL:
+ BACKCHANNEL_CTL4res opbackchannel_ctl;
+
+ case OP_BIND_CONN_TO_SESSION:
+ BIND_CONN_TO_SESSION4res
+ opbind_conn_to_session;
+
+ case OP_EXCHANGE_ID: EXCHANGE_ID4res opexchange_id;
+
+ case OP_CREATE_SESSION: CREATE_SESSION4res opcreate_session;
+
+ case OP_DESTROY_SESSION:
+ DESTROY_SESSION4res opdestroy_session;
+
+ case OP_FREE_STATEID: FREE_STATEID4res opfree_stateid;
+
+ case OP_GET_DIR_DELEGATION:
+ GET_DIR_DELEGATION4res
+ opget_dir_delegation;
+
+ case OP_GETDEVICEINFO: GETDEVICEINFO4res opgetdeviceinfo;
+ case OP_GETDEVICELIST: GETDEVICELIST4res opgetdevicelist;
+ case OP_LAYOUTCOMMIT: LAYOUTCOMMIT4res oplayoutcommit;
+ case OP_LAYOUTGET: LAYOUTGET4res oplayoutget;
+ case OP_LAYOUTRETURN: LAYOUTRETURN4res oplayoutreturn;
+
+ case OP_SECINFO_NO_NAME:
+ SECINFO_NO_NAME4res opsecinfo_no_name;
+
+ case OP_SEQUENCE: SEQUENCE4res opsequence;
+ case OP_SET_SSV: SET_SSV4res opset_ssv;
+ case OP_TEST_STATEID: TEST_STATEID4res optest_stateid;
+
+ case OP_WANT_DELEGATION:
+ WANT_DELEGATION4res opwant_delegation;
+
+ case OP_DESTROY_CLIENTID:
+ DESTROY_CLIENTID4res
+ opdestroy_clientid;
+
+ case OP_RECLAIM_COMPLETE:
+ RECLAIM_COMPLETE4res
+ opreclaim_complete;
+
+ /* Operations new to NFSv4.2 */
+ case OP_ALLOCATE: ALLOCATE4res opallocate;
+ case OP_COPY: COPY4res opcopy;
+ case OP_COPY_NOTIFY: COPY_NOTIFY4res opcopy_notify;
+ case OP_DEALLOCATE: DEALLOCATE4res opdeallocate;
+ case OP_IO_ADVISE: IO_ADVISE4res opio_advise;
+ case OP_LAYOUTERROR: LAYOUTERROR4res oplayouterror;
+ case OP_LAYOUTSTATS: LAYOUTSTATS4res oplayoutstats;
+ case OP_OFFLOAD_CANCEL: OFFLOAD_CANCEL4res opoffload_cancel;
+ case OP_OFFLOAD_STATUS: OFFLOAD_STATUS4res opoffload_status;
+ case OP_READ_PLUS: READ_PLUS4res opread_plus;
+ case OP_SEEK: SEEK4res opseek;
+ case OP_WRITE_SAME: WRITE_SAME4res opwrite_same;
+ case OP_CLONE: CLONE4res opclone;
+
+ /* Operations not new to NFSv4.1 */
+ case OP_ILLEGAL: ILLEGAL4res opillegal;
};
struct COMPOUND4args {
- utf8str_cs tag;
- uint32_t minorversion;
- nfs_argop4 argarray<>;
+ utf8str_cs tag;
+ uint32_t minorversion;
+ nfs_argop4 argarray<>;
};
struct COMPOUND4res {
- nfsstat4 status;
- utf8str_cs tag;
- nfs_resop4 resarray<>;
+ nfsstat4 status;
+ utf8str_cs tag;
+ nfs_resop4 resarray<>;
};
@@ -1511,10 +3275,10 @@ struct COMPOUND4res {
program NFS4_PROGRAM {
version NFS_V4 {
void
- NFSPROC4_NULL(void) = 0;
+ NFSPROC4_NULL(void) = 0;
COMPOUND4res
- NFSPROC4_COMPOUND(COMPOUND4args) = 1;
+ NFSPROC4_COMPOUND(COMPOUND4args) = 1;
} = 4;
} = 100003;
@@ -1556,24 +3320,361 @@ struct CB_ILLEGAL4res {
};
/*
- * Various definitions for CB_COMPOUND
+ * NFSv4.1 callback arguments and results
*/
-enum nfs_cb_opnum4 {
- OP_CB_GETATTR = 3,
- OP_CB_RECALL = 4,
- OP_CB_ILLEGAL = 10044
+
+enum layoutrecall_type4 {
+ LAYOUTRECALL4_FILE = LAYOUT4_RET_REC_FILE,
+ LAYOUTRECALL4_FSID = LAYOUT4_RET_REC_FSID,
+ LAYOUTRECALL4_ALL = LAYOUT4_RET_REC_ALL
};
-union nfs_cb_argop4 switch (unsigned argop) {
- case OP_CB_GETATTR: CB_GETATTR4args opcbgetattr;
- case OP_CB_RECALL: CB_RECALL4args opcbrecall;
- case OP_CB_ILLEGAL: void;
+struct layoutrecall_file4 {
+ nfs_fh4 lor_fh;
+ offset4 lor_offset;
+ length4 lor_length;
+ stateid4 lor_stateid;
};
-union nfs_cb_resop4 switch (unsigned resop) {
- case OP_CB_GETATTR: CB_GETATTR4res opcbgetattr;
- case OP_CB_RECALL: CB_RECALL4res opcbrecall;
- case OP_CB_ILLEGAL: CB_ILLEGAL4res opcbillegal;
+union layoutrecall4 switch (layoutrecall_type4 lor_recalltype) {
+ case LAYOUTRECALL4_FILE:
+ layoutrecall_file4 lor_layout;
+ case LAYOUTRECALL4_FSID:
+ fsid4 lor_fsid;
+ case LAYOUTRECALL4_ALL:
+ void;
+};
+
+struct CB_LAYOUTRECALL4args {
+ layouttype4 clora_type;
+ layoutiomode4 clora_iomode;
+ bool clora_changed;
+ layoutrecall4 clora_recall;
+};
+struct CB_LAYOUTRECALL4res {
+ nfsstat4 clorr_status;
+};
+
+/*
+ * Directory notification types
+ */
+enum notify_type4 {
+ NOTIFY4_CHANGE_CHILD_ATTRS = 0,
+ NOTIFY4_CHANGE_DIR_ATTRS = 1,
+ NOTIFY4_REMOVE_ENTRY = 2,
+ NOTIFY4_ADD_ENTRY = 3,
+ NOTIFY4_RENAME_ENTRY = 4,
+ NOTIFY4_CHANGE_COOKIE_VERIFIER = 5
+};
+
+/* Changed entry information */
+struct notify_entry4 {
+ component4 ne_file;
+ fattr4 ne_attrs;
+};
+
+/* Previous entry information */
+struct prev_entry4 {
+ notify_entry4 pe_prev_entry;
+ /* What READDIR returned for this entry */
+ nfs_cookie4 pe_prev_entry_cookie;
+};
+
+struct notify_remove4 {
+ notify_entry4 nrm_old_entry;
+ nfs_cookie4 nrm_old_entry_cookie;
+};
+
+struct notify_add4 {
+ /*
+ * During a rename, contains
+ * the object that was deleted.
+ */
+ notify_remove4 nad_old_entry<1>;
+ notify_entry4 nad_new_entry;
+ /* What READDIR would have returned for this entry */
+ nfs_cookie4 nad_new_entry_cookie<1>;
+ prev_entry4 nad_prev_entry<1>;
+ bool nad_last_entry;
+};
+
+struct notify_attr4 {
+ notify_entry4 na_changed_entry;
+};
+
+struct notify_rename4 {
+ notify_remove4 nrn_old_entry;
+ notify_add4 nrn_new_entry;
+};
+
+struct notify_verifier4 {
+ verifier4 nv_old_cookieverf;
+ verifier4 nv_new_cookieverf;
+};
+
+/*
+ * Objects of type notify_<>4 and
+ * notify_device_<>4 are encoded in this.
+ */
+typedef opaque notifylist4<>;
+
+struct notify4 {
+ /* Composed from notify_type4 or notify_deviceid_type4 */
+ bitmap4 notify_mask;
+ notifylist4 notify_vals;
+};
+
+struct CB_NOTIFY4args {
+ stateid4 cna_stateid;
+ nfs_fh4 cna_fh;
+ notify4 cna_changes<>;
+};
+
+struct CB_NOTIFY4res {
+ nfsstat4 cnr_status;
+};
+
+struct CB_PUSH_DELEG4args {
+ nfs_fh4 cpda_fh;
+ open_delegation4 cpda_delegation;
+
+};
+
+struct CB_PUSH_DELEG4res {
+ nfsstat4 cpdr_status;
+};
+
+const RCA4_TYPE_MASK_RDATA_DLG = 0;
+const RCA4_TYPE_MASK_WDATA_DLG = 1;
+const RCA4_TYPE_MASK_DIR_DLG = 2;
+const RCA4_TYPE_MASK_FILE_LAYOUT = 3;
+const RCA4_TYPE_MASK_BLK_LAYOUT = 4;
+const RCA4_TYPE_MASK_OBJ_LAYOUT_MIN = 8;
+const RCA4_TYPE_MASK_OBJ_LAYOUT_MAX = 9;
+const RCA4_TYPE_MASK_OTHER_LAYOUT_MIN = 12;
+const RCA4_TYPE_MASK_OTHER_LAYOUT_MAX = 15;
+
+struct CB_RECALL_ANY4args {
+ uint32_t craa_objects_to_keep;
+ bitmap4 craa_type_mask;
+};
+
+struct CB_RECALL_ANY4res {
+ nfsstat4 crar_status;
+};
+
+typedef CB_RECALL_ANY4args CB_RECALLABLE_OBJ_AVAIL4args;
+
+struct CB_RECALLABLE_OBJ_AVAIL4res {
+ nfsstat4 croa_status;
+};
+
+struct CB_RECALL_SLOT4args {
+ slotid4 rsa_target_highest_slotid;
+};
+
+struct CB_RECALL_SLOT4res {
+ nfsstat4 rsr_status;
+};
+
+struct referring_call4 {
+ sequenceid4 rc_sequenceid;
+ slotid4 rc_slotid;
+};
+
+struct referring_call_list4 {
+ sessionid4 rcl_sessionid;
+ referring_call4 rcl_referring_calls<>;
+};
+
+struct CB_SEQUENCE4args {
+ sessionid4 csa_sessionid;
+ sequenceid4 csa_sequenceid;
+ slotid4 csa_slotid;
+ slotid4 csa_highest_slotid;
+ bool csa_cachethis;
+ referring_call_list4 csa_referring_call_lists<>;
+};
+
+struct CB_SEQUENCE4resok {
+ sessionid4 csr_sessionid;
+ sequenceid4 csr_sequenceid;
+ slotid4 csr_slotid;
+ slotid4 csr_highest_slotid;
+ slotid4 csr_target_highest_slotid;
+};
+
+union CB_SEQUENCE4res switch (nfsstat4 csr_status) {
+ case NFS4_OK:
+ CB_SEQUENCE4resok csr_resok4;
+ default:
+ void;
+};
+
+struct CB_WANTS_CANCELLED4args {
+ bool cwca_contended_wants_cancelled;
+ bool cwca_resourced_wants_cancelled;
+};
+
+struct CB_WANTS_CANCELLED4res {
+ nfsstat4 cwcr_status;
+};
+
+struct CB_NOTIFY_LOCK4args {
+ nfs_fh4 cnla_fh;
+ lock_owner4 cnla_lock_owner;
+};
+
+struct CB_NOTIFY_LOCK4res {
+ nfsstat4 cnlr_status;
+};
+
+/*
+ * Device notification types
+ */
+enum notify_deviceid_type4 {
+ NOTIFY_DEVICEID4_CHANGE = 1,
+ NOTIFY_DEVICEID4_DELETE = 2
+};
+
+/* For NOTIFY4_DEVICEID4_DELETE */
+struct notify_deviceid_delete4 {
+ layouttype4 ndd_layouttype;
+ deviceid4 ndd_deviceid;
+};
+
+/* For NOTIFY4_DEVICEID4_CHANGE */
+struct notify_deviceid_change4 {
+ layouttype4 ndc_layouttype;
+ deviceid4 ndc_deviceid;
+ bool ndc_immediate;
+};
+
+struct CB_NOTIFY_DEVICEID4args {
+ notify4 cnda_changes<>;
+};
+
+struct CB_NOTIFY_DEVICEID4res {
+ nfsstat4 cndr_status;
+};
+
+union offload_info4 switch (nfsstat4 coa_status) {
+ case NFS4_OK:
+ write_response4 coa_resok4;
+ default:
+ length4 coa_bytes_copied;
+};
+struct CB_OFFLOAD4args {
+ nfs_fh4 coa_fh;
+ stateid4 coa_stateid;
+ offload_info4 coa_offload_info;
+};
+struct CB_OFFLOAD4res {
+ nfsstat4 cor_status;
+};
+/*
+ * Various definitions for CB_COMPOUND
+ */
+%
+enum nfs_cb_opnum4 {
+ OP_CB_GETATTR = 3,
+ OP_CB_RECALL = 4,
+%/* Callback operations new to NFSv4.1 */
+ OP_CB_LAYOUTRECALL = 5,
+ OP_CB_NOTIFY = 6,
+ OP_CB_PUSH_DELEG = 7,
+ OP_CB_RECALL_ANY = 8,
+ OP_CB_RECALLABLE_OBJ_AVAIL = 9,
+ OP_CB_RECALL_SLOT = 10,
+ OP_CB_SEQUENCE = 11,
+ OP_CB_WANTS_CANCELLED = 12,
+ OP_CB_NOTIFY_LOCK = 13,
+ OP_CB_NOTIFY_DEVICEID = 14,
+%/* Callback operations new to NFSv4.2 */
+ OP_CB_OFFLOAD = 15,
+
+ OP_CB_ILLEGAL = 10044
+};
+
+union nfs_cb_argop4 switch (nfs_cb_opnum4 argop) {
+ case OP_CB_GETATTR:
+ CB_GETATTR4args opcbgetattr;
+
+ /* New NFSv4.1 operations */
+ case OP_CB_RECALL:
+ CB_RECALL4args opcbrecall;
+ case OP_CB_LAYOUTRECALL:
+ CB_LAYOUTRECALL4args opcblayoutrecall;
+ case OP_CB_NOTIFY:
+ CB_NOTIFY4args opcbnotify;
+ case OP_CB_PUSH_DELEG:
+ CB_PUSH_DELEG4args opcbpush_deleg;
+ case OP_CB_RECALL_ANY:
+ CB_RECALL_ANY4args opcbrecall_any;
+ case OP_CB_RECALLABLE_OBJ_AVAIL:
+ CB_RECALLABLE_OBJ_AVAIL4args opcbrecallable_obj_avail;
+ case OP_CB_RECALL_SLOT:
+ CB_RECALL_SLOT4args opcbrecall_slot;
+ case OP_CB_SEQUENCE:
+ CB_SEQUENCE4args opcbsequence;
+ case OP_CB_WANTS_CANCELLED:
+ CB_WANTS_CANCELLED4args opcbwants_cancelled;
+ case OP_CB_NOTIFY_LOCK:
+ CB_NOTIFY_LOCK4args opcbnotify_lock;
+ case OP_CB_NOTIFY_DEVICEID:
+ CB_NOTIFY_DEVICEID4args opcbnotify_deviceid;
+
+ /* New NFSv4.2 operations */
+ case OP_CB_OFFLOAD:
+ CB_OFFLOAD4args opcboffload;
+
+ case OP_CB_ILLEGAL: void;
+};
+
+union nfs_cb_resop4 switch (nfs_cb_opnum4 resop) {
+ case OP_CB_GETATTR: CB_GETATTR4res opcbgetattr;
+ case OP_CB_RECALL: CB_RECALL4res opcbrecall;
+
+ /* New NFSv4.1 operations */
+ case OP_CB_LAYOUTRECALL:
+ CB_LAYOUTRECALL4res
+ opcblayoutrecall;
+
+ case OP_CB_NOTIFY: CB_NOTIFY4res opcbnotify;
+
+ case OP_CB_PUSH_DELEG: CB_PUSH_DELEG4res
+ opcbpush_deleg;
+
+ case OP_CB_RECALL_ANY: CB_RECALL_ANY4res
+ opcbrecall_any;
+
+ case OP_CB_RECALLABLE_OBJ_AVAIL:
+ CB_RECALLABLE_OBJ_AVAIL4res
+ opcbrecallable_obj_avail;
+
+ case OP_CB_RECALL_SLOT:
+ CB_RECALL_SLOT4res
+ opcbrecall_slot;
+
+ case OP_CB_SEQUENCE: CB_SEQUENCE4res opcbsequence;
+
+ case OP_CB_WANTS_CANCELLED:
+ CB_WANTS_CANCELLED4res
+ opcbwants_cancelled;
+
+ case OP_CB_NOTIFY_LOCK:
+ CB_NOTIFY_LOCK4res
+ opcbnotify_lock;
+
+ case OP_CB_NOTIFY_DEVICEID:
+ CB_NOTIFY_DEVICEID4res
+ opcbnotify_deviceid;
+
+ /* New NFSv4.2 operations */
+ case OP_CB_OFFLOAD: CB_OFFLOAD4res opcboffload;
+
+ /* Not new operation */
+ case OP_CB_ILLEGAL: CB_ILLEGAL4res opcbillegal;
};
@@ -1585,7 +3686,7 @@ struct CB_COMPOUND4args {
};
struct CB_COMPOUND4res {
- nfsstat4 status;
+ nfsstat4 status;
utf8str_cs tag;
nfs_cb_resop4 resarray<>;
};
@@ -1595,7 +3696,8 @@ struct CB_COMPOUND4res {
/*
* Program number is in the transient range, since the client
* will assign the exact transient program number and provide
- * that to the server via the SETCLIENTID operation.
+ * that to the server via the CREATE_SESSION or
+ * BACKCHANNEL_CTL operations.
*/
program NFS4_CALLBACK {
version NFS_CB {
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 7dfbae4a68..b250ad08d9 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1136,14 +1136,16 @@ NFS_OBJS += nfs_client.o nfs_common.o nfs_dump.o \
nfs4_acache.o nfs4_common.o nfs4_client_state.o \
nfs4_callback.o nfs4_recovery.o nfs4_client_secinfo.o \
nfs4_client_debug.o nfs_stats.o \
- nfs4_acl.o nfs4_stub_vnops.o nfs_cmd.o
+ nfs4_acl.o nfs4_stub_vnops.o nfs_cmd.o \
+ nfs4x_xdr.o
NFSSRV_OBJS += nfs_server.o nfs_srv.o nfs3_srv.o \
nfs_acl_srv.o nfs_auth.o nfs_auth_xdr.o \
nfs_export.o nfs_log.o nfs_log_xdr.o \
nfs4_srv.o nfs4_state.o nfs4_srv_attr.o \
nfs4_srv_ns.o nfs4_db.o nfs4_srv_deleg.o \
- nfs4_deleg_ops.o nfs4_srv_readdir.o nfs4_dispatch.o
+ nfs4_deleg_ops.o nfs4_srv_readdir.o nfs4_dispatch.o \
+ nfs4x_srv.o nfs4x_state.o nfs4x_dispatch.o
SMBSRV_SHARED_OBJS += \
smb_cfg_util.o \
diff --git a/usr/src/uts/common/fs/nfs/nfs4_attr.c b/usr/src/uts/common/fs/nfs/nfs4_attr.c
index c32a9526ec..820b804312 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_attr.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_attr.c
@@ -772,6 +772,9 @@ struct nfs4_ntov_map nfs4_ntov_map[] = {
xdr_u_longlong_t,
NULL, "fattr4_mounted_on_fileid" },
+ { FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL, 0, FALSE, FALSE,
+ FATTR4_MOUNTED_ON_FILEID + 1, 0, xdr_bitmap4,
+ NULL, "fattr4_suppattr_exclcreat" },
};
uint_t nfs4_ntov_map_size = sizeof (nfs4_ntov_map) /
diff --git a/usr/src/uts/common/fs/nfs/nfs4_dispatch.c b/usr/src/uts/common/fs/nfs/nfs4_dispatch.c
index 1fdfd0f601..0988dea0ef 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_dispatch.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_dispatch.c
@@ -26,6 +26,7 @@
/*
* Copyright 2018 Nexenta Systems, Inc.
+ * Copyright 2020 RackTop Systems, Inc.
*/
#include <sys/systm.h>
@@ -40,7 +41,7 @@
#include <nfs/nfs_dispatch.h>
#include <nfs/nfs4_drc.h>
-#define NFS4_MAX_MINOR_VERSION 0
+#define NFS4_MAX_MINOR_VERSION 2
/*
* The default size of the duplicate request cache
@@ -372,43 +373,28 @@ rfs4_find_dr(struct svc_req *req, rfs4_drc_t *drc, rfs4_dupreq_t **dup)
*
*/
int
-rfs4_dispatch(struct rpcdisp *disp, struct svc_req *req, SVCXPRT *xprt,
- char *ap)
+rfs40_dispatch(struct svc_req *req, SVCXPRT *xprt, char *ap)
{
COMPOUND4res res_buf;
COMPOUND4res *rbp;
COMPOUND4args *cap;
- cred_t *cr = NULL;
int error = 0;
int dis_flags = 0;
int dr_stat = NFS4_NOT_DUP;
rfs4_dupreq_t *drp = NULL;
int rv;
+ struct compound_state cs;
nfs4_srv_t *nsrv4 = nfs4_get_srv();
rfs4_drc_t *nfs4_drc = nsrv4->nfs4_drc;
- ASSERT(disp);
-
- /*
- * Short circuit the RPC_NULL proc.
- */
- if (disp->dis_proc == rpc_null) {
- DTRACE_NFSV4_1(null__start, struct svc_req *, req);
- if (!svc_sendreply(xprt, xdr_void, NULL)) {
- DTRACE_NFSV4_1(null__done, struct svc_req *, req);
- svcerr_systemerr(xprt);
- return (1);
- }
- DTRACE_NFSV4_1(null__done, struct svc_req *, req);
- return (0);
- }
-
/* Only NFSv4 Compounds from this point onward */
rbp = &res_buf;
cap = (COMPOUND4args *)ap;
+ rfs4_init_compound_state(&cs);
+
/*
* Figure out the disposition of the whole COMPOUND
* and record it's IDEMPOTENTCY.
@@ -445,9 +431,11 @@ rfs4_dispatch(struct rpcdisp *disp, struct svc_req *req, SVCXPRT *xprt,
case NFS4_DUP_NEW:
curthread->t_flag |= T_DONTPEND;
/* NON-IDEMPOTENT proc call */
- rfs4_compound(cap, rbp, NULL, req, cr, &rv);
+ rfs4_compound(cap, rbp, &cs, req, &rv);
curthread->t_flag &= ~T_DONTPEND;
+ rfs4_fini_compound_state(&cs);
+
if (rv) /* short ckt sendreply on error */
return (rv);
@@ -478,9 +466,11 @@ rfs4_dispatch(struct rpcdisp *disp, struct svc_req *req, SVCXPRT *xprt,
} else {
curthread->t_flag |= T_DONTPEND;
/* IDEMPOTENT proc call */
- rfs4_compound(cap, rbp, NULL, req, cr, &rv);
+ rfs4_compound(cap, rbp, &cs, req, &rv);
curthread->t_flag &= ~T_DONTPEND;
+ rfs4_fini_compound_state(&cs);
+
if (rv) /* short ckt sendreply on error */
return (rv);
@@ -528,19 +518,11 @@ rfs4_dispatch(struct rpcdisp *disp, struct svc_req *req, SVCXPRT *xprt,
return (error);
}
-bool_t
-rfs4_minorvers_mismatch(struct svc_req *req, SVCXPRT *xprt, void *args)
+static int
+rfs4_send_minor_mismatch(SVCXPRT *xprt, COMPOUND4args *argsp)
{
- COMPOUND4args *argsp;
COMPOUND4res res_buf, *resp;
-
- if (req->rq_vers != 4)
- return (FALSE);
-
- argsp = (COMPOUND4args *)args;
-
- if (argsp->minorversion <= NFS4_MAX_MINOR_VERSION)
- return (FALSE);
+ int err = 0;
resp = &res_buf;
@@ -563,8 +545,26 @@ rfs4_minorvers_mismatch(struct svc_req *req, SVCXPRT *xprt, void *args)
DTRACE_PROBE2(nfss__e__minorvers_mismatch,
SVCXPRT *, xprt, char *, resp);
svcerr_systemerr(xprt);
+ err = 1;
}
rfs4_compound_free(resp);
+ return (err);
+}
+
+bool_t
+rfs4_minorvers_mismatch(struct svc_req *req, SVCXPRT *xprt, void *args)
+{
+ COMPOUND4args *argsp;
+
+ if (req->rq_vers != 4)
+ return (FALSE);
+
+ argsp = (COMPOUND4args *)args;
+
+ if (argsp->minorversion <= NFS4_MAX_MINOR_VERSION)
+ return (FALSE);
+
+ (void) rfs4_send_minor_mismatch(xprt, argsp);
return (TRUE);
}
@@ -619,3 +619,37 @@ rfs4_resource_err(struct svc_req *req, COMPOUND4args *argsp)
UTF8STRING_FREE(rbp->tag);
kmem_free(rbp->array, rbp->array_len * sizeof (nfs_resop4));
}
+
+/* ARGSUSED */
+int
+rfs4_dispatch(struct rpcdisp *disp, struct svc_req *req,
+ SVCXPRT *xprt, char *ap)
+{
+ COMPOUND4args *cmp;
+ int error = 0;
+
+ /*
+ * Handle the NULL Proc here
+ */
+ if (req->rq_proc == RFS_NULL) {
+ return (!svc_sendreply(xprt, xdr_void, NULL));
+ }
+
+ cmp = (COMPOUND4args *)ap;
+ ASSERT(cmp != NULL);
+
+ switch (cmp->minorversion) {
+ case 1:
+ case 2:
+ error = rfs4x_dispatch(req, xprt, ap);
+ break;
+
+ case 0:
+ error = rfs40_dispatch(req, xprt, ap);
+ break;
+
+ default:
+ error = rfs4_send_minor_mismatch(xprt, cmp);
+ }
+ return (error);
+}
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c
index 757964eb84..acaf6a8f8b 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c
@@ -32,6 +32,7 @@
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright 2019 Nexenta Systems, Inc.
* Copyright 2019 Nexenta by DDN, Inc.
+ * Copyright 2020 RackTop Systems, Inc.
*/
#include <sys/param.h>
@@ -185,6 +186,8 @@ static void rfs4_op_getfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
static void rfs4_op_getfh_free(nfs_resop4 *);
static void rfs4_op_illegal(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
struct compound_state *);
+static void rfs4_op_notsup(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
+ struct compound_state *);
static void rfs4_op_link(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
struct compound_state *);
static void rfs4_op_lock(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
@@ -247,12 +250,36 @@ static void rfs4_op_secinfo(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
struct compound_state *);
static void rfs4_op_secinfo_free(nfs_resop4 *);
+void rfs4x_op_exchange_id(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, struct compound_state *cs);
+void rfs4x_exchange_id_free(nfs_resop4 *);
+
+void rfs4x_op_create_session(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, struct compound_state *cs);
+
+void rfs4x_op_destroy_session(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs);
+
+void rfs4x_op_sequence(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, struct compound_state *cs);
+
+void rfs4x_op_reclaim_complete(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs);
+
+void rfs4x_op_destroy_clientid(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs);
+
+void rfs4x_op_bind_conn_to_session(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs);
+
+void rfs4x_op_secinfo_noname(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs);
+
static nfsstat4 check_open_access(uint32_t, struct compound_state *,
struct svc_req *);
nfsstat4 rfs4_client_sysid(rfs4_client_t *, sysid_t *);
void rfs4_ss_clid(nfs4_srv_t *, rfs4_client_t *);
-
/*
* translation table for attrs
*/
@@ -410,6 +437,67 @@ static struct rfsv4disp rfsv4disptab[] = {
/* OP_RELEASE_LOCKOWNER = 39 */
{rfs4_op_release_lockowner, nullfree, 0},
+
+ /*
+ * NFSv4.1 operations
+ */
+
+ /* OP_BACKCHANNEL_CTL = 40 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_BIND_CONN_TO_SESSION = 41 */
+ {rfs4x_op_bind_conn_to_session, nullfree, 0},
+
+ /* OP_EXCHANGE_ID = 42 */
+ {rfs4x_op_exchange_id, rfs4x_exchange_id_free, 0},
+
+ /* OP_CREATE_SESSION = 43 */
+ {rfs4x_op_create_session, nullfree, 0},
+
+ /* OP_DESTROY_SESSION = 44 */
+ {rfs4x_op_destroy_session, nullfree, 0},
+
+ /* OP_FREE_STATEID = 45 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_GET_DIR_DELEGATION = 46 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_GETDEVICEINFO = 47 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_GETDEVICELIST = 48 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_LAYOUTCOMMIT = 49 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_LAYOUTGET = 50 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_LAYOUTRETURN = 51 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_SECINFO_NO_NAME = 52 */
+ {rfs4x_op_secinfo_noname, rfs4_op_secinfo_free, 0},
+
+ /* OP_SEQUENCE = 53 */
+ {rfs4x_op_sequence, nullfree, 0},
+
+ /* OP_SET_SSV = 54 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_TEST_STATEID = 55 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_WANT_DELEGATION = 56 */
+ {rfs4_op_notsup, nullfree, 0},
+
+ /* OP_DESTROY_CLIENTID = 57 */
+ {rfs4x_op_destroy_clientid, nullfree, 0},
+
+ /* OP_RECLAIM_COMPLETE = 58 */
+ {rfs4x_op_reclaim_complete, nullfree, 0},
};
static uint_t rfsv4disp_cnt = sizeof (rfsv4disptab) / sizeof (rfsv4disptab[0]);
@@ -463,8 +551,29 @@ static char *rfs4_op_string[] = {
"rfs4_op_verify",
"rfs4_op_write",
"rfs4_op_release_lockowner",
+ /* NFSv4.1 */
+ "backchannel_ctl",
+ "bind_conn_to_session",
+ "exchange_id",
+ "create_session",
+ "destroy_session",
+ "free_stateid",
+ "get_dir_delegation",
+ "getdeviceinfo",
+ "getdevicelist",
+ "layoutcommit",
+ "layoutget",
+ "layoutreturn",
+ "secinfo_no_name",
+ "sequence",
+ "set_ssv",
+ "test_stateid",
+ "want_delegation",
+ "destroy_clientid",
+ "reclaim_complete",
"rfs4_op_illegal"
};
+
#endif
void rfs4_ss_chkclid(nfs4_srv_t *, rfs4_client_t *);
@@ -662,6 +771,31 @@ rfs4_init_compound_state(struct compound_state *cs)
cs->fh.nfs_fh4_val = cs->fhbuf;
}
+/* Do cleanup of the compound_state */
+void
+rfs4_fini_compound_state(struct compound_state *cs)
+{
+ if (cs->vp) {
+ VN_RELE(cs->vp);
+ }
+ if (cs->saved_vp) {
+ VN_RELE(cs->saved_vp);
+ }
+ if (cs->cr) {
+ crfree(cs->cr);
+ }
+ if (cs->saved_fh.nfs_fh4_val) {
+ kmem_free(cs->saved_fh.nfs_fh4_val, NFS4_FHSIZE);
+ }
+
+ if (cs->basecr) {
+ crfree(cs->basecr);
+ }
+ if (cs->sp) {
+ rfs4x_session_rele(cs->sp);
+ }
+}
+
void
rfs4_grace_start(rfs4_servinst_t *sip)
{
@@ -697,6 +831,8 @@ rfs4_servinst_in_grace(rfs4_servinst_t *sip)
rw_enter(&sip->rwlock, RW_READER);
grace_expiry = sip->start_time + sip->grace_period;
+ if (sip->nreclaim == 0)
+ grace_expiry = 0;
rw_exit(&sip->rwlock);
return (((time_t)TICK_TO_SEC(ddi_get_lbolt())) < grace_expiry);
@@ -796,6 +932,7 @@ rfs4_servinst_create(nfs4_srv_t *nsrv4, int start_grace,
sip = kmem_alloc(sizeof (rfs4_servinst_t), KM_SLEEP);
rw_init(&sip->rwlock, NULL, RW_DEFAULT, NULL);
+ sip->nreclaim = 0;
sip->start_time = (time_t)0;
sip->grace_period = (time_t)0;
sip->next = NULL;
@@ -948,7 +1085,7 @@ in_flavor_list(int nfsnum, int *flavor_list, int count)
* export structure associated with the component.
*/
/* ARGSUSED */
-static nfsstat4
+nfsstat4
do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
{
int error, different_export = 0;
@@ -1274,9 +1411,14 @@ rfs4_op_secinfo(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
goto out;
}
-
*cs->statusp = resp->status = do_rfs4_op_secinfo(cs, name, resp);
+ if (resp->status == NFS4_OK && rfs4_has_session(cs)) {
+ /* See rfc 5661 section 2.6.3.1.1.8 and 18.29.3 */
+ VN_RELE(cs->vp);
+ cs->vp = NULL;
+ }
+
if (name != nm)
kmem_free(name, MAXPATHLEN + 1);
kmem_free(nm, len);
@@ -2521,6 +2663,14 @@ rfs4_op_illegal(nfs_argop4 *argop, nfs_resop4 *resop,
*cs->statusp = resp->status = NFS4ERR_OP_ILLEGAL;
}
+/* ARGSUSED */
+static void
+rfs4_op_notsup(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
+ struct compound_state *cs)
+{
+ *cs->statusp = *((nfsstat4 *)&(resop)->nfs_resop4_u) = NFS4ERR_NOTSUPP;
+}
+
/*
* link: args: SAVED_FH: file, CURRENT_FH: target directory
* res: status. If success - CURRENT_FH unchanged, return change_info
@@ -3257,7 +3407,7 @@ rfs4_op_read(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
}
if ((stat = rfs4_check_stateid(FREAD, vp, &args->stateid, FALSE,
- deleg, TRUE, &ct)) != NFS4_OK) {
+ deleg, TRUE, &ct, cs)) != NFS4_OK) {
*cs->statusp = resp->status = stat;
goto out;
}
@@ -5198,6 +5348,7 @@ do_rfs4_op_setattr(bitmap4 *resp, fattr4 *fattrp, struct compound_state *cs,
*/
goto done;
}
+
if ((sarg.vap->va_mask == 0) &&
(! (fattrp->attrmask & FATTR4_ACL_MASK))) {
/*
@@ -5233,7 +5384,7 @@ do_rfs4_op_setattr(bitmap4 *resp, fattr4 *fattrp, struct compound_state *cs,
if (sarg.vap->va_mask & AT_SIZE) {
trunc = (sarg.vap->va_size == 0);
status = rfs4_check_stateid(FWRITE, cs->vp, stateid,
- trunc, &cs->deleg, sarg.vap->va_mask & AT_SIZE, &ct);
+ trunc, &cs->deleg, sarg.vap->va_mask & AT_SIZE, &ct, cs);
if (status != NFS4_OK)
goto done;
} else {
@@ -5622,7 +5773,7 @@ rfs4_op_write(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
cr = cs->cr;
if ((stat = rfs4_check_stateid(FWRITE, vp, &args->stateid, FALSE,
- deleg, TRUE, &ct)) != NFS4_OK) {
+ deleg, TRUE, &ct, cs)) != NFS4_OK) {
*cs->statusp = resp->status = stat;
goto out;
}
@@ -5790,18 +5941,31 @@ out:
/* XXX put in a header file */
extern int sec_svc_getcred(struct svc_req *, cred_t *, caddr_t *, int *);
+static inline int
+rfs4_opnum_in_range(const compound_state_t *cs, int opnum)
+{
+ if (opnum < FIRST_NFS4_OP || opnum > LAST_NFS4_OP)
+ return (0);
+ else if (cs->minorversion == 0 && opnum > LAST_NFS40_OP)
+ return (0);
+ else if (cs->minorversion == 1 && opnum > LAST_NFS41_OP)
+ return (0);
+ else if (cs->minorversion == 2 && opnum > LAST_NFS42_OP)
+ return (0);
+ return (1);
+}
+
void
-rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
- struct svc_req *req, cred_t *cr, int *rv)
+rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, compound_state_t *cs,
+ struct svc_req *req, int *rv)
{
uint_t i;
- struct compound_state cs;
+ cred_t *cr;
nfs4_srv_t *nsrv4;
nfs_export_t *ne = nfs_get_export();
if (rv != NULL)
*rv = 0;
- rfs4_init_compound_state(&cs);
/*
* Form a reply tag by copying over the request tag.
*/
@@ -5815,53 +5979,41 @@ rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
resp->tag.utf8string_val = NULL;
}
- cs.statusp = &resp->status;
- cs.req = req;
+ cs->statusp = &resp->status;
+ cs->req = req;
+ cs->minorversion = args->minorversion;
resp->array = NULL;
resp->array_len = 0;
- /*
- * XXX for now, minorversion should be zero
- */
- if (args->minorversion != NFS4_MINORVERSION) {
- DTRACE_NFSV4_2(compound__start, struct compound_state *,
- &cs, COMPOUND4args *, args);
- resp->status = NFS4ERR_MINOR_VERS_MISMATCH;
- DTRACE_NFSV4_2(compound__done, struct compound_state *,
- &cs, COMPOUND4res *, resp);
- return;
- }
-
if (args->array_len == 0) {
resp->status = NFS4_OK;
return;
}
- ASSERT(exi == NULL);
- ASSERT(cr == NULL);
-
cr = crget();
ASSERT(cr != NULL);
- if (sec_svc_getcred(req, cr, &cs.principal, &cs.nfsflavor) == 0) {
+ if (sec_svc_getcred(req, cr, &cs->principal, &cs->nfsflavor) == 0) {
DTRACE_NFSV4_2(compound__start, struct compound_state *,
- &cs, COMPOUND4args *, args);
+ cs, COMPOUND4args *, args);
crfree(cr);
DTRACE_NFSV4_2(compound__done, struct compound_state *,
- &cs, COMPOUND4res *, resp);
+ cs, COMPOUND4res *, resp);
svcerr_badcred(req->rq_xprt);
if (rv != NULL)
*rv = 1;
return;
}
+
resp->array_len = args->array_len;
resp->array = kmem_zalloc(args->array_len * sizeof (nfs_resop4),
KM_SLEEP);
- cs.basecr = cr;
+ cs->op_len = args->array_len;
+ cs->basecr = cr;
nsrv4 = nfs4_get_srv();
- DTRACE_NFSV4_2(compound__start, struct compound_state *, &cs,
+ DTRACE_NFSV4_2(compound__start, struct compound_state *, cs,
COMPOUND4args *, args);
/*
@@ -5890,7 +6042,7 @@ rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
nsrv4->seen_first_compound = 1;
}
- for (i = 0; i < args->array_len && cs.cont; i++) {
+ for (i = 0; i < args->array_len && cs->cont; i++) {
nfs_argop4 *argop;
nfs_resop4 *resop;
uint_t op;
@@ -5901,7 +6053,8 @@ rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
resop->resop = argop->argop;
op = (uint_t)resop->resop;
- if (op < rfsv4disp_cnt) {
+ cs->op_pos = i;
+ if (op < rfsv4disp_cnt && rfs4_opnum_in_range(cs, op)) {
/*
* Count the individual ops here; NULL and COMPOUND
* are counted in common_dispatch()
@@ -5910,11 +6063,11 @@ rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
NFS4_DEBUG(rfs4_debug > 1,
(CE_NOTE, "Executing %s", rfs4_op_string[op]));
- (*rfsv4disptab[op].dis_proc)(argop, resop, req, &cs);
+ (*rfsv4disptab[op].dis_proc)(argop, resop, req, cs);
NFS4_DEBUG(rfs4_debug > 1, (CE_NOTE, "%s returned %d",
- rfs4_op_string[op], *cs.statusp));
- if (*cs.statusp != NFS4_OK)
- cs.cont = FALSE;
+ rfs4_op_string[op], *cs->statusp));
+ if (*cs->statusp != NFS4_OK)
+ cs->cont = FALSE;
} else {
/*
* This is effectively dead code since XDR code
@@ -5925,15 +6078,15 @@ rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
op = OP_ILLEGAL;
stat[OP_ILLEGAL_IDX].value.ui64++;
- rfs4_op_illegal(argop, resop, req, &cs);
- cs.cont = FALSE;
+ rfs4_op_illegal(argop, resop, req, cs);
+ cs->cont = FALSE;
}
/*
* If not at last op, and if we are to stop, then
* compact the results array.
*/
- if ((i + 1) < args->array_len && !cs.cont) {
+ if ((i + 1) < args->array_len && !cs->cont) {
nfs_resop4 *new_res = kmem_alloc(
(i+1) * sizeof (nfs_resop4), KM_SLEEP);
bcopy(resp->array,
@@ -5948,27 +6101,9 @@ rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
rw_exit(&ne->exported_lock);
- /*
- * clear exportinfo and vnode fields from compound_state before dtrace
- * probe, to avoid tracing residual values for path and share path.
- */
- if (cs.vp)
- VN_RELE(cs.vp);
- if (cs.saved_vp)
- VN_RELE(cs.saved_vp);
- cs.exi = cs.saved_exi = NULL;
- cs.vp = cs.saved_vp = NULL;
-
- DTRACE_NFSV4_2(compound__done, struct compound_state *, &cs,
+ DTRACE_NFSV4_2(compound__done, struct compound_state *, cs,
COMPOUND4res *, resp);
- if (cs.saved_fh.nfs_fh4_val)
- kmem_free(cs.saved_fh.nfs_fh4_val, NFS4_FHSIZE);
-
- if (cs.basecr)
- crfree(cs.basecr);
- if (cs.cr)
- crfree(cs.cr);
/*
* done with this compound request, free the label
*/
@@ -6094,7 +6229,7 @@ static void lock_print(char *str, int operation, struct flock64 *flk)
/*ARGSUSED*/
static bool_t
-creds_ok(cred_set_t cr_set, struct svc_req *req, struct compound_state *cs)
+creds_ok(cred_set_t *cr_set, struct svc_req *req, struct compound_state *cs)
{
return (TRUE);
}
@@ -6360,6 +6495,21 @@ check_open_access(uint32_t access, struct compound_state *cs,
return (NFS4_OK);
}
+static void
+rfs4_verifier_to_mtime(verifier4 v, timestruc_t *mtime)
+{
+ timespec32_t *time = (timespec32_t *)&v;
+
+ /*
+ * Ensure no time overflows. Assumes underlying
+ * filesystem supports at least 32 bits.
+ * Truncate nsec to usec resolution to allow valid
+ * compares even if the underlying filesystem truncates.
+ */
+ mtime->tv_sec = time->tv_sec % TIME32_MAX;
+ mtime->tv_nsec = (time->tv_nsec / 1000) * 1000;
+}
+
static nfsstat4
rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
change_info4 *cinfo, bitmap4 *attrset, clientid4 clientid)
@@ -6373,7 +6523,6 @@ rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
vnode_t *vp;
vattr_t bva, ava, iva, cva, *vap;
vnode_t *dvp;
- timespec32_t *mtime;
char *nm = NULL;
uint_t buflen;
bool_t created;
@@ -6386,6 +6535,9 @@ rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
bslabel_t *clabel;
struct sockaddr *ca;
char *name = NULL;
+ fattr4 *fattr = NULL;
+
+ ASSERT(*attrset == 0);
sarg.sbp = &sb;
sarg.is_referral = B_FALSE;
@@ -6411,11 +6563,17 @@ rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
}
}
+ if ((args->mode == EXCLUSIVE4 || args->mode == EXCLUSIVE4_1) &&
+ dvp->v_flag & V_XATTRDIR) {
+ /* prohibit EXCL create of named attributes */
+ return (NFS4ERR_INVAL);
+ }
+
/*
* Get the last component of path name in nm. cs will reference
* the including directory on success.
*/
- component = &args->open_claim4_u.file;
+ component = &args->claim.open_claim4_u.file;
status = utf8_dir_verify(component);
if (status != NFS4_OK)
return (status);
@@ -6448,12 +6606,17 @@ rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
case GUARDED4:
/*FALLTHROUGH*/
case UNCHECKED4:
+ case EXCLUSIVE4_1:
nfs4_ntov_table_init(&ntov);
ntov_table_init = TRUE;
- *attrset = 0;
+ if (args->mode == EXCLUSIVE4_1)
+ fattr = &args->createhow4_u.ch_createboth.cva_attrs;
+ else
+ fattr = &args->createhow4_u.createattrs;
+
status = do_rfs4_set_attrs(attrset,
- &args->createhow4_u.createattrs,
+ fattr,
cs, &sarg, &ntov, NFS4ATTR_SETIT);
if (status == NFS4_OK && (sarg.vap->va_mask & AT_TYPE) &&
@@ -6494,28 +6657,24 @@ rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
}
setsize = TRUE;
}
+ if (args->mode == EXCLUSIVE4_1) {
+ rfs4_verifier_to_mtime(
+ args->createhow4_u.ch_createboth.cva_verf,
+ &vap->va_mtime);
+ /* attrset will be set later */
+ fattr->attrmask |= FATTR4_TIME_MODIFY_MASK;
+ vap->va_mask |= AT_MTIME;
+ }
break;
case EXCLUSIVE4:
- /* prohibit EXCL create of named attributes */
- if (dvp->v_flag & V_XATTRDIR) {
- kmem_free(nm, buflen);
- *attrset = 0;
- return (NFS4ERR_INVAL);
- }
-
cva.va_mask = AT_TYPE | AT_MTIME | AT_MODE;
cva.va_type = VREG;
- /*
- * Ensure no time overflows. Assumes underlying
- * filesystem supports at least 32 bits.
- * Truncate nsec to usec resolution to allow valid
- * compares even if the underlying filesystem truncates.
- */
- mtime = (timespec32_t *)&args->createhow4_u.createverf;
- cva.va_mtime.tv_sec = mtime->tv_sec % TIME32_MAX;
- cva.va_mtime.tv_nsec = (mtime->tv_nsec / 1000) * 1000;
cva.va_mode = (mode_t)0;
+
+ rfs4_verifier_to_mtime(args->createhow4_u.createverf,
+ &cva.va_mtime);
+
vap = &cva;
/*
@@ -6551,7 +6710,7 @@ rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
trunc = (setsize && !created);
if (args->mode != EXCLUSIVE4) {
- bitmap4 createmask = args->createhow4_u.createattrs.attrmask;
+ bitmap4 createmask = fattr->attrmask;
/*
* True verification that object was created with correct
@@ -6993,6 +7152,16 @@ rfs4_do_open(struct compound_state *cs, struct svc_req *req,
/*ARGSUSED*/
static void
+rfs4_do_openfh(struct compound_state *cs, struct svc_req *req, OPEN4args *args,
+ rfs4_openowner_t *oo, OPEN4res *resp)
+{
+ /* cs->vp and cs->fh have been updated by putfh. */
+ rfs4_do_open(cs, req, oo, DELEG_ANY,
+ (args->share_access & 0xff), args->share_deny, resp, 0);
+}
+
+/*ARGSUSED*/
+static void
rfs4_do_opennull(struct compound_state *cs, struct svc_req *req,
OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
{
@@ -7000,7 +7169,7 @@ rfs4_do_opennull(struct compound_state *cs, struct svc_req *req,
bitmap4 *attrset = &resp->attrset;
if (args->opentype == OPEN4_NOCREATE)
- resp->status = rfs4_lookupfile(&args->open_claim4_u.file,
+ resp->status = rfs4_lookupfile(&args->claim.open_claim4_u.file,
req, cs, args->share_access, cinfo);
else {
/* inhibit delegation grants during exclusive create */
@@ -7087,7 +7256,7 @@ rfs4_do_openprev(struct compound_state *cs, struct svc_req *req,
cinfo->atomic = FALSE;
rfs4_do_open(cs, req, oo,
- NFS4_DELEG4TYPE2REQTYPE(args->open_claim4_u.delegate_type),
+ NFS4_DELEG4TYPE2REQTYPE(args->claim.open_claim4_u.delegate_type),
args->share_access, args->share_deny, resp, 0);
}
@@ -7098,7 +7267,7 @@ rfs4_do_opendelcur(struct compound_state *cs, struct svc_req *req,
int error;
nfsstat4 status;
stateid4 stateid =
- args->open_claim4_u.delegate_cur_info.delegate_stateid;
+ args->claim.open_claim4_u.delegate_cur_info.delegate_stateid;
rfs4_deleg_state_t *dsp;
/*
@@ -7168,7 +7337,8 @@ rfs4_do_opendelprev(struct compound_state *cs, struct svc_req *req,
nfsace4 *ace;
/* Note we ignore oflags */
- resp->status = rfs4_lookupfile(&args->open_claim4_u.file_delegate_prev,
+ resp->status = rfs4_lookupfile(
+ &args->claim.open_claim4_u.file_delegate_prev,
req, cs, args->share_access, &resp->cinfo);
if (resp->status != NFS4_OK) {
@@ -7298,10 +7468,14 @@ rfs4_check_seqid(seqid4 seqid, nfs_resop4 *lastop,
static rfs4_chkseq_t
-rfs4_check_open_seqid(seqid4 seqid, rfs4_openowner_t *op, nfs_resop4 *resop)
+rfs4_check_open_seqid(seqid4 seqid, rfs4_openowner_t *op, nfs_resop4 *resop,
+ const compound_state_t *cs)
{
rfs4_chkseq_t rc;
+ if (rfs4_has_session(cs))
+ return (NFS4_CHKSEQ_OKAY);
+
rfs4_dbe_lock(op->ro_dbe);
rc = rfs4_check_seqid(op->ro_open_seqid, &op->ro_reply, seqid, resop,
TRUE);
@@ -7347,7 +7521,7 @@ rfs4_op_open(nfs_argop4 *argop, nfs_resop4 *resop,
OPEN4args *args = &argop->nfs_argop4_u.opopen;
OPEN4res *resp = &resop->nfs_resop4_u.opopen;
open_owner4 *owner = &args->owner;
- open_claim_type4 claim = args->claim;
+ open_claim_type4 claim = args->claim.claim;
rfs4_client_t *cp;
rfs4_openowner_t *oo;
bool_t create;
@@ -7362,6 +7536,10 @@ rfs4_op_open(nfs_argop4 *argop, nfs_resop4 *resop,
goto end;
}
+ /* rfc5661 section 18.16.3 */
+ if (rfs4_has_session(cs))
+ owner->clientid = cs->client->rc_clientid;
+
/*
* Need to check clientid and lease expiration first based on
* error ordering and incrementing sequence id.
@@ -7394,6 +7572,13 @@ retry:
goto end;
}
+ /*
+ * OPEN_CONFIRM must not be implemented in v4.1
+ */
+ if (rfs4_has_session(cs)) {
+ oo->ro_need_confirm = FALSE;
+ }
+
/* Hold off access to the sequence space while the open is done */
rfs4_sw_enter(&oo->ro_sw);
@@ -7402,7 +7587,7 @@ retry:
* the sequence id.
*/
if (!create && !oo->ro_postpone_confirm) {
- switch (rfs4_check_open_seqid(args->seqid, oo, resop)) {
+ switch (rfs4_check_open_seqid(args->seqid, oo, resop, cs)) {
case NFS4_CHKSEQ_BAD:
if ((args->seqid > oo->ro_open_seqid) &&
oo->ro_need_confirm) {
@@ -7434,7 +7619,8 @@ retry:
}
/* Grace only applies to regular-type OPENs */
if (rfs4_clnt_in_grace(cp) &&
- (claim == CLAIM_NULL || claim == CLAIM_DELEGATE_CUR)) {
+ (claim == CLAIM_NULL || claim == CLAIM_DELEGATE_CUR ||
+ claim == CLAIM_FH)) {
*cs->statusp = resp->status = NFS4ERR_GRACE;
goto out;
}
@@ -7512,6 +7698,9 @@ retry:
case CLAIM_DELEGATE_PREV:
rfs4_do_opendelprev(cs, req, args, oo, resp);
break;
+ case CLAIM_FH:
+ rfs4_do_openfh(cs, req, args, oo, resp);
+ break;
default:
resp->status = NFS4ERR_INVAL;
break;
@@ -7636,6 +7825,8 @@ rfs4_op_open_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
DTRACE_NFSV4_2(op__open__confirm__start, struct compound_state *, cs,
OPEN_CONFIRM4args *, args);
+ ASSERT(!rfs4_has_session(cs));
+
if (cs->vp == NULL) {
*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
goto out;
@@ -7663,10 +7854,10 @@ rfs4_op_open_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
/* hold off other access to open_owner while we tinker */
rfs4_sw_enter(&sp->rs_owner->ro_sw);
- switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
+ switch (rfs4_check_stateid_seqid(sp, &args->open_stateid, cs)) {
case NFS4_CHECK_STATEID_OKAY:
if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
- resop) != 0) {
+ resop, cs) != 0) {
*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
break;
}
@@ -7692,7 +7883,7 @@ rfs4_op_open_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
break;
case NFS4_CHECK_STATEID_REPLAY:
switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
- resop)) {
+ resop, cs)) {
case NFS4_CHKSEQ_OKAY:
/*
* This is replayed stateid; if seqid matches
@@ -7714,7 +7905,7 @@ rfs4_op_open_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
break;
case NFS4_CHECK_STATEID_UNCONFIRMED:
if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
- resop) != NFS4_CHKSEQ_OKAY) {
+ resop, cs) != NFS4_CHKSEQ_OKAY) {
*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
break;
}
@@ -7783,10 +7974,10 @@ rfs4_op_open_downgrade(nfs_argop4 *argop, nfs_resop4 *resop,
/* hold off other access to open_owner while we tinker */
rfs4_sw_enter(&sp->rs_owner->ro_sw);
- switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
+ switch (rfs4_check_stateid_seqid(sp, &args->open_stateid, cs)) {
case NFS4_CHECK_STATEID_OKAY:
if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
- resop) != NFS4_CHKSEQ_OKAY) {
+ resop, cs) != NFS4_CHKSEQ_OKAY) {
*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
goto end;
}
@@ -7807,9 +7998,11 @@ rfs4_op_open_downgrade(nfs_argop4 *argop, nfs_resop4 *resop,
*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
goto end;
case NFS4_CHECK_STATEID_REPLAY:
+ ASSERT(!rfs4_has_session(cs));
+
/* Check the sequence id for the open owner */
switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
- resop)) {
+ resop, cs)) {
case NFS4_CHKSEQ_OKAY:
/*
* This is replayed stateid; if seqid matches
@@ -8098,7 +8291,7 @@ retry:
*/
if (cp_confirmed) {
/* If creds don't match then client identifier is inuse */
- if (!creds_ok(cp_confirmed->rc_cr_set, req, cs)) {
+ if (!creds_ok(&cp_confirmed->rc_cr_set, req, cs)) {
rfs4_cbinfo_t *cbp;
/*
* Some one else has established this client
@@ -8260,7 +8453,7 @@ rfs4_op_setclientid_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
goto out;
}
- if (!creds_ok(cp, req, cs)) {
+ if (!creds_ok(&cp->rc_cr_set, req, cs)) {
*cs->statusp = res->status = NFS4ERR_CLID_INUSE;
rfs4_client_rele(cp);
goto out;
@@ -8352,10 +8545,10 @@ rfs4_op_close(nfs_argop4 *argop, nfs_resop4 *resop,
/* hold off other access to open_owner while we tinker */
rfs4_sw_enter(&sp->rs_owner->ro_sw);
- switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
+ switch (rfs4_check_stateid_seqid(sp, &args->open_stateid, cs)) {
case NFS4_CHECK_STATEID_OKAY:
if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
- resop) != NFS4_CHKSEQ_OKAY) {
+ resop, cs) != NFS4_CHKSEQ_OKAY) {
*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
goto end;
}
@@ -8376,9 +8569,11 @@ rfs4_op_close(nfs_argop4 *argop, nfs_resop4 *resop,
*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
goto end;
case NFS4_CHECK_STATEID_REPLAY:
+ ASSERT(!rfs4_has_session(cs));
+
/* Check the sequence id for the open owner */
switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
- resop)) {
+ resop, cs)) {
case NFS4_CHKSEQ_OKAY:
/*
* This is replayed stateid; if seqid matches
@@ -8911,7 +9106,7 @@ rfs4_op_lock(nfs_argop4 *argop, nfs_resop4 *resop,
/* hold off other access to open_owner while we tinker */
rfs4_sw_enter(&sp->rs_owner->ro_sw);
- switch (rc = rfs4_check_stateid_seqid(sp, stateid)) {
+ switch (rc = rfs4_check_stateid_seqid(sp, stateid, cs)) {
case NFS4_CHECK_STATEID_OLD:
*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
goto end;
@@ -8928,7 +9123,12 @@ rfs4_op_lock(nfs_argop4 *argop, nfs_resop4 *resop,
*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
goto end;
case NFS4_CHECK_STATEID_OKAY:
+ if (rfs4_has_session(cs))
+ break;
+ /* FALLTHROUGH */
case NFS4_CHECK_STATEID_REPLAY:
+ ASSERT(!rfs4_has_session(cs));
+
switch (rfs4_check_olo_seqid(olo->open_seqid,
sp->rs_owner, resop)) {
case NFS4_CHKSEQ_OKAY:
@@ -8995,7 +9195,7 @@ rfs4_op_lock(nfs_argop4 *argop, nfs_resop4 *resop,
* not appropriate. The client should be using the
* existing lock_owner branch.
*/
- if (dup_lock == FALSE && create == FALSE) {
+ if (!rfs4_has_session(cs) && !dup_lock && !create) {
if (lsp->rls_lock_completed == TRUE) {
*cs->statusp =
resp->status = NFS4ERR_BAD_SEQID;
@@ -9087,12 +9287,15 @@ rfs4_op_lock(nfs_argop4 *argop, nfs_resop4 *resop,
rfs4_sw_enter(&lsp->rls_sw);
ls_sw_held = TRUE;
- switch (rfs4_check_lo_stateid_seqid(lsp, stateid)) {
+ switch (rfs4_check_lo_stateid_seqid(lsp, stateid, cs)) {
/*
* The stateid looks like it was okay (expected to be
* the next one)
*/
case NFS4_CHECK_STATEID_OKAY:
+ if (rfs4_has_session(cs))
+ break;
+
/*
* The sequence id is now checked. Determine
* if this is a replay or if it is in the
@@ -9152,6 +9355,8 @@ rfs4_op_lock(nfs_argop4 *argop, nfs_resop4 *resop,
*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
goto end;
case NFS4_CHECK_STATEID_REPLAY:
+ ASSERT(!rfs4_has_session(cs));
+
switch (rfs4_check_lock_seqid(
args->locker.locker4_u.lock_owner.lock_seqid,
lsp, resop)) {
@@ -9317,8 +9522,11 @@ rfs4_op_locku(nfs_argop4 *argop, nfs_resop4 *resop,
/* hold off other access to lsp while we tinker */
rfs4_sw_enter(&lsp->rls_sw);
- switch (rfs4_check_lo_stateid_seqid(lsp, stateid)) {
+ switch (rfs4_check_lo_stateid_seqid(lsp, stateid, cs)) {
case NFS4_CHECK_STATEID_OKAY:
+ if (rfs4_has_session(cs))
+ break;
+
if (rfs4_check_lock_seqid(args->seqid, lsp, resop)
!= NFS4_CHKSEQ_OKAY) {
*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
@@ -9338,6 +9546,8 @@ rfs4_op_locku(nfs_argop4 *argop, nfs_resop4 *resop,
*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
goto end;
case NFS4_CHECK_STATEID_REPLAY:
+ ASSERT(!rfs4_has_session(cs));
+
switch (rfs4_check_lock_seqid(args->seqid, lsp, resop)) {
case NFS4_CHKSEQ_OKAY:
/*
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c b/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c
index a9ee217a8b..a558c48466 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c
@@ -26,6 +26,7 @@
/*
* Copyright 2018 Nexenta Systems, Inc.
+ * Copyright 2020 RackTop Systems, Inc.
*/
#include <sys/systm.h>
@@ -126,6 +127,24 @@ static int rfs4_fattr4_time_modify_set();
/*
* Initialize the supported attributes
*/
+bitmap4 supported_attrs[3];
+
+static void
+init_supported_attrs()
+{
+ bitmap4 supported = rfs4_supported_attrs;
+
+ supported_attrs[0] = supported_attrs[1] = supported_attrs[2] =
+ rfs4_supported_attrs;
+
+ /* restrict to nfsv4.0 */
+ supported_attrs[0] &= ~(FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL |
+ FATTR4_SEC_LABEL_MASK_LOCAL);
+
+ /* restrict to nfsv4.1 */
+ supported_attrs[1] &= ~FATTR4_SEC_LABEL_MASK_LOCAL;
+}
+
void
rfs4_attr_init()
{
@@ -143,6 +162,7 @@ rfs4_attr_init()
cs.vp = rootvp;
cs.fh.nfs_fh4_val = NULL;
cs.cr = kcred;
+ cs.minorversion = 2;
/*
* Get all the supported attributes
@@ -169,6 +189,8 @@ rfs4_attr_init()
rfs4_supported_attrs |= nfs4_ntov_map[i].fbit;
}
}
+
+ init_supported_attrs();
}
/*
@@ -219,6 +241,7 @@ rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
union nfs4_attr_u *na)
{
int error = 0;
+ bitmap4 supported = supported_attrs[sarg->cs->minorversion];
switch (cmd) {
case NFS4ATTR_SUPPORTED:
@@ -226,7 +249,7 @@ rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
error = EINVAL;
break; /* this attr is supported */
case NFS4ATTR_GETIT:
- na->supported_attrs = rfs4_supported_attrs;
+ na->supported_attrs = supported;
break;
case NFS4ATTR_SETIT:
/*
@@ -238,7 +261,7 @@ rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
/*
* Compare the input bitmap to the server's bitmap
*/
- if (na->supported_attrs != rfs4_supported_attrs) {
+ if (na->supported_attrs != supported) {
error = -1; /* no match */
}
break;
@@ -2814,6 +2837,40 @@ rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
return (error);
}
+/* ARGSUSED */
+static int
+rfs4_fattr4_suppattr_exclcreat(nfs4_attr_cmd_t cmd,
+ struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na)
+{
+ int error = 0;
+
+ /* Not supported for nfs4.0 */
+ if (sarg->cs->minorversion == 0)
+ return (ENOTSUP);
+
+ switch (cmd) {
+ case NFS4ATTR_SUPPORTED:
+ if (sarg->op == NFS4ATTR_SETIT)
+ error = EINVAL;
+ break; /* this attr is supported */
+ case NFS4ATTR_GETIT:
+ na->supp_exclcreat = RFS4_SUPPATTR_EXCLCREAT;
+ break;
+ case NFS4ATTR_SETIT:
+ /*
+ * read-only attr
+ */
+ error = EINVAL;
+ break;
+ case NFS4ATTR_VERIT:
+ if (na->supp_exclcreat != RFS4_SUPPATTR_EXCLCREAT)
+ error = -1; /* no match */
+ break;
+ case NFS4ATTR_FREEIT:
+ break;
+ }
+ return (error);
+}
static void
rfs4_ntov_init(void)
@@ -2875,4 +2932,5 @@ rfs4_ntov_init(void)
nfs4_ntov_map[53].sv_getit = rfs4_fattr4_time_modify;
nfs4_ntov_map[54].sv_getit = rfs4_fattr4_time_modify_set;
nfs4_ntov_map[55].sv_getit = rfs4_fattr4_mounted_on_fileid;
+ nfs4_ntov_map[56].sv_getit = rfs4_fattr4_suppattr_exclcreat;
}
diff --git a/usr/src/uts/common/fs/nfs/nfs4_state.c b/usr/src/uts/common/fs/nfs/nfs4_state.c
index b95dd6fb02..582813bf93 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_state.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_state.c
@@ -26,6 +26,7 @@
/*
* Copyright 2018 Nexenta Systems, Inc.
* Copyright 2019 Nexenta by DDN, Inc.
+ * Copyright 2020 RackTop Systems, Inc.
*/
#include <sys/systm.h>
@@ -595,6 +596,31 @@ rfs4_ss_getstate(vnode_t *dvp, rfs4_ss_pn_t *ss_pn)
#define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
/*
+ * Check whether list @head already contains the @client
+ * This protects against counting the same client twice.
+ */
+static bool_t
+rfs4_ss_has_client(rfs4_oldstate_t *head, nfs_client_id4 *client)
+{
+ rfs4_oldstate_t *p;
+
+ for (p = head->next; p != head; p = p->next) {
+ nfs_client_id4 *m = &p->cl_id4;
+
+ if (m->id_len != client->id_len)
+ continue;
+
+ if (bcmp(m->id_val, client->id_val, client->id_len) == 0)
+ continue;
+
+ /* client ids match */
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+/*
* Add entries from statedir to supplied oldstate list.
* Optionally, move all entries from statedir -> destdir.
*/
@@ -610,6 +636,7 @@ rfs4_ss_oldstate(rfs4_oldstate_t *oldstate, char *statedir, char *destdir)
struct uio uio;
struct dirent64 *dep;
offset_t dirchunk_offset = 0;
+ unsigned int nclients = 0;
/*
* open the state directory
@@ -670,6 +697,11 @@ rfs4_ss_oldstate(rfs4_oldstate_t *oldstate, char *statedir, char *destdir)
} else {
cl_ss->ss_pn = ss_pn;
}
+
+ if (!rfs4_ss_has_client(oldstate,
+ &cl_ss->cl_id4))
+ nclients++;
+
insque(cl_ss, oldstate);
} else {
rfs4_ss_pnfree(ss_pn);
@@ -682,6 +714,12 @@ out:
VN_RELE(dvp);
if (dirt)
kmem_free((caddr_t)dirt, RFS4_SS_DIRSIZE);
+
+ if (nclients > 0) {
+ nfs4_srv_t *nsrv4 = nfs4_get_srv();
+
+ atomic_add_32(&(nsrv4->nfs4_cur_servinst->nreclaim), nclients);
+ }
}
static void
@@ -1181,6 +1219,9 @@ rfs4_state_g_init()
/* CSTYLED */
rfs4_delegstID_mem_cache = nfs4_init_mem_cache("DelegStateID_entry_cache", 2, sizeof (rfs4_deleg_state_t), 7);
+ /* CSTYLED */
+ (void) nfs4_init_mem_cache("Session_entry_cache", 1, sizeof (rfs4_session_t), 8);
+
rfs4_client_clrst = rfs4_clear_client_state;
}
@@ -1480,6 +1521,8 @@ rfs4_state_zone_init(nfs4_srv_t *nsrv4)
deleg_state_compare,
deleg_state_mkkey, FALSE);
+ rfs4x_state_init_locked(nsrv4);
+
mutex_exit(&nsrv4->state_lock);
/*
@@ -1516,6 +1559,8 @@ rfs4_state_zone_fini()
return;
}
+ rfs4x_state_fini(nsrv4);
+
/* destroy server instances and current instance ptr */
rfs4_servinst_destroy_all(nsrv4);
@@ -1720,6 +1765,8 @@ rfs4_client_destroy(rfs4_entry_t u_entry)
cv_destroy(cp->rc_cbinfo.cb_cv_nullcaller);
list_destroy(&cp->rc_openownerlist);
+ list_destroy(&cp->rc_sessions);
+
/* free callback info */
rfs4_cbinfo_free(&cp->rc_cbinfo);
@@ -1738,6 +1785,8 @@ rfs4_client_destroy(rfs4_entry_t u_entry)
if (cp->rc_sysidt != LM_NOSYSID)
lm_free_sysidt(cp->rc_sysidt);
+
+ rfs4_free_cred_set(&cp->rc_cr_set);
}
static bool_t
@@ -1786,6 +1835,7 @@ rfs4_client_create(rfs4_entry_t u_entry, void *arg)
/* We need the client to ack us */
cp->rc_need_confirm = TRUE;
cp->rc_cp_confirmed = NULL;
+ cp->rc_destroying = FALSE;
/* TRUE all the time until the callback path actually fails */
cp->rc_cbinfo.cb_notified_of_cb_path_down = TRUE;
@@ -1793,13 +1843,16 @@ rfs4_client_create(rfs4_entry_t u_entry, void *arg)
/* Initialize the access time to now */
cp->rc_last_access = gethrestime_sec();
- cp->rc_cr_set = NULL;
+ bzero(&cp->rc_cr_set, sizeof (cred_set_t));
cp->rc_sysidt = LM_NOSYSID;
list_create(&cp->rc_openownerlist, sizeof (rfs4_openowner_t),
offsetof(rfs4_openowner_t, ro_node));
+ list_create(&cp->rc_sessions, sizeof (rfs4_session_t),
+ offsetof(rfs4_session_t, sn_node));
+
/* set up the callback control structure */
cp->rc_cbinfo.cb_state = CB_UNINIT;
mutex_init(cp->rc_cbinfo.cb_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -1815,6 +1868,12 @@ rfs4_client_create(rfs4_entry_t u_entry, void *arg)
rfs4_servinst_assign(nsrv4, cp, nsrv4->nfs4_cur_servinst);
rfs4_dbe_rele(cp->rc_dbe);
+ /*
+ * NFSv4.1: See rfc5661, Section 18.36.4, eir_sequenceid
+ */
+ cp->rc_contrived.xi_sid = 1;
+ cp->rc_contrived.cs_status = NFS4ERR_SEQ_MISORDERED;
+
return (TRUE);
}
@@ -2202,7 +2261,6 @@ rfs4_openowner_create(rfs4_entry_t u_entry, void *arg)
oo->ro_open_seqid = seqid;
bzero(&oo->ro_reply, sizeof (nfs_resop4));
oo->ro_client = cp;
- oo->ro_cr_set = NULL;
list_create(&oo->ro_statelist, sizeof (rfs4_state_t),
offsetof(rfs4_state_t, rs_node));
@@ -3337,6 +3395,7 @@ rfs4_client_close(rfs4_client_t *cp)
rfs4_dbe_unlock(cp->rc_dbe);
rfs4_client_state_remove(cp);
+ rfs4x_client_session_remove(cp);
/* Release the client */
rfs4_client_rele(cp);
@@ -3461,19 +3520,26 @@ rfs4_get_state(stateid4 *stateid, rfs4_state_t **spp,
}
int
-rfs4_check_stateid_seqid(rfs4_state_t *sp, stateid4 *stateid)
+rfs4_check_stateid_seqid(rfs4_state_t *sp, stateid4 *stateid,
+ const compound_state_t *cs)
{
stateid_t *id = (stateid_t *)stateid;
+ bool_t has_session = rfs4_has_session(cs);
if (rfs4_lease_expired(sp->rs_owner->ro_client))
return (NFS4_CHECK_STATEID_EXPIRED);
+ if (has_session && id->bits.chgseq == 0)
+ return (NFS4_CHECK_STATEID_OKAY);
+
/* Stateid is some time in the future - that's bad */
if (sp->rs_stateid.bits.chgseq < id->bits.chgseq)
return (NFS4_CHECK_STATEID_BAD);
- if (sp->rs_stateid.bits.chgseq == id->bits.chgseq + 1)
+ if (!has_session &&
+ sp->rs_stateid.bits.chgseq == id->bits.chgseq + 1) {
return (NFS4_CHECK_STATEID_REPLAY);
+ }
/* Stateid is some time in the past - that's old */
if (sp->rs_stateid.bits.chgseq > id->bits.chgseq)
@@ -3490,19 +3556,26 @@ rfs4_check_stateid_seqid(rfs4_state_t *sp, stateid4 *stateid)
}
int
-rfs4_check_lo_stateid_seqid(rfs4_lo_state_t *lsp, stateid4 *stateid)
+rfs4_check_lo_stateid_seqid(rfs4_lo_state_t *lsp, stateid4 *stateid,
+ const compound_state_t *cs)
{
stateid_t *id = (stateid_t *)stateid;
+ bool_t has_session = rfs4_has_session(cs);
if (rfs4_lease_expired(lsp->rls_state->rs_owner->ro_client))
return (NFS4_CHECK_STATEID_EXPIRED);
+ if (has_session && id->bits.chgseq == 0)
+ return (NFS4_CHECK_STATEID_OKAY);
+
/* Stateid is some time in the future - that's bad */
if (lsp->rls_lockid.bits.chgseq < id->bits.chgseq)
return (NFS4_CHECK_STATEID_BAD);
- if (lsp->rls_lockid.bits.chgseq == id->bits.chgseq + 1)
+ if (!has_session &&
+ lsp->rls_lockid.bits.chgseq == id->bits.chgseq + 1) {
return (NFS4_CHECK_STATEID_REPLAY);
+ }
/* Stateid is some time in the past - that's old */
if (lsp->rls_lockid.bits.chgseq > id->bits.chgseq)
@@ -3663,6 +3736,24 @@ out:
return (stat);
}
+static nfsstat4
+check_state_seqid(stateid_t *st, stateid_t *in, bool_t has_session)
+{
+ /* rfc56661, section 8.2.2, "seqid to zero" */
+ if (has_session && in->bits.chgseq == 0)
+ return (NFS4_OK);
+
+ /* Seqid in the future? - that's bad */
+ if (st->bits.chgseq < in->bits.chgseq)
+ return (NFS4ERR_BAD_STATEID);
+
+ /* Seqid in the past? - that's old */
+ if (st->bits.chgseq > in->bits.chgseq)
+ return (NFS4ERR_OLD_STATEID);
+
+ return (NFS4_OK);
+}
+
/*
* Given the I/O mode (FREAD or FWRITE), the vnode, the stateid and whether
* the file is being truncated, return NFS4_OK if allowed or appropriate
@@ -3681,7 +3772,7 @@ out:
nfsstat4
rfs4_check_stateid(int mode, vnode_t *vp,
stateid4 *stateid, bool_t trunc, bool_t *deleg,
- bool_t do_access, caller_context_t *ct)
+ bool_t do_access, caller_context_t *ct, compound_state_t *cs)
{
rfs4_file_t *fp;
bool_t create = FALSE;
@@ -3690,6 +3781,7 @@ rfs4_check_stateid(int mode, vnode_t *vp,
rfs4_lo_state_t *lsp;
stateid_t *id = (stateid_t *)stateid;
nfsstat4 stat = NFS4_OK;
+ bool_t use_ss = rfs4_has_session(cs);
if (ct != NULL) {
ct->cc_sysid = 0;
@@ -3702,6 +3794,7 @@ rfs4_check_stateid(int mode, vnode_t *vp,
fp = rfs4_findfile(vp, NULL, &create);
if (fp == NULL)
return (NFS4_OK);
+
if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
rfs4_file_rele(fp);
return (NFS4_OK);
@@ -3718,6 +3811,7 @@ rfs4_check_stateid(int mode, vnode_t *vp,
stat = rfs4_get_all_state(stateid, &sp, &dsp, &lsp);
if (stat != NFS4_OK)
return (stat);
+
if (lsp != NULL) {
/* Is associated server instance in its grace period? */
if (rfs4_clnt_in_grace(lsp->rls_locker->rl_client)) {
@@ -3726,31 +3820,24 @@ rfs4_check_stateid(int mode, vnode_t *vp,
rfs4_state_rele_nounlock(sp);
return (NFS4ERR_GRACE);
}
- if (id->bits.type == LOCKID) {
- /* Seqid in the future? - that's bad */
- if (lsp->rls_lockid.bits.chgseq <
- id->bits.chgseq) {
- rfs4_lo_state_rele(lsp, FALSE);
- if (sp != NULL)
- rfs4_state_rele_nounlock(sp);
- return (NFS4ERR_BAD_STATEID);
- }
- /* Seqid in the past? - that's old */
- if (lsp->rls_lockid.bits.chgseq >
- id->bits.chgseq) {
- rfs4_lo_state_rele(lsp, FALSE);
- if (sp != NULL)
- rfs4_state_rele_nounlock(sp);
- return (NFS4ERR_OLD_STATEID);
- }
- /* Ensure specified filehandle matches */
- if (lsp->rls_state->rs_finfo->rf_vp != vp) {
- rfs4_lo_state_rele(lsp, FALSE);
- if (sp != NULL)
- rfs4_state_rele_nounlock(sp);
- return (NFS4ERR_BAD_STATEID);
- }
+
+ ASSERT(id->bits.type == LOCKID);
+ stat = check_state_seqid(&lsp->rls_lockid, id, use_ss);
+ if (stat) {
+ rfs4_lo_state_rele(lsp, FALSE);
+ if (sp)
+ rfs4_state_rele_nounlock(sp);
+ return (stat);
+ }
+
+ /* Ensure specified filehandle matches */
+ if (lsp->rls_state->rs_finfo->rf_vp != vp) {
+ rfs4_lo_state_rele(lsp, FALSE);
+ if (sp != NULL)
+ rfs4_state_rele_nounlock(sp);
+ return (NFS4ERR_BAD_STATEID);
}
+
if (ct != NULL) {
ct->cc_sysid =
lsp->rls_locker->rl_client->rc_sysidt;
@@ -3766,18 +3853,13 @@ rfs4_check_stateid(int mode, vnode_t *vp,
rfs4_state_rele_nounlock(sp);
return (NFS4ERR_GRACE);
}
+ /* Skip if is here via the LOCKID */
if (id->bits.type == OPENID) {
- /* Seqid in the future? - that's bad */
- if (sp->rs_stateid.bits.chgseq <
- id->bits.chgseq) {
+ stat = check_state_seqid(&sp->rs_stateid, id,
+ use_ss);
+ if (stat) {
rfs4_state_rele_nounlock(sp);
- return (NFS4ERR_BAD_STATEID);
- }
- /* Seqid in the past - that's old */
- if (sp->rs_stateid.bits.chgseq >
- id->bits.chgseq) {
- rfs4_state_rele_nounlock(sp);
- return (NFS4ERR_OLD_STATEID);
+ return (stat);
}
}
/* Ensure specified filehandle matches */
@@ -3842,9 +3924,11 @@ rfs4_check_stateid(int mode, vnode_t *vp,
rfs4_deleg_state_rele(dsp);
return (NFS4ERR_GRACE);
}
- if (dsp->rds_delegid.bits.chgseq != id->bits.chgseq) {
+
+ stat = check_state_seqid(&dsp->rds_delegid, id, use_ss);
+ if (stat) {
rfs4_deleg_state_rele(dsp);
- return (NFS4ERR_BAD_STATEID);
+ return (stat);
}
/* Ensure specified filehandle matches */
diff --git a/usr/src/uts/common/fs/nfs/nfs4_xdr.c b/usr/src/uts/common/fs/nfs/nfs4_xdr.c
index 36b19fe657..1879482a14 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_xdr.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_xdr.c
@@ -21,6 +21,7 @@
/*
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2020 RackTop Systems, Inc.
*/
/*
@@ -65,6 +66,7 @@ bool_t
xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
{
int32_t len, size;
+ uint32_t bmval2 = 0;
if (xdrs->x_op == XDR_FREE)
return (TRUE);
@@ -75,7 +77,15 @@ xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
* uint64_t and ignore all of the rest.
*/
if (xdrs->x_op == XDR_ENCODE) {
- len = 2;
+ bitmap4 obj = *objp;
+
+ objp = &obj;
+ if (*objp & FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL) {
+ bmval2 |= 1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64);
+ *objp &= ~FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL;
+ }
+
+ len = bmval2 ? 3 : 2;
if (!XDR_PUTINT32(xdrs, &len))
return (FALSE);
@@ -83,15 +93,19 @@ xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
#if defined(_LITTLE_ENDIAN)
if (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
BYTES_PER_XDR_UNIT)) == TRUE) {
- return (XDR_PUTINT32(xdrs, (int32_t *)objp));
+ if (!XDR_PUTINT32(xdrs, (int32_t *)objp))
+ return (FALSE);
}
#elif defined(_BIG_ENDIAN)
if (XDR_PUTINT32(xdrs, (int32_t *)objp) == TRUE) {
- return (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
- BYTES_PER_XDR_UNIT)));
+ if (!XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
+ BYTES_PER_XDR_UNIT)))
+ return (FALSE);
}
#endif
- return (FALSE);
+ if (len == 3 && !XDR_PUTINT32(xdrs, (int32_t *)&bmval2))
+ return (FALSE);
+ return (TRUE);
}
if (!XDR_GETINT32(xdrs, &len))
@@ -100,19 +114,28 @@ xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
/*
* Common fast DECODE cases
*/
- if (len == 2) {
+ if (len == 2 || len == 3) {
#if defined(_LITTLE_ENDIAN)
if (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
BYTES_PER_XDR_UNIT)) == TRUE) {
- return (XDR_GETINT32(xdrs, (int32_t *)objp));
+ if (!XDR_GETINT32(xdrs, (int32_t *)objp))
+ return (FALSE);
}
#elif defined(_BIG_ENDIAN)
if (XDR_GETINT32(xdrs, (int32_t *)objp) == TRUE) {
- return (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
- BYTES_PER_XDR_UNIT)));
+ if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
+ BYTES_PER_XDR_UNIT)))
+ return (FALSE);
}
#endif
- return (FALSE);
+ if (len == 3) {
+ if (!XDR_GETINT32(xdrs, (int32_t *)&bmval2))
+ return (FALSE);
+ if (bmval2 & (1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64)))
+ *objp |= FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL;
+ }
+
+ return (TRUE);
}
*objp = 0;
@@ -134,6 +157,12 @@ xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
return (FALSE);
if (--len == 0)
return (TRUE);
+
+ if (!XDR_GETINT32(xdrs, (int32_t *)&bmval2))
+ return (FALSE);
+ if (bmval2 & (1ULL << (FATTR4_SUPPATTR_EXCLCREAT - 64)))
+ *objp |= FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL;
+
if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
return (FALSE);
#else
@@ -661,7 +690,7 @@ xdr_fs_location4(XDR *xdrs, fs_location4 *objp)
}
/* Called by xdr_array */
-static bool_t
+bool_t
xdr_nfsace4(XDR *xdrs, nfsace4 *objp)
{
if (xdrs->x_op != XDR_FREE) {
@@ -755,6 +784,33 @@ xdr_nfstime4(XDR *xdrs, nfstime4 *objp)
return (xdr_u_int(xdrs, &objp->nseconds));
}
+bool_t
+xdr_fattr4_sec_label(XDR *xdrs, fattr4_sec_label *objp)
+{
+ uint_t dummy = 0;
+
+ if (xdrs->x_op == XDR_FREE) {
+ /*
+ * Optimized free case
+ */
+ if (objp->slai_val != NULL)
+ kmem_free(objp->slai_val, objp->slai_len);
+ return (TRUE);
+ }
+
+ /*
+ * For now use a 0 here to indicate the null translation; in
+ * the future we place a call to translation code here.
+ */
+ if (!xdr_u_int(xdrs, &dummy)) /* lfs */
+ return (FALSE);
+
+ if (!xdr_u_int(xdrs, &dummy)) /* pi */
+ return (FALSE);
+
+ return (xdr_bytes(xdrs, (char **)&objp->slai_val,
+ (uint_t *)&objp->slai_len, NFS4_OPAQUE_LIMIT));
+}
/*
* structured used for calls into xdr_ga_fattr_res() as a means
@@ -2510,7 +2566,7 @@ xdr_settime4(XDR *xdrs, settime4 *objp)
return (xdr_u_int(xdrs, &objp->time.nseconds));
}
-static bool_t
+bool_t
xdr_fattr4(XDR *xdrs, fattr4 *objp)
{
if (xdrs->x_op != XDR_FREE) {
@@ -2882,12 +2938,29 @@ xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp)
}
static bool_t
+xdr_share_access(XDR *xdrs, uint32_t *share_access, uint32_t *deleg_want)
+{
+ uint32_t w;
+
+ if (xdrs->x_op == XDR_DECODE) {
+ if (!xdr_u_int(xdrs, &w))
+ return (FALSE);
+
+ *share_access = w & OPEN4_SHARE_ACCESS_MASK;
+ *deleg_want = w & OPEN4_SHARE_WANT_MASK;
+ }
+
+ return (TRUE);
+}
+
+static bool_t
xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
{
if (xdrs->x_op != XDR_FREE) {
if (!xdr_u_int(xdrs, &objp->seqid))
return (FALSE);
- if (!xdr_u_int(xdrs, &objp->share_access))
+ if (!xdr_share_access(xdrs, &objp->share_access,
+ &objp->deleg_want))
return (FALSE);
if (!xdr_u_int(xdrs, &objp->share_deny))
return (FALSE);
@@ -2922,47 +2995,21 @@ xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
createverf))
return (FALSE);
break;
+ case EXCLUSIVE4_1:
+ if (!xdr_creatverfattr(xdrs,
+ &objp->createhow4_u.ch_createboth))
+ return (FALSE);
+ break;
default:
return (FALSE);
}
}
/* xdr_open_claim4 */
- if (!xdr_int(xdrs, (int *)&objp->claim))
- return (FALSE);
-
- switch (objp->claim) {
- case CLAIM_NULL:
- return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
- file.utf8string_val,
- (uint_t *)&objp->open_claim4_u.file.
- utf8string_len,
- NFS4_MAX_UTF8STRING));
- case CLAIM_PREVIOUS:
- return (xdr_int(xdrs,
- (int *)&objp->open_claim4_u.delegate_type));
- case CLAIM_DELEGATE_CUR:
- if (!xdr_u_int(xdrs, (uint_t *)&objp->open_claim4_u.
- delegate_cur_info.delegate_stateid.seqid))
- return (FALSE);
- if (!xdr_opaque(xdrs, objp->open_claim4_u.
- delegate_cur_info.delegate_stateid.other,
- NFS4_OTHER_SIZE))
- return (FALSE);
- return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
- delegate_cur_info.file.utf8string_val,
- (uint_t *)&objp->open_claim4_u.
- delegate_cur_info.file.utf8string_len,
- NFS4_MAX_UTF8STRING));
- case CLAIM_DELEGATE_PREV:
- return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
- file_delegate_prev.utf8string_val,
- (uint_t *)&objp->open_claim4_u.
- file_delegate_prev.utf8string_len,
- NFS4_MAX_UTF8STRING));
- default:
+ if (!xdr_open_claim4(xdrs, &objp->claim))
return (FALSE);
- }
+
+ return (TRUE);
}
/*
@@ -2984,35 +3031,8 @@ xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
}
}
- switch (objp->claim) {
- case CLAIM_NULL:
- if (objp->open_claim4_u.file.utf8string_val != NULL)
- kmem_free(objp->open_claim4_u.file.utf8string_val,
- objp->open_claim4_u.file.utf8string_len);
- return (TRUE);
- case CLAIM_PREVIOUS:
- return (TRUE);
- case CLAIM_DELEGATE_CUR:
- if (objp->open_claim4_u.delegate_cur_info.file.utf8string_val !=
- NULL) {
- kmem_free(objp->open_claim4_u.delegate_cur_info.file.
- utf8string_val,
- objp->open_claim4_u.delegate_cur_info.file.
- utf8string_len);
- }
- return (TRUE);
- case CLAIM_DELEGATE_PREV:
- if (objp->open_claim4_u.file_delegate_prev.utf8string_val !=
- NULL) {
- kmem_free(objp->open_claim4_u.file_delegate_prev.
- utf8string_val,
- objp->open_claim4_u.file_delegate_prev.
- utf8string_len);
- }
- return (TRUE);
- default:
- return (TRUE);
- }
+ (void) xdr_open_claim4(xdrs, &objp->claim);
+ return (TRUE);
}
static bool_t
@@ -3284,7 +3304,7 @@ xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp)
return (FALSE);
if (!xdr_u_int(xdrs, &objp->seqid))
return (FALSE);
- if (!xdr_u_int(xdrs, &objp->share_access))
+ if (!xdr_share_access(xdrs, &objp->share_access, &objp->deleg_want))
return (FALSE);
return (xdr_u_int(xdrs, &objp->share_deny));
}
@@ -3792,6 +3812,18 @@ xdr_secinfo4(XDR *xdrs, secinfo4 *objp)
return (TRUE);
}
+bool_t
+xdr_SECINFO4res(XDR *xdrs, SECINFO4res *objp)
+{
+ if (!xdr_int(xdrs, (int32_t *)&objp->status))
+ return (FALSE);
+ if (objp->status != NFS4_OK)
+ return (TRUE);
+ return (xdr_array(xdrs, (char **)&objp->SECINFO4resok_val,
+ (uint_t *)&objp->SECINFO4resok_len, ~0, sizeof (secinfo4),
+ (xdrproc_t)xdr_secinfo4));
+}
+
static bool_t
xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp)
{
@@ -3948,6 +3980,13 @@ xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len)
return (TRUE);
for (i = 0; i < len; i++) {
+ /* Freeing for nfs4.x */
+ if (array[i].argop >= OP_BACKCHANNEL_CTL &&
+ array[i].argop != OP_ILLEGAL) {
+ xdr_nfs4x_argop4(xdrs, &array[i]);
+ continue;
+ }
+
/*
* These should be ordered by frequency of use
*/
@@ -4309,6 +4348,10 @@ xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp)
return (xdr_decode_nfs_fh4(xdrs,
&objp->nfs_argop4_u.opputfh.object));
default:
+ if (objp->argop >= OP_BACKCHANNEL_CTL &&
+ objp->argop != OP_ILLEGAL)
+ return (xdr_nfs4x_argop4(xdrs, objp));
+
return (xdr_nfs_argop4(xdrs, objp));
}
}
@@ -4775,6 +4818,10 @@ xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp)
return (xdr_encode_nfs_fh4(xdrs,
&objp->nfs_resop4_u.opgetfh.object));
default:
+ if (objp->resop >= OP_BACKCHANNEL_CTL &&
+ objp->resop != OP_ILLEGAL)
+ return (xdr_nfs4x_resop4(xdrs, objp));
+
return (xdr_nfs_resop4(xdrs, objp));
}
}
@@ -5176,32 +5223,6 @@ xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
return (FALSE);
}
-static bool_t
-xdr_nfs_cb_resop4(XDR *xdrs, nfs_cb_resop4 *objp)
-{
- if (!xdr_u_int(xdrs, &objp->resop))
- return (FALSE);
- switch (objp->resop) {
- case OP_CB_GETATTR:
- if (!xdr_int(xdrs,
- (int32_t *)&objp->nfs_cb_resop4_u.opcbgetattr.
- status))
- return (FALSE);
- if (objp->nfs_cb_resop4_u.opcbgetattr.status != NFS4_OK)
- return (TRUE);
- return (xdr_fattr4(xdrs,
- &objp->nfs_cb_resop4_u.opcbgetattr.
- obj_attributes));
- case OP_CB_RECALL:
- return (xdr_int(xdrs,
- (int32_t *)&objp->nfs_cb_resop4_u.opcbrecall.status));
- case OP_CB_ILLEGAL:
- return (xdr_int(xdrs,
- (int32_t *)&objp->nfs_cb_resop4_u.opcbillegal.status));
- }
- return (FALSE);
-}
-
/*
* The NFS client side callback, RPC server
*/
diff --git a/usr/src/uts/common/fs/nfs/nfs4x_dispatch.c b/usr/src/uts/common/fs/nfs/nfs4x_dispatch.c
new file mode 100644
index 0000000000..49ae2d6ad4
--- /dev/null
+++ b/usr/src/uts/common/fs/nfs/nfs4x_dispatch.c
@@ -0,0 +1,177 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2017 RackTop Systems.
+ */
+
+#include <sys/systm.h>
+#include <sys/sdt.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include <rpc/auth_des.h>
+#include <rpc/svc.h>
+#include <rpc/xdr.h>
+#include <nfs/nfs4.h>
+#include <nfs/nfs_dispatch.h>
+#include <sys/cmn_err.h>
+#include <sys/modctl.h>
+
+static void
+rfs4_err_resp(COMPOUND4args *args, COMPOUND4res *resp, nfsstat4 err)
+{
+ size_t sz;
+
+ resp->array_len = 1;
+ sz = resp->array_len * sizeof (nfs_resop4);
+ resp->array = kmem_zalloc(sz, KM_SLEEP);
+
+ resp->array[0].resop = args->array[0].argop;
+ resp->status = resp->array[0].nfs_resop4_u.opillegal.status = err;
+}
+
+/*
+ * The function checks if given compound operation is allowed
+ * to be the very fist operation in compound array.
+ */
+static bool_t
+valid_first_compound_op(nfs_opnum4 op)
+{
+ if (op == OP_BIND_CONN_TO_SESSION ||
+ op == OP_SEQUENCE ||
+ op == OP_EXCHANGE_ID ||
+ op == OP_CREATE_SESSION ||
+ op == OP_DESTROY_SESSION ||
+ op == OP_DESTROY_CLIENTID ||
+ op == OP_ILLEGAL)
+ return (TRUE);
+
+ return (FALSE);
+}
+
+/*
+ * The function verifies arguments passed to mds_op_compound.
+ * If agrguments are valid, NFS4_OK is returned, otherwise
+ * function returns correspoinding NFS4 error code.
+ */
+static nfsstat4
+verify_compound_args(COMPOUND4args *args)
+{
+ if (args->array_len == 0)
+ return (NFS4_OK);
+
+ if (!valid_first_compound_op(args->array[0].argop))
+ return (NFS4ERR_OP_NOT_IN_SESSION);
+
+ if (args->array_len > 1 && args->array[0].argop != OP_SEQUENCE) {
+ /*
+ * Compound is outside the session. There must be
+ * only one operation in request.
+ */
+ return (NFS4ERR_NOT_ONLY_OP);
+ }
+
+ return (NFS4_OK);
+}
+
+static void
+rfs4x_dispatch_done(compound_state_t *cs)
+{
+ if (cs->slot)
+ rfs4x_sequence_done(cs->cmpresp, cs);
+ else {
+ rfs4_compound_free(cs->cmpresp);
+ }
+ cs->cs_flags |= RFS4_DISPATCH_DONE;
+}
+
+static bool_t
+xdr_compound_wrapper(XDR *xdrs, compound_state_t *cs)
+{
+ COMPOUND4res *resp = cs->cmpresp;
+ bool_t res = FALSE;
+ bool_t isreal = (xdrs->x_handy != 0); /* real data encoding ? */
+
+ if (!(cs->cs_flags & RFS4_DISPATCH_DONE)) {
+ res = xdr_COMPOUND4res_srv(xdrs, resp);
+ if (isreal)
+ rfs4x_dispatch_done(cs);
+ }
+
+ return (res);
+}
+
+int
+rfs4x_dispatch(struct svc_req *req, SVCXPRT *xprt, char *ap)
+{
+ struct compound_state cs;
+ COMPOUND4res res_buf;
+ COMPOUND4res *rbp;
+ COMPOUND4args *cap;
+ int rpcerr = 0;
+ nfsstat4 error;
+
+ bzero(&res_buf, sizeof (COMPOUND4res));
+ rbp = &res_buf;
+ cap = (COMPOUND4args *)ap;
+ rfs4_init_compound_state(&cs);
+
+ cs.statusp = &error;
+ cs.cmpresp = rbp;
+
+ error = verify_compound_args(cap);
+ if (error != NFS4_OK) { /* NFS4_OK is 0 */
+ rfs4_err_resp(cap, rbp, error);
+ goto out_send;
+ }
+
+ error = rfs4x_sequence_prep(cap, rbp, &cs);
+ if (error != NFS4_OK) {
+ if (error != nfserr_replay_cache)
+ rfs4_err_resp(cap, rbp, error);
+ goto out_send;
+ }
+
+ /* Regular processing */
+ curthread->t_flag |= T_DONTPEND;
+ rfs4_compound(cap, rbp, &cs, req, &rpcerr);
+ curthread->t_flag &= ~T_DONTPEND;
+
+ /*
+ * On RPC error, short sendreply
+ */
+ if (rpcerr) {
+ goto out_free;
+ }
+
+ if (curthread->t_flag & T_WOULDBLOCK) {
+ curthread->t_flag &= ~T_WOULDBLOCK;
+ error = 1;
+ goto out_free;
+ }
+
+out_send:
+ if (!svc_sendreply(xprt, xdr_compound_wrapper, (char *)&cs)) {
+ DTRACE_PROBE2(sendfail, SVCXPRT *, xprt,
+ compound_state_t *, &cs);
+ svcerr_systemerr(xprt);
+ rpcerr = 1;
+ }
+
+out_free:
+ if (!(cs.cs_flags & RFS4_DISPATCH_DONE)) {
+ rfs4x_dispatch_done(&cs);
+ }
+
+ rfs4_fini_compound_state(&cs);
+ return ((error != NFS4_OK || rpcerr) ? 1 : 0);
+}
diff --git a/usr/src/uts/common/fs/nfs/nfs4x_srv.c b/usr/src/uts/common/fs/nfs/nfs4x_srv.c
new file mode 100644
index 0000000000..854a8e1abe
--- /dev/null
+++ b/usr/src/uts/common/fs/nfs/nfs4x_srv.c
@@ -0,0 +1,1250 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2017 RackTop Systems.
+ */
+
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/rpcsec_gss.h>
+#include <sys/sdt.h>
+#include <sys/disp.h>
+#include <nfs/nfs.h>
+#include <nfs/nfs4.h>
+#include <sys/systeminfo.h>
+
+/* Helpers */
+
+/* Principal handling routines */
+/* returns 0 if no match; or 1 for a match */
+int
+rfs4_cmp_cred_set(cred_set_t *p, struct compound_state *cs)
+{
+ int rc = 0;
+ rpc_gss_principal_t recp; /* cached clnt princ */
+ rpc_gss_principal_t ibrp; /* inbound req princ */
+
+
+ if (p->cp_cr == NULL)
+ return (rc); /* nothing to compare with */
+
+ if (p->cp_aflavor != cs->req->rq_cred.oa_flavor)
+ return (rc);
+
+ if (p->cp_secmod != cs->nfsflavor)
+ return (rc);
+
+ if (crcmp(p->cp_cr, cs->basecr))
+ return (rc);
+
+ switch (p->cp_aflavor) {
+ case AUTH_DES:
+ rc = (strcmp(p->cp_princ, cs->principal) == 0);
+ break;
+
+ case RPCSEC_GSS:
+ recp = (rpc_gss_principal_t)p->cp_princ;
+ ibrp = (rpc_gss_principal_t)cs->principal;
+
+ if (recp->len != ibrp->len)
+ break;
+ rc = (bcmp(recp->name, ibrp->name, ibrp->len) == 0);
+ break;
+
+ case AUTH_SYS:
+ case AUTH_NONE:
+ default:
+ rc = 1;
+ break;
+ }
+ return (rc);
+}
+
+static rpc_gss_principal_t
+rfs4_dup_princ(rpc_gss_principal_t ppl)
+{
+ rpc_gss_principal_t pdup;
+ int len;
+
+ if (ppl == NULL)
+ return (NULL);
+
+ len = sizeof (int) + ppl->len;
+ pdup = (rpc_gss_principal_t)kmem_alloc(len, KM_SLEEP);
+ bcopy(ppl, pdup, len);
+ return (pdup);
+}
+
+void
+rfs4_set_cred_set(cred_set_t *p, struct compound_state *cs)
+{
+ ASSERT(p->cp_cr == NULL);
+
+ p->cp_cr = crdup(cs->basecr);
+ p->cp_aflavor = cs->req->rq_cred.oa_flavor;
+ p->cp_secmod = cs->nfsflavor; /* secmod != flavor for RPCSEC_GSS */
+
+ /*
+ * Set principal as per security flavor
+ */
+ switch (p->cp_aflavor) {
+ case AUTH_DES:
+ p->cp_princ = strdup(cs->principal);
+ break;
+
+ case RPCSEC_GSS:
+ p->cp_princ =
+ (caddr_t)rfs4_dup_princ((rpc_gss_principal_t)cs->principal);
+ break;
+
+ case AUTH_SYS:
+ case AUTH_NONE:
+ default:
+ break;
+ }
+}
+
+void
+rfs4_free_cred_set(cred_set_t *p)
+{
+ rpc_gss_principal_t ppl;
+
+ if (p->cp_cr == NULL)
+ return;
+
+ switch (p->cp_aflavor) {
+ case AUTH_DES:
+ kmem_free(p->cp_princ, strlen(p->cp_princ) + 1);
+ break;
+
+ case RPCSEC_GSS:
+ ppl = (rpc_gss_principal_t)p->cp_princ;
+ kmem_free(ppl, ppl->len + sizeof (int));
+ break;
+ }
+
+ crfree(p->cp_cr);
+ p->cp_cr = NULL;
+}
+
+/* principal end */
+
+bool_t
+nfs_clid4_cmp(nfs_client_id4 *s1, nfs_client_id4 *s2)
+{
+ if (s1->verifier != s2->verifier)
+ return (FALSE);
+ if (s1->id_len != s2->id_len)
+ return (FALSE);
+ if (bcmp(s1->id_val, s2->id_val, s2->id_len))
+ return (FALSE);
+ return (TRUE);
+}
+
+/*
+ * Rudimentary server implementation (XXX - for now)
+ */
+void
+rfs4x_get_server_impl_id(EXCHANGE_ID4resok *resp)
+{
+ char *sol_impl = "illumos NFSv4.1 Server Implementation";
+ char *sol_idom = "nfsv41.ietf.org";
+ void *p;
+ uint_t len = 0;
+ nfs_impl_id4 *nip;
+
+ resp->eir_server_impl_id.eir_server_impl_id_len = 1;
+ nip = kmem_zalloc(sizeof (nfs_impl_id4), KM_SLEEP);
+ resp->eir_server_impl_id.eir_server_impl_id_val = nip;
+
+ /* Domain */
+ nip->nii_domain.utf8string_len = len = strlen(sol_idom);
+ p = kmem_zalloc(len * sizeof (char), KM_SLEEP);
+ nip->nii_domain.utf8string_val = p;
+ bcopy(sol_idom, p, len);
+
+ /* Implementation */
+ nip->nii_name.utf8string_len = len = strlen(sol_impl);
+ p = kmem_zalloc(len * sizeof (char), KM_SLEEP);
+ nip->nii_name.utf8string_val = p;
+ bcopy(sol_impl, p, len);
+
+ /* Time is zero for now */
+}
+
+/*
+ * Compute the "use bits", i.e. the flags specifying the permissible
+ * regular, MDS, and data server ops for the returned clientid.
+ *
+ * The minorversion1 specification allows a server implementor two
+ * alternatives: allow PNFS_MDS and PNFS_DS on the same clientid, or
+ * force the client to create separate clientids to distinguish
+ * MDS versus DS operations.
+ *
+ * Our design distinguishes operations based upon filehandle, and thus
+ * there is no reason to force the client to create separate clientids.
+ * Thus, we give the client as much as possible, while keeping the result
+ * within the allowed combinations as specified in the specification.
+ *
+ * Our constraints are: use a subset of the client's request, unless
+ * the client requested nothing, in which case we may return any
+ * legal combination; and, the combination of NON_PNFS and PNFS_MDS
+ * may not both be set in the results. These constraints are reflected
+ * in the ASSERT()s at the end.
+ */
+
+static uint32_t
+compute_use_pnfs_flags(uint32_t request)
+{
+ uint32_t rc;
+
+ /* Start with the client's initial request */
+ rc = request & EXCHGID4_FLAG_MASK_PNFS;
+
+ /* If the client requested nothing, return the most permissive. */
+ if (rc == 0) {
+ rc = EXCHGID4_FLAG_USE_NON_PNFS;
+ goto done;
+ }
+
+ /* Don't permit the illegal combination of MDS and NON_PNFS */
+ if ((rc &
+ (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS)) ==
+ (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))
+ rc &= ~EXCHGID4_FLAG_USE_PNFS_MDS;
+done:
+ ASSERT(((request & EXCHGID4_FLAG_MASK_PNFS) == 0) ||
+ ((rc & ~(request & EXCHGID4_FLAG_MASK_PNFS)) == 0));
+ ASSERT((rc & (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))
+ != (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS));
+ ASSERT(rc != 0);
+
+ return (rc);
+}
+
+static void
+rfs4x_set_trunkinfo(EXCHANGE_ID4resok *rok)
+{
+ const char *nodename = uts_nodename();
+ unsigned int nd_len = strlen(nodename);
+ unsigned int hw_len = strlen(hw_serial);
+ unsigned id_len = nd_len + 1 + hw_len;
+ char *s = kmem_alloc(id_len, KM_SLEEP);
+ server_owner4 *so = &rok->eir_server_owner;
+ struct eir_server_scope *ss = &rok->eir_server_scope;
+
+ (void) memcpy(s, nodename, nd_len);
+ s[nd_len] = ' ';
+ (void) memcpy(s + nd_len + 1, hw_serial, hw_len);
+
+ so->so_major_id.so_major_id_len = id_len;
+ so->so_major_id.so_major_id_val = s;
+
+ ss->eir_server_scope_len = id_len;
+ ss->eir_server_scope_val = kmem_alloc(id_len, KM_SLEEP);
+ (void) memcpy(ss->eir_server_scope_val, s, id_len);
+
+ rok->eir_server_owner.so_minor_id = 0;
+}
+
+static bool_t
+client_has_state_locked(rfs4_client_t *cp)
+{
+ if (list_head(&cp->rc_sessions) != NULL ||
+ list_head(&cp->rc_openownerlist) != NULL)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+/* OPERATIONS */
+
+/* EXCHANGE_ID */
+void
+rfs4x_op_exchange_id(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs)
+{
+ EXCHANGE_ID4args *args = &argop->nfs_argop4_u.opexchange_id;
+ EXCHANGE_ID4res *resp = &resop->nfs_resop4_u.opexchange_id;
+ EXCHANGE_ID4resok *rok = &resp->EXCHANGE_ID4res_u.eir_resok4;
+ rfs4_client_t *cp, *conf;
+ bool_t update, create;
+ client_owner4 *cop;
+ nfs_client_id4 cid; /* cip */
+ nfsstat4 status = NFS4_OK;
+ nfs4_srv_t *nsrv4;
+
+ DTRACE_NFSV4_2(op__exchange__id__start,
+ struct compound_state *, cs,
+ EXCHANGE_ID4args *, args);
+
+ /*
+ * EXCHANGE_ID's may be preceded by SEQUENCE
+ *
+ * Check that eia_flags only has "valid" spec bits
+ * and that no 'eir_flag' ONLY bits are specified.
+ */
+ if (args->eia_flags & ~EXID4_FLAG_MASK) {
+ status = NFS4ERR_INVAL;
+ goto err;
+ }
+
+ update = (args->eia_flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A);
+ cop = &args->eia_clientowner;
+ conf = NULL;
+
+ cid.verifier = cop->co_verifier;
+ cid.id_len = cop->co_ownerid.co_ownerid_len;
+ cid.id_val = cop->co_ownerid.co_ownerid_val;
+ cid.cl_addr = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
+
+ /*
+ * Refer to Section 18.35.4
+ */
+again:
+ create = TRUE;
+ cp = rfs4_findclient(&cid, &create, conf);
+ ASSERT(cp != NULL);
+
+ if (conf) {
+ rfs4_dbe_lock(cp->rc_dbe);
+ if (cp->rc_cp_confirmed == NULL)
+ cp->rc_cp_confirmed = conf;
+ else
+ rfs4_client_rele(conf);
+ rfs4_dbe_unlock(cp->rc_dbe);
+ conf = NULL;
+ }
+
+ if (create) {
+ /* Record just created */
+ if (!update) {
+ /* case 1 - utok */
+ rfs4_set_cred_set(&cp->rc_cr_set, cs);
+
+ rok->eir_clientid = cp->rc_clientid;
+ rok->eir_sequenceid = cp->rc_contrived.xi_sid;
+ goto out;
+ } else {
+ /* no record and trying to update */
+ status = NFS4ERR_NOENT;
+ goto err_out;
+ }
+ }
+
+ /* Record exists */
+
+ /* expired clients should be ignored and released */
+ if (rfs4_lease_expired(cp)) {
+ rfs4_client_close(cp);
+ update = FALSE;
+ goto again;
+ }
+
+ if (cp->rc_need_confirm) {
+ /* UNCONFIRMED */
+ if (!update) {
+ /* case 4 - utok */
+ rfs4_client_close(cp);
+
+ ASSERT(!update);
+ goto again;
+ } else {
+ /* case 7 - utok */
+ status = NFS4ERR_NOENT;
+ goto err_out;
+ }
+ }
+
+ /* record exists and confirmed */
+ if (!update) {
+ if (!rfs4_cmp_cred_set(&cp->rc_cr_set, cs)) {
+ /* case 3 */
+ /* lease is checked above */
+ rfs4_dbe_lock(cp->rc_dbe);
+ if (!client_has_state_locked(cp)) {
+ rfs4_dbe_unlock(cp->rc_dbe);
+
+ rfs4_client_close(cp);
+ ASSERT(!update);
+ goto again;
+ }
+ rfs4_dbe_unlock(cp->rc_dbe);
+
+ /*
+ * clid_in_use. old_client_ret has unexpired
+ * lease with state.
+ */
+ status = NFS4ERR_CLID_INUSE;
+ goto err_out;
+ } else if (cp->rc_nfs_client.verifier != cid.verifier) {
+ /* case 5: Client Restart */
+ /*
+ * Skip confirmed client record to allow confirmed
+ * and unconfirmed state at the same time. The number
+ * of states can collapse to one once the server
+ * receives an applicable CREATE_SESSION or EXCHANGE_ID.
+ */
+ ASSERT(conf == NULL);
+ conf = cp;
+ ASSERT(!update);
+ goto again;
+
+ } else if (nfs_clid4_cmp(&cp->rc_nfs_client, &cid)) {
+ /* case 2 - utok */
+ rok->eir_clientid = cp->rc_clientid;
+ rok->eir_sequenceid = cp->rc_contrived.xi_sid;
+ /* trickle down to "out" */
+
+ } else {
+ /* something is really wacky in srv state */
+ status = NFS4ERR_SERVERFAULT;
+ goto err_out;
+ }
+
+ } else { /* UPDATE */
+ if (cp->rc_nfs_client.verifier != cid.verifier) {
+ /* 18.35.4 case 8 */
+ status = NFS4ERR_NOT_SAME;
+ goto err_out;
+ }
+ if (!rfs4_cmp_cred_set(&cp->rc_cr_set, cs)) {
+ /* 18.35.4 case 9 */
+ status = NFS4ERR_PERM;
+ goto err_out;
+ }
+
+ /* case 6 - utok */
+ rok->eir_clientid = cp->rc_clientid;
+ rok->eir_sequenceid = cp->rc_contrived.xi_sid;
+ /* trickle down to "out" */
+ }
+out:
+ rok->eir_flags = 0;
+ if (resp->eir_status == NFS4_OK && !cp->rc_need_confirm)
+ rok->eir_flags |= EXCHGID4_FLAG_CONFIRMED_R;
+
+ /*
+ * State Protection Mojo
+ */
+ cp->rc_state_prot.sp_type = args->eia_state_protect.spa_how;
+ switch (cp->rc_state_prot.sp_type) {
+ case SP4_NONE:
+ break;
+
+ case SP4_MACH_CRED:
+ /* XXX - Some of Karen's secret sauce here... */
+ break;
+
+ case SP4_SSV:
+ /* XXX - ... and here */
+#define ssv_args eia_state_protect.state_protect4_a_u.spa_ssv_parms
+ if (args->ssv_args.ssp_ops.spo_must_allow & OP_EXCHANGE_ID) {
+ /*
+ * if the client ID was created specifying SP4_SSV
+ * state protection and EXCHANGE_ID as the one of
+ * the operations in spo_must_allow, then server MUST
+ * authorize EXCHANGE_IDs with the SSV principal in
+ * addition to the principal that created the client
+ * ID.
+ */
+ /* EMPTY */;
+ }
+ break;
+ }
+
+ /*
+ * Referrals supports
+ */
+ if (args->eia_flags & EXCHGID4_FLAG_SUPP_MOVED_REFER) {
+ rok->eir_flags |= EXCHGID4_FLAG_SUPP_MOVED_REFER;
+ }
+
+ /*
+ * Migration/Replication not (yet) supported
+ */
+ if (args->eia_flags & EXCHGID4_FLAG_SUPP_MOVED_MIGR)
+ rok->eir_flags &= ~EXCHGID4_FLAG_SUPP_MOVED_MIGR;
+
+ /*
+ * TODO: Add the appropriate "use_pnfs" flags.
+ */
+ rok->eir_flags |= compute_use_pnfs_flags(args->eia_flags);
+
+ /* force no state protection for now */
+ rok->eir_state_protect.spr_how = SP4_NONE;
+
+ /* Implementation specific mojo */
+ if (args->eia_client_impl_id.eia_client_impl_id_len != 0) {
+ /* EMPTY */;
+ }
+
+ nsrv4 = nfs4_get_srv();
+
+ /* XXX - jw - best guess */
+ rfs4_ss_clid(nsrv4, cp);
+
+ /* Server's implementation */
+ rfs4x_get_server_impl_id(rok);
+
+ /* compute trunking capabilities */
+ bzero(&rok->eir_server_scope, sizeof (rok->eir_server_scope));
+ bzero(&rok->eir_server_owner, sizeof (server_owner4));
+
+ /* Add trunk handling */
+ rfs4x_set_trunkinfo(rok);
+
+ /*
+ * XXX - jw - best guess
+ * Check to see if client can perform reclaims
+ */
+ rfs4_ss_chkclid(nsrv4, cp);
+
+err_out:
+ rfs4_client_rele(cp);
+err:
+ *cs->statusp = resp->eir_status = status;
+
+ DTRACE_NFSV4_2(op__exchange__id__done,
+ struct compound_state *, cs,
+ EXCHANGE_ID4res *, resp);
+}
+
+void
+rfs4x_exchange_id_free(nfs_resop4 *resop)
+{
+ EXCHANGE_ID4res *resp = &resop->nfs_resop4_u.opexchange_id;
+ EXCHANGE_ID4resok *rok = &resp->EXCHANGE_ID4res_u.eir_resok4;
+ struct server_owner4 *sop = &rok->eir_server_owner;
+ nfs_impl_id4 *nip;
+ int len = 0;
+
+ /* Server Owner: major */
+ if ((len = sop->so_major_id.so_major_id_len) != 0)
+ kmem_free(sop->so_major_id.so_major_id_val, len);
+
+ if ((nip = rok->eir_server_impl_id.eir_server_impl_id_val) != NULL) {
+ /* Immplementation */
+ len = nip->nii_name.utf8string_len;
+ kmem_free(nip->nii_name.utf8string_val, len * sizeof (char));
+
+ /* Domain */
+ len = nip->nii_domain.utf8string_len;
+ kmem_free(nip->nii_domain.utf8string_val, len * sizeof (char));
+
+ /* Server Impl */
+ kmem_free(nip, sizeof (nfs_impl_id4));
+ }
+}
+
+void
+rfs4x_op_create_session(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs)
+{
+ CREATE_SESSION4args *args = &argop->nfs_argop4_u.opcreate_session;
+ CREATE_SESSION4res *resp = &resop->nfs_resop4_u.opcreate_session;
+ CREATE_SESSION4resok *rok = &resp->CREATE_SESSION4res_u.csr_resok4;
+ CREATE_SESSION4resok *crp;
+ rfs4_client_t *cp;
+ rfs4_session_t *sp;
+ session41_create_t sca;
+ sequenceid4 stseq;
+ sequenceid4 agseq;
+ nfsstat4 status = NFS4_OK;
+
+ DTRACE_NFSV4_2(op__create__session__start,
+ struct compound_state *, cs,
+ CREATE_SESSION4args*, args);
+
+ /*
+ * A CREATE_SESSION request can be prefixed by OP_SEQUENCE.
+ * In this case, the newly created session has no relation
+ * to the sessid used for the OP_SEQUENCE.
+ */
+
+ /*
+ * Find the clientid
+ */
+ cp = rfs4_findclient_by_id(args->csa_clientid, TRUE);
+ if (cp == NULL) {
+ status = NFS4ERR_STALE_CLIENTID;
+ goto out;
+ }
+
+ /*
+ * Make sure the lease is still valid.
+ */
+ if (rfs4_lease_expired(cp)) {
+ rfs4_client_close(cp);
+ status = NFS4ERR_STALE_CLIENTID;
+ goto out;
+ }
+
+ /*
+ * Sequenceid processing (handling replay's, etc)
+ */
+ agseq = args->csa_sequence;
+ stseq = cp->rc_contrived.xi_sid;
+ if (stseq == agseq + 1) {
+ /*
+ * If the previous sequenceid, then must be a replay of a
+ * previous CREATE_SESSION; return the cached result.
+ */
+ crp = (CREATE_SESSION4resok *)&cp->rc_contrived.cs_res;
+ status = cp->rc_contrived.cs_status;
+ rok->csr_sequence = agseq;
+ bcopy(crp->csr_sessionid, rok->csr_sessionid,
+ sizeof (sessionid4));
+ rok->csr_flags = crp->csr_flags;
+ rok->csr_fore_chan_attrs = crp->csr_fore_chan_attrs;
+ rok->csr_back_chan_attrs = crp->csr_back_chan_attrs;
+
+ rfs4_update_lease(cp);
+ rfs4_client_rele(cp);
+ goto out;
+ }
+
+ if (stseq != agseq) {
+ /*
+ * No way to differentiate MISORD_NEWREQ vs. MISORD_REPLAY,
+ * so anything else, we simply treat as SEQ_MISORDERED.
+ */
+ status = NFS4ERR_SEQ_MISORDERED;
+ rfs4_client_rele(cp);
+ goto out;
+ }
+
+ /*
+ * Clientid confirmation
+ */
+ if (cp->rc_need_confirm) {
+ if (rfs4_cmp_cred_set(&cp->rc_cr_set, cs)) {
+ cp->rc_need_confirm = FALSE;
+ if (cp->rc_cp_confirmed != NULL) {
+ rfs4_client_close(cp->rc_cp_confirmed);
+ cp->rc_cp_confirmed = NULL;
+ }
+ } else {
+ status = NFS4ERR_CLID_INUSE;
+ rfs4_client_rele(cp);
+ goto out;
+ }
+ }
+
+ /*
+ * Session creation
+ */
+ sca.cs_error = 0;
+ sca.cs_req = req;
+ sca.cs_client = cp;
+ sca.cs_aotw = *args;
+ sp = rfs4x_createsession(&sca);
+
+ if (sca.cs_error) {
+ status = sca.cs_error;
+ rfs4_client_rele(cp);
+ if (sp != NULL)
+ rfs4x_session_rele(sp);
+ goto out;
+ }
+
+ if (sp == NULL) {
+ status = NFS4ERR_SERVERFAULT;
+ rfs4_client_rele(cp);
+ goto out;
+ }
+
+ /*
+ * Need to store the result in the rfs4_client_t's contrived
+ * result slot and then respond from there. This way, when the
+ * csa_sequence == contrived.cc_sid, we can return the latest
+ * cached result. (see replay: above)
+ */
+ crp = (CREATE_SESSION4resok *)&cp->rc_contrived.cs_res;
+ cp->rc_contrived.cs_status = NFS4_OK;
+ rok->csr_sequence = crp->csr_sequence = cp->rc_contrived.xi_sid;
+ bcopy(sp->sn_sessid, rok->csr_sessionid, sizeof (sessionid4));
+ bcopy(sp->sn_sessid, crp->csr_sessionid, sizeof (sessionid4));
+ rok->csr_flags = crp->csr_flags = sp->sn_csflags;
+
+ cp->rc_contrived.xi_sid++;
+
+ /*
+ * XXX: struct assignment of channel4_attrs is broken because
+ * ca_rdma_ird is specified as a single element array. A struct
+ * assignment will copy the ca_rdma_ird array ptr to multiple args/
+ * res structs, and the ptr will be free'd multiple times.
+ * Without RDMA, ca_rdma_ird is a zero element array so its ptr
+ * is NULL (which is why this doesn't cause problems right now).
+ *
+ * Struct assignment is convenient, and it would be best to enable
+ * it by creating an in-kernel channel4_attrs struct which didn't
+ * contain the single element array, but just contained the inbound
+ * receive queue depth. Let the XDR encode/decode funcs convert
+ * from the in-kernel form to the OTW form.
+ */
+ rok->csr_fore_chan_attrs =
+ crp->csr_fore_chan_attrs = sp->sn_fore->cn_attrs;
+ rok->csr_back_chan_attrs = crp->csr_back_chan_attrs =
+ args->csa_back_chan_attrs;
+
+ rfs4_update_lease(cp);
+
+ /*
+ * References from the session to the client are
+ * accounted for while session is being created.
+ */
+ rfs4_client_rele(cp);
+ rfs4x_session_rele(sp);
+out:
+ *cs->statusp = resp->csr_status = status;
+
+ DTRACE_NFSV4_2(op__create__session__done,
+ struct compound_state *, cs,
+ CREATE_SESSION4res *, resp);
+}
+
+/* ARGSUSED */
+void
+rfs4x_op_destroy_session(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs)
+{
+ DESTROY_SESSION4args *args = &argop->nfs_argop4_u.opdestroy_session;
+ DESTROY_SESSION4res *resp = &resop->nfs_resop4_u.opdestroy_session;
+ rfs4_session_t *sp;
+ rfs4_client_t *cp;
+ nfsstat4 status = NFS4_OK;
+ int addref = 0; /* additional reference */
+
+ DTRACE_NFSV4_2(op__destroy__session__start,
+ struct compound_state *, cs,
+ DESTROY_SESSION4args *, args);
+
+ /* section 18.37.3 rfc5661 */
+ if (rfs4_has_session(cs)) {
+ /* compound with a sequence */
+ if (bcmp(args->dsa_sessionid, cs->sp->sn_sessid,
+ sizeof (sessionid4)) == 0) {
+ /*
+ * Same session.
+ * must be the final operation in the COMPOUND request
+ */
+ if ((cs->op_pos + 1) != cs->op_len) {
+ status = NFS4ERR_NOT_ONLY_OP;
+ goto out;
+ }
+ addref++;
+ } else {
+ /* Not the same session */
+ /*
+ * TODO: need to verify that both sessions share
+ * the connection
+ */
+ DTRACE_PROBE(nfss41__i__destroy_encap_session);
+
+ }
+ }
+
+ sp = rfs4x_findsession_by_id(args->dsa_sessionid);
+ if (sp == NULL) {
+ status = NFS4ERR_BADSESSION;
+ goto out;
+ }
+ /*
+ * verify cred that was used to create the session matches and is in
+ * concordance w/the state protection type used.
+ */
+ cp = sp->sn_clnt;
+ switch (cp->rc_state_prot.sp_type) {
+ case SP4_MACH_CRED:
+ cmn_err(CE_NOTE, "op_destroy_session: SP4_MACH_CRED");
+ if (!rfs4_cmp_cred_set(&cp->rc_cr_set, cs)) {
+ status = NFS4ERR_PERM;
+ rfs4x_session_rele(sp);
+ goto out;
+ }
+ break;
+
+ case SP4_SSV:
+ /*
+ * XXX - Need some of Karen's secret ssv sauce
+ * here. For now, just allow the destroy.
+ */
+ cmn_err(CE_NOTE, "op_destroy_session: SP4_SSV");
+ break;
+
+ case SP4_NONE:
+ break;
+
+ default:
+ break;
+ }
+
+ status = rfs4x_destroysession(sp, 2 + addref);
+ rfs4x_session_rele(sp);
+out:
+ *cs->statusp = resp->dsr_status = status;
+
+ DTRACE_NFSV4_2(op__destroy__session__done,
+ struct compound_state *, cs,
+ DESTROY_SESSION4res *, resp);
+}
+
+/*
+ * The thread will traverse the entire list pinging the connections
+ * that need it and refreshing any stale/dead connections.
+ */
+static void
+ping_cb_null_thr(rfs4_session_t *sp)
+{
+ /* TODO: Need implementation */
+ cmn_err(CE_NOTE, "nfs4x: ping_cb_null thread");
+ rfs4x_session_rele(sp);
+ thread_exit();
+}
+
+/*
+ * Find session and validate sequence args.
+ * If this function successfully completes the compound state
+ * will contain a session pointer.
+ */
+static nfsstat4
+rfs4x_find_session(SEQUENCE4args *sargs, struct compound_state *cs)
+{
+ rfs4_session_t *sp;
+ slotid4 slot;
+
+ ASSERT(sargs != NULL);
+
+ if ((sp = rfs4x_findsession_by_id(sargs->sa_sessionid)) == NULL)
+ return (NFS4ERR_BADSESSION);
+
+ slot = sargs->sa_slotid;
+ if (slot < 0 || slot >= sp->sn_fore->cn_attrs.ca_maxrequests) {
+ rfs4x_session_rele(sp);
+ return (NFS4ERR_BADSLOT);
+ }
+ cs->sp = sp;
+ cs->cachethis = sargs->sa_cachethis;
+
+ return (NFS4_OK);
+}
+
+/* called under held lock */
+static nfsstat4
+check_slot_seqid(rfs4_slot_t *slot, sequenceid4 seqid)
+{
+ nfsstat4 status = NFS4ERR_SEQ_MISORDERED;
+
+ if (slot->se_flags & RFS4_SLOT_INUSE) {
+ /*
+ * There are three cases:
+ * 1. Duplicated requests for currently performing
+ * duplicated request.
+ * 2. New request for currently performing duplicated
+ * request.
+ * 3. Request with bad seqid for non finished performing
+ * request (due to a little window between 'prep'
+ * stage and actual renew se_seqid).
+ * In all cases tell a client to retry request later.
+ */
+ if (slot->se_seqid == seqid || slot->se_seqid + 1 == seqid) {
+ status = NFS4ERR_DELAY;
+ }
+ } else {
+ if (seqid == slot->se_seqid + 1)
+ status = NFS4_OK;
+ else if (seqid == slot->se_seqid)
+ status = nfserr_replay_cache;
+ }
+ return (status);
+}
+
+/*
+ * Prep stage for SEQUENCE operation.
+ *
+ * Main purpose to call this:
+ * - check on cached replay
+ * - Set cs.sp and cs.slot
+ */
+int
+rfs4x_sequence_prep(COMPOUND4args *args, COMPOUND4res *resp,
+ compound_state_t *cs)
+{
+ SEQUENCE4args *sargs;
+ nfsstat4 status;
+ rfs4_slot_t *slot;
+
+ if (args->array_len == 0 || args->array[0].argop != OP_SEQUENCE)
+ return (NFS4_OK);
+
+ sargs = &args->array[0].nfs_argop4_u.opsequence;
+
+ status = rfs4x_find_session(sargs, cs);
+ if (status != NFS4_OK)
+ return (status);
+
+ /* have reference to session */
+ slot = &cs->sp->sn_slots[sargs->sa_slotid];
+
+ mutex_enter(&slot->se_lock);
+ status = check_slot_seqid(slot, sargs->sa_sequenceid);
+ if (status == nfserr_replay_cache) {
+ if (slot->se_flags & RFS4_SLOT_CACHED) {
+ slot->se_flags |= RFS4_SLOT_INUSE;
+ cs->slot = slot;
+ *resp = slot->se_buf;
+ } else {
+ status = NFS4ERR_SEQ_MISORDERED;
+ }
+ } else if (status == NFS4_OK) {
+ slot->se_flags |= RFS4_SLOT_INUSE;
+ cs->slot = slot;
+ }
+ mutex_exit(&slot->se_lock);
+
+ return (status);
+}
+
+/*
+ * Do cleanup things
+ * 1. cache reply
+ * 2. release slot
+ */
+void
+rfs4x_sequence_done(COMPOUND4res *resp, compound_state_t *cs)
+{
+ rfs4_slot_t *slot = cs->slot;
+ rfs4_session_t *sp = cs->sp;
+ int add = 0;
+
+ ASSERT(slot != NULL);
+ ASSERT(sp != NULL);
+
+ mutex_enter(&slot->se_lock);
+ slot->se_flags &= ~RFS4_SLOT_INUSE;
+
+ if (*cs->statusp != nfserr_replay_cache) {
+ if (slot->se_flags & RFS4_SLOT_CACHED) {
+ rfs4_compound_free(&slot->se_buf);
+ slot->se_flags &= ~RFS4_SLOT_CACHED;
+ add = -1;
+ }
+
+ if (*cs->statusp == NFS4_OK && cs->cachethis) {
+ slot->se_flags |= RFS4_SLOT_CACHED;
+ slot->se_buf = *resp; /* cache a reply */
+ add += 1;
+ } else {
+ rfs4_compound_free(resp);
+ }
+ }
+ mutex_exit(&slot->se_lock);
+
+ if (add != 0)
+ atomic_add_32(&sp->sn_rcached, add);
+}
+
+/*
+ * Process the SEQUENCE operation. The session pointer has already been
+ * cached in the compound state, so we just dereference
+ */
+/*ARGSUSED*/
+void
+rfs4x_op_sequence(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs)
+{
+ SEQUENCE4args *args = &argop->nfs_argop4_u.opsequence;
+ SEQUENCE4res *resp = &resop->nfs_resop4_u.opsequence;
+ SEQUENCE4resok *rok = &resp->SEQUENCE4res_u.sr_resok4;
+ rfs4_session_t *sp = cs->sp;
+ rfs4_slot_t *slot = cs->slot;
+ nfsstat4 status = NFS4_OK;
+ uint32_t cbstat = 0x0;
+
+ DTRACE_NFSV4_2(op__sequence__start,
+ struct compound_state *, cs,
+ SEQUENCE4args *, args);
+
+ ASSERT(sp != NULL && slot != NULL);
+
+ if (cs->op_pos != 0) {
+ status = NFS4ERR_SEQUENCE_POS;
+ goto out;
+ }
+
+ if (rfs4_lease_expired(sp->sn_clnt)) {
+ status = NFS4ERR_BADSESSION;
+ goto out;
+ }
+
+ /*
+ * If the back channel has been established...
+ * . if the channel has _not_ been marked as failed _AND_
+ * there are connections that have pings outstanding,
+ * we go ahead and fire the thread to traverse all of
+ * the session's conns, issuing CB_NULL's to those that
+ * need a ping.
+ * . if the channel is _not_ OK (ie. failed), then notify
+ * client that there is currently a problem with the CB
+ * path.
+ */
+ rfs4_dbe_lock(sp->sn_dbe);
+ if (SN_CB_CHAN_EST(sp)) {
+ if (SN_CB_CHAN_OK(sp)) {
+ if (sp->sn_bc.pngcnt > 0 && !sp->sn_bc.pnginprog) {
+ kthread_t *t;
+
+ rfs4x_session_hold(sp);
+ t = thread_create(NULL, 0, ping_cb_null_thr,
+ sp, 0, &p0, TS_RUN, minclsyspri);
+ if (!t)
+ rfs4x_session_rele(sp);
+ }
+ } else {
+ cbstat |= SEQ4_STATUS_CB_PATH_DOWN;
+ }
+ }
+ cs->client = sp->sn_clnt;
+
+ DTRACE_PROBE1(compound_clid, clientid4, cs->client->rc_clientid);
+
+ ASSERT(args->sa_sequenceid == slot->se_seqid + 1);
+
+ /*
+ * New request.
+ */
+ mutex_enter(&slot->se_lock);
+ slot->se_seqid = args->sa_sequenceid;
+ mutex_exit(&slot->se_lock);
+
+ /*
+ * Update access time and lease
+ */
+ cs->slotno = args->sa_slotid;
+ sp->sn_laccess = nfs_sys_uptime();
+ rfs4_update_lease(cs->client);
+
+ /*
+ * Let's keep it simple for now
+ */
+ bcopy(sp->sn_sessid, rok->sr_sessionid, sizeof (sessionid4));
+ rok->sr_sequenceid = slot->se_seqid;
+ rok->sr_slotid = args->sa_slotid;
+ rok->sr_highest_slotid =
+ sp->sn_fore->cn_attrs.ca_maxrequests - 1;
+ rok->sr_target_highest_slotid =
+ sp->sn_fore->cn_attrs.ca_maxrequests - 1;
+ rok->sr_status_flags |= cbstat;
+ rfs4_dbe_unlock(sp->sn_dbe);
+out:
+ *cs->statusp = resp->sr_status = status;
+ DTRACE_NFSV4_2(op__sequence__done,
+ struct compound_state *, cs,
+ SEQUENCE4res *, resp);
+}
+
+/* ARGSUSED */
+void
+rfs4x_op_reclaim_complete(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs)
+{
+ RECLAIM_COMPLETE4args *args = &argop->nfs_argop4_u.opreclaim_complete;
+ RECLAIM_COMPLETE4res *resp = &resop->nfs_resop4_u.opreclaim_complete;
+ rfs4_client_t *cp;
+ nfsstat4 status = NFS4_OK;
+
+ DTRACE_NFSV4_2(op__reclaim__complete__start,
+ struct compound_state *, cs,
+ RECLAIM_COMPLETE4args *, args);
+
+ cp = cs->client;
+ rfs4_dbe_lock(cp->rc_dbe);
+ if (args->rca_one_fs) {
+ /* do what? we don't track this */
+ goto out;
+ }
+
+ if (cp->rc_reclaim_completed) {
+ status = NFS4ERR_COMPLETE_ALREADY;
+ goto out;
+ }
+
+ if (cp->rc_can_reclaim) {
+ ASSERT(rfs4_servinst(cp)->nreclaim > 0);
+ atomic_add_32(&(rfs4_servinst(cp))->nreclaim, -1);
+ }
+
+ cp->rc_reclaim_completed = 1;
+out:
+ rfs4_dbe_unlock(cp->rc_dbe);
+
+ *cs->statusp = resp->rcr_status = status;
+ DTRACE_NFSV4_2(op__reclaim__complete__done,
+ struct compound_state *, cs,
+ RECLAIM_COMPLETE4res *, resp);
+}
+
+/* ARGSUSED */
+void
+rfs4x_op_destroy_clientid(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs)
+{
+ DESTROY_CLIENTID4args *args = &argop->nfs_argop4_u.opdestroy_clientid;
+ DESTROY_CLIENTID4res *resp = &resop->nfs_resop4_u.opdestroy_clientid;
+ rfs4_client_t *cp;
+ nfsstat4 status = NFS4_OK;
+
+ DTRACE_NFSV4_2(op__destroy__clientid__start,
+ struct compound_state *, cs,
+ DESTROY_CLIENTID4args *, args);
+
+ cp = rfs4_findclient_by_id(args->dca_clientid, TRUE);
+ if (cp == NULL) {
+ status = NFS4ERR_STALE_CLIENTID;
+ goto end;
+ }
+
+ rfs4_dbe_lock(cp->rc_dbe);
+ if (client_has_state_locked(cp))
+ status = NFS4ERR_CLIENTID_BUSY;
+ else
+ cp->rc_destroying = TRUE;
+ rfs4_dbe_unlock(cp->rc_dbe);
+
+ if (status == NFS4_OK)
+ rfs4_client_close(cp);
+ else
+ rfs4_client_rele(cp);
+end:
+ *cs->statusp = resp->dcr_status = status;
+
+ DTRACE_NFSV4_2(op__destroy__clientid__done,
+ struct compound_state *, cs,
+ DESTROY_CLIENTID4res *, resp);
+}
+
+/*ARGSUSED*/
+void
+rfs4x_op_bind_conn_to_session(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs)
+{
+ BIND_CONN_TO_SESSION4args *args =
+ &argop->nfs_argop4_u.opbind_conn_to_session;
+ BIND_CONN_TO_SESSION4res *resp =
+ &resop->nfs_resop4_u.opbind_conn_to_session;
+ BIND_CONN_TO_SESSION4resok *rok =
+ &resp->BIND_CONN_TO_SESSION4res_u.bctsr_resok4;
+ rfs4_session_t *sp;
+ nfsstat4 status = NFS4_OK;
+
+ DTRACE_NFSV4_2(op__bind__conn__to__session__start,
+ struct compound_state *, cs,
+ BIND_CONN_TO_SESSION4args *, args);
+
+ if (cs->op_pos != 0) {
+ status = NFS4ERR_NOT_ONLY_OP;
+ goto end;
+ }
+
+ sp = rfs4x_findsession_by_id(args->bctsa_sessid);
+ if (sp == NULL) {
+ status = NFS4ERR_BADSESSION;
+ goto end;
+ }
+
+ rfs4_update_lease(sp->sn_clnt); /* no need lock protection */
+
+ rfs4_dbe_lock(sp->sn_dbe);
+ sp->sn_laccess = nfs_sys_uptime();
+ rfs4_dbe_unlock(sp->sn_dbe);
+
+ rok->bctsr_use_conn_in_rdma_mode = FALSE;
+
+ switch (args->bctsa_dir) {
+ case CDFC4_FORE:
+ case CDFC4_FORE_OR_BOTH:
+ /* always map to Fore */
+ rok->bctsr_dir = CDFS4_FORE;
+ break;
+
+ case CDFC4_BACK:
+ case CDFC4_BACK_OR_BOTH:
+ /* TODO: always map to Back */
+ rok->bctsr_dir = CDFS4_FORE;
+ break;
+ default:
+ break;
+ }
+
+ bcopy(sp->sn_sessid, rok->bctsr_sessid, sizeof (sessionid4));
+ rfs4x_session_rele(sp);
+end:
+ *cs->statusp = resp->bctsr_status = status;
+
+ DTRACE_NFSV4_2(op__bind__conn__to__session__done,
+ struct compound_state *, cs,
+ BIND_CONN_TO_SESSION4res *, resp);
+}
+
+/* ARGSUSED */
+void
+rfs4x_op_secinfo_noname(nfs_argop4 *argop, nfs_resop4 *resop,
+ struct svc_req *req, compound_state_t *cs)
+{
+ SECINFO_NO_NAME4res *resp = &resop->nfs_resop4_u.opsecinfo_no_name;
+ nfsstat4 status;
+ bool_t dotdot;
+
+ DTRACE_NFSV4_1(op__secinfo__no__name__start,
+ struct compound_state *, cs);
+
+ if (cs->vp == NULL) {
+ status = NFS4ERR_NOFILEHANDLE;
+ goto out;
+ }
+
+ if (cs->vp->v_type != VDIR) {
+ status = NFS4ERR_NOTDIR;
+ goto out;
+ }
+
+ dotdot =
+ (argop->nfs_argop4_u.opsecinfo_no_name == SECINFO_STYLE4_PARENT);
+
+ status = do_rfs4_op_secinfo(cs, dotdot ? ".." : ".", resp);
+
+ /* Cleanup FH as described at 18.45.3 and 2.6.3.1.1.8 */
+ if (status == NFS4_OK) {
+ VN_RELE(cs->vp);
+ cs->vp = NULL;
+ }
+out:
+ *cs->statusp = resp->status = status;
+
+ DTRACE_NFSV4_2(op__secinfo__no__name__done,
+ struct compound_state *, cs,
+ SECINFO_NO_NAME4res *, resp);
+}
diff --git a/usr/src/uts/common/fs/nfs/nfs4x_state.c b/usr/src/uts/common/fs/nfs/nfs4x_state.c
new file mode 100644
index 0000000000..aba02734fc
--- /dev/null
+++ b/usr/src/uts/common/fs/nfs/nfs4x_state.c
@@ -0,0 +1,576 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2017 RackTop Systems.
+ */
+
+#include <sys/sdt.h>
+#include <sys/atomic.h>
+#include <nfs/nfs4.h>
+
+#ifdef DEBUG
+#define RFS4_TABSIZE 17
+#else
+#define RFS4_TABSIZE 2047
+#endif
+
+#define RFS4_MAXTABSZ 1024*1024
+
+slotid4 rfs4_max_slots = MAXSLOTS; /* fore channel */
+slotid4 rfs4_back_max_slots = MAXSLOTS_BACK; /* back channel */
+
+typedef union {
+ /* Both members have the same size */
+ struct {
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t start_time; /* NFS server start time */
+ uint32_t s_id; /* unique session index */
+ } impl_id;
+ sessionid4 id4;
+} rfs4_sid;
+
+/*
+ * --------------------------------------------------------
+ * MDS - NFSv4.1 Sessions
+ * --------------------------------------------------------
+ */
+static uint32_t
+sessid_hash(void *key)
+{
+ rfs4_sid *idp = key;
+
+ return (idp->impl_id.s_id);
+}
+
+static bool_t
+sessid_compare(rfs4_entry_t entry, void *key)
+{
+ rfs4_session_t *sp = (rfs4_session_t *)entry;
+ sessionid4 *idp = (sessionid4 *)key;
+
+ return (bcmp(idp, &sp->sn_sessid, sizeof (sessionid4)) == 0);
+}
+
+static void *
+sessid_mkkey(rfs4_entry_t entry)
+{
+ rfs4_session_t *sp = (rfs4_session_t *)entry;
+
+ return (&sp->sn_sessid);
+}
+
+/* ARGSUSED */
+static bool_t
+cmp_false(rfs4_entry_t entry, void *key)
+{
+ return (FALSE);
+}
+
+/* ARGSUSED */
+static void *
+mkkey_null(rfs4_entry_t entry)
+{
+ return (NULL);
+}
+
+void
+rfs4x_session_rele(rfs4_session_t *sp)
+{
+ rfs4_dbe_rele(sp->sn_dbe);
+}
+
+void
+rfs4x_session_hold(rfs4_session_t *sp)
+{
+ rfs4_dbe_hold(sp->sn_dbe);
+}
+
+rfs4_session_t *
+rfs4x_findsession_by_id(sessionid4 sessid)
+{
+ rfs4_session_t *sp;
+ bool_t create = FALSE;
+ nfs4_srv_t *nsrv4 = nfs4_get_srv();
+
+ rw_enter(&nsrv4->findsession_lock, RW_READER);
+ sp = (rfs4_session_t *)rfs4_dbsearch(nsrv4->rfs4_session_idx,
+ sessid, &create, NULL, RFS4_DBS_VALID);
+ rw_exit(&nsrv4->findsession_lock);
+
+ return (sp);
+}
+
+/*
+ * A clientid can have multiple sessions associated with it. Hence,
+ * performing a raw 'mds_findsession' (even for a create) might
+ * yield a list of sessions associated with the clientid in question.
+ * Call rfs4_dbseach() function with key that cannot be found
+ * and create an association between the session table and both
+ * primary (sessionid) index and secondary (clientid) index for the
+ * newly created session.
+ */
+
+rfs4_session_t *
+rfs4x_createsession(session41_create_t *ap)
+{
+ static volatile uint32_t session_id_counter;
+
+ rfs4_session_t *sp = NULL;
+ bool_t create = TRUE;
+ rfs4_sid key = {0, 0, 0, 0};
+ nfs4_srv_t *nsrv4 = nfs4_get_srv();
+
+ /*
+ * Use unique counter for s_id and s_id to ensure that
+ * created entry will have the same index in dbi_buckets[]
+ */
+ ap->cs_id = key.impl_id.s_id = atomic_inc_32_nv(&session_id_counter);
+
+ rw_enter(&nsrv4->findsession_lock, RW_WRITER);
+ if ((sp = (rfs4_session_t *)rfs4_dbsearch(nsrv4->rfs4_session_idx,
+ &key, &create, (void *)ap, RFS4_DBS_VALID)) == NULL) {
+ DTRACE_PROBE1(mds__srv__createsession__fail,
+ session41_create_t *, ap);
+ }
+ rw_exit(&nsrv4->findsession_lock);
+ return (sp);
+}
+
+/* return success of operation */
+static bool_t
+client_insert_session(rfs4_client_t *cp, rfs4_session_t *sp)
+{
+ bool_t res = TRUE;
+
+ rfs4_dbe_lock(cp->rc_dbe);
+ if (cp->rc_destroying)
+ res = FALSE;
+ else
+ list_insert_tail(&cp->rc_sessions, sp);
+ rfs4_dbe_unlock(cp->rc_dbe);
+
+ return (res);
+}
+
+static void
+client_remove_session(rfs4_client_t *cp, rfs4_session_t *sp)
+{
+ rfs4_dbe_lock(cp->rc_dbe);
+ if (list_link_active(&sp->sn_node))
+ list_remove(&cp->rc_sessions, sp);
+ rfs4_dbe_unlock(cp->rc_dbe);
+}
+
+/*
+ * Invalidate the session in the DB (so it can't be found anymore)
+ */
+nfsstat4
+rfs4x_destroysession(rfs4_session_t *sp, unsigned useref)
+{
+ nfsstat4 status = NFS4_OK;
+
+ /*
+ * RFC 7862 Section 14.1.3:
+ * In hindsight, the NFSv4.1 specification should have
+ * mandated that DESTROY_SESSION either abort or complete
+ * all outstanding operations.
+ */
+ rfs4_dbe_lock(sp->sn_dbe);
+ if (rfs4_dbe_refcnt(sp->sn_dbe) > useref)
+ status = NFS4ERR_DELAY;
+ else
+ rfs4_dbe_invalidate(sp->sn_dbe);
+ rfs4_dbe_unlock(sp->sn_dbe);
+
+ if (status == NFS4_OK)
+ client_remove_session(sp->sn_clnt, sp);
+
+ return (status);
+}
+
+/* Invalidate all client's sessions */
+void
+rfs4x_client_session_remove(rfs4_client_t *cp)
+{
+ rfs4_session_t *sp;
+
+ /*
+ * Client is forcibly closing so invalidate all sessions
+ * without checking the refcount.
+ */
+ rfs4_dbe_lock(cp->rc_dbe);
+ while ((sp = list_head(&cp->rc_sessions)) != NULL) {
+ list_remove(&cp->rc_sessions, sp);
+
+ rfs4_dbe_lock(sp->sn_dbe);
+ rfs4_dbe_invalidate(sp->sn_dbe);
+ rfs4_dbe_unlock(sp->sn_dbe);
+
+ }
+ rfs4_dbe_unlock(cp->rc_dbe);
+}
+
+nfsstat4
+sess_chan_limits(sess_channel_t *scp)
+{
+ if (scp->cn_attrs.ca_maxrequests > rfs4_max_slots) {
+ scp->cn_attrs.ca_maxrequests = rfs4_max_slots;
+ }
+
+ if (scp->cn_back_attrs.ca_maxrequests > rfs4_back_max_slots)
+ scp->cn_back_attrs.ca_maxrequests = rfs4_back_max_slots;
+
+
+ if (scp->cn_attrs.ca_maxoperations > NFS4_COMPOUND_LIMIT)
+ scp->cn_attrs.ca_maxoperations = NFS4_COMPOUND_LIMIT;
+
+ /*
+ * Lower limit should be set to smallest sane COMPOUND. Even
+ * though a singleton SEQUENCE op is the very smallest COMPOUND,
+ * it's also quite boring. For all practical purposes, the lower
+ * limit for creating a sess is limited to:
+ *
+ * [SEQUENCE + PUTROOTFH + GETFH]
+ *
+ * XXX - can't limit READ's to a specific threshold, otherwise
+ * we artificially limit the clients to perform reads of
+ * AT LEAST that granularity, which is WRONG !!! Same goes
+ * for READDIR's and GETATTR's.
+ */
+ if (scp->cn_attrs.ca_maxresponsesize < (sizeof (SEQUENCE4res) +
+ sizeof (PUTROOTFH4res) + sizeof (GETFH4res)))
+ return (NFS4ERR_TOOSMALL);
+ return (NFS4_OK);
+}
+
+/*
+ * NFSv4.1 Slot replay cache
+ */
+static void
+rfs41_cleanup_slot(rfs4_slot_t *se)
+{
+ rfs4_compound_free((COMPOUND4res *)&se->se_buf);
+}
+
+static rfs4_slot_t *
+slots_alloc(size_t n)
+{
+ rfs4_slot_t *p;
+ int i;
+
+ p = kmem_zalloc(sizeof (rfs4_slot_t) * n, KM_SLEEP);
+ for (i = 0; i < n; i++) {
+ mutex_init(&p[i].se_lock, NULL, MUTEX_DEFAULT, NULL);
+ }
+
+ return (p);
+}
+
+static void
+slots_free(rfs4_slot_t *slots, size_t n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ rfs4_slot_t *slot = &slots[i];
+
+ mutex_destroy(&slot->se_lock);
+
+ if (slot->se_flags & RFS4_SLOT_CACHED) {
+ rfs41_cleanup_slot(slot);
+ }
+ }
+ kmem_free(slots, sizeof (rfs4_slot_t) * n);
+}
+
+/* Additional functions */
+
+/* check csa_flags for OP_CREATE_SESSION */
+bool_t
+nfs4x_csa_flags_valid(uint32_t flags)
+{
+ if (flags & ~CREATE_SESSION4_FLAG_MASK)
+ return (FALSE);
+
+ return (TRUE);
+}
+
+sess_channel_t *
+rfs41_create_session_channel(channel_dir_from_server4 dir)
+{
+ sess_channel_t *cp;
+ sess_bcsd_t *bp;
+
+ cp = (sess_channel_t *)kmem_zalloc(sizeof (sess_channel_t), KM_SLEEP);
+ rw_init(&cp->cn_lock, NULL, RW_DEFAULT, NULL);
+
+ switch (dir) {
+ case CDFS4_FORE:
+ break;
+
+ case CDFS4_BOTH:
+ case CDFS4_BACK:
+ /* BackChan Specific Data */
+ bp = (sess_bcsd_t *)kmem_zalloc(sizeof (sess_bcsd_t), KM_SLEEP);
+ rw_init(&bp->bsd_rwlock, NULL, RW_DEFAULT, NULL);
+ cp->cn_csd = (sess_bcsd_t *)bp;
+ break;
+ }
+ return (cp);
+}
+
+void
+rfs41_destroy_session_channel(rfs4_session_t *sp)
+{
+ sess_channel_t *cp;
+ sess_bcsd_t *bp;
+
+ if (sp->sn_back != NULL) {
+ /* only one channel for both direction for now */
+ ASSERT(sp->sn_fore == sp->sn_back);
+
+ cp = sp->sn_back;
+ bp = (sess_bcsd_t *)cp->cn_csd;
+ rw_destroy(&bp->bsd_rwlock);
+ kmem_free(bp, sizeof (sess_bcsd_t));
+ } else {
+ cp = sp->sn_fore;
+ }
+
+ rw_destroy(&cp->cn_lock);
+ kmem_free(cp, sizeof (sess_channel_t));
+
+ sp->sn_back = NULL;
+ sp->sn_fore = NULL;
+}
+
+static bool_t
+rfs4_session_create(rfs4_entry_t u_entry, void *arg)
+{
+ rfs4_session_t *sp = (rfs4_session_t *)u_entry;
+ session41_create_t *ap = (session41_create_t *)arg;
+ sess_channel_t *ocp = NULL;
+ rfs4_sid *sidp;
+ bool_t bdrpc = FALSE;
+ channel_dir_from_server4 dir;
+ nfsstat4 sle;
+ nfs4_srv_t *nsrv4 = nfs4_get_srv();
+
+ ASSERT(sp != NULL);
+ if (sp == NULL)
+ return (FALSE);
+
+ /*
+ * Back pointer/ref to parent data struct (rfs4_client_t)
+ */
+ sp->sn_clnt = (rfs4_client_t *)ap->cs_client;
+ rfs4_dbe_hold(sp->sn_clnt->rc_dbe);
+
+ /*
+ * Handcrafting the session id
+ */
+ sidp = (rfs4_sid *)&sp->sn_sessid;
+ sidp->impl_id.pad0 = 0x00000000;
+ sidp->impl_id.pad1 = 0xFFFFFFFF;
+ sidp->impl_id.start_time = nsrv4->rfs4_start_time;
+ sidp->impl_id.s_id = ap->cs_id;
+
+ /*
+ * Process csa_flags; note that CREATE_SESSION4_FLAG_CONN_BACK_CHAN
+ * is processed below since it affects direction and setup of the
+ * backchannel accordingly.
+ */
+ if (!nfs4x_csa_flags_valid(ap->cs_aotw.csa_flags)) {
+ ap->cs_error = NFS4ERR_INVAL;
+ goto err;
+ }
+
+ sp->sn_csflags = 0;
+ if (ap->cs_aotw.csa_flags & CREATE_SESSION4_FLAG_PERSIST)
+ /* XXX - Worry about persistence later */
+ sp->sn_csflags &= ~CREATE_SESSION4_FLAG_PERSIST;
+
+ if (ap->cs_aotw.csa_flags & CREATE_SESSION4_FLAG_CONN_RDMA)
+ /* XXX - No RDMA for now */
+ sp->sn_csflags &= ~CREATE_SESSION4_FLAG_CONN_RDMA;
+
+ /*
+ * Initialize some overall sessions values
+ */
+ sp->sn_bc.progno = ap->cs_aotw.csa_cb_program;
+ sp->sn_laccess = nfs_sys_uptime();
+ sp->sn_flags = 0;
+ sp->sn_rcached = 0;
+
+ /*
+ * Check if client has specified that the FORE channel should
+ * also be used for call back traffic (ie. bidir RPC). If so,
+ * let's try to accomodate the request.
+ */
+ DTRACE_PROBE1(csa__flags, uint32_t, ap->cs_aotw.csa_flags);
+
+ /*
+ * Session's channel flags depending on bdrpc
+ * TODO: Add backchannel handling, i.e. when bdrpc is TRUE
+ */
+ dir = bdrpc ? (CDFS4_FORE | CDFS4_BACK) : CDFS4_FORE;
+ ocp = rfs41_create_session_channel(dir);
+ ocp->cn_dir = dir;
+ sp->sn_fore = ocp;
+
+ /*
+ * Check if channel attrs will be flexible enough for future
+ * purposes. Channel attribute enforcement is done as part of
+ * COMPOUND processing.
+ */
+ ocp->cn_attrs = ap->cs_aotw.csa_fore_chan_attrs;
+ ocp->cn_back_attrs = ap->cs_aotw.csa_back_chan_attrs;
+ if (sle = sess_chan_limits(ocp)) {
+ ap->cs_error = sle;
+ goto err_free_chan;
+ }
+
+ /* will fail if client is going to destroy */
+ if (!client_insert_session(sp->sn_clnt, sp)) {
+ ap->cs_error = NFS4ERR_DELAY;
+ goto err_free_chan;
+ }
+
+ /*
+ * No need for locks/synchronization at this time,
+ * since we're barely creating the session.
+ */
+ if (bdrpc) {
+ /* Need to be implemented */
+ VERIFY(0);
+ } else {
+ /*
+ * If not doing bdrpc, then we expect the client to perform
+ * an explicit BIND_CONN_TO_SESSION if it wants callback
+ * traffic. Subsequently, the cb channel should be set up
+ * at that point along with its corresponding slot (see
+ * rfs41_bc_setup).
+ */
+ sp->sn_csflags &= ~CREATE_SESSION4_FLAG_CONN_BACK_CHAN;
+ sp->sn_back = NULL;
+
+ /*
+ * XXX 08/15/2008 (rick) - if the channel is not bidir when
+ * created in CREATE_SESSION, then we should save off
+ * the ap->cs_aotw.csa_back_chan_attrs in case later
+ * a bc2s is called to create the back channel.
+ */
+ }
+
+ /*
+ * Now we allocate space for the slrc, initializing each slot's
+ * sequenceid and slotid to zero and a (pre)cached result of
+ * NFS4ERR_SEQ_MISORDERED. Note that we zero out the entries
+ * by virtue of the z-alloc.
+ */
+ sp->sn_slots = slots_alloc(ocp->cn_attrs.ca_maxrequests);
+
+ return (TRUE);
+
+err_free_chan:
+ rfs41_destroy_session_channel(sp);
+err:
+ rfs4_dbe_rele(sp->sn_clnt->rc_dbe);
+ return (FALSE);
+}
+
+static void
+rfs4_session_destroy(rfs4_entry_t u_entry)
+{
+ rfs4_session_t *sp = (rfs4_session_t *)u_entry;
+ sess_bcsd_t *bsdp;
+
+ if (SN_CB_CHAN_EST(sp) && (bsdp = sp->sn_back->cn_csd) != NULL) {
+ slots_free(bsdp->bsd_slots,
+ sp->sn_back->cn_back_attrs.ca_maxrequests);
+ bsdp->bsd_slots = NULL;
+ }
+
+ /*
+ * Nuke slot replay cache for this session
+ */
+ if (sp->sn_slots) {
+ slots_free(sp->sn_slots, sp->sn_fore->cn_attrs.ca_maxrequests);
+ sp->sn_slots = NULL;
+ }
+
+ /*
+ * XXX - A session can have multiple BC clnt handles that need
+ * to be discarded. rfs4_session_inval calls CLNT_DESTROY
+ * which will remove the CB client handle from the global
+ * list (cb_clnt_list) now. This will have to change once
+ * we manage the BC clnt handles per session.
+ */
+
+ /*
+ * Remove the fore and back channels.
+ */
+ rfs41_destroy_session_channel(sp);
+
+ client_remove_session(sp->sn_clnt, sp);
+
+ rfs4_client_rele(sp->sn_clnt);
+}
+
+static bool_t
+rfs4_session_expiry(rfs4_entry_t u_entry)
+{
+ rfs4_session_t *sp = (rfs4_session_t *)u_entry;
+
+ if (sp == NULL || rfs4_dbe_is_invalid(sp->sn_dbe))
+ return (TRUE);
+
+ if (rfs4_lease_expired(sp->sn_clnt))
+ return (TRUE);
+
+ return (FALSE);
+}
+
+void
+rfs4x_state_init_locked(nfs4_srv_t *nsrv4)
+{
+ rw_init(&nsrv4->findsession_lock, NULL, RW_DEFAULT, NULL);
+
+ nsrv4->rfs4_session_tab = rfs4_table_create(nsrv4->nfs4_server_state,
+ "Session", 5 * rfs4_lease_time, 1, rfs4_session_create,
+ rfs4_session_destroy, rfs4_session_expiry, sizeof (rfs4_session_t),
+ RFS4_TABSIZE, RFS4_MAXTABSZ/8, 100);
+
+ nsrv4->rfs4_session_idx = rfs4_index_create(nsrv4->rfs4_session_tab,
+ "session_idx", sessid_hash, sessid_compare, sessid_mkkey, TRUE);
+}
+
+void
+rfs4x_state_fini(nfs4_srv_t *nsrv4)
+{
+ /* All tables will be destroyed by caller */
+ rw_destroy(&nsrv4->findsession_lock);
+}
diff --git a/usr/src/uts/common/fs/nfs/nfs4x_xdr.c b/usr/src/uts/common/fs/nfs/nfs4x_xdr.c
new file mode 100644
index 0000000000..7b4bce31f8
--- /dev/null
+++ b/usr/src/uts/common/fs/nfs/nfs4x_xdr.c
@@ -0,0 +1,2935 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ * Copyright 2017 RackTop Systems.
+ */
+
+/*
+ * This file contains the xdr for datatypes and operations that are
+ * specific to NFSv4 minor version 1 (i.e., datatypes that
+ * were either introduced or changed by the NFSv4.1 specification).
+ */
+
+/*
+ * INSTRUCTIONS for updating to a new NFSv4.1:
+ *
+ * **DO NOT** simply replace this file with code rpcgen creates
+ * and then remove non-NFS41 code. The file now contains the hand
+ * coded xdr for the NFS4.1 attributes. If you run rpcgen,
+ * manually integrate parts related to the draft diffs.
+ */
+#include <sys/statvfs.h>
+#include <sys/sysmacros.h>
+#include <sys/sdt.h>
+#include <nfs/nfs4.h>
+#include <nfs/nfs4_attr.h>
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif /* !_KERNEL */
+
+/* modified version */
+bool_t
+xdr_verifier4(XDR *xdrs, verifier4 *objp)
+{
+ if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_sequenceid4(XDR *xdrs, sequenceid4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_sessionid4(XDR *xdrs, sessionid4 objp)
+{
+ if (!xdr_opaque(xdrs, objp, NFS4_SESSIONID_SIZE))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_slotid4(XDR *xdrs, slotid4 *objp)
+{
+
+ if (!xdr_uint32_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_change_policy4(XDR *xdrs, change_policy4 *objp)
+{
+ if (!xdr_uint64_t(xdrs, &objp->cp_major))
+ return (FALSE);
+ if (!xdr_uint64_t(xdrs, &objp->cp_minor))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_aclflag4(XDR *xdrs, aclflag4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_nfsacl41(XDR *xdrs, nfsacl41 *objp)
+{
+ if (!xdr_aclflag4(xdrs, &objp->na41_flag))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->na41_aces.na41_aces_val,
+ (uint_t *)&objp->na41_aces.na41_aces_len, ~0, sizeof (nfsace4),
+ (xdrproc_t)xdr_nfsace4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_mode_masked4(XDR *xdrs, mode_masked4 *objp)
+{
+ if (!xdr_mode4(xdrs, &objp->mm_value_to_set))
+ return (FALSE);
+ if (!xdr_mode4(xdrs, &objp->mm_mask_bits))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_nfs_impl_id4(XDR *xdrs, nfs_impl_id4 *objp)
+{
+ if (!xdr_utf8str_cis(xdrs, &objp->nii_domain))
+ return (FALSE);
+ if (!xdr_utf8str_cs(xdrs, &objp->nii_name))
+ return (FALSE);
+ if (!xdr_nfstime4(xdrs, &objp->nii_date))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layouttype4(XDR *xdrs, layouttype4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layout_content4(XDR *xdrs, layout_content4 *objp)
+{
+ if (!xdr_layouttype4(xdrs, &objp->loc_type))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->loc_body.loc_body_val,
+ (uint_t *)&objp->loc_body.loc_body_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layoutiomode4(XDR *xdrs, layoutiomode4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+bool_t
+xdr_layout4(XDR *xdrs, layout4 *objp)
+{
+ if (!xdr_offset4(xdrs, &objp->lo_offset))
+ return (FALSE);
+ if (!xdr_length4(xdrs, &objp->lo_length))
+ return (FALSE);
+ if (!xdr_layoutiomode4(xdrs, &objp->lo_iomode))
+ return (FALSE);
+ if (!xdr_layout_content4(xdrs, &objp->lo_content))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_deviceid4(XDR *xdrs, deviceid4 objp)
+{
+ if (!xdr_opaque(xdrs, objp, NFS4_DEVICEID4_SIZE))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_device_addr4(XDR *xdrs, device_addr4 *objp)
+{
+ if (!xdr_layouttype4(xdrs, &objp->da_layout_type))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->da_addr_body.da_addr_body_val,
+ (uint_t *)&objp->da_addr_body.da_addr_body_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layoutupdate4(XDR *xdrs, layoutupdate4 *objp)
+{
+ if (!xdr_layouttype4(xdrs, &objp->lou_type))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->lou_body.lou_body_val,
+ (uint_t *)&objp->lou_body.lou_body_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layoutreturn_type4(XDR *xdrs, layoutreturn_type4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+/* layouttype4 specific data */
+
+bool_t
+xdr_layoutreturn_file4(XDR *xdrs, layoutreturn_file4 *objp)
+{
+ if (!xdr_offset4(xdrs, &objp->lrf_offset))
+ return (FALSE);
+ if (!xdr_length4(xdrs, &objp->lrf_length))
+ return (FALSE);
+ if (!xdr_stateid4(xdrs, &objp->lrf_stateid))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->lrf_body.lrf_body_val,
+ (uint_t *)&objp->lrf_body.lrf_body_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layoutreturn4(XDR *xdrs, layoutreturn4 *objp)
+{
+ if (!xdr_layoutreturn_type4(xdrs, &objp->lr_returntype))
+ return (FALSE);
+ switch (objp->lr_returntype) {
+ case LAYOUTRETURN4_FILE:
+ if (!xdr_layoutreturn_file4(xdrs,
+ &objp->layoutreturn4_u.lr_layout))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+
+bool_t
+xdr_fs4_status_type(XDR *xdrs, fs4_status_type *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fs4_status(XDR *xdrs, fs4_status *objp)
+{
+ if (!xdr_bool(xdrs, &objp->fss_absent))
+ return (FALSE);
+ if (!xdr_fs4_status_type(xdrs, &objp->fss_type))
+ return (FALSE);
+ if (!xdr_utf8str_cs(xdrs, &objp->fss_source))
+ return (FALSE);
+ if (!xdr_utf8str_cs(xdrs, &objp->fss_current))
+ return (FALSE);
+ if (!xdr_int32_t(xdrs, &objp->fss_age))
+ return (FALSE);
+ if (!xdr_nfstime4(xdrs, &objp->fss_version))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_threshold4_read_size(XDR *xdrs, threshold4_read_size *objp)
+{
+
+ if (!xdr_length4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_threshold4_write_size(XDR *xdrs, threshold4_write_size *objp)
+{
+ if (!xdr_length4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_threshold4_read_iosize(XDR *xdrs, threshold4_read_iosize *objp)
+{
+ if (!xdr_length4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_threshold4_write_iosize(XDR *xdrs, threshold4_write_iosize *objp)
+{
+ if (!xdr_length4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_threshold_item4(XDR *xdrs, threshold_item4 *objp)
+{
+ if (!xdr_layouttype4(xdrs, &objp->thi_layout_type))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->thi_hintset))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->thi_hintlist.thi_hintlist_val,
+ (uint_t *)&objp->thi_hintlist.thi_hintlist_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_mdsthreshold4(XDR *xdrs, mdsthreshold4 *objp)
+{
+ if (!xdr_array(xdrs, (char **)&objp->mth_hints.mth_hints_val,
+ (uint_t *)&objp->mth_hints.mth_hints_len, ~0,
+ sizeof (threshold_item4), (xdrproc_t)xdr_threshold_item4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_retention_get4(XDR *xdrs, retention_get4 *objp)
+{
+ if (!xdr_uint64_t(xdrs, &objp->rg_duration))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->rg_begin_time.rg_begin_time_val,
+ (uint_t *)&objp->rg_begin_time.rg_begin_time_len, 1,
+ sizeof (nfstime4), (xdrproc_t)xdr_nfstime4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_retention_set4(XDR *xdrs, retention_set4 *objp)
+{
+ if (!xdr_bool(xdrs, &objp->rs_enable))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->rs_duration.rs_duration_val,
+ (uint_t *)&objp->rs_duration.rs_duration_len, 1, sizeof (uint64_t),
+ (xdrproc_t)xdr_uint64_t))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fs_charset_cap4(XDR *xdrs, fs_charset_cap4 *objp)
+{
+
+ if (!xdr_uint32_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_mode_set_masked(XDR *xdrs, fattr4_mode_set_masked *objp)
+{
+ if (!xdr_mode_masked4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_dir_notif_delay(XDR *xdrs, fattr4_dir_notif_delay *objp)
+{
+
+ if (!xdr_nfstime4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_dirent_notif_delay(XDR *xdrs, fattr4_dirent_notif_delay *objp)
+{
+ if (!xdr_nfstime4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_fs_layout_types(XDR *xdrs, fattr4_fs_layout_types *objp)
+{
+ if (!xdr_array(xdrs, (char **)&objp->fattr4_fs_layout_types_val,
+ (uint_t *)&objp->fattr4_fs_layout_types_len, ~0,
+ sizeof (layouttype4), (xdrproc_t)xdr_layouttype4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_fs_status(XDR *xdrs, fattr4_fs_status *objp)
+{
+ if (!xdr_fs4_status(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_fs_charset_cap4(XDR *xdrs, fattr4_fs_charset_cap *objp)
+{
+ if (!xdr_fs_charset_cap4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_retention_get(XDR *xdrs, fattr4_retention_get *objp)
+{
+ if (!xdr_retention_get4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_retention_set(XDR *xdrs, fattr4_retention_set *objp)
+{
+ if (!xdr_retention_set4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_retentevt_get(XDR *xdrs, fattr4_retentevt_get *objp)
+{
+ if (!xdr_retention_get4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_retentevt_set(XDR *xdrs, fattr4_retentevt_set *objp)
+{
+ if (!xdr_retention_set4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_retention_hold(XDR *xdrs, fattr4_retention_hold *objp)
+{
+ if (!xdr_uint64_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_dacl(XDR *xdrs, fattr4_dacl *objp)
+{
+ if (!xdr_nfsacl41(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_sacl(XDR *xdrs, fattr4_sacl *objp)
+{
+ if (!xdr_nfsacl41(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_client_owner4(XDR *xdrs, client_owner4 *objp)
+{
+ if (!xdr_verifier4(xdrs, (verifier4 *)&objp->co_verifier))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->co_ownerid.co_ownerid_val,
+ (uint_t *)&objp->co_ownerid.co_ownerid_len, NFS4_OPAQUE_LIMIT))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_server_owner4(XDR *xdrs, server_owner4 *objp)
+{
+ if (!xdr_uint64_t(xdrs, &objp->so_minor_id))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->so_major_id.so_major_id_val,
+ (uint_t *)&objp->so_major_id.so_major_id_len, NFS4_OPAQUE_LIMIT))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_state_owner4(XDR *xdrs, state_owner4 *objp)
+{
+ if (!xdr_clientid4(xdrs, &objp->clientid))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
+ (uint_t *)&objp->owner.owner_len, NFS4_OPAQUE_LIMIT))
+ return (FALSE);
+ return (TRUE);
+}
+
+/* Input for computing subkeys */
+
+bool_t
+xdr_ssv_subkey4(XDR *xdrs, ssv_subkey4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+/* Input for computing smt_hmac */
+
+bool_t
+xdr_ssv_mic_plain_tkn4(XDR *xdrs, ssv_mic_plain_tkn4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->smpt_ssv_seq))
+ return (FALSE);
+ if (!xdr_bytes(xdrs,
+ (char **)&objp->smpt_orig_plain.smpt_orig_plain_val,
+ (uint_t *)&objp->smpt_orig_plain.smpt_orig_plain_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+/* SSV GSS PerMsgToken token */
+
+bool_t
+xdr_ssv_mic_tkn4(XDR *xdrs, ssv_mic_tkn4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->smt_ssv_seq))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->smt_hmac.smt_hmac_val,
+ (uint_t *)&objp->smt_hmac.smt_hmac_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+/* Input for computing ssct_encr_data and ssct_hmac */
+
+bool_t
+xdr_ssv_seal_plain_tkn4(XDR *xdrs, ssv_seal_plain_tkn4 *objp)
+{
+ if (!xdr_bytes(xdrs,
+ (char **)&objp->sspt_confounder.sspt_confounder_val,
+ (uint_t *)&objp->sspt_confounder.sspt_confounder_len, ~0))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->sspt_ssv_seq))
+ return (FALSE);
+ if (!xdr_bytes(xdrs,
+ (char **)&objp->sspt_orig_plain.sspt_orig_plain_val,
+ (uint_t *)&objp->sspt_orig_plain.sspt_orig_plain_len, ~0))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->sspt_pad.sspt_pad_val,
+ (uint_t *)&objp->sspt_pad.sspt_pad_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+/* SSV GSS SealedMessage token */
+
+bool_t
+xdr_ssv_seal_cipher_tkn4(XDR *xdrs, ssv_seal_cipher_tkn4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->ssct_ssv_seq))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->ssct_iv.ssct_iv_val,
+ (uint_t *)&objp->ssct_iv.ssct_iv_len, ~0))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->ssct_encr_data.ssct_encr_data_val,
+ (uint_t *)&objp->ssct_encr_data.ssct_encr_data_len, ~0))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->ssct_hmac.ssct_hmac_val,
+ (uint_t *)&objp->ssct_hmac.ssct_hmac_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+bool_t
+xdr_fs_locations_server4(XDR *xdrs, fs_locations_server4 *objp)
+{
+ if (!xdr_int32_t(xdrs, &objp->fls_currency))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->fls_info.fls_info_val,
+ (uint_t *)&objp->fls_info.fls_info_len, ~0))
+ return (FALSE);
+ if (!xdr_utf8str_cis(xdrs, &objp->fls_server))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fs_locations_item4(XDR *xdrs, fs_locations_item4 *objp)
+{
+ if (!xdr_array(xdrs, (char **)&objp->fli_entries.fli_entries_val,
+ (uint_t *)&objp->fli_entries.fli_entries_len, ~0,
+ sizeof (fs_locations_server4), (xdrproc_t)xdr_fs_locations_server4))
+ return (FALSE);
+ if (!xdr_pathname4(xdrs, &objp->fli_rootpath))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fs_locations_info4(XDR *xdrs, fs_locations_info4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->fli_flags))
+ return (FALSE);
+ if (!xdr_int32_t(xdrs, &objp->fli_valid_for))
+ return (FALSE);
+ if (!xdr_pathname4(xdrs, &objp->fli_fs_root))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->fli_items.fli_items_val,
+ (uint_t *)&objp->fli_items.fli_items_len, ~0,
+ sizeof (fs_locations_item4), (xdrproc_t)xdr_fs_locations_item4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr4_fs_locations_info(XDR *xdrs, fattr4_fs_locations_info *objp)
+{
+ if (!xdr_fs_locations_info4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_nfl_util4(XDR *xdrs, nfl_util4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_filelayout_hint_care4(XDR *xdrs, filelayout_hint_care4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+bool_t
+xdr_multipath_list4(XDR *xdrs, multipath_list4 *objp)
+{
+ if (!xdr_array(xdrs, (char **)&objp->multipath_list4_val,
+ (uint_t *)&objp->multipath_list4_len, ~0,
+ sizeof (netaddr4), (xdrproc_t)xdr_netaddr4))
+ return (FALSE);
+ return (TRUE);
+}
+
+/* Encoded in the da_addr_body field of type device_addr4: */
+
+bool_t
+xdr_nfsv4_1_file_layout_ds_addr4(XDR *xdrs, nfsv4_1_file_layout_ds_addr4 *objp)
+{
+ if (!xdr_array(xdrs,
+ (char **)&objp->nflda_stripe_indices.nflda_stripe_indices_val,
+ (uint_t *)&objp->nflda_stripe_indices.nflda_stripe_indices_len, ~0,
+ sizeof (uint32_t), (xdrproc_t)xdr_uint32_t))
+ return (FALSE);
+ if (!xdr_array(xdrs,
+ (char **)&objp->nflda_multipath_ds_list.nflda_multipath_ds_list_val,
+ (uint_t *)&objp->nflda_multipath_ds_list.
+ nflda_multipath_ds_list_len, ~0, sizeof (multipath_list4),
+ (xdrproc_t)xdr_multipath_list4))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+/* Encoded in the loc_body field of type layout_content4: */
+
+bool_t
+xdr_nfsv4_1_file_layout4(XDR *xdrs, nfsv4_1_file_layout4 *objp)
+{
+ if (!xdr_deviceid4(xdrs, objp->nfl_deviceid))
+ return (FALSE);
+ if (!xdr_nfl_util4(xdrs, &objp->nfl_util))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->nfl_first_stripe_index))
+ return (FALSE);
+ if (!xdr_offset4(xdrs, &objp->nfl_pattern_offset))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->nfl_fh_list.nfl_fh_list_val,
+ (uint_t *)&objp->nfl_fh_list.nfl_fh_list_len, ~0,
+ sizeof (nfs_fh4), (xdrproc_t)xdr_nfs_fh4))
+ return (FALSE);
+ return (TRUE);
+}
+
+/*
+ * Encoded in the lou_body field of type layoutupdate4:
+ * Nothing. lou_body is a zero length array of octets.
+ */
+
+
+bool_t
+xdr_creatverfattr(XDR *xdrs, creatverfattr *objp)
+{
+ if (!xdr_verifier4(xdrs, (verifier4 *)&objp->cva_verf))
+ return (FALSE);
+ if (!xdr_fattr4(xdrs, &objp->cva_attrs))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_open_claim_delegate_cur4(XDR *xdrs, open_claim_delegate_cur4 *objp)
+{
+ if (!xdr_stateid4(xdrs, &objp->delegate_stateid))
+ return (FALSE);
+ if (!xdr_component4(xdrs, &objp->file))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_open_claim4(XDR *xdrs, open_claim4 *objp)
+{
+ if (!xdr_open_claim_type4(xdrs, &objp->claim))
+ return (FALSE);
+ switch (objp->claim) {
+ case CLAIM_NULL:
+ if (!xdr_component4(xdrs, &objp->open_claim4_u.file))
+ return (FALSE);
+ break;
+ case CLAIM_PREVIOUS:
+ if (!xdr_open_delegation_type4(xdrs,
+ &objp->open_claim4_u.delegate_type))
+ return (FALSE);
+ break;
+ case CLAIM_DELEGATE_CUR:
+ if (!xdr_open_claim_delegate_cur4(xdrs,
+ &objp->open_claim4_u.delegate_cur_info))
+ return (FALSE);
+ break;
+ case CLAIM_DELEGATE_PREV:
+ if (!xdr_component4(xdrs,
+ &objp->open_claim4_u.file_delegate_prev))
+ return (FALSE);
+ break;
+ case CLAIM_FH:
+ break;
+ case CLAIM_DELEG_PREV_FH:
+ break;
+ case CLAIM_DELEG_CUR_FH:
+ if (!xdr_stateid4(xdrs,
+ &objp->open_claim4_u.oc_delegate_stateid))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_why_no_delegation4(XDR *xdrs, why_no_delegation4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_open_none_delegation4(XDR *xdrs, open_none_delegation4 *objp)
+{
+ if (!xdr_why_no_delegation4(xdrs, &objp->ond_why))
+ return (FALSE);
+ switch (objp->ond_why) {
+ case WND4_CONTENTION:
+ if (!xdr_bool(xdrs,
+ &objp->open_none_delegation4_u.ond_server_will_push_deleg))
+ return (FALSE);
+ break;
+ case WND4_RESOURCE:
+ if (!xdr_bool(xdrs, &objp->open_none_delegation4_u.
+ ond_server_will_signal_avail))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_open_delegation4(XDR *xdrs, open_delegation4 *objp)
+{
+ if (!xdr_open_delegation_type4(xdrs, &objp->delegation_type))
+ return (FALSE);
+ switch (objp->delegation_type) {
+ case OPEN_DELEGATE_NONE:
+ break;
+ case OPEN_DELEGATE_READ:
+ if (!xdr_open_read_delegation4(xdrs,
+ &objp->open_delegation4_u.read))
+ return (FALSE);
+ break;
+ case OPEN_DELEGATE_WRITE:
+ if (!xdr_open_write_delegation4(xdrs,
+ &objp->open_delegation4_u.write))
+ return (FALSE);
+ break;
+ case OPEN_DELEGATE_NONE_EXT:
+ if (!xdr_open_none_delegation4(xdrs,
+ &objp->open_delegation4_u.od_whynone))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_gsshandle4_t(XDR *xdrs, gsshandle4_t *objp)
+{
+ if (!xdr_bytes(xdrs, (char **)&objp->gsshandle4_t_val,
+ (uint_t *)&objp->gsshandle4_t_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_gss_cb_handles4(XDR *xdrs, gss_cb_handles4 *objp)
+{
+ if (!xdr_rpc_gss_svc_t(xdrs, &objp->gcbp_service))
+ return (FALSE);
+ if (!xdr_gsshandle4_t(xdrs, &objp->gcbp_handle_from_server))
+ return (FALSE);
+ if (!xdr_gsshandle4_t(xdrs, &objp->gcbp_handle_from_client))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_callback_sec_parms4(XDR *xdrs, callback_sec_parms4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->cb_secflavor))
+ return (FALSE);
+ switch (objp->cb_secflavor) {
+ case AUTH_NONE:
+ break;
+ case AUTH_SYS:
+ if (!xdr_authsys_parms(xdrs,
+ &objp->callback_sec_parms4_u.cbsp_sys_cred))
+ return (FALSE);
+ break;
+ case RPCSEC_GSS:
+ if (!xdr_gss_cb_handles4(xdrs,
+ &objp->callback_sec_parms4_u.cbsp_gss_handles))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_BACKCHANNEL_CTL4args(XDR *xdrs, BACKCHANNEL_CTL4args *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->bca_cb_program))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->bca_sec_parms.bca_sec_parms_val,
+ (uint_t *)&objp->bca_sec_parms.bca_sec_parms_len, ~0,
+ sizeof (callback_sec_parms4), (xdrproc_t)xdr_callback_sec_parms4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_BACKCHANNEL_CTL4res(XDR *xdrs, BACKCHANNEL_CTL4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->bcr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_channel_dir_from_client4(XDR *xdrs, channel_dir_from_client4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_BIND_CONN_TO_SESSION4args(XDR *xdrs, BIND_CONN_TO_SESSION4args *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->bctsa_sessid))
+ return (FALSE);
+ if (!xdr_channel_dir_from_client4(xdrs, &objp->bctsa_dir))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->bctsa_use_conn_in_rdma_mode))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_channel_dir_from_server4(XDR *xdrs, channel_dir_from_server4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_BIND_CONN_TO_SESSION4resok(XDR *xdrs, BIND_CONN_TO_SESSION4resok *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->bctsr_sessid))
+ return (FALSE);
+ if (!xdr_channel_dir_from_server4(xdrs, &objp->bctsr_dir))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->bctsr_use_conn_in_rdma_mode))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_BIND_CONN_TO_SESSION4res(XDR *xdrs, BIND_CONN_TO_SESSION4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->bctsr_status))
+ return (FALSE);
+ switch (objp->bctsr_status) {
+ case NFS4_OK:
+ if (!xdr_BIND_CONN_TO_SESSION4resok(xdrs,
+ &objp->BIND_CONN_TO_SESSION4res_u.bctsr_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_state_protect_ops4(XDR *xdrs, state_protect_ops4 *objp)
+{
+ if (!xdr_bitmap4(xdrs, &objp->spo_must_enforce))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->spo_must_allow))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_ssv_sp_parms4(XDR *xdrs, ssv_sp_parms4 *objp)
+{
+ if (!xdr_state_protect_ops4(xdrs, &objp->ssp_ops))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->ssp_hash_algs.ssp_hash_algs_val,
+ (uint_t *)&objp->ssp_hash_algs.ssp_hash_algs_len, ~0,
+ sizeof (sec_oid4), (xdrproc_t)xdr_sec_oid4))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->ssp_encr_algs.ssp_encr_algs_val,
+ (uint_t *)&objp->ssp_encr_algs.ssp_encr_algs_len, ~0,
+ sizeof (sec_oid4), (xdrproc_t)xdr_sec_oid4))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->ssp_window))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->ssp_num_gss_handles))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_state_protect_how4(XDR *xdrs, state_protect_how4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_state_protect4_a(XDR *xdrs, state_protect4_a *objp)
+{
+ if (!xdr_state_protect_how4(xdrs, &objp->spa_how))
+ return (FALSE);
+ switch (objp->spa_how) {
+ case SP4_NONE:
+ break;
+ case SP4_MACH_CRED:
+ if (!xdr_state_protect_ops4(xdrs,
+ &objp->state_protect4_a_u.spa_mach_ops))
+ return (FALSE);
+ break;
+ case SP4_SSV:
+ if (!xdr_ssv_sp_parms4(xdrs,
+ &objp->state_protect4_a_u.spa_ssv_parms))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_EXCHANGE_ID4args(XDR *xdrs, EXCHANGE_ID4args *objp)
+{
+ if (!xdr_client_owner4(xdrs, &objp->eia_clientowner))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->eia_flags))
+ return (FALSE);
+ if (!xdr_state_protect4_a(xdrs, &objp->eia_state_protect))
+ return (FALSE);
+ if (!xdr_array(xdrs,
+ (char **)&objp->eia_client_impl_id.eia_client_impl_id_val,
+ (uint_t *)&objp->eia_client_impl_id.eia_client_impl_id_len, 1,
+ sizeof (nfs_impl_id4), (xdrproc_t)xdr_nfs_impl_id4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_ssv_prot_info4(XDR *xdrs, ssv_prot_info4 *objp)
+{
+ if (!xdr_state_protect_ops4(xdrs, &objp->spi_ops))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->spi_hash_alg))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->spi_encr_alg))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->spi_ssv_len))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->spi_window))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->spi_handles.spi_handles_val,
+ (uint_t *)&objp->spi_handles.spi_handles_len, ~0,
+ sizeof (gsshandle4_t), (xdrproc_t)xdr_gsshandle4_t))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_state_protect4_r(XDR *xdrs, state_protect4_r *objp)
+{
+ if (!xdr_state_protect_how4(xdrs, &objp->spr_how))
+ return (FALSE);
+ switch (objp->spr_how) {
+ case SP4_NONE:
+ break;
+ case SP4_MACH_CRED:
+ if (!xdr_state_protect_ops4(xdrs,
+ &objp->state_protect4_r_u.spr_mach_ops))
+ return (FALSE);
+ break;
+ case SP4_SSV:
+ if (!xdr_ssv_prot_info4(xdrs,
+ &objp->state_protect4_r_u.spr_ssv_info))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_EXCHANGE_ID4resok(XDR *xdrs, EXCHANGE_ID4resok *objp)
+{
+ if (!xdr_clientid4(xdrs, &objp->eir_clientid))
+ return (FALSE);
+ if (!xdr_sequenceid4(xdrs, &objp->eir_sequenceid))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->eir_flags))
+ return (FALSE);
+ if (!xdr_state_protect4_r(xdrs, &objp->eir_state_protect))
+ return (FALSE);
+ if (!xdr_server_owner4(xdrs, &objp->eir_server_owner))
+ return (FALSE);
+ if (!xdr_bytes(xdrs,
+ (char **)&objp->eir_server_scope.eir_server_scope_val,
+ (uint_t *)&objp->eir_server_scope.eir_server_scope_len,
+ NFS4_OPAQUE_LIMIT))
+ return (FALSE);
+ if (!xdr_array(xdrs,
+ (char **)&objp->eir_server_impl_id.eir_server_impl_id_val,
+ (uint_t *)&objp->eir_server_impl_id.eir_server_impl_id_len, 1,
+ sizeof (nfs_impl_id4), (xdrproc_t)xdr_nfs_impl_id4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_EXCHANGE_ID4res(XDR *xdrs, EXCHANGE_ID4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->eir_status))
+ return (FALSE);
+ switch (objp->eir_status) {
+ case NFS4_OK:
+ if (!xdr_EXCHANGE_ID4resok(xdrs,
+ &objp->EXCHANGE_ID4res_u.eir_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_channel_attrs4(XDR *xdrs, channel_attrs4 *objp)
+{
+ if (!xdr_count4(xdrs, &objp->ca_headerpadsize))
+ return (FALSE);
+ if (!xdr_count4(xdrs, &objp->ca_maxrequestsize))
+ return (FALSE);
+ if (!xdr_count4(xdrs, &objp->ca_maxresponsesize))
+ return (FALSE);
+ if (!xdr_count4(xdrs, &objp->ca_maxresponsesize_cached))
+ return (FALSE);
+ if (!xdr_count4(xdrs, &objp->ca_maxoperations))
+ return (FALSE);
+ if (!xdr_count4(xdrs, &objp->ca_maxrequests))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->ca_rdma_ird.ca_rdma_ird_val,
+ (uint_t *)&objp->ca_rdma_ird.ca_rdma_ird_len, 1,
+ sizeof (uint32_t), (xdrproc_t)xdr_uint32_t))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CREATE_SESSION4args(XDR *xdrs, CREATE_SESSION4args *objp)
+{
+
+ if (!xdr_clientid4(xdrs, &objp->csa_clientid))
+ return (FALSE);
+ if (!xdr_sequenceid4(xdrs, &objp->csa_sequence))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->csa_flags))
+ return (FALSE);
+ if (!xdr_channel_attrs4(xdrs, &objp->csa_fore_chan_attrs))
+ return (FALSE);
+ if (!xdr_channel_attrs4(xdrs, &objp->csa_back_chan_attrs))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->csa_cb_program))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->csa_sec_parms.csa_sec_parms_val,
+ (uint_t *)&objp->csa_sec_parms.csa_sec_parms_len, ~0,
+ sizeof (callback_sec_parms4), (xdrproc_t)xdr_callback_sec_parms4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CREATE_SESSION4resok(XDR *xdrs, CREATE_SESSION4resok *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->csr_sessionid))
+ return (FALSE);
+ if (!xdr_sequenceid4(xdrs, &objp->csr_sequence))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->csr_flags))
+ return (FALSE);
+ if (!xdr_channel_attrs4(xdrs, &objp->csr_fore_chan_attrs))
+ return (FALSE);
+ if (!xdr_channel_attrs4(xdrs, &objp->csr_back_chan_attrs))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CREATE_SESSION4res(XDR *xdrs, CREATE_SESSION4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->csr_status))
+ return (FALSE);
+ switch (objp->csr_status) {
+ case NFS4_OK:
+ if (!xdr_CREATE_SESSION4resok(xdrs,
+ &objp->CREATE_SESSION4res_u.csr_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_DESTROY_SESSION4args(XDR *xdrs, DESTROY_SESSION4args *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->dsa_sessionid))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_DESTROY_SESSION4res(XDR *xdrs, DESTROY_SESSION4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->dsr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_FREE_STATEID4args(XDR *xdrs, FREE_STATEID4args *objp)
+{
+ if (!xdr_stateid4(xdrs, &objp->fsa_stateid))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_FREE_STATEID4res(XDR *xdrs, FREE_STATEID4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->fsr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_attr_notice4(XDR *xdrs, attr_notice4 *objp)
+{
+ if (!xdr_nfstime4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_GET_DIR_DELEGATION4args(XDR *xdrs, GET_DIR_DELEGATION4args *objp)
+{
+ if (!xdr_bool(xdrs, &objp->gdda_signal_deleg_avail))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->gdda_notification_types))
+ return (FALSE);
+ if (!xdr_attr_notice4(xdrs, &objp->gdda_child_attr_delay))
+ return (FALSE);
+ if (!xdr_attr_notice4(xdrs, &objp->gdda_dir_attr_delay))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->gdda_child_attributes))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->gdda_dir_attributes))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_GET_DIR_DELEGATION4resok(XDR *xdrs, GET_DIR_DELEGATION4resok *objp)
+{
+ if (!xdr_verifier4(xdrs, (verifier4 *)&objp->gddr_cookieverf))
+ return (FALSE);
+ if (!xdr_stateid4(xdrs, &objp->gddr_stateid))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->gddr_notification))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->gddr_child_attributes))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->gddr_dir_attributes))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_gddrnf4_status(XDR *xdrs, gddrnf4_status *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_GET_DIR_DELEGATION4res_non_fatal(XDR *xdrs,
+ GET_DIR_DELEGATION4res_non_fatal *objp)
+{
+ if (!xdr_gddrnf4_status(xdrs, &objp->gddrnf_status))
+ return (FALSE);
+ switch (objp->gddrnf_status) {
+ case GDD4_OK:
+ if (!xdr_GET_DIR_DELEGATION4resok(xdrs,
+ &objp->GET_DIR_DELEGATION4res_non_fatal_u.gddrnf_resok4))
+ return (FALSE);
+ break;
+ case GDD4_UNAVAIL:
+ if (!xdr_bool(xdrs, &objp->GET_DIR_DELEGATION4res_non_fatal_u.
+ gddrnf_will_signal_deleg_avail))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_GET_DIR_DELEGATION4res(XDR *xdrs, GET_DIR_DELEGATION4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->gddr_status))
+ return (FALSE);
+ switch (objp->gddr_status) {
+ case NFS4_OK:
+ if (!xdr_GET_DIR_DELEGATION4res_non_fatal(xdrs,
+ &objp->GET_DIR_DELEGATION4res_u.gddr_res_non_fatal4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+/*
+ * Special xdr function to encode single word bitmaps for
+ * notification bitmaps which only need a single word.
+ */
+bool_t
+xdr_bitmap4_notify(XDR *xdrs, bitmap4 *objp)
+{
+ int32_t len = 1;
+
+ ASSERT(xdrs->x_op == XDR_ENCODE);
+ if (!XDR_PUTINT32(xdrs, &len))
+ return (FALSE);
+#if defined(_BIG_ENDIAN)
+ return (XDR_PUTINT32(xdrs, (int32_t *)objp));
+#elif defined(_LITTLE_ENDIAN)
+ return (XDR_PUTINT32(xdrs, (int32_t *)objp+1));
+#endif
+}
+
+bool_t
+xdr_GETDEVICEINFO4args(XDR *xdrs, GETDEVICEINFO4args *objp)
+{
+ if (!xdr_deviceid4(xdrs, objp->gdia_device_id))
+ return (FALSE);
+ if (!xdr_layouttype4(xdrs, &objp->gdia_layout_type))
+ return (FALSE);
+ if (!xdr_count4(xdrs, &objp->gdia_maxcount))
+ return (FALSE);
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!xdr_bitmap4_notify(xdrs, &objp->gdia_notify_types))
+ return (FALSE);
+ } else
+ if (!xdr_bitmap4(xdrs, &objp->gdia_notify_types))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_GETDEVICEINFO4resok(XDR *xdrs, GETDEVICEINFO4resok *objp)
+{
+ if (!xdr_device_addr4(xdrs, &objp->gdir_device_addr))
+ return (FALSE);
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!xdr_bitmap4_notify(xdrs, &objp->gdir_notification))
+ return (FALSE);
+ } else
+ if (!xdr_bitmap4(xdrs, &objp->gdir_notification))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_GETDEVICEINFO4res(XDR *xdrs, GETDEVICEINFO4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->gdir_status))
+ return (FALSE);
+ switch (objp->gdir_status) {
+ case NFS4_OK:
+ if (!xdr_GETDEVICEINFO4resok(xdrs,
+ &objp->GETDEVICEINFO4res_u.gdir_resok4))
+ return (FALSE);
+ break;
+ case NFS4ERR_TOOSMALL:
+ if (!xdr_count4(xdrs, &objp->GETDEVICEINFO4res_u.gdir_mincount))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_GETDEVICELIST4args(XDR *xdrs, GETDEVICELIST4args *objp)
+{
+ if (!xdr_layouttype4(xdrs, &objp->gdla_layout_type))
+ return (FALSE);
+ if (!xdr_count4(xdrs, &objp->gdla_maxdevices))
+ return (FALSE);
+ if (!xdr_nfs_cookie4(xdrs, &objp->gdla_cookie))
+ return (FALSE);
+ if (!xdr_verifier4(xdrs, (verifier4 *)&objp->gdla_cookieverf))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_GETDEVICELIST4resok(XDR *xdrs, GETDEVICELIST4resok *objp)
+{
+ if (!xdr_nfs_cookie4(xdrs, &objp->gdlr_cookie))
+ return (FALSE);
+ if (!xdr_verifier4(xdrs, (verifier4 *)&objp->gdlr_cookieverf))
+ return (FALSE);
+ if (!xdr_array(xdrs,
+ (char **)&objp->gdlr_deviceid_list.gdlr_deviceid_list_val,
+ (uint_t *)&objp->gdlr_deviceid_list.gdlr_deviceid_list_len,
+ ~0, sizeof (deviceid4), (xdrproc_t)xdr_deviceid4))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->gdlr_eof))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_GETDEVICELIST4res(XDR *xdrs, GETDEVICELIST4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->gdlr_status))
+ return (FALSE);
+ switch (objp->gdlr_status) {
+ case NFS4_OK:
+ if (!xdr_GETDEVICELIST4resok(xdrs,
+ &objp->GETDEVICELIST4res_u.gdlr_resok4))
+ return (FALSE);
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_newtime4(XDR *xdrs, newtime4 *objp)
+{
+ if (!xdr_bool(xdrs, &objp->nt_timechanged))
+ return (FALSE);
+ switch (objp->nt_timechanged) {
+ case TRUE:
+ if (!xdr_nfstime4(xdrs, &objp->newtime4_u.nt_time))
+ return (FALSE);
+ break;
+ case FALSE:
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_newoffset4(XDR *xdrs, newoffset4 *objp)
+{
+ if (!xdr_bool(xdrs, &objp->no_newoffset))
+ return (FALSE);
+ switch (objp->no_newoffset) {
+ case TRUE:
+ if (!xdr_offset4(xdrs, &objp->newoffset4_u.no_offset))
+ return (FALSE);
+ break;
+ case FALSE:
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_LAYOUTCOMMIT4args(XDR *xdrs, LAYOUTCOMMIT4args *objp)
+{
+ if (!xdr_offset4(xdrs, &objp->loca_offset))
+ return (FALSE);
+ if (!xdr_length4(xdrs, &objp->loca_length))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->loca_reclaim))
+ return (FALSE);
+ if (!xdr_stateid4(xdrs, &objp->loca_stateid))
+ return (FALSE);
+ if (!xdr_newoffset4(xdrs, &objp->loca_last_write_offset))
+ return (FALSE);
+ if (!xdr_newtime4(xdrs, &objp->loca_time_modify))
+ return (FALSE);
+ if (!xdr_layoutupdate4(xdrs, &objp->loca_layoutupdate))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_newsize4(XDR *xdrs, newsize4 *objp)
+{
+ if (!xdr_bool(xdrs, &objp->ns_sizechanged))
+ return (FALSE);
+ switch (objp->ns_sizechanged) {
+ case TRUE:
+ if (!xdr_length4(xdrs, &objp->newsize4_u.ns_size))
+ return (FALSE);
+ break;
+ case FALSE:
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_LAYOUTCOMMIT4resok(XDR *xdrs, LAYOUTCOMMIT4resok *objp)
+{
+ if (!xdr_newsize4(xdrs, &objp->locr_newsize))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_LAYOUTCOMMIT4res(XDR *xdrs, LAYOUTCOMMIT4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->locr_status))
+ return (FALSE);
+ switch (objp->locr_status) {
+ case NFS4_OK:
+ if (!xdr_LAYOUTCOMMIT4resok(xdrs,
+ &objp->LAYOUTCOMMIT4res_u.locr_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_LAYOUTGET4args(XDR *xdrs, LAYOUTGET4args *objp)
+{
+ if (!xdr_bool(xdrs, &objp->loga_signal_layout_avail))
+ return (FALSE);
+ if (!xdr_layouttype4(xdrs, &objp->loga_layout_type))
+ return (FALSE);
+ if (!xdr_layoutiomode4(xdrs, &objp->loga_iomode))
+ return (FALSE);
+ if (!xdr_offset4(xdrs, &objp->loga_offset))
+ return (FALSE);
+ if (!xdr_length4(xdrs, &objp->loga_length))
+ return (FALSE);
+ if (!xdr_length4(xdrs, &objp->loga_minlength))
+ return (FALSE);
+ if (!xdr_stateid4(xdrs, &objp->loga_stateid))
+ return (FALSE);
+ if (!xdr_count4(xdrs, &objp->loga_maxcount))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_LAYOUTGET4resok(XDR *xdrs, LAYOUTGET4resok *objp)
+{
+ if (!xdr_bool(xdrs, &objp->logr_return_on_close))
+ return (FALSE);
+ if (!xdr_stateid4(xdrs, &objp->logr_stateid))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->logr_layout.logr_layout_val,
+ (uint_t *)&objp->logr_layout.logr_layout_len, ~0,
+ sizeof (layout4), (xdrproc_t)xdr_layout4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_LAYOUTGET4res(XDR *xdrs, LAYOUTGET4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->logr_status))
+ return (FALSE);
+ switch (objp->logr_status) {
+ case NFS4_OK:
+ if (!xdr_LAYOUTGET4resok(xdrs,
+ &objp->LAYOUTGET4res_u.logr_resok4))
+ return (FALSE);
+ break;
+ case NFS4ERR_LAYOUTTRYLATER:
+ if (!xdr_bool(xdrs,
+ &objp->LAYOUTGET4res_u.logr_will_signal_layout_avail))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_LAYOUTRETURN4args(XDR *xdrs, LAYOUTRETURN4args *objp)
+{
+ if (!xdr_bool(xdrs, &objp->lora_reclaim))
+ return (FALSE);
+ if (!xdr_layouttype4(xdrs, &objp->lora_layout_type))
+ return (FALSE);
+ if (!xdr_layoutiomode4(xdrs, &objp->lora_iomode))
+ return (FALSE);
+ if (!xdr_layoutreturn4(xdrs, &objp->lora_layoutreturn))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layoutreturn_stateid(XDR *xdrs, layoutreturn_stateid *objp)
+{
+ if (!xdr_bool(xdrs, &objp->lrs_present))
+ return (FALSE);
+ switch (objp->lrs_present) {
+ case TRUE:
+ if (!xdr_stateid4(xdrs,
+ &objp->layoutreturn_stateid_u.lrs_stateid))
+ return (FALSE);
+ break;
+ case FALSE:
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_LAYOUTRETURN4res(XDR *xdrs, LAYOUTRETURN4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->lorr_status))
+ return (FALSE);
+ switch (objp->lorr_status) {
+ case NFS4_OK:
+ if (!xdr_layoutreturn_stateid(xdrs,
+ &objp->LAYOUTRETURN4res_u.lorr_stateid))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_secinfo_style4(XDR *xdrs, secinfo_style4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_SECINFO_NO_NAME4args(XDR *xdrs, SECINFO_NO_NAME4args *objp)
+{
+ if (!xdr_secinfo_style4(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_SECINFO_NO_NAME4res(XDR *xdrs, SECINFO_NO_NAME4res *objp)
+{
+ if (!xdr_SECINFO4res(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_SEQUENCE4args(XDR *xdrs, SEQUENCE4args *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->sa_sessionid))
+ return (FALSE);
+ if (!xdr_sequenceid4(xdrs, &objp->sa_sequenceid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->sa_slotid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->sa_highest_slotid))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->sa_cachethis))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_SEQUENCE4resok(XDR *xdrs, SEQUENCE4resok *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->sr_sessionid))
+ return (FALSE);
+ if (!xdr_sequenceid4(xdrs, &objp->sr_sequenceid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->sr_slotid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->sr_highest_slotid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->sr_target_highest_slotid))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->sr_status_flags))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_SEQUENCE4res(XDR *xdrs, SEQUENCE4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->sr_status))
+ return (FALSE);
+ switch (objp->sr_status) {
+ case NFS4_OK:
+ if (!xdr_SEQUENCE4resok(xdrs, &objp->SEQUENCE4res_u.sr_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_ssa_digest_input4(XDR *xdrs, ssa_digest_input4 *objp)
+{
+ if (!xdr_SEQUENCE4args(xdrs, &objp->sdi_seqargs))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_SET_SSV4args(XDR *xdrs, SET_SSV4args *objp)
+{
+ if (!xdr_bytes(xdrs, (char **)&objp->ssa_ssv.ssa_ssv_val,
+ (uint_t *)&objp->ssa_ssv.ssa_ssv_len, ~0))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->ssa_digest.ssa_digest_val,
+ (uint_t *)&objp->ssa_digest.ssa_digest_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_ssr_digest_input4(XDR *xdrs, ssr_digest_input4 *objp)
+{
+ if (!xdr_SEQUENCE4res(xdrs, &objp->sdi_seqres))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_SET_SSV4resok(XDR *xdrs, SET_SSV4resok *objp)
+{
+ if (!xdr_bytes(xdrs, (char **)&objp->ssr_digest.ssr_digest_val,
+ (uint_t *)&objp->ssr_digest.ssr_digest_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_SET_SSV4res(XDR *xdrs, SET_SSV4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->ssr_status))
+ return (FALSE);
+ switch (objp->ssr_status) {
+ case NFS4_OK:
+ if (!xdr_SET_SSV4resok(xdrs, &objp->SET_SSV4res_u.ssr_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_TEST_STATEID4args(XDR *xdrs, TEST_STATEID4args *objp)
+{
+ if (!xdr_array(xdrs, (char **)&objp->ts_stateids.ts_stateids_val,
+ (uint_t *)&objp->ts_stateids.ts_stateids_len, ~0,
+ sizeof (stateid4), (xdrproc_t)xdr_stateid4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_TEST_STATEID4resok(XDR *xdrs, TEST_STATEID4resok *objp)
+{
+ if (!xdr_array(xdrs,
+ (char **)&objp->tsr_status_codes.tsr_status_codes_val,
+ (uint_t *)&objp->tsr_status_codes.tsr_status_codes_len, ~0,
+ sizeof (nfsstat4), (xdrproc_t)xdr_nfsstat4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_TEST_STATEID4res(XDR *xdrs, TEST_STATEID4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->tsr_status))
+ return (FALSE);
+ switch (objp->tsr_status) {
+ case NFS4_OK:
+ if (!xdr_TEST_STATEID4resok(xdrs,
+ &objp->TEST_STATEID4res_u.tsr_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_deleg_claim4(XDR *xdrs, deleg_claim4 *objp)
+{
+ if (!xdr_open_claim_type4(xdrs, &objp->dc_claim))
+ return (FALSE);
+ switch (objp->dc_claim) {
+ case CLAIM_FH:
+ break;
+ case CLAIM_DELEG_PREV_FH:
+ break;
+ case CLAIM_PREVIOUS:
+ if (!xdr_open_delegation_type4(xdrs,
+ &objp->deleg_claim4_u.dc_delegate_type))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_WANT_DELEGATION4args(XDR *xdrs, WANT_DELEGATION4args *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->wda_want))
+ return (FALSE);
+ if (!xdr_deleg_claim4(xdrs, &objp->wda_claim))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_WANT_DELEGATION4res(XDR *xdrs, WANT_DELEGATION4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->wdr_status))
+ return (FALSE);
+ switch (objp->wdr_status) {
+ case NFS4_OK:
+ if (!xdr_open_delegation4(xdrs,
+ &objp->WANT_DELEGATION4res_u.wdr_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_DESTROY_CLIENTID4args(XDR *xdrs, DESTROY_CLIENTID4args *objp)
+{
+ if (!xdr_clientid4(xdrs, &objp->dca_clientid))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_DESTROY_CLIENTID4res(XDR *xdrs, DESTROY_CLIENTID4res *objp)
+{
+
+ if (!xdr_nfsstat4(xdrs, &objp->dcr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_RECLAIM_COMPLETE4args(XDR *xdrs, RECLAIM_COMPLETE4args *objp)
+{
+ if (!xdr_bool(xdrs, &objp->rca_one_fs))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_RECLAIM_COMPLETE4res(XDR *xdrs, RECLAIM_COMPLETE4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->rcr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+/* new operations for NFSv4.1 */
+
+bool_t
+xdr_nfs4x_argop4(XDR *xdrs, nfs_argop4 *objp)
+{
+ /* nfs_opnum4 has already been xdr'd */
+ switch (objp->argop) {
+ case OP_BACKCHANNEL_CTL:
+ if (!xdr_BACKCHANNEL_CTL4args(xdrs,
+ &objp->nfs_argop4_u.opbackchannel_ctl))
+ return (FALSE);
+ break;
+ case OP_BIND_CONN_TO_SESSION:
+ if (!xdr_BIND_CONN_TO_SESSION4args(xdrs,
+ &objp->nfs_argop4_u.opbind_conn_to_session))
+ return (FALSE);
+ break;
+ case OP_EXCHANGE_ID:
+ if (!xdr_EXCHANGE_ID4args(xdrs,
+ &objp->nfs_argop4_u.opexchange_id))
+ return (FALSE);
+ break;
+ case OP_CREATE_SESSION:
+ if (!xdr_CREATE_SESSION4args(xdrs,
+ &objp->nfs_argop4_u.opcreate_session))
+ return (FALSE);
+ break;
+ case OP_DESTROY_SESSION:
+ if (!xdr_DESTROY_SESSION4args(xdrs,
+ &objp->nfs_argop4_u.opdestroy_session))
+ return (FALSE);
+ break;
+ case OP_FREE_STATEID:
+ if (!xdr_FREE_STATEID4args(xdrs,
+ &objp->nfs_argop4_u.opfree_stateid))
+ return (FALSE);
+ break;
+ case OP_GET_DIR_DELEGATION:
+ if (!xdr_GET_DIR_DELEGATION4args(xdrs,
+ &objp->nfs_argop4_u.opget_dir_delegation))
+ return (FALSE);
+ break;
+ case OP_GETDEVICEINFO:
+ if (!xdr_GETDEVICEINFO4args(xdrs,
+ &objp->nfs_argop4_u.opgetdeviceinfo))
+ return (FALSE);
+ break;
+ case OP_GETDEVICELIST:
+ if (!xdr_GETDEVICELIST4args(xdrs,
+ &objp->nfs_argop4_u.opgetdevicelist))
+ return (FALSE);
+ break;
+ case OP_LAYOUTCOMMIT:
+ if (!xdr_LAYOUTCOMMIT4args(xdrs,
+ &objp->nfs_argop4_u.oplayoutcommit))
+ return (FALSE);
+ break;
+ case OP_LAYOUTGET:
+ if (!xdr_LAYOUTGET4args(xdrs,
+ &objp->nfs_argop4_u.oplayoutget))
+ return (FALSE);
+ break;
+ case OP_LAYOUTRETURN:
+ if (!xdr_LAYOUTRETURN4args(xdrs,
+ &objp->nfs_argop4_u.oplayoutreturn))
+ return (FALSE);
+ break;
+ case OP_SECINFO_NO_NAME:
+ if (!xdr_SECINFO_NO_NAME4args(xdrs,
+ &objp->nfs_argop4_u.opsecinfo_no_name))
+ return (FALSE);
+ break;
+ case OP_SEQUENCE:
+ if (!xdr_SEQUENCE4args(xdrs,
+ &objp->nfs_argop4_u.opsequence))
+ return (FALSE);
+ break;
+ case OP_SET_SSV:
+ if (!xdr_SET_SSV4args(xdrs,
+ &objp->nfs_argop4_u.opset_ssv))
+ return (FALSE);
+ break;
+ case OP_TEST_STATEID:
+ if (!xdr_TEST_STATEID4args(xdrs,
+ &objp->nfs_argop4_u.optest_stateid))
+ return (FALSE);
+ break;
+ case OP_WANT_DELEGATION:
+ if (!xdr_WANT_DELEGATION4args(xdrs,
+ &objp->nfs_argop4_u.opwant_delegation))
+ return (FALSE);
+ break;
+ case OP_DESTROY_CLIENTID:
+ if (!xdr_DESTROY_CLIENTID4args(xdrs,
+ &objp->nfs_argop4_u.opdestroy_clientid))
+ return (FALSE);
+ break;
+ case OP_RECLAIM_COMPLETE:
+ if (!xdr_RECLAIM_COMPLETE4args(xdrs,
+ &objp->nfs_argop4_u.opreclaim_complete))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_nfs4x_resop4(XDR *xdrs, nfs_resop4 *objp)
+{
+ /* nfs_opnum4 has already been xdr's */
+ switch (objp->resop) {
+ case OP_BACKCHANNEL_CTL:
+ if (!xdr_BACKCHANNEL_CTL4res(xdrs,
+ &objp->nfs_resop4_u.opbackchannel_ctl))
+ return (FALSE);
+ break;
+ case OP_BIND_CONN_TO_SESSION:
+ if (!xdr_BIND_CONN_TO_SESSION4res(xdrs,
+ &objp->nfs_resop4_u.opbind_conn_to_session))
+ return (FALSE);
+ break;
+ case OP_EXCHANGE_ID:
+ if (!xdr_EXCHANGE_ID4res(xdrs,
+ &objp->nfs_resop4_u.opexchange_id))
+ return (FALSE);
+ break;
+ case OP_CREATE_SESSION:
+ if (!xdr_CREATE_SESSION4res(xdrs,
+ &objp->nfs_resop4_u.opcreate_session))
+ return (FALSE);
+ break;
+ case OP_DESTROY_SESSION:
+ if (!xdr_DESTROY_SESSION4res(xdrs,
+ &objp->nfs_resop4_u.opdestroy_session))
+ return (FALSE);
+ break;
+ case OP_FREE_STATEID:
+ if (!xdr_FREE_STATEID4res(xdrs,
+ &objp->nfs_resop4_u.opfree_stateid))
+ return (FALSE);
+ break;
+ case OP_GET_DIR_DELEGATION:
+ if (!xdr_GET_DIR_DELEGATION4res(xdrs,
+ &objp->nfs_resop4_u.opget_dir_delegation))
+ return (FALSE);
+ break;
+ case OP_GETDEVICEINFO:
+ if (!xdr_GETDEVICEINFO4res(xdrs,
+ &objp->nfs_resop4_u.opgetdeviceinfo))
+ return (FALSE);
+ break;
+ case OP_GETDEVICELIST:
+ if (!xdr_GETDEVICELIST4res(xdrs,
+ &objp->nfs_resop4_u.opgetdevicelist))
+ return (FALSE);
+ break;
+ case OP_LAYOUTCOMMIT:
+ if (!xdr_LAYOUTCOMMIT4res(xdrs,
+ &objp->nfs_resop4_u.oplayoutcommit))
+ return (FALSE);
+ break;
+ case OP_LAYOUTGET:
+ if (!xdr_LAYOUTGET4res(xdrs,
+ &objp->nfs_resop4_u.oplayoutget))
+ return (FALSE);
+ break;
+ case OP_LAYOUTRETURN:
+ if (!xdr_LAYOUTRETURN4res(xdrs,
+ &objp->nfs_resop4_u.oplayoutreturn))
+ return (FALSE);
+ break;
+ case OP_SECINFO_NO_NAME:
+ if (!xdr_SECINFO_NO_NAME4res(xdrs,
+ &objp->nfs_resop4_u.opsecinfo_no_name))
+ return (FALSE);
+ break;
+ case OP_SEQUENCE:
+ if (!xdr_SEQUENCE4res(xdrs,
+ &objp->nfs_resop4_u.opsequence))
+ return (FALSE);
+ break;
+ case OP_SET_SSV:
+ if (!xdr_SET_SSV4res(xdrs,
+ &objp->nfs_resop4_u.opset_ssv))
+ return (FALSE);
+ break;
+ case OP_TEST_STATEID:
+ if (!xdr_TEST_STATEID4res(xdrs,
+ &objp->nfs_resop4_u.optest_stateid))
+ return (FALSE);
+ break;
+ case OP_WANT_DELEGATION:
+ if (!xdr_WANT_DELEGATION4res(xdrs,
+ &objp->nfs_resop4_u.opwant_delegation))
+ return (FALSE);
+ break;
+ case OP_DESTROY_CLIENTID:
+ if (!xdr_DESTROY_CLIENTID4res(xdrs,
+ &objp->nfs_resop4_u.opdestroy_clientid))
+ return (FALSE);
+ break;
+ case OP_RECLAIM_COMPLETE:
+ if (!xdr_RECLAIM_COMPLETE4res(xdrs,
+ &objp->nfs_resop4_u.opreclaim_complete))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_layoutrecall_type4(XDR *xdrs, layoutrecall_type4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layoutrecall_file4(XDR *xdrs, layoutrecall_file4 *objp)
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ /* TODO: encode nfs4x_fh */
+ return (FALSE);
+
+ case XDR_DECODE:
+ if (!xdr_bytes(xdrs, (char **)&objp->lor_fh.nfs_fh4_val,
+ (uint_t *)&objp->lor_fh.nfs_fh4_len, NFS4_FHSIZE))
+ return (FALSE);
+ break;
+
+ case XDR_FREE:
+ if (objp->lor_fh.nfs_fh4_val != NULL) {
+ if (!xdr_bytes(xdrs,
+ (char **)&objp->lor_fh.nfs_fh4_val,
+ (uint_t *)&objp->lor_fh.nfs_fh4_len,
+ NFS4_FHSIZE))
+ return (FALSE);
+ }
+ break;
+ }
+
+ if (!xdr_offset4(xdrs, &objp->lor_offset))
+ return (FALSE);
+ if (!xdr_length4(xdrs, &objp->lor_length))
+ return (FALSE);
+ if (!xdr_stateid4(xdrs, &objp->lor_stateid))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_layoutrecall4(XDR *xdrs, layoutrecall4 *objp)
+{
+ if (!xdr_layoutrecall_type4(xdrs, &objp->lor_recalltype))
+ return (FALSE);
+ switch (objp->lor_recalltype) {
+ case LAYOUTRECALL4_FILE:
+ if (!xdr_layoutrecall_file4(xdrs,
+ &objp->layoutrecall4_u.lor_layout))
+ return (FALSE);
+ break;
+ case LAYOUTRECALL4_FSID:
+ if (!xdr_fsid4(xdrs, &objp->layoutrecall4_u.lor_fsid))
+ return (FALSE);
+ break;
+ case LAYOUTRECALL4_ALL:
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_LAYOUTRECALL4args(XDR *xdrs, CB_LAYOUTRECALL4args *objp)
+{
+ if (!xdr_layouttype4(xdrs, &objp->clora_type))
+ return (FALSE);
+ if (!xdr_layoutiomode4(xdrs, &objp->clora_iomode))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->clora_changed))
+ return (FALSE);
+ if (!xdr_layoutrecall4(xdrs, &objp->clora_recall))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_LAYOUTRECALL4res(XDR *xdrs, CB_LAYOUTRECALL4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->clorr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_type4(XDR *xdrs, notify_type4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_entry4(XDR *xdrs, notify_entry4 *objp)
+{
+ if (!xdr_component4(xdrs, &objp->ne_file))
+ return (FALSE);
+ if (!xdr_fattr4(xdrs, &objp->ne_attrs))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_prev_entry4(XDR *xdrs, prev_entry4 *objp)
+{
+ if (!xdr_notify_entry4(xdrs, &objp->pe_prev_entry))
+ return (FALSE);
+ if (!xdr_nfs_cookie4(xdrs, &objp->pe_prev_entry_cookie))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_remove4(XDR *xdrs, notify_remove4 *objp)
+{
+
+ if (!xdr_notify_entry4(xdrs, &objp->nrm_old_entry))
+ return (FALSE);
+ if (!xdr_nfs_cookie4(xdrs, &objp->nrm_old_entry_cookie))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_add4(XDR *xdrs, notify_add4 *objp)
+{
+ if (!xdr_array(xdrs, (char **)&objp->nad_old_entry.nad_old_entry_val,
+ (uint_t *)&objp->nad_old_entry.nad_old_entry_len, 1,
+ sizeof (notify_remove4), (xdrproc_t)xdr_notify_remove4))
+ return (FALSE);
+ if (!xdr_notify_entry4(xdrs, &objp->nad_new_entry))
+ return (FALSE);
+ if (!xdr_array(xdrs,
+ (char **)&objp->nad_new_entry_cookie.nad_new_entry_cookie_val,
+ (uint_t *)&objp->nad_new_entry_cookie.nad_new_entry_cookie_len, 1,
+ sizeof (nfs_cookie4), (xdrproc_t)xdr_nfs_cookie4))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->nad_prev_entry.nad_prev_entry_val,
+ (uint_t *)&objp->nad_prev_entry.nad_prev_entry_len, 1,
+ sizeof (prev_entry4), (xdrproc_t)xdr_prev_entry4))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->nad_last_entry))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_attr4(XDR *xdrs, notify_attr4 *objp)
+{
+ if (!xdr_notify_entry4(xdrs, &objp->na_changed_entry))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_rename4(XDR *xdrs, notify_rename4 *objp)
+{
+ if (!xdr_notify_remove4(xdrs, &objp->nrn_old_entry))
+ return (FALSE);
+ if (!xdr_notify_add4(xdrs, &objp->nrn_new_entry))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_verifier4(XDR *xdrs, notify_verifier4 *objp)
+{
+ if (!xdr_verifier4(xdrs, (verifier4 *)&objp->nv_old_cookieverf))
+ return (FALSE);
+ if (!xdr_verifier4(xdrs, (verifier4 *)&objp->nv_new_cookieverf))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notifylist4(XDR *xdrs, notifylist4 *objp)
+{
+ if (!xdr_bytes(xdrs, (char **)&objp->notifylist4_val,
+ (uint_t *)&objp->notifylist4_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify4(XDR *xdrs, notify4 *objp)
+{
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!xdr_bitmap4_notify(xdrs, &objp->notify_mask))
+ return (FALSE);
+ } else
+ if (!xdr_bitmap4(xdrs, &objp->notify_mask))
+ return (FALSE);
+ if (!xdr_notifylist4(xdrs, &objp->notify_vals))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_NOTIFY4args(XDR *xdrs, CB_NOTIFY4args *objp)
+{
+ if (!xdr_stateid4(xdrs, &objp->cna_stateid))
+ return (FALSE);
+ if (!xdr_nfs_fh4(xdrs, &objp->cna_fh))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->cna_changes.cna_changes_val,
+ (uint_t *)&objp->cna_changes.cna_changes_len, ~0,
+ sizeof (notify4), (xdrproc_t)xdr_notify4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_NOTIFY4res(XDR *xdrs, CB_NOTIFY4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->cnr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_PUSH_DELEG4args(XDR *xdrs, CB_PUSH_DELEG4args *objp)
+{
+ if (!xdr_nfs_fh4(xdrs, &objp->cpda_fh))
+ return (FALSE);
+ if (!xdr_open_delegation4(xdrs, &objp->cpda_delegation))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_PUSH_DELEG4res(XDR *xdrs, CB_PUSH_DELEG4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->cpdr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_RECALL_ANY4args(XDR *xdrs, CB_RECALL_ANY4args *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->craa_objects_to_keep))
+ return (FALSE);
+ if (!xdr_bitmap4(xdrs, &objp->craa_type_mask))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_RECALL_ANY4res(XDR *xdrs, CB_RECALL_ANY4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->crar_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_RECALLABLE_OBJ_AVAIL4args(XDR *xdrs, CB_RECALLABLE_OBJ_AVAIL4args *objp)
+{
+ if (!xdr_CB_RECALL_ANY4args(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_RECALLABLE_OBJ_AVAIL4res(XDR *xdrs, CB_RECALLABLE_OBJ_AVAIL4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->croa_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_RECALL_SLOT4args(XDR *xdrs, CB_RECALL_SLOT4args *objp)
+{
+ if (!xdr_slotid4(xdrs, &objp->rsa_target_highest_slotid))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_RECALL_SLOT4res(XDR *xdrs, CB_RECALL_SLOT4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->rsr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_referring_call4(XDR *xdrs, referring_call4 *objp)
+{
+ if (!xdr_sequenceid4(xdrs, &objp->rc_sequenceid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->rc_slotid))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_referring_call_list4(XDR *xdrs, referring_call_list4 *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->rcl_sessionid))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->rcl_referring_calls.
+ rcl_referring_calls_val,
+ (uint_t *)&objp->rcl_referring_calls.rcl_referring_calls_len, ~0,
+ sizeof (referring_call4), (xdrproc_t)xdr_referring_call4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_SEQUENCE4args(XDR *xdrs, CB_SEQUENCE4args *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->csa_sessionid))
+ return (FALSE);
+ if (!xdr_sequenceid4(xdrs, &objp->csa_sequenceid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->csa_slotid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->csa_highest_slotid))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->csa_cachethis))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->csa_referring_call_lists.
+ csa_referring_call_lists_val,
+ (uint_t *)&objp->csa_referring_call_lists.
+ csa_referring_call_lists_len, ~0, sizeof (referring_call_list4),
+ (xdrproc_t)xdr_referring_call_list4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_SEQUENCE4resok(XDR *xdrs, CB_SEQUENCE4resok *objp)
+{
+ if (!xdr_sessionid4(xdrs, objp->csr_sessionid))
+ return (FALSE);
+ if (!xdr_sequenceid4(xdrs, &objp->csr_sequenceid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->csr_slotid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->csr_highest_slotid))
+ return (FALSE);
+ if (!xdr_slotid4(xdrs, &objp->csr_target_highest_slotid))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_SEQUENCE4res(XDR *xdrs, CB_SEQUENCE4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->csr_status))
+ return (FALSE);
+ switch (objp->csr_status) {
+ case NFS4_OK:
+ if (!xdr_CB_SEQUENCE4resok(xdrs,
+ &objp->CB_SEQUENCE4res_u.csr_resok4))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_WANTS_CANCELLED4args(XDR *xdrs, CB_WANTS_CANCELLED4args *objp)
+{
+ if (!xdr_bool(xdrs, &objp->cwca_contended_wants_cancelled))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->cwca_resourced_wants_cancelled))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_WANTS_CANCELLED4res(XDR *xdrs, CB_WANTS_CANCELLED4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->cwcr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_NOTIFY_LOCK4args(XDR *xdrs, CB_NOTIFY_LOCK4args *objp)
+{
+ if (!xdr_nfs_fh4(xdrs, &objp->cnla_fh))
+ return (FALSE);
+ if (!xdr_lock_owner4(xdrs, &objp->cnla_lock_owner))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_NOTIFY_LOCK4res(XDR *xdrs, CB_NOTIFY_LOCK4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->cnlr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_deviceid_type4(XDR *xdrs, notify_deviceid_type4 *objp)
+{
+
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_deviceid_delete4(XDR *xdrs, notify_deviceid_delete4 *objp)
+{
+ if (!xdr_layouttype4(xdrs, &objp->ndd_layouttype))
+ return (FALSE);
+ if (!xdr_deviceid4(xdrs, objp->ndd_deviceid))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_notify_deviceid_change4(XDR *xdrs, notify_deviceid_change4 *objp)
+{
+
+ if (!xdr_layouttype4(xdrs, &objp->ndc_layouttype))
+ return (FALSE);
+ if (!xdr_deviceid4(xdrs, objp->ndc_deviceid))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->ndc_immediate))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_NOTIFY_DEVICEID4args(XDR *xdrs, CB_NOTIFY_DEVICEID4args *objp)
+{
+ if (!xdr_array(xdrs, (char **)&objp->cnda_changes.cnda_changes_val,
+ (uint_t *)&objp->cnda_changes.cnda_changes_len, ~0,
+ sizeof (notify4), (xdrproc_t)xdr_notify4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_NOTIFY_DEVICEID4res(XDR *xdrs, CB_NOTIFY_DEVICEID4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->cndr_status))
+ return (FALSE);
+ return (TRUE);
+}
+
+/* Callback operations new to NFSv4.1 */
+
+bool_t
+xdr_nfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
+{
+ /* argop has already been xdr'd */
+ switch (objp->argop) {
+ case OP_CB_LAYOUTRECALL:
+ if (!xdr_CB_LAYOUTRECALL4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcblayoutrecall))
+ return (FALSE);
+ break;
+ case OP_CB_NOTIFY:
+ if (!xdr_CB_NOTIFY4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbnotify))
+ return (FALSE);
+ break;
+ case OP_CB_PUSH_DELEG:
+ if (!xdr_CB_PUSH_DELEG4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbpush_deleg))
+ return (FALSE);
+ break;
+ case OP_CB_RECALL_ANY:
+ if (!xdr_CB_RECALL_ANY4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbrecall_any))
+ return (FALSE);
+ break;
+ case OP_CB_RECALLABLE_OBJ_AVAIL:
+ if (!xdr_CB_RECALLABLE_OBJ_AVAIL4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbrecallable_obj_avail))
+ return (FALSE);
+ break;
+ case OP_CB_RECALL_SLOT:
+ if (!xdr_CB_RECALL_SLOT4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbrecall_slot))
+ return (FALSE);
+ break;
+ case OP_CB_SEQUENCE:
+ if (!xdr_CB_SEQUENCE4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbsequence))
+ return (FALSE);
+ break;
+ case OP_CB_WANTS_CANCELLED:
+ if (!xdr_CB_WANTS_CANCELLED4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbwants_cancelled))
+ return (FALSE);
+ break;
+ case OP_CB_NOTIFY_LOCK:
+ if (!xdr_CB_NOTIFY_LOCK4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbnotify_lock))
+ return (FALSE);
+ break;
+ case OP_CB_NOTIFY_DEVICEID:
+ if (!xdr_CB_NOTIFY_DEVICEID4args(xdrs,
+ &objp->nfs_cb_argop4_u.opcbnotify_deviceid))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_GETATTR4res(XDR *xdrs, CB_GETATTR4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->status))
+ return (FALSE);
+
+ switch (objp->status) {
+ case NFS4_OK:
+ if (!xdr_fattr4(xdrs, &objp->obj_attributes))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_RECALL4res(XDR *xdrs, CB_RECALL4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_CB_ILLEGAL4res(XDR *xdrs, CB_ILLEGAL4res *objp)
+{
+ if (!xdr_nfsstat4(xdrs, &objp->status))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_nfs_cb_resop4(XDR *xdrs, nfs_cb_resop4 *objp)
+{
+ if (!xdr_u_int(xdrs, &objp->resop))
+ return (FALSE);
+
+ switch (objp->resop) {
+ case OP_CB_GETATTR:
+ if (!xdr_CB_GETATTR4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbgetattr))
+ return (FALSE);
+ break;
+ case OP_CB_RECALL:
+ if (!xdr_CB_RECALL4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbrecall))
+ return (FALSE);
+ break;
+ case OP_CB_LAYOUTRECALL:
+ if (!xdr_CB_LAYOUTRECALL4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcblayoutrecall))
+ return (FALSE);
+ break;
+ case OP_CB_NOTIFY:
+ if (!xdr_CB_NOTIFY4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbnotify))
+ return (FALSE);
+ break;
+ case OP_CB_PUSH_DELEG:
+ if (!xdr_CB_PUSH_DELEG4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbpush_deleg))
+ return (FALSE);
+ break;
+ case OP_CB_RECALL_ANY:
+ if (!xdr_CB_RECALL_ANY4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbrecall_any))
+ return (FALSE);
+ break;
+ case OP_CB_RECALLABLE_OBJ_AVAIL:
+ if (!xdr_CB_RECALLABLE_OBJ_AVAIL4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbrecallable_obj_avail))
+ return (FALSE);
+ break;
+ case OP_CB_RECALL_SLOT:
+ if (!xdr_CB_RECALL_SLOT4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbrecall_slot))
+ return (FALSE);
+ break;
+ case OP_CB_SEQUENCE:
+ if (!xdr_CB_SEQUENCE4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbsequence))
+ return (FALSE);
+ break;
+ case OP_CB_WANTS_CANCELLED:
+ if (!xdr_CB_WANTS_CANCELLED4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbwants_cancelled))
+ return (FALSE);
+ break;
+ case OP_CB_NOTIFY_LOCK:
+ if (!xdr_CB_NOTIFY_LOCK4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbnotify_lock))
+ return (FALSE);
+ break;
+ case OP_CB_NOTIFY_DEVICEID:
+ if (!xdr_CB_NOTIFY_DEVICEID4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbnotify_deviceid))
+ return (FALSE);
+ break;
+ case OP_CB_ILLEGAL:
+ if (!xdr_CB_ILLEGAL4res(xdrs,
+ &objp->nfs_cb_resop4_u.opcbillegal))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * Additional common NFSv4 XDR
+ */
+
+bool_t
+xdr_clientid4(XDR *xdrs, clientid4 *objp)
+{
+ if (!xdr_uint64_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_component4(XDR *xdrs, component4 *objp)
+{
+ if (!xdr_utf8string(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_count4(XDR *xdrs, count4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fsid4(XDR *xdrs, fsid4 *objp)
+{
+ if (!xdr_uint64_t(xdrs, &objp->major))
+ return (FALSE);
+ if (!xdr_uint64_t(xdrs, &objp->minor))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_length4(XDR *xdrs, length4 *objp)
+{
+ if (!xdr_uint64_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_limit_by4(XDR *xdrs, limit_by4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_lock_owner4(XDR *xdrs, lock_owner4 *objp)
+{
+ if (!xdr_clientid4(xdrs, &objp->clientid))
+ return (FALSE);
+ if (!xdr_bytes(xdrs, (char **)&objp->owner_val,
+ (uint_t *)&objp->owner_len, NFS4_OPAQUE_LIMIT))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_mode4(XDR *xdrs, mode4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_netaddr4(XDR *xdrs, netaddr4 *objp)
+{
+ if (!xdr_string(xdrs, &objp->na_r_netid, ~0))
+ return (FALSE);
+ if (!xdr_string(xdrs, &objp->na_r_addr, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_nfs_cookie4(XDR *xdrs, nfs_cookie4 *objp)
+{
+ if (!xdr_uint64_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+bool_t
+xdr_nfs_modified_limit4(XDR *xdrs, nfs_modified_limit4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->num_blocks))
+ return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->bytes_per_block))
+ return (FALSE);
+ return (TRUE);
+}
+
+
+bool_t
+xdr_nfs_space_limit4(XDR *xdrs, nfs_space_limit4 *objp)
+{
+ if (!xdr_limit_by4(xdrs, &objp->limitby))
+ return (FALSE);
+ switch (objp->limitby) {
+ case NFS_LIMIT_SIZE:
+ if (!xdr_uint64_t(xdrs, &objp->nfs_space_limit4_u.filesize))
+ return (FALSE);
+ break;
+ case NFS_LIMIT_BLOCKS:
+ if (!xdr_nfs_modified_limit4(xdrs,
+ &objp->nfs_space_limit4_u.mod_blocks))
+ return (FALSE);
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_nfsstat4(XDR *xdrs, nfsstat4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_offset4(XDR *xdrs, offset4 *objp)
+{
+ if (!xdr_uint64_t(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_open_claim_type4(XDR *xdrs, open_claim_type4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_open_delegation_type4(XDR *xdrs, open_delegation_type4 *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_open_read_delegation4(XDR *xdrs, open_read_delegation4 *objp)
+{
+ if (!xdr_stateid4(xdrs, &objp->stateid))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->recall))
+ return (FALSE);
+ if (!xdr_nfsace4(xdrs, &objp->permissions))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_open_write_delegation4(XDR *xdrs, open_write_delegation4 *objp)
+{
+ if (!xdr_stateid4(xdrs, &objp->stateid))
+ return (FALSE);
+ if (!xdr_bool(xdrs, &objp->recall))
+ return (FALSE);
+ if (!xdr_nfs_space_limit4(xdrs, &objp->space_limit))
+ return (FALSE);
+ if (!xdr_nfsace4(xdrs, &objp->permissions))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_pathname4(XDR *xdrs, pathname4 *objp)
+{
+ if (!xdr_array(xdrs, (char **)&objp->pathname4_val,
+ (uint_t *)&objp->pathname4_len, ~0, sizeof (component4),
+ (xdrproc_t)xdr_component4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_sec_oid4(XDR *xdrs, sec_oid4 *objp)
+{
+ if (!xdr_bytes(xdrs, (char **)&objp->sec_oid4_val,
+ (uint_t *)&objp->sec_oid4_len, ~0))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_rpc_gss_svc_t(XDR *xdrs, rpc_gss_svc_t *objp)
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_stateid4(XDR *xdrs, stateid4 *objp)
+{
+ if (!xdr_uint32_t(xdrs, &objp->seqid))
+ return (FALSE);
+ if (!xdr_opaque(xdrs, objp->other, 12))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_utf8str_cis(XDR *xdrs, utf8str_cis *objp)
+{
+ if (!xdr_utf8string(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_utf8str_cs(XDR *xdrs, utf8str_cs *objp)
+{
+ if (!xdr_utf8string(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+/* End of additional common NFSv4 XDR */
diff --git a/usr/src/uts/common/fs/nfs/nfs_server.c b/usr/src/uts/common/fs/nfs/nfs_server.c
index b916f727d9..0071fe50c8 100644
--- a/usr/src/uts/common/fs/nfs/nfs_server.c
+++ b/usr/src/uts/common/fs/nfs/nfs_server.c
@@ -261,7 +261,6 @@ static SVC_CALLOUT_TABLE nfs_sct_rdma = {
*/
nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths;
-int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *);
bool_t rfs4_minorvers_mismatch(struct svc_req *, SVCXPRT *, void *);
/*
@@ -1056,13 +1055,13 @@ static struct rpcdisp rfsdisptab_v4[] = {
*/
/* RFS_NULL = 0 */
- {rpc_null,
+ {NULL,
xdr_void, NULL_xdrproc_t, 0,
xdr_void, NULL_xdrproc_t, 0,
nullfree, RPC_IDEMPOTENT, 0},
/* RFS4_compound = 1 */
- {rfs4_compound,
+ {NULL,
xdr_COMPOUND4args_srv, NULL_xdrproc_t, sizeof (COMPOUND4args),
xdr_COMPOUND4res_srv, NULL_xdrproc_t, sizeof (COMPOUND4res),
rfs4_compound_free, 0, 0},
diff --git a/usr/src/uts/common/fs/nfs/nfs_stats.c b/usr/src/uts/common/fs/nfs/nfs_stats.c
index 97f820d756..6dc19f67d3 100644
--- a/usr/src/uts/common/fs/nfs/nfs_stats.c
+++ b/usr/src/uts/common/fs/nfs/nfs_stats.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2020 RackTop Systems, Inc.
*/
#include <sys/types.h>
@@ -417,6 +419,25 @@ static const kstat_named_t rfsproccnt_v4_tmpl[] = {
{ "verify", KSTAT_DATA_UINT64 },
{ "write", KSTAT_DATA_UINT64 },
{ "release_lockowner", KSTAT_DATA_UINT64 },
+ { "backchannel_ctl", KSTAT_DATA_UINT64 },
+ { "bind_conn_to_session", KSTAT_DATA_UINT64 },
+ { "exchange_id", KSTAT_DATA_UINT64 },
+ { "create_session", KSTAT_DATA_UINT64 },
+ { "destroy_session", KSTAT_DATA_UINT64 },
+ { "free_stateid", KSTAT_DATA_UINT64 },
+ { "get_dir_delegation", KSTAT_DATA_UINT64 },
+ { "getdeviceinfo", KSTAT_DATA_UINT64 },
+ { "getdevicelist", KSTAT_DATA_UINT64 },
+ { "layoutcommit", KSTAT_DATA_UINT64 },
+ { "layoutget", KSTAT_DATA_UINT64 },
+ { "layoutreturn", KSTAT_DATA_UINT64 },
+ { "secinfo_no_name", KSTAT_DATA_UINT64 },
+ { "sequence", KSTAT_DATA_UINT64 },
+ { "set_ssv", KSTAT_DATA_UINT64 },
+ { "test_stateid", KSTAT_DATA_UINT64 },
+ { "want_delegation", KSTAT_DATA_UINT64 },
+ { "destroy_clientid", KSTAT_DATA_UINT64 },
+ { "reclaim_complete", KSTAT_DATA_UINT64 },
{ "illegal", KSTAT_DATA_UINT64 },
};
diff --git a/usr/src/uts/common/fs/nfs/nfs_subr.c b/usr/src/uts/common/fs/nfs/nfs_subr.c
index 68cd0df081..ee622988ab 100644
--- a/usr/src/uts/common/fs/nfs/nfs_subr.c
+++ b/usr/src/uts/common/fs/nfs/nfs_subr.c
@@ -5277,3 +5277,13 @@ do_xattr_exists_check(vnode_t *vp, ulong_t *valp, cred_t *cr)
kmem_free(dbuf, dlen);
return (0);
}
+
+/*
+ * NFS specific function that returns time since
+ * system boot in seconds.
+ */
+time_t
+nfs_sys_uptime(void)
+{
+ return (TICK_TO_SEC(ddi_get_lbolt()));
+}
diff --git a/usr/src/uts/common/nfs/Makefile b/usr/src/uts/common/nfs/Makefile
index a40eaa9939..5d9d326368 100644
--- a/usr/src/uts/common/nfs/Makefile
+++ b/usr/src/uts/common/nfs/Makefile
@@ -33,7 +33,7 @@ HDRS= export.h lm.h \
nfs_clnt.h nfs_log.h nfs_sec.h nfs4.h \
nfs4_attr.h nfs4_clnt.h rnode.h rnode4.h \
nfs4_kprot.h nfs4_db_impl.h nfs4_idmap_impl.h \
- nfsid_map.h auth.h nfs_cmd.h
+ nfsid_map.h auth.h nfs_cmd.h nfs4x.h
ROOTDIRS= $(ROOT)/usr/include/nfs
diff --git a/usr/src/uts/common/nfs/nfs.h b/usr/src/uts/common/nfs/nfs.h
index 6f76fc93ea..ace44d9dc6 100644
--- a/usr/src/uts/common/nfs/nfs.h
+++ b/usr/src/uts/common/nfs/nfs.h
@@ -2400,6 +2400,8 @@ extern mblk_t *rfs_read_alloc(uint_t, struct iovec **, int *);
extern void rfs_rndup_mblks(mblk_t *, uint_t, int);
extern void rfs_free_xuio(void *);
+extern time_t nfs_sys_uptime(void);
+
#endif /* _KERNEL */
#ifdef __cplusplus
diff --git a/usr/src/uts/common/nfs/nfs4.h b/usr/src/uts/common/nfs/nfs4.h
index 48e6194d8a..f98f0ef77d 100644
--- a/usr/src/uts/common/nfs/nfs4.h
+++ b/usr/src/uts/common/nfs/nfs4.h
@@ -47,6 +47,7 @@
#include <nfs/nfs4_attr.h>
#include <sys/acl.h>
#include <sys/list.h>
+#include <nfs/nfs4x.h>
#ifdef __cplusplus
extern "C" {
@@ -76,6 +77,12 @@ typedef struct nfs4_fhandle {
#define NFS4_MINORVERSION 0
#define CB4_MINORVERSION 0
+#define FIRST_NFS4_OP OP_ACCESS
+#define LAST_NFS40_OP OP_RELEASE_LOCKOWNER
+#define LAST_NFS41_OP OP_RECLAIM_COMPLETE
+#define LAST_NFS42_OP OP_RECLAIM_COMPLETE
+#define LAST_NFS4_OP LAST_NFS42_OP
+
/*
* Set the fattr4_change variable using a time struct. Note that change
* is 64 bits, but timestruc_t is 128 bits in a 64-bit kernel.
@@ -238,14 +245,6 @@ typedef union {
*/
typedef enum {OPENID, LOCKID, DELEGID} stateid_type_t;
-
-/*
- * Set of RPC credentials used for a particular operation.
- * Used for operations like SETCLIENTID_CONFIRM where the
- * credentials needs to match those used at SETCLIENTID.
- */
-typedef void *cred_set_t; /* For now XXX */
-
/*
* "wait" struct for use in the open open and lock owner state
* structures to provide serialization between server threads that are
@@ -364,6 +363,7 @@ typedef struct rfs4_servinst {
krwlock_t oldstate_lock;
time_t start_time;
time_t grace_period;
+ uint_t nreclaim; /* number reclaim clients */
rfs4_oldstate_t *oldstate;
struct rfs4_dss_path **dss_paths;
struct rfs4_servinst *next;
@@ -513,6 +513,7 @@ typedef struct rfs4_client {
unsigned rc_can_reclaim:1;
unsigned rc_ss_remove:1;
unsigned rc_forced_expire:1;
+ unsigned rc_reclaim_completed:1;
uint_t rc_deleg_revoked;
struct rfs4_client *rc_cp_confirmed;
time_t rc_last_access;
@@ -523,6 +524,12 @@ typedef struct rfs4_client {
rfs4_ss_pn_t *rc_ss_pn;
struct sockaddr_storage rc_addr;
rfs4_servinst_t *rc_server_instance;
+
+ /* nfsv4.1 */
+ rfs41_csr_t rc_contrived;
+ rfs41_sprot_t rc_state_prot;
+ list_t rc_sessions;
+ unsigned rc_destroying:1; /* flag: going to destroy */
} rfs4_client_t;
/*
@@ -550,7 +557,6 @@ typedef struct rfs4_clntip {
* state2confirm - what stateid4 should be used on the OPEN_CONFIRM
* open_seqid - what is the next open_seqid expected for this openowner
* oo_sw - used to serialize access to the open seqid/reply handling
- * cr_set - credential used for the OPEN
* statelist - root of state struct list associated with this openowner
* node - node for client struct list of openowners
* reply_fh - open replay processing needs the filehandle so that it is
@@ -566,7 +572,6 @@ typedef struct rfs4_openowner {
unsigned ro_postpone_confirm:1;
seqid4 ro_open_seqid;
rfs4_state_wait_t ro_sw;
- cred_set_t ro_cr_set;
list_t ro_statelist;
list_node_t ro_node;
nfs_fh4 ro_reply_fh;
@@ -854,6 +859,11 @@ typedef struct nfs4_srv {
rfs4_index_t *rfs4_deleg_idx;
rfs4_index_t *rfs4_deleg_state_idx;
+ /* nfs4.x */
+ krwlock_t findsession_lock;
+ rfs4_table_t *rfs4_session_tab;
+ rfs4_index_t *rfs4_session_idx;
+
/* client stable storage */
int rfs4_ss_enabled;
} nfs4_srv_t;
@@ -874,11 +884,10 @@ typedef struct rfs4_db_mem_cache {
kmem_cache_t *r_db_mem_cache;
} rfs4_db_mem_cache_t;
-#define RFS4_DB_MEM_CACHE_NUM 8
+#define RFS4_DB_MEM_CACHE_NUM 9
extern rfs4_db_mem_cache_t rfs4_db_mem_cache_table[RFS4_DB_MEM_CACHE_NUM];
-
extern srv_deleg_policy_t nfs4_get_deleg_policy();
extern void rfs4_servinst_create(nfs4_srv_t *, int, int, char **);
@@ -963,12 +972,16 @@ extern nfsstat4 rfs4_get_deleg_state(stateid4 *,
rfs4_deleg_state_t **);
extern nfsstat4 rfs4_get_lo_state(stateid4 *, rfs4_lo_state_t **,
bool_t);
+struct compound_state;
extern nfsstat4 rfs4_check_stateid(int, vnode_t *, stateid4 *,
bool_t, bool_t *, bool_t,
- caller_context_t *);
-extern int rfs4_check_stateid_seqid(rfs4_state_t *, stateid4 *);
+ caller_context_t *,
+ struct compound_state *);
+extern int rfs4_check_stateid_seqid(rfs4_state_t *, stateid4 *,
+ const struct compound_state *);
extern int rfs4_check_lo_stateid_seqid(rfs4_lo_state_t *,
- stateid4 *);
+ stateid4 *,
+ const struct compound_state *);
/* return values for rfs4_check_stateid_seqid() */
#define NFS4_CHECK_STATEID_OKAY 1
@@ -1210,8 +1223,29 @@ struct compound_state {
/* saved_vp != NULL */
struct svc_req *req;
char fhbuf[NFS4_FHSIZE];
+
+ /* NFSv4.1 */
+ uint8_t minorversion; /* NFS4 minor version */
+ rfs4_session_t *sp; /* OP_SEQUENCE set it */
+ slotid4 slotno;
+ rfs4_slot_t *slot;
+ rfs4_client_t *client;
+ uint16_t op_pos;
+ uint16_t op_len; /* number operations in compound req */
+#define RFS4_DISPATCH_DONE (1 << 0)
+ uint8_t cs_flags;
+ bool_t cachethis;
+ COMPOUND4res *cmpresp;
};
+typedef struct compound_state compound_state_t;
+
+static inline bool_t
+rfs4_has_session(const compound_state_t *cs)
+{
+ return (cs->slot != NULL);
+}
+
/*
* Conversion commands for nfsv4 server attr checking
*/
@@ -1237,6 +1271,7 @@ struct nfs4_svgetit_arg {
/* (if rdattr_err) */
bool_t is_referral; /* because sometimes we tell lies */
bool_t mntdfid_set;
+
fattr4_mounted_on_fileid
mounted_on_fileid;
/* readdir op can always return */
@@ -1479,13 +1514,25 @@ extern stateid4 clnt_special1;
#define CLNT_ISSPECIAL(id) (stateid4_cmp(id, &clnt_special0) || \
stateid4_cmp(id, &clnt_special1))
+/* State's functions */
+extern void rfs4_ss_clid(nfs4_srv_t *nsrv4, rfs4_client_t *);
+extern void rfs4_ss_chkclid(nfs4_srv_t *nsrv4, rfs4_client_t *);
+
+/* Declarations for nfs4.x */
+nfsstat4 do_rfs4_op_secinfo(struct compound_state *, char *, SECINFO4res *);
+
/*
* The NFS Version 4 service procedures.
*/
extern void rfs4_do_server_start(int, int, int);
extern void rfs4_compound(COMPOUND4args *, COMPOUND4res *,
- struct exportinfo *, struct svc_req *, cred_t *, int *);
+ compound_state_t *, struct svc_req *, int *);
+extern void rfs4_init_compound_state(struct compound_state *);
+extern void rfs4_fini_compound_state(struct compound_state *);
+
+struct rpcdisp;
+extern int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *);
extern void rfs4_compound_free(COMPOUND4res *);
extern void rfs4_compound_flagproc(COMPOUND4args *, int *);
diff --git a/usr/src/uts/common/nfs/nfs4_attr.h b/usr/src/uts/common/nfs/nfs4_attr.h
index 026a155abc..2b6b88ee41 100644
--- a/usr/src/uts/common/nfs/nfs4_attr.h
+++ b/usr/src/uts/common/nfs/nfs4_attr.h
@@ -94,6 +94,12 @@ extern "C" {
#define FATTR4_TIME_MODIFY_SET_MASK (1ULL << (FATTR4_WORD1 + 22))
#define FATTR4_MOUNTED_ON_FILEID_MASK (1ULL << (FATTR4_WORD1 + 23))
+/* nfsv4.1 */
+
+/* Overload to fit to 64-bits bitmap4 */
+#define FATTR4_SUPPATTR_EXCLCREAT_MASK_LOCAL (1ULL << (FATTR4_WORD1 + 24))
+#define FATTR4_SEC_LABEL_MASK_LOCAL (1ULL << (FATTR4_WORD1 + 25))
+
/*
* Common bitmap4 of file attributes to be gathered
*/
@@ -299,12 +305,20 @@ extern "C" {
FATTR4_MOUNTED_ON_FILEID_MASK \
)
+/* nfsv4.1 */
+#define RFS4_SUPPATTR_EXCLCREAT ( \
+ FATTR4_SIZE_MASK | \
+ FATTR4_MODE_MASK | \
+ FATTR4_ACL_MASK | \
+ FATTR4_OWNER_MASK | \
+ FATTR4_OWNER_GROUP_MASK | \
+ FATTR4_TIME_ACCESS_SET_MASK)
#define FATTR4_FSID_EQ(a, b) \
((a)->major == (b)->major && (a)->minor == (b)->minor)
#define NFS4_MAXNUM_BITWORDS 2
-#define NFS4_MAXNUM_ATTRS 56
+#define NFS4_MAXNUM_ATTRS 57
union nfs4_attr_u {
fattr4_supported_attrs supported_attrs;
@@ -363,6 +377,7 @@ union nfs4_attr_u {
fattr4_time_modify time_modify;
fattr4_time_modify_set time_modify_set;
fattr4_mounted_on_fileid mounted_on_fileid;
+ fattr4_suppattr_exclcreat supp_exclcreat;
};
/*
diff --git a/usr/src/uts/common/nfs/nfs4_kprot.h b/usr/src/uts/common/nfs/nfs4_kprot.h
index e3acc9b901..8311b0de3b 100644
--- a/usr/src/uts/common/nfs/nfs4_kprot.h
+++ b/usr/src/uts/common/nfs/nfs4_kprot.h
@@ -21,6 +21,7 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2020 RackTop Systems, Inc.
*/
/*
@@ -33,7 +34,7 @@
/*
* Kernel specific version.
- * NFS Version 4 protocol definitions. From nfs4_prot.x rev 1.119.
+ * NFS Version 4 protocol definitions. From nfs4_prot.x RFC 5662
*/
#ifdef __cplusplus
@@ -46,6 +47,9 @@ extern "C" {
#endif
#include <sys/stream.h>
+#include <rpc/auth_sys.h>
+typedef struct authsys_parms authsys_parms;
+
#define NFS4_FHSIZE 128
#define NFS4_VERIFIER_SIZE 8
#define NFS4_OTHER_SIZE 12
@@ -61,6 +65,8 @@ extern "C" {
#define NFS4_FATTR4_LIMIT 1048576
#define NFS4_DATA_LIMIT 134217728
+#define NFS4_SESSIONID_SIZE 16
+
enum nfs_ftype4 {
NF4REG = 1,
NF4DIR = 2,
@@ -140,7 +146,48 @@ enum nfsstat4 {
NFS4ERR_DEADLOCK = 10045,
NFS4ERR_FILE_OPEN = 10046,
NFS4ERR_ADMIN_REVOKED = 10047,
- NFS4ERR_CB_PATH_DOWN = 10048
+ NFS4ERR_CB_PATH_DOWN = 10048,
+ NFS4ERR_BADIOMODE = 10049, /* nfsv4.1 */
+ NFS4ERR_BADLAYOUT = 10050,
+ NFS4ERR_BAD_SESSION_DIGEST = 10051,
+ NFS4ERR_BADSESSION = 10052,
+ NFS4ERR_BADSLOT = 10053,
+ NFS4ERR_COMPLETE_ALREADY = 10054,
+ NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
+ NFS4ERR_DELEG_ALREADY_WANTED = 10056,
+ NFS4ERR_BACK_CHAN_BUSY = 10057,
+ NFS4ERR_LAYOUTTRYLATER = 10058,
+ NFS4ERR_LAYOUTUNAVAILABLE = 10059,
+ NFS4ERR_NOMATCHING_LAYOUT = 10060,
+ NFS4ERR_RECALLCONFLICT = 10061,
+ NFS4ERR_UNKNOWN_LAYOUTTYPE = 10062,
+ NFS4ERR_SEQ_MISORDERED = 10063,
+ NFS4ERR_SEQUENCE_POS = 10064,
+ NFS4ERR_REQ_TOO_BIG = 10065,
+ NFS4ERR_REP_TOO_BIG = 10066,
+ NFS4ERR_REP_TOO_BIG_TO_CACHE = 10067,
+ NFS4ERR_RETRY_UNCACHED_REP = 10068,
+ NFS4ERR_UNSAFE_COMPOUND = 10069,
+ NFS4ERR_TOO_MANY_OPS = 10070,
+ NFS4ERR_OP_NOT_IN_SESSION = 10071,
+ NFS4ERR_HASH_ALG_UNSUPP = 10072,
+ NFS4ERR_CLIENTID_BUSY = 10074,
+ NFS4ERR_PNFS_IO_HOLE = 10075,
+ NFS4ERR_SEQ_FALSE_RETRY = 10076,
+ NFS4ERR_BAD_HIGH_SLOT = 10077,
+ NFS4ERR_DEADSESSION = 10078,
+ NFS4ERR_ENCR_ALG_UNSUPP = 10079,
+ NFS4ERR_PNFS_NO_LAYOUT = 10080,
+ NFS4ERR_NOT_ONLY_OP = 10081,
+ NFS4ERR_WRONG_CRED = 10082,
+ NFS4ERR_WRONG_TYPE = 10083,
+ NFS4ERR_DIRDELEG_UNAVAIL = 10084,
+ NFS4ERR_REJECT_DELEG = 10085,
+ NFS4ERR_RETURNCONFLICT = 10086,
+ NFS4ERR_DELEG_REVOKED = 10087,
+
+ /* for internal use */
+ NFS4ERR_REPLAY_CACHE = 30000
};
typedef enum nfsstat4 nfsstat4;
@@ -149,6 +196,11 @@ typedef enum nfsstat4 nfsstat4;
*/
typedef uint64_t bitmap4;
+typedef struct {
+ uint_t attrlist4_len;
+ char *attrlist4_val;
+} attrlist4;
+
typedef uint64_t offset4;
typedef uint32_t count4;
@@ -161,6 +213,12 @@ typedef uint32_t nfs_lease4;
typedef uint32_t seqid4;
+typedef uint32_t sequenceid4;
+
+typedef char sessionid4[NFS4_SESSIONID_SIZE];
+
+typedef uint32_t slotid4;
+
typedef struct {
uint_t utf8string_len;
char *utf8string_val;
@@ -168,13 +226,17 @@ typedef struct {
typedef utf8string component4;
+typedef utf8string utf8str_cis;
+
+typedef utf8string utf8str_cs;
+
+typedef utf8string utf8str_mixed;
+
typedef struct {
uint_t pathname4_len;
component4 *pathname4_val;
} pathname4;
-typedef uint64_t nfs_lockid4;
-
typedef uint64_t nfs_cookie4;
typedef struct {
@@ -226,6 +288,12 @@ struct fsid4 {
};
typedef struct fsid4 fsid4;
+struct change_policy4 {
+ uint64_t cp_major;
+ uint64_t cp_minor;
+};
+typedef struct change_policy4 change_policy4;
+
struct fs_location4 {
uint_t server_len;
utf8string *server_val;
@@ -268,6 +336,8 @@ typedef uint32_t aceflag4;
#define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
#define ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020
#define ACE4_IDENTIFIER_GROUP 0x00000040
+#define ACE4_INHERITED_ACE 0x00000080
+
/*
* This defines all valid flag bits, as defined by RFC 7530. If
* any additional flag bits are deemed part of the NFSv4 spec,
@@ -295,6 +365,8 @@ typedef uint32_t acemask4;
#define ACE4_DELETE_CHILD 0x00000040
#define ACE4_READ_ATTRIBUTES 0x00000080
#define ACE4_WRITE_ATTRIBUTES 0x00000100
+#define ACE4_WRITE_RETENTION 0x00000200
+#define ACE4_WRITE_RETENTION_HOLD 0x00000400
#define ACE4_DELETE 0x00010000
#define ACE4_READ_ACL 0x00020000
#define ACE4_WRITE_ACL 0x00040000
@@ -341,6 +413,21 @@ struct nfsace4 {
utf8string who;
};
typedef struct nfsace4 nfsace4;
+
+typedef uint32_t aclflag4; /* 4.1 */
+#define ACL4_AUTO_INHERIT 0x00000001
+#define ACL4_PROTECTED 0x00000002
+#define ACL4_DEFAULTED 0x00000004
+
+struct nfsacl41 { /* 4.1 */
+ aclflag4 na41_flag;
+ struct {
+ u_int na41_aces_len;
+ nfsace4 *na41_aces_val;
+ } na41_aces;
+};
+typedef struct nfsacl41 nfsacl41;
+
#define MODE4_SUID 0x800
#define MODE4_SGID 0x400
#define MODE4_SVTX 0x200
@@ -354,6 +441,12 @@ typedef struct nfsace4 nfsace4;
#define MODE4_WOTH 0x002
#define MODE4_XOTH 0x001
+struct mode_masked4 { /* 4.1 */
+ mode4 mm_value_to_set;
+ mode4 mm_mask_bits;
+};
+typedef struct mode_masked4 mode_masked4;
+
/*
* ACL conversion helpers
*/
@@ -401,6 +494,206 @@ typedef struct specdata4 specdata4;
#define FH4_VOL_MIGRATION 0x00000004
#define FH4_VOL_RENAME 0x00000008
+/*
+ * nfsv4.1
+ */
+struct netaddr4 {
+ char *na_r_netid;
+ char *na_r_addr;
+};
+typedef struct netaddr4 netaddr4;
+
+struct nfs_impl_id4 {
+ utf8str_cis nii_domain;
+ utf8str_cs nii_name;
+ nfstime4 nii_date;
+};
+typedef struct nfs_impl_id4 nfs_impl_id4;
+
+struct stateid4 {
+ uint32_t seqid;
+ char other[NFS4_OTHER_SIZE];
+};
+typedef struct stateid4 stateid4;
+
+enum layouttype4 {
+ LAYOUT4_NFSV4_1_FILES = 0x1,
+ LAYOUT4_OSD2_OBJECTS = 0x2,
+ LAYOUT4_BLOCK_VOLUME = 0x3
+};
+typedef enum layouttype4 layouttype4;
+
+struct layout_content4 {
+ layouttype4 loc_type;
+ struct {
+ u_int loc_body_len;
+ char *loc_body_val;
+ } loc_body;
+};
+typedef struct layout_content4 layout_content4;
+
+/*
+ * LAYOUT4_OSD2_OBJECTS loc_body description
+ * is in a separate .x file
+ */
+
+/*
+ * LAYOUT4_BLOCK_VOLUME loc_body description
+ * is in a separate .x file
+ */
+
+struct layouthint4 {
+ layouttype4 loh_type;
+ struct {
+ u_int loh_body_len;
+ char *loh_body_val;
+ } loh_body;
+};
+typedef struct layouthint4 layouthint4;
+
+enum layoutiomode4 {
+ LAYOUTIOMODE4_READ = 1,
+ LAYOUTIOMODE4_RW = 2,
+ LAYOUTIOMODE4_ANY = 3
+};
+typedef enum layoutiomode4 layoutiomode4;
+
+struct layout4 {
+ offset4 lo_offset;
+ length4 lo_length;
+ layoutiomode4 lo_iomode;
+ layout_content4 lo_content;
+};
+typedef struct layout4 layout4;
+#define NFS4_DEVICEID4_SIZE 16
+
+typedef char deviceid4[NFS4_DEVICEID4_SIZE];
+
+struct device_addr4 {
+ layouttype4 da_layout_type;
+ struct {
+ u_int da_addr_body_len;
+ char *da_addr_body_val;
+ } da_addr_body;
+};
+typedef struct device_addr4 device_addr4;
+
+struct layoutupdate4 {
+ layouttype4 lou_type;
+ struct {
+ u_int lou_body_len;
+ char *lou_body_val;
+ } lou_body;
+};
+typedef struct layoutupdate4 layoutupdate4;
+
+#define LAYOUT4_RET_REC_FILE 1
+#define LAYOUT4_RET_REC_FSID 2
+#define LAYOUT4_RET_REC_ALL 3
+
+enum layoutreturn_type4 {
+ LAYOUTRETURN4_FILE = LAYOUT4_RET_REC_FILE,
+ LAYOUTRETURN4_FSID = LAYOUT4_RET_REC_FSID,
+ LAYOUTRETURN4_ALL = LAYOUT4_RET_REC_ALL
+};
+typedef enum layoutreturn_type4 layoutreturn_type4;
+
+/* layouttype4 specific data */
+
+struct layoutreturn_file4 {
+ offset4 lrf_offset;
+ length4 lrf_length;
+ stateid4 lrf_stateid;
+ struct {
+ u_int lrf_body_len;
+ char *lrf_body_val;
+ } lrf_body;
+};
+typedef struct layoutreturn_file4 layoutreturn_file4;
+
+struct layoutreturn4 {
+ layoutreturn_type4 lr_returntype;
+ union {
+ layoutreturn_file4 lr_layout;
+ } layoutreturn4_u;
+};
+typedef struct layoutreturn4 layoutreturn4;
+
+enum fs4_status_type {
+ STATUS4_FIXED = 1,
+ STATUS4_UPDATED = 2,
+ STATUS4_VERSIONED = 3,
+ STATUS4_WRITABLE = 4,
+ STATUS4_REFERRAL = 5
+};
+typedef enum fs4_status_type fs4_status_type;
+
+struct fs4_status {
+ bool_t fss_absent;
+ fs4_status_type fss_type;
+ utf8str_cs fss_source;
+ utf8str_cs fss_current;
+ int32_t fss_age;
+ nfstime4 fss_version;
+};
+typedef struct fs4_status fs4_status;
+
+#define TH4_READ_SIZE 0
+#define TH4_WRITE_SIZE 1
+#define TH4_READ_IOSIZE 2
+#define TH4_WRITE_IOSIZE 3
+
+typedef length4 threshold4_read_size;
+
+typedef length4 threshold4_write_size;
+
+typedef length4 threshold4_read_iosize;
+
+typedef length4 threshold4_write_iosize;
+
+struct threshold_item4 {
+ layouttype4 thi_layout_type;
+ bitmap4 thi_hintset;
+ struct {
+ u_int thi_hintlist_len;
+ char *thi_hintlist_val;
+ } thi_hintlist;
+};
+typedef struct threshold_item4 threshold_item4;
+
+struct mdsthreshold4 {
+ struct {
+ u_int mth_hints_len;
+ threshold_item4 *mth_hints_val;
+ } mth_hints;
+};
+typedef struct mdsthreshold4 mdsthreshold4;
+#define RET4_DURATION_INFINITE 0xffffffffffffffff
+
+struct retention_get4 {
+ uint64_t rg_duration;
+ struct {
+ u_int rg_begin_time_len;
+ nfstime4 *rg_begin_time_val;
+ } rg_begin_time;
+};
+typedef struct retention_get4 retention_get4;
+
+struct retention_set4 {
+ bool_t rs_enable;
+ struct {
+ u_int rs_duration_len;
+ uint64_t *rs_duration_val;
+ } rs_duration;
+};
+typedef struct retention_set4 retention_set4;
+#define FSCHARSET_CAP4_CONTAINS_NON_UTF8 0x1
+#define FSCHARSET_CAP4_ALLOWS_ONLY_UTF8 0x2
+
+typedef uint32_t fs_charset_cap4;
+
+/* nfsv4.1 end */
+
typedef bitmap4 fattr4_supported_attrs;
typedef nfs_ftype4 fattr4_type;
@@ -472,6 +765,8 @@ typedef ascii_REQUIRED4 fattr4_mimetype;
typedef mode4 fattr4_mode;
+typedef mode_masked4 fattr4_mode_set_masked;
+
typedef uint64_t fattr4_mounted_on_fileid;
typedef bool_t fattr4_no_trunc;
@@ -515,6 +810,57 @@ typedef nfstime4 fattr4_time_metadata;
typedef nfstime4 fattr4_time_modify;
typedef settime4 fattr4_time_modify_set;
+
+/* nfsv4.1 */
+typedef bitmap4 fattr4_suppattr_exclcreat;
+
+typedef nfstime4 fattr4_dir_notif_delay;
+
+typedef nfstime4 fattr4_dirent_notif_delay;
+
+typedef struct {
+ u_int fattr4_fs_layout_types_len;
+ layouttype4 *fattr4_fs_layout_types_val;
+} fattr4_fs_layout_types;
+
+typedef fs4_status fattr4_fs_status;
+
+typedef fs_charset_cap4 fattr4_fs_charset_cap;
+
+typedef uint32_t fattr4_layout_alignment;
+
+typedef uint32_t fattr4_layout_blksize;
+
+typedef layouthint4 fattr4_layout_hint;
+
+typedef struct {
+ u_int fattr4_layout_types_len;
+ layouttype4 *fattr4_layout_types_val;
+} fattr4_layout_types;
+
+typedef mdsthreshold4 fattr4_mdsthreshold;
+
+typedef retention_get4 fattr4_retention_get;
+
+typedef retention_set4 fattr4_retention_set;
+
+typedef retention_get4 fattr4_retentevt_get;
+
+typedef retention_set4 fattr4_retentevt_set;
+
+typedef uint64_t fattr4_retention_hold;
+
+typedef nfsacl41 fattr4_dacl;
+
+typedef nfsacl41 fattr4_sacl;
+
+typedef change_policy4 fattr4_change_policy;
+
+/* nfsv4.1 end */
+
+/*
+ * REQUIRED Attributes
+ */
#define FATTR4_SUPPORTED_ATTRS 0
#define FATTR4_TYPE 1
#define FATTR4_FH_EXPIRE_TYPE 2
@@ -528,6 +874,12 @@ typedef settime4 fattr4_time_modify_set;
#define FATTR4_LEASE_TIME 10
#define FATTR4_RDATTR_ERROR 11
#define FATTR4_FILEHANDLE 19
+/* new to NFSV4.1 */
+#define FATTR4_SUPPATTR_EXCLCREAT 75
+
+/*
+ * RECOMMENDED Attributes
+ */
#define FATTR4_ACL 12
#define FATTR4_ACLSUPPORT 13
#define FATTR4_ARCHIVE 14
@@ -572,6 +924,32 @@ typedef settime4 fattr4_time_modify_set;
#define FATTR4_TIME_MODIFY_SET 54
#define FATTR4_MOUNTED_ON_FILEID 55
+/* new to NFSV4.1 */
+#define FATTR4_DIR_NOTIF_DELAY 56
+#define FATTR4_DIRENT_NOTIF_DELAY 57
+#define FATTR4_DACL 58
+#define FATTR4_SACL 59
+#define FATTR4_CHANGE_POLICY 60
+#define FATTR4_FS_STATUS 61
+#define FATTR4_FS_LAYOUT_TYPES 62
+#define FATTR4_LAYOUT_HINT 63
+#define FATTR4_LAYOUT_TYPES 64
+#define FATTR4_LAYOUT_BLKSIZE 65
+#define FATTR4_LAYOUT_ALIGNMENT 66
+#define FATTR4_FS_LOCATIONS_INFO 67
+#define FATTR4_MDSTHRESHOLD 68
+#define FATTR4_RETENTION_GET 69
+#define FATTR4_RETENTION_SET 70
+#define FATTR4_RETENTEVT_GET 71
+#define FATTR4_RETENTEVT_SET 72
+#define FATTR4_RETENTION_HOLD 73
+#define FATTR4_MODE_SET_MASKED 74
+#define FATTR4_SUPPATTR_EXCLCREAT 75
+#define FATTR4_FS_CHARSET_CAP 76
+
+/* new to NFSv4.2 */
+#define FATTR4_SEC_LABEL 80
+
struct fattr4 {
bitmap4 attrmask;
char *attrlist4;
@@ -598,12 +976,6 @@ struct cb_client4 {
};
typedef struct cb_client4 cb_client4;
-struct stateid4 {
- uint32_t seqid;
- char other[NFS4_OTHER_SIZE];
-};
-typedef struct stateid4 stateid4;
-
struct nfs_client_id4 {
verifier4 verifier;
uint_t id_len;
@@ -612,6 +984,33 @@ struct nfs_client_id4 {
};
typedef struct nfs_client_id4 nfs_client_id4;
+struct client_owner4 {
+ verifier4 co_verifier;
+ struct {
+ u_int co_ownerid_len;
+ char *co_ownerid_val;
+ } co_ownerid;
+};
+typedef struct client_owner4 client_owner4;
+
+struct server_owner4 {
+ uint64_t so_minor_id;
+ struct {
+ u_int so_major_id_len;
+ char *so_major_id_val;
+ } so_major_id;
+};
+typedef struct server_owner4 server_owner4;
+
+struct state_owner4 {
+ clientid4 clientid;
+ struct {
+ uint_t owner_len;
+ char *owner_val;
+ } owner;
+};
+typedef struct state_owner4 state_owner4;
+
struct open_owner4 {
clientid4 clientid;
uint_t owner_len;
@@ -633,6 +1032,207 @@ enum nfs_lock_type4 {
WRITEW_LT = 4
};
typedef enum nfs_lock_type4 nfs_lock_type4;
+
+/*
+ * nfsv4.1
+ */
+
+/* Input for computing subkeys */
+
+enum ssv_subkey4 {
+ SSV4_SUBKEY_MIC_I2T = 1,
+ SSV4_SUBKEY_MIC_T2I = 2,
+ SSV4_SUBKEY_SEAL_I2T = 3,
+ SSV4_SUBKEY_SEAL_T2I = 4
+};
+typedef enum ssv_subkey4 ssv_subkey4;
+
+/* Input for computing smt_hmac */
+
+struct ssv_mic_plain_tkn4 {
+ uint32_t smpt_ssv_seq;
+ struct {
+ u_int smpt_orig_plain_len;
+ char *smpt_orig_plain_val;
+ } smpt_orig_plain;
+};
+typedef struct ssv_mic_plain_tkn4 ssv_mic_plain_tkn4;
+
+/* SSV GSS PerMsgToken token */
+
+struct ssv_mic_tkn4 {
+ uint32_t smt_ssv_seq;
+ struct {
+ u_int smt_hmac_len;
+ char *smt_hmac_val;
+ } smt_hmac;
+};
+typedef struct ssv_mic_tkn4 ssv_mic_tkn4;
+
+/* Input for computing ssct_encr_data and ssct_hmac */
+
+struct ssv_seal_plain_tkn4 {
+ struct {
+ u_int sspt_confounder_len;
+ char *sspt_confounder_val;
+ } sspt_confounder;
+ uint32_t sspt_ssv_seq;
+ struct {
+ u_int sspt_orig_plain_len;
+ char *sspt_orig_plain_val;
+ } sspt_orig_plain;
+ struct {
+ u_int sspt_pad_len;
+ char *sspt_pad_val;
+ } sspt_pad;
+};
+typedef struct ssv_seal_plain_tkn4 ssv_seal_plain_tkn4;
+
+/* SSV GSS SealedMessage token */
+
+struct ssv_seal_cipher_tkn4 {
+ uint32_t ssct_ssv_seq;
+ struct {
+ u_int ssct_iv_len;
+ char *ssct_iv_val;
+ } ssct_iv;
+ struct {
+ u_int ssct_encr_data_len;
+ char *ssct_encr_data_val;
+ } ssct_encr_data;
+ struct {
+ u_int ssct_hmac_len;
+ char *ssct_hmac_val;
+ } ssct_hmac;
+};
+typedef struct ssv_seal_cipher_tkn4 ssv_seal_cipher_tkn4;
+
+struct fs_locations_server4 {
+ int32_t fls_currency;
+ struct {
+ u_int fls_info_len;
+ char *fls_info_val;
+ } fls_info;
+ utf8str_cis fls_server;
+};
+typedef struct fs_locations_server4 fs_locations_server4;
+#define FSLI4BX_GFLAGS 0
+#define FSLI4BX_TFLAGS 1
+#define FSLI4BX_CLSIMUL 2
+#define FSLI4BX_CLHANDLE 3
+#define FSLI4BX_CLFILEID 4
+#define FSLI4BX_CLWRITEVER 5
+#define FSLI4BX_CLCHANGE 6
+#define FSLI4BX_CLREADDIR 7
+#define FSLI4BX_READRANK 8
+#define FSLI4BX_WRITERANK 9
+#define FSLI4BX_READORDER 10
+#define FSLI4BX_WRITEORDER 11
+#define FSLI4GF_WRITABLE 0x01
+#define FSLI4GF_CUR_REQ 0x02
+#define FSLI4GF_ABSENT 0x04
+#define FSLI4GF_GOING 0x08
+#define FSLI4GF_SPLIT 0x10
+#define FSLI4TF_RDMA 0x01
+
+struct fs_locations_item4 {
+ struct {
+ u_int fli_entries_len;
+ fs_locations_server4 *fli_entries_val;
+ } fli_entries;
+ pathname4 fli_rootpath;
+};
+typedef struct fs_locations_item4 fs_locations_item4;
+
+struct fs_locations_info4 {
+ uint32_t fli_flags;
+ int32_t fli_valid_for;
+ pathname4 fli_fs_root;
+ struct {
+ u_int fli_items_len;
+ fs_locations_item4 *fli_items_val;
+ } fli_items;
+};
+typedef struct fs_locations_info4 fs_locations_info4;
+#define FSLI4IF_VAR_SUB 0x00000001
+
+typedef fs_locations_info4 fattr4_fs_locations_info;
+#define NFL4_UFLG_MASK 0x0000003F
+#define NFL4_UFLG_DENSE 0x00000001
+#define NFL4_UFLG_COMMIT_THRU_MDS 0x00000002
+#define NFL4_UFLG_STRIPE_UNIT_SIZE_MASK 0xFFFFFFC0
+
+typedef uint32_t nfl_util4;
+
+enum filelayout_hint_care4 {
+ NFLH4_CARE_DENSE = NFL4_UFLG_DENSE,
+ NFLH4_CARE_COMMIT_THRU_MDS = NFL4_UFLG_COMMIT_THRU_MDS,
+ NFLH4_CARE_STRIPE_UNIT_SIZE = 0x00000040,
+ NFLH4_CARE_STRIPE_COUNT = 0x00000080
+};
+typedef enum filelayout_hint_care4 filelayout_hint_care4;
+
+/* Encoded in the loh_body field of data type layouthint4: */
+
+struct nfsv4_1_file_layouthint4 {
+ uint32_t nflh_care;
+ nfl_util4 nflh_util;
+ count4 nflh_stripe_count;
+};
+typedef struct nfsv4_1_file_layouthint4 nfsv4_1_file_layouthint4;
+
+typedef struct {
+ u_int multipath_list4_len;
+ netaddr4 *multipath_list4_val;
+} multipath_list4;
+
+/*
+ * Encoded in the da_addr_body field of
+ * data type device_addr4:
+ */
+
+struct nfsv4_1_file_layout_ds_addr4 {
+ struct {
+ u_int nflda_stripe_indices_len;
+ uint32_t *nflda_stripe_indices_val;
+ } nflda_stripe_indices;
+ struct {
+ u_int nflda_multipath_ds_list_len;
+ multipath_list4 *nflda_multipath_ds_list_val;
+ } nflda_multipath_ds_list;
+};
+typedef struct nfsv4_1_file_layout_ds_addr4 nfsv4_1_file_layout_ds_addr4;
+
+/*
+ * Encoded in the loc_body field of
+ * data type layout_content4:
+ */
+
+struct nfsv4_1_file_layout4 {
+ deviceid4 nfl_deviceid;
+ nfl_util4 nfl_util;
+ uint32_t nfl_first_stripe_index;
+ offset4 nfl_pattern_offset;
+ struct {
+ u_int nfl_fh_list_len;
+ nfs_fh4 *nfl_fh_list_val;
+ } nfl_fh_list;
+};
+typedef struct nfsv4_1_file_layout4 nfsv4_1_file_layout4;
+
+/*
+ * Encoded in the lou_body field of data type layoutupdate4:
+ * Nothing. lou_body is a zero length array of bytes.
+ */
+
+/*
+ * Encoded in the lrf_body field of
+ * data type layoutreturn_file4:
+ * Nothing. lrf_body is a zero length array of bytes.
+ */
+
+/* nfsv4.1 end */
+
#define ACCESS4_READ 0x00000001
#define ACCESS4_LOOKUP 0x00000002
#define ACCESS4_MODIFY 0x00000004
@@ -892,16 +1492,41 @@ typedef struct NVERIFY4res NVERIFY4res;
enum createmode4 {
UNCHECKED4 = 0,
GUARDED4 = 1,
- EXCLUSIVE4 = 2
+ EXCLUSIVE4 = 2,
+ EXCLUSIVE4_1 = 3
};
typedef enum createmode4 createmode4;
+struct creatverfattr {
+ verifier4 cva_verf;
+ fattr4 cva_attrs;
+};
+typedef struct creatverfattr creatverfattr;
+
+struct createhow4 {
+ createmode4 mode;
+ union {
+ fattr4 createattrs;
+ verifier4 createverf;
+ creatverfattr ch_createboth;
+ } createhow4_u;
+};
+typedef struct createhow4 createhow4;
+
enum opentype4 {
OPEN4_NOCREATE = 0,
OPEN4_CREATE = 1
};
typedef enum opentype4 opentype4;
+struct openflag4 {
+ opentype4 opentype;
+ union {
+ createhow4 how;
+ } openflag4_u;
+};
+typedef struct openflag4 openflag4;
+
enum limit_by4 {
NFS_LIMIT_SIZE = 1,
NFS_LIMIT_BLOCKS = 2
@@ -922,6 +1547,8 @@ struct nfs_space_limit4 {
} nfs_space_limit4_u;
};
typedef struct nfs_space_limit4 nfs_space_limit4;
+
+#define OPEN4_SHARE_ACCESS_MASK 0x00FF
#define OPEN4_SHARE_ACCESS_READ 0x00000001
#define OPEN4_SHARE_ACCESS_WRITE 0x00000002
#define OPEN4_SHARE_ACCESS_BOTH 0x00000003
@@ -929,11 +1556,24 @@ typedef struct nfs_space_limit4 nfs_space_limit4;
#define OPEN4_SHARE_DENY_READ 0x00000001
#define OPEN4_SHARE_DENY_WRITE 0x00000002
#define OPEN4_SHARE_DENY_BOTH 0x00000003
+/* nfsv4.1 */
+#define OPEN4_SHARE_WANT_MASK 0xFF00
+#define OPEN4_SHARE_WANT_NO_PREFERENCE 0x0000
+#define OPEN4_SHARE_WANT_READ_DELEG 0x0100
+#define OPEN4_SHARE_WANT_WRITE_DELEG 0x0200
+#define OPEN4_SHARE_WANT_ANY_DELEG 0x0300
+#define OPEN4_SHARE_WANT_NO_DELEG 0x0400
+#define OPEN4_SHARE_WANT_CANCEL 0x0500
+
+#define OPEN4_SHARE_WHEN_MASK 0xF0000
+#define OPEN4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000
+#define OPEN4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED 0x20000
enum open_delegation_type4 {
OPEN_DELEGATE_NONE = 0,
OPEN_DELEGATE_READ = 1,
- OPEN_DELEGATE_WRITE = 2
+ OPEN_DELEGATE_WRITE = 2,
+ OPEN_DELEGATE_NONE_EXT = 3
};
typedef enum open_delegation_type4 open_delegation_type4;
@@ -941,7 +1581,10 @@ enum open_claim_type4 {
CLAIM_NULL = 0,
CLAIM_PREVIOUS = 1,
CLAIM_DELEGATE_CUR = 2,
- CLAIM_DELEGATE_PREV = 3
+ CLAIM_DELEGATE_PREV = 3,
+ CLAIM_FH = 4,
+ CLAIM_DELEG_CUR_FH = 5,
+ CLAIM_DELEG_PREV_FH = 6
};
typedef enum open_claim_type4 open_claim_type4;
@@ -957,9 +1600,22 @@ struct copen_claim_delegate_cur4 {
};
typedef struct copen_claim_delegate_cur4 copen_claim_delegate_cur4;
+struct open_claim4 {
+ open_claim_type4 claim;
+ union {
+ component4 file;
+ open_delegation_type4 delegate_type;
+ open_claim_delegate_cur4 delegate_cur_info;
+ component4 file_delegate_prev;
+ stateid4 oc_delegate_stateid;
+ } open_claim4_u;
+};
+typedef struct open_claim4 open_claim4;
+
struct OPEN4args {
seqid4 seqid;
uint32_t share_access;
+ uint32_t deleg_want; /* nfsv4.1 */
uint32_t share_deny;
open_owner4 owner;
opentype4 opentype;
@@ -967,14 +1623,9 @@ struct OPEN4args {
union {
fattr4 createattrs;
verifier4 createverf;
+ creatverfattr ch_createboth; /* for nfsv4.1 */
} createhow4_u;
- open_claim_type4 claim;
- union {
- component4 file;
- open_delegation_type4 delegate_type;
- open_claim_delegate_cur4 delegate_cur_info;
- component4 file_delegate_prev;
- } open_claim4_u;
+ open_claim4 claim;
};
typedef struct OPEN4args OPEN4args;
@@ -1014,16 +1665,44 @@ struct open_write_delegation4 {
};
typedef struct open_write_delegation4 open_write_delegation4;
+/* nfsv4.1 */
+enum why_no_delegation4 {
+ WND4_NOT_WANTED = 0,
+ WND4_CONTENTION = 1,
+ WND4_RESOURCE = 2,
+ WND4_NOT_SUPP_FTYPE = 3,
+ WND4_WRITE_DELEG_NOT_SUPP_FTYPE = 4,
+ WND4_NOT_SUPP_UPGRADE = 5,
+ WND4_NOT_SUPP_DOWNGRADE = 6,
+ WND4_CANCELLED = 7,
+ WND4_IS_DIR = 8
+};
+typedef enum why_no_delegation4 why_no_delegation4;
+
+struct open_none_delegation4 {
+ why_no_delegation4 ond_why;
+ union {
+ bool_t ond_server_will_push_deleg;
+ bool_t ond_server_will_signal_avail;
+ } open_none_delegation4_u;
+};
+typedef struct open_none_delegation4 open_none_delegation4;
+
+/* nfsv4.1 end */
+
struct open_delegation4 {
open_delegation_type4 delegation_type;
union {
open_read_delegation4 read;
open_write_delegation4 write;
+ open_none_delegation4 od_whynone; /* nfsv4.1 */
} open_delegation4_u;
};
typedef struct open_delegation4 open_delegation4;
#define OPEN4_RESULT_CONFIRM 0x00000002
#define OPEN4_RESULT_LOCKTYPE_POSIX 0x00000004
+#define OPEN4_RESULT_PRESERVE_UNLINKED 0x00000008 /* nfsv4.1 */
+#define OPEN4_RESULT_MAY_NOTIFY_LOCK 0x00000020 /* nfsv4.1 */
struct OPEN4res {
nfsstat4 status;
@@ -1061,6 +1740,7 @@ struct OPEN_DOWNGRADE4args {
stateid4 open_stateid;
seqid4 seqid;
uint32_t share_access;
+ uint32_t deleg_want; /* nfsv4.1 */
uint32_t share_deny;
};
typedef struct OPEN_DOWNGRADE4args OPEN_DOWNGRADE4args;
@@ -1365,6 +2045,616 @@ struct ILLEGAL4res {
};
typedef struct ILLEGAL4res ILLEGAL4res;
+/*
+ * New operations for nfsv4.1
+ */
+typedef struct {
+ u_int gsshandle4_t_len;
+ char *gsshandle4_t_val;
+} gsshandle4_t;
+
+struct gss_cb_handles4 {
+ rpc_gss_svc_t gcbp_service;
+ gsshandle4_t gcbp_handle_from_server;
+ gsshandle4_t gcbp_handle_from_client;
+};
+typedef struct gss_cb_handles4 gss_cb_handles4;
+
+struct callback_sec_parms4 {
+ uint32_t cb_secflavor;
+ union {
+ authsys_parms cbsp_sys_cred;
+ gss_cb_handles4 cbsp_gss_handles;
+ } callback_sec_parms4_u;
+};
+typedef struct callback_sec_parms4 callback_sec_parms4;
+
+struct BACKCHANNEL_CTL4args {
+ uint32_t bca_cb_program;
+ struct {
+ u_int bca_sec_parms_len;
+ callback_sec_parms4 *bca_sec_parms_val;
+ } bca_sec_parms;
+};
+typedef struct BACKCHANNEL_CTL4args BACKCHANNEL_CTL4args;
+
+struct BACKCHANNEL_CTL4res {
+ nfsstat4 bcr_status;
+};
+typedef struct BACKCHANNEL_CTL4res BACKCHANNEL_CTL4res;
+
+enum channel_dir_from_client4 {
+ CDFC4_FORE = 0x1,
+ CDFC4_BACK = 0x2,
+ CDFC4_FORE_OR_BOTH = 0x3,
+ CDFC4_BACK_OR_BOTH = 0x7
+};
+typedef enum channel_dir_from_client4 channel_dir_from_client4;
+
+struct BIND_CONN_TO_SESSION4args {
+ sessionid4 bctsa_sessid;
+ channel_dir_from_client4 bctsa_dir;
+ bool_t bctsa_use_conn_in_rdma_mode;
+};
+typedef struct BIND_CONN_TO_SESSION4args BIND_CONN_TO_SESSION4args;
+
+enum channel_dir_from_server4 {
+ CDFS4_FORE = 0x1,
+ CDFS4_BACK = 0x2,
+ CDFS4_BOTH = 0x3
+};
+typedef enum channel_dir_from_server4 channel_dir_from_server4;
+
+struct BIND_CONN_TO_SESSION4resok {
+ sessionid4 bctsr_sessid;
+ channel_dir_from_server4 bctsr_dir;
+ bool_t bctsr_use_conn_in_rdma_mode;
+};
+typedef struct BIND_CONN_TO_SESSION4resok BIND_CONN_TO_SESSION4resok;
+
+struct BIND_CONN_TO_SESSION4res {
+ nfsstat4 bctsr_status;
+ union {
+ BIND_CONN_TO_SESSION4resok bctsr_resok4;
+ } BIND_CONN_TO_SESSION4res_u;
+};
+typedef struct BIND_CONN_TO_SESSION4res BIND_CONN_TO_SESSION4res;
+
+#define EXCHGID4_FLAG_SUPP_MOVED_REFER 0x00000001
+#define EXCHGID4_FLAG_SUPP_MOVED_MIGR 0x00000002
+#define EXCHGID4_FLAG_BIND_PRINC_STATEID 0x00000100
+
+#define EXCHGID4_FLAG_USE_NON_PNFS 0x00010000
+#define EXCHGID4_FLAG_USE_PNFS_MDS 0x00020000
+#define EXCHGID4_FLAG_USE_PNFS_DS 0x00040000
+#define EXCHGID4_FLAG_MASK_PNFS 0x00070000
+
+#define EXCHGID4_FLAG_UPD_CONFIRMED_REC_A 0x40000000
+#define EXCHGID4_FLAG_CONFIRMED_R 0x80000000
+
+#define EXID4_FLAG_MASK 0x40070103
+
+struct state_protect_ops4 {
+ bitmap4 spo_must_enforce;
+ bitmap4 spo_must_allow;
+};
+typedef struct state_protect_ops4 state_protect_ops4;
+
+struct ssv_sp_parms4 {
+ state_protect_ops4 ssp_ops;
+ struct {
+ u_int ssp_hash_algs_len;
+ sec_oid4 *ssp_hash_algs_val;
+ } ssp_hash_algs;
+ struct {
+ u_int ssp_encr_algs_len;
+ sec_oid4 *ssp_encr_algs_val;
+ } ssp_encr_algs;
+ uint32_t ssp_window;
+ uint32_t ssp_num_gss_handles;
+};
+typedef struct ssv_sp_parms4 ssv_sp_parms4;
+
+enum state_protect_how4 {
+ SP4_NONE = 0,
+ SP4_MACH_CRED = 1,
+ SP4_SSV = 2
+};
+typedef enum state_protect_how4 state_protect_how4;
+
+struct state_protect4_a {
+ state_protect_how4 spa_how;
+ union {
+ state_protect_ops4 spa_mach_ops;
+ ssv_sp_parms4 spa_ssv_parms;
+ } state_protect4_a_u;
+};
+typedef struct state_protect4_a state_protect4_a;
+
+struct EXCHANGE_ID4args {
+ client_owner4 eia_clientowner;
+ uint32_t eia_flags;
+ state_protect4_a eia_state_protect;
+ struct {
+ u_int eia_client_impl_id_len;
+ nfs_impl_id4 *eia_client_impl_id_val;
+ } eia_client_impl_id;
+};
+typedef struct EXCHANGE_ID4args EXCHANGE_ID4args;
+
+struct ssv_prot_info4 {
+ state_protect_ops4 spi_ops;
+ uint32_t spi_hash_alg;
+ uint32_t spi_encr_alg;
+ uint32_t spi_ssv_len;
+ uint32_t spi_window;
+ struct {
+ u_int spi_handles_len;
+ gsshandle4_t *spi_handles_val;
+ } spi_handles;
+};
+typedef struct ssv_prot_info4 ssv_prot_info4;
+
+struct state_protect4_r {
+ state_protect_how4 spr_how;
+ union {
+ state_protect_ops4 spr_mach_ops;
+ ssv_prot_info4 spr_ssv_info;
+ } state_protect4_r_u;
+};
+typedef struct state_protect4_r state_protect4_r;
+
+struct EXCHANGE_ID4resok {
+ clientid4 eir_clientid;
+ sequenceid4 eir_sequenceid;
+ uint32_t eir_flags;
+ state_protect4_r eir_state_protect;
+ server_owner4 eir_server_owner;
+ struct eir_server_scope {
+ u_int eir_server_scope_len;
+ char *eir_server_scope_val;
+ } eir_server_scope;
+ struct {
+ u_int eir_server_impl_id_len;
+ nfs_impl_id4 *eir_server_impl_id_val;
+ } eir_server_impl_id;
+};
+typedef struct EXCHANGE_ID4resok EXCHANGE_ID4resok;
+
+struct EXCHANGE_ID4res {
+ nfsstat4 eir_status;
+ union {
+ EXCHANGE_ID4resok eir_resok4;
+ } EXCHANGE_ID4res_u;
+};
+typedef struct EXCHANGE_ID4res EXCHANGE_ID4res;
+
+struct channel_attrs4 {
+ count4 ca_headerpadsize;
+ count4 ca_maxrequestsize;
+ count4 ca_maxresponsesize;
+ count4 ca_maxresponsesize_cached;
+ count4 ca_maxoperations;
+ count4 ca_maxrequests;
+ struct {
+ u_int ca_rdma_ird_len;
+ uint32_t *ca_rdma_ird_val;
+ } ca_rdma_ird;
+};
+typedef struct channel_attrs4 channel_attrs4;
+
+#define CREATE_SESSION4_FLAG_PERSIST 0x00000001
+#define CREATE_SESSION4_FLAG_CONN_BACK_CHAN 0x00000002
+#define CREATE_SESSION4_FLAG_CONN_RDMA 0x00000004
+
+#define CREATE_SESSION4_FLAG_MASK 0x07
+
+struct CREATE_SESSION4args {
+ clientid4 csa_clientid;
+ sequenceid4 csa_sequence;
+ uint32_t csa_flags;
+ channel_attrs4 csa_fore_chan_attrs;
+ channel_attrs4 csa_back_chan_attrs;
+ uint32_t csa_cb_program;
+ struct {
+ u_int csa_sec_parms_len;
+ callback_sec_parms4 *csa_sec_parms_val;
+ } csa_sec_parms;
+};
+typedef struct CREATE_SESSION4args CREATE_SESSION4args;
+
+struct CREATE_SESSION4resok {
+ sessionid4 csr_sessionid;
+ sequenceid4 csr_sequence;
+ uint32_t csr_flags;
+ channel_attrs4 csr_fore_chan_attrs;
+ channel_attrs4 csr_back_chan_attrs;
+};
+typedef struct CREATE_SESSION4resok CREATE_SESSION4resok;
+
+struct CREATE_SESSION4res {
+ nfsstat4 csr_status;
+ union {
+ CREATE_SESSION4resok csr_resok4;
+ } CREATE_SESSION4res_u;
+};
+typedef struct CREATE_SESSION4res CREATE_SESSION4res;
+
+struct DESTROY_SESSION4args {
+ sessionid4 dsa_sessionid;
+};
+typedef struct DESTROY_SESSION4args DESTROY_SESSION4args;
+
+struct DESTROY_SESSION4res {
+ nfsstat4 dsr_status;
+};
+typedef struct DESTROY_SESSION4res DESTROY_SESSION4res;
+
+struct FREE_STATEID4args {
+ stateid4 fsa_stateid;
+};
+typedef struct FREE_STATEID4args FREE_STATEID4args;
+
+struct FREE_STATEID4res {
+ nfsstat4 fsr_status;
+};
+typedef struct FREE_STATEID4res FREE_STATEID4res;
+
+typedef nfstime4 attr_notice4;
+
+struct GET_DIR_DELEGATION4args {
+ bool_t gdda_signal_deleg_avail;
+ bitmap4 gdda_notification_types;
+ attr_notice4 gdda_child_attr_delay;
+ attr_notice4 gdda_dir_attr_delay;
+ bitmap4 gdda_child_attributes;
+ bitmap4 gdda_dir_attributes;
+};
+typedef struct GET_DIR_DELEGATION4args GET_DIR_DELEGATION4args;
+
+struct GET_DIR_DELEGATION4resok {
+ verifier4 gddr_cookieverf;
+ stateid4 gddr_stateid;
+ bitmap4 gddr_notification;
+ bitmap4 gddr_child_attributes;
+ bitmap4 gddr_dir_attributes;
+};
+typedef struct GET_DIR_DELEGATION4resok GET_DIR_DELEGATION4resok;
+
+enum gddrnf4_status {
+ GDD4_OK = 0,
+ GDD4_UNAVAIL = 1
+};
+typedef enum gddrnf4_status gddrnf4_status;
+
+struct GET_DIR_DELEGATION4res_non_fatal {
+ gddrnf4_status gddrnf_status;
+ union {
+ GET_DIR_DELEGATION4resok gddrnf_resok4;
+ bool_t gddrnf_will_signal_deleg_avail;
+ } GET_DIR_DELEGATION4res_non_fatal_u;
+};
+typedef struct GET_DIR_DELEGATION4res_non_fatal
+ GET_DIR_DELEGATION4res_non_fatal;
+
+struct GET_DIR_DELEGATION4res {
+ nfsstat4 gddr_status;
+ union {
+ GET_DIR_DELEGATION4res_non_fatal gddr_res_non_fatal4;
+ } GET_DIR_DELEGATION4res_u;
+};
+typedef struct GET_DIR_DELEGATION4res GET_DIR_DELEGATION4res;
+
+struct GETDEVICEINFO4args {
+ deviceid4 gdia_device_id;
+ layouttype4 gdia_layout_type;
+ count4 gdia_maxcount;
+ bitmap4 gdia_notify_types;
+};
+typedef struct GETDEVICEINFO4args GETDEVICEINFO4args;
+
+struct GETDEVICEINFO4resok {
+ device_addr4 gdir_device_addr;
+ bitmap4 gdir_notification;
+};
+typedef struct GETDEVICEINFO4resok GETDEVICEINFO4resok;
+
+struct GETDEVICEINFO4res {
+ nfsstat4 gdir_status;
+ union {
+ GETDEVICEINFO4resok gdir_resok4;
+ count4 gdir_mincount;
+ } GETDEVICEINFO4res_u;
+};
+typedef struct GETDEVICEINFO4res GETDEVICEINFO4res;
+
+struct GETDEVICELIST4args {
+ layouttype4 gdla_layout_type;
+ count4 gdla_maxdevices;
+ nfs_cookie4 gdla_cookie;
+ verifier4 gdla_cookieverf;
+};
+typedef struct GETDEVICELIST4args GETDEVICELIST4args;
+
+struct GETDEVICELIST4resok {
+ nfs_cookie4 gdlr_cookie;
+ verifier4 gdlr_cookieverf;
+ struct {
+ u_int gdlr_deviceid_list_len;
+ deviceid4 *gdlr_deviceid_list_val;
+ } gdlr_deviceid_list;
+ bool_t gdlr_eof;
+};
+typedef struct GETDEVICELIST4resok GETDEVICELIST4resok;
+
+struct GETDEVICELIST4res {
+ nfsstat4 gdlr_status;
+ union {
+ GETDEVICELIST4resok gdlr_resok4;
+ } GETDEVICELIST4res_u;
+};
+typedef struct GETDEVICELIST4res GETDEVICELIST4res;
+
+struct newtime4 {
+ bool_t nt_timechanged;
+ union {
+ nfstime4 nt_time;
+ } newtime4_u;
+};
+typedef struct newtime4 newtime4;
+
+struct newoffset4 {
+ bool_t no_newoffset;
+ union {
+ offset4 no_offset;
+ } newoffset4_u;
+};
+typedef struct newoffset4 newoffset4;
+
+struct LAYOUTCOMMIT4args {
+ offset4 loca_offset;
+ length4 loca_length;
+ bool_t loca_reclaim;
+ stateid4 loca_stateid;
+ newoffset4 loca_last_write_offset;
+ newtime4 loca_time_modify;
+ layoutupdate4 loca_layoutupdate;
+};
+typedef struct LAYOUTCOMMIT4args LAYOUTCOMMIT4args;
+
+struct newsize4 {
+ bool_t ns_sizechanged;
+ union {
+ length4 ns_size;
+ } newsize4_u;
+};
+typedef struct newsize4 newsize4;
+
+struct LAYOUTCOMMIT4resok {
+ newsize4 locr_newsize;
+};
+typedef struct LAYOUTCOMMIT4resok LAYOUTCOMMIT4resok;
+
+struct LAYOUTCOMMIT4res {
+ nfsstat4 locr_status;
+ union {
+ LAYOUTCOMMIT4resok locr_resok4;
+ } LAYOUTCOMMIT4res_u;
+};
+typedef struct LAYOUTCOMMIT4res LAYOUTCOMMIT4res;
+
+struct LAYOUTGET4args {
+ bool_t loga_signal_layout_avail;
+ layouttype4 loga_layout_type;
+ layoutiomode4 loga_iomode;
+ offset4 loga_offset;
+ length4 loga_length;
+ length4 loga_minlength;
+ stateid4 loga_stateid;
+ count4 loga_maxcount;
+};
+typedef struct LAYOUTGET4args LAYOUTGET4args;
+
+struct LAYOUTGET4resok {
+ bool_t logr_return_on_close;
+ stateid4 logr_stateid;
+ struct {
+ u_int logr_layout_len;
+ layout4 *logr_layout_val;
+ } logr_layout;
+};
+typedef struct LAYOUTGET4resok LAYOUTGET4resok;
+
+struct LAYOUTGET4res {
+ nfsstat4 logr_status;
+ union {
+ LAYOUTGET4resok logr_resok4;
+ bool_t logr_will_signal_layout_avail;
+ } LAYOUTGET4res_u;
+};
+typedef struct LAYOUTGET4res LAYOUTGET4res;
+
+struct LAYOUTRETURN4args {
+ bool_t lora_reclaim;
+ layouttype4 lora_layout_type;
+ layoutiomode4 lora_iomode;
+ layoutreturn4 lora_layoutreturn;
+};
+typedef struct LAYOUTRETURN4args LAYOUTRETURN4args;
+
+struct layoutreturn_stateid {
+ bool_t lrs_present;
+ union {
+ stateid4 lrs_stateid;
+ } layoutreturn_stateid_u;
+};
+typedef struct layoutreturn_stateid layoutreturn_stateid;
+
+struct LAYOUTRETURN4res {
+ nfsstat4 lorr_status;
+ union {
+ layoutreturn_stateid lorr_stateid;
+ } LAYOUTRETURN4res_u;
+};
+typedef struct LAYOUTRETURN4res LAYOUTRETURN4res;
+
+enum secinfo_style4 {
+ SECINFO_STYLE4_CURRENT_FH = 0,
+ SECINFO_STYLE4_PARENT = 1
+};
+typedef enum secinfo_style4 secinfo_style4;
+
+typedef secinfo_style4 SECINFO_NO_NAME4args;
+
+typedef SECINFO4res SECINFO_NO_NAME4res;
+
+struct SEQUENCE4args {
+ sessionid4 sa_sessionid;
+ sequenceid4 sa_sequenceid;
+ slotid4 sa_slotid;
+ slotid4 sa_highest_slotid;
+ bool_t sa_cachethis;
+};
+typedef struct SEQUENCE4args SEQUENCE4args;
+#define SEQ4_STATUS_CB_PATH_DOWN 0x00000001
+#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING 0x00000002
+#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED 0x00000004
+#define SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED 0x00000008
+#define SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED 0x00000010
+#define SEQ4_STATUS_ADMIN_STATE_REVOKED 0x00000020
+#define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040
+#define SEQ4_STATUS_LEASE_MOVED 0x00000080
+#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100
+#define SEQ4_STATUS_CB_PATH_DOWN_SESSION 0x00000200
+#define SEQ4_STATUS_BACKCHANNEL_FAULT 0x00000400
+#define SEQ4_STATUS_DEVID_CHANGED 0x00000800
+#define SEQ4_STATUS_DEVID_DELETED 0x00001000
+#define SEQ4_HIGH_BIT SEQ4_STATUS_DEVID_DELETED /* highest defined flag */
+
+struct SEQUENCE4resok {
+ sessionid4 sr_sessionid;
+ sequenceid4 sr_sequenceid;
+ slotid4 sr_slotid;
+ slotid4 sr_highest_slotid;
+ slotid4 sr_target_highest_slotid;
+ uint32_t sr_status_flags;
+};
+typedef struct SEQUENCE4resok SEQUENCE4resok;
+
+struct SEQUENCE4res {
+ nfsstat4 sr_status;
+ union {
+ SEQUENCE4resok sr_resok4;
+ } SEQUENCE4res_u;
+};
+typedef struct SEQUENCE4res SEQUENCE4res;
+
+struct ssa_digest_input4 {
+ SEQUENCE4args sdi_seqargs;
+};
+typedef struct ssa_digest_input4 ssa_digest_input4;
+
+struct SET_SSV4args {
+ struct {
+ u_int ssa_ssv_len;
+ char *ssa_ssv_val;
+ } ssa_ssv;
+ struct {
+ u_int ssa_digest_len;
+ char *ssa_digest_val;
+ } ssa_digest;
+};
+typedef struct SET_SSV4args SET_SSV4args;
+
+struct ssr_digest_input4 {
+ SEQUENCE4res sdi_seqres;
+};
+typedef struct ssr_digest_input4 ssr_digest_input4;
+
+struct SET_SSV4resok {
+ struct {
+ u_int ssr_digest_len;
+ char *ssr_digest_val;
+ } ssr_digest;
+};
+typedef struct SET_SSV4resok SET_SSV4resok;
+
+struct SET_SSV4res {
+ nfsstat4 ssr_status;
+ union {
+ SET_SSV4resok ssr_resok4;
+ } SET_SSV4res_u;
+};
+typedef struct SET_SSV4res SET_SSV4res;
+
+struct TEST_STATEID4args {
+ struct {
+ u_int ts_stateids_len;
+ stateid4 *ts_stateids_val;
+ } ts_stateids;
+};
+typedef struct TEST_STATEID4args TEST_STATEID4args;
+
+struct TEST_STATEID4resok {
+ struct {
+ u_int tsr_status_codes_len;
+ nfsstat4 *tsr_status_codes_val;
+ } tsr_status_codes;
+};
+typedef struct TEST_STATEID4resok TEST_STATEID4resok;
+
+struct TEST_STATEID4res {
+ nfsstat4 tsr_status;
+ union {
+ TEST_STATEID4resok tsr_resok4;
+ } TEST_STATEID4res_u;
+};
+typedef struct TEST_STATEID4res TEST_STATEID4res;
+
+struct deleg_claim4 {
+ open_claim_type4 dc_claim;
+ union {
+ open_delegation_type4 dc_delegate_type;
+ } deleg_claim4_u;
+};
+typedef struct deleg_claim4 deleg_claim4;
+
+struct WANT_DELEGATION4args {
+ uint32_t wda_want;
+ deleg_claim4 wda_claim;
+};
+typedef struct WANT_DELEGATION4args WANT_DELEGATION4args;
+
+struct WANT_DELEGATION4res {
+ nfsstat4 wdr_status;
+ union {
+ open_delegation4 wdr_resok4;
+ } WANT_DELEGATION4res_u;
+};
+typedef struct WANT_DELEGATION4res WANT_DELEGATION4res;
+
+struct DESTROY_CLIENTID4args {
+ clientid4 dca_clientid;
+};
+typedef struct DESTROY_CLIENTID4args DESTROY_CLIENTID4args;
+
+struct DESTROY_CLIENTID4res {
+ nfsstat4 dcr_status;
+};
+typedef struct DESTROY_CLIENTID4res DESTROY_CLIENTID4res;
+
+struct RECLAIM_COMPLETE4args {
+ bool_t rca_one_fs;
+};
+typedef struct RECLAIM_COMPLETE4args RECLAIM_COMPLETE4args;
+
+struct RECLAIM_COMPLETE4res {
+ nfsstat4 rcr_status;
+};
+typedef struct RECLAIM_COMPLETE4res RECLAIM_COMPLETE4res;
+
+/* new operations for NFSv4.1 end */
+
enum nfs_opnum4 {
OP_ACCESS = 3,
OP_CLOSE = 4,
@@ -1403,6 +2693,28 @@ enum nfs_opnum4 {
OP_VERIFY = 37,
OP_WRITE = 38,
OP_RELEASE_LOCKOWNER = 39,
+
+ /* nfsv4.1 */
+ OP_BACKCHANNEL_CTL = 40,
+ OP_BIND_CONN_TO_SESSION = 41,
+ OP_EXCHANGE_ID = 42,
+ OP_CREATE_SESSION = 43,
+ OP_DESTROY_SESSION = 44,
+ OP_FREE_STATEID = 45,
+ OP_GET_DIR_DELEGATION = 46,
+ OP_GETDEVICEINFO = 47,
+ OP_GETDEVICELIST = 48,
+ OP_LAYOUTCOMMIT = 49,
+ OP_LAYOUTGET = 50,
+ OP_LAYOUTRETURN = 51,
+ OP_SECINFO_NO_NAME = 52,
+ OP_SEQUENCE = 53,
+ OP_SET_SSV = 54,
+ OP_TEST_STATEID = 55,
+ OP_WANT_DELEGATION = 56,
+ OP_DESTROY_CLIENTID = 57,
+ OP_RECLAIM_COMPLETE = 58,
+
OP_ILLEGAL = 10044,
/*
* These are internal client pseudo ops that *MUST* never go over the wire
@@ -1461,6 +2773,25 @@ struct nfs_argop4 {
VERIFY4args opverify;
WRITE4args opwrite;
RELEASE_LOCKOWNER4args oprelease_lockowner;
+ BACKCHANNEL_CTL4args opbackchannel_ctl; /* nfsv4.1 */
+ BIND_CONN_TO_SESSION4args opbind_conn_to_session;
+ EXCHANGE_ID4args opexchange_id;
+ CREATE_SESSION4args opcreate_session;
+ DESTROY_SESSION4args opdestroy_session;
+ FREE_STATEID4args opfree_stateid;
+ GET_DIR_DELEGATION4args opget_dir_delegation;
+ GETDEVICEINFO4args opgetdeviceinfo;
+ GETDEVICELIST4args opgetdevicelist;
+ LAYOUTCOMMIT4args oplayoutcommit;
+ LAYOUTGET4args oplayoutget;
+ LAYOUTRETURN4args oplayoutreturn;
+ SECINFO_NO_NAME4args opsecinfo_no_name;
+ SEQUENCE4args opsequence;
+ SET_SSV4args opset_ssv;
+ TEST_STATEID4args optest_stateid;
+ WANT_DELEGATION4args opwant_delegation;
+ DESTROY_CLIENTID4args opdestroy_clientid;
+ RECLAIM_COMPLETE4args opreclaim_complete;
} nfs_argop4_u;
};
typedef struct nfs_argop4 nfs_argop4;
@@ -1506,6 +2837,25 @@ struct nfs_resop4 {
VERIFY4res opverify;
WRITE4res opwrite;
RELEASE_LOCKOWNER4res oprelease_lockowner;
+ BACKCHANNEL_CTL4res opbackchannel_ctl; /* nfsv4.1 */
+ BIND_CONN_TO_SESSION4res opbind_conn_to_session;
+ EXCHANGE_ID4res opexchange_id;
+ CREATE_SESSION4res opcreate_session;
+ DESTROY_SESSION4res opdestroy_session;
+ FREE_STATEID4res opfree_stateid;
+ GET_DIR_DELEGATION4res opget_dir_delegation;
+ GETDEVICEINFO4res opgetdeviceinfo;
+ GETDEVICELIST4res opgetdevicelist;
+ LAYOUTCOMMIT4res oplayoutcommit;
+ LAYOUTGET4res oplayoutget;
+ LAYOUTRETURN4res oplayoutreturn;
+ SECINFO_NO_NAME4res opsecinfo_no_name;
+ SEQUENCE4res opsequence;
+ SET_SSV4res opset_ssv;
+ TEST_STATEID4res optest_stateid;
+ WANT_DELEGATION4res opwant_delegation;
+ DESTROY_CLIENTID4res opdestroy_clientid;
+ RECLAIM_COMPLETE4res opreclaim_complete;
ILLEGAL4res opillegal;
} nfs_resop4_u;
};
@@ -1585,9 +2935,297 @@ struct CB_ILLEGAL4res {
};
typedef struct CB_ILLEGAL4res CB_ILLEGAL4res;
+/*
+ * New to nfsv4.1
+ */
+enum layoutrecall_type4 {
+ LAYOUTRECALL4_FILE = LAYOUT4_RET_REC_FILE,
+ LAYOUTRECALL4_FSID = LAYOUT4_RET_REC_FSID,
+ LAYOUTRECALL4_ALL = LAYOUT4_RET_REC_ALL
+};
+typedef enum layoutrecall_type4 layoutrecall_type4;
+
+struct layoutrecall_file4 {
+ nfs_fh4 lor_fh;
+ offset4 lor_offset;
+ length4 lor_length;
+ stateid4 lor_stateid;
+};
+typedef struct layoutrecall_file4 layoutrecall_file4;
+
+struct layoutrecall4 {
+ layoutrecall_type4 lor_recalltype;
+ union {
+ layoutrecall_file4 lor_layout;
+ fsid4 lor_fsid;
+ } layoutrecall4_u;
+};
+typedef struct layoutrecall4 layoutrecall4;
+
+struct CB_LAYOUTRECALL4args {
+ layouttype4 clora_type;
+ layoutiomode4 clora_iomode;
+ bool_t clora_changed;
+ layoutrecall4 clora_recall;
+};
+typedef struct CB_LAYOUTRECALL4args CB_LAYOUTRECALL4args;
+
+struct CB_LAYOUTRECALL4res {
+ nfsstat4 clorr_status;
+};
+typedef struct CB_LAYOUTRECALL4res CB_LAYOUTRECALL4res;
+
+enum notify_type4 {
+ NOTIFY4_CHANGE_CHILD_ATTRS = 0,
+ NOTIFY4_CHANGE_DIR_ATTRS = 1,
+ NOTIFY4_REMOVE_ENTRY = 2,
+ NOTIFY4_ADD_ENTRY = 3,
+ NOTIFY4_RENAME_ENTRY = 4,
+ NOTIFY4_CHANGE_COOKIE_VERIFIER = 5
+};
+typedef enum notify_type4 notify_type4;
+
+struct notify_entry4 {
+ component4 ne_file;
+ fattr4 ne_attrs;
+};
+typedef struct notify_entry4 notify_entry4;
+
+struct prev_entry4 {
+ notify_entry4 pe_prev_entry;
+ nfs_cookie4 pe_prev_entry_cookie;
+};
+typedef struct prev_entry4 prev_entry4;
+
+struct notify_remove4 {
+ notify_entry4 nrm_old_entry;
+ nfs_cookie4 nrm_old_entry_cookie;
+};
+typedef struct notify_remove4 notify_remove4;
+
+struct notify_add4 {
+ struct {
+ u_int nad_old_entry_len;
+ notify_remove4 *nad_old_entry_val;
+ } nad_old_entry;
+ notify_entry4 nad_new_entry;
+ struct {
+ u_int nad_new_entry_cookie_len;
+ nfs_cookie4 *nad_new_entry_cookie_val;
+} nad_new_entry_cookie;
+ struct {
+ u_int nad_prev_entry_len;
+ prev_entry4 *nad_prev_entry_val;
+ } nad_prev_entry;
+ bool_t nad_last_entry;
+};
+typedef struct notify_add4 notify_add4;
+
+struct notify_attr4 {
+ notify_entry4 na_changed_entry;
+};
+typedef struct notify_attr4 notify_attr4;
+
+struct notify_rename4 {
+ notify_remove4 nrn_old_entry;
+ notify_add4 nrn_new_entry;
+};
+typedef struct notify_rename4 notify_rename4;
+
+struct notify_verifier4 {
+ verifier4 nv_old_cookieverf;
+ verifier4 nv_new_cookieverf;
+};
+typedef struct notify_verifier4 notify_verifier4;
+
+typedef struct {
+ u_int notifylist4_len;
+ char *notifylist4_val;
+} notifylist4;
+
+struct notify4 {
+ bitmap4 notify_mask;
+ notifylist4 notify_vals;
+};
+typedef struct notify4 notify4;
+
+struct CB_NOTIFY4args {
+ stateid4 cna_stateid;
+ nfs_fh4 cna_fh;
+ struct {
+ u_int cna_changes_len;
+ notify4 *cna_changes_val;
+ } cna_changes;
+};
+typedef struct CB_NOTIFY4args CB_NOTIFY4args;
+
+struct CB_NOTIFY4res {
+ nfsstat4 cnr_status;
+};
+typedef struct CB_NOTIFY4res CB_NOTIFY4res;
+
+struct CB_PUSH_DELEG4args {
+ nfs_fh4 cpda_fh;
+ open_delegation4 cpda_delegation;
+};
+typedef struct CB_PUSH_DELEG4args CB_PUSH_DELEG4args;
+
+struct CB_PUSH_DELEG4res {
+ nfsstat4 cpdr_status;
+};
+typedef struct CB_PUSH_DELEG4res CB_PUSH_DELEG4res;
+#define RCA4_TYPE_MASK_RDATA_DLG 0
+#define RCA4_TYPE_MASK_WDATA_DLG 1
+#define RCA4_TYPE_MASK_DIR_DLG 2
+#define RCA4_TYPE_MASK_FILE_LAYOUT 3
+#define RCA4_TYPE_MASK_BLK_LAYOUT 4
+#define RCA4_TYPE_MASK_OBJ_LAYOUT_MIN 8
+#define RCA4_TYPE_MASK_OBJ_LAYOUT_MAX 9
+#define RCA4_TYPE_MASK_OTHER_LAYOUT_MIN 12
+#define RCA4_TYPE_MASK_OTHER_LAYOUT_MAX 15
+
+struct CB_RECALL_ANY4args {
+ uint32_t craa_objects_to_keep;
+ bitmap4 craa_type_mask;
+};
+typedef struct CB_RECALL_ANY4args CB_RECALL_ANY4args;
+
+struct CB_RECALL_ANY4res {
+ nfsstat4 crar_status;
+};
+typedef struct CB_RECALL_ANY4res CB_RECALL_ANY4res;
+
+typedef CB_RECALL_ANY4args CB_RECALLABLE_OBJ_AVAIL4args;
+
+struct CB_RECALLABLE_OBJ_AVAIL4res {
+ nfsstat4 croa_status;
+};
+typedef struct CB_RECALLABLE_OBJ_AVAIL4res CB_RECALLABLE_OBJ_AVAIL4res;
+
+struct CB_RECALL_SLOT4args {
+ slotid4 rsa_target_highest_slotid;
+};
+typedef struct CB_RECALL_SLOT4args CB_RECALL_SLOT4args;
+
+struct CB_RECALL_SLOT4res {
+ nfsstat4 rsr_status;
+};
+typedef struct CB_RECALL_SLOT4res CB_RECALL_SLOT4res;
+
+struct referring_call4 {
+ sequenceid4 rc_sequenceid;
+ slotid4 rc_slotid;
+};
+typedef struct referring_call4 referring_call4;
+
+struct referring_call_list4 {
+ sessionid4 rcl_sessionid;
+ struct {
+ u_int rcl_referring_calls_len;
+ referring_call4 *rcl_referring_calls_val;
+ } rcl_referring_calls;
+};
+typedef struct referring_call_list4 referring_call_list4;
+
+struct CB_SEQUENCE4args {
+ sessionid4 csa_sessionid;
+ sequenceid4 csa_sequenceid;
+ slotid4 csa_slotid;
+ slotid4 csa_highest_slotid;
+ bool_t csa_cachethis;
+ struct {
+ u_int csa_referring_call_lists_len;
+ referring_call_list4 *csa_referring_call_lists_val;
+ } csa_referring_call_lists;
+};
+typedef struct CB_SEQUENCE4args CB_SEQUENCE4args;
+
+struct CB_SEQUENCE4resok {
+ sessionid4 csr_sessionid;
+ sequenceid4 csr_sequenceid;
+ slotid4 csr_slotid;
+ slotid4 csr_highest_slotid;
+ slotid4 csr_target_highest_slotid;
+};
+typedef struct CB_SEQUENCE4resok CB_SEQUENCE4resok;
+
+struct CB_SEQUENCE4res {
+ nfsstat4 csr_status;
+ union {
+ CB_SEQUENCE4resok csr_resok4;
+ } CB_SEQUENCE4res_u;
+};
+typedef struct CB_SEQUENCE4res CB_SEQUENCE4res;
+
+struct CB_WANTS_CANCELLED4args {
+ bool_t cwca_contended_wants_cancelled;
+ bool_t cwca_resourced_wants_cancelled;
+};
+typedef struct CB_WANTS_CANCELLED4args CB_WANTS_CANCELLED4args;
+
+struct CB_WANTS_CANCELLED4res {
+ nfsstat4 cwcr_status;
+};
+typedef struct CB_WANTS_CANCELLED4res CB_WANTS_CANCELLED4res;
+
+struct CB_NOTIFY_LOCK4args {
+ nfs_fh4 cnla_fh;
+ lock_owner4 cnla_lock_owner;
+};
+typedef struct CB_NOTIFY_LOCK4args CB_NOTIFY_LOCK4args;
+
+struct CB_NOTIFY_LOCK4res {
+ nfsstat4 cnlr_status;
+};
+typedef struct CB_NOTIFY_LOCK4res CB_NOTIFY_LOCK4res;
+
+enum notify_deviceid_type4 {
+ NOTIFY_DEVICEID4_CHANGE = 1,
+ NOTIFY_DEVICEID4_DELETE = 2
+};
+typedef enum notify_deviceid_type4 notify_deviceid_type4;
+
+struct notify_deviceid_delete4 {
+ layouttype4 ndd_layouttype;
+ deviceid4 ndd_deviceid;
+};
+typedef struct notify_deviceid_delete4 notify_deviceid_delete4;
+
+struct notify_deviceid_change4 {
+ layouttype4 ndc_layouttype;
+ deviceid4 ndc_deviceid;
+ bool_t ndc_immediate;
+};
+typedef struct notify_deviceid_change4 notify_deviceid_change4;
+
+struct CB_NOTIFY_DEVICEID4args {
+ struct {
+ u_int cnda_changes_len;
+ notify4 *cnda_changes_val;
+ } cnda_changes;
+};
+typedef struct CB_NOTIFY_DEVICEID4args CB_NOTIFY_DEVICEID4args;
+
+struct CB_NOTIFY_DEVICEID4res {
+ nfsstat4 cndr_status;
+};
+typedef struct CB_NOTIFY_DEVICEID4res CB_NOTIFY_DEVICEID4res;
+
+/* Callback operations new to NFSv4.1 */
+
enum nfs_cb_opnum4 {
OP_CB_GETATTR = 3,
OP_CB_RECALL = 4,
+ OP_CB_LAYOUTRECALL = 5,
+ OP_CB_NOTIFY = 6,
+ OP_CB_PUSH_DELEG = 7,
+ OP_CB_RECALL_ANY = 8,
+ OP_CB_RECALLABLE_OBJ_AVAIL = 9,
+ OP_CB_RECALL_SLOT = 10,
+ OP_CB_SEQUENCE = 11,
+ OP_CB_WANTS_CANCELLED = 12,
+ OP_CB_NOTIFY_LOCK = 13,
+ OP_CB_NOTIFY_DEVICEID = 14,
OP_CB_ILLEGAL = 10044
};
typedef enum nfs_cb_opnum4 nfs_cb_opnum4;
@@ -1597,6 +3235,16 @@ struct nfs_cb_argop4 {
union {
CB_GETATTR4args opcbgetattr;
CB_RECALL4args opcbrecall;
+ CB_LAYOUTRECALL4args opcblayoutrecall;
+ CB_NOTIFY4args opcbnotify;
+ CB_PUSH_DELEG4args opcbpush_deleg;
+ CB_RECALL_ANY4args opcbrecall_any;
+ CB_RECALLABLE_OBJ_AVAIL4args opcbrecallable_obj_avail;
+ CB_RECALL_SLOT4args opcbrecall_slot;
+ CB_SEQUENCE4args opcbsequence;
+ CB_WANTS_CANCELLED4args opcbwants_cancelled;
+ CB_NOTIFY_LOCK4args opcbnotify_lock;
+ CB_NOTIFY_DEVICEID4args opcbnotify_deviceid;
} nfs_cb_argop4_u;
};
typedef struct nfs_cb_argop4 nfs_cb_argop4;
@@ -1606,6 +3254,16 @@ struct nfs_cb_resop4 {
union {
CB_GETATTR4res opcbgetattr;
CB_RECALL4res opcbrecall;
+ CB_LAYOUTRECALL4res opcblayoutrecall;
+ CB_NOTIFY4res opcbnotify;
+ CB_PUSH_DELEG4res opcbpush_deleg;
+ CB_RECALL_ANY4res opcbrecall_any;
+ CB_RECALLABLE_OBJ_AVAIL4res opcbrecallable_obj_avail;
+ CB_RECALL_SLOT4res opcbrecall_slot;
+ CB_SEQUENCE4res opcbsequence;
+ CB_WANTS_CANCELLED4res opcbwants_cancelled;
+ CB_NOTIFY_LOCK4res opcbnotify_lock;
+ CB_NOTIFY_DEVICEID4res opcbnotify_deviceid;
CB_ILLEGAL4res opcbillegal;
} nfs_cb_resop4_u;
};
@@ -1655,6 +3313,380 @@ extern bool_t xdr_CB_COMPOUND4args_clnt(XDR *, CB_COMPOUND4args *);
extern bool_t xdr_CB_COMPOUND4args_srv(XDR *, CB_COMPOUND4args *);
extern bool_t xdr_CB_COMPOUND4res(XDR *, CB_COMPOUND4res *);
+/* New XDR to nfsv4.1 */
+extern bool_t xdr_nfs_ftype4(XDR *, nfs_ftype4*);
+extern bool_t xdr_nfsstat4(XDR *, nfsstat4*);
+extern bool_t xdr_attrlist4(XDR *, attrlist4*);
+extern bool_t xdr_bitmap4(XDR *, bitmap4*);
+extern bool_t xdr_changeid4(XDR *, changeid4*);
+extern bool_t xdr_clientid4(XDR *, clientid4*);
+extern bool_t xdr_count4(XDR *, count4*);
+extern bool_t xdr_length4(XDR *, length4*);
+extern bool_t xdr_mode4(XDR *, mode4*);
+extern bool_t xdr_nfs_cookie4(XDR *, nfs_cookie4*);
+extern bool_t xdr_nfs_fh4(XDR *, nfs_fh4*);
+extern bool_t xdr_offset4(XDR *, offset4*);
+extern bool_t xdr_qop4(XDR *, qop4*);
+extern bool_t xdr_sec_oid4(XDR *, sec_oid4*);
+extern bool_t xdr_sequenceid4(XDR *, sequenceid4*);
+extern bool_t xdr_seqid4(XDR *, seqid4*);
+extern bool_t xdr_sessionid4(XDR *, sessionid4);
+extern bool_t xdr_slotid4(XDR *, slotid4*);
+extern bool_t xdr_utf8string(XDR *, utf8string*);
+extern bool_t xdr_utf8str_cis(XDR *, utf8str_cis*);
+extern bool_t xdr_utf8str_cs(XDR *, utf8str_cs*);
+extern bool_t xdr_utf8str_mixed(XDR *, utf8str_mixed*);
+extern bool_t xdr_component4(XDR *, component4*);
+extern bool_t xdr_linktext4(XDR *, linktext4*);
+extern bool_t xdr_pathname4(XDR *, pathname4*);
+extern bool_t xdr_verifier4(XDR *, verifier4*);
+extern bool_t xdr_nfstime4(XDR *, nfstime4*);
+extern bool_t xdr_time_how4(XDR *, time_how4*);
+extern bool_t xdr_settime4(XDR *, settime4*);
+extern bool_t xdr_nfs_lease4(XDR *, nfs_lease4*);
+extern bool_t xdr_fsid4(XDR *, fsid4*);
+extern bool_t xdr_change_policy4(XDR *, change_policy4*);
+extern bool_t xdr_fs_locations4(XDR *, fs_locations4*);
+extern bool_t xdr_acetype4(XDR *, acetype4*);
+extern bool_t xdr_aceflag4(XDR *, aceflag4*);
+extern bool_t xdr_acemask4(XDR *, acemask4*);
+extern bool_t xdr_nfsace4(XDR *, nfsace4*);
+extern bool_t xdr_aclflag4(XDR *, aclflag4*);
+extern bool_t xdr_nfsacl41(XDR *, nfsacl41*);
+extern bool_t xdr_mode_masked4(XDR *, mode_masked4*);
+extern bool_t xdr_specdata4(XDR *, specdata4*);
+extern bool_t xdr_netaddr4(XDR *, netaddr4*);
+extern bool_t xdr_nfs_impl_id4(XDR *, nfs_impl_id4*);
+extern bool_t xdr_stateid4(XDR *, stateid4*);
+extern bool_t xdr_layouttype4(XDR *, layouttype4*);
+extern bool_t xdr_layout_content4(XDR *, layout_content4*);
+extern bool_t xdr_layouthint4(XDR *, layouthint4*);
+extern bool_t xdr_layoutiomode4(XDR *, layoutiomode4*);
+extern bool_t xdr_layout4(XDR *, layout4*);
+extern bool_t xdr_deviceid4(XDR *, deviceid4);
+extern bool_t xdr_device_addr4(XDR *, device_addr4*);
+extern bool_t xdr_layoutupdate4(XDR *, layoutupdate4*);
+extern bool_t xdr_layoutreturn_type4(XDR *, layoutreturn_type4*);
+extern bool_t xdr_layoutreturn_file4(XDR *, layoutreturn_file4*);
+extern bool_t xdr_layoutreturn4(XDR *, layoutreturn4*);
+extern bool_t xdr_fs4_status_type(XDR *, fs4_status_type*);
+extern bool_t xdr_fs4_status(XDR *, fs4_status*);
+extern bool_t xdr_threshold4_read_size(XDR *, threshold4_read_size*);
+extern bool_t xdr_threshold4_write_size(XDR *, threshold4_write_size*);
+extern bool_t xdr_threshold4_read_iosize(XDR *, threshold4_read_iosize*);
+extern bool_t xdr_threshold4_write_iosize(XDR *, threshold4_write_iosize*);
+extern bool_t xdr_threshold_item4(XDR *, threshold_item4*);
+extern bool_t xdr_mdsthreshold4(XDR *, mdsthreshold4*);
+extern bool_t xdr_retention_get4(XDR *, retention_get4*);
+extern bool_t xdr_retention_set4(XDR *, retention_set4*);
+extern bool_t xdr_fs_charset_cap4(XDR *, fs_charset_cap4*);
+extern bool_t xdr_fattr4_supported_attrs(XDR *, fattr4_supported_attrs*);
+extern bool_t xdr_fattr4_type(XDR *, fattr4_type*);
+extern bool_t xdr_fattr4_fh_expire_type(XDR *, fattr4_fh_expire_type*);
+extern bool_t xdr_fattr4_change(XDR *, fattr4_change*);
+extern bool_t xdr_fattr4_size(XDR *, fattr4_size*);
+extern bool_t xdr_fattr4_link_support(XDR *, fattr4_link_support*);
+extern bool_t xdr_fattr4_symlink_support(XDR *, fattr4_symlink_support*);
+extern bool_t xdr_fattr4_named_attr(XDR *, fattr4_named_attr*);
+extern bool_t xdr_fattr4_fsid(XDR *, fattr4_fsid*);
+extern bool_t xdr_fattr4_unique_handles(XDR *, fattr4_unique_handles*);
+extern bool_t xdr_fattr4_lease_time(XDR *, fattr4_lease_time*);
+extern bool_t xdr_fattr4_rdattr_error(XDR *, fattr4_rdattr_error*);
+extern bool_t xdr_fattr4_acl(XDR *, fattr4_acl*);
+extern bool_t xdr_fattr4_aclsupport(XDR *, fattr4_aclsupport*);
+extern bool_t xdr_fattr4_archive(XDR *, fattr4_archive*);
+extern bool_t xdr_fattr4_cansettime(XDR *, fattr4_cansettime*);
+extern bool_t xdr_fattr4_case_insensitive(XDR *, fattr4_case_insensitive*);
+extern bool_t xdr_fattr4_case_preserving(XDR *, fattr4_case_preserving*);
+extern bool_t xdr_fattr4_chown_restricted(XDR *, fattr4_chown_restricted*);
+extern bool_t xdr_fattr4_fileid(XDR *, fattr4_fileid*);
+extern bool_t xdr_fattr4_files_avail(XDR *, fattr4_files_avail*);
+extern bool_t xdr_fattr4_filehandle(XDR *, fattr4_filehandle*);
+extern bool_t xdr_fattr4_files_free(XDR *, fattr4_files_free*);
+extern bool_t xdr_fattr4_files_total(XDR *, fattr4_files_total*);
+extern bool_t xdr_fattr4_fs_locations(XDR *, fattr4_fs_locations*);
+extern bool_t xdr_fattr4_hidden(XDR *, fattr4_hidden*);
+extern bool_t xdr_fattr4_homogeneous(XDR *, fattr4_homogeneous*);
+extern bool_t xdr_fattr4_maxfilesize(XDR *, fattr4_maxfilesize*);
+extern bool_t xdr_fattr4_maxlink(XDR *, fattr4_maxlink*);
+extern bool_t xdr_fattr4_maxname(XDR *, fattr4_maxname*);
+extern bool_t xdr_fattr4_maxread(XDR *, fattr4_maxread*);
+extern bool_t xdr_fattr4_maxwrite(XDR *, fattr4_maxwrite*);
+extern bool_t xdr_fattr4_mimetype(XDR *, fattr4_mimetype*);
+extern bool_t xdr_fattr4_mode(XDR *, fattr4_mode*);
+extern bool_t xdr_fattr4_mode_set_masked(XDR *, fattr4_mode_set_masked*);
+extern bool_t xdr_fattr4_mounted_on_fileid(XDR *, fattr4_mounted_on_fileid*);
+extern bool_t xdr_fattr4_no_trunc(XDR *, fattr4_no_trunc*);
+extern bool_t xdr_fattr4_numlinks(XDR *, fattr4_numlinks*);
+extern bool_t xdr_fattr4_owner(XDR *, fattr4_owner*);
+extern bool_t xdr_fattr4_owner_group(XDR *, fattr4_owner_group*);
+extern bool_t xdr_fattr4_quota_avail_hard(XDR *, fattr4_quota_avail_hard*);
+extern bool_t xdr_fattr4_quota_avail_soft(XDR *, fattr4_quota_avail_soft*);
+extern bool_t xdr_fattr4_quota_used(XDR *, fattr4_quota_used*);
+extern bool_t xdr_fattr4_rawdev(XDR *, fattr4_rawdev*);
+extern bool_t xdr_fattr4_space_avail(XDR *, fattr4_space_avail*);
+extern bool_t xdr_fattr4_space_free(XDR *, fattr4_space_free*);
+extern bool_t xdr_fattr4_space_total(XDR *, fattr4_space_total*);
+extern bool_t xdr_fattr4_space_used(XDR *, fattr4_space_used*);
+extern bool_t xdr_fattr4_system(XDR *, fattr4_system*);
+extern bool_t xdr_fattr4_time_access(XDR *, fattr4_time_access*);
+extern bool_t xdr_fattr4_time_access_set(XDR *, fattr4_time_access_set*);
+extern bool_t xdr_fattr4_time_backup(XDR *, fattr4_time_backup*);
+extern bool_t xdr_fattr4_time_create(XDR *, fattr4_time_create*);
+extern bool_t xdr_fattr4_time_delta(XDR *, fattr4_time_delta*);
+extern bool_t xdr_fattr4_time_metadata(XDR *, fattr4_time_metadata*);
+extern bool_t xdr_fattr4_time_modify(XDR *, fattr4_time_modify*);
+extern bool_t xdr_fattr4_time_modify_set(XDR *, fattr4_time_modify_set*);
+extern bool_t xdr_fattr4_suppattr_exclcreat(XDR *, fattr4_suppattr_exclcreat*);
+extern bool_t xdr_fattr4_dir_notif_delay(XDR *, fattr4_dir_notif_delay*);
+extern bool_t xdr_fattr4_dirent_notif_delay(XDR *, fattr4_dirent_notif_delay*);
+extern bool_t xdr_fattr4_fs_layout_types(XDR *, fattr4_fs_layout_types*);
+extern bool_t xdr_fattr4_fs_status(XDR *, fattr4_fs_status*);
+extern bool_t xdr_fattr4_fs_charset_cap(XDR *, fattr4_fs_charset_cap*);
+extern bool_t xdr_fattr4_layout_alignment(XDR *, fattr4_layout_alignment*);
+extern bool_t xdr_fattr4_layout_blksize(XDR *, fattr4_layout_blksize*);
+extern bool_t xdr_fattr4_layout_hint(XDR *, fattr4_layout_hint*);
+extern bool_t xdr_fattr4_layout_types(XDR *, fattr4_layout_types*);
+extern bool_t xdr_fattr4_mdsthreshold(XDR *, fattr4_mdsthreshold*);
+extern bool_t xdr_fattr4_retention_get(XDR *, fattr4_retention_get*);
+extern bool_t xdr_fattr4_retention_set(XDR *, fattr4_retention_set*);
+extern bool_t xdr_fattr4_retentevt_get(XDR *, fattr4_retentevt_get*);
+extern bool_t xdr_fattr4_retentevt_set(XDR *, fattr4_retentevt_set*);
+extern bool_t xdr_fattr4_retention_hold(XDR *, fattr4_retention_hold*);
+extern bool_t xdr_fattr4_dacl(XDR *, fattr4_dacl*);
+extern bool_t xdr_fattr4_sacl(XDR *, fattr4_sacl*);
+extern bool_t xdr_fattr4_change_policy(XDR *, fattr4_change_policy*);
+extern bool_t xdr_fattr4(XDR *, fattr4*);
+extern bool_t xdr_change_info4(XDR *, change_info4*);
+extern bool_t xdr_clientaddr4(XDR *, clientaddr4*);
+extern bool_t xdr_cb_client4(XDR *, cb_client4*);
+extern bool_t xdr_nfs_client_id4(XDR *, nfs_client_id4*);
+extern bool_t xdr_client_owner4(XDR *, client_owner4*);
+extern bool_t xdr_server_owner4(XDR *, server_owner4*);
+extern bool_t xdr_state_owner4(XDR *, state_owner4*);
+extern bool_t xdr_open_owner4(XDR *, open_owner4*);
+extern bool_t xdr_lock_owner4(XDR *, lock_owner4*);
+extern bool_t xdr_nfs_lock_type4(XDR *, nfs_lock_type4*);
+extern bool_t xdr_ssv_subkey4(XDR *, ssv_subkey4*);
+extern bool_t xdr_ssv_mic_plain_tkn4(XDR *, ssv_mic_plain_tkn4*);
+extern bool_t xdr_ssv_mic_tkn4(XDR *, ssv_mic_tkn4*);
+extern bool_t xdr_ssv_seal_plain_tkn4(XDR *, ssv_seal_plain_tkn4*);
+extern bool_t xdr_ssv_seal_cipher_tkn4(XDR *, ssv_seal_cipher_tkn4*);
+extern bool_t xdr_fs_locations_server4(XDR *, fs_locations_server4*);
+extern bool_t xdr_fs_locations_item4(XDR *, fs_locations_item4*);
+extern bool_t xdr_fs_locations_info4(XDR *, fs_locations_info4*);
+extern bool_t xdr_fattr4_fs_locations_info(XDR *, fattr4_fs_locations_info*);
+extern bool_t xdr_nfl_util4(XDR *, nfl_util4*);
+extern bool_t xdr_filelayout_hint_care4(XDR *, filelayout_hint_care4*);
+extern bool_t xdr_nfsv4_1_file_layouthint4(XDR *, nfsv4_1_file_layouthint4*);
+extern bool_t xdr_multipath_list4(XDR *, multipath_list4*);
+extern bool_t xdr_nfsv4_1_file_layout_ds_addr4(XDR *,
+ nfsv4_1_file_layout_ds_addr4*);
+extern bool_t xdr_nfsv4_1_file_layout4(XDR *, nfsv4_1_file_layout4*);
+extern bool_t xdr_ACCESS4args(XDR *, ACCESS4args*);
+extern bool_t xdr_COMMIT4args(XDR *, COMMIT4args*);
+extern bool_t xdr_COMMIT4res(XDR *, COMMIT4res*);
+extern bool_t xdr_DELEGPURGE4args(XDR *, DELEGPURGE4args*);
+extern bool_t xdr_DELEGPURGE4res(XDR *, DELEGPURGE4res*);
+extern bool_t xdr_DELEGRETURN4args(XDR *, DELEGRETURN4args*);
+extern bool_t xdr_DELEGRETURN4res(XDR *, DELEGRETURN4res*);
+extern bool_t xdr_GETATTR4args(XDR *, GETATTR4args*);
+extern bool_t xdr_GETATTR4res(XDR *, GETATTR4res*);
+extern bool_t xdr_GETFH4res(XDR *, GETFH4res*);
+extern bool_t xdr_open_to_lock_owner4(XDR *, open_to_lock_owner4*);
+extern bool_t xdr_exist_lock_owner4(XDR *, exist_lock_owner4*);
+extern bool_t xdr_locker4(XDR *, locker4*);
+extern bool_t xdr_LOCK4denied(XDR *, LOCK4denied*);
+extern bool_t xdr_LOOKUP4args(XDR *, LOOKUP4args*);
+extern bool_t xdr_LOOKUP4res(XDR *, LOOKUP4res*);
+extern bool_t xdr_LOOKUPP4res(XDR *, LOOKUPP4res*);
+extern bool_t xdr_NVERIFY4args(XDR *, NVERIFY4args*);
+extern bool_t xdr_NVERIFY4res(XDR *, NVERIFY4res*);
+extern bool_t xdr_createmode4(XDR *, createmode4*);
+extern bool_t xdr_creatverfattr(XDR *, creatverfattr*);
+extern bool_t xdr_createhow4(XDR *, createhow4*);
+extern bool_t xdr_opentype4(XDR *, opentype4*);
+extern bool_t xdr_openflag4(XDR *, openflag4*);
+extern bool_t xdr_limit_by4(XDR *, limit_by4*);
+extern bool_t xdr_nfs_modified_limit4(XDR *, nfs_modified_limit4*);
+extern bool_t xdr_nfs_space_limit4(XDR *, nfs_space_limit4*);
+extern bool_t xdr_open_delegation_type4(XDR *, open_delegation_type4*);
+extern bool_t xdr_open_claim_type4(XDR *, open_claim_type4*);
+extern bool_t xdr_open_claim_delegate_cur4(XDR *, open_claim_delegate_cur4*);
+extern bool_t xdr_open_claim4(XDR *, open_claim4*);
+extern bool_t xdr_open_read_delegation4(XDR *, open_read_delegation4*);
+extern bool_t xdr_open_write_delegation4(XDR *, open_write_delegation4*);
+extern bool_t xdr_why_no_delegation4(XDR *, why_no_delegation4*);
+extern bool_t xdr_open_none_delegation4(XDR *, open_none_delegation4*);
+extern bool_t xdr_open_delegation4(XDR *, open_delegation4*);
+extern bool_t xdr_PUTFH4args(XDR *, PUTFH4args*);
+extern bool_t xdr_PUTFH4res(XDR *, PUTFH4res*);
+extern bool_t xdr_PUTPUBFH4res(XDR *, PUTPUBFH4res*);
+extern bool_t xdr_PUTROOTFH4res(XDR *, PUTROOTFH4res*);
+extern bool_t xdr_RENEW4args(XDR *, RENEW4args*);
+extern bool_t xdr_RENEW4res(XDR *, RENEW4res*);
+extern bool_t xdr_RESTOREFH4res(XDR *, RESTOREFH4res*);
+extern bool_t xdr_SAVEFH4res(XDR *, SAVEFH4res*);
+extern bool_t xdr_SECINFO4args(XDR *, SECINFO4args*);
+extern bool_t xdr_rpc_gss_svc_t(XDR *, rpc_gss_svc_t *);
+extern bool_t xdr_rpcsec_gss_info(XDR *, rpcsec_gss_info*);
+extern bool_t xdr_SECINFO4res(XDR *, SECINFO4res*);
+extern bool_t xdr_SETATTR4args(XDR *, SETATTR4args*);
+extern bool_t xdr_SETATTR4res(XDR *, SETATTR4res*);
+extern bool_t xdr_SETCLIENTID_CONFIRM4args(XDR *, SETCLIENTID_CONFIRM4args*);
+extern bool_t xdr_SETCLIENTID_CONFIRM4res(XDR *, SETCLIENTID_CONFIRM4res*);
+extern bool_t xdr_VERIFY4args(XDR *, VERIFY4args*);
+extern bool_t xdr_VERIFY4res(XDR *, VERIFY4res*);
+extern bool_t xdr_stable_how4(XDR *, stable_how4*);
+extern bool_t xdr_RELEASE_LOCKOWNER4args(XDR *, RELEASE_LOCKOWNER4args*);
+extern bool_t xdr_RELEASE_LOCKOWNER4res(XDR *, RELEASE_LOCKOWNER4res*);
+extern bool_t xdr_ILLEGAL4res(XDR *, ILLEGAL4res*);
+extern bool_t xdr_gsshandle4_t(XDR *, gsshandle4_t *);
+extern bool_t xdr_gss_cb_handles4(XDR *, gss_cb_handles4*);
+extern bool_t xdr_callback_sec_parms4(XDR *, callback_sec_parms4*);
+extern bool_t xdr_BACKCHANNEL_CTL4args(XDR *, BACKCHANNEL_CTL4args*);
+extern bool_t xdr_BACKCHANNEL_CTL4res(XDR *, BACKCHANNEL_CTL4res*);
+extern bool_t xdr_channel_dir_from_client4(XDR *, channel_dir_from_client4*);
+extern bool_t xdr_BIND_CONN_TO_SESSION4args(XDR *, BIND_CONN_TO_SESSION4args*);
+extern bool_t xdr_channel_dir_from_server4(XDR *, channel_dir_from_server4*);
+extern bool_t xdr_BIND_CONN_TO_SESSION4resok(XDR *,
+ BIND_CONN_TO_SESSION4resok*);
+extern bool_t xdr_BIND_CONN_TO_SESSION4res(XDR *, BIND_CONN_TO_SESSION4res*);
+extern bool_t xdr_state_protect_ops4(XDR *, state_protect_ops4*);
+extern bool_t xdr_ssv_sp_parms4(XDR *, ssv_sp_parms4*);
+extern bool_t xdr_state_protect_how4(XDR *, state_protect_how4*);
+extern bool_t xdr_state_protect4_a(XDR *, state_protect4_a*);
+extern bool_t xdr_EXCHANGE_ID4args(XDR *, EXCHANGE_ID4args*);
+extern bool_t xdr_ssv_prot_info4(XDR *, ssv_prot_info4*);
+extern bool_t xdr_state_protect4_r(XDR *, state_protect4_r*);
+extern bool_t xdr_EXCHANGE_ID4resok(XDR *, EXCHANGE_ID4resok*);
+extern bool_t xdr_EXCHANGE_ID4res(XDR *, EXCHANGE_ID4res*);
+extern bool_t xdr_channel_attrs4(XDR *, channel_attrs4*);
+extern bool_t xdr_CREATE_SESSION4args(XDR *, CREATE_SESSION4args*);
+extern bool_t xdr_CREATE_SESSION4resok(XDR *, CREATE_SESSION4resok*);
+extern bool_t xdr_CREATE_SESSION4res(XDR *, CREATE_SESSION4res*);
+extern bool_t xdr_DESTROY_SESSION4args(XDR *, DESTROY_SESSION4args*);
+extern bool_t xdr_DESTROY_SESSION4res(XDR *, DESTROY_SESSION4res*);
+extern bool_t xdr_FREE_STATEID4args(XDR *, FREE_STATEID4args*);
+extern bool_t xdr_FREE_STATEID4res(XDR *, FREE_STATEID4res*);
+extern bool_t xdr_attr_notice4(XDR *, attr_notice4*);
+extern bool_t xdr_GET_DIR_DELEGATION4args(XDR *, GET_DIR_DELEGATION4args*);
+extern bool_t xdr_GET_DIR_DELEGATION4resok(XDR *, GET_DIR_DELEGATION4resok*);
+extern bool_t xdr_gddrnf4_status(XDR *, gddrnf4_status*);
+extern bool_t xdr_GET_DIR_DELEGATION4res_non_fatal(XDR *,
+ GET_DIR_DELEGATION4res_non_fatal*);
+extern bool_t xdr_GET_DIR_DELEGATION4res(XDR *, GET_DIR_DELEGATION4res*);
+extern bool_t xdr_GETDEVICEINFO4args(XDR *, GETDEVICEINFO4args*);
+extern bool_t xdr_GETDEVICEINFO4resok(XDR *, GETDEVICEINFO4resok*);
+extern bool_t xdr_GETDEVICEINFO4res(XDR *, GETDEVICEINFO4res*);
+extern bool_t xdr_GETDEVICELIST4args(XDR *, GETDEVICELIST4args*);
+extern bool_t xdr_GETDEVICELIST4resok(XDR *, GETDEVICELIST4resok*);
+extern bool_t xdr_GETDEVICELIST4res(XDR *, GETDEVICELIST4res*);
+extern bool_t xdr_newtime4(XDR *, newtime4*);
+extern bool_t xdr_newoffset4(XDR *, newoffset4*);
+extern bool_t xdr_LAYOUTCOMMIT4args(XDR *, LAYOUTCOMMIT4args*);
+extern bool_t xdr_newsize4(XDR *, newsize4*);
+extern bool_t xdr_LAYOUTCOMMIT4resok(XDR *, LAYOUTCOMMIT4resok*);
+extern bool_t xdr_LAYOUTCOMMIT4res(XDR *, LAYOUTCOMMIT4res*);
+extern bool_t xdr_LAYOUTGET4args(XDR *, LAYOUTGET4args*);
+extern bool_t xdr_LAYOUTGET4resok(XDR *, LAYOUTGET4resok*);
+extern bool_t xdr_LAYOUTGET4res(XDR *, LAYOUTGET4res*);
+extern bool_t xdr_LAYOUTRETURN4args(XDR *, LAYOUTRETURN4args*);
+extern bool_t xdr_layoutreturn_stateid(XDR *, layoutreturn_stateid*);
+extern bool_t xdr_LAYOUTRETURN4res(XDR *, LAYOUTRETURN4res*);
+extern bool_t xdr_secinfo_style4(XDR *, secinfo_style4*);
+extern bool_t xdr_SECINFO_NO_NAME4args(XDR *, SECINFO_NO_NAME4args*);
+extern bool_t xdr_SECINFO_NO_NAME4res(XDR *, SECINFO_NO_NAME4res*);
+extern bool_t xdr_SEQUENCE4args(XDR *, SEQUENCE4args*);
+extern bool_t xdr_SEQUENCE4resok(XDR *, SEQUENCE4resok*);
+extern bool_t xdr_SEQUENCE4res(XDR *, SEQUENCE4res*);
+extern bool_t xdr_ssa_digest_input4(XDR *, ssa_digest_input4*);
+extern bool_t xdr_SET_SSV4args(XDR *, SET_SSV4args*);
+extern bool_t xdr_ssr_digest_input4(XDR *, ssr_digest_input4*);
+extern bool_t xdr_SET_SSV4resok(XDR *, SET_SSV4resok*);
+extern bool_t xdr_SET_SSV4res(XDR *, SET_SSV4res*);
+extern bool_t xdr_TEST_STATEID4args(XDR *, TEST_STATEID4args*);
+extern bool_t xdr_TEST_STATEID4resok(XDR *, TEST_STATEID4resok*);
+extern bool_t xdr_TEST_STATEID4res(XDR *, TEST_STATEID4res*);
+extern bool_t xdr_deleg_claim4(XDR *, deleg_claim4*);
+extern bool_t xdr_WANT_DELEGATION4args(XDR *, WANT_DELEGATION4args*);
+extern bool_t xdr_WANT_DELEGATION4res(XDR *, WANT_DELEGATION4res*);
+extern bool_t xdr_DESTROY_CLIENTID4args(XDR *, DESTROY_CLIENTID4args*);
+extern bool_t xdr_DESTROY_CLIENTID4res(XDR *, DESTROY_CLIENTID4res*);
+extern bool_t xdr_RECLAIM_COMPLETE4args(XDR *, RECLAIM_COMPLETE4args*);
+extern bool_t xdr_RECLAIM_COMPLETE4res(XDR *, RECLAIM_COMPLETE4res*);
+extern bool_t xdr_nfs_opnum4(XDR *, nfs_opnum4*);
+extern bool_t xdr_COMPOUND4args(XDR *, COMPOUND4args*);
+extern bool_t xdr_COMPOUND4res(XDR *, COMPOUND4res*);
+extern bool_t xdr_CB_GETATTR4args(XDR *, CB_GETATTR4args*);
+extern bool_t xdr_CB_GETATTR4res(XDR *, CB_GETATTR4res*);
+extern bool_t xdr_CB_RECALL4args(XDR *, CB_RECALL4args*);
+extern bool_t xdr_CB_RECALL4res(XDR *, CB_RECALL4res*);
+extern bool_t xdr_CB_ILLEGAL4res(XDR *, CB_ILLEGAL4res*);
+extern bool_t xdr_layoutrecall_type4(XDR *, layoutrecall_type4*);
+extern bool_t xdr_layoutrecall_file4(XDR *, layoutrecall_file4*);
+extern bool_t xdr_layoutrecall4(XDR *, layoutrecall4*);
+extern bool_t xdr_CB_LAYOUTRECALL4args(XDR *, CB_LAYOUTRECALL4args*);
+extern bool_t xdr_CB_LAYOUTRECALL4res(XDR *, CB_LAYOUTRECALL4res*);
+extern bool_t xdr_notify_type4(XDR *, notify_type4*);
+extern bool_t xdr_notify_entry4(XDR *, notify_entry4*);
+extern bool_t xdr_prev_entry4(XDR *, prev_entry4*);
+extern bool_t xdr_notify_remove4(XDR *, notify_remove4*);
+extern bool_t xdr_notify_add4(XDR *, notify_add4*);
+extern bool_t xdr_notify_attr4(XDR *, notify_attr4*);
+extern bool_t xdr_notify_rename4(XDR *, notify_rename4*);
+extern bool_t xdr_notify_verifier4(XDR *, notify_verifier4*);
+extern bool_t xdr_notifylist4(XDR *, notifylist4*);
+extern bool_t xdr_notify4(XDR *, notify4*);
+extern bool_t xdr_CB_NOTIFY4args(XDR *, CB_NOTIFY4args*);
+extern bool_t xdr_CB_NOTIFY4res(XDR *, CB_NOTIFY4res*);
+extern bool_t xdr_CB_PUSH_DELEG4args(XDR *, CB_PUSH_DELEG4args*);
+extern bool_t xdr_CB_PUSH_DELEG4res(XDR *, CB_PUSH_DELEG4res*);
+extern bool_t xdr_CB_RECALL_ANY4args(XDR *, CB_RECALL_ANY4args*);
+extern bool_t xdr_CB_RECALL_ANY4res(XDR *, CB_RECALL_ANY4res*);
+extern bool_t xdr_CB_RECALLABLE_OBJ_AVAIL4args(XDR *,
+ CB_RECALLABLE_OBJ_AVAIL4args*);
+extern bool_t xdr_CB_RECALLABLE_OBJ_AVAIL4res(XDR *,
+ CB_RECALLABLE_OBJ_AVAIL4res*);
+extern bool_t xdr_CB_RECALL_SLOT4args(XDR *, CB_RECALL_SLOT4args*);
+extern bool_t xdr_CB_RECALL_SLOT4res(XDR *, CB_RECALL_SLOT4res*);
+extern bool_t xdr_referring_call4(XDR *, referring_call4*);
+extern bool_t xdr_referring_call_list4(XDR *, referring_call_list4*);
+extern bool_t xdr_CB_SEQUENCE4args(XDR *, CB_SEQUENCE4args*);
+extern bool_t xdr_CB_SEQUENCE4resok(XDR *, CB_SEQUENCE4resok*);
+extern bool_t xdr_CB_SEQUENCE4res(XDR *, CB_SEQUENCE4res*);
+extern bool_t xdr_CB_WANTS_CANCELLED4args(XDR *, CB_WANTS_CANCELLED4args*);
+extern bool_t xdr_CB_WANTS_CANCELLED4res(XDR *, CB_WANTS_CANCELLED4res*);
+extern bool_t xdr_CB_NOTIFY_LOCK4args(XDR *, CB_NOTIFY_LOCK4args*);
+extern bool_t xdr_CB_NOTIFY_LOCK4res(XDR *, CB_NOTIFY_LOCK4res*);
+extern bool_t xdr_notify_deviceid_type4(XDR *, notify_deviceid_type4*);
+extern bool_t xdr_notify_deviceid_delete4(XDR *, notify_deviceid_delete4*);
+extern bool_t xdr_notify_deviceid_change4(XDR *, notify_deviceid_change4*);
+extern bool_t xdr_CB_NOTIFY_DEVICEID4args(XDR *, CB_NOTIFY_DEVICEID4args*);
+extern bool_t xdr_CB_NOTIFY_DEVICEID4res(XDR *, CB_NOTIFY_DEVICEID4res*);
+extern bool_t xdr_nfs_cb_opnum4(XDR *, nfs_cb_opnum4*);
+extern bool_t xdr_nfs_cb_argop4(XDR *, nfs_cb_argop4*);
+extern bool_t xdr_nfs_cb_resop4(XDR *, nfs_cb_resop4*);
+extern bool_t xdr_CB_COMPOUND4args(XDR *, CB_COMPOUND4args*);
+extern bool_t xdr_CB_COMPOUND4res(XDR *, CB_COMPOUND4res*);
+/* nfsv4.1 end */
+
+/* nfsv4.2 */
+struct sec_label4 {
+ uint_t slai_len;
+ char *slai_val;
+};
+
+typedef struct sec_label4 sec_label4;
+typedef sec_label4 fattr4_sec_label;
+
+extern bool_t xdr_fattr4_sec_label(XDR *xdrs, fattr4_sec_label *objp);
+/* nfsv4.2 end */
+
+/* NFSv4.x xdr */
+extern bool_t xdr_nfs4x_argop4(XDR *xdrs, nfs_argop4 *objp);
+extern bool_t xdr_nfs4x_resop4(XDR *xdrs, nfs_resop4 *objp);
+
/*
* xdr for referrrals upcall
*/
diff --git a/usr/src/uts/common/nfs/nfs4x.h b/usr/src/uts/common/nfs/nfs4x.h
new file mode 100644
index 0000000000..9606d14f2c
--- /dev/null
+++ b/usr/src/uts/common/nfs/nfs4x.h
@@ -0,0 +1,195 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2017 RackTop Systems.
+ */
+
+#ifndef _NFS4X_SRV_H
+#define _NFS4X_SRV_H
+
+#ifdef _KERNEL
+
+#include <sys/cred.h>
+#include <nfs/nfs4_kprot.h>
+
+/*
+ * NFSv4.1: slot support (reply cache)
+ */
+
+#define RFS4_SLOT_INUSE (1 << 0)
+#define RFS4_SLOT_CACHED (1 << 1)
+
+/* Slot entry structure */
+typedef struct rfs4_slot {
+ uint32_t se_flags;
+ sequenceid4 se_seqid;
+ COMPOUND4res se_buf; /* Buf for slot and replays */
+ kmutex_t se_lock;
+} rfs4_slot_t;
+
+/*
+ * NFSv4.1 Sessions
+ */
+
+typedef struct rfs41_csr { /* contrived create_session result */
+ sequenceid4 xi_sid; /* seqid response to EXCHG_ID */
+ nfsstat4 cs_status;
+ CREATE_SESSION4resok cs_res; /* cached results if NFS4_OK */
+} rfs41_csr_t;
+
+/*
+ * Sessions Callback Infrastructure
+ *
+ * Locking:
+ *
+ * . cn_lock protects all fields in sess_channel_t, but since
+ * fore/back and dir don't change often, we serialize only
+ * the occasional update.
+ *
+ * cn_lock: cn_lock
+ * bsd_rwlock: cn_lock -> bsd_rwlock
+ */
+
+#define MAX_CH_CACHE 10
+typedef struct { /* Back Chan Specific Data */
+ rfs4_slot_t *bsd_slots; /* opaque token for slot tab */
+ nfsstat4 bsd_stat;
+ krwlock_t bsd_rwlock; /* protect slot tab info */
+ uint64_t bsd_idx; /* Index of next spare CLNT */
+ uint64_t bsd_cur; /* Most recent added CLNT */
+ int bsd_ch_free;
+ CLIENT *bsd_clnt[MAX_CH_CACHE];
+} sess_bcsd_t;
+
+typedef struct {
+ channel_dir_from_server4 cn_dir; /* Chan Direction */
+ channel_attrs4 cn_attrs; /* chan Attrs */
+ channel_attrs4 cn_back_attrs; /* back channel Attrs */
+ sess_bcsd_t *cn_csd; /* Chan Specific Data */
+ krwlock_t cn_lock;
+} sess_channel_t;
+
+/*
+ * Maximum number of concurrent COMPOUND requests per session
+ */
+#define MAXSLOTS 256
+#define MAXSLOTS_BACK 4
+
+typedef struct {
+ state_protect_how4 sp_type;
+} rfs41_sprot_t;
+
+/*
+ * NFSv4.1 Sessions (cont'd)
+ *
+ * rfs4_session_t rfs4_client_t
+ * +-------------+ +--------------------+
+ * | sn_sessid | | clientid |
+ * | sn_clnt * -|---------->| : |
+ * | sn_fore | +--------------------+
+ * | sn_back |
+ * | sn_slots * -|---------> +--------------------------------+
+ * +-------------+ | (slot_ent_t) |
+ * | +----------------------------+|
+ * | | status, slot, seqid, resp *||------><Res>
+ * | +----------------------------+|
+ * | | status, slot, seqid, resp *||
+ * | +----------------------------+|
+ * | | status, slot, seqid, resp *||
+ * | +----------------------------+|
+ * | . |
+ * | : |
+ * +--------------------------------+
+ * stok_t
+ */
+struct rfs4_client;
+struct rfs4_dbe;
+
+typedef struct {
+ nfsstat4 cs_error;
+ struct rfs4_client *cs_client;
+ struct svc_req *cs_req;
+ uint32_t cs_id;
+ CREATE_SESSION4args cs_aotw;
+} session41_create_t;
+
+/*
+ * sn_seq4 - sequence result bit accounting info (session scope)
+ * CB_PATH_DOWN_SESSION, CB_GSS_CONTEXT_EXPIRING,
+ * CB_GSS_CONTEXT_EXPIRED, BACKCHANNEL_FAULT
+ */
+typedef struct rfs4_session {
+ struct rfs4_dbe *sn_dbe;
+ sessionid4 sn_sessid; /* session id */
+ struct rfs4_client *sn_clnt; /* back ptr to client state */
+ sess_channel_t *sn_fore; /* fore chan for this session */
+ sess_channel_t *sn_back; /* back chan for this session */
+ rfs4_slot_t *sn_slots; /* slot replay cache */
+ time_t sn_laccess; /* struct was last accessed */
+ int sn_csflags; /* create_session only flags */
+ uint32_t sn_flags; /* SEQ4 status bits */
+ list_node_t sn_node; /* link node to rfs4_client */
+ struct {
+ uint32_t pngcnt; /* conn pings outstanding */
+ uint32_t progno; /* cb_program number */
+ uint32_t failed:1; /* TRUE if no cb path avail */
+ uint32_t pnginprog:1;
+ } sn_bc;
+ uint32_t sn_rcached; /* cached replies, for stat */
+} rfs4_session_t;
+
+#define SN_CB_CHAN_EST(x) ((x)->sn_back != NULL)
+#define SN_CB_CHAN_OK(x) ((x)->sn_bc.failed == 0)
+
+/* error code for internal use */
+#define nfserr_replay_cache NFS4ERR_REPLAY_CACHE
+
+/* Session end */
+
+/*
+ * Set of RPC credentials used for a particular operation.
+ * Used for operations like SETCLIENTID_CONFIRM where the
+ * credentials needs to match those used at SETCLIENTID.
+ * For EXCHANGE_ID (NFSv4.1+)
+ */
+
+typedef struct {
+ cred_t *cp_cr;
+ int cp_aflavor;
+ int cp_secmod;
+ caddr_t cp_princ;
+} cred_set_t;
+
+/* NFSv4.1 Functions */
+extern int rfs4x_dispatch(struct svc_req *, SVCXPRT *, char *);
+
+void rfs4_free_cred_set(cred_set_t *);
+void rfs4x_session_rele(rfs4_session_t *);
+rfs4_session_t *rfs4x_createsession(session41_create_t *);
+nfsstat4 rfs4x_destroysession(rfs4_session_t *, unsigned useref);
+void rfs4x_client_session_remove(struct rfs4_client *);
+rfs4_session_t *rfs4x_findsession_by_id(sessionid4);
+void rfs4x_session_hold(rfs4_session_t *);
+void rfs4x_session_rele(rfs4_session_t *);
+
+/* Some init/fini helpers */
+struct rfs4_srv;
+struct compound_state;
+void rfs4x_state_init_locked(struct nfs4_srv *);
+void rfs4x_state_fini(struct nfs4_srv *);
+int rfs4x_sequence_prep(COMPOUND4args *, COMPOUND4res *,
+ struct compound_state *);
+void rfs4x_sequence_done(COMPOUND4res *, struct compound_state *);
+
+#endif /* _KERNEL */
+
+#endif /* _NFS4_SRV_H */