#ifndef _SYS_SDEV_IMPL_H
#define _SYS_SDEV_IMPL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <rpc/rpc.h>
#include <sys/dirent.h>
#include <sys/vfs.h>
#include <sys/vfs_opreg.h>
#include <sys/list.h>
#include <sys/nvpair.h>
#include <sys/sunddi.h>
#include <sys/fs/sdev_plugin.h>
struct sdev_mountargs {
uint64_t sdev_attrdir;
};
#define SDEV_NVNAME_MOUNTPT "prof_mountpt"
#define SDEV_NVNAME_INCLUDE "prof_include"
#define SDEV_NVNAME_EXCLUDE "prof_exclude"
#define SDEV_NVNAME_SYMLINK "prof_symlink"
#define SDEV_NVNAME_MAP "prof_map"
#define DEVFSADMD_RUN_ALL 1
#define DEVFSADM_RUN_INVALID 1
#define DEVFSADM_RUN_EPERM 2
#define DEVFSADM_RUN_NOTSUP 3
typedef struct sdev_door_arg {
uint8_t devfsadm_cmd;
} sdev_door_arg_t;
typedef struct sdev_door_res {
int32_t devfsadm_error;
} sdev_door_res_t;
#ifdef _KERNEL
struct sdev_dprof {
int has_glob;
nvlist_t *dev_name;
nvlist_t *dev_map;
nvlist_t *dev_symlink;
nvlist_t *dev_glob_incdir;
nvlist_t *dev_glob_excdir;
};
struct devname_handle {
struct sdev_node *dh_data;
void *dh_args;
};
typedef struct devname_handle devname_handle_t;
typedef struct sdev_global_data {
struct devname_handle sdev_ghandle;
ulong_t sdev_dir_ggen;
} sdev_global_data_t;
typedef struct sdev_local_data {
ulong_t sdev_dir_lgen;
ulong_t sdev_devtree_lgen;
struct sdev_node *sdev_lorigin;
struct sdev_dprof sdev_lprof;
} sdev_local_data_t;
typedef enum sdev_flags {
SDEV_BUILD = 0x0001,
SDEV_GLOBAL = 0x0002,
SDEV_PERSIST = 0x0004,
SDEV_NO_NCACHE = 0x0008,
SDEV_DYNAMIC = 0x0010,
SDEV_VTOR = 0x0020,
SDEV_ATTR_INVALID = 0x0040,
SDEV_SUBDIR = 0x0080,
SDEV_ZONED = 0x0100
} sdev_flags_t;
typedef struct sdev_node {
char *sdev_name;
size_t sdev_namelen;
char *sdev_path;
char *sdev_symlink;
struct vnode *sdev_vnode;
krwlock_t sdev_contents;
struct sdev_node *sdev_dotdot;
avl_tree_t sdev_entries;
avl_node_t sdev_avllink;
struct vnode *sdev_attrvp;
struct vattr *sdev_attr;
ino64_t sdev_ino;
uint_t sdev_nlink;
int sdev_state;
sdev_flags_t sdev_flags;
kmutex_t sdev_lookup_lock;
kcondvar_t sdev_lookup_cv;
int sdev_lookup_flags;
union {
struct sdev_global_data sdev_globaldata;
struct sdev_local_data sdev_localdata;
} sdev_instance_data;
list_node_t sdev_plist;
void *sdev_private;
} sdev_node_t;
#define sdev_ldata sdev_instance_data.sdev_localdata
#define sdev_gdata sdev_instance_data.sdev_globaldata
#define sdev_handle sdev_gdata.sdev_ghandle
#define sdev_gdir_gen sdev_gdata.sdev_dir_ggen
#define sdev_ldir_gen sdev_ldata.sdev_dir_lgen
#define sdev_devtree_gen sdev_ldata.sdev_devtree_lgen
#define sdev_origin sdev_ldata.sdev_lorigin
#define sdev_prof sdev_ldata.sdev_lprof
#define SDEV_FIRST_ENTRY(ddv) avl_first(&(ddv)->sdev_entries)
#define SDEV_NEXT_ENTRY(ddv, dv) AVL_NEXT(&(ddv)->sdev_entries, (dv))
typedef enum {
SDEV_ZOMBIE = -1,
SDEV_INIT = 0,
SDEV_READY
} sdev_node_state_t;
#define SDEV_LOOKUP 0x0001
#define SDEV_READDIR 0x0002
#define SDEV_LGWAITING 0x0004
#define SDEV_IS_GLOBAL(dv) \
(dv->sdev_flags & SDEV_GLOBAL)
#define SDEV_IS_PERSIST(dv) \
(dv->sdev_flags & SDEV_PERSIST)
#define SDEV_IS_DYNAMIC(dv) \
(dv->sdev_flags & SDEV_DYNAMIC)
#define SDEV_IS_NO_NCACHE(dv) \
(dv->sdev_flags & SDEV_NO_NCACHE)
#define SDEV_IS_LOOKUP(dv) \
(dv->sdev_lookup_flags & SDEV_LOOKUP)
#define SDEV_IS_READDIR(dv) \
(dv->sdev_lookup_flags & SDEV_READDIR)
#define SDEV_IS_LGWAITING(dv) \
(dv->sdev_lookup_flags & SDEV_LGWAITING)
#define SDEVTOV(n) ((struct vnode *)(n)->sdev_vnode)
#define VTOSDEV(vp) ((struct sdev_node *)(vp)->v_data)
#define VN_HELD(v) ((v)->v_count != 0)
#define SDEV_HELD(dv) (VN_HELD(SDEVTOV(dv)))
#define SDEV_HOLD(dv) VN_HOLD(SDEVTOV(dv))
#define SDEV_RELE(dv) VN_RELE(SDEVTOV(dv))
#define SDEV_SIMPLE_RELE(dv) { \
struct vnode *vp = SDEVTOV(dv); \
mutex_enter(&vp->v_lock); \
VN_RELE_LOCKED(vp); \
mutex_exit(&vp->v_lock); \
}
#define SDEV_ACL_FLAVOR(vp) (VFSTOSDEVFS(vp->v_vfsp)->sdev_acl_flavor)
#define SDEV_ROOTINO ((ino_t)2)
#define SDEV_UID_DEFAULT (0)
#define SDEV_GID_DEFAULT (3)
#define SDEV_DIRMODE_DEFAULT (S_IFDIR |0755)
#define SDEV_DEVMODE_DEFAULT (0600)
#define SDEV_LNKMODE_DEFAULT (S_IFLNK | 0777)
extern struct vattr sdev_vattr_dir;
extern struct vattr sdev_vattr_lnk;
extern struct vattr sdev_vattr_blk;
extern struct vattr sdev_vattr_chr;
extern int devname_lookup_func(struct sdev_node *, char *, struct vnode **,
struct cred *, int (*)(struct sdev_node *, char *, void **, struct cred *,
void *, char *), int);
#define SDEV_VATTR 0x4
#define SDEV_VLINK 0x8
extern int devname_readdir_func(vnode_t *, uio_t *, cred_t *, int *, int);
#define SDEV_BROWSE 0x1
extern int devname_setattr_func(struct vnode *, struct vattr *, int,
struct cred *, int (*)(struct sdev_node *, struct vattr *, int), int);
extern void devname_inactive_func(struct vnode *, struct cred *,
void (*)(struct vnode *));
struct sdev_data {
struct sdev_data *sdev_prev;
struct sdev_data *sdev_next;
struct sdev_node *sdev_root;
struct vfs *sdev_vfsp;
struct sdev_mountargs *sdev_mountargs;
ulong_t sdev_acl_flavor;
};
#define VFSTOSDEVFS(vfsp) ((struct sdev_data *)((vfsp)->vfs_data))
struct sdev_fid {
uint16_t sdevfid_len;
ino32_t sdevfid_ino;
int32_t sdevfid_gen;
};
typedef enum {
DEVNAME_DEVFSADM_STOPPED = 0,
DEVNAME_DEVFSADM_RUNNING,
DEVNAME_DEVFSADM_RUN
} devname_devfsadm_state_t;
extern volatile uint_t devfsadm_state;
#define DEVNAME_DEVFSADM_SET_RUNNING(devfsadm_state) \
(devfsadm_state = DEVNAME_DEVFSADM_RUNNING)
#define DEVNAME_DEVFSADM_SET_STOP(devfsadm_state) \
(devfsadm_state = DEVNAME_DEVFSADM_STOPPED)
#define DEVNAME_DEVFSADM_SET_RUN(devfsadm_state) \
(devfsadm_state = DEVNAME_DEVFSADM_RUN)
#define DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) \
(devfsadm_state == DEVNAME_DEVFSADM_RUNNING)
#define DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state) \
(devfsadm_state == DEVNAME_DEVFSADM_RUN)
#define SDEV_BLOCK_OTHERS(dv, cmd) { \
ASSERT(MUTEX_HELD(&dv->sdev_lookup_lock)); \
dv->sdev_lookup_flags |= cmd; \
}
extern void sdev_unblock_others(struct sdev_node *, uint_t);
#define SDEV_UNBLOCK_OTHERS(dv, cmd) { \
sdev_unblock_others(dv, cmd); \
}
#define SDEV_CLEAR_LOOKUP_FLAGS(dv, cmd) { \
dv->sdev_lookup_flags &= ~cmd; \
}
extern int sdev_wait4lookup(struct sdev_node *, int);
extern int devname_filename_register(char *);
extern int devname_nsmaps_register(char *, size_t);
extern void sdev_devfsadm_lockinit(void);
extern void sdev_devfsadm_lockdestroy(void);
extern void devname_add_devfsadm_node(char *);
extern void sdev_devfsadmd_thread(struct sdev_node *, struct sdev_node *,
struct cred *);
extern int devname_profile_update(char *, size_t);
extern struct sdev_data *sdev_find_mntinfo(char *);
void sdev_mntinfo_rele(struct sdev_data *);
typedef void (*sdev_mnt_walk_f)(struct sdev_node *, void *);
void sdev_mnt_walk(sdev_mnt_walk_f, void *);
extern struct vnodeops *devpts_getvnodeops(void);
extern struct vnodeops *devvt_getvnodeops(void);
extern void sdev_plugin_nodeready(struct sdev_node *);
extern int sdev_plugin_init(void);
extern int sdev_plugin_fini(void);
#define SDEV_BOOT_STATE_INITIAL 0
#define SDEV_BOOT_STATE_RECONFIG 1
#define SDEV_BOOT_STATE_SYSAVAIL 2
#define SDEV_BOOT_STATE_COMPLETE 3
typedef struct sdev_nc_list {
list_t ncl_list;
kmutex_t ncl_mutex;
krwlock_t ncl_lock;
int ncl_flags;
int ncl_nentries;
} sdev_nc_list_t;
typedef struct sdev_nc_node {
char *ncn_name;
int ncn_flags;
int ncn_expirecnt;
list_node_t ncn_link;
} sdev_nc_node_t;
#define NCL_LIST_DIRTY 0x01
#define NCL_LIST_WRITING 0x02
#define NCL_LIST_WENABLE 0x04
#define NCN_ACTIVE 0x01
#define NCN_SRC_STORE 0x02
#define NCN_SRC_CURRENT 0x04
#define SLF_NO_NCACHE 0x01
#define SLF_REBUILT 0x02
#define DP_DEVNAME_ID "devname"
#define DP_DEVNAME_NCACHE_ID "ncache"
#define DP_DEVNAME_NC_EXPIRECNT_ID "expire-counts"
typedef struct nvp_devname {
char **nvp_paths;
int *nvp_expirecnts;
int nvp_npaths;
list_node_t nvp_link;
} nvp_devname_t;
typedef enum {
SDEV_CACHE_ADD = 0,
SDEV_CACHE_DELETE
} sdev_cache_ops_t;
extern struct sdev_node *sdev_cache_lookup(struct sdev_node *, char *);
extern void sdev_cache_update(struct sdev_node *, struct sdev_node **, char *,
sdev_cache_ops_t);
extern void sdev_node_cache_init(void);
extern void sdev_node_cache_fini(void);
extern struct sdev_node *sdev_mkroot(struct vfs *, dev_t, struct vnode *,
struct vnode *, struct cred *);
extern void sdev_filldir_dynamic(struct sdev_node *);
extern int sdev_mknode(struct sdev_node *, char *, struct sdev_node **,
struct vattr *, struct vnode *, void *, struct cred *, sdev_node_state_t);
extern int sdev_getlink(struct vnode *linkvp, char **link);
extern int sdev_nodeinit(struct sdev_node *, char *, struct sdev_node **,
vattr_t *);
extern int sdev_nodeready(struct sdev_node *, vattr_t *, vnode_t *, void *,
cred_t *);
extern int sdev_shadow_node(struct sdev_node *, struct cred *);
extern void sdev_nodedestroy(struct sdev_node *, uint_t);
extern void sdev_update_timestamps(struct vnode *, cred_t *, uint_t);
extern void sdev_vattr_merge(struct sdev_node *, struct vattr *);
extern void sdev_devstate_change(void);
extern int sdev_lookup_filter(sdev_node_t *, char *);
extern void sdev_lookup_failed(sdev_node_t *, char *, int);
extern int sdev_unlocked_access(void *, int, struct cred *);
#define SDEV_ENFORCE 0x1
extern void sdev_stale(struct sdev_node *);
extern int sdev_cleandir(struct sdev_node *, char *, uint_t);
extern int sdev_rnmnode(struct sdev_node *, struct sdev_node *,
struct sdev_node *, struct sdev_node **, char *, struct cred *);
extern size_t add_dir_entry(dirent64_t *, char *, size_t, ino_t, offset_t);
extern struct vattr *sdev_getdefault_attr(enum vtype type);
extern int sdev_to_vp(struct sdev_node *, struct vnode **);
extern ino_t sdev_mkino(struct sdev_node *);
extern int devname_backstore_lookup(struct sdev_node *, char *,
struct vnode **);
extern int sdev_is_devfs_node(char *);
extern int sdev_copyin_mountargs(struct mounta *, struct sdev_mountargs *);
extern int sdev_reserve_subdirs(struct sdev_node *);
extern int prof_lookup();
extern void prof_filldir(struct sdev_node *);
extern int prof_name_matched(char *, struct sdev_node *);
extern int devpts_validate(struct sdev_node *dv);
extern int devnet_validate(struct sdev_node *dv);
extern int devipnet_validate(struct sdev_node *dv);
extern int devvt_validate(struct sdev_node *dv);
extern int devzvol_validate(struct sdev_node *dv);
extern void *sdev_get_vtor(struct sdev_node *dv);
extern int sdev_modctl_readdir(const char *, char ***, int *, int *, int);
extern void sdev_modctl_readdir_free(char **, int, int);
extern int sdev_modctl_devexists(const char *);
extern void sdev_ncache_init(void);
extern void sdev_ncache_setup(void);
extern void sdev_ncache_teardown(void);
extern void sdev_nc_addname(sdev_nc_list_t *, sdev_node_t *, char *, int);
extern void sdev_nc_node_exists(sdev_node_t *);
extern void sdev_nc_path_exists(sdev_nc_list_t *, char *);
extern void sdev_modctl_dump_files(void);
typedef struct sdev_vop_table {
char *vt_name;
const fs_operation_def_t *vt_service;
struct vnodeops **vt_global_vops;
int (*vt_vtor)(struct sdev_node *);
int vt_flags;
} sdev_vop_table_t;
extern struct sdev_vop_table vtab[];
extern struct vnodeops *sdev_get_vop(struct sdev_node *);
extern void sdev_set_no_negcache(struct sdev_node *);
extern void *sdev_get_vtor(struct sdev_node *dv);
extern kmutex_t sdev_lock;
extern int devtype;
extern kmem_cache_t *sdev_node_cache;
extern struct vnodeops *sdev_vnodeops;
extern struct vnodeops *devpts_vnodeops;
extern struct vnodeops *devnet_vnodeops;
extern struct vnodeops *devipnet_vnodeops;
extern struct vnodeops *devvt_vnodeops;
extern struct sdev_data *sdev_origins;
extern struct vnodeops *devzvol_vnodeops;
extern int sdev_vnodeops_tbl_size;
extern const fs_operation_def_t sdev_vnodeops_tbl[];
extern const fs_operation_def_t devpts_vnodeops_tbl[];
extern const fs_operation_def_t devnet_vnodeops_tbl[];
extern const fs_operation_def_t devipnet_vnodeops_tbl[];
extern const fs_operation_def_t devvt_vnodeops_tbl[];
extern const fs_operation_def_t devsys_vnodeops_tbl[];
extern const fs_operation_def_t devpseudo_vnodeops_tbl[];
extern const fs_operation_def_t devzvol_vnodeops_tbl[];
extern sdev_nc_list_t *sdev_ncache;
extern int sdev_reconfig_boot;
extern int sdev_boot_state;
extern int sdev_reconfig_verbose;
extern int sdev_reconfig_disable;
extern int sdev_nc_disable;
extern int sdev_nc_disable_reset;
extern int sdev_nc_verbose;
extern taskq_t *sdev_taskq;
#ifdef DEBUG
extern int sdev_debug;
#define SDEV_DEBUG 0x01
#define SDEV_DEBUG_VOPS 0x02
#define SDEV_DEBUG_DLF 0x04
#define SDEV_DEBUG_DRF 0x08
#define SDEV_DEBUG_NCACHE 0x10
#define SDEV_DEBUG_DEVFSADMD 0x20
#define SDEV_DEBUG_PTS 0x40
#define SDEV_DEBUG_RECONFIG 0x80
#define SDEV_DEBUG_SDEV_NODE 0x100
#define SDEV_DEBUG_PROFILE 0x200
#define SDEV_DEBUG_MODCTL 0x400
#define SDEV_DEBUG_FLK 0x800
#define SDEV_DEBUG_NET 0x1000
#define SDEV_DEBUG_ZVOL 0x2000
#define sdcmn_err(args) if (sdev_debug & SDEV_DEBUG) printf args
#define sdcmn_err2(args) if (sdev_debug & SDEV_DEBUG_VOPS) printf args
#define sdcmn_err3(args) if (sdev_debug & SDEV_DEBUG_DLF) printf args
#define sdcmn_err4(args) if (sdev_debug & SDEV_DEBUG_DRF) printf args
#define sdcmn_err5(args) if (sdev_debug & SDEV_DEBUG_NCACHE) printf args
#define sdcmn_err6(args) if (sdev_debug & SDEV_DEBUG_DEVFSADMD) printf args
#define sdcmn_err7(args) if (sdev_debug & SDEV_DEBUG_PTS) printf args
#define sdcmn_err8(args) if (sdev_debug & SDEV_DEBUG_RECONFIG) printf args
#define sdcmn_err9(args) if (sdev_debug & SDEV_DEBUG_SDEV_NODE) printf args
#define sdcmn_err10(args) if (sdev_debug & SDEV_DEBUG_PROFILE) printf args
#define sdcmn_err11(args) if (sdev_debug & SDEV_DEBUG_MODCTL) printf args
#define sdcmn_err12(args) if (sdev_debug & SDEV_DEBUG_NET) printf args
#define sdcmn_err13(args) if (sdev_debug & SDEV_DEBUG_ZVOL) printf args
#define impossible(args) printf args
#else
#define sdcmn_err(args) ((void)0)
#define sdcmn_err2(args) ((void)0)
#define sdcmn_err3(args) ((void)0)
#define sdcmn_err4(args) ((void)0)
#define sdcmn_err5(args) ((void)0)
#define sdcmn_err6(args) ((void)0)
#define sdcmn_err7(args) ((void)0)
#define sdcmn_err8(args) ((void)0)
#define sdcmn_err9(args) ((void)0)
#define sdcmn_err10(args) ((void)0)
#define sdcmn_err11(args) ((void)0)
#define sdcmn_err12(args) ((void)0)
#define sdcmn_err13(args) ((void)0)
#define impossible(args) ((void)0)
#endif
#ifdef DEBUG
#define SD_TRACE_FAILED_LOOKUP(ddv, nm, retried) \
if ((sdev_debug & SDEV_DEBUG_FLK) || \
((retried) && (sdev_debug & SDEV_DEBUG_RECONFIG))) { \
printf("lookup of %s/%s by %s failed, line %d\n", \
(ddv)->sdev_name, (nm), curproc->p_user.u_comm, \
__LINE__); \
}
#else
#define SD_TRACE_FAILED_LOOKUP(ddv, nm, retried) ((void)0)
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif