]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/nfsmount.h
xnu-2422.90.20.tar.gz
[apple/xnu.git] / bsd / nfs / nfsmount.h
index cfbdec71a59a6f9945787d66b9ff9ddc5dbae598..4e9e88e6c090b95c117b1ed713a78c026c18abf8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -105,31 +105,144 @@ struct nfs_fsattr {
 #define NFS_FSFLAG_CHOWN_RESTRICTED    0x00000080
 #define NFS_FSFLAG_HOMOGENEOUS         0x00000100
 #define NFS_FSFLAG_NO_TRUNC            0x00000200
+#define NFS_FSFLAG_NAMED_ATTR          0x00000400
 #define NFS_FSFLAG_FHTYPE_MASK         0xFF000000
 #define NFS_FSFLAG_FHTYPE_SHIFT                24
 
+/*
+ * NFS file system location structures
+ */
+struct nfs_fs_server {
+       char *                  ns_name;                /* name of server */
+       char **                 ns_addresses;           /* array of addresses for server */
+       uint32_t                ns_addrcount;           /* # of addresses */
+};
+struct nfs_fs_path {
+       char **                 np_components;          /* array of component pointers */
+       uint32_t                np_compcount;           /* # components in path */
+};
+struct nfs_fs_location {
+       struct nfs_fs_server ** nl_servers;             /* array of server pointers */
+       struct nfs_fs_path      nl_path;                /* file system path */
+       uint32_t                nl_servcount;           /* # of servers */
+};
+
+struct nfs_location_index {
+       uint8_t                 nli_flags;              /* misc flags */
+       uint8_t                 nli_loc;                /* location index */
+       uint8_t                 nli_serv;               /* server index */
+       uint8_t                 nli_addr;               /* address index */
+};
+#define NLI_VALID      0x01    /* index is valid */
+
+struct nfs_fs_locations {
+       struct nfs_fs_path      nl_root;                /* current server's root file system path */
+       uint32_t                nl_numlocs;             /* # of locations */
+       struct nfs_location_index nl_current;           /* index of current location/server/address */
+       struct nfs_fs_location **nl_locations;          /* array of fs locations */
+};
+
+/*
+ * RPC record marker parsing state
+ */
+struct nfs_rpc_record_state {
+       mbuf_t                  nrrs_m;                 /* mbufs for current record */
+       mbuf_t                  nrrs_mlast;
+       uint16_t                nrrs_lastfrag;          /* last fragment of record */
+       uint16_t                nrrs_markerleft;        /* marker bytes remaining */
+       uint32_t                nrrs_fragleft;          /* fragment bytes remaining */
+       uint32_t                nrrs_reclen;            /* length of RPC record */
+};
+
+/*
+ * NFS socket structures
+ */
+struct nfs_socket {
+       lck_mtx_t               nso_lock;               /* nfs socket lock */
+       TAILQ_ENTRY(nfs_socket) nso_link;               /* list of sockets */
+       struct sockaddr *       nso_saddr;              /* socket address */
+       struct sockaddr *       nso_saddr2;             /* additional socket address */
+       void *                  nso_wake;               /* address to wake up */
+       time_t                  nso_timestamp;
+       time_t                  nso_reqtimestamp;       /* last request sent */
+       socket_t                nso_so;                 /* socket */
+       uint8_t                 nso_sotype;             /* Type of socket */
+       uint16_t                nso_flags;              /* NSO_* flags */
+       struct nfs_location_index nso_location;         /* location index */
+       uint32_t                nso_protocol;           /* RPC protocol */
+       uint32_t                nso_version;            /* RPC protocol version */
+       uint32_t                nso_pingxid;            /* RPC XID of NULL ping request */
+       int                     nso_error;              /* saved error/status */
+       struct nfs_rpc_record_state nso_rrs;            /* RPC record parsing state (TCP) */
+};
+TAILQ_HEAD(nfssocketlist, nfs_socket);
+/* nso_flags */
+#define NSO_UPCALL             0x0001                  /* socket upcall in progress */
+#define NSO_DEAD               0x0002                  /* socket is dead */
+#define NSO_CONNECTING         0x0004                  /* socket is being connected */
+#define NSO_CONNECTED          0x0008                  /* socket connection complete */
+#define NSO_PINGING            0x0010                  /* socket is being tested */
+#define NSO_VERIFIED           0x0020                  /* socket appears functional */
+#define NSO_DISCONNECTING      0x0040                  /* socket is being disconnected */
+
+/* NFS connect socket search state */
+struct nfs_socket_search {
+       struct nfs_location_index nss_startloc;         /* starting location index */
+       struct nfs_location_index nss_nextloc;          /* next location index */
+       struct nfssocketlist    nss_socklist;           /* list of active sockets */
+       time_t                  nss_timestamp;          /* search start time */
+       time_t                  nss_last;               /* timestamp of last socket */
+       struct nfs_socket *     nss_sock;               /* found socket */
+       uint8_t                 nss_sotype;             /* TCP/UDP */
+       uint8_t                 nss_sockcnt;            /* # of active sockets */
+       in_port_t               nss_port;               /* port # to connect to */
+       uint32_t                nss_protocol;           /* RPC protocol */
+       uint32_t                nss_version;            /* RPC protocol version */
+       uint32_t                nss_flags;              /* (see below) */
+       int                     nss_addrcnt;            /* Number addresses to try or left */
+       int                     nss_timeo;              /* how long we are willing to wait */
+       int                     nss_error;              /* best error we've gotten so far */
+};
+/* nss_flags */
+#define NSS_VERBOSE            0x00000001              /* OK to log info about socket search */
+#define NSS_WARNED             0x00000002              /* logged warning about socket search taking a while */
+
 /*
  * function table for calling version-specific NFS functions
  */
 struct nfs_funcs {
-       int     (*nf_mount)(struct nfsmount *, vfs_context_t, struct user_nfs_args *, nfsnode_t *);
+       int     (*nf_mount)(struct nfsmount *, vfs_context_t, nfsnode_t *);
        int     (*nf_update_statfs)(struct nfsmount *, vfs_context_t);
-       int     (*nf_getquota)(struct nfsmount *, vfs_context_t, u_long, int, struct dqblk *);
-       int     (*nf_access_rpc)(nfsnode_t, u_long *, vfs_context_t);
-       int     (*nf_getattr_rpc)(nfsnode_t, mount_t, u_char *, size_t, vfs_context_t, struct nfs_vattr *, u_int64_t *);
-       int     (*nf_setattr_rpc)(nfsnode_t, struct vnode_attr *, vfs_context_t, int);
+       int     (*nf_getquota)(struct nfsmount *, vfs_context_t, uid_t, int, struct dqblk *);
+       int     (*nf_access_rpc)(nfsnode_t, u_int32_t *, vfs_context_t);
+       int     (*nf_getattr_rpc)(nfsnode_t, mount_t, u_char *, size_t, int, vfs_context_t, struct nfs_vattr *, u_int64_t *);
+       int     (*nf_setattr_rpc)(nfsnode_t, struct vnode_attr *, vfs_context_t);
        int     (*nf_read_rpc_async)(nfsnode_t, off_t, size_t, thread_t, kauth_cred_t, struct nfsreq_cbinfo *, struct nfsreq **);
-       int     (*nf_read_rpc_async_finish)(nfsnode_t, struct nfsreq *, struct uio *, size_t *, int *);
+       int     (*nf_read_rpc_async_finish)(nfsnode_t, struct nfsreq *, uio_t, size_t *, int *);
        int     (*nf_readlink_rpc)(nfsnode_t, char *, uint32_t *, vfs_context_t);
-       int     (*nf_write_rpc_async)(nfsnode_t, struct uio *, size_t, thread_t, kauth_cred_t, int, struct nfsreq_cbinfo *, struct nfsreq **);
+       int     (*nf_write_rpc_async)(nfsnode_t, uio_t, size_t, thread_t, kauth_cred_t, int, struct nfsreq_cbinfo *, struct nfsreq **);
        int     (*nf_write_rpc_async_finish)(nfsnode_t, struct nfsreq *, int *, size_t *, uint64_t *);
-       int     (*nf_commit_rpc)(nfsnode_t, uint64_t, uint64_t, kauth_cred_t);
+       int     (*nf_commit_rpc)(nfsnode_t, uint64_t, uint64_t, kauth_cred_t, uint64_t);
        int     (*nf_lookup_rpc_async)(nfsnode_t, char *, int, vfs_context_t, struct nfsreq **);
-       int     (*nf_lookup_rpc_async_finish)(nfsnode_t, vfs_context_t, struct nfsreq *, u_int64_t *, fhandle_t *, struct nfs_vattr *);
+       int     (*nf_lookup_rpc_async_finish)(nfsnode_t, char *, int, vfs_context_t, struct nfsreq *, u_int64_t *, fhandle_t *, struct nfs_vattr *);
        int     (*nf_remove_rpc)(nfsnode_t, char *, int, thread_t, kauth_cred_t);
        int     (*nf_rename_rpc)(nfsnode_t, char *, int, nfsnode_t, char *, int, vfs_context_t);
+       int     (*nf_setlock_rpc)(nfsnode_t, struct nfs_open_file *, struct nfs_file_lock *, int, int, thread_t, kauth_cred_t);
+       int     (*nf_unlock_rpc)(nfsnode_t, struct nfs_lock_owner *, int, uint64_t, uint64_t, int, thread_t, kauth_cred_t);
+       int     (*nf_getlock_rpc)(nfsnode_t, struct nfs_lock_owner *, struct flock *, uint64_t, uint64_t, vfs_context_t);
 };
 
+/*
+ * The long form of the NFSv4 client ID.
+ */
+struct nfs_client_id {
+       TAILQ_ENTRY(nfs_client_id)      nci_link;       /* list of client IDs */
+       char                            *nci_id;        /* client id buffer */
+       int                             nci_idlen;      /* length of client id buffer */
+};
+TAILQ_HEAD(nfsclientidlist, nfs_client_id);
+extern struct nfsclientidlist nfsclientids;
+
 /*
  * Mount structure.
  * One allocated on every NFS mount.
@@ -137,41 +250,73 @@ struct nfs_funcs {
  */
 struct nfsmount {
        lck_mtx_t nm_lock;              /* nfs mount lock */
-       int     nm_flag;                /* Flags for soft/hard... */
+       char *  nm_args;                /* NFS mount args (XDR) */
+       uint32_t nm_mattrs[NFS_MATTR_BITMAP_LEN]; /* mount attributes in mount args */
+       uint32_t nm_mflags_mask[NFS_MFLAG_BITMAP_LEN]; /* mount flags mask in mount args */
+       uint32_t nm_mflags[NFS_MFLAG_BITMAP_LEN]; /* mount flags in mount args */
+       uint32_t nm_flags[NFS_MFLAG_BITMAP_LEN]; /* current mount flags (soft, intr, etc...) */
+       char *  nm_realm;               /* Kerberos realm to use */
+       char *  nm_principal;           /* GSS principal to use on initial mount */
+       char *  nm_sprinc;              /* Kerberos principal of the server */
        int     nm_state;               /* Internal state flags */
        int     nm_vers;                /* NFS version */
        struct nfs_funcs *nm_funcs;     /* version-specific functions */
+       kauth_cred_t nm_mcred;          /* credential used for the mount */
        mount_t nm_mountp;              /* VFS structure for this filesystem */
        nfsnode_t nm_dnp;               /* root directory nfsnode pointer */
-       int     nm_numgrps;             /* Max. size of groupslist */
+       struct nfs_fs_locations nm_locations; /* file system locations */
+       uint32_t nm_numgrps;            /* Max. size of groupslist */
        TAILQ_HEAD(, nfs_gss_clnt_ctx) nm_gsscl; /* GSS user contexts */
        int     nm_timeo;               /* Init timer for NFSMNT_DUMBTIMR */
        int     nm_retry;               /* Max retries */
-       int     nm_rsize;               /* Max size of read rpc */
-       int     nm_wsize;               /* Max size of write rpc */
-       int     nm_biosize;             /* buffer I/O size */
-       int     nm_readdirsize;         /* Size of a readdir rpc */
-       int     nm_readahead;           /* Num. of blocks to readahead */
-       int     nm_acregmin;            /* reg file min attr cache timeout */
-       int     nm_acregmax;            /* reg file max attr cache timeout */
-       int     nm_acdirmin;            /* dir min attr cache timeout */
-       int     nm_acdirmax;            /* dir max attr cache timeout */
-       uint32_t nm_auth;               /* security mechanism flavor */
+       uint32_t nm_rsize;              /* Max size of read rpc */
+       uint32_t nm_wsize;              /* Max size of write rpc */
+       uint32_t nm_biosize;            /* buffer I/O size */
+       uint32_t nm_readdirsize;        /* Size of a readdir rpc */
+       uint32_t nm_readahead;          /* Num. of blocks to readahead */
+       uint32_t nm_acregmin;           /* reg file min attr cache timeout */
+       uint32_t nm_acregmax;           /* reg file max attr cache timeout */
+       uint32_t nm_acdirmin;           /* dir min attr cache timeout */
+       uint32_t nm_acdirmax;           /* dir max attr cache timeout */
+       uint32_t nm_auth;               /* security mechanism flavor being used */
+       uint32_t nm_writers;            /* Number of nodes open for writing */
+       uint32_t nm_mappers;            /* Number of nodes that have mmapped */
+       struct nfs_sec nm_sec;          /* acceptable security mechanism flavors */
+       struct nfs_sec nm_servsec;      /* server's acceptable security mechanism flavors */
+       fhandle_t *nm_fh;               /* initial file handle */
+       uint8_t  nm_lockmode;           /* advisory file locking mode */
        /* mount info */
        uint32_t nm_fsattrstamp;        /* timestamp for fs attrs */
        struct nfs_fsattr nm_fsattr;    /* file system attributes */
        uint64_t nm_verf;               /* v3/v4 write verifier */
        union {
            struct {                    /* v2/v3 specific fields */
-               u_short rqport;         /* cached rquota port */
-               uint32_t rqportstamp;   /* timestamp of rquota port */
+               TAILQ_ENTRY(nfsmount) ldlink; /* chain of mounts registered for lockd use */
+               int udp_sent;           /* UDP request send count */
+               int udp_cwnd;           /* UDP request congestion window */
+               struct nfs_reqqhead udp_cwndq; /* requests waiting on cwnd */
+               struct sockaddr *rqsaddr;/* cached rquota socket address */
+               uint32_t rqsaddrstamp;  /* timestamp of rquota socket address */
            } v3;
            struct {                    /* v4 specific fields */
-               uint64_t clientid;      /* client ID */
-               uint64_t mounttime;     /* mount verifier */
+               struct nfs_client_id *longid; /* client ID, long form */
+               uint64_t mounttime;     /* used as client ID verifier */
+               uint64_t clientid;      /* client ID, short form */
                thread_call_t renew_timer; /* RENEW timer call */
+               nfs_fsid fsid;          /* NFS file system id */
+               TAILQ_HEAD(, nfsnode) delegations; /* list of nodes with delegations */
+               TAILQ_HEAD(, nfsnode) dreturnq; /* list of nodes with delegations to return */
+               TAILQ_ENTRY(nfsmount) cblink; /* chain of mounts registered for callbacks */
+               uint32_t cbid;          /* callback channel identifier */
+               uint32_t cbrefs;        /* # callbacks using this mount */
            } v4;
        } nm_un;
+       /* common state */
+       TAILQ_HEAD(, nfs_open_owner) nm_open_owners; /* list of open owners */
+       uint32_t nm_stateinuse;         /* state in use counter */
+       uint32_t nm_stategenid;         /* state generation counter */
+       time_t  nm_recover_start;       /* recover start time */
+       LIST_HEAD(, nfsnode) nm_monlist; /* list of nodes being monitored */
        /* async I/O queue */
        struct nfs_reqqhead nm_resendq; /* async I/O resend queue */
        struct nfs_reqqhead nm_iodq;    /* async I/O request queue */
@@ -179,38 +324,45 @@ struct nfsmount {
        TAILQ_ENTRY(nfsmount) nm_iodlink; /* chain of mounts awaiting nfsiod */
        int     nm_asyncwrites;         /* outstanding async I/O writes */
        /* socket state */
-       int     nm_sotype;              /* Type of socket */
-       int     nm_soproto;             /* and protocol */
-       mbuf_t  nm_nam;                 /* Address of server */
+       uint8_t nm_sofamily;            /* (preferred) protocol family of socket */
+       uint8_t nm_sotype;              /* (preferred) type of socket */
+       in_port_t       nm_nfsport;     /* NFS protocol port */
+       in_port_t       nm_mountport;   /* MOUNT protocol port (v2/v3) */
+       struct nfs_socket_search *nm_nss; /* current socket search structure */
+       struct nfs_socket *nm_nso;      /* current socket */
+       struct sockaddr *nm_saddr;      /* Address of server */
        u_short nm_sockflags;           /* socket state flags */
-       socket_t nm_so;                 /* RPC socket */
-       int     nm_reconnect_start;     /* reconnect start time */
+       time_t  nm_deadto_start;        /* dead timeout start time */
+       time_t  nm_reconnect_start;     /* reconnect start time */
        int     nm_tprintf_initial_delay;       /* delay first "server down" */
        int     nm_tprintf_delay;       /* delay between "server down" */
+       int     nm_deadtimeout;         /* delay between first "server down" and dead set at mount time */
+       int     nm_curdeadtimeout;      /* current dead timeout. Adjusted by mount state and mobility */
        int     nm_srtt[4];             /* Timers for RPCs */
        int     nm_sdrtt[4];
        int     nm_timeouts;            /* Request timeouts */
-       union {
-               struct {
-                       int sent;       /* Request send count */
-                       int cwnd;       /* Request congestion window */
-                       struct nfs_reqqhead cwndq; /* requests waiting on cwnd */
-               } udp;
-               struct {
-                       u_int32_t mleft;/* marker bytes remaining */
-                       u_int32_t fleft;/* fragment bytes remaining */
-                       u_int32_t len;  /* length of RPC record */
-                       mbuf_t m;       /* mbufs for current record */
-                       mbuf_t mlast;
-               } tcp;
-       } nm_sockstate;
+       int     nm_jbreqs;              /* # R_JBTPRINTFMSG requests */
+       int     nm_mounterror;          /* status of mount connect */
        TAILQ_ENTRY(nfsmount) nm_pokeq; /* mount poke queue chain */
        thread_t nm_sockthd;            /* socket thread for this mount */
 };
 
+/* macro for checking current mount flags */
+#define NMFLAG(NMP, F)         NFS_BITMAP_ISSET((NMP)->nm_flags, NFS_MFLAG_ ## F)
+/* macros for checking (original) mount attributes/flags */
+#define NM_OMATTR_GIVEN(NMP, F)        NFS_BITMAP_ISSET((NMP)->nm_mattrs, NFS_MATTR_ ## F)
+#define NM_OMFLAG_GIVEN(NMP, F)        NFS_BITMAP_ISSET((NMP)->nm_mflags_mask, NFS_MFLAG_ ## F)
+#define NM_OMFLAG(NMP, F)      NFS_BITMAP_ISSET((NMP)->nm_mflags, NFS_MFLAG_ ## F)
+
 /*
  * NFS mount state flags (nm_state)
  */
+#define NFSSTA_MOUNT_THREAD    0x00000040  /* nfs_mount_connect_thread running */
+#define NFSSTA_MONITOR_SCAN    0x00000080  /* scan of monitored nodes in progress */
+#define NFSSTA_UNMOUNTING      0x00000100  /* an unmount attempt is in progress */
+#define NFSSTA_NEEDSECINFO     0x00000200  /* need to fetch security info */
+#define NFSSTA_CLIENTID                0x00000400  /* short client ID is valid */
+#define NFSSTA_BIGCOOKIES      0x00000800  /* have seen >32bit dir cookies */
 #define NFSSTA_JUKEBOXTIMEO    0x00001000  /* experienced a jukebox timeout */
 #define NFSSTA_LOCKTIMEO       0x00002000  /* experienced a lock req timeout */
 #define NFSSTA_MOUNTED         0x00004000  /* completely mounted */
@@ -220,34 +372,42 @@ struct nfsmount {
 #define NFSSTA_HASWRITEVERF    0x00040000  /* Has write verifier for V3 */
 #define NFSSTA_GOTPATHCONF     0x00080000  /* Got the V3 pathconf info */
 #define NFSSTA_GOTFSINFO       0x00100000  /* Got the V3 fsinfo */
+#define NFSSTA_SENDING         0x00800000  /* Sending on socket */
 #define NFSSTA_SNDLOCK         0x01000000  /* Send socket lock */
 #define NFSSTA_WANTSND         0x02000000  /* Want above */
+#define NFSSTA_DEAD            0x04000000  /* mount is dead */
+#define NFSSTA_RECOVER         0x08000000  /* mount state needs to be recovered */
+#define NFSSTA_RECOVER_EXPIRED 0x10000000  /* mount state expired */
+#define NFSSTA_REVOKE          0x20000000  /* need to scan for revoked nodes */
+#define        NFSSTA_SQUISHY          0x40000000  /* we can ask to be forcibly unmounted */
 
 /* flags for nm_sockflags */
 #define NMSOCK_READY           0x0001  /* socket is ready for use */
 #define NMSOCK_CONNECTING      0x0002  /* socket is being connect()ed */
 #define NMSOCK_SETUP           0x0004  /* socket/connection is being set up */
 #define NMSOCK_UNMOUNT         0x0008  /* unmounted, no more socket activity */
-#define NMSOCK_LASTFRAG                0x0010  /* on last fragment of RPC record */
+#define NMSOCK_HASCONNECTED    0x0010  /* socket has connected before */
 #define NMSOCK_POKE            0x0020  /* socket needs to be poked */
-#define NMSOCK_UPCALL          0x0040  /* socket upcall in progress */
-
-/* aliases for socket state variables */
-#define nm_sent                nm_sockstate.udp.sent
-#define nm_cwnd                nm_sockstate.udp.cwnd
-#define nm_cwndq       nm_sockstate.udp.cwndq
-#define nm_markerleft  nm_sockstate.tcp.mleft
-#define nm_fragleft    nm_sockstate.tcp.fleft
-#define nm_reclen      nm_sockstate.tcp.len
-#define nm_m           nm_sockstate.tcp.m
-#define nm_mlast       nm_sockstate.tcp.mlast
+#define NMSOCK_DISCONNECTING   0x0080  /* socket is being disconnected */
 
 /* aliases for version-specific fields */
-#define nm_rqport      nm_un.v3.rqport
-#define nm_rqportstamp nm_un.v3.rqportstamp
+#define nm_ldlink      nm_un.v3.ldlink
+#define nm_sent                nm_un.v3.udp_sent
+#define nm_cwnd                nm_un.v3.udp_cwnd
+#define nm_cwndq       nm_un.v3.udp_cwndq
+#define nm_rqproto     nm_un.v3.rqproto
+#define nm_rqsaddr     nm_un.v3.rqsaddr
+#define nm_rqsaddrstamp        nm_un.v3.rqsaddrstamp
+#define nm_longid      nm_un.v4.longid
 #define nm_clientid    nm_un.v4.clientid
 #define nm_mounttime   nm_un.v4.mounttime
+#define nm_fsid                nm_un.v4.fsid
 #define nm_renew_timer nm_un.v4.renew_timer
+#define nm_cbid                nm_un.v4.cbid
+#define nm_cblink      nm_un.v4.cblink
+#define nm_cbrefs      nm_un.v4.cbrefs
+#define nm_delegations nm_un.v4.delegations
+#define nm_dreturnq    nm_un.v4.dreturnq
 
 #if defined(KERNEL)
 /*