Print this page
11083 support NFS server in zone
Portions contributed by: Dan Kruchinin <dan.kruchinin@nexenta.com>
Portions contributed by: Stepan Zastupov <stepan.zastupov@gmail.com>
Portions contributed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Portions contributed by: Mike Zeller <mike@mikezeller.net>
Portions contributed by: Dan McDonald <danmcd@joyent.com>
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Portions contributed by: Vitaliy Gusev <gusev.vitaliy@gmail.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Jason King <jbk@joyent.com>
Reviewed by: C Fraire <cfraire@me.com>
Change-Id: I22f289d357503f9b48a0bc2482cc4328a6d43d16
@@ -21,10 +21,11 @@
/*
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
* Copyright 2016 Jason King.
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -35,11 +36,16 @@
#include <nfs/auth.h>
#include <sys/vnode.h>
#include <nfs/nfs4.h>
#include <sys/kiconv.h>
#include <sys/avl.h>
+#include <sys/zone.h>
+#ifdef _KERNEL
+#include <sys/pkp_hash.h> /* for PKP_HASH_SIZE */
+#endif /* _KERNEL */
+
#ifdef __cplusplus
extern "C" {
#endif
/*
@@ -465,23 +471,29 @@
struct exportinfo *tree_exi;
struct exp_visible *tree_vis;
} treenode_t;
/*
- * TREE_ROOT checks if the node corresponds to a filesystem root
+ * Now that we have links to chase, we can get the zone rootvp just from
+ * an export. No current-zone-context needed.
+ */
+#define EXI_TO_ZONEROOTVP(exi) ((exi)->exi_ne->exi_root->exi_vp)
+
+/*
+ * TREE_ROOT checks if the node corresponds to a filesystem root or
+ * the zone's root directory.
* TREE_EXPORTED checks if the node is explicitly shared
*/
#define TREE_ROOT(t) \
- ((t)->tree_exi && (t)->tree_exi->exi_vp->v_flag & VROOT)
+ ((t)->tree_exi != NULL && \
+ (((t)->tree_exi->exi_vp->v_flag & VROOT) || \
+ VN_CMP(EXI_TO_ZONEROOTVP((t)->tree_exi), (t)->tree_exi->exi_vp)))
#define TREE_EXPORTED(t) \
((t)->tree_exi && !PSEUDO((t)->tree_exi))
-/* Root of nfs pseudo namespace */
-extern treenode_t *ns_root;
-
#define EXPTABLESIZE 256
struct exp_hash {
struct exportinfo *prev; /* ptr to the previous exportinfo */
struct exportinfo *next; /* ptr to the next exportinfo */
@@ -515,23 +527,33 @@
struct treenode *exi_tree;
fhandle_t exi_fh;
krwlock_t exi_cache_lock;
kmutex_t exi_lock;
uint_t exi_count;
+ zoneid_t exi_zoneid;
vnode_t *exi_vp;
vnode_t *exi_dvp;
avl_tree_t *exi_cache[AUTH_TABLESIZE];
struct log_buffer *exi_logbuffer;
struct exp_visible *exi_visible;
struct charset_cache *exi_charset;
unsigned exi_volatile_dev:1;
unsigned exi_moved:1;
+ int exi_id;
+ avl_node_t exi_id_link;
+ /*
+ * Soft-reference/backpointer to zone's nfs_export_t.
+ * This allows us access to the zone's rootvp (stored in
+ * exi_ne->exi_root->exi_vp) even if the current thread isn't in
+ * same-zone context.
+ */
+ struct nfs_export *exi_ne;
#ifdef VOLATILE_FH_TEST
uint32_t exi_volatile_id;
struct ex_vol_rename *exi_vol_rename;
kmutex_t exi_vol_rename_lock;
-#endif /* VOLATILE_FH_TEST */
+#endif /* VOLATILE_FH_TEST -- keep last! */
};
typedef struct exportinfo exportinfo_t;
typedef struct exportdata exportdata_t;
typedef struct secinfo secinfo_t;
@@ -606,12 +628,16 @@
struct svc_req *, cred_t *, uid_t *, gid_t *, uint_t *, gid_t **);
extern int nfsauth4_secinfo_access(struct exportinfo *,
struct svc_req *, int, int, cred_t *);
extern int nfsauth_cache_clnt_compar(const void *, const void *);
extern int nfs_fhbcmp(char *, char *, int);
-extern int nfs_exportinit(void);
+extern void nfs_exportinit(void);
extern void nfs_exportfini(void);
+extern void nfs_export_zone_init(nfs_globals_t *);
+extern void nfs_export_zone_fini(nfs_globals_t *);
+extern void nfs_export_zone_shutdown(nfs_globals_t *);
+extern int nfs_export_get_rootfh(nfs_globals_t *);
extern int chk_clnt_sec(struct exportinfo *, struct svc_req *);
extern int makefh(fhandle_t *, struct vnode *, struct exportinfo *);
extern int makefh_ol(fhandle_t *, struct exportinfo *, uint_t);
extern int makefh3(nfs_fh3 *, struct vnode *, struct exportinfo *);
extern int makefh3_ol(nfs_fh3 *, struct exportinfo *, uint_t);
@@ -623,50 +649,82 @@
extern void exi_rele(struct exportinfo *);
extern struct exportinfo *nfs_vptoexi(vnode_t *, vnode_t *, cred_t *, int *,
int *, bool_t);
extern int nfs_check_vpexi(vnode_t *, vnode_t *, cred_t *,
struct exportinfo **);
-extern void export_link(struct exportinfo *);
-extern void export_unlink(struct exportinfo *);
-extern vnode_t *untraverse(vnode_t *);
+extern vnode_t *untraverse(vnode_t *, vnode_t *);
extern int vn_is_nfs_reparse(vnode_t *, cred_t *);
extern int client_is_downrev(struct svc_req *);
extern char *build_symlink(vnode_t *, cred_t *, size_t *);
+extern fhandle_t nullfh2; /* for comparing V2 filehandles */
+
+typedef struct nfs_export {
+ /* Root of nfs pseudo namespace */
+ treenode_t *ns_root;
+
+ nfs_globals_t *ne_globals; /* "up" pointer */
+
+ struct exportinfo *exptable_path_hash[PKP_HASH_SIZE];
+ struct exportinfo *exptable[EXPTABLESIZE];
+
+ /*
+ * Read/Write lock that protects the exportinfo list. This lock
+ * must be held when searching or modifiying the exportinfo list.
+ */
+ krwlock_t exported_lock;
+
+ /* "public" and default (root) location for public filehandle */
+ struct exportinfo *exi_public;
+ struct exportinfo *exi_root;
+ /* For checking default public file handle */
+ fid_t exi_rootfid;
+ /* For comparing V2 filehandles */
+ fhandle_t nullfh2;
+
+ /* The change attribute value of the root of nfs pseudo namespace */
+ timespec_t ns_root_change;
+} nfs_export_t;
+
/*
* Functions that handle the NFSv4 server namespace
*/
extern exportinfo_t *vis2exi(treenode_t *);
extern int treeclimb_export(struct exportinfo *);
-extern void treeclimb_unexport(struct exportinfo *);
+extern void treeclimb_unexport(nfs_export_t *, struct exportinfo *);
extern int nfs_visible(struct exportinfo *, vnode_t *, int *);
extern int nfs_visible_inode(struct exportinfo *, ino64_t,
struct exp_visible **);
extern int has_visible(struct exportinfo *, vnode_t *);
extern void free_visible(struct exp_visible *);
extern int nfs_exported(struct exportinfo *, vnode_t *);
-extern struct exportinfo *pseudo_exportfs(vnode_t *, fid_t *,
+extern struct exportinfo *pseudo_exportfs(nfs_export_t *, vnode_t *, fid_t *,
struct exp_visible *, struct exportdata *);
extern int vop_fid_pseudo(vnode_t *, fid_t *);
extern int nfs4_vget_pseudo(struct exportinfo *, vnode_t **, fid_t *);
extern bool_t nfs_visible_change(struct exportinfo *, vnode_t *,
timespec_t *);
-extern void tree_update_change(treenode_t *, timespec_t *);
+extern void tree_update_change(nfs_export_t *, treenode_t *, timespec_t *);
+extern void rfs4_clean_state_exi(nfs_export_t *, struct exportinfo *);
+
/*
* Functions that handle the NFSv4 server namespace security flavors
* information.
*/
extern void srv_secinfo_exp2pseu(struct exportdata *, struct exportdata *);
extern void srv_secinfo_list_free(struct secinfo *, int);
+extern nfs_export_t *nfs_get_export();
+extern void export_link(nfs_export_t *, struct exportinfo *);
+extern void export_unlink(nfs_export_t *, struct exportinfo *);
+
/*
- * "public" and default (root) location for public filehandle
+ * exi_id support
*/
-extern struct exportinfo *exi_public, *exi_root;
-extern fhandle_t nullfh2; /* for comparing V2 filehandles */
-extern krwlock_t exported_lock;
-extern struct exportinfo *exptable[];
+extern kmutex_t nfs_exi_id_lock;
+extern avl_tree_t exi_id_tree;
+extern int exi_id_get_next(void);
/*
* Two macros for identifying public filehandles.
* A v2 public filehandle is 32 zero bytes.
* A v3 public filehandle is zero length.