/*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2015 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
-__private_extern__ int nfs_ticks;
+extern int nfs_ticks;
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
#define NFS_TRYLATERDEL 4 /* Initial try later delay (sec) */
-#define NFS_MAXGRPS 16 /* Max. size of groups list */
+#define NFS_MAXGRPS 16U /* Max. size of groups list */
#define NFS_MINATTRTIMO 5 /* Attribute cache timeout in sec */
#define NFS_MAXATTRTIMO 60
#define NFS_MINDIRATTRTIMO 5 /* directory attribute cache timeout in sec */
#define NFS_ASYNCTHREADMAXIDLE 60 /* Seconds before idle nfsiods are reaped */
#define NFS_DEFSTATFSRATELIMIT 10 /* Def. max # statfs RPCs per second */
#define NFS_REQUESTDELAY 10 /* ms interval to check request queue */
-#define NFSRV_DEADSOCKDELAY 5 /* Seconds before dead sockets are reaped */
#define NFSRV_MAXWGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFSRV_WGATHERDELAY
#define NFSRV_WGATHERDELAY 1 /* Default write gather delay (msec) */
#define NFS_MATTR_FS_LOCATIONS 21 /* list of locations for the file system */
#define NFS_MATTR_MNTFLAGS 22 /* VFS mount flags (MNT_*) */
#define NFS_MATTR_MNTFROM 23 /* fixed string to use for "f_mntfromname" */
+#define NFS_MATTR_REALM 24 /* Realm to authenticate with */
+#define NFS_MATTR_PRINCIPAL 25 /* GSS principal to authenticate with */
+#define NFS_MATTR_SVCPRINCIPAL 26 /* GSS principal to authenticate to, the server principal */
+#define NFS_MATTR_NFS_VERSION_RANGE 27 /* Packed version range to try */
/* NFS mount flags */
#define NFS_MFLAG_SOFT 0 /* soft mount (requests fail if unresponsive) */
#define NFS_MFLAG_MNTUDP 16 /* MOUNT protocol should use UDP */
#define NFS_MFLAG_MNTQUICK 17 /* use short timeouts while mounting */
+/* Macros for packing and unpacking packed versions */
+#define PVER2MAJOR(M) ((uint32_t)(((M) >> 16) & 0xffff))
+#define PVER2MINOR(m) ((uint32_t)((m) & 0xffff))
+#define VER2PVER(M, m) ((uint32_t)((M) << 16) | ((m) & 0xffff))
+
/* NFS advisory file locking modes */
#define NFS_LOCK_MODE_ENABLED 0 /* advisory file locking enabled */
#define NFS_LOCK_MODE_DISABLED 1 /* do not support advisory file locking */
#define NX_MAPALL 0x0008 /* map all access to anon credential */
#define NX_32BITCLIENTS 0x0020 /* restrict directory cookies to 32 bits */
#define NX_OFFLINE 0x0040 /* export is offline */
+#define NX_MANGLEDNAMES 0x0080 /* export will return mangled names for names > 255 bytes */
/*
* fs.nfs sysctl(3) export stats record structures
#define NFSRV_USER_STAT_DEF_IDLE_SEC 7200 /* default idle seconds (node no longer considered active) */
/* active user list globals */
-__private_extern__ uint32_t nfsrv_user_stat_enabled; /* enable/disable active user list */
-__private_extern__ uint32_t nfsrv_user_stat_node_count; /* current count of user stat nodes */
-__private_extern__ uint32_t nfsrv_user_stat_max_idle_sec; /* idle seconds (node no longer considered active) */
-__private_extern__ uint32_t nfsrv_user_stat_max_nodes; /* active user list size limit */
-__private_extern__ lck_grp_t *nfsrv_active_user_mutex_group;
+extern uint32_t nfsrv_user_stat_enabled; /* enable/disable active user list */
+extern uint32_t nfsrv_user_stat_node_count; /* current count of user stat nodes */
+extern uint32_t nfsrv_user_stat_max_idle_sec; /* idle seconds (node no longer considered active) */
+extern uint32_t nfsrv_user_stat_max_nodes; /* active user list size limit */
+extern lck_grp_t *nfsrv_active_user_mutex_group;
/* An active user node represented in the kernel */
struct nfs_user_stat_node {
LIST_HEAD(,nfs_export) nxfs_exports; /* list of exports for this file system */
};
-__private_extern__ LIST_HEAD(nfsrv_expfs_list, nfs_exportfs) nfsrv_exports;
-__private_extern__ lck_rw_t nfsrv_export_rwlock; // lock for export data structures
+extern LIST_HEAD(nfsrv_expfs_list, nfs_exportfs) nfsrv_exports;
+extern lck_rw_t nfsrv_export_rwlock; // lock for export data structures
#define NFSRVEXPHASHSZ 64
#define NFSRVEXPHASHVAL(FSID, EXPID) \
(((FSID) >> 24) ^ ((FSID) >> 16) ^ ((FSID) >> 8) ^ (EXPID))
#define NFSRVEXPHASH(FSID, EXPID) \
(&nfsrv_export_hashtbl[NFSRVEXPHASHVAL((FSID),(EXPID)) & nfsrv_export_hash])
-__private_extern__ LIST_HEAD(nfsrv_export_hashhead, nfs_export) *nfsrv_export_hashtbl;
-__private_extern__ u_long nfsrv_export_hash;
+extern LIST_HEAD(nfsrv_export_hashhead, nfs_export) *nfsrv_export_hashtbl;
+extern u_long nfsrv_export_hash;
#if CONFIG_FSE
/*
#define NFSRVFMODHASHSZ 128
#define NFSRVFMODHASH(vp) (((uintptr_t) vp) & nfsrv_fmod_hash)
-__private_extern__ LIST_HEAD(nfsrv_fmod_hashhead, nfsrv_fmod) *nfsrv_fmod_hashtbl;
-__private_extern__ u_long nfsrv_fmod_hash;
-__private_extern__ lck_mtx_t *nfsrv_fmod_mutex;
-__private_extern__ int nfsrv_fmod_pending, nfsrv_fsevents_enabled;
+extern LIST_HEAD(nfsrv_fmod_hashhead, nfsrv_fmod) *nfsrv_fmod_hashtbl;
+extern u_long nfsrv_fmod_hash;
+extern lck_mtx_t *nfsrv_fmod_mutex;
+extern int nfsrv_fmod_pending, nfsrv_fsevents_enabled;
#endif
-__private_extern__ int nfsrv_async, nfsrv_export_hash_size,
+extern int nfsrv_async, nfsrv_export_hash_size,
nfsrv_reqcache_size, nfsrv_sock_max_rec_queue_length;
-__private_extern__ uint32_t nfsrv_gss_context_ttl;
-__private_extern__ struct nfsstats nfsstats;
+extern uint32_t nfsrv_gss_context_ttl;
+extern struct nfsstats nfsstats;
+#define NFS_UC_Q_DEBUG
+#ifdef NFS_UC_Q_DEBUG
+extern int nfsrv_uc_use_proxy;
+extern uint32_t nfsrv_uc_queue_limit;
+extern uint32_t nfsrv_uc_queue_max_seen;
+extern volatile uint32_t nfsrv_uc_queue_count;
+#endif
#endif // KERNEL
* Stats structure
*/
struct nfsstats {
- int attrcache_hits;
- int attrcache_misses;
- int lookupcache_hits;
- int lookupcache_misses;
- int direofcache_hits;
- int direofcache_misses;
- int biocache_reads;
- int read_bios;
- int read_physios;
- int biocache_writes;
- int write_bios;
- int write_physios;
- int biocache_readlinks;
- int readlink_bios;
- int biocache_readdirs;
- int readdir_bios;
- int rpccnt[NFS_NPROCS];
- int rpcretries;
- int srvrpccnt[NFS_NPROCS];
- int srvrpc_errs;
- int srv_errs;
- int rpcrequests;
- int rpctimeouts;
- int rpcunexpected;
- int rpcinvalid;
- int srvcache_inproghits;
- int srvcache_idemdonehits;
- int srvcache_nonidemdonehits;
- int srvcache_misses;
- int srvvop_writes;
- int pageins;
- int pageouts;
+ uint64_t attrcache_hits;
+ uint64_t attrcache_misses;
+ uint64_t lookupcache_hits;
+ uint64_t lookupcache_misses;
+ uint64_t direofcache_hits;
+ uint64_t direofcache_misses;
+ uint64_t biocache_reads;
+ uint64_t read_bios;
+ uint64_t read_physios;
+ uint64_t biocache_writes;
+ uint64_t write_bios;
+ uint64_t write_physios;
+ uint64_t biocache_readlinks;
+ uint64_t readlink_bios;
+ uint64_t biocache_readdirs;
+ uint64_t readdir_bios;
+ uint64_t rpccnt[NFS_NPROCS];
+ uint64_t rpcretries;
+ uint64_t srvrpccnt[NFS_NPROCS];
+ uint64_t srvrpc_errs;
+ uint64_t srv_errs;
+ uint64_t rpcrequests;
+ uint64_t rpctimeouts;
+ uint64_t rpcunexpected;
+ uint64_t rpcinvalid;
+ uint64_t srvcache_inproghits;
+ uint64_t srvcache_idemdonehits;
+ uint64_t srvcache_nonidemdonehits;
+ uint64_t srvcache_misses;
+ uint64_t srvvop_writes;
+ uint64_t pageins;
+ uint64_t pageouts;
};
#endif
*/
#define NFSCLNT_LOCKDANS 0x200
#define NFSCLNT_LOCKDNOTIFY 0x400
-
+#define NFSCLNT_TESTIDMAP 0x001
+
+#include <sys/_types/_guid_t.h> /* for guid_t below */
+#define MAXIDNAMELEN 1024
+struct nfs_testmapid {
+ uint32_t ntm_name2id; /* lookup name 2 id or id 2 name */
+ uint32_t ntm_grpflag; /* Is this a group or user maping */
+ uint32_t ntm_id; /* id to map or return */
+ uint32_t pad;
+ guid_t ntm_guid; /* intermidiate guid used in conversion */
+ char ntm_name[MAXIDNAMELEN]; /* name to map or return */
+};
+
/*
* fs.nfs sysctl(3) identifiers
*/
struct nfs_location_index;
struct nfs_socket;
struct nfs_socket_search;
+struct nfsrv_uc_arg;
/*
* The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
#define NFSINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \
sigmask(SIGHUP)|sigmask(SIGQUIT))
-__private_extern__ size_t nfs_mbuf_mhlen, nfs_mbuf_minclsize;
+extern size_t nfs_mbuf_mhlen, nfs_mbuf_minclsize;
/*
* NFS mbuf chain structure used for managing the building/dissection of RPCs
* Queue head for nfsreq's
*/
TAILQ_HEAD(nfs_reqqhead, nfsreq);
-__private_extern__ struct nfs_reqqhead nfs_reqq;
-__private_extern__ lck_grp_t *nfs_request_grp;
+extern struct nfs_reqqhead nfs_reqq;
+extern lck_grp_t *nfs_request_grp;
#define R_XID32(x) ((x) & 0xffffffff)
-#define NFSREQNOLIST ((struct nfsreq *)0xdeadbeef) /* sentinel value for nfsreq lists */
+#define NFSNOLIST ((void *)0x0badcafe) /* sentinel value for nfs lists */
+#define NFSREQNOLIST NFSNOLIST /* sentinel value for nfsreq lists */
/* Flag values for r_flags */
#define R_TIMING 0x00000001 /* timing request (in mntp) */
#define R_ASYNCWAIT 0x00002000 /* async request now being waited on */
#define R_RESENDQ 0x00004000 /* async request currently on resendq */
#define R_SENDING 0x00008000 /* request currently being sent */
+#define R_SOFT 0x00010000 /* request is soft - don't retry or reconnect */
+#define R_IOD 0x00020000 /* request is being managed by an IOD */
#define R_NOINTR 0x20000000 /* request should not be interupted by a signal */
#define R_RECOVER 0x40000000 /* a state recovery RPC - during NFSSTA_RECOVER */
#define RL_WAITING 0x0002 /* Someone waiting for lock. */
#define RL_QUEUED 0x0004 /* request is on the queue */
-__private_extern__ u_int32_t nfs_xid, nfs_xidwrap;
-__private_extern__ int nfs_iosize, nfs_allow_async, nfs_statfs_rate_limit;
-__private_extern__ int nfs_access_cache_timeout, nfs_access_delete, nfs_access_dotzfs, nfs_access_for_getattr;
-__private_extern__ int nfs_lockd_mounts, nfs_lockd_request_sent, nfs_single_des;
-__private_extern__ int nfs_tprintf_initial_delay, nfs_tprintf_delay;
-__private_extern__ int nfsiod_thread_count, nfsiod_thread_max, nfs_max_async_writes;
-__private_extern__ int nfs_idmap_ctrl, nfs_callback_port;
+extern u_int32_t nfs_xid, nfs_xidwrap;
+extern int nfs_iosize, nfs_allow_async, nfs_statfs_rate_limit;
+extern int nfs_access_cache_timeout, nfs_access_delete, nfs_access_dotzfs, nfs_access_for_getattr;
+extern int nfs_lockd_mounts, nfs_lockd_request_sent, nfs_single_des;
+extern int nfs_tprintf_initial_delay, nfs_tprintf_delay;
+extern int nfsiod_thread_count, nfsiod_thread_max, nfs_max_async_writes;
+extern int nfs_idmap_ctrl, nfs_callback_port;
+extern int nfs_is_mobile, nfs_readlink_nocache, nfs_root_steals_ctx;
+extern uint32_t nfs_squishy_flags;
+extern uint32_t nfs_debug_ctl;
/* bits for nfs_idmap_ctrl: */
#define NFS_IDMAP_CTRL_USE_IDMAP_SERVICE 0x00000001 /* use the ID mapping service */
TAILQ_ENTRY(nfsrv_sock) ns_chain; /* List of all nfsrv_sock's */
TAILQ_ENTRY(nfsrv_sock) ns_svcq; /* List of sockets needing servicing */
TAILQ_ENTRY(nfsrv_sock) ns_wgq; /* List of sockets with a pending write gather */
+ struct nfsrv_uc_arg *ns_ua; /* Opaque pointer to upcall */
lck_rw_t ns_rwlock; /* lock for most fields */
socket_t ns_so;
mbuf_t ns_nam;
#define SLPNOLIST ((struct nfsrv_sock *)0xdeadbeef) /* sentinel value for sockets not in the nfsrv_sockwg list */
-__private_extern__ struct nfsrv_sock *nfsrv_udpsock, *nfsrv_udp6sock;
+extern struct nfsrv_sock *nfsrv_udpsock, *nfsrv_udp6sock;
/*
* global NFS server socket lists:
* nfsrv_sockwork - sockets being worked on which may have more work to do (ns_svcq)
* nfsrv_sockwg - sockets with pending write gather input (ns_wgq)
*/
-__private_extern__ TAILQ_HEAD(nfsrv_sockhead, nfsrv_sock) nfsrv_socklist, nfsrv_deadsocklist,
- nfsrv_sockwg, nfsrv_sockwait, nfsrv_sockwork;
+extern TAILQ_HEAD(nfsrv_sockhead, nfsrv_sock) nfsrv_socklist, nfsrv_sockwg,
+ nfsrv_sockwait, nfsrv_sockwork;
/* lock groups for nfsrv_sock's */
-__private_extern__ lck_grp_t *nfsrv_slp_rwlock_group;
-__private_extern__ lck_grp_t *nfsrv_slp_mutex_group;
+extern lck_grp_t *nfsrv_slp_rwlock_group;
+extern lck_grp_t *nfsrv_slp_mutex_group;
/*
* One of these structures is allocated for each nfsd.
kauth_cred_t nd_cr; /* Credentials */
};
-__private_extern__ TAILQ_HEAD(nfsd_head, nfsd) nfsd_head, nfsd_queue;
+extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head, nfsd_queue;
/* mutex for nfs server */
-__private_extern__ lck_mtx_t *nfsd_mutex;
-__private_extern__ int nfsd_thread_count, nfsd_thread_max;
+extern lck_mtx_t *nfsd_mutex;
+extern int nfsd_thread_count, nfsd_thread_max;
/* request list mutex */
-__private_extern__ lck_mtx_t *nfs_request_mutex;
-__private_extern__ int nfs_request_timer_on;
+extern lck_mtx_t *nfs_request_mutex;
+extern int nfs_request_timer_on;
/* mutex for nfs client globals */
-__private_extern__ lck_mtx_t *nfs_global_mutex;
+extern lck_mtx_t *nfs_global_mutex;
/* NFSv4 callback globals */
-__private_extern__ int nfs4_callback_timer_on;
-__private_extern__ in_port_t nfs4_cb_port, nfs4_cb_port6;
+extern int nfs4_callback_timer_on;
+extern in_port_t nfs4_cb_port, nfs4_cb_port6;
/* nfs timer call structures */
-__private_extern__ thread_call_t nfs_request_timer_call;
-__private_extern__ thread_call_t nfs_buf_timer_call;
-__private_extern__ thread_call_t nfs4_callback_timer_call;
-__private_extern__ thread_call_t nfsrv_deadsock_timer_call;
+extern thread_call_t nfs_request_timer_call;
+extern thread_call_t nfs_buf_timer_call;
+extern thread_call_t nfs4_callback_timer_call;
+extern thread_call_t nfsrv_idlesock_timer_call;
#if CONFIG_FSE
-__private_extern__ thread_call_t nfsrv_fmod_timer_call;
+extern thread_call_t nfsrv_fmod_timer_call;
#endif
__BEGIN_DECLS
void nfs_disconnect(struct nfsmount *);
void nfs_need_reconnect(struct nfsmount *);
void nfs_mount_sock_thread_wake(struct nfsmount *);
-void nfs_mount_check_dead_timeout(struct nfsmount *);
+int nfs_mount_check_dead_timeout(struct nfsmount *);
+int nfs_mount_gone(struct nfsmount *);
+void nfs_mount_rele(struct nfsmount *);
+void nfs_mount_zombie(struct nfsmount *, int);
+void nfs_mount_make_zombie(struct nfsmount *);
+
void nfs_rpc_record_state_init(struct nfs_rpc_record_state *);
void nfs_rpc_record_state_cleanup(struct nfs_rpc_record_state *);
int nfs_rpc_record_read(socket_t, struct nfs_rpc_record_state *, int, int *, mbuf_t *);
int nfs_write_rpc(nfsnode_t, uio_t, vfs_context_t, int *, uint64_t *);
int nfs_write_rpc2(nfsnode_t, uio_t, thread_t, kauth_cred_t, int *, uint64_t *);
-int nfs3_access_rpc(nfsnode_t, u_int32_t *, vfs_context_t);
-int nfs4_access_rpc(nfsnode_t, u_int32_t *, vfs_context_t);
+int nfs3_access_rpc(nfsnode_t, u_int32_t *, int, vfs_context_t);
+int nfs4_access_rpc(nfsnode_t, u_int32_t *, int, vfs_context_t);
int nfs3_getattr_rpc(nfsnode_t, mount_t, u_char *, size_t, int, vfs_context_t, struct nfs_vattr *, u_int64_t *);
int nfs4_getattr_rpc(nfsnode_t, mount_t, u_char *, size_t, int, vfs_context_t, struct nfs_vattr *, u_int64_t *);
int nfs3_setattr_rpc(nfsnode_t, struct vnode_attr *, vfs_context_t);
void nfsrv_cleanup(void);
int nfsrv_credcheck(struct nfsrv_descript *, vfs_context_t, struct nfs_export *,
struct nfs_export_options *);
-void nfsrv_deadsock_timer(void *, void *);
+void nfsrv_idlesock_timer(void *, void *);
int nfsrv_dorec(struct nfsrv_sock *, struct nfsd *, struct nfsrv_descript **);
int nfsrv_errmap(struct nfsrv_descript *, int);
int nfsrv_export(struct user_nfs_export_args *, vfs_context_t);
int nfsrv_fhmatch(struct nfs_filehandle *, struct nfs_filehandle *);
int nfsrv_fhtovp(struct nfs_filehandle *, struct nfsrv_descript *, vnode_t *,
struct nfs_export **, struct nfs_export_options **);
+int nfsrv_check_exports_allow_address(mbuf_t);
#if CONFIG_FSE
void nfsrv_fmod_timer(void *, void *);
#endif
int nfsrv_write(struct nfsrv_descript *, struct nfsrv_sock *, vfs_context_t, mbuf_t *);
void nfs_interval_timer_start(thread_call_t, int);
+int nfs_use_cache(struct nfsmount *);
void nfs_up(struct nfsmount *, thread_t, int, const char *);
-void nfs_down(struct nfsmount *, thread_t, int, int, const char *);
+void nfs_down(struct nfsmount *, thread_t, int, int, const char *, int);
int nfs_msg(thread_t, const char *, const char *, int);
int nfs_mountroot(void);
void nfs_ephemeral_mount_harvester(__unused void *arg, __unused wait_result_t wr);
#endif
+/* socket upcall interfaces */
+void nfsrv_uc_init(void);
+void nfsrv_uc_cleanup(void);
+void nfsrv_uc_addsock(struct nfsrv_sock *, int);
+void nfsrv_uc_dequeue(struct nfsrv_sock *);
+
+/* Debug support */
+#define NFS_DEBUG_LEVEL (nfs_debug_ctl & 0xf)
+#define NFS_DEBUG_FACILITY ((nfs_debug_ctl >> 4) & 0xff)
+#define NFS_DEBUG_FLAGS ((nfs_debug_ctl >> 12) & 0xff)
+#define NFS_DEBUG_VALUE ((nfs_debug_ctl >> 20) & 0xfff)
+#define NFS_FAC_SOCK 0x01
+#define NFS_FAC_STATE 0x02
+#define NFS_FAC_NODE 0x04
+#define NFS_FAC_VNOP 0x08
+#define NFS_FAC_BIO 0x10
+#define NFS_FAC_GSS 0x20
+#define NFS_FAC_VFS 0x40
+
+#define NFS_DBG(fac, lev, fmt, ...) \
+ if (__builtin_expect(NFS_DEBUG_LEVEL, 0)) nfs_printf(fac, lev, "%s: %d: " fmt, __func__, __LINE__, ## __VA_ARGS__)
+
+void nfs_printf(int, int, const char *, ...) __printflike(3,4);
+int nfs_mountopts(struct nfsmount *, char *, int);
+
__END_DECLS
#endif /* KERNEL */