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,30 ****
--- 21,31 ----
  
  /*
   * 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,45 ****
--- 36,51 ----
  #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,487 ****
          struct exportinfo  *tree_exi;
          struct exp_visible *tree_vis;
  } treenode_t;
  
  /*
!  * TREE_ROOT checks if the node corresponds to a filesystem root
   * TREE_EXPORTED checks if the node is explicitly shared
   */
  
  #define TREE_ROOT(t) \
!         ((t)->tree_exi && (t)->tree_exi->exi_vp->v_flag & VROOT)
  
  #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 */
--- 471,499 ----
          struct exportinfo  *tree_exi;
          struct exp_visible *tree_vis;
  } treenode_t;
  
  /*
!  * 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 != 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))
  
  #define EXPTABLESIZE   256
  
  struct exp_hash {
          struct exportinfo       *prev;  /* ptr to the previous exportinfo */
          struct exportinfo       *next;  /* ptr to the next exportinfo */
*** 515,537 ****
          struct treenode         *exi_tree;
          fhandle_t               exi_fh;
          krwlock_t               exi_cache_lock;
          kmutex_t                exi_lock;
          uint_t                  exi_count;
          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;
  #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 */
  };
  
  typedef struct exportinfo exportinfo_t;
  typedef struct exportdata exportdata_t;
  typedef struct secinfo secinfo_t;
--- 527,559 ----
          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 -- keep last! */
  };
  
  typedef struct exportinfo exportinfo_t;
  typedef struct exportdata exportdata_t;
  typedef struct secinfo secinfo_t;
*** 606,617 ****
      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_exportfini(void);
  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);
--- 628,643 ----
      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 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,672 ****
  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 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 *);
  
  /*
   * 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 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 *,
      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 *);
  /*
   * 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);
  
  /*
!  * "public" and default (root) location for public filehandle
   */
! extern struct exportinfo *exi_public, *exi_root;
! extern fhandle_t nullfh2;       /* for comparing V2 filehandles */
! extern krwlock_t exported_lock;
! extern struct exportinfo *exptable[];
  
  /*
   * Two macros for identifying public filehandles.
   * A v2 public filehandle is 32 zero bytes.
   * A v3 public filehandle is zero length.
--- 649,730 ----
  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 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(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(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(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 *);
+ 
  /*
!  * exi_id support
   */
! 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.