/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2014 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_FS_AUTOFS_H #define _SYS_FS_AUTOFS_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _KERNEL #include #endif #ifdef __cplusplus extern "C" { #endif #ifdef _KERNEL /* * Tracing macro; expands to nothing for non-debug kernels. */ #ifndef DEBUG #define AUTOFS_DPRINT(x) #else #define AUTOFS_DPRINT(x) auto_dprint x #endif /* * Per AUTOFS mountpoint information. */ typedef struct fninfo { struct vfs *fi_mountvfs; /* mounted-here VFS */ struct vnode *fi_rootvp; /* root vnode */ struct knetconfig fi_knconf; /* netconfig */ struct netbuf fi_addr; /* daemon address */ char *fi_path; /* autofs mountpoint */ char *fi_map; /* context/map-name */ char *fi_subdir; /* subdir within map */ char *fi_key; /* key to use on direct maps */ char *fi_opts; /* default mount options */ int fi_pathlen; /* autofs mountpoint len */ int fi_maplen; /* size of context */ int fi_subdirlen; int fi_keylen; int fi_optslen; /* default mount options len */ int fi_refcnt; /* reference count */ int fi_flags; int fi_mount_to; int fi_rpc_to; zoneid_t fi_zoneid; /* zone mounted in */ } fninfo_t; /* * The AUTOFS locking scheme: * * The locks: * fn_lock: protects the fn_node. It must be grabbed to change any * field on the fn_node, except for those protected by * fn_rwlock. * * fn_rwlock: readers/writers lock to protect the subdirectory and * top level list traversal. * Protects: fn_dirents * fn_next * fn_size * fn_linkcnt * - Grab readers when checking if certain fn_node exists * under fn_dirents. * - Grab readers when attempting to reference a node * pointed to by fn_dirents, fn_next, and fn_parent. * - Grab writers to add a new fnnode under fn_dirents and * to remove a node pointed to by fn_dirents or fn_next. * * Lock ordering: * fn_rwlock > fn_lock * * The flags: * MF_INPROG: * - Indicates a mount request has been sent to the daemon. * - If this flag is set, the thread sets MF_WAITING on the * fnnode and sleeps. * * MF_WAITING: * - Set by a thread when it puts itself to sleep waiting for * the ongoing operation on this fnnode to be done. * * MF_LOOKUP: * - Indicates a lookup request has been sent to the daemon. * - If this flag is set, the thread sets MF_WAITING on the * fnnode and sleeps. * * MF_IK_MOUNT: * - This flag is set to indicate the mount was done in the * kernel, and so should the unmount. * * MF_DIRECT: * - Direct mountpoint if set, indirect otherwise. * * MF_TRIGGER: * - This is a trigger node. * * MF_THISUID_MATCH_RQD: * - User-relative context binding kind of node. * - Node with this flag set requires a name match as well * as a cred match in order to be returned from the directory * hierarchy. * * MF_MOUNTPOINT: * - At some point automountd mounted a filesystem on this node. * If fn_trigger is non-NULL, v_vfsmountedhere is NULL and this * flag is set then the filesystem must have been forcibly * unmounted. */ /* * The inode of AUTOFS */ typedef struct fnnode { char *fn_name; char *fn_symlink; /* if VLNK, this is what it */ /* points to */ int fn_namelen; int fn_symlinklen; uint_t fn_linkcnt; /* link count */ mode_t fn_mode; /* file mode bits */ uid_t fn_uid; /* owner's uid */ gid_t fn_gid; /* group's uid */ int fn_error; /* mount/lookup error */ ino_t fn_nodeid; off_t fn_offset; /* offset into directory */ int fn_flags; uint_t fn_size; /* size of directory */ struct vnode *fn_vnode; struct fnnode *fn_parent; struct fnnode *fn_next; /* sibling */ struct fnnode *fn_dirents; /* children */ struct fnnode *fn_trigger; /* pointer to next level */ /* AUTOFS trigger nodes */ struct action_list *fn_alp; /* Pointer to mount info */ /* used for remounting */ /* trigger nodes */ cred_t *fn_cred; /* pointer to cred, used for */ /* "thisuser" processing */ krwlock_t fn_rwlock; /* protects list traversal */ kmutex_t fn_lock; /* protects the fnnode */ timestruc_t fn_atime; timestruc_t fn_mtime; timestruc_t fn_ctime; time_t fn_ref_time; /* time last referenced */ time_t fn_unmount_ref_time; /* last time unmount was done */ kcondvar_t fn_cv_mount; /* mount blocking variable */ struct vnode *fn_seen; /* vnode already traversed */ kthread_t *fn_thread; /* thread that has currently */ /* modified fn_seen */ struct autofs_globals *fn_globals; /* global variables */ } fnnode_t; #define vntofn(vp) ((struct fnnode *)((vp)->v_data)) #define fntovn(fnp) (((fnp)->fn_vnode)) #define vfstofni(vfsp) ((struct fninfo *)((vfsp)->vfs_data)) #define MF_DIRECT 0x001 #define MF_INPROG 0x002 /* Mount in progress */ #define MF_WAITING 0x004 #define MF_LOOKUP 0x008 /* Lookup in progress */ #define MF_ATTR_WAIT 0x010 #define MF_IK_MOUNT 0x040 #define MF_TRIGGER 0x080 #define MF_THISUID_MATCH_RQD 0x100 /* UID match required for this node */ /* required for thisuser kind of */ /* nodes */ #define MF_MOUNTPOINT 0x200 /* Node is/was a mount point */ #define AUTOFS_MODE 0555 #define AUTOFS_BLOCKSIZE 1024 struct autofs_callargs { fnnode_t *fnc_fnp; /* fnnode */ char *fnc_name; /* path to lookup/mount */ kthread_t *fnc_origin; /* thread that fired up this thread */ /* used for debugging purposes */ cred_t *fnc_cred; }; struct autofs_globals { fnnode_t *fng_rootfnnodep; int fng_fnnode_count; int fng_printed_not_running_msg; kmutex_t fng_unmount_threads_lock; int fng_unmount_threads; int fng_verbose; zoneid_t fng_zoneid; pid_t fng_autofs_pid; kmutex_t fng_autofs_daemon_lock; /* * autofs_daemon_lock protects fng_autofs_daemon_dh */ door_handle_t fng_autofs_daemon_dh; }; extern kmutex_t autofs_minor_lock; extern zone_key_t autofs_key; /* * Sets the MF_INPROG flag on this fnnode. * fnp->fn_lock should be held before this macro is called, * operation is either MF_INPROG or MF_LOOKUP. */ #define AUTOFS_BLOCK_OTHERS(fnp, operation) { \ ASSERT(MUTEX_HELD(&(fnp)->fn_lock)); \ ASSERT(!((fnp)->fn_flags & operation)); \ (fnp)->fn_flags |= (operation); \ } #define AUTOFS_UNBLOCK_OTHERS(fnp, operation) { \ auto_unblock_others((fnp), (operation)); \ } extern struct vnodeops *auto_vnodeops; extern const struct fs_operation_def auto_vnodeops_template[]; /* * Utility routines */ extern int auto_search(fnnode_t *, char *, fnnode_t **, cred_t *); extern int auto_enter(fnnode_t *, char *, fnnode_t **, cred_t *); extern void auto_unblock_others(fnnode_t *, uint_t); extern int auto_wait4mount(fnnode_t *); extern fnnode_t *auto_makefnnode(vtype_t, vfs_t *, char *, cred_t *, struct autofs_globals *); extern void auto_freefnnode(fnnode_t *); extern void auto_disconnect(fnnode_t *, fnnode_t *); extern void auto_do_unmount(struct autofs_globals *); /*PRINTFLIKE4*/ extern void auto_log(int verbose, zoneid_t zoneid, int level, const char *fmt, ...) __KPRINTFLIKE(4); /*PRINTFLIKE2*/ extern void auto_dprint(int level, const char *fmt, ...) __KPRINTFLIKE(2); extern int auto_calldaemon(zoneid_t, int, xdrproc_t, void *, xdrproc_t, void *, int, bool_t); extern int auto_lookup_aux(fnnode_t *, char *, cred_t *); extern void auto_new_mount_thread(fnnode_t *, char *, cred_t *); extern int auto_nobrowse_option(char *); extern int unmount_subtree(fnnode_t *, boolean_t); extern void unmount_tree(struct autofs_globals *, boolean_t); extern void autofs_free_globals(struct autofs_globals *); extern void autofs_shutdown_zone(struct autofs_globals *); #endif /* _KERNEL */ /* * autofs structures and defines needed for use with doors. */ #define AUTOFS_NULL 0 #define AUTOFS_MOUNT 1 #define AUTOFS_UNMOUNT 2 #define AUTOFS_READDIR 3 #define AUTOFS_LOOKUP 4 #define AUTOFS_SRVINFO 5 #define AUTOFS_MNTINFO 6 /* * autofs_door_args is a generic structure used to grab the command * from any of the argument structures passed in. */ typedef struct { int cmd; int xdr_len; char xdr_arg[1]; /* buffer holding xdr encoded data */ } autofs_door_args_t; typedef struct { int res_status; int xdr_len; char xdr_res[1]; /* buffer holding xdr encoded data */ } autofs_door_res_t; typedef enum autofs_res autofs_res_t; typedef enum autofs_stat autofs_stat_t; typedef enum autofs_action autofs_action_t; typedef struct { void * atsd_buf; size_t atsd_len; } autofs_tsd_t; typedef struct sec_desdata { int nd_sec_syncaddr_len; int nd_sec_knc_semantics; int nd_sec_netnamelen; uint64_t nd_sec_knc_rdev; int nd_sec_knc_unused[8]; } sec_desdata_t; typedef struct sec_gssdata { int element_length; rpc_gss_service_t service; char uname[MAX_NAME_LEN]; char inst[MAX_NAME_LEN]; char realm[MAX_NAME_LEN]; uint_t qop; } sec_gssdata_t; typedef struct nfs_secdata { sec_desdata_t nfs_des_clntdata; sec_gssdata_t nfs_gss_clntdata; } nfs_secdata_t; /* * Comma separated list of mntoptions which are inherited when the * "restrict" option is present. The RESTRICT option must be first! * This define is shared between the kernel and the automount daemon. */ #define RESTRICTED_MNTOPTS \ MNTOPT_RESTRICT, MNTOPT_NOSUID, MNTOPT_NOSETUID, MNTOPT_NODEVICES /* * AUTOFS syscall entry point */ enum autofssys_op { AUTOFS_UNMOUNTALL, AUTOFS_SETDOOR }; #ifdef _KERNEL extern int autofssys(enum autofssys_op, uintptr_t); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_AUTOFS_H */ /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright (c) 2014 Joyent, Inc. All rights reserved. */ #ifndef _SYS_FS_BOOTFS_IMPL_H #define _SYS_FS_BOOTFS_IMPL_H #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * The bootfs node is the file system specific version of the vnode for the * bootfs file system. Because the bootfs file system is entirely a read-only * file system, this structure requires no locking as the contents are * immutable. */ typedef struct bootfs_node { char *bvn_name; /* entry name */ struct vnode *bvn_vnp; /* Corresponding vnode */ avl_tree_t bvn_dir; /* directory entries, if VDIR */ avl_node_t bvn_link; /* dirent link */ list_node_t bvn_alink; /* link for all nodes */ uint64_t bvn_addr; /* Address in pmem */ uint64_t bvn_size; /* Size of the file */ struct bootfs_node *bvn_parent; /* .. */ vattr_t bvn_attr; /* attributes for the node */ } bootfs_node_t; typedef struct bootfs_stat { kstat_named_t bfss_nfiles; kstat_named_t bfss_ndirs; kstat_named_t bfss_nbytes; kstat_named_t bfss_ndups; kstat_named_t bfss_ndiscards; } bootfs_stat_t; typedef struct bootfs { vfs_t *bfs_vfsp; char *bfs_mntpath; bootfs_node_t *bfs_rootvn; kstat_t *bfs_kstat; list_t bfs_nodes; minor_t bfs_minor; uint_t bfs_ninode; bootfs_stat_t bfs_stat; } bootfs_t; extern void bootfs_construct(bootfs_t *); extern void bootfs_destruct(bootfs_t *); extern int bootfs_node_constructor(void *, void *, int); extern void bootfs_node_destructor(void *, void *); extern struct vnodeops *bootfs_vnodeops; extern const fs_operation_def_t bootfs_vnodeops_template[]; extern kmem_cache_t *bootfs_node_cache; extern major_t bootfs_major; #ifdef __cplusplus } #endif #endif /* _SYS_FS_BOOTFS_IMPL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_DECOMP_H #define _SYS_DECOMP_H #ifdef __cplusplus extern "C" { #endif #define CH_MAGIC_ZLIB 0x5a636d70 /* ZLIB compression */ #define CH_MAGIC_GZIP 0x8B1F /* GZIP compression */ #define CH_VERSION 1 #define CH_ALG_ZLIB 1 struct comphdr { uint64_t ch_magic; uint64_t ch_version; uint64_t ch_algorithm; uint64_t ch_fsize; uint64_t ch_blksize; uint64_t ch_blkmap[1]; }; #define ZMAXBUF(n) ((n) + ((n) / 1000) + 12) #ifdef _KERNEL struct dcnode { struct vnode *dc_vp; struct vnode *dc_subvp; struct kmem_cache *dc_bufcache; kmutex_t dc_lock; struct dcnode *dc_hash; struct dcnode *dc_lrunext; struct dcnode *dc_lruprev; struct comphdr *dc_hdr; size_t dc_hdrsize; size_t dc_zmax; int dc_mapcnt; }; #define VTODC(vp) ((struct dcnode *)(vp)->v_data) #define DCTOV(dp) ((dp)->dc_vp) struct vnode *decompvp(struct vnode *, struct cred *, caller_context_t *); #endif #ifdef __cplusplus } #endif #endif /* _SYS_DECOMP_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_DV_NODE_H #define _SYS_DV_NODE_H /* * dv_nodes are the file-system specific part of the * vnodes for the device filesystem. * * The device filesystem exports two node types: * * VDIR nodes to represent nexus drivers * VCHR & VBLK nodes to represent devices */ #include #include #include #include #include #include #include #ifdef _KERNEL #include #endif #ifdef __cplusplus extern "C" { #endif #ifdef _KERNEL /* * Here's the focal point of this filesystem */ typedef struct dv_node { char *dv_name; /* pointer to name */ size_t dv_namelen; /* strlen(dv_name) */ struct vnode *dv_vnode; /* vnode for this dv_node */ /* * The dv_contents lock should be held (read) before looking at * any of the fields below, and held (write) before modifying them. */ krwlock_t dv_contents; /* held while anything is changing */ dev_info_t *dv_devi; /* VDIR: underlying devinfo node */ /* has ndi_devi_hold on device */ struct dv_node *dv_dotdot; /* parent: my parent dv_node */ avl_tree_t dv_entries; /* VDIR: contents as avl tree */ avl_node_t dv_avllink; /* avl node linkage */ struct vnode *dv_attrvp; /* persistent attribute store */ struct vattr *dv_attr; /* attributes not yet persistent */ ino64_t dv_ino; /* fake inode */ int dv_flags; /* state bits and stuff */ uint_t dv_nlink; /* link count */ uint_t dv_busy; /* directory busy count */ devplcy_t *dv_priv; /* access privilege */ mode_t dv_dflt_mode; /* create_priv_minor_node mode */ struct sdev_dv *dv_sdev; /* sdev node[s] if exists */ } dvnode_t; #define DV_BUILD 0x1 /* directory out-of-date */ #define DV_NO_FSPERM 0x2 /* ignore fs permissions */ #define DV_INTERNAL 0x04 /* internal node */ #define DV_ACL 0x08 /* node has acl */ #define DV_DFLT_MODE 0x010 /* dv_dflt_mode set */ #define DV_ROOTINO ((ino_t)2) /* root inode no. for devfs */ #define DVTOV(n) ((struct vnode *)(n)->dv_vnode) #define VTODV(vp) ((struct dv_node *)(vp)->v_data) #define DV_STALE(dv) (dv->dv_devi == NULL) #define DV_UID_DEFAULT 0 /* default uid for devs and dirs */ #define DV_GID_DEFAULT 3 /* default gid for devs and dirs */ #define DV_DIRMODE_DEFAULT (S_IFDIR | 0755) /* directories */ #define DV_DEVMODE_DEFAULT (0600) /* special files */ #define DV_DEVMODE_PRIV (0666) /* priv based access only */ /* flags for devfs_clean() */ #define DV_CLEAN_FORCE 0x01 /* force clean of refed directories */ #define DV_RESET_PERM 0x02 /* force resetting of node permission */ #define DV_CLEANDIR_LCK 0x04 /* dv_contents already held */ struct devfs_data { struct dv_node *devfs_root; struct vfs *devfs_vfsp; }; #define VFSTODVFS(vfsp) ((struct devfs_data *)((vfsp)->vfs_data)) /* dv_fid overlays the fid structure (for VFS_VGET) */ struct dv_fid { uint16_t dvfid_len; ino32_t dvfid_ino; int32_t dvfid_gen; }; /* * Compare a vattr's and mperm_t's minor permissions (uid, gid & mode) */ #define VATTRP_MP_CMP(attrp, mp) \ (!((attrp->va_uid == mp.mp_uid) && \ (attrp->va_gid == mp.mp_gid) && \ ((attrp->va_mode & S_IAMB) == (mp.mp_mode & S_IAMB)))) /* * Merge an mperm_t's minor permissions into a vattr */ #define VATTR_MP_MERGE(attr, mp) \ attr.va_uid = mp.mp_uid; \ attr.va_gid = mp.mp_gid; \ attr.va_mode = \ (attr.va_mode & ~S_IAMB) | (mp.mp_mode & S_IAMB); #define VATTRP_MP_MERGE(attrp, mp) \ attrp->va_uid = mp.mp_uid; \ attrp->va_gid = mp.mp_gid; \ attrp->va_mode = \ (attrp->va_mode & ~S_IAMB) | (mp.mp_mode & S_IAMB); /* * dv_shadow_node flags */ #define DV_SHADOW_CREATE 0x01 /* create attribute node */ #define DV_SHADOW_WRITE_HELD 0x02 /* dv_contents write held */ /* * Directory tree traversal */ #define DV_FIRST_ENTRY(ddv) avl_first(&(ddv)->dv_entries) #define DV_NEXT_ENTRY(ddv, dv) AVL_NEXT(&(ddv)->dv_entries, (dv)) extern uint_t devfs_clean_key; /* tsd key */ extern const char dvnm[]; /* share some space.. */ extern struct dv_node *dvroot; /* devfs root node */ extern void dv_node_cache_init(void); extern void dv_node_cache_fini(void); extern struct dv_node *dv_mkdir(struct dv_node *, dev_info_t *, char *); extern struct dv_node *dv_mkroot(struct vfs *, dev_t); extern void dv_destroy(struct dv_node *, uint_t); extern void dv_insert(struct dv_node *, struct dv_node *); extern void dv_shadow_node(struct vnode *, char *nm, struct vnode *, struct pathname *, struct vnode *, struct cred *, int); extern int dv_find(struct dv_node *, char *, struct vnode **, struct pathname *, struct vnode *, struct cred *, uint_t); extern void dv_filldir(struct dv_node *); extern int dv_cleandir(struct dv_node *, char *, uint_t); extern void dv_vattr_merge(struct dv_node *, struct vattr *); extern void dv_walk(struct dv_node *, char *, void (*f)(struct dv_node *, void *), void *); extern int devfs_clean(dev_info_t *, char *, uint_t); extern int devfs_lookupname(char *, vnode_t **, vnode_t **); extern int devfs_walk(char *, void (*f)(struct dv_node *, void *), void *); extern int devfs_devpolicy(vnode_t *, devplcy_t **); extern void devfs_get_defattr(vnode_t *, struct vattr *, int *); extern struct dv_node *devfs_dip_to_dvnode(dev_info_t *); extern int devfs_reset_perm(uint_t); extern int devfs_remdrv_cleanup(const char *, const char *); extern struct vnodeops *dv_vnodeops; extern const struct fs_operation_def dv_vnodeops_template[]; #ifdef DEBUG extern int devfs_debug; #define DV_DEBUG 0x01 #define DV_DEBUG2 0x02 #define DV_DEBUG3 0x04 #define DV_DEBUG4 0x08 #define DV_DEBUG5 0x10 #define DV_SYSERR 0x1000 #define DV_SYSTRACE 0x2000 #define dcmn_err(args) if (devfs_debug & DV_DEBUG) printf args #define dcmn_err2(args) if (devfs_debug & DV_DEBUG2) printf args #define dcmn_err3(args) if (devfs_debug & DV_DEBUG3) printf args #define dcmn_err4(args) if (devfs_debug & DV_DEBUG4) printf args #define dcmn_err5(args) if (devfs_debug & DV_DEBUG5) printf args #define dsysdebug(err, args) \ if ((err && (devfs_debug & DV_SYSERR)) || \ (devfs_debug & DV_SYSTRACE)) printf args #else #define dcmn_err(args) /* nothing */ #define dcmn_err2(args) /* nothing */ #define dcmn_err3(args) /* nothing */ #define dcmn_err4(args) /* nothing */ #define dcmn_err5(args) /* nothing */ #define dsysdebug(err, args) /* nothing */ #endif #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_DV_NODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #ifndef _SYS_FS_FIFONODE_H #define _SYS_FS_FIFONODE_H #if defined(_KERNEL) #include #endif #ifdef __cplusplus extern "C" { #endif /* * Each FIFOFS object is identified by a struct fifonode/vnode pair. * This is also the hierarchy * flk_lock protects: * fn_mp * fn_tail * fn_count * fn_flag * fn_wcnt * fn_rcnt * fn_open * fn_rsynccnt * fn_wsynccnt * fn_wwaitcnt * fn_atime * fn_mtime * fn_ctime * fn_insync * flk_ref * flk_ocsync * ftable lock protects - actually this is independent * fifoalloc[] * fn_nextp * fn_backp */ typedef struct fifolock { kmutex_t flk_lock; /* fifo lock */ int flk_ref; /* number of fifonodes using this */ short flk_ocsync; /* sync open/close */ kcondvar_t flk_wait_cv; /* conditional for flk_ocsync */ uint_t flk_fill[4]; /* cache align lock structure */ } fifolock_t; typedef struct fifonode fifonode_t; struct fifonode { struct vnode *fn_vnode; /* represents the fifo/pipe */ struct vnode *fn_realvp; /* node being shadowed by fifo */ ino_t fn_ino; /* node id for pipes */ fifonode_t *fn_dest; /* the other end of a pipe */ struct msgb *fn_mp; /* message waiting to be read */ struct msgb *fn_tail; /* last message to read */ fifolock_t *fn_lock; /* pointer to per fifo lock */ uint_t fn_count; /* Number of bytes on fn_mp */ kcondvar_t fn_wait_cv; /* fifo conditional variable */ ushort_t fn_wcnt; /* number of writers */ ushort_t fn_rcnt; /* number of readers */ ushort_t fn_open; /* open count of node */ ushort_t fn_wsynccnt; /* fifos waiting for open write sync */ ushort_t fn_rsynccnt; /* fifos waiting for open read sync */ ushort_t fn_wwaitcnt; /* threads waiting to write data */ timestruc_t fn_atime; /* access times */ timestruc_t fn_mtime; /* modification time */ timestruc_t fn_ctime; /* change time */ fifonode_t *fn_nextp; /* next link in the linked list */ fifonode_t *fn_backp; /* back link in linked list */ struct cred *fn_pcredp; /* credential associated with peer */ pid_t fn_cpid; /* original peer pid */ int fn_insync; uint_t fn_flag; /* flags as defined below */ }; typedef struct fifodata { fifolock_t fifo_lock; fifonode_t fifo_fnode[2]; } fifodata_t; /* * Valid flags for fifonodes. */ #define ISPIPE 0x0001 /* fifonode is that of a pipe */ #define FIFOSEND 0x0002 /* file descriptor at stream head of pipe */ #define FIFOOPEN 0x0004 /* fifo is opening */ #define FIFOCLOSE 0x0008 /* fifo is closing */ #define FIFOCONNLD 0x0010 /* connld pushed on pipe */ #define FIFOFAST 0x0020 /* FIFO in fast mode */ #define FIFOWANTR 0x0040 /* reader waiting for data */ #define FIFOWANTW 0x0080 /* writer waiting to write */ #define FIFOSETSIG 0x0100 /* I_SETSIG ioctl was issued */ #define FIFOHIWATW 0x0200 /* We have gone over hi water mark */ #define FIFORWBUSY 0x0400 /* Fifo is busy in read or write */ #define FIFOPOLLW 0x0800 /* process waiting on poll write */ #define FIFOPOLLR 0x1000 /* process waiting on poll read */ #define FIFOISOPEN 0x2000 /* pipe is open */ #define FIFOSYNC 0x4000 /* FIFO is waiting for open sync */ #define FIFOWOCR 0x8000 /* Write open occurred */ #define FIFOROCR 0x10000 /* Read open occurred */ /* * process waiting on poll read on band data * this can only occur if we go to streams * mode */ #define FIFOPOLLRBAND 0x20000 #define FIFOSTAYFAST 0x40000 /* don't turn into stream mode */ #define FIFOWAITMODE 0x80000 /* waiting for the possibility to change mode */ #define FIFOHIWAT (16 * 1024) #define FIFOLOWAT (0) /* * Macros to convert a vnode to a fifnode, and vice versa. */ #define VTOF(vp) ((struct fifonode *)((vp)->v_data)) #define FTOV(fp) ((fp)->fn_vnode) #if defined(_KERNEL) /* * Fifohiwat defined as a variable is to allow tuning of the high * water mark if needed. It is not meant to be released. */ #if FIFODEBUG extern int Fifohiwat; #else /* FIFODEBUG */ #define Fifohiwat FIFOHIWAT #endif /* FIFODEBUG */ extern struct vnodeops *fifo_vnodeops; extern const struct fs_operation_def fifo_vnodeops_template[]; extern struct kmem_cache *fnode_cache; extern struct kmem_cache *pipe_cache; struct vfssw; struct queue; extern int fifoinit(int, char *); extern int fifo_stropen(vnode_t **, int, cred_t *, int, int); extern int fifo_open(vnode_t **, int, cred_t *, caller_context_t *); extern int fifo_close(vnode_t *, int, int, offset_t, cred_t *, caller_context_t *); extern void fifo_cleanup(vnode_t *, int); extern void fiforemove(fifonode_t *); extern ino_t fifogetid(void); extern vnode_t *fifovp(vnode_t *, cred_t *); extern void makepipe(vnode_t **, vnode_t **); extern void fifo_fastflush(fifonode_t *); extern void fifo_vfastoff(vnode_t *); extern void fifo_fastoff(fifonode_t *); extern struct streamtab *fifo_getinfo(); extern void fifo_wakereader(fifonode_t *, fifolock_t *); extern void fifo_wakewriter(fifonode_t *, fifolock_t *); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_FIFONODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * High Sierra filesystem internal routine definitions. */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_HSFS_IMPL_H #define _SYS_FS_HSFS_IMPL_H #include #ifdef __cplusplus extern "C" { #endif /* * global routines. */ extern int hsfs_putapage(vnode_t *, page_t *, u_offset_t *, size_t *, int, cred_t *); /* read a sector */ extern int hs_readsector(struct vnode *vp, uint_t secno, uchar_t *ptr); /* lookup/construct an hsnode/vnode */ extern struct vnode *hs_makenode(struct hs_direntry *dp, uint_t lbn, uint_t off, struct vfs *vfsp); /* make hsnode from directory lbn/off */ extern int hs_remakenode(uint_t lbn, uint_t off, struct vfs *vfsp, struct vnode **vpp); /* lookup name in directory */ extern int hs_dirlook(struct vnode *dvp, char *name, int namlen, struct vnode **vpp, struct cred *cred); /* find an hsnode in the hash list */ extern struct vnode *hs_findhash(ino64_t nodeid, uint_t lbn, uint_t off, struct vfs *vfsp); /* destroy an hsnode */ extern void hs_freenode(vnode_t *vp, struct hsfs *fsp, int nopage); /* parse a directory entry */ extern int hs_parsedir(struct hsfs *fsp, uchar_t *dirp, struct hs_direntry *hdp, char *dnp, int *dnlen, int last_offset); /* convert d-characters */ extern int hs_namecopy(char *from, char *to, int size, ulong_t flags); extern int hs_jnamecopy(char *from, char *to, int size, int maxsize, ulong_t flags); extern int hs_joliet_cp(char *from, char *to, int size); /* destroy the incore hnode table */ extern void hs_filldirent(struct vnode *vp, struct hs_direntry *hdp); /* check vnode protection */ extern int hs_access(struct vnode *vp, mode_t m, struct cred *cred); extern int hs_synchash(struct vfs *vfsp); extern void hs_parse_dirdate(uchar_t *dp, struct timeval *tvp); extern void hs_parse_longdate(uchar_t *dp, struct timeval *tvp); extern int hs_uppercase_copy(char *from, char *to, int size); extern void hs_log_bogus_disk_warning(struct hsfs *fsp, int errtype, uint_t data); extern int hsfs_valid_dir(struct hs_direntry *hd); extern void hs_init_hsnode_cache(void); extern void hs_fini_hsnode_cache(void); /* * Global data structures */ extern const struct fs_operation_def hsfs_vnodeops_template[]; extern struct vnodeops *hsfs_vnodeops; extern kmutex_t hs_mounttab_lock; extern struct hsfs *hs_mounttab; #ifdef __cplusplus } #endif #endif /* _SYS_FS_HSFS_IMPL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_HSFS_ISOSPEC_H #define _SYS_FS_HSFS_ISOSPEC_H /* * ISO 9660 filesystem specification */ #ifdef __cplusplus extern "C" { #endif /* macros to parse binary integers */ #define ZERO(x) (uint_t)(((uchar_t *)(x))[0]) #define ONE(x) (uint_t)(((uchar_t *)(x))[1]) #define TWO(x) (uint_t)(((uchar_t *)(x))[2]) #define THREE(x) (uint_t)(((uchar_t *)(x))[3]) #define MSB_INT(x) \ ((((((ZERO(x) << 8) | ONE(x)) << 8) | TWO(x)) << 8) | THREE(x)) #define LSB_INT(x) \ ((((((THREE(x) << 8) | TWO(x)) << 8) | ONE(x)) << 8) | ZERO(x)) #define MSB_SHORT(x) ((ZERO(x) << 8) | ONE(x)) #define LSB_SHORT(x) ((ONE(x) << 8) | ZERO(x)) #if defined(__i386) || defined(__amd64) #define BOTH_SHORT(x) (short)*((short *)x) #define BOTH_INT(x) (int)*((int *)x) #elif defined(__sparc) /* * SPARC machines require that integers must * be aligned on a full word boundary. CD-ROM data aligns * to even word boundary only. Because of this mismatch, * we have to move integer data from CD-ROM to memory one * byte at a time. LSB data starts first. We therefore * use this to do byte by byte copying. */ #define BOTH_SHORT(x) LSB_SHORT(x) #define BOTH_INT(x) LSB_INT(x) #endif /* * The following describes actual on-disk structures. * To achieve portability, all structures are #defines * rather than a structure definition. Macros are provided * to get either the data or address of individual fields. */ /* Overall High Sierra disk structure */ #define ISO_SECTOR_SIZE 2048 /* bytes per logical sector */ #define ISO_SECTOR_SHIFT 11 /* sector<->byte shift count */ #define ISO_SEC_PER_PAGE (PAGESIZE/HS_SECTOR_SIZE) /* sectors per page */ #define ISO_SYSAREA_SEC 0 /* 1st sector of system area */ #define ISO_VOLDESC_SEC 16 /* 1st sector of volume descriptors */ #define MAXISOOFFSET (ISO_SECTOR_SIZE - 1) #define MAXISOMASK (~MAXISOOFFSET) /* Standard File Structure Volume Descriptor */ enum iso_voldesc_type { ISO_VD_BOOT = 0, ISO_VD_PVD = 1, ISO_VD_SVD = 2, ISO_VD_VPD = 3, ISO_VD_UNIX = 4, /* UNIX extension */ ISO_VD_EOV = 255 }; #define ISO_ID_STRING "CD001" /* ISO_std_id field */ #define ISO_ID_STRLEN 5 /* ISO_std_id field length */ #define ISO_ID_VER 1 /* ISO_std_ver field ISO-9660:1988 */ #define ISO_ID_VER2 2 /* ISO_std_ver field ISO-9660:1999 */ #define ISO_FILE_STRUCT_ID_VER 1 /* ISO_file structure version field */ #define ISO_SYS_ID_STRLEN 32 #define ISO_VOL_ID_STRLEN 32 #define ISO_VOL_SET_ID_STRLEN 128 #define ISO_PUB_ID_STRLEN 128 #define ISO_PREP_ID_STRLEN 128 #define ISO_APPL_ID_STRLEN 128 #define ISO_COPYR_ID_STRLEN 37 #define ISO_ABSTR_ID_STRLEN 37 #define ISO_SHORT_DATE_LEN 7 #define ISO_DATE_LEN 17 /* macros to get the address of each field */ #define ISO_desc_type(x) (&((uchar_t *)x)[0]) #define ISO_std_id(x) (&((uchar_t *)x)[1]) #define ISO_std_ver(x) (&((uchar_t *)x)[6]) #define ISO_sys_id(x) (&((uchar_t *)x)[8]) #define ISO_vol_id(x) (&((uchar_t *)x)[40]) #define ISO_vol_size(x) (&((uchar_t *)x)[80]) #define ISO_svd_esc(x) (&((uchar_t *)x)[88]) /* Supplemental VD */ #define ISO_set_size(x) (&((uchar_t *)x)[120]) #define ISO_set_seq(x) (&((uchar_t *)x)[124]) #define ISO_blk_size(x) (&((uchar_t *)x)[128]) #define ISO_ptbl_size(x) (&((uchar_t *)x)[132]) #define ISO_ptbl_man_ls(x) (&((uchar_t *)x)[140]) #define ISO_ptbl_opt_ls1(x) (&((uchar_t *)x)[144]) #define ISO_ptbl_man_ms(x) (&((uchar_t *)x)[148]) #define ISO_ptbl_opt_ms1(x) (&((uchar_t *)x)[152]) #define ISO_root_dir(x) (&((uchar_t *)x)[156]) #define ISO_vol_set_id(x) (&((uchar_t *)x)[190]) #define ISO_pub_id(x) (&((uchar_t *)x)[318]) #define ISO_prep_id(x) (&((uchar_t *)x)[446]) #define ISO_appl_id(x) (&((uchar_t *)x)[574]) #define ISO_copyr_id(x) (&((uchar_t *)x)[702]) #define ISO_abstr_id(x) (&((uchar_t *)x)[739]) #define ISO_bibli_id(x) (&((uchar_t *)x)[776]) #define ISO_cre_date(x) (&((uchar_t *)x)[813]) #define ISO_mod_date(x) (&((uchar_t *)x)[830]) #define ISO_exp_date(x) (&((uchar_t *)x)[847]) #define ISO_eff_date(x) (&((uchar_t *)x)[864]) #define ISO_file_struct_ver(x) (&((uchar_t *)x)[881]) /* macros to get the values of each field (strings are returned as ptrs) */ #define ISO_DESC_TYPE(x) ((enum iso_voldesc_type)*(ISO_desc_type(x))) #define ISO_STD_ID(x) ISO_std_id(x) #define ISO_STD_VER(x) *(ISO_std_ver(x)) #define ISO_SYS_ID(x) ISO_sys_id(x) #define ISO_VOL_ID(x) ISO_vol_id(x) #define ISO_VOL_SIZE(x) BOTH_INT(ISO_vol_size(x)) #define ISO_SET_SIZE(x) BOTH_SHORT(ISO_set_size(x)) #define ISO_SET_SEQ(x) BOTH_SHORT(ISO_set_seq(x)) #define ISO_BLK_SIZE(x) BOTH_SHORT(ISO_blk_size(x)) #define ISO_PTBL_SIZE(x) BOTH_INT(ISO_ptbl_size(x)) #define ISO_PTBL_MAN_LS(x) LSB_INT(ISO_ptbl_man_ls(x)) #define ISO_PTBL_OPT_LS1(x) LSB_INT(ISO_ptbl_opt_ls1(x)) #define ISO_PTBL_MAN_MS(x) MSB_INT(ISO_ptbl_man_ms(x)) #define ISO_PTBL_OPT_MS1(x) MSB_INT(ISO_ptbl_opt_ms1(x)) #define ISO_ROOT_DIR(x) ISO_root_dir(x) #define ISO_VOL_SET_ID(x) ISO_vol_set_id(x) #define ISO_PUB_ID(x) ISO_pub_id(x) #define ISO_PREP_ID(x) ISO_prep_id(x) #define ISO_APPL_ID(x) ISO_appl_id(x) #define ISO_COPYR_ID(x) ISO_copyr_id(x) #define ISO_ABSTR_ID(x) ISO_abstr_id(x) #define ISO_BIBLI_ID(x) ISO_bibli_id(x) #define ISO_CRE_DATE(x) HSV_cre_date(x) #define ISO_MOD_DATE(x) HSV_mod_date(x) #define ISO_EXP_DATE(x) HSV_exp_date(x) #define ISO_EFF_DATE(x) HSV_eff_date(x) #define ISO_FILE_STRUCT_VER(x) *(ISO_file_struct_ver(x)) /* Standard File Structure Volume Descriptor date fields */ #define ISO_DATE_2DIG(x) ((((x)[0] - '0') * 10) + \ ((x)[1] - '0')) #define ISO_DATE_4DIG(x) ((((x)[0] - '0') * 1000) + \ (((x)[1] - '0') * 100) + \ (((x)[2] - '0') * 10) + \ ((x)[3] - '0')) #define ISO_DATE_YEAR(x) ISO_DATE_4DIG(&((uchar_t *)x)[0]) #define ISO_DATE_MONTH(x) ISO_DATE_2DIG(&((uchar_t *)x)[4]) #define ISO_DATE_DAY(x) ISO_DATE_2DIG(&((uchar_t *)x)[6]) #define ISO_DATE_HOUR(x) ISO_DATE_2DIG(&((uchar_t *)x)[8]) #define ISO_DATE_MIN(x) ISO_DATE_2DIG(&((uchar_t *)x)[10]) #define ISO_DATE_SEC(x) ISO_DATE_2DIG(&((uchar_t *)x)[12]) #define ISO_DATE_HSEC(x) ISO_DATE_2DIG(&((uchar_t *)x)[14]) #define ISO_DATE_GMTOFF(x) (((char *)x)[16]) /* Directory Entry (Directory Record) */ #define IDE_ROOT_DIR_REC_SIZE 34 /* size of root directory record */ #define IDE_FDESIZE 33 /* fixed size for hsfs directory area */ /* max size of a name */ #define IDE_MAX_NAME_LEN (255 - IDE_FDESIZE) /* macros to get the address of each field */ #define IDE_dir_len(x) (&((uchar_t *)x)[0]) #define IDE_xar_len(x) (&((uchar_t *)x)[1]) #define IDE_ext_lbn(x) (&((uchar_t *)x)[2]) #define IDE_ext_size(x) (&((uchar_t *)x)[10]) #define IDE_cdate(x) (&((uchar_t *)x)[18]) #define IDE_flags(x) (&((uchar_t *)x)[25]) #define IDE_intrlv_size(x) (&((uchar_t *)x)[26]) #define IDE_intrlv_skip(x) (&((uchar_t *)x)[27]) #define IDE_vol_set(x) (&((uchar_t *)x)[28]) #define IDE_name_len(x) (&((uchar_t *)x)[32]) #define IDE_name(x) (&((uchar_t *)x)[33]) #define IDE_sys_use_area(x) (&((uchar_t *)x)[IDE_NAME_LEN(x) + \ IDE_PAD_LEN(x)] + IDE_FDESIZE) /* macros to get the values of each field (strings are returned as ptrs) */ #define IDE_DIR_LEN(x) *(IDE_dir_len(x)) #define IDE_XAR_LEN(x) *(IDE_xar_len(x)) #define IDE_EXT_LBN(x) BOTH_INT(IDE_ext_lbn(x)) #define IDE_EXT_SIZE(x) BOTH_INT(IDE_ext_size(x)) #define IDE_CDATE(x) IDE_cdate(x) #define IDE_FLAGS(x) *(IDE_flags(x)) #define IDE_INTRLV_SIZE(x) *(IDE_intrlv_size(x)) #define IDE_INTRLV_SKIP(x) *(IDE_intrlv_skip(x)) #define IDE_VOL_SET(x) BOTH_SHORT(IDE_vol_set(x)) #define IDE_NAME_LEN(x) *(IDE_name_len(x)) #define IDE_NAME(x) IDE_name(x) #define IDE_PAD_LEN(x) ((IDE_NAME_LEN(x) % 2) ? 0 : 1) #define IDE_SUA_LEN(x) ((int)(IDE_DIR_LEN(x)) - (int)(IDE_FDESIZE) - \ (int)(IDE_NAME_LEN(x)) - (int)(IDE_PAD_LEN(x))) /* mask bits for IDE_FLAGS */ #define IDE_EXISTENCE 0x01 /* zero if file exists */ #define IDE_DIRECTORY 0x02 /* zero if file is not a directory */ #define IDE_ASSOCIATED 0x04 /* zero if file is not Associated */ #define IDE_RECORD 0x08 /* zero if no record attributes */ #define IDE_PROTECTION 0x10 /* zero if no protection attributes */ #define IDE_UNUSED_FLAGS 0x60 #define IDE_LAST_EXTENT 0x80 /* zero if last extent in file */ #define IDE_PROHIBITED (IDE_DIRECTORY | IDE_RECORD | \ IDE_LAST_EXTENT | IDE_UNUSED_FLAGS) /* Directory Record date fields */ #define IDE_DATE_YEAR(x) (((uchar_t *)x)[0] + 1900) #define IDE_DATE_MONTH(x) (((uchar_t *)x)[1]) #define IDE_DATE_DAY(x) (((uchar_t *)x)[2]) #define IDE_DATE_HOUR(x) (((uchar_t *)x)[3]) #define IDE_DATE_MIN(x) (((uchar_t *)x)[4]) #define IDE_DATE_SEC(x) (((uchar_t *)x)[5]) #define IDE_DATE_GMTOFF(x) (((char *)x)[6]) /* tests for Interchange Levels 1 & 2 file types */ #define IDE_REGULAR_FILE(x) (((x) & IDE_PROHIBITED) == 0) #define IDE_REGULAR_DIR(x) (((x) & IDE_PROHIBITED) == IDE_DIRECTORY) /* * A ISO filename is: "ABCDE.EEE;1" -> '.' ';' * * The ISO-9660:1988 (Version 1) maximum needed string length is: * 30 chars (filename + ext) * + 2 chars ('.' + ';') * + strlen("32767") * + null byte * ================================ * = 38 chars * * ISO_DIR_NAMELEN counts 30 chars + '.' */ #define ISO_DIR_NAMELEN 31 /* max length of a directory name */ #define ISO_FILE_NAMELEN 31 /* max length of a filename, */ /* excluding ";" and version num */ #define ISO_NAMELEN_V2 207 /* ISOv2: 254 - 33 - 14 (XA Record) */ #define ISO_NAMELEN_V2_MAX 221 /* max length, ignorig ISOv2 */ #define JOLIET_NAMELEN 64 /* Joliet file name length (spec) */ #define JOLIET_NAMELEN_MAX 110 /* max Joliet file name length */ /* Path table enry */ /* fix size of path table entry */ #define IPE_FPESIZE 8 /* macros to get the address of each field */ #define IPE_name_len(x) (&((uchar_t *)x)[0]) #define IPE_xar_len(x) (&((uchar_t *)x)[1]) #define IPE_ext_lbn(x) (&((uchar_t *)x)[2]) #define IPE_parent_no(x) (&((uchar_t *)x)[6]) #define IPE_name(x) (&((uchar_t *)x)[8]) /* macros to get the values of each field */ #define IPE_EXT_LBN(x) (MSB_INT(IPE_ext_lbn(x))) #define IPE_XAR_LEN(x) *(IPE_xar_len(x)) #define IPE_NAME_LEN(x) *(IPE_name_len(x)) #define IPE_PARENT_NO(x) *(short *)(IPE_parent_no(x)) #define IPE_NAME(x) IPE_name(x) #ifdef __cplusplus } #endif #endif /* _SYS_FS_HSFS_ISOSPEC_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * High Sierra filesystem structure definitions */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_HSFS_NODE_H #define _SYS_FS_HSFS_NODE_H #ifdef __cplusplus extern "C" { #endif #include struct hs_direntry { uint_t ext_lbn; /* LBN of start of extent */ uint_t ext_size; /* no. of data bytes in extent */ struct timeval cdate; /* creation date */ struct timeval mdate; /* last modification date */ struct timeval adate; /* last access date */ enum vtype type; /* file type */ mode_t mode; /* mode and type of file (UNIX) */ uint_t nlink; /* no. of links to file */ uid_t uid; /* owner's user id */ gid_t gid; /* owner's group id */ ino64_t inode; /* inode number from rrip data */ dev_t r_dev; /* major/minor device numbers */ uint_t xar_prot :1; /* 1 if protection in XAR */ uchar_t xar_len; /* no. of Logical blocks in XAR */ uchar_t intlf_sz; /* intleaving size */ uchar_t intlf_sk; /* intleaving skip factor */ ushort_t sym_link_flag; /* flags for sym link */ char *sym_link; /* path of sym link for readlink() */ }; struct ptable { uchar_t filler[7]; /* filler */ uchar_t dname_len; /* length of directory name */ uchar_t dname[HS_DIR_NAMELEN+1]; /* directory name */ }; struct ptable_idx { struct ptable_idx *idx_pptbl_idx; /* parent's path table index entry */ struct ptable *idx_mptbl; /* path table entry for myself */ ushort_t idx_nochild; /* no. of children */ ushort_t idx_childid; /* directory no of first child */ }; /* * hsnode structure: * * hs_offset, hs_ptbl_idx, base apply to VDIR type only * * nodeid uniquely identifies an hsnode, ISO9660 means * nodeid can be very big. * For directories it is the disk address of * the data extent of the dir (the directory itself, * ".", and ".." all point to same data extent). * For non-directories, it is the disk address of the * directory entry for the file; note that this does * not permit hard links, as it assumes a single dir * entry per file. */ struct hsnode { struct hsnode *hs_hash; /* next hsnode in hash list */ struct hsnode *hs_freef; /* next hsnode in free list */ struct hsnode *hs_freeb; /* previous hsnode in free list */ struct vnode *hs_vnode; /* the real vnode for the file */ struct hs_direntry hs_dirent; /* the directory entry for this file */ ino64_t hs_nodeid; /* "inode" number for hsnode */ uint_t hs_dir_lbn; /* LBN of directory entry */ uint_t hs_dir_off; /* offset in LBN of directory entry */ struct ptable_idx *hs_ptbl_idx; /* path table index */ uint_t hs_offset; /* start offset in dir for searching */ long hs_mapcnt; /* mappings to file pages */ uint_t hs_seq; /* sequence number */ uint_t hs_flags; /* (see below) */ u_offset_t hs_prev_offset; /* Last read end offset (readahead) */ int hs_num_contig; /* Count of contiguous reads */ int hs_ra_bytes; /* Bytes to readahead */ kmutex_t hs_contents_lock; /* protects hsnode contents */ /* except hs_offset */ }; /* hs_flags */ #define HREF 1 /* hsnode is referenced */ /* hs_modes */ #define HFDIR 0040000 /* directory */ #define HFREG 0100000 /* regular file */ struct hsfid { ushort_t hf_len; /* length of fid */ ushort_t hf_dir_off; /* offset in LBN of directory entry */ uint_t hf_dir_lbn; /* LBN of directory */ uint32_t hf_ino; /* The inode number or HS_DUMMY_INO */ }; /* * All of the fields in the hs_volume are read-only once they have been * initialized. */ struct hs_volume { ulong_t vol_size; /* no. of Logical blocks in Volume */ uint_t lbn_size; /* no. of bytes in a block */ uint_t lbn_shift; /* shift to convert lbn to bytes */ uint_t lbn_secshift; /* shift to convert lbn to sec */ uint_t lbn_maxoffset; /* max lbn-relative offset and mask */ uchar_t file_struct_ver; /* version of directory structure */ uid_t vol_uid; /* uid of volume */ gid_t vol_gid; /* gid of volume */ uint_t vol_prot; /* protection (mode) of volume */ struct timeval cre_date; /* volume creation time */ struct timeval mod_date; /* volume modification time */ struct hs_direntry root_dir; /* dir entry for Root Directory */ ushort_t ptbl_len; /* number of bytes in Path Table */ uint_t ptbl_lbn; /* logical block no of Path Table */ ushort_t vol_set_size; /* number of CD in this vol set */ ushort_t vol_set_seq; /* the sequence number of this CD */ char vol_id[32]; /* volume id in PVD */ }; /* * The hsnode table is no longer fixed in size but grows * and shrinks dynamically. However a cache of nodes is still maintained * for efficiency. This cache size (nhsnode) is a tunable which * is either specified in /etc/system or calculated as the number * that will fit into the number of bytes defined by HS_HSNODESPACE (below). */ #define HS_HASHSIZE 32 /* hsnode hash table size */ #define HS_HSNODESPACE 16384 /* approx. space used for hsnodes */ /* * We usually use the starting extent LBA for the inode numbers of files and * directories. As this will not work for zero sized files, we assign a dummy * inode number to all zero sized files. We use the number 16 as this is the * LBA for the PVD, this number cannot be a valid starting extent LBA for a * file. In case that the node number is the HS_DUMMY_INO, we use the LBA and * offset of the directory entry of this file (which is what we used before * we started to support correct hard links). */ #define HS_DUMMY_INO 16 /* dummy inode number for empty files */ /* * Hsfs I/O Scheduling parameters and data structures. * Deadline for reads is set at 5000 usec. */ #define HSFS_READ_DEADLINE 5000 #define HSFS_NORMAL 0x0 /* * This structure holds information for a read request that is enqueued * for processing by the scheduling function. An AVL tree is used to * access the read requests in a sorted manner. */ struct hio { struct buf *bp; /* The buf for this read */ struct hio *contig_chain; /* Next adjacent read if any */ offset_t io_lblkno; /* Starting disk block of io */ u_offset_t nblocks; /* # disk blocks */ uint64_t io_timestamp; /* usec timestamp for deadline */ ksema_t *sema; /* Completion flag */ avl_node_t io_offset_node; /* Avl tree requirements */ avl_node_t io_deadline_node; }; /* * This structure holds information about all the read requests issued * during a read-ahead invocation. This is then enqueued on a task-queue * for processing by a background thread that takes this read-ahead to * completion and cleans up. */ struct hio_info { struct buf *bufs; /* array of bufs issued for this R/A */ caddr_t *vas; /* The kmem_alloced chunk for the bufs */ ksema_t *sema; /* Semaphores used in the bufs */ uint_t bufsused; /* # of bufs actually used */ uint_t bufcnt; /* Tot bufs allocated. */ struct page *pp; /* The list of I/O locked pages */ struct hsfs *fsp; /* The filesystem structure */ }; /* * This is per-filesystem structure that stores toplevel data structures for * the I/O scheduler. */ struct hsfs_queue { /* * A dummy hio holding the LBN of the last read processed. Easy * to use in AVL_NEXT for Circular Look behavior. */ struct hio *next; /* * A pre-allocated buf for issuing coalesced reads. The scheduling * function is mostly single threaded by necessity. */ struct buf *nbuf; kmutex_t hsfs_queue_lock; /* Protects the AVL trees */ /* * Makes most of the scheduling function Single-threaded. */ kmutex_t strategy_lock; avl_tree_t read_tree; /* Reads ordered by LBN */ avl_tree_t deadline_tree; /* Reads ordered by timestamp */ taskq_t *ra_task; /* Read-ahead Q */ int max_ra_bytes; /* Max read-ahead quantum */ /* Device Max Transfer size in DEV_BSIZE */ uint_t dev_maxtransfer; }; /* * High Sierra filesystem structure. * There is one of these for each mounted High Sierra filesystem. */ enum hs_vol_type { HS_VOL_TYPE_HS = 0, HS_VOL_TYPE_ISO = 1, HS_VOL_TYPE_ISO_V2 = 2, HS_VOL_TYPE_JOLIET = 3 }; #define HSFS_MAGIC 0x03095500 struct hsfs { struct hsfs *hsfs_next; /* ptr to next entry in linked list */ long hsfs_magic; /* should be HSFS_MAGIC */ struct vfs *hsfs_vfs; /* vfs for this fs */ struct vnode *hsfs_rootvp; /* vnode for root of filesystem */ struct vnode *hsfs_devvp; /* device mounted on */ enum hs_vol_type hsfs_vol_type; /* see above */ struct hs_volume hsfs_vol; /* File Structure Volume Descriptor */ struct ptable *hsfs_ptbl; /* pointer to incore Path Table */ int hsfs_ptbl_size; /* size of incore path table */ struct ptable_idx *hsfs_ptbl_idx; /* pointer to path table index */ int hsfs_ptbl_idx_size; /* no. of path table index */ ulong_t hsfs_ext_impl; /* ext. information bits */ ushort_t hsfs_sua_off; /* the SUA offset */ ushort_t hsfs_namemax; /* maximum file name length */ ushort_t hsfs_namelen; /* "official" max. file name length */ ulong_t hsfs_err_flags; /* ways in which fs is non-conformant */ char *hsfs_fsmnt; /* name mounted on */ ulong_t hsfs_flags; /* hsfs-specific mount flags */ krwlock_t hsfs_hash_lock; /* protect hash table & hst_nohsnode */ struct hsnode *hsfs_hash[HS_HASHSIZE]; /* head of hash lists */ uint32_t hsfs_nohsnode; /* no. of allocated hsnodes */ kmutex_t hsfs_free_lock; /* protects free list */ struct hsnode *hsfs_free_f; /* first entry of free list */ struct hsnode *hsfs_free_b; /* last entry of free list */ /* * Counters exported through kstats. */ uint64_t physical_read_bytes; uint64_t cache_read_pages; uint64_t readahead_bytes; uint64_t coalesced_bytes; uint64_t total_pages_requested; kstat_t *hsfs_kstats; struct hsfs_queue *hqueue; /* I/O Scheduling parameters */ }; /* * Error types: bit offsets into hsfs_err_flags. * Also serves as index into hsfs_error[], so must be * kept in sync with that data structure. */ #define HSFS_ERR_TRAILING_JUNK 0 #define HSFS_ERR_LOWER_CASE_NM 1 #define HSFS_ERR_BAD_ROOT_DIR 2 #define HSFS_ERR_UNSUP_TYPE 3 #define HSFS_ERR_BAD_FILE_LEN 4 #define HSFS_ERR_BAD_JOLIET_FILE_LEN 5 #define HSFS_ERR_TRUNC_JOLIET_FILE_LEN 6 #define HSFS_ERR_BAD_DIR_ENTRY 7 #define HSFS_ERR_NEG_SUA_LEN 8 #define HSFS_ERR_BAD_SUA_LEN 9 #define HSFS_HAVE_LOWER_CASE(fsp) \ ((fsp)->hsfs_err_flags & (1 << HSFS_ERR_LOWER_CASE_NM)) /* * File system parameter macros */ #define hs_blksize(HSFS, HSP, OFF) /* file system block size */ \ ((HSP)->hs_vn.v_flag & VROOT ? \ ((OFF) >= \ ((HSFS)->hsfs_rdirsec & ~((HSFS)->hsfs_spcl - 1))*HS_SECSIZE ?\ ((HSFS)->hsfs_rdirsec & ((HSFS)->hsfs_spcl - 1))*HS_SECSIZE :\ (HSFS)->hsfs_clsize): \ (HSFS)->hsfs_clsize) #define hs_blkoff(OFF) /* offset within block */ \ ((OFF) & (HS_SECSIZE - 1)) /* * Conversion macros */ #define VFS_TO_HSFS(VFSP) ((struct hsfs *)(VFSP)->vfs_data) #define HSFS_TO_VFS(FSP) ((FSP)->hsfs_vfs) #define VTOH(VP) ((struct hsnode *)(VP)->v_data) #define HTOV(HP) (((HP)->hs_vnode)) /* * Convert between Logical Block Number and Sector Number. */ #define LBN_TO_SEC(lbn, vfsp) ((lbn)>>((struct hsfs *)((vfsp)->vfs_data))-> \ hsfs_vol.lbn_secshift) #define SEC_TO_LBN(sec, vfsp) ((sec)<<((struct hsfs *)((vfsp)->vfs_data))-> \ hsfs_vol.lbn_secshift) #define LBN_TO_BYTE(lbn, vfsp) ((lbn)<<((struct hsfs *)((vfsp)->vfs_data))-> \ hsfs_vol.lbn_shift) #define BYTE_TO_LBN(boff, vfsp) ((boff)>>((struct hsfs *)((vfsp)->vfs_data))-> \ hsfs_vol.lbn_shift) #ifdef __cplusplus } #endif #endif /* _SYS_FS_HSFS_NODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * ISO 9660 RRIP extension filesystem specifications */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_HSFS_RRIP_H #define _SYS_FS_HSFS_RRIP_H #ifdef __cplusplus extern "C" { #endif /* * Mount options specific to HSFS. * This is not a good place for them; we should probably have a file * named hsfs_mount.h for such stuff. */ #define HSFSMNT_NORRIP 0x1 /* -nrr option found */ #define HSFSMNT_NOTRAILDOT 0x2 /* ignore trailing '.' */ #define HSFSMNT_NOMAPLCASE 0x4 /* do not map filenames to lcase */ #define HSFSMNT_NOTRAILSPACE 0x8 /* no trailing space in iso 9660 */ #define HSFSMNT_NOVERSION 0x10 /* no version info in iso 9660 */ #define HSFSMNT_NOJOLIET 0x20 /* ignore Joliet even if present */ #define HSFSMNT_JOLIETLONG 0x40 /* do not truncate Joliet filenames */ #define HSFSMNT_NOVERS2 0x80 /* ignore ISO-9660:1999 */ #define HSFSMNT_INODE 0x1000 /* May use ext_lbn as inode #, */ /* FS is from a recent mkisofs */ /* * XXX: The following flag was used in the past to instruct the kernel to * ignore Rock Ridge extensions on a CD. Unfortunately, this was * implemented as part of the generic mount flags, a bad idea. * This flag should not be used anymore. The HSFSMNT_NORRIP * flag should be used in its place. The hsfs_mount code currently * understands this flag, but this functionality should go * away in the future. */ #define MS_NO_RRIP 0x800000 /* if set, don't use Rock Ridge */ #define MIN(a, b) ((a) < (b) ? (a) : (b)) /* * Make sure we have this first */ #define RRIP_VERSION 1 #define RRIP_SUF_VERSION 1 #define RRIP_EXT_VERSION 1 #define RRIP_BIT 1 /* loc. in extension_name_table in susp.c */ #define IS_RRIP_IMPLEMENTED(fsp) (IS_IMPL_BIT_SET(fsp, RRIP_BIT) ? 1 : 0) /* * RRIP signature macros */ #define RRIP_CL "CL" #define RRIP_NM "NM" #define RRIP_PL "PL" #define RRIP_PN "PN" #define RRIP_PX "PX" #define RRIP_RE "RE" #define RRIP_RR "RR" #define RRIP_SL "SL" #define RRIP_TF "TF" /* * RRIP ER extension fields */ #define RRIP_ER_EXT_ID "RRIP_1991A" #define RRIP_ER_EXT_DES "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES \ SUPPORT FOR POSIX FILE SYSTEM SEMANTICS." #define RRIP_ER_EXT_SRC "PLEASE CONTACT DISC PUBLISHER FOR \ SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR \ FOR CONTACT INFORMATION." /* * "TF" time macros */ #define RRIP_TF_FLAGS(x) *(RRIP_tf_flags(x)) #define RRIP_tf_flags(x) (&((uchar_t *)(x))[4]) #define RRIP_TIME_START_BP 5 #define RRIP_TF_TIME_LENGTH(x) (IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \ RRIP_TF_LONG_BIT) ? \ ISO_DATE_LEN : ISO_SHORT_DATE_LEN) /* * Time location bits */ #define RRIP_TF_CREATION_BIT 0x01 #define RRIP_TF_MODIFY_BIT 0x02 #define RRIP_TF_ACCESS_BIT 0x04 #define RRIP_TF_ATTRIBUTES_BIT 0x08 #define RRIP_TF_BACKUP_BIT 0x10 #define RRIP_TF_EXPIRATION_BIT 0x20 #define RRIP_TF_EFFECTIVE_BIT 0x40 #define RRIP_TF_LONG_BIT 0x80 #define RRIP_tf_creation(x) (&((uchar_t *)x)[RRIP_TIME_START_BP]) #define RRIP_tf_modify(x) (&((uchar_t *)x)[RRIP_TIME_START_BP + \ (RRIP_TF_TIME_LENGTH(x) * \ (IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \ RRIP_TF_CREATION_BIT)))]) #define RRIP_tf_access(x) (&((uchar_t *)x)[RRIP_TIME_START_BP + \ (RRIP_TF_TIME_LENGTH(x) * \ (IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \ RRIP_TF_CREATION_BIT) + \ IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \ RRIP_TF_MODIFY_BIT)))]) #define RRIP_tf_attributes(x) (&((uchar_t *)x)[RRIP_TIME_START_BP + \ (RRIP_TF_TIME_LENGTH(x) * \ (IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \ RRIP_TF_CREATION_BIT) + \ IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \ RRIP_TF_MODIFY_BIT) + \ IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \ RRIP_TF_ACCESS_BIT)))]) /* * Check if TF Bits are set. * * Note : IS_TIME_BIT_SET(x, y) must be kept returning 1 and 0. * see RRIP_tf_*(x) Macros */ #define IS_TIME_BIT_SET(x, y) (((x) & (y)) ? 1 : 0) #define SET_TIME_BIT(x, y) ((x) |= (y)) /* * "PX" Posix attibutes */ #define RRIP_mode(x) (&((uchar_t *)x)[4]) #define RRIP_MODE(x) (mode_t)BOTH_INT(RRIP_mode(x)) #define RRIP_nlink(x) (&((uchar_t *)x)[12]) #define RRIP_NLINK(x) (short)BOTH_INT(RRIP_nlink(x)) #define RRIP_uid(x) (&((uchar_t *)x)[20]) #define RRIP_UID(x) (uid_t)BOTH_INT(RRIP_uid(x)) #define RRIP_gid(x) (&((uchar_t *)x)[28]) #define RRIP_GID(x) (gid_t)BOTH_INT(RRIP_gid(x)) #define RRIP_ino(x) (&((uchar_t *)x)[36]) #define RRIP_INO(x) (uint32_t)BOTH_INT(RRIP_ino(x)) #define RRIP_PX_OLD_SIZE 36 #define RRIP_PX_SIZE 44 /* * "PN" Posix major/minor numbers */ #define RRIP_major(x) (&((uchar_t *)x)[4]) #define RRIP_MAJOR(x) BOTH_INT(RRIP_major(x)) #define RRIP_minor(x) (&((uchar_t *)x)[12]) #define RRIP_MINOR(x) BOTH_INT(RRIP_minor(x)) /* * "NM" alternate name and "SL" symbolic link macros... */ #define SYM_LINK_LEN(x) (strlen(x) + 1) #define RRIP_NAME_LEN_BASE 5 #define RRIP_NAME_LEN(x) (SUF_LEN(x) - RRIP_NAME_LEN_BASE) #define RRIP_NAME_FLAGS(x) (((uchar_t *)x)[4]) /* * These are for the flag bits in the NM and SL and must remain <= 8 bits */ #define RRIP_NAME_CONTINUE 0x01 #define RRIP_NAME_CURRENT 0x02 #define RRIP_NAME_PARENT 0x04 #define RRIP_NAME_ROOT 0x08 #define RRIP_NAME_VOLROOT 0x10 #define RRIP_NAME_HOST 0x20 /* * These are unique to use in the > 8 bits of sig_args.name_flags * They are > 8 so that we can share bits from above. * This can grow to 32 bits. */ #define RRIP_NAME_CHANGE 0x40 #define RRIP_SYM_LINK_COMPLETE 0x80 /* set if sym link already read */ /* from SUA (no longer than a short) */ /* * Bit handling.... */ #define SET_NAME_BIT(x, y) ((x) |= (y)) #define UNSET_NAME_BIT(x, y) ((x) &= ~(y)) #define IS_NAME_BIT_SET(x, y) ((x) & (y)) #define NAME_HAS_CHANGED(flag) \ (IS_NAME_BIT_SET(flag, RRIP_NAME_CHANGE) ? 1 : 0) #define RRIP_name(x) (&((uchar_t *)x)[5]) #define RRIP_NAME(x) RRIP_name(x) /* * This is the maximum filename length that we support */ #define RRIP_FILE_NAMELEN 255 /* * SL Symbolic link macros (in addition to common name flag macos */ /* these two macros are from the SL SUF pointer */ #define RRIP_sl_comp(x) (&((uchar_t *)x)[5]) #define RRIP_SL_COMP(x) RRIP_sl_comp(x) #define RRIP_SL_FLAGS(x) (((uchar_t *)x)[4]) /* these macros are from the component pointer within the SL SUF */ #define RRIP_comp(x) (&((uchar_t *)x)[2]) #define RRIP_COMP(x) RRIP_comp(x) #define RRIP_COMP_FLAGS(x) (((uchar_t *)x)[0]) #define RRIP_COMP_LEN(x) (RRIP_COMP_NAME_LEN(x) + 2) #define RRIP_COMP_NAME_LEN(x) (((uchar_t *)x)[1]) /* * Directory hierarchy macros */ /* * Macros for checking relocation bits in flags member of dlist * structure defined in iso_impl.h */ #define IS_RELOC_BIT_SET(x, y) (((x) & (y)) ? 1 : 0) #define SET_RELOC_BIT(x, y) ((x) |= (y)) #define CHILD_LINK 0x01 #define PARENT_LINK 0x02 #define RELOCATED_DIR 0x04 #define RRIP_child_lbn(x) (&((uchar_t *)x)[4]) #define RRIP_CHILD_LBN(x) (uint_t)BOTH_INT(RRIP_child_lbn(x)) #define RRIP_parent_lbn(x) (&((uchar_t *)x)[4]) #define RRIP_PARENT_LBN(x) (uint_t)BOTH_INT(RRIP_parent_lbn(x)) #ifdef _KERNEL /* * Forward declarations */ extern uchar_t *rrip_name(sig_args_t *); extern uchar_t *rrip_file_attr(sig_args_t *); extern uchar_t *rrip_dev_nodes(sig_args_t *); extern uchar_t *rrip_file_time(sig_args_t *); extern uchar_t *rrip_sym_link(sig_args_t *); extern uchar_t *rrip_parent_link(sig_args_t *); extern uchar_t *rrip_child_link(sig_args_t *); extern uchar_t *rrip_reloc_dir(sig_args_t *); extern uchar_t *rrip_rock_ridge(sig_args_t *); extern void hs_check_root_dirent(struct vnode *vp, struct hs_direntry *hdp); extern int rrip_namecopy(char *from, char *to, char *tmp_name, uchar_t *dirp, uint_t last_offset, struct hsfs *fsp, struct hs_direntry *hdp); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_HSFS_RRIP_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_HSFS_SPEC_H #define _SYS_FS_HSFS_SPEC_H /* * High Sierra filesystem specification */ #include #include #ifdef __cplusplus extern "C" { #endif #ifdef _KERNEL /* routines required for date parsing */ extern void hs_parse_dirdate(uchar_t *, struct timeval *); extern void hs_parse_longdate(uchar_t *, struct timeval *); #endif /* _KERNEL */ /* macros to parse binary integers */ #define ZERO(x) (uint_t)(((uchar_t *)(x))[0]) #define ONE(x) (uint_t)(((uchar_t *)(x))[1]) #define TWO(x) (uint_t)(((uchar_t *)(x))[2]) #define THREE(x) (uint_t)(((uchar_t *)(x))[3]) #define MSB_INT(x) \ ((((((ZERO(x) << 8) | ONE(x)) << 8) | TWO(x)) << 8) | THREE(x)) #define LSB_INT(x) \ ((((((THREE(x) << 8) | TWO(x)) << 8) | ONE(x)) << 8) | ZERO(x)) #define MSB_SHORT(x) ((ZERO(x) << 8) | ONE(x)) #define LSB_SHORT(x) ((ONE(x) << 8) | ZERO(x)) #if defined(__i386) || defined(__amd64) #define BOTH_SHORT(x) (short)*((short *)x) #define BOTH_INT(x) (int)*((int *)x) #elif defined(__sparc) /* * SPARC machines requires that integer must * be in a full word boundary. CD-ROM data aligns * to even word boundary only. Because of this mismatch, * we have to move integer data from CD-ROM to memory one * byte at a time. LSB data starts first. We therefore * use this to do byte by byte copying. */ #define BOTH_SHORT(x) LSB_SHORT(x) #define BOTH_INT(x) LSB_INT(x) #endif /* * The following describes actual on-disk structures. * To achieve portability, all structures are #defines * rather than a structure definition. Macros are provided * to get either the data or address of individual fields. */ /* Overall High Sierra disk structure */ #define HS_SECTOR_SIZE 2048 /* bytes per logical sector */ #define HS_SECTOR_SHIFT 11 /* sector<->byte shift count */ #define HS_SEC_PER_PAGE (PAGESIZE/HS_SECTOR_SIZE) /* sectors per page */ #define HS_SYSAREA_SEC 0 /* 1st sector of system area */ #define HS_VOLDESC_SEC 16 /* 1st sector of volume descriptors */ #define HS_MAXFILEOFF 4294967295U /* Max file offset (4Gb - 1). */ #define MAXHSOFFSET (HS_SECTOR_SIZE - 1) #define MAXHSMASK (~MAXHSOFFSET) /* Standard File Structure Volume Descriptor */ enum hs_voldesc_type { VD_BOOT = 0, VD_SFS = 1, VD_CCFS = 2, VD_UNSPEC = 3, VD_EOV = 255 }; #define HSV_ID_STRING "CDROM" /* HSV_std_id field */ #define HSV_ID_STRLEN 5 /* HSV_std_id field length */ #define HSV_ID_VER 1 /* HSV_std_ver field */ #define HSV_FILE_STRUCT_ID_VER 1 /* HSV_file_struct_ver field */ #define HSV_SYS_ID_STRLEN 32 /* HSV_sys_id field length */ #define HSV_VOL_ID_STRLEN 32 /* HSV_vol_id field length */ #define HSV_VOL_SET_ID_STRLEN 128 /* HSV_vol_set_id field length */ #define HSV_PUB_ID_STRLEN 128 /* HSV_pub_id field length */ #define HSV_PREP_ID_STRLEN 128 /* HSV_prep_id field length */ #define HSV_APPL_ID_STRLEN 128 /* HSV_appl_id field length */ #define HSV_COPYR_ID_STRLEN 32 /* HSV_copyr_id field length */ #define HSV_ABSTR_ID_STRLEN 32 /* HSV_abstr_id field length */ #define HSV_DATE_LEN 16 /* HSV date filed length */ /* macros to get the address of each field */ #define HSV_desc_lbn(x) (&((uchar_t *)x)[0]) #define HSV_desc_type(x) (&((uchar_t *)x)[8]) #define HSV_std_id(x) (&((uchar_t *)x)[9]) #define HSV_std_ver(x) (&((uchar_t *)x)[14]) #define HSV_sys_id(x) (&((uchar_t *)x)[16]) #define HSV_vol_id(x) (&((uchar_t *)x)[48]) #define HSV_vol_size(x) (&((uchar_t *)x)[88]) #define HSV_set_size(x) (&((uchar_t *)x)[128]) #define HSV_set_seq(x) (&((uchar_t *)x)[132]) #define HSV_blk_size(x) (&((uchar_t *)x)[136]) #define HSV_ptbl_size(x) (&((uchar_t *)x)[140]) #define HSV_ptbl_man_ls(x) (&((uchar_t *)x)[148]) #define HSV_ptbl_opt_ls1(x) (&((uchar_t *)x)[152]) #define HSV_ptbl_opt_ls2(x) (&((uchar_t *)x)[156]) #define HSV_ptbl_opt_ls3(x) (&((uchar_t *)x)[160]) #define HSV_ptbl_man_ms(x) (&((uchar_t *)x)[164]) #define HSV_ptbl_opt_ms1(x) (&((uchar_t *)x)[168]) #define HSV_ptbl_opt_ms2(x) (&((uchar_t *)x)[172]) #define HSV_ptbl_opt_ms3(x) (&((uchar_t *)x)[176]) #define HSV_root_dir(x) (&((uchar_t *)x)[180]) #define HSV_vol_set_id(x) (&((uchar_t *)x)[214]) #define HSV_pub_id(x) (&((uchar_t *)x)[342]) #define HSV_prep_id(x) (&((uchar_t *)x)[470]) #define HSV_appl_id(x) (&((uchar_t *)x)[598]) #define HSV_copyr_id(x) (&((uchar_t *)x)[726]) #define HSV_abstr_id(x) (&((uchar_t *)x)[758]) #define HSV_cre_date(x) (&((uchar_t *)x)[790]) #define HSV_mod_date(x) (&((uchar_t *)x)[806]) #define HSV_exp_date(x) (&((uchar_t *)x)[822]) #define HSV_eff_date(x) (&((uchar_t *)x)[838]) #define HSV_file_struct_ver(x) (&((uchar_t *)x)[854]) /* macros to get the values of each field (strings are returned as ptrs) */ #define HSV_DESC_LBN(x) BOTH_INT(HSV_desc_lbn(x)) #define HSV_DESC_TYPE(x) ((enum hs_voldesc_type)*(HSV_desc_type(x))) #define HSV_STD_ID(x) HSV_std_id(x) #define HSV_STD_VER(x) *(HSV_std_ver(x)) #define HSV_SYS_ID(x) HSV_sys_id(x) #define HSV_VOL_ID(x) HSV_vol_id(x) #define HSV_VOL_SIZE(x) BOTH_INT(HSV_vol_size(x)) #define HSV_SET_SIZE(x) BOTH_SHORT(HSV_set_size(x)) #define HSV_SET_SEQ(x) BOTH_SHORT(HSV_set_seq(x)) #define HSV_BLK_SIZE(x) BOTH_SHORT(HSV_blk_size(x)) #define HSV_PTBL_SIZE(x) BOTH_INT(HSV_ptbl_size(x)) #define HSV_PTBL_MAN_LS(x) LSB_INT(HSV_ptbl_man_ls(x)) #define HSV_PTBL_OPT_LS1(x) LSB_INT(HSV_ptbl_opt_ls1(x)) #define HSV_PTBL_OPT_LS2(x) LSB_INT(HSV_ptbl_opt_ls2(x)) #define HSV_PTBL_OPT_LS3(x) LSB_INT(HSV_ptbl_opt_ls3(x)) #define HSV_PTBL_MAN_MS(x) MSB_INT(HSV_ptbl_man_ms(x)) #define HSV_PTBL_OPT_MS1(x) MSB_INT(HSV_ptbl_opt_ms1(x)) #define HSV_PTBL_OPT_MS2(x) MSB_INT(HSV_ptbl_opt_ms2(x)) #define HSV_PTBL_OPT_MS3(x) MSB_INT(HSV_ptbl_opt_ms3(x)) #define HSV_ROOT_DIR(x) HSV_root_dir(x) #define HSV_VOL_SET_ID(x) HSV_vol_set_id(x) #define HSV_PUB_ID(x) HSV_pub_id(x) #define HSV_PREP_ID(x) HSV_prep_id(x) #define HSV_APPL_ID(x) HSV_appl_id(x) #define HSV_COPYR_ID(x) HSV_copyr_id(x) #define HSV_ABSTR_ID(x) HSV_abstr_id(x) #define HSV_CRE_DATE(x) HSV_cre_date(x) #define HSV_MOD_DATE(x) HSV_mod_date(x) #define HSV_EXP_DATE(x) HSV_exp_date(x) #define HSV_EFF_DATE(x) HSV_eff_date(x) #define HSV_FILE_STRUCT_VER(x) *(HSV_file_struct_ver(x)) /* Standard File Structure Volume Descriptor date fields */ #define HSV_DATE_2DIG(x) ((((x)[0] - '0') * 10) + \ ((x)[1] - '0')) #define HSV_DATE_4DIG(x) ((((x)[0] - '0') * 1000) + \ (((x)[1] - '0') * 100) + \ (((x)[2] - '0') * 10) + \ ((x)[3] - '0')) #define HSV_DATE_YEAR(x) HSV_DATE_4DIG(&((uchar_t *)x)[0]) #define HSV_DATE_MONTH(x) HSV_DATE_2DIG(&((uchar_t *)x)[4]) #define HSV_DATE_DAY(x) HSV_DATE_2DIG(&((uchar_t *)x)[6]) #define HSV_DATE_HOUR(x) HSV_DATE_2DIG(&((uchar_t *)x)[8]) #define HSV_DATE_MIN(x) HSV_DATE_2DIG(&((uchar_t *)x)[10]) #define HSV_DATE_SEC(x) HSV_DATE_2DIG(&((uchar_t *)x)[12]) #define HSV_DATE_HSEC(x) HSV_DATE_2DIG(&((uchar_t *)x)[14]) #define HSV_DATE_GMTOFF(x) (((char *)x)[16]) /* Path table enry */ /* fix size of path table entry */ #define HPE_FPESIZE 8 /* macros to get the address of each field */ #define HPE_ext_lbn(x) (&((uchar_t *)x)[0]) #define HPE_xar_len(x) (&((uchar_t *)x)[4]) #define HPE_name_len(x) (&((uchar_t *)x)[5]) #define HPE_parent_no(x) (&((uchar_t *)x)[6]) #define HPE_name(x) (&((uchar_t *)x)[8]) /* macros to get the values of each field */ #if defined(__sparc) #define HPE_EXT_LBN(x) (MSB_INT(HPE_ext_lbn(x))) #else #define HPE_EXT_LBN(x) *(int *)(HPE_ext_lbn(x)) #endif #define HPE_XAR_LEN(x) *(HPE_xar_len(x)) #define HPE_NAME_LEN(x) *(HPE_name_len(x)) #define HPE_PARENT_NO(x) *(short *)(HPE_parent_no(x)) #define HPE_NAME(x) HPE_name(x) /* root record */ #define HDE_ROOT_DIR_REC_SIZE 34 /* size of root directory record */ #define HDE_FDESIZE 33 /* fixed size for hsfs directory area */ #define HDE_FUSIZE 12 /* fixed size for unix area */ /* max size of a name */ #define HDE_MAX_NAME_LEN (255 - HDE_FDESIZE - HDE_FUSIZE) /* Directory Entry (Directory Record) */ #define UNIX_TO_HDE_DATE(t, p) parse_unixdate((t), (p)) /* macros to get the address of each field */ #define HDE_dir_len(x) (&((uchar_t *)x)[0]) #define HDE_xar_len(x) (&((uchar_t *)x)[1]) #define HDE_ext_lbn(x) (&((uchar_t *)x)[2]) #define HDE_ext_size(x) (&((uchar_t *)x)[10]) #define HDE_cdate(x) (&((uchar_t *)x)[18]) #define HDE_flags(x) (&((uchar_t *)x)[24]) #define HDE_reserved(x) (&((uchar_t *)x)[25]) #define HDE_intrlv_size(x) (&((uchar_t *)x)[26]) #define HDE_intrlv_skip(x) (&((uchar_t *)x)[27]) #define HDE_vol_set(x) (&((uchar_t *)x)[28]) #define HDE_name_len(x) (&((uchar_t *)x)[32]) #define HDE_name(x) (&((uchar_t *)x)[33]) /* **UNIX extension*** */ #define HDE_mode(x) (&((uchar_t *)x)[0]) #define HDE_uid(x) (&((uchar_t *)x)[4]) #define HDE_gid(x) (&((uchar_t *)x)[8]) /* macros to get the values of each field (strings are returned as ptrs) */ #define HDE_DIR_LEN(x) *(HDE_dir_len(x)) #define HDE_XAR_LEN(x) *(HDE_xar_len(x)) #define HDE_EXT_LBN(x) BOTH_INT(HDE_ext_lbn(x)) #define HDE_EXT_SIZE(x) BOTH_INT(HDE_ext_size(x)) #define HDE_CDATE(x) HDE_cdate(x) #define HDE_FLAGS(x) *(HDE_flags(x)) #define HDE_RESERVED(x) *(HDE_reserved(x)) #define HDE_INTRLV_SIZE(x) *(HDE_intrlv_size(x)) #define HDE_INTRLV_SKIP(x) *(HDE_intrlv_skip(x)) #define HDE_VOL_SET(x) BOTH_SHORT(HDE_vol_set(x)) #define HDE_NAME_LEN(x) *(HDE_name_len(x)) #define HDE_NAME(x) HDE_name(x) /* **UNIX EXTENSION**** */ #define HDE_MODE(x) *(HDE_mode(x)) #define HDE_UID(x) *(HDE_uid(x)) #define HDE_GID(x) *(HDE_gid(x)) /* mask bits for HDE_FLAGS */ #define HDE_EXISTENCE 0x01 /* zero if file exists */ #define HDE_DIRECTORY 0x02 /* zero if file is not a directory */ #define HDE_ASSOCIATED 0x04 /* zero if file is not Associated */ #define HDE_RECORD 0x08 /* zero if no record attributes */ #define HDE_PROTECTION 0x10 /* zero if no protection attributes */ #define HDE_UNUSED_FLAGS 0x60 #define HDE_LAST_EXTENT 0x80 /* zero if last extent in file */ #define HDE_PROHIBITED (HDE_DIRECTORY | HDE_RECORD | \ HDE_LAST_EXTENT | HDE_UNUSED_FLAGS) /* Directory Record date fields */ #define HDE_DATE_YEAR(x) (((uchar_t *)x)[0] + 1900) #define HDE_DATE_MONTH(x) (((uchar_t *)x)[1]) #define HDE_DATE_DAY(x) (((uchar_t *)x)[2]) #define HDE_DATE_HOUR(x) (((uchar_t *)x)[3]) #define HDE_DATE_MIN(x) (((uchar_t *)x)[4]) #define HDE_DATE_SEC(x) (((uchar_t *)x)[5]) #define HDE_DATE_GMTOFF(x) (((char *)x)[6]) /* tests for Interchange Levels 1 & 2 file types */ #define HDE_REGULAR_FILE(x) (((x) & HDE_PROHIBITED) == 0) #define HDE_REGULAR_DIR(x) (((x) & HDE_PROHIBITED) == HDE_DIRECTORY) #define HS_DIR_NAMELEN 31 /* max length of a directory name */ #define HS_FILE_NAMELEN 31 /* max length of a filename */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_HSFS_SPEC_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * ISO 9660 RRIP extension filesystem specifications * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_HSFS_SUSP_H #define _SYS_FS_HSFS_SUSP_H #ifdef __cplusplus extern "C" { #endif #define DEBUGGING_ALL 0 #define DEBUGGING 0 #define DPRINTF if (DEBUGGING) printf #define DPRINTF_ALL if (DEBUGGING_ALL) printf /* * return values from SUA parsing */ #define SUA_NULL_POINTER -1 #define END_OF_SUA_PARSING -2 #define END_OF_SUA -3 #define GET_CONTINUATION -4 #define SUA_ENOMEM -5 #define SUA_EINVAL -6 #define RELOC_DIR -7 /* actually for rrip */ /* * For dealing with implemented bits... * These here expect the fsp and a bit as an agument */ #define SET_IMPL_BIT(fsp, y) ((fsp->hsfs_ext_impl) |= (0x01L) << (y)) #define UNSET_IMPL_BIT(fsp, y) ((fsp->hsfs_ext_impl) &= ~((0x01L) << (y))) #define IS_IMPL_BIT_SET(fsp, y) ((fsp->hsfs_ext_impl) & ((0x01L) << (y))) #define HAVE_SUSP 0 /* have a SUSP */ #define HAVE_PROHIBITED 1 /* prohibited file/dir type in fs */ /* * For dealing with implemented bits... * These here expect just the fsp->hsfs_ext_impl */ #define SET_SUSP_BIT(fsp) (SET_IMPL_BIT((fsp), HAVE_SUSP)) #define UNSET_SUSP_BIT(fsp) (UNSET_IMPL_BIT((fsp), HAVE_SUSP)) #define IS_SUSP_IMPLEMENTED(fsp) (IS_IMPL_BIT_SET(fsp, 0) ? 1 : 0) #define SUSP_VERSION 1 /* * SUSP signagure definitions */ #define SUSP_SP "SP" #define SUSP_CE "CE" #define SUSP_PD "PD" #define SUSP_ER "ER" #define SUSP_ST "ST" /* * Generic System Use Field (SUF) Macros and declarations */ #define SUF_SIG_LEN 2 /* length of signatures */ #define SUF_MIN_LEN 4 /* minimum length of a */ /* signature field */ #define SUF_LEN(x) *(SUF_len(x)) /* SUF length */ #define SUF_len(x) (&((uchar_t *)x)[2]) /* SUF length */ #define SUF_VER(x) *(SUF_ver(x)) /* SUF version */ #define SUF_ver(x) (&((uchar_t *)x)[3]) /* SUF version */ /* * Extension Reference Macros */ #define ER_ID_LEN(x) *(ER_id_len(x)) /* Extension ref id length */ #define ER_id_len(x) (&((uchar_t *)x)[4]) /* Extension ref id length */ #define ER_DES_LEN(x) *(ER_des_len(x)) /* Extension ref description */ /* length */ #define ER_des_len(x) (&((uchar_t *)x)[5]) /* Extension ref description */ /* length */ #define ER_SRC_LEN(x) *(ER_src_len(x)) /* Extension ref source */ /* description length */ #define ER_src_len(x) (&((uchar_t *)x)[6]) /* Extension ref source */ /* description length */ #define ER_EXT_VER(x) *(ER_ext_ver(x)) /* Extension ref description */ /* length */ #define ER_ext_ver(x) (&((uchar_t *)x)[7]) /* Extension ref description */ /* length */ #define ER_EXT_ID_LOC 8 /* location where the ER id */ /* string begins */ #define ER_ext_id(x) (&((uchar_t *)x)[ER_EXT_ID_LOC]) /* extension id string */ #define ER_ext_des(x) (&((uchar_t *)x)[ER_EXT_ID_LOC + ER_ID_LEN(x)]) /* ext. description string */ #define ER_ext_src(x) (&((uchar_t *)x)[ER_EXT_ID_LOC + ER_ID_LEN(x) + \ ER_DES_LEN(x)]) /* ext. source string */ /* * Continuation Area Macros */ #define CE_BLK_LOC(x) BOTH_INT(CE_blk_loc(x)) /* cont. starting block */ #define CE_blk_loc(x) (&((uchar_t *)x)[4]) /* cont. starting block */ #define CE_OFFSET(x) BOTH_INT(CE_offset(x)) /* cont. offset */ #define CE_offset(x) (&((uchar_t *)x)[12]) /* cont. offset */ #define CE_CONT_LEN(x) BOTH_INT(CE_cont_len(x)) /* continuation len */ #define CE_cont_len(x) (&((uchar_t *)x)[20]) /* continuation len */ /* * Sharing Protocol (SP) Macros */ #define SP_CHK_BYTE_1(x) *(SP_chk_byte_1(x)) /* check bytes */ #define SP_chk_byte_1(x) (&((uchar_t *)x)[4]) /* check bytes */ #define SP_CHK_BYTE_2(x) *(SP_chk_byte_2(x)) /* check bytes */ #define SP_chk_byte_2(x) (&((uchar_t *)x)[5]) /* check bytes */ #define SUSP_CHECK_BYTE_1 (uchar_t)0xBE /* check for 0xBE */ #define SUSP_CHECK_BYTE_2 (uchar_t)0xEF /* check for 0xEF */ #define CHECK_BYTES_OK(x) ((SP_CHK_BYTE_1(x) == SUSP_CHECK_BYTE_1) && \ (SP_CHK_BYTE_2(x) == SUSP_CHECK_BYTE_2)) #define SP_SUA_OFFSET(x) *(SP_sua_offset(x)) /* SUA bytes to skip */ #define SP_sua_offset(x) (&((uchar_t *)x)[6]) /* SUA bytes to skip */ /* * Forward declarations */ #ifdef _KERNEL extern uchar_t *share_protocol(); extern uchar_t *share_ext_ref(); extern uchar_t *share_continue(); extern uchar_t *share_padding(); extern uchar_t *share_stop(); #endif /* * Extension signature structure, to corrolate the handler functions * with the signatures */ struct extension_signature_struct { char *ext_signature; /* extension signature */ uchar_t *(*sig_handler)(); /* extension handler function */ }; typedef struct extension_signature_struct ext_signature_t; /* * Extension name structure, to corrolate the extensions with their own * signature tables. */ struct extension_name_struct { char *extension_name; /* ER field identifier */ ushort_t ext_version; /* version # of extensions */ ext_signature_t *signature_table; /* pointer to signature */ /* table for appropriate */ /* extension */ }; typedef struct extension_name_struct extension_name_t; /* * Extern declaration for all supported extensions */ struct cont_info_struct { uint_t cont_lbn; /* location of cont */ uint_t cont_offset; /* offset into cont */ uint_t cont_len; /* len of cont */ }; typedef struct cont_info_struct cont_info_t; /* * Structure for passing arguments to sig_handler()'s. Since there are * so many sig_handler()'s, it would be slower to pass multiple * arguments to all of them. It would also ease maintainance */ struct sig_args_struct { uchar_t *dirp; /* pointer to ISO dir entry */ uchar_t *name_p; /* dir entry name */ int *name_len_p; /* dir entry name length */ short flags; /* misc flags */ ulong_t name_flags; /* misc flags */ uchar_t *SUF_ptr; /* pointer to current SUF */ struct hs_direntry *hdp; /* directory entry */ struct hsfs *fsp; /* file system */ cont_info_t *cont_info_p; /* continuation area */ }; typedef struct sig_args_struct sig_args_t; /* * Extern declaration for all supported extensions */ #ifdef _KERNEL extern ext_signature_t rrip_signature_table[]; extern ext_signature_t susp_signature_table[]; extern extension_name_t extension_name_table[]; extern ext_signature_t *susp_sp; extern int parse_sua(uchar_t *, int *name_len_p, int *, uchar_t *, uint_t, struct hs_direntry *, struct hsfs *, uchar_t *, int search_num); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_HSFS_SUSP_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Loopback mount info - one per mount */ #ifndef _SYS_FS_LOFS_INFO_H #define _SYS_FS_LOFS_INFO_H #ifdef _KERNEL #include #endif #ifdef __cplusplus extern "C" { #endif struct lnode; struct lobucket { kmutex_t lh_lock; /* lock protecting bucket contents */ struct lnode *lh_chain; /* vnode chain for this bucket */ uint_t lh_count; /* Number of vnodes in chain */ /* Pad up to 64-byte boundary to avoid false sharing */ #ifdef _LP64 char _pad[44]; #else char _pad[48]; #endif }; struct lo_retired_ht { struct lo_retired_ht *lrh_next; struct lobucket *lrh_table; uint_t lrh_size; }; struct loinfo { struct vfs *li_realvfs; /* real vfs of mount */ struct vfs *li_mountvfs; /* loopback vfs */ struct vnode *li_rootvp; /* root vnode of this vfs */ int li_mflag; /* mount flags to inherit */ int li_dflag; /* mount flags to not inherit */ uint_t li_refct; /* # outstanding vnodes */ volatile uint_t li_htsize; /* # buckets in hashtable */ struct lobucket *volatile li_hashtable; /* table of per-mount vnodes */ struct lfsnode *li_lfs; /* list of other vfss */ kmutex_t li_lfslock; /* lock protecting li_lfs */ kmutex_t li_htlock; /* protect hashtable, htsize, retired */ struct lo_retired_ht *li_retired; /* list of retired hashtables */ int li_flag; /* filesystem behavior flags */ }; /* inheritable mount flags - propagated from real vfs to loopback */ #define INHERIT_VFS_FLAG \ (VFS_RDONLY|VFS_NOSETUID|VFS_NODEVICES|VFS_XATTR|VFS_NBMAND|VFS_NOEXEC) /* * "nosub" is used to provide NFS server-like semantics for lo_lookup(): never * traverse mount points for sub-mounts. The lookup will instead look under * the mount point. */ #define MNTOPT_LOFS_NOSUB "nosub" #define MNTOPT_LOFS_SUB "sub" /* * Flag values (for li_flag) */ #define LO_NOSUB 0x02 /* don't traverse sub-mounts */ /* * lfsnodes are allocated as new real vfs's are encountered * when looking up things in a loopback name space * It contains a new vfs which is paired with the real vfs * so that vfs ops (fsstat) can get to the correct real vfs * given just a loopback vfs */ struct lfsnode { struct lfsnode *lfs_next; /* next in loinfo list */ struct vfs *lfs_realvfs; /* real vfs */ struct vnode *lfs_realrootvp; /* real root vp */ struct vfs lfs_vfs; /* new loopback vfs */ }; #define vtoli(VFSP) ((struct loinfo *)((VFSP)->vfs_data)) #ifdef _KERNEL extern struct vfs *lo_realvfs(struct vfs *, struct vnode **); extern void lofs_subrinit(void); extern void lofs_subrfini(void); extern void lsetup(struct loinfo *, uint_t); extern void ldestroy(struct loinfo *); extern const struct fs_operation_def lo_vnodeops_template[]; extern struct vnodeops *lo_vnodeops; extern vfsops_t *lo_vfsops; extern struct mod_ops mod_fsops; #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_LOFS_INFO_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Loop-back file information structure. */ #ifndef _SYS_FS_LOFS_NODE_H #define _SYS_FS_LOFS_NODE_H #include #ifdef __cplusplus extern "C" { #endif /* * The lnode is the "inode" for loop-back files. It contains * all the information necessary to handle loop-back file on the * client side. */ typedef struct lnode { struct lnode *lo_next; /* link for hash chain */ struct vnode *lo_vp; /* pointer to real vnode */ uint_t lo_looping; /* looping flags (see below) */ struct vnode *lo_vnode; /* place holder vnode for file */ } lnode_t; /* * Flags used when looping has been detected. */ #define LO_LOOPING 0x01 /* Looping detected */ #define LO_AUTOLOOP 0x02 /* Autonode looping detected */ /* * Flag passed to makelonode(). */ #define LOF_FORCE 0x1 /* Force creation of new lnode */ /* * Convert between vnode and lnode */ #define ltov(lp) (((lp)->lo_vnode)) #define vtol(vp) ((struct lnode *)((vp)->v_data)) #define realvp(vp) (vtol(vp)->lo_vp) #ifdef _KERNEL extern vnode_t *makelonode(vnode_t *, struct loinfo *, int); extern void freelonode(lnode_t *); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_LOFS_NODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_MNTFS_MNTDATA_H #define _SYS_MNTFS_MNTDATA_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct mntelem { /* Metadata. */ struct mntelem *mnte_next; struct mntelem *mnte_prev; timespec_t mnte_birth; timespec_t mnte_death; timespec_t mnte_vfs_ctime; int mnte_refcnt; /* Payload. */ int mnte_hidden; char *mnte_text; size_t mnte_text_size; struct extmnttab mnte_tab; } mntelem_t; typedef struct mntsnap { timespec_t mnts_time; /* Time of this snapshot. */ timespec_t mnts_last_mtime; /* mnttab modification time. */ mntelem_t *mnts_first; /* First element in this snapshot. */ mntelem_t *mnts_next; /* Next element to use. */ int mnts_flags; /* flags; see below. */ size_t mnts_nmnts; /* # of elements in this snapshot. */ size_t mnts_text_size; /* Text size for this snapshot. */ size_t mnts_foffset; /* File offset of last read(). */ size_t mnts_ieoffset; /* Offset of last read() in element. */ } mntsnap_t; typedef struct mntnode { vnode_t *mnt_vnode; /* vnode for this mntnode */ vnode_t *mnt_mountvp; /* vnode mounted on */ krwlock_t mnt_contents; /* protects mnt_flags, mnt_read & mnt_ioctl */ uint_t mnt_flags; /* flags; see below */ mntsnap_t mnt_read; /* data for read() */ mntsnap_t mnt_ioctl; /* data for ioctl() */ } mntnode_t; /* * Conversion macros. */ #define VTOM(vp) ((struct mntnode *)(vp)->v_data) #define MTOV(pnp) ((pnp)->mnt_vnode) #define MTOD(pnp) ((struct mntdata *)MTOV(pnp)->v_vfsp->vfs_data) #define MNTFS_ELEM_IS_DEAD(x) ((x)->mnte_death.tv_sec || \ (x)->mnte_death.tv_nsec) #define MNTFS_ELEM_IS_ALIVE(x) !MNTFS_ELEM_IS_DEAD(x) #if defined(_KERNEL) typedef struct mntdata { zone_ref_t mnt_zone_ref; /* zone for mount point */ uint_t mnt_nopen; /* count of vnodes open */ size_t mnt_size; /* size of last normal snapshot */ size_t mnt_hidden_size; /* size of last hidden snapshot */ timespec_t mnt_mtime; /* mtime at last normal snapshot */ timespec_t mnt_hidden_mtime; /* mtime at last hidden snapshot */ struct mntnode mnt_node; /* embedded mntnode */ } mntdata_t; /* * Value for a mntsnap_t's mnts_flags. */ #define MNTS_SHOWHIDDEN 0x1 /* This snapshot contains hidden mounts. */ #define MNTS_REWIND 0x2 /* This snapshot must be refreshed. */ /* * Values for a mntnode_t's mnt_flags. */ #define MNT_SHOWHIDDEN 0x1 /* Include MS_NOMNTTAB mounts in snapshots. */ extern struct vnodeops *mntvnodeops; extern void mntfs_getmntopts(struct vfs *, char **, size_t *); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_MNTFS_MNTDATA_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ #ifndef _SYS_FS_NAMENODE_H #define _SYS_FS_NAMENODE_H #if defined(_KERNEL) #include #include #endif #ifdef __cplusplus extern "C" { #endif /* * This structure is used to pass a file descriptor from user * level to the kernel. It is first used by fattach() and then * be NAMEFS. */ struct namefd { int fd; }; #if defined(_KERNEL) /* * Each NAMEFS object is identified by a struct namenode/vnode pair. */ struct namenode { struct vnode *nm_vnode; /* represents mounted file desc. */ int nm_flag; /* flags defined below */ struct vattr nm_vattr; /* attributes of mounted file desc. */ struct vnode *nm_filevp; /* file desc. prior to mounting */ struct file *nm_filep; /* file pointer of nm_filevp */ struct vnode *nm_mountpt; /* mount point prior to mounting */ struct namenode *nm_nextp; /* next link in the linked list */ kmutex_t nm_lock; /* protects nm_vattr */ }; /* * Valid flags for namenodes. */ #define NMNMNT 0x01 /* namenode not mounted */ /* * Macros to convert a vnode to a namenode, and vice versa. */ #define VTONM(vp) ((struct namenode *)((vp)->v_data)) #define NMTOV(nm) ((nm)->nm_vnode) #define NM_FILEVP_HASH_SIZE 64 #define NM_FILEVP_HASH_MASK (NM_FILEVP_HASH_SIZE - 1) #define NM_FILEVP_HASH_SHIFT 7 #define NM_FILEVP_HASH(vp) (&nm_filevp_hash[(((uintptr_t)vp) >> \ NM_FILEVP_HASH_SHIFT) & NM_FILEVP_HASH_MASK]) extern struct namenode *nm_filevp_hash[NM_FILEVP_HASH_SIZE]; extern struct vfs namevfs; extern int nameinit(int, char *); extern int nm_unmountall(struct vnode *, struct cred *); extern void nameinsert(struct namenode *); extern void nameremove(struct namenode *); extern struct namenode *namefind(struct vnode *, struct vnode *); extern uint64_t namenodeno_alloc(void); extern void namenodeno_free(uint64_t); extern struct vnodeops *nm_vnodeops; extern const struct fs_operation_def nm_vnodeops_template[]; extern kmutex_t ntable_lock; typedef int nm_walk_mounts_f(const struct namenode *, cred_t *, void *); extern int nm_walk_mounts(const vnode_t *, nm_walk_mounts_f *, cred_t *, void *); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_NAMENODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_PC_DIR_H #define _SYS_FS_PC_DIR_H #include #ifdef __cplusplus extern "C" { #endif #define PCFNAMESIZE 8 #define PCFEXTSIZE 3 #define PCMAXNAMLEN 255 #define PCMAXNAM_UTF16 (256 * sizeof (uint16_t)) /* for UTF-16 */ #define PCLFNCHUNKSIZE 13 struct pctime { ushort_t pct_time; /* hh:mm:ss (little endian) */ ushort_t pct_date; /* yy:mm:dd (little endian) */ }; /* * Shifts and masks for time and date fields, in host byte order. */ #define SECSHIFT 0 #define SECMASK 0x1F #define MINSHIFT 5 #define MINMASK 0x3F #define HOURSHIFT 11 #define HOURMASK 0x1F #define DAYSHIFT 0 #define DAYMASK 0x1F #define MONSHIFT 5 #define MONMASK 0x0F #define YEARSHIFT 9 #define YEARMASK 0x7F struct pcdir { char pcd_filename[PCFNAMESIZE] __nonstring; /* file name */ char pcd_ext[PCFEXTSIZE] __nonstring; /* file extension */ uchar_t pcd_attr; /* file attributes */ uchar_t pcd_ntattr; /* reserved for NT attributes */ uchar_t pcd_crtime_msec; /* milliseconds after the minute */ struct pctime pcd_crtime; /* creation time/date */ ushort_t pcd_ladate; /* last-access date */ union { uint16_t pcd_eattr; /* OS/2 extended attribute */ pc_cluster16_t pcd_scluster_hi; } un; struct pctime pcd_mtime; /* last modified time/date */ pc_cluster16_t pcd_scluster_lo; /* starting cluster (little endian) */ uint_t pcd_size; /* file size (little endian) */ }; #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /* * Long filename support (introduced by Windows 95) is an interesting * exercise in compatibility. Basically, it is now no longer the case * that an entry in a directory (as described by the 'pcdir' structure above) * contains the entire name of a file. Now, a directory entry can consist of * a long filename component (a series of 'pcdir'-like structures) followed * by a short filename (the old form). Each long filename component is * identified by having it's Read-Only, Hidden, System, and Volume Label * attributes set. Each can store 13 Unicode characters (16-bits, of * which we only look at the lower 8 for now), broken into (gak) three * sections of the entry (since that's the way the available bits fall out). * In addition, each long filename entry has a sequence number (starting * from 1). The first entry has bit 7 (0x40) set in the sequence number, and * has the maximum value in the sequence. This may seem a bit backwards, and * it gets worse: the first entry stores the last component of * the name. So the directory entry for a file named * "This is a very long filename indeed" might look like this: * * Offset Sequence Component Attributes Cluster Size * 0 0x43 "me indeed" RSHV 0 0 * 32 0x02 "y long filena" RSHV 0 0 * 64 0x01 "This is a ver" RSHV 0 0 * 96 ---- "THISIS~1.TXT" 2122 110 * * The last entry is for the short filename, which stores actual information * about the file (like type, permissions, cluster, and size). The short name * is also used by non-long-filename aware applications (like Windows 3.X and * DOS). This name is generated by Windows 95 (and now Solaris) from the * long name, and must (of course) be unique within the directory. * Solaris continues to this entry to actually identify the file and its * attributes (filenames only really matter when names are used, like at * lookup/readdir/remove/create/rename time - for general access to the file * they aren't used). * * Long filenames can also be broken by applications that don't * understand them (for example, a Solaris 2.5.1 user could rename * "THISIS~1.TXT" to "test.exe"). This can be detected because each long * filename component has a checksum which is based on the short filename. * After reading the long filename entry, if the checksum doesn't match the * short name that follows, we simply ignore it and use the short name. * * One subtle thing - though long file names are case-sensitive, * searches for them are not. * * Another _very_ subtle thing. The number of characters in the * last long filename chunk (the first entry, with the 0x40 bit set) is * either all the characters (if there is no null, '\0'), or all the * characters up to the null. _However_, if the remaining characters are * null, Norton Disk Doctor and Microsoft ScanDisk will claim * that the filename entry is damaged. The remaining bytes must actually * contain 0xff (discovered with Disk Doctor). * * Some information about long filename support can be found in the * book "Inside Windows 95" by Adrian King. */ /* * The number of bytes in each section of the name in a long filename * entry. This is _bytes_, not characters: each character is actually * 16 bits. */ #define PCLF_FIRSTNAMESIZE 10 #define PCLF_SECONDNAMESIZE 12 #define PCLF_THIRDNAMESIZE 4 /* * A long filename entry. It must match the 'pcdir' structure in size, * and pcdl_attr must overlap pcd_attr. */ struct pcdir_lfn { uchar_t pcdl_ordinal; /* lfn order. First is 01, next 02, */ /* last has bit 7 (0x40) set */ uchar_t pcdl_firstfilename[PCLF_FIRSTNAMESIZE]; uchar_t pcdl_attr; uchar_t pcdl_type; /* type - always contains 0 for an LFN entry */ uchar_t pcdl_checksum; /* checksum to validate the LFN entry - */ /* based on the short name */ uchar_t pcdl_secondfilename[PCLF_SECONDNAMESIZE]; pc_cluster16_t pcd_scluster; /* (not used, always 0) */ uchar_t pcdl_thirdfilename[PCLF_THIRDNAMESIZE]; }; /* * FAT LFN entries are consecutively numbered downwards, and the last * entry of a LFN chain will have the 0x40 'termination' marker logically * or'ed in. The entry immediately preceeding the short name has number 1, * consecutively increasing. Since the filename length limit on FAT is * 255 unicode characters and every LFN entry contributes 13 characters, * the maximum sequence number is 255/13 + 1 == 20. */ #define PCDL_IS_LAST_LFN(x) ((x->pcdl_ordinal) & 0x40) #define PCDL_LFN_BITS (PCA_RDONLY | PCA_HIDDEN | PCA_SYSTEM | PCA_LABEL) #define PCDL_LFN_MASK (PCDL_LFN_BITS | PCA_DIR | PCA_ARCH) #define PCDL_LFN_VALID_ORD(x) \ (((((struct pcdir_lfn *)(x))->pcdl_ordinal & ~0x40) > 0) && \ ((((struct pcdir_lfn *)(x))->pcdl_ordinal & ~0x40) <= 20)) #define PCDL_IS_LFN(x) \ (enable_long_filenames && \ (((x)->pcd_attr & PCDL_LFN_MASK) == PCDL_LFN_BITS) && \ PCDL_LFN_VALID_ORD((x))) /* * The first char of the file name has special meaning as follows: */ #define PCD_UNUSED ((char)0x00) /* entry has never been used */ #define PCD_ERASED ((char)0xE5) /* entry was erased */ /* * File attributes. */ #define PCA_RDONLY 0x01 /* file is read only */ #define PCA_HIDDEN 0x02 /* file is hidden */ #define PCA_SYSTEM 0x04 /* system file */ #define PCA_LABEL 0x08 /* entry contains the volume label */ #define PCA_DIR 0x10 /* subdirectory */ #define PCA_ARCH 0x20 /* file has been modified since last backup */ /* * Avoid hidden files unless the private variable is set. * Always avoid the label. */ #define PCA_IS_HIDDEN(fsp, attr) \ ((((attr) & PCA_LABEL) == PCA_LABEL) || \ ((((fsp)->pcfs_flags & PCFS_HIDDEN) == 0) && \ ((attr) & (PCA_HIDDEN | PCA_SYSTEM)))) #define PC_NAME_IS_DOT(namep) \ (((namep)[0] == '.') && ((namep)[1] == '\0')) #define PC_NAME_IS_DOTDOT(namep) \ (((namep)[0] == '.') && ((namep)[1] == '.') && ((namep)[2] == '\0')) #define PC_SHORTNAME_IS_DOT(namep) \ (((namep)[0] == '.') && ((namep)[1] == ' ')) #define PC_SHORTNAME_IS_DOTDOT(namep) \ (((namep)[0] == '.') && ((namep)[1] == '.') && ((namep)[2] == ' ')) /* * slot structure is used by the directory search routine to return * the results of the search. If the search is successful sl_blkno and * sl_offset reflect the disk address of the entry and sl_ep points to * the actual entry data in buffer sl_bp. sl_flags is set to whether the * entry is dot or dotdot. If the search is unsuccessful sl_blkno and * sl_offset points to an empty directory slot if there are any. Otherwise * it is set to -1. */ struct pcslot { enum {SL_NONE, SL_FOUND, SL_EXTEND} sl_status; /* slot status */ daddr_t sl_blkno; /* disk block number which has entry */ int sl_offset; /* offset of entry within block */ struct buf *sl_bp; /* buffer containing entry data */ struct pcdir *sl_ep; /* pointer to entry data */ int sl_flags; /* flags (see below) */ }; #define SL_DOT 1 /* entry point to self */ #define SL_DOTDOT 2 /* entry points to parent */ /* * A pcfs directory entry. Directory entries are actually variable * length, but this is the maximum size. * * This _must_ match a dirent64 structure in format. * d_name is 512 bytes long to accomodate 256 UTF-16 characters. */ struct pc_dirent { ino64_t d_ino; /* "inode number" of entry */ off64_t d_off; /* offset of disk directory entry */ unsigned short d_reclen; /* length of this record */ char d_name[PCMAXNAM_UTF16]; }; /* * Check FAT 8.3 filename characters for validity. * Lacking a kernel iconv, codepage support for short filenames * is not provided. * Short names must be uppercase ASCII (no support for MSDOS * codepages right now, sorry) and may not contain any of * *+=|\[];:",<>.?/ which are explicitly forbidden by the * FAT specifications. */ #define pc_invalchar(c) \ (((c) >= 'a' && (c) <= 'z') || \ (c) == '"' || (c) == '*' || (c) == '+' || (c) == ',' || \ (c) == '.' || (c) == '/' || (c) == ':' || (c) == ';' || \ (c) == '<' || (c) == '=' || (c) == '>' || (c) == '?' || \ (c) == '[' || (c) == '|' || (c) == ']' || (c) == '\\') #define pc_validchar(c) (((c) >= ' ' && !((c) & ~0177)) && !pc_invalchar(c)) #ifdef _KERNEL /* * macros for converting ASCII to/from upper or lower case. * users may give and get names in lower case, but they are stored on the * disk in upper case to be PCDOS compatible. * These would better come from some shared source in but * there is no such place yet. */ #define toupper(C) (((C) >= 'a' && (C) <= 'z') ? (C) - 'a' + 'A' : (C)) #define tolower(C) (((C) >= 'A' && (C) <= 'Z') ? (C) - 'A' + 'a' : (C)) extern int pc_tvtopct(timestruc_t *, struct pctime *); /* timeval to pctime */ extern void pc_pcttotv(struct pctime *, int64_t *); /* pctime to timeval */ extern int pc_valid_lfn_char(char); /* valid long filename ch */ extern int pc_read_long_fn(struct vnode *, struct uio *, struct pc_dirent *, struct pcdir **, offset_t *, struct buf **); extern int pc_read_short_fn(struct vnode *, struct uio *, struct pc_dirent *, struct pcdir **, offset_t *, struct buf **); extern int pc_match_long_fn(struct pcnode *, char *, struct pcdir **, struct pcslot *, offset_t *); extern int pc_match_short_fn(struct pcnode *, char *, struct pcdir **, struct pcslot *, offset_t *); extern uchar_t pc_checksum_long_fn(char *, char *); extern void set_long_fn_chunk(struct pcdir_lfn *, char *, int); extern int pc_valid_long_fn(char *, int); extern int pc_extract_long_fn(struct pcnode *, char *, struct pcdir **, offset_t *offset, struct buf **); extern int pc_fname_ext_to_name(char *, char *, char *, int); extern pc_cluster32_t pc_getstartcluster(struct pcfs *, struct pcdir *); extern void pc_setstartcluster(struct pcfs *, struct pcdir *, pc_cluster32_t); /* * Private tunables */ /* * Use long filenames (Windows 95). Disabling this causes pcfs * to not recognize long filenames at all, which may cause it to * break associations between the short and long names. This is likely * to leave unused long filename entries in directories (which may make * apparently empty directories unremovable), and would require a fsck_pcfs * to find and fix (or a Windows utility like Norton Disk Doctor or * Microsoft ScanDisk). */ extern int enable_long_filenames; /* default: on */ #endif #ifdef __cplusplus } #endif #endif /* _SYS_FS_PC_DIR_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_PC_FS_H #define _SYS_FS_PC_FS_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef uint16_t pc_cluster16_t; typedef uint32_t pc_cluster32_t; /* * PC (MSDOS) compatible virtual file system. * * A main goal of the implementation was to maintain statelessness * except while files are open. Thus mounting and unmounting merely * declared the file system name. The user may change disks at almost * any time without concern (just like the PC). It is assumed that when * files are open for writing the disk access light will be on, as a * warning not to change disks. The implementation must, however, detect * disk change and recover gracefully. It does this by comparing the * in core entry for a directory to the on disk entry whenever a directory * is searched. If a discrepancy is found active directories become root and * active files are marked invalid. * * There are only two type of nodes on the PC file system; files and * directories. These are represented by two separate vnode op vectors, * and they are kept in two separate tables. Files are known by the * disk block number and block (cluster) offset of the files directory * entry. Directories are known by the starting cluster number. * * The file system is locked for during each user operation. This is * done to simplify disk verification error conditions. * * Notes on FAT32 support * ---------------------- * The basic difference between FAT32 and FAT16 is that cluster numbers are now * 32-bit instead of 16-bit. The FAT is thus an array of 32-bit cluster numbers, * and because of this the cluster size can be much smaller on a large disk * (4k, say, on a 1 Gig drive instead of 16k). Unfortunately, the FAT is not * the only place cluster numbers are stored - the starting cluster is stored * in the directory entry for a file, and of course it's only 16-bit. Luckily, * there's a 16-bit OS/2 Extended Attribute field that is now used to store the * upper 16-bits of the starting cluster number. * * Most of the FAT32 changes to pcfs are under 'if it's FAT32' to minimize the * effect on non-FAT32 filesystems (and still share the code), except for the * starting cluster changes. It seemed easier to make common functions to * handle that. * * Other changes: * * 1. FAT32 partitions are indicated by partition types 0xB and 0xC. * 2. The boot sector is now 2 sectors, to make room for FAT32 extensions. * 3. The root directory is no longer stored in a fixed location. Its' * starting cluster is stored in the extended boot sector. * 4. "Summary information" is now stored and we need to (at least) maintain * the number of free clusters or scandisk will be upset. Though the * sector this info is in is pointed to by the extensions in the boot * sector, the magic offset of this information is just that so * far - magic. 0x1e0. * 5. FAT32 can use the alternate FAT. But we don't. * * FAT32 also exposed a latent bug: we bread() each copy of the FAT in one * big chunk. This is not good on a large FAT32 drive, such as a 1 Gig * Jaz drive that has 4k clusters, since the FAT becomes 1 Meg in size and * bread blocks forever. So now we read the FAT in chunks. */ /* * The FAT bootsector uses little-endian multibyte values not aligned at * a 'native' wordsize. Instead of defining a strange data structure and * odd accessor methods for some members while using standard C accesses * for others, we don't bother and just define the structure offsets, and * a common set of misaligned-littleendian accessor macros. * * The "bootsec" and "fat32_bootsec" structures are only provided for * compatibility with old code including but not used * by the PCFS kernel driver anymore. */ struct bootsec { uchar_t instr[3]; uchar_t version[8]; uchar_t bps[2]; /* bytes per sector */ uchar_t spcl; /* sectors per allocation unit */ uchar_t res_sec[2]; /* reserved sectors, starting at 0 */ uchar_t nfat; /* number of FATs */ uchar_t rdirents[2]; /* number of root directory entries */ uchar_t numsect[2]; /* old total sectors in logical image */ uchar_t mediadesriptor; /* media descriptor byte */ ushort_t fatsec; /* number of sectors per FAT */ ushort_t spt; /* sectors per track */ ushort_t nhead; /* number of heads */ uint_t hiddensec; /* number of hidden sectors */ uint_t totalsec; /* total sectors in logical image */ }; /* * FAT32 volumes have a bigger boot sector. They include the normal * boot sector. */ struct fat32_bootsec { struct bootsec f_bs; uint32_t f_fatlength; /* size of FAT */ uint16_t f_flags; uint8_t f_major; /* major filesystem version #? */ uint8_t f_minor; /* minor filesystem version #? */ uint32_t f_rootcluster; /* first cluster in root directory */ uint16_t f_infosector; /* where summary info is */ uint16_t f_backupboot; /* backup boot sector */ uint16_t f_reserved2[6]; }; #define OFF_JMPBOOT 0 #define OFF_OEMNAME 3 #define OFF_BYTESPERSEC 11 #define OFF_SECPERCLUS 13 #define OFF_RSVDSECCNT 14 #define OFF_NUMFATS 16 #define OFF_ROOTENTCNT 17 #define OFF_TOTSEC16 19 #define OFF_MEDIA 21 #define OFF_FATSZ16 22 #define OFF_SECPERTRK 24 #define OFF_NUMHEADS 26 #define OFF_HIDDSEC 28 #define OFF_TOTSEC32 32 #define OFF_BPBSIG 510 #define OFF_DRVNUM16 36 #define OFF_BOOTSIG16 38 #define OFF_VOLID16 39 #define OFF_VOLLAB16 43 #define OFF_FILSYSTYP16 54 #define OFF_FATSZ32 36 #define OFF_EXTFLAGS32 40 #define OFF_FSVER32 42 #define OFF_ROOTCLUS32 44 #define OFF_FSINFO32 48 #define OFF_BKBOOTSEC32 50 #define OFF_DRVNUM32 64 #define OFF_BOOTSIG32 66 #define OFF_VOLID32 67 #define OFF_VOLLAB32 71 #define OFF_FILSYSTYP32 82 #define LE_16_NA(addr) \ (((uint16_t)*((uint8_t *)(addr))) + \ ((uint16_t)*((uint8_t *)(addr) + 1) << 8)) #define LE_32_NA(addr) \ (((uint32_t)*((uint8_t *)(addr))) + \ ((uint32_t)*((uint8_t *)(addr) + 1) << 8) + \ ((uint32_t)*((uint8_t *)(addr) + 2) << 16) + \ ((uint32_t)*((uint8_t *)(addr) + 3) << 24)) /* * Generic FAT BPB fields */ #define bpb_jmpBoot(bpb) ((unsigned char *)(bpb)) #define bpb_OEMName(bpb) ((char *)(bpb) + OFF_OEMNAME) #define bpb_get_BytesPerSec(bpb) LE_16_NA((bpb) + OFF_BYTESPERSEC) #define bpb_get_SecPerClus(bpb) (((uint8_t *)(bpb))[OFF_SECPERCLUS]) #define bpb_get_RsvdSecCnt(bpb) LE_16_NA((bpb) + OFF_RSVDSECCNT) #define bpb_get_NumFATs(bpb) (((uint8_t *)(bpb))[OFF_NUMFATS]) #define bpb_get_RootEntCnt(bpb) LE_16_NA((bpb) + OFF_ROOTENTCNT) #define bpb_get_TotSec16(bpb) LE_16_NA((bpb) + OFF_TOTSEC16) #define bpb_get_Media(bpb) (((uint8_t *)(bpb))[OFF_MEDIA]) #define bpb_get_FatSz16(bpb) LE_16_NA((bpb) + OFF_FATSZ16) #define bpb_get_SecPerTrk(bpb) LE_16_NA((bpb) + OFF_SECPERTRK) #define bpb_get_NumHeads(bpb) LE_16_NA((bpb) + OFF_NUMHEADS) #define bpb_get_HiddSec(bpb) LE_32_NA((bpb) + OFF_HIDDSEC) #define bpb_get_TotSec32(bpb) LE_32_NA((bpb) + OFF_TOTSEC32) #define bpb_get_BPBSig(bpb) LE_16_NA((bpb) + OFF_BPBSIG) /* * FAT12/16 extended BPB fields */ #define bpb_get_DrvNum16(bpb) (((uint8_t *)(bpb))[OFF_DRVNUM16]) #define bpb_get_BootSig16(bpb) (((uint8_t *)(bpb))[OFF_BOOTSIG16]) #define bpb_VolLab16(bpb) ((char *)(bpb) + OFF_VOLLAB16) #define bpb_FilSysType16(bpb) ((char *)(bpb) + OFF_FILSYSTYP16) #define bpb_get_VolID16(bpb) LE_32_NA((bpb) + OFF_VOLID16) /* * FAT32 extended BPB fields */ #define bpb_get_FatSz32(bpb) LE_32_NA((bpb) + OFF_FATSZ32) #define bpb_get_ExtFlags32(bpb) LE_16_NA((bpb) + OFF_EXTFLAGS32) #define bpb_get_FSVer32(bpb) LE_16_NA((bpb) + OFF_FSVER32) #define bpb_get_RootClus32(bpb) LE_32_NA((bpb) + OFF_ROOTCLUS32) #define bpb_get_FSInfo32(bpb) LE_16_NA((bpb) + OFF_FSINFO32) #define bpb_get_BkBootSec32(bpb) LE_16_NA((bpb) + OFF_BKBOOTSEC32) #define bpb_get_DrvNum32(bpb) (((uint8_t *)(bpb))[OFF_DRVNUM32]) #define bpb_get_BootSig32(bpb) (((uint8_t *)(bpb))[OFF_BOOTSIG32]) #define bpb_get_VolID32(bpb) LE_32_NA((bpb) + OFF_VOLID32) #define bpb_VolLab32(bpb) ((char *)(bpb) + OFF_VOLLAB32) #define bpb_FilSysType32(bpb) ((char *)(bpb) + OFF_FILSYSTYP32) /* * Validators */ #define VALID_SECSIZE(s) \ (s == 512 || s == 1024 || s == 2048 || s == 4096) #define VALID_SPCL(s) (ISP2((s)) && (unsigned int)(s) <= 128) #define VALID_CLSIZE(s) (ISP2((s)) && (unsigned int)(s) <= (64 * 1024)) #define VALID_NUMFATS(n) ((n) > 0 && (n) < 8) #define VALID_RSVDSEC(s) ((s) > 0) #define VALID_BPBSIG(sig) ((sig) == MBB_MAGIC) #define VALID_BOOTSIG(sig) ((sig) == 0x29) #define VALID_MEDIA(m) ((m) == 0xF0 || ((m) >= 0xF8 && (m) <= 0xFF)) /* * this might require a change for codepage support. In particular, * pc_validchar() cannot be a macro anymore if codepages get involved. */ #define VALID_VOLLAB(l) ( \ pc_validchar((l)[0]) && pc_validchar((l)[1]) && \ pc_validchar((l)[2]) && pc_validchar((l)[3]) && \ pc_validchar((l)[4]) && pc_validchar((l)[5]) && \ pc_validchar((l)[6]) && pc_validchar((l)[7]) && \ pc_validchar((l)[8]) && pc_validchar((l)[9]) && \ pc_validchar((l)[10])) /* * We might actually use the 'validchar' checks as well; it only needs * to be printable. Should this ever caused failed media recognition, * we can change it. Many ISVs put different strings into the "oemname" * field. */ #define VALID_OEMNAME(nm) ( \ bcmp((nm), "MSDOS", 5) == 0 || bcmp((nm), "MSWIN", 5) == 0) #define VALID_FSTYPSTR16(typ) (bcmp((typ), "FAT", 3) == 0) #define VALID_FSTYPSTR32(typ) (bcmp((typ), "FAT32", 5) == 0) #define VALID_JMPBOOT(b) ( \ ((b)[0] == 0xeb && (b)[2] == 0x90) || (b)[0] == 0xe9) #define VALID_FSVER32(v) ((v) == PCFS_SUPPORTED_FSVER) /* * Can we check this properly somehow ? There should be a better way. * The FAT spec doesn't mention reserved bits need to be zero ... */ #define VALID_EXTFLAGS(flags) (((flags) & 0x8f) == (flags)) /* * Validation results */ #define BPB_SECSIZE_OK (1 << 0) /* ok: 512/1024/2048/4096 */ #define BPB_OEMNAME_OK (1 << 1) /* "MSDOS" or "MSWIN" */ #define BPB_JMPBOOT_OK (1 << 2) /* 16bit "jmp" / "call" */ #define BPB_SECPERCLUS_OK (1 << 3) /* power of 2, [1 .. 128] */ #define BPB_RSVDSECCNT_OK (1 << 4) /* cannot be zero */ #define BPB_NUMFAT_OK (1 << 5) /* >= 1, <= 8 */ #define BPB_ROOTENTCNT_OK (1 << 6) /* 0 on FAT32, != 0 else */ #define BPB_TOTSEC_OK (1 << 7) /* smaller than volume */ #define BPB_TOTSEC16_OK (1 << 8) /* 0 on FAT32, != 0 on FAT12 */ #define BPB_TOTSEC32_OK (1 << 9) /* 0 on FAT12, != 0 on FAT32 */ #define BPB_MEDIADESC_OK (1 << 10) /* 0xf0 or 0xf8..0xff */ #define BPB_FATSZ_OK (1 << 11) /* [nclusters], no smaller */ #define BPB_FATSZ16_OK (1 << 12) /* 0 on FAT32, != 0 else */ #define BPB_FATSZ32_OK (1 << 13) /* non-zero on FAT32 */ #define BPB_BPBSIG_OK (1 << 14) /* 0x55, 0xAA */ #define BPB_BOOTSIG16_OK (1 << 15) /* 0x29 - if present */ #define BPB_BOOTSIG32_OK (1 << 16) /* 0x29 - unless SYSLINUX2.x */ #define BPB_FSTYPSTR16_OK (1 << 17) /* At least "FAT" */ #define BPB_FSTYPSTR32_OK (1 << 18) /* "FAT32" */ #define BPB_EXTFLAGS_OK (1 << 19) /* reserved bits should be 0 */ #define BPB_FSVER_OK (1 << 20) /* must be 0 */ #define BPB_ROOTCLUSTER_OK (1 << 21) /* must be != 0 and valid */ #define BPB_FSISEC_OK (1 << 22) /* != 0, <= reserved */ #define BPB_BKBOOTSEC_OK (1 << 23) /* != 0, <= reserved, != fsi */ #define BPB_VOLLAB16_OK (1 << 24) /* passes pc_validchar() */ #define BPB_VOLLAB32_OK (1 << 25) /* passes pc_validchar() */ #define BPB_NCLUSTERS_OK (1 << 26) /* from FAT spec */ #define BPB_CLSIZE_OK (1 << 27) /* cluster size */ #define BPB_MEDIASZ_OK (1 << 28) /* filesystem fits on device */ #define FAT12_VALIDMSK \ (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \ BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \ BPB_TOTSEC_OK | BPB_TOTSEC16_OK | \ BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK) #define FAT16_VALIDMSK \ (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \ BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \ BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | \ BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK) /* * A note on FAT32: According to the FAT spec, FAT32 _must_ have a valid * extended BPB and therefore, as a proof of its existance, the FAT32 * boot signature (offset 66) must be valid as well. Why don't we check * for BPB_BOOTSIG32_OK then ? * * We don't test for this here first-pass, because there are media out * there that are valid FAT32 structurally but don't have a valid sig. * This happens if older versions of the SYSLINUX bootloader (below 3.x) * are installed on a media with a FAT32 on it. SYSLINUX 2.x and lower * overwrite the BPB past the end of the FAT12/16 extension with its * bootloader code - and the FAT16 extended BPB is 62 Bytes... * All structurally relevant fields of the FAT32 BPB are within the first * 52 Bytes, so the filesystem is accessible - but the signature check * would reject it. */ #define FAT32_VALIDMSK \ (BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK | \ BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK | \ BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | \ BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_FATSZ32_OK | \ BPB_EXTFLAGS_OK | BPB_FSVER_OK | BPB_ROOTCLUSTER_OK | \ BPB_BPBSIG_OK) /* * FAT32 BPB allows 'versioning' via FSVer32. We follow the 'NULL' spec. */ #define PCFS_SUPPORTED_FSVER 0 /* * Filesystem summary information (introduced originally for FAT32 volumes). * We need to maintain fs_free_clusters or Microsoft Scandisk will be upset. * We keep these values in-core even for FAT12/FAT16 but will never attempt * to write them out to disk then. */ typedef struct fat_fsinfo { uint32_t fs_free_clusters; /* # free clusters. -1 if unknown */ uint32_t fs_next_free; /* search next free after this cn */ } fat_fsi_t; /* * On-disk FSI. All values in little endian. Only FAT32 has this. */ typedef struct fat_od_fsi { uint32_t fsi_leadsig; /* 0x41615252 */ char fsi_reserved1[480]; uint32_t fsi_strucsig; /* 0x61417272 */ fat_fsi_t fsi_incore; /* free/nextfree */ char fsi_reserved2[12]; uint32_t fsi_trailsig; /* 0xaa550000 */ } fat_od_fsi_t; #define FSI_LEADSIG LE_32(0x41615252) #define FSI_STRUCSIG LE_32(0x61417272) #define FSI_TRAILSIG LE_32(0xaa550000) /* same as MBB_MAGIC */ #define FSISIG_OK(fsi) ( \ ((fat_od_fsi_t *)(fsi))->fsi_leadsig == FSI_LEADSIG && \ ((fat_od_fsi_t *)(fsi))->fsi_strucsig == FSI_STRUCSIG && \ ((fat_od_fsi_t *)(fsi))->fsi_trailsig == FSI_TRAILSIG) #define FSINFO_UNKNOWN ((uint32_t)(-1)) /* free/next not valid */ typedef enum { FAT12, FAT16, FAT32, FAT_UNKNOWN, FAT_QUESTIONABLE } fattype_t; struct pcfs { struct vfs *pcfs_vfs; /* vfs for this fs */ int pcfs_flags; /* flags */ int pcfs_ldrive; /* logical DOS drive number */ fattype_t pcfs_fattype; dev_t pcfs_xdev; /* actual device that is mounted */ struct vnode *pcfs_devvp; /* and a vnode for it */ int pcfs_secsize; /* sector size in bytes */ int pcfs_spcl; /* sectors per cluster */ int pcfs_spt; /* sectors per track */ int pcfs_sdshift; /* shift to convert sector into */ /* DEV_BSIZE "sectors"; assume */ /* pcfs_secsize is 2**n times of */ /* DEV_BSIZE */ int pcfs_fatsec; /* number of sec per FAT */ int pcfs_numfat; /* number of FAT copies */ int pcfs_rdirsec; /* number of sec in root dir */ daddr_t pcfs_dosstart; /* start blkno of DOS partition */ daddr_t pcfs_fsistart; /* start blkno of FSI sector */ daddr_t pcfs_fatstart; /* start blkno of first FAT */ daddr_t pcfs_rdirstart; /* start blkno of root dir */ daddr_t pcfs_datastart; /* start blkno of data area */ int pcfs_clsize; /* cluster size in bytes */ int pcfs_ncluster; /* number of clusters in fs */ int pcfs_nrefs; /* number of active pcnodes */ int pcfs_frefs; /* number of active file pcnodes */ int pcfs_nxfrecls; /* next free cluster */ uchar_t *pcfs_fatp; /* ptr to FAT data */ uchar_t *pcfs_fat_changemap; /* map of changed fat data */ int pcfs_fat_changemapsize; /* size of FAT changemap */ time_t pcfs_fattime; /* time FAT becomes invalid */ time_t pcfs_verifytime; /* time to reverify disk */ kmutex_t pcfs_lock; /* per filesystem lock */ kthread_id_t pcfs_owner; /* id of thread locking pcfs */ int pcfs_count; /* # of pcfs locks for pcfs_owner */ struct fat_fsinfo pcfs_fsinfo; /* in-core fsinfo */ struct pcfs *pcfs_nxt; /* linked list of all mounts */ int pcfs_fatjustread; /* Used to flag a freshly found FAT */ struct vnode *pcfs_root; /* vnode for the root dir of the fs */ int pcfs_secondswest; /* recording timezone for this fs */ len_t pcfs_mediasize; int pcfs_rootblksize; int pcfs_mediadesc; /* media descriptor */ pc_cluster32_t pcfs_lastclmark; pc_cluster32_t pcfs_rootclnum; timestruc_t pcfs_mounttime; /* timestamp for "/" */ }; /* * flags */ #define PCFS_FATMOD 0x01 /* FAT has been modified */ #define PCFS_LOCKED 0x02 /* fs is locked */ #define PCFS_WANTED 0x04 /* locked fs is wanted */ #define PCFS_NOCHK 0x800 /* don't resync fat on error */ #define PCFS_BOOTPART 0x1000 /* boot partition type */ #define PCFS_HIDDEN 0x2000 /* show hidden files */ #define PCFS_PCMCIA_NO_CIS 0x4000 /* PCMCIA psuedo floppy */ #define PCFS_FOLDCASE 0x8000 /* fold filenames to lowercase */ #define PCFS_FSINFO_OK 0x10000 /* valid FAT32 fsinfo sector */ #define PCFS_IRRECOV 0x20000 /* FS was messed with during write */ #define PCFS_NOCLAMPTIME 0x40000 /* expose full FAT timestamp range */ #define PCFS_NOATIME 0x80000 /* disable atime updates */ #define IS_FAT12(PCFS) ((PCFS)->pcfs_fattype == FAT12) #define IS_FAT16(PCFS) ((PCFS)->pcfs_fattype == FAT16) #define IS_FAT32(PCFS) ((PCFS)->pcfs_fattype == FAT32) /* for compatibility */ struct old_pcfs_args { int secondswest; /* seconds west of Greenwich */ int dsttime; /* type of dst correction */ }; struct pcfs_args { int secondswest; /* seconds west of Greenwich */ int dsttime; /* type of dst correction */ int flags; }; /* * pcfs mount options. */ #define MNTOPT_PCFS_HIDDEN "hidden" #define MNTOPT_PCFS_NOHIDDEN "nohidden" #define MNTOPT_PCFS_FOLDCASE "foldcase" #define MNTOPT_PCFS_NOFOLDCASE "nofoldcase" #define MNTOPT_PCFS_CLAMPTIME "clamptime" #define MNTOPT_PCFS_NOCLAMPTIME "noclamptime" #define MNTOPT_PCFS_TIMEZONE "timezone" #define MNTOPT_PCFS_SECSIZE "secsize" /* * Disk timeout value in sec. * This is used to time out the in core FAT and to re-verify the disk. * This should be less than the time it takes to change floppys */ #define PCFS_DISKTIMEOUT 2 #define PCFS_MAXOFFSET_T UINT32_MAX /* PCFS max file size */ #define VFSTOPCFS(VFSP) ((struct pcfs *)((VFSP)->vfs_data)) #define PCFSTOVFS(FSP) ((FSP)->pcfs_vfs) /* * special cluster numbers in FAT */ #define PCF_FREECLUSTER 0x00 /* cluster is available */ #define PCF_ERRORCLUSTER 0x01 /* error occurred allocating cluster */ #define PCF_12BCLUSTER 0xFF0 /* 12-bit version of reserved cluster */ #define PCF_RESCLUSTER 0xFFF0 /* 16-bit version of reserved cluster */ #define PCF_RESCLUSTER32 0xFFFFFF0 /* 32-bit version */ #define PCF_BADCLUSTER 0xFFF7 /* bad cluster, do not use */ #define PCF_BADCLUSTER32 0xFFFFFF7 /* 32-bit version */ #define PCF_LASTCLUSTER 0xFFF8 /* >= means last cluster in file */ #define PCF_LASTCLUSTER32 0xFFFFFF8 /* 32-bit version */ #define PCF_LASTCLUSTERMARK 0xFFFF /* value used to mark last cluster */ #define PCF_LASTCLUSTERMARK32 0xFFFFFFF /* 32-bit version */ #define PCF_FIRSTCLUSTER 2 /* first valid cluster number */ /* * file system constants */ #define PC_MAXFATSEC 256 /* maximum number of sectors in FAT */ /* * file system parameter macros */ #define pc_clear_fatchanges(PCFS) \ bzero((PCFS)->pcfs_fat_changemap, (PCFS)->pcfs_fat_changemapsize) #define pc_blksize(PCFS, PCP, OFF) /* file system block size */ \ (((PCTOV(PCP)->v_flag & VROOT) && !IS_FAT32(PCFS)) ? \ ((OFF) >= \ ((PCFS)->pcfs_rdirsec & \ ~((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize)? \ ((PCFS)->pcfs_rdirsec & \ ((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize): \ (PCFS)->pcfs_clsize): \ (PCFS)->pcfs_clsize) #define pc_blkoff(PCFS, OFF) /* offset within block */ \ ((int)((OFF) & ((PCFS)->pcfs_clsize - 1))) #define pc_lblkno(PCFS, OFF) /* logical block (cluster) no */ \ ((daddr_t)((OFF) / (PCFS)->pcfs_clsize)) #define pc_dbtocl(PCFS, DB) /* disk blks to clusters */ \ ((int)((DB) / (PCFS)->pcfs_spcl)) #define pc_cltodb(PCFS, CL) /* clusters to disk blks */ \ ((daddr_t)((CL) * (PCFS)->pcfs_spcl)) #define pc_dbdaddr(PCFS, DB) /* sector to DEV_BSIZE "sector" addr */ \ ((DB) << (PCFS)->pcfs_sdshift) #define pc_daddrdb(PCFS, DADDR) /* DEV_BSIZE "sector" addr to sector addr */ \ ((DADDR) >> (PCFS)->pcfs_sdshift) #define pc_cldaddr(PCFS, CL) /* DEV_BSIZE "sector" addr for cluster */ \ pc_dbdaddr(PCFS, ((daddr_t)((PCFS)->pcfs_datastart + \ pc_cltodb(PCFS, (CL) - PCF_FIRSTCLUSTER)))) #define pc_daddrcl(PCFS, DADDR) /* cluster for disk address */ \ ((int)(PCF_FIRSTCLUSTER + \ pc_dbtocl(pc_daddrdb(PCFS, DADDR) - (PCFS)->pcfs_datastart))) /* * Number of directory entries per sector / cluster */ #define pc_direntpersec(PCFS) \ ((int)((PCFS)->pcfs_secsize / sizeof (struct pcdir))) #define pc_direntpercl(PCFS) \ ((int)((PCFS)->pcfs_clsize / sizeof (struct pcdir))) /* * out-of-range check for cluster numbers. */ #define pc_validcl(PCFS, CL) /* check that cluster no is legit */ \ ((int)(CL) >= PCF_FIRSTCLUSTER && \ (int)(CL) < (PCFS)->pcfs_ncluster + PCF_FIRSTCLUSTER) /* * external routines. */ extern int pc_lockfs(struct pcfs *, int, int); /* lock fs and get fat */ extern void pc_unlockfs(struct pcfs *); /* ulock the fs */ extern int pc_getfat(struct pcfs *); /* get fat from disk */ extern void pc_invalfat(struct pcfs *); /* invalidate incore fat */ extern int pc_syncfat(struct pcfs *); /* sync fat to disk */ extern int pc_freeclusters(struct pcfs *); /* num free clusters in fs */ extern pc_cluster32_t pc_alloccluster(struct pcfs *, int); extern void pc_setcluster(struct pcfs *, pc_cluster32_t, pc_cluster32_t); extern void pc_mark_fat_updated(struct pcfs *fsp, pc_cluster32_t cn); extern int pc_fat_is_changed(struct pcfs *fsp, pc_cluster32_t bn); /* * debugging */ extern int pcfsdebuglevel; #define PC_DPRINTF0(level, A) \ if (pcfsdebuglevel >= level) \ cmn_err(CE_CONT, (A)) #define PC_DPRINTF1(level, A, B) \ if (pcfsdebuglevel >= level) \ cmn_err(CE_CONT, (A), (B)) #define PC_DPRINTF2(level, A, B, C) \ if (pcfsdebuglevel >= level) \ cmn_err(CE_CONT, (A), (B), (C)) #define PC_DPRINTF3(level, A, B, C, D) \ if (pcfsdebuglevel >= level) \ cmn_err(CE_CONT, (A), (B), (C), (D)) #define PC_DPRINTF4(level, A, B, C, D, E) \ if (pcfsdebuglevel >= level) \ cmn_err(CE_CONT, (A), (B), (C), (D), (E)) #ifdef __cplusplus } #endif #endif /* _SYS_FS_PC_FS_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_PC_LABEL_H #define _SYS_FS_PC_LABEL_H #ifdef __cplusplus extern "C" { #endif #include /* * PC master boot block & partition table defines. */ #define PCB_BPSEC 11 /* (short) bytes per sector */ #define PCB_SPC 13 /* (byte) sectors per cluster */ #define PCB_RESSEC 14 /* (short) reserved sectors */ #define PCB_NFAT 16 /* (byte) number of fats */ #define PCB_NROOTENT 17 /* (short) number of root dir entries */ #define PCB_NSEC 19 /* (short) number of sectors on disk */ #define PCB_MEDIA 21 /* (byte) media descriptor */ #define PCB_SPF 22 /* (short) sectors per fat */ #define PCB_SPT 24 /* (short) sectors per track */ #define PCB_NHEAD 26 /* (short) number of heads */ #define PCB_HIDSEC 28 /* (short) number of hidden sectors */ #define PCFS_PART 0x1be /* partition table offs in blk 0 of unit */ #define PCFS_NUMPART 4 /* Number of partitions in blk 0 of unit */ /* * Offsets into the boot sector where the string 'FAT' is expected. * First value is where the string is on 12 and 16 bit FATs, * the second value is where it is on 32 bit FATs. */ #define PCFS_TYPESTRING_OFFSET16 0x36 #define PCFS_TYPESTRING_OFFSET32 0x52 #define PCFS_BPB 0xb /* offset of the BPB in the boot block */ #define PCFS_SIGN 0x1fe /* offset of the DOS signature */ #define DOS_SYSFAT12 1 /* DOS FAT 12 system indicator */ #define DOS_SYSFAT16 4 /* DOS FAT 16 system indicator */ #define DOS_SYSHUGE 6 /* DOS FAT 16 system indicator > 32MB */ #define DOS_FAT32 0xB /* FAT32 system indicator */ #define DOS_FAT32_LBA 0xC /* FAT32 system indicator (LBA) */ #define DOS_FAT16P_LBA 0xE /* FAT16 system indicator (Primary/LBA ) */ #define DOS_FAT16_LBA 0xF /* FAT16 system indicator (Extended/LBA) */ #define DOS_F12MAXS 20740 /* Max sector for 12 Bit FAT (DOS>=3.2) */ #define DOS_F12MAXC 4086 /* Max cluster for 12 Bit FAT (DOS>=3.2) */ #define DOS_ID1 0xe9 /* JMP intrasegment */ #define DOS_ID2a 0xeb /* JMP short */ #define DOS_ID2b 0x90 #define DOS_SIGN 0xaa55 /* DOS signature in boot and partition */ #define PC_FATBLOCK 1 /* starting block number of fat */ /* * Media descriptor byte. * Found in the boot block and in the first byte of the FAT. * Second and third byte in the FAT must be 0xFF. * Note that all technical sources indicate that this means of * identification is extremely unreliable. */ #define MD_FIXED 0xF8 /* fixed disk */ #define SS8SPT 0xFE /* single sided 8 sectors per track */ #define DS8SPT 0xFF /* double sided 8 sectors per track */ #define SS9SPT 0xFC /* single sided 9 sectors per track */ #define DS9SPT 0xFD /* double sided 9 sectors per track */ #define DS18SPT 0xF0 /* double sided 18 sectors per track */ #define DS9_15SPT 0xF9 /* double sided 9/15 sectors per track */ #define PC_SECSIZE 512 /* pc filesystem sector size */ /* * conversions to/from little endian format */ #if defined(_LITTLE_ENDIAN) /* e.g. i386 machines */ #define ltohs(S) (*((ushort_t *)(&(S)))) #define ltohi(I) (*((uint_t *)(&(I)))) #define htols(S) (*((ushort_t *)(&(S)))) #define htoli(I) (*((uint_t *)(&(I)))) #else /* e.g. SPARC machines */ #define getbyte(A, N) (((unsigned char *)(&(A)))[N]) #define ltohs(S) ((getbyte(S, 1) << 8) | getbyte(S, 0)) #define ltohi(I) ((getbyte(I, 3) << 24) | (getbyte(I, 2) << 16) | \ (getbyte(I, 1) << 8) | getbyte(I, 0)) #define htols(S) ((getbyte(S, 1) << 8) | getbyte(S, 0)) #define htoli(I) ((getbyte(I, 3) << 24) | (getbyte(I, 2) << 16) | \ (getbyte(I, 1) << 8) | getbyte(I, 0)) #endif #ifdef __cplusplus } #endif #endif /* _SYS_FS_PC_LABEL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_PC_NODE_H #define _SYS_FS_PC_NODE_H #ifdef __cplusplus extern "C" { #endif #include #include #include #ifdef _KERNEL #include #endif /* * This overlays the fid structure (see vfs.h) * * 10 bytes max. */ struct pc_fid { ushort_t pcfid_len; uint32_t pcfid_block; /* dblock containing directory entry */ uint16_t pcfid_offset; /* offset within block of entry */ uint16_t pcfid_ctime; /* creation time of entry (~= i_gen) */ }; struct pcnode { struct pcnode *pc_forw; /* active list ptrs, must be first */ struct pcnode *pc_back; int pc_flags; /* see below */ struct vnode *pc_vn; /* vnode for pcnode */ uint_t pc_size; /* size of file */ pc_cluster32_t pc_scluster; /* starting cluster of file */ daddr_t pc_eblkno; /* disk blkno for entry */ int pc_eoffset; /* offset in disk block of entry */ struct pcdir pc_entry; /* directory entry of file */ pc_cluster32_t pc_lcluster; /* last cluster visited */ daddr_t pc_lindex; /* index of last cluster visited */ }; /* * flags */ #define PC_MOD 0x01 /* file data has been modified */ #define PC_CHG 0x02 /* node data has been changed */ #define PC_INVAL 0x04 /* node is invalid */ #define PC_EXTERNAL 0x08 /* vnode ref is held externally */ #define PC_ACC 0x10 /* file data has been accessed */ #define PC_RELEHOLD 0x80 /* node is being released */ #define PCTOV(PCP) ((PCP)->pc_vn) #define VTOPC(VP) ((struct pcnode *)((VP)->v_data)) /* * Make a unique integer for a file */ #define pc_makenodeid(BN, OFF, ATTR, SCLUSTER, ENTPS) \ (ino_t)((ATTR) & PCA_DIR ? \ (uint32_t)(-(SCLUSTER) - 1) : \ ((BN) * (ENTPS)) + ((OFF) / sizeof (struct pcdir))) #define NPCHASH 1 #if NPCHASH == 1 #define PCFHASH(FSP, BN, O) 0 #define PCDHASH(FSP, SC) 0 #else #define PCFHASH(FSP, BN, O) (((unsigned)FSP + BN + O) % NPCHASH) #define PCDHASH(FSP, SC) (((unsigned)FSP + SC) % NPCHASH) #endif struct pchead { struct pcnode *pch_forw; struct pcnode *pch_back; }; /* * pcnode file and directory operations vectors */ extern struct vnodeops *pcfs_fvnodeops; extern struct vnodeops *pcfs_dvnodeops; #ifdef _KERNEL extern const struct fs_operation_def pcfs_fvnodeops_template[]; extern const struct fs_operation_def pcfs_dvnodeops_template[]; #endif extern struct pchead pcfhead[]; extern struct pchead pcdhead[]; /* * pcnode routines */ extern void pc_init(void); extern struct pcnode *pc_getnode(struct pcfs *, daddr_t, int, struct pcdir *); extern void pc_rele(struct pcnode *); extern void pc_mark_mod(struct pcfs *, struct pcnode *); extern void pc_mark_acc(struct pcfs *, struct pcnode *); extern int pc_nodesync(struct pcnode *); extern int pc_nodeupdate(struct pcnode *); extern int pc_bmap(struct pcnode *, daddr_t, daddr_t *, uint_t *); extern int pc_balloc(struct pcnode *, daddr_t, int, daddr_t *); extern int pc_bfree(struct pcnode *, pc_cluster32_t); extern int pc_verify(struct pcfs *); extern void pc_diskchanged(struct pcfs *); extern void pc_mark_irrecov(struct pcfs *); extern int pc_dirlook(struct pcnode *, char *, struct pcnode **); extern int pc_direnter(struct pcnode *, char *, struct vattr *, struct pcnode **); extern int pc_dirremove(struct pcnode *, char *, struct vnode *, enum vtype, caller_context_t *); extern int pc_rename(struct pcnode *, struct pcnode *, char *, char *, caller_context_t *); extern int pc_blkatoff(struct pcnode *, offset_t, struct buf **, struct pcdir **); extern int pc_truncate(struct pcnode *, uint_t); extern int pc_fileclsize(struct pcfs *, pc_cluster32_t, pc_cluster32_t *); extern int pcfs_putapage(struct vnode *, page_t *, u_offset_t *, size_t *, int, struct cred *); extern void pc_badfs(struct pcfs *); #ifdef __cplusplus } #endif #endif /* _SYS_FS_PC_NODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1997-1998 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _PXFS_KI_H #define _PXFS_KI_H #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Kernel interface to pxfs routines: definition of stubs. */ /* * kaio interface to pxfs */ extern int clpxfs_aio_write(vnode_t *vp, struct aio_req *aio, cred_t *cred_p); extern int clpxfs_aio_read(vnode_t *vp, struct aio_req *aio, cred_t *cred_p); #ifdef __cplusplus } #endif #endif /* _PXFS_KI_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2015, 2016 Joyent, Inc. All rights reserved. * Copyright (c) 2014, 2017 by Delphix. All rights reserved. */ #ifndef _SYS_SDEV_IMPL_H #define _SYS_SDEV_IMPL_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include /* * sdev_nodes are the file-system specific part of the * vnodes for the device filesystem. * * The device filesystem exports two node types: * * VDIR nodes to represent directories * VCHR & VBLK nodes to represent devices */ /* * /dev mount arguments */ struct sdev_mountargs { uint64_t sdev_attrdir; }; /* * Nvpair names of profile information (list of device files available) of * non-global /dev mounts. These strings must be unique among them. */ #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" /* * supported devfsadm_cmd */ #define DEVFSADMD_RUN_ALL 1 /* * devfsadm_error codes */ #define DEVFSADM_RUN_INVALID 1 #define DEVFSADM_RUN_EPERM 2 #define DEVFSADM_RUN_NOTSUP 3 /* * devfsadm/devname door data structures */ typedef struct sdev_door_arg { uint8_t devfsadm_cmd; /* what to do for devfsadm[d] */ } 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; }; /* * devname_handle_t */ struct devname_handle { struct sdev_node *dh_data; /* the sdev_node */ void *dh_args; }; typedef struct devname_handle devname_handle_t; /* * Per-instance node data for the global zone instance * Only one mount of /dev in the global zone */ typedef struct sdev_global_data { struct devname_handle sdev_ghandle; ulong_t sdev_dir_ggen; /* name space generation # */ } sdev_global_data_t; /* * Per-instance node data - profile data per non-global zone mount instance */ typedef struct sdev_local_data { ulong_t sdev_dir_lgen; /* cached generation # of /dev dir */ ulong_t sdev_devtree_lgen; /* cached generation # of devtree */ struct sdev_node *sdev_lorigin; /* corresponding global sdev_node */ struct sdev_dprof sdev_lprof; /* profile for multi-inst */ } sdev_local_data_t; /* sdev_flags */ typedef enum sdev_flags { SDEV_BUILD = 0x0001, /* directory cache out-of-date */ SDEV_GLOBAL = 0x0002, /* global /dev nodes */ SDEV_PERSIST = 0x0004, /* backing store persisted node */ SDEV_NO_NCACHE = 0x0008, /* do not include in neg. cache */ SDEV_DYNAMIC = 0x0010, /* special-purpose vnode ops */ /* (ex: pts) */ SDEV_VTOR = 0x0020, /* validate sdev_nodes during search */ SDEV_ATTR_INVALID = 0x0040, /* invalid node attributes, */ /* need update */ SDEV_SUBDIR = 0x0080, /* match all subdirs under here */ SDEV_ZONED = 0x0100 /* zoned subdir */ } sdev_flags_t; /* * /dev filesystem sdev_node defines */ typedef struct sdev_node { char *sdev_name; /* node name */ size_t sdev_namelen; /* strlen(sdev_name) */ char *sdev_path; /* absolute path */ char *sdev_symlink; /* source for a symlink */ struct vnode *sdev_vnode; /* vnode */ krwlock_t sdev_contents; /* rw lock for this data structure */ struct sdev_node *sdev_dotdot; /* parent */ avl_tree_t sdev_entries; /* VDIR: contents as avl tree */ avl_node_t sdev_avllink; /* avl node linkage */ struct vnode *sdev_attrvp; /* backing store vnode if persisted */ struct vattr *sdev_attr; /* memory copy of the vattr */ ino64_t sdev_ino; /* inode */ uint_t sdev_nlink; /* link count */ int sdev_state; /* state of this node */ sdev_flags_t sdev_flags; /* flags bit */ kmutex_t sdev_lookup_lock; /* node creation synch lock */ kcondvar_t sdev_lookup_cv; /* node creation sync cv */ int sdev_lookup_flags; /* node creation flags */ /* per-instance data, either global or non-global zone */ union { struct sdev_global_data sdev_globaldata; struct sdev_local_data sdev_localdata; } sdev_instance_data; list_node_t sdev_plist; /* link on plugin list */ 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 /* * Directory contents traversal */ #define SDEV_FIRST_ENTRY(ddv) avl_first(&(ddv)->sdev_entries) #define SDEV_NEXT_ENTRY(ddv, dv) AVL_NEXT(&(ddv)->sdev_entries, (dv)) /* * See the big theory statement in sdev_vnops.c for an explanation of these * states. */ typedef enum { SDEV_ZOMBIE = -1, SDEV_INIT = 0, SDEV_READY } sdev_node_state_t; /* sdev_lookup_flags */ #define SDEV_LOOKUP 0x0001 /* node creation in progress */ #define SDEV_READDIR 0x0002 /* VDIR readdir in progress */ #define SDEV_LGWAITING 0x0004 /* waiting for devfsadm completion */ /* convenient macros */ #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) /* * some defaults */ #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; /* * devname_lookup_func() */ extern int devname_lookup_func(struct sdev_node *, char *, struct vnode **, struct cred *, int (*)(struct sdev_node *, char *, void **, struct cred *, void *, char *), int); /* * flags used by devname_lookup_func callbacks */ #define SDEV_VATTR 0x4 /* callback returning node vattr */ #define SDEV_VLINK 0x8 /* callback returning /dev link */ /* * devname_readdir_func() */ extern int devname_readdir_func(vnode_t *, uio_t *, cred_t *, int *, int); /* * flags for devname_readdir_func */ #define SDEV_BROWSE 0x1 /* fetch all entries from backing store */ /* * devname_setattr_func() */ extern int devname_setattr_func(struct vnode *, struct vattr *, int, struct cred *, int (*)(struct sdev_node *, struct vattr *, int), int); /* * devname_inactive_func() */ extern void devname_inactive_func(struct vnode *, struct cred *, void (*)(struct vnode *)); /* * /dev file system instance defines */ /* * /dev version of vfs_data */ 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)) /* * sdev_fid overlays the fid structure (for VFS_VGET) */ struct sdev_fid { uint16_t sdevfid_len; ino32_t sdevfid_ino; int32_t sdevfid_gen; }; /* * devfsadm and devname communication defines */ typedef enum { DEVNAME_DEVFSADM_STOPPED = 0, /* devfsadm has never run */ DEVNAME_DEVFSADM_RUNNING, /* devfsadm is running */ DEVNAME_DEVFSADM_RUN /* devfsadm ran once */ } devname_devfsadm_state_t; extern volatile uint_t devfsadm_state; /* atomic mask for devfsadm status */ #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); /* * boot states - warning, the ordering here is significant * * the difference between "system available" and "boot complete" * is a debounce timeout to catch some daemon issuing a readdir * triggering a nuisance implict reconfig on each boot. */ #define SDEV_BOOT_STATE_INITIAL 0 #define SDEV_BOOT_STATE_RECONFIG 1 /* reconfig */ #define SDEV_BOOT_STATE_SYSAVAIL 2 /* system available */ #define SDEV_BOOT_STATE_COMPLETE 3 /* boot complete */ /* * Negative cache list and list element * The mutex protects the flags against multiple accesses and * must only be acquired when already holding the r/w lock. */ typedef struct sdev_nc_list { list_t ncl_list; /* the list itself */ kmutex_t ncl_mutex; /* protects ncl_flags */ krwlock_t ncl_lock; /* protects ncl_list */ int ncl_flags; int ncl_nentries; } sdev_nc_list_t; typedef struct sdev_nc_node { char *ncn_name; /* name of the node */ int ncn_flags; /* state information */ int ncn_expirecnt; /* remove once expired */ list_node_t ncn_link; /* link to next in list */ } sdev_nc_node_t; /* ncl_flags */ #define NCL_LIST_DIRTY 0x01 /* needs to be flushed */ #define NCL_LIST_WRITING 0x02 /* write in progress */ #define NCL_LIST_WENABLE 0x04 /* write-enabled post boot */ /* ncn_flags */ #define NCN_ACTIVE 0x01 /* a lookup has occurred */ #define NCN_SRC_STORE 0x02 /* src: persistent store */ #define NCN_SRC_CURRENT 0x04 /* src: current boot */ /* sdev_lookup_failed flags */ #define SLF_NO_NCACHE 0x01 /* node should not be added to ncache */ #define SLF_REBUILT 0x02 /* reconfig performed during lookup attempt */ /* * The nvlist name and nvpair identifiers in the * /etc/devices/devname_cache nvlist format */ #define DP_DEVNAME_ID "devname" #define DP_DEVNAME_NCACHE_ID "ncache" #define DP_DEVNAME_NC_EXPIRECNT_ID "expire-counts" /* devname-cache list element */ typedef struct nvp_devname { char **nvp_paths; int *nvp_expirecnts; int nvp_npaths; list_node_t nvp_link; } nvp_devname_t; /* * name service globals and prototypes */ /* * vnodeops and vfsops helpers */ 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); /* * devinfo helpers */ 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 *); /* * ncache handlers */ 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); /* * plugin and legacy vtab stuff */ /* directory dependent vop table */ typedef struct sdev_vop_table { char *vt_name; /* subdirectory name */ const fs_operation_def_t *vt_service; /* vnodeops table */ struct vnodeops **vt_global_vops; /* global container for vop */ int (*vt_vtor)(struct sdev_node *); /* validate 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); /* * globals */ 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; /* mount info for global /dev instance */ 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; /* * misc. defines */ #ifdef DEBUG extern int sdev_debug; #define SDEV_DEBUG 0x01 /* error messages to console/log */ #define SDEV_DEBUG_VOPS 0x02 /* vnode ops errors */ #define SDEV_DEBUG_DLF 0x04 /* trace devname_lookup_func */ #define SDEV_DEBUG_DRF 0x08 /* trace devname_readdir_func */ #define SDEV_DEBUG_NCACHE 0x10 /* negative cache tracing */ #define SDEV_DEBUG_DEVFSADMD 0x20 /* comm. of devnamefs & devfsadm */ #define SDEV_DEBUG_PTS 0x40 /* /dev/pts tracing */ #define SDEV_DEBUG_RECONFIG 0x80 /* events triggering reconfig */ #define SDEV_DEBUG_SDEV_NODE 0x100 /* trace sdev_node activities */ #define SDEV_DEBUG_PROFILE 0x200 /* trace sdev_profile */ #define SDEV_DEBUG_MODCTL 0x400 /* trace modctl activity */ #define SDEV_DEBUG_FLK 0x800 /* trace failed lookups */ #define SDEV_DEBUG_NET 0x1000 /* /dev/net tracing */ #define SDEV_DEBUG_ZVOL 0x2000 /* /dev/zvol/tracing */ #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 /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_SDEV_IMPL_H */ /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright (c) 2018, Joyent, Inc. */ #ifndef _SYS_SDEV_PLUGIN_H #define _SYS_SDEV_PLUGIN_H /* * Kernel sdev plugin interface */ #ifdef _KERNEL #include #include #include #endif /* _KERNEL */ #ifdef __cplusplus extern "C" { #endif #ifdef _KERNEL typedef uintptr_t sdev_plugin_hdl_t; typedef uintptr_t sdev_ctx_t; /* * Valid return values for sdev_plugin_validate_t. */ typedef enum sdev_plugin_validate { SDEV_VTOR_INVALID = -1, SDEV_VTOR_SKIP = 0, SDEV_VTOR_VALID = 1, SDEV_VTOR_STALE = 2 } sdev_plugin_validate_t; /* * Valid flags */ typedef enum sdev_plugin_flags { SDEV_PLUGIN_NO_NCACHE = 0x1, SDEV_PLUGIN_SUBDIR = 0x2 } sdev_plugin_flags_t; #define SDEV_PLUGIN_FLAGS_MASK 0x3 /* * Functions a module must implement */ typedef sdev_plugin_validate_t (*sp_valid_f)(sdev_ctx_t); typedef int (*sp_filldir_f)(sdev_ctx_t); typedef void (*sp_inactive_f)(sdev_ctx_t); #define SDEV_PLUGIN_VERSION 1 typedef struct sdev_plugin_ops { int spo_version; sdev_plugin_flags_t spo_flags; sp_valid_f spo_validate; sp_filldir_f spo_filldir; sp_inactive_f spo_inactive; } sdev_plugin_ops_t; extern sdev_plugin_hdl_t sdev_plugin_register(const char *, sdev_plugin_ops_t *, int *); extern int sdev_plugin_unregister(sdev_plugin_hdl_t); typedef enum sdev_ctx_flags { SDEV_CTX_GLOBAL = 0x2 /* node belongs to the GZ */ } sdev_ctx_flags_t; /* * Context helper functions */ extern sdev_ctx_flags_t sdev_ctx_flags(sdev_ctx_t); extern const char *sdev_ctx_name(sdev_ctx_t); extern const char *sdev_ctx_path(sdev_ctx_t); extern int sdev_ctx_minor(sdev_ctx_t, minor_t *); extern enum vtype sdev_ctx_vtype(sdev_ctx_t); /* * Callbacks to manipulate nodes */ extern int sdev_plugin_mkdir(sdev_ctx_t, char *); extern int sdev_plugin_mknod(sdev_ctx_t, char *, mode_t, dev_t); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_SDEV_PLUGIN_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SMBFS_IOCTL_H #define _SMBFS_IOCTL_H /* * Project private IOCTL interface provided by SMBFS. */ #include #ifdef __cplusplus extern "C" { #endif typedef struct ioc_sdbuf { uint64_t addr; /* buffer address (user space) */ uint32_t alloc; /* allocated length */ uint32_t used; /* content length */ uint32_t selector; /* i.e. DACL_SECURITY_INFORMATION */ } ioc_sdbuf_t; /* * SMBFS ioctl codes * * We only need a couple of these, so (re)using some * FS-specific ioctl codes from sys/filio.h * Data for both is ioc_sdbuf_t */ #define SMBFSIO_GETSD _IO('f', 81) #define SMBFSIO_SETSD _IO('f', 82) #ifdef __cplusplus } #endif #endif /* _SMBFS_IOCTL_H */ /* * Copyright (c) 2000-2001, Boris Popov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Boris Popov. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: smbfs.h,v 1.30.100.1 2005/05/27 02:35:28 lindak Exp $ */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SMBFS_MOUNT_H #define _SMBFS_MOUNT_H /* * This file defines the interface used by mount_smbfs. * Some of this came from the Darwin file: * smb-217.2/kernel/fs/smbfs/smbfs.h */ #define SMBFS_VERMAJ 1 #define SMBFS_VERMIN 3300 #define SMBFS_VERSION (SMBFS_VERMAJ*100000 + SMBFS_VERMIN) #define SMBFS_VER_STR "1.33" #define SMBFS_VFSNAME "smbfs" /* Additions not in mntent.h */ #define MNTOPT_ACL "acl" /* enable smbfs ACLs */ #define MNTOPT_NOACL "noacl" /* disable smbfs ACLs */ /* Values for smbfs_args.flags */ #define SMBFS_MF_SOFT 0x0001 #define SMBFS_MF_INTR 0x0002 #define SMBFS_MF_NOAC 0x0004 #define SMBFS_MF_ACREGMIN 0x0100 /* set min secs for file attr cache */ #define SMBFS_MF_ACREGMAX 0x0200 /* set max secs for file attr cache */ #define SMBFS_MF_ACDIRMIN 0x0400 /* set min secs for dir attr cache */ #define SMBFS_MF_ACDIRMAX 0x0800 /* set max secs for dir attr cache */ /* Layout of the mount control block for an smb file system. */ struct smbfs_args { int version; /* smbfs mount version */ int devfd; /* file descriptor */ uint_t flags; /* SMBFS_MF_ flags */ uid_t uid; /* octal user id */ gid_t gid; /* octal group id */ mode_t file_mode; /* octal srwx for files */ mode_t dir_mode; /* octal srwx for dirs */ int acregmin; /* attr cache file min secs */ int acregmax; /* attr cache file max secs */ int acdirmin; /* attr cache dir min secs */ int acdirmax; /* attr cache dir max secs */ }; #ifdef _SYSCALL32 /* Layout of the mount control block for an smb file system. */ struct smbfs_args32 { int32_t version; /* smbfs mount version */ int32_t devfd; /* file descriptor */ uint32_t flags; /* SMBFS_MF_ flags */ uid32_t uid; /* octal user id */ gid32_t gid; /* octal group id */ mode32_t file_mode; /* octal srwx for files */ mode32_t dir_mode; /* octal srwx for dirs */ int32_t acregmin; /* attr cache file min secs */ int32_t acregmax; /* attr cache file max secs */ int32_t acdirmin; /* attr cache dir min secs */ int32_t acdirmax; /* attr cache dir max secs */ }; #endif /* _SYSCALL32 */ #endif /* _SMBFS_MOUNT_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_SNODE_H #define _SYS_FS_SNODE_H #include #include #include #include /* * The snode represents a special file in any filesystem. There is * one snode for each active special file. Filesystems that support * special files use specvp(vp, dev, type, cr) to convert a normal * vnode to a special vnode in the ops lookup() and create(). * * To handle having multiple snodes that represent the same * underlying device vnode without cache aliasing problems, * the s_commonvp is used to point to the "common" vnode used for * caching data. If an snode is created internally by the kernel, * then the s_realvp field is NULL and s_commonvp points to s_vnode. * The other snodes which are created as a result of a lookup of a * device in a file system have s_realvp pointing to the vp which * represents the device in the file system while the s_commonvp points * into the "common" vnode for the device in another snode. */ /* * Include SUNDDI type definitions so that the s_dip tag doesn't urk. */ #include #ifdef __cplusplus extern "C" { #endif struct snode { /* These fields are protected by stable_lock */ struct snode *s_next; /* must be first */ struct vnode *s_vnode; /* vnode associated with this snode */ /* * These fields are initialized once. */ struct vnode *s_realvp; /* vnode for the fs entry (if any) */ struct vnode *s_commonvp; /* common device vnode */ dev_t s_dev; /* device the snode represents */ dev_info_t *s_dip; /* dev_info (common snode only) */ /* * Doesn't always need to be updated atomically because it is a hint. * No lock required. */ u_offset_t s_nextr; /* next byte read offset (read-ahead) */ /* These fields are protected by spec_syncbusy */ struct snode *s_list; /* used for syncing */ /* These fields are protected by s_lock */ struct devplcy *s_plcy; /* device node open policy (cs only) */ u_offset_t s_size; /* block device size in bytes */ uint_t s_flag; /* flags, see below */ dev_t s_fsid; /* file system identifier */ time_t s_atime; /* time of last access */ time_t s_mtime; /* time of last modification */ time_t s_ctime; /* time of last attributes change */ int s_count; /* count of opened references */ long s_mapcnt; /* count of mappings of pages */ /* The locks themselves */ kmutex_t s_lock; /* protects snode fields */ kcondvar_t s_cv; /* synchronize open/closes */ }; /* flags */ #define SUPD 0x01 /* update device access time */ #define SACC 0x02 /* update device modification time */ #define SCHG 0x04 /* update device change time */ #define SPRIV 0x08 /* file open for private access */ #define SLOFFSET 0x10 /* device takes 64-bit uio offsets */ #define SLOCKED 0x20 /* use to serialize open/closes */ #define SWANT 0x40 /* some process waiting on lock */ #define SANYOFFSET 0x80 /* device takes any uio offset */ #define SCLONE 0x100 /* represents a cloned device */ #define SNEEDCLOSE 0x200 /* needs driver close call */ #define SDIPSET 0x400 /* the vnode has an association with */ /* the driver, even though it may */ /* not currently have an association */ /* with a specific hardware instance */ /* if s_dip is NULL */ #define SSIZEVALID 0x800 /* s_size field is valid */ #define SMUXED 0x1000 /* this snode is a stream that has */ /* been multiplexed */ #define SSELFCLONE 0x2000 /* represents a self cloning device */ #define SNOFLUSH 0x4000 /* do not flush device on fsync */ #define SCLOSING 0x8000 /* in last close(9E) */ #define SFENCED 0x10000 /* snode fenced off for I/O retire */ #ifdef _KERNEL /* * Convert between vnode and snode */ #define VTOS(vp) ((struct snode *)((vp)->v_data)) #define VTOCS(vp) (VTOS(VTOS(vp)->s_commonvp)) #define STOV(sp) ((sp)->s_vnode) extern int spec_debug; #define SPEC_FENCE_DEBUG 0x0001 /* emit fence related debug messages */ #define FENDBG(args) if (spec_debug & SPEC_FENCE_DEBUG) cmn_err args /* * Forward declarations */ struct vfssw; struct cred; extern struct vfs spec_vfs; extern struct vfsops spec_vfsops; extern struct kmem_cache *snode_cache; /* * specfs functions */ offset_t spec_maxoffset(struct vnode *); struct vnodeops *spec_getvnodeops(void); struct vnode *specvp(struct vnode *, dev_t, vtype_t, struct cred *); struct vnode *makespecvp(dev_t, vtype_t); struct vnode *other_specvp(struct vnode *); struct vnode *common_specvp(struct vnode *); struct vnode *specfind(dev_t, vtype_t); struct vnode *commonvp(dev_t, vtype_t); struct vnode *makectty(vnode_t *); void sdelete(struct snode *); void smark(struct snode *, int); int specinit(int, char *); int device_close(struct vnode *, int, struct cred *); int spec_putpage(struct vnode *, offset_t, size_t, int, struct cred *, caller_context_t *); int spec_segmap(dev_t, off_t, struct as *, caddr_t *, off_t, uint_t, uint_t, uint_t, cred_t *); struct vnode *specvp_devfs(struct vnode *, dev_t, vtype_t, struct cred *, dev_info_t *); void spec_assoc_vp_with_devi(struct vnode *, dev_info_t *); dev_info_t *spec_hold_devi_by_vp(struct vnode *); int spec_sync(struct vfs *, short, struct cred *); void spec_snode_walk(int (*callback)(struct snode *, void *), void *); int spec_devi_open_count(struct snode *, dev_info_t **); int spec_is_clone(struct vnode *); int spec_is_selfclone(struct vnode *); int spec_fence_snode(dev_info_t *dip, struct vnode *vp); int spec_unfence_snode(dev_info_t *dip); void spec_size_invalidate(dev_t, vtype_t); /* * UNKNOWN_SIZE: If driver does not support the [Ss]ize or [Nn]blocks property * then the size is assumed to be "infinite". Note that this "infinite" value * may need to be converted to a smaller "infinite" value to avoid EOVERFLOW at * field width conversion locations like the stat(2) and NFS code running * against a special file. Special file code outside specfs may check the * type of the vnode (VCHR|VBLK) and use MAXOFFSET_T directly to detect * UNKNOWN_SIZE. */ #define UNKNOWN_SIZE MAXOFFSET_T /* * SPEC_MAXOFFSET_T: Solaris does not fully support 64-bit offsets for D_64BIT * (SLOFFSET) block drivers on a 32-bit kernels: daddr_t is still a signed * 32-bit quantity - which limits the byte offset to 1TB. This issue goes * beyond a driver needing to convert from daddr_t to diskaddr_t if it sets * D_64BIT. Many of the DDI interfaces which take daddr_t arguments have no * 64-bit counterpart (bioclone, blkflush, bread, bread_common, breada, getblk, * getblk_common). SPEC_MAXOFFSET_T is used by 32-bit kernel code to enforce * this restriction. */ #ifdef _ILP32 #ifdef _LONGLONG_TYPE #define SPEC_MAXOFFSET_T ((1LL << ((NBBY * sizeof (daddr32_t)) + \ DEV_BSHIFT - 1)) - 1) #else /* !defined(_LONGLONG_TYPE) */ #define SPEC_MAXOFFSET_T MAXOFF_T #endif /* _LONGLONG_TYPE */ #endif /* _ILP32 */ /* * Snode lookup stuff. * These routines maintain a table of snodes hashed by dev so * that the snode for an dev can be found if it already exists. * NOTE: STABLESIZE must be a power of 2 for STABLEHASH to work! */ #define STABLESIZE 256 #define STABLEHASH(dev) ((getmajor(dev) + getminor(dev)) & (STABLESIZE - 1)) extern struct snode *stable[]; extern kmutex_t stable_lock; extern kmutex_t spec_syncbusy; /* * Variables used by during asynchronous VOP_PUTPAGE operations. */ extern struct async_reqs *spec_async_reqs; /* async request list */ extern kmutex_t spec_async_lock; /* lock to protect async list */ #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_SNODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #ifndef _SYS_FS_SWAPNODE_H #define _SYS_FS_SWAPNODE_H #ifdef __cplusplus extern "C" { #endif /* * pointer to swapfs global data structures */ extern pgcnt_t swapfs_minfree; /* amount of availrmem (in pages) */ /* that is unavailable to swapfs */ extern pgcnt_t swapfs_desfree; extern pgcnt_t swapfs_reserve; /* amount of availrmem (in pages) */ /* that is unavailable for swap */ /* reservation to non-priv processes */ extern struct vnodeops *swap_vnodeops; extern struct vnode *swapfs_getvp(ulong_t); #ifdef SWAPFS_DEBUG extern int swapfs_debug; #define SWAPFS_PRINT(X, S, Y1, Y2, Y3, Y4, Y5) \ if (swapfs_debug & (X)) \ printf(S, Y1, Y2, Y3, Y4, Y5); #define SWAP_SUBR 0x01 #define SWAP_VOPS 0x02 #define SWAP_VFSOPS 0x04 #define SWAP_PGC 0x08 #define SWAP_PUTP 0x10 #else /* SWAPFS_DEBUG */ #define SWAPFS_PRINT(X, S, Y1, Y2, Y3, Y4, Y5) #endif /* SWAPFS_DEBUG */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_SWAPNODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. * All rights reserved. Use is subject to license terms. */ /* * Copyright 2015 Joyent, Inc. */ #ifndef _SYS_FS_TMP_H #define _SYS_FS_TMP_H #ifdef __cplusplus extern "C" { #endif /* * tmpfs per-mount data structure. * * All fields are protected by tm_contents. * File renames on a particular file system are protected tm_renamelck. */ struct tmount { struct vfs *tm_vfsp; /* filesystem's vfs struct */ struct tmpnode *tm_rootnode; /* root tmpnode */ char *tm_mntpath; /* name of tmpfs mount point */ ulong_t tm_anonmax; /* file system max anon reservation */ pgcnt_t tm_anonmem; /* pages of reserved anon memory */ dev_t tm_dev; /* unique dev # of mounted `device' */ uint_t tm_gen; /* pseudo generation number for files */ kmutex_t tm_contents; /* lock for tmount structure */ kmutex_t tm_renamelck; /* rename lock for this mount */ }; /* * File system independent to tmpfs conversion macros */ #define VFSTOTM(vfsp) ((struct tmount *)(vfsp)->vfs_data) #define VTOTM(vp) ((struct tmount *)(vp)->v_vfsp->vfs_data) #define VTOTN(vp) ((struct tmpnode *)(vp)->v_data) #define TNTOV(tp) ((tp)->tn_vnode) #define tmpnode_hold(tp) VN_HOLD(TNTOV(tp)) #define tmpnode_rele(tp) VN_RELE(TNTOV(tp)) /* * enums */ enum de_op { DE_CREATE, DE_MKDIR, DE_LINK, DE_RENAME }; /* direnter ops */ enum dr_op { DR_REMOVE, DR_RMDIR, DR_RENAME }; /* dirremove ops */ /* * tmpfs_minfree is the amount (in pages) of anonymous memory that tmpfs * leaves free for the rest of the system. E.g. in a system with 32MB of * configured swap space, if 16MB were reserved (leaving 16MB free), * tmpfs could allocate up to 16MB - tmpfs_minfree. The default value * for tmpfs_minfree is btopr(TMPMINFREE) but it can cautiously patched * to a different number of pages. * NB: If tmpfs allocates too much swap space, other processes will be * unable to execute. */ #define TMPMINFREE 2 * 1024 * 1024 /* 2 Megabytes */ extern size_t tmpfs_minfree; /* Anonymous memory in pages */ /* * tmpfs can allocate only a certain percentage of kernel memory, * which is used for tmpnodes, directories, file names, etc. * This is statically set as TMPMAXFRACKMEM of physical memory. * The actual number of allocatable bytes can be patched in tmpfs_maxkmem. */ #define TMPMAXFRACKMEM 25 /* 1/25 of physical memory */ extern size_t tmp_kmemspace; extern size_t tmpfs_maxkmem; /* Allocatable kernel memory in bytes */ extern void tmpnode_init(struct tmount *, struct tmpnode *, struct vattr *, struct cred *); extern int tmpnode_trunc(struct tmount *, struct tmpnode *, ulong_t); extern void tmpnode_growmap(struct tmpnode *, ulong_t); extern int tdirlookup(struct tmpnode *, char *, struct tmpnode **, struct cred *); extern int tdirdelete(struct tmpnode *, struct tmpnode *, char *, enum dr_op, struct cred *); extern void tdirinit(struct tmpnode *, struct tmpnode *); extern void tdirtrunc(struct tmpnode *); extern void *tmp_memalloc(size_t, int); extern void tmp_memfree(void *, size_t); extern int tmp_resv(struct tmount *, struct tmpnode *, size_t, int); extern int tmp_taccess(void *, int, struct cred *); extern int tmp_sticky_remove_access(struct tmpnode *, struct tmpnode *, struct cred *); extern int tmp_convnum(char *, pgcnt_t *); extern int tmp_convmode(char *, mode_t *); extern int tdirenter(struct tmount *, struct tmpnode *, char *, enum de_op, struct tmpnode *, struct tmpnode *, struct vattr *, struct tmpnode **, struct cred *, caller_context_t *); #define TMP_MUSTHAVE 0x01 #ifdef __cplusplus } #endif #endif /* _SYS_FS_TMP_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_TMPNODE_H #define _SYS_FS_TMPNODE_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * tmpnode is the file system dependent node for tmpfs. * * tn_rwlock protects access of the directory list at tn_dir * as well as syncronizing read and writes to the tmpnode * * tn_contents protects growing, shrinking, reading and writing * the file along with tn_rwlock (see below). * * tn_tlock protects updates to tn_mode and tn_nlink * * tm_contents in the tmount filesystem data structure protects * tn_forw and tn_back which are used to maintain a linked * list of all tmpfs files associated with that file system * * The anon array represents the secondary store for tmpfs. * To grow or shrink the file or fill in holes requires * manipulation of the anon array. These operations are protected * by a combination of tn_rwlock and tn_contents. Growing or shrinking * the array requires the write lock on tn_rwlock and tn_contents. * Filling in a slot in the array requires the write lock on tn_contents. * Reading the array requires the read lock on tn_contents. * * The ordering of the locking is: * tn_rwlock -> tn_contents -> page locks on pages in file * * tn_tlock doesn't require any tmpnode locks */ struct tmpnode { struct tmpnode *tn_back; /* linked list of tmpnodes */ struct tmpnode *tn_forw; /* linked list of tmpnodes */ union { struct { struct tdirent *un_dirlist; /* dirent list */ uint_t un_dirents; /* number of dirents */ } un_dirstruct; char *un_symlink; /* pointer to symlink */ struct { struct anon_hdr *un_anon; /* anon backing for file */ pgcnt_t un_size; /* size repres. by array */ } un_anonstruct; } un_tmpnode; struct vnode *tn_vnode; /* vnode for this tmpnode */ int tn_gen; /* pseudo gen number for tfid */ struct vattr tn_attr; /* attributes */ krwlock_t tn_contents; /* vm side -serialize mods */ krwlock_t tn_rwlock; /* rw,trunc size - serialize */ /* mods and directory updates */ kmutex_t tn_tlock; /* time, flag, and nlink lock */ struct tmpnode *tn_xattrdp; /* ext. attribute directory */ uint_t tn_flags; /* tmpnode specific flags */ }; #define tn_dir un_tmpnode.un_dirstruct.un_dirlist #define tn_dirents un_tmpnode.un_dirstruct.un_dirents #define tn_symlink un_tmpnode.un_symlink #define tn_anon un_tmpnode.un_anonstruct.un_anon #define tn_asize un_tmpnode.un_anonstruct.un_size /* * tmnode flag values. */ #define ISXATTR 0x1 /* * Attributes */ #define tn_mask tn_attr.va_mask #define tn_type tn_attr.va_type #define tn_mode tn_attr.va_mode #define tn_uid tn_attr.va_uid #define tn_gid tn_attr.va_gid #define tn_fsid tn_attr.va_fsid #define tn_nodeid tn_attr.va_nodeid #define tn_nlink tn_attr.va_nlink #define tn_size tn_attr.va_size #define tn_atime tn_attr.va_atime #define tn_mtime tn_attr.va_mtime #define tn_ctime tn_attr.va_ctime #define tn_rdev tn_attr.va_rdev #define tn_blksize tn_attr.va_blksize #define tn_nblocks tn_attr.va_nblocks #define tn_seq tn_attr.va_seq /* * tmpfs directories are made up of a linked list of tdirent structures * hanging off directory tmpnodes. File names are not fixed length, * but are null terminated. */ struct tdirent { struct tmpnode *td_tmpnode; /* tnode for this file */ struct tdirent *td_next; /* next directory entry */ struct tdirent *td_prev; /* prev directory entry */ uint_t td_offset; /* "offset" of dir entry */ uint_t td_hash; /* a hash of td_name */ struct tdirent *td_link; /* linked via the hash table */ struct tmpnode *td_parent; /* parent, dir we are in */ char *td_name; /* must be null terminated */ /* max length is MAXNAMELEN */ }; /* * tfid overlays the fid structure (for VFS_VGET) */ struct tfid { uint16_t tfid_len; ino32_t tfid_ino; int32_t tfid_gen; }; #define ESAME (-1) /* trying to rename linked files (special) */ extern struct vnodeops *tmp_vnodeops; extern const struct fs_operation_def tmp_vnodeops_template[]; #ifdef __cplusplus } #endif #endif /* _SYS_FS_TMPNODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #ifndef _SYS_FS_UDF_INODE_H #define _SYS_FS_UDF_INODE_H #include #ifdef __cplusplus extern "C" { #endif #define SUN_IMPL_ID "*SUN SOLARIS UDF" #define SUN_IMPL_ID_LEN 16 #define SUN_OS_CLASS 4 #define SUN_OS_ID 2 /* * Size of each cluster * and bits to be shifted */ #define CLSTR_SIZE 8 #define CLSTR_MASK 7 /* * enums */ enum de_op { DE_CREATE, DE_MKDIR, DE_LINK, DE_RENAME }; /* direnter ops */ enum dr_op { DR_REMOVE, DR_RMDIR, DR_RENAME }; /* dirremove ops */ /* * The following macros optimize certain frequently calculated * quantities by using shifts and masks in place of divisions * modulos and multiplications. */ #define blkoff(udfvfsp, loc) /* calculates (loc % udfcfs->udf_lbsize) */ \ ((loc) & (udfvfsp)->udf_lbmask) #define lblkno(udf_vfsp, loc) \ ((int32_t)((loc) / (udf_vfsp)->udf_lbsize)) #define fsbtodb(udf, blk) \ ((blk) << udf->udf_l2d_shift) struct udf_fid { uint16_t udfid_len; /* Length of data */ uint16_t udfid_prn; /* the partition number of icb */ uint32_t udfid_icb_lbn; /* file entry block no */ uint32_t udfid_uinq_lo; /* uniq id to validate the vnode */ }; #define MAXNAMLEN 255 struct ud_part { uint16_t udp_flags; /* See below */ uint16_t udp_number; /* partition Number */ uint32_t udp_seqno; /* to find the prevailaing desc */ uint32_t udp_access; /* access type */ uint32_t udp_start; /* Starting block no of partition */ uint32_t udp_length; /* Lenght of the partition */ uint32_t udp_unall_loc; /* unall space tbl or bitmap loc */ uint32_t udp_unall_len; /* unall space tbl or bitmap length */ uint32_t udp_freed_loc; /* freed space tbl or bitmap loc */ uint32_t udp_freed_len; /* freed space tbl or bitmap length */ /* From part desc */ uint32_t udp_nfree; /* No of free blocks in the partition */ uint32_t udp_nblocks; /* Total no of blks in the partition */ /* From lvid */ uint32_t udp_last_alloc; /* Last allocated space in bitmap */ int32_t udp_cache_count; /* Cache is used for metadata */ daddr_t udp_cache[CLSTR_SIZE]; }; /* * udp_flags */ #define UDP_BITMAPS 0x00 #define UDP_SPACETBLS 0x01 /* * udp_access */ #define UDP_MT_RO 0x0001 /* ROM */ #define UDP_MT_WO 0x0002 /* WORM */ #define UDP_MT_RW 0x0003 /* RW */ #define UDP_MT_OW 0x0004 /* OW */ #define MAX_SPM 4 struct ud_map { uint32_t udm_flags; /* Flags */ uint16_t udm_vsn; /* Volume Sequence Number */ uint16_t udm_pn; /* Partition Number */ uint32_t udm_vat_icb; /* VAT ICB location */ uint32_t udm_nent; /* Number of vat entries */ uint32_t *udm_count; /* Number of entrues in each table */ struct buf **udm_bp; /* VAT translation tables */ uint32_t **udm_addr; int32_t udm_plen; int32_t udm_nspm; uint32_t udm_spsz; uint32_t udm_loc[MAX_SPM]; struct buf *udm_sbp[MAX_SPM]; caddr_t udm_spaddr[MAX_SPM]; }; /* * udm_flags */ #define UDM_MAP_NORM 0x00 #define UDM_MAP_VPM 0x01 #define UDM_MAP_SPM 0x02 struct udf_vfs { struct vfs *udf_vfs; /* Back link */ struct udf_vfs *udf_next; /* Chain of udf file-system's */ struct udf_vfs *udf_wnext; /* work list link */ struct buf *udf_vds; /* most of the superblock */ struct buf *udf_iseq; /* Integrity of the fs */ struct vnode *udf_root; /* Root vnode */ struct vnode *udf_devvp; /* Block device vnode */ char *udf_fsmnt; /* Path name of directory mouted on */ uint32_t udf_flags; /* Flags */ uint32_t udf_mtype; /* Media type */ int32_t udf_rdclustsz; /* read cluster size */ int32_t udf_wrclustsz; /* write cluster size */ uint64_t udf_maxfsize; /* Max file size allowed in this fs */ int32_t udf_maxfbits; /* No of bit's for max file size */ char udf_volid[32]; /* volume identifier */ /* from pvd */ uint16_t udf_tsno; /* Taken from pvd and */ /* used in making tags */ int32_t udf_lbsize; /* Block size */ /* from lvd */ int32_t udf_lbmask; /* udf_lbsize - 1 */ int32_t udf_l2b_shift; /* lbsize to bytes */ int32_t udf_l2d_shift; /* right shift's to */ /* make lbsize to DEV_BSIZE */ int32_t udf_npart; /* No. of partition's in the volume */ /* restricted to 1 till udf 1.50 */ struct ud_part *udf_parts; /* pointer to array of partitions */ /* from part desc's */ int32_t udf_nmaps; struct ud_map *udf_maps; int32_t udf_fragmented; /* File System fragmented */ int32_t udf_mark_bad; /* force fsck at next mount */ /* * sum of udp_nfree and udp_nblocks * from the array udf_parts[0] to udf_parts[udf_nparts - 1] */ uint32_t udf_freeblks; /* Total udf_lbsize Free Blocks */ uint32_t udf_totalblks; /* Total number of Blocks */ /* udf_parts[0].udp_nfree == udf_freespace */ /* till udf 1.50 (DVD-R?) */ uint64_t udf_maxuniq; /* Maximum unique ID on the fs */ uint32_t udf_nfiles; /* No of files */ uint32_t udf_ndirs; /* No of directories */ uint32_t udf_miread; /* minimum read revision */ uint32_t udf_miwrite; /* minimum write revision */ uint32_t udf_mawrite; /* maximum read revision */ /* from lvid */ time_t udf_time; /* Last time super block is written */ uint32_t udf_mod; /* file system was modified */ uint32_t udf_clean; /* state of the file system */ kmutex_t udf_lock; /* protects contents */ kmutex_t udf_rename_lck; /* lock for udf_rename */ /* * Have them cached here for fast access */ struct pri_vol_desc *udf_pvd; struct log_vol_desc *udf_lvd; struct log_vol_int_desc *udf_lvid; uint32_t udf_mvds_loc; uint32_t udf_mvds_len; uint32_t udf_rvds_loc; uint32_t udf_rvds_len; uint32_t udf_iseq_loc; uint32_t udf_iseq_len; uint16_t udf_fsd_prn; uint32_t udf_fsd_loc; uint32_t udf_fsd_len; uint16_t udf_ricb_prn; uint32_t udf_ricb_loc; uint32_t udf_ricb_len; daddr_t udf_root_blkno; }; #ifndef __lint _NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock, udf_vfs::udf_fragmented)) _NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock, udf_vfs::udf_freeblks udf_vfs::udf_totalblks)) _NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock, udf_vfs::udf_maxuniq udf_vfs::udf_nfiles udf_vfs::udf_ndirs)) _NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock, udf_vfs::udf_time udf_vfs::udf_mod udf_vfs::udf_clean)) _NOTE(READ_ONLY_DATA(udf_vfs::udf_nmaps udf_vfs::udf_maps)) _NOTE(READ_ONLY_DATA(udf_vfs::udf_mtype udf_vfs::udf_rdclustsz udf_vfs::udf_wrclustsz udf_vfs::udf_maxfsize udf_vfs::udf_maxfbits udf_vfs::udf_lbsize udf_vfs::udf_l2b_shift udf_vfs::udf_lbmask udf_vfs::udf_l2d_shift)) _NOTE(READ_ONLY_DATA(udf_vfs::udf_pvd udf_vfs::udf_lvd udf_vfs::udf_lvid)) _NOTE(READ_ONLY_DATA(udf_vfs::udf_mvds_loc udf_vfs::udf_mvds_len udf_vfs::udf_iseq_loc udf_vfs::udf_iseq_len udf_vfs::udf_fsd_prn udf_vfs::udf_fsd_loc udf_vfs::udf_fsd_len udf_vfs::udf_ricb_prn udf_vfs::udf_ricb_loc udf_vfs::udf_ricb_len udf_vfs::udf_root_blkno)) _NOTE(READ_ONLY_DATA(ud_part::udp_flags ud_part::udp_number ud_part::udp_seqno ud_part::udp_access ud_part::udp_start ud_part::udp_length ud_part::udp_unall_loc ud_part::udp_unall_len ud_part::udp_freed_loc ud_part::udp_freed_len ud_part::udp_nblocks)) _NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock, ud_part::udp_nfree ud_part::udp_last_alloc ud_part::udp_cache_count ud_part::udp_cache)) #endif /* * udf_mtype */ #define UDF_MT_RO UDP_MT_RO /* ROM */ #define UDF_MT_WO UDP_MT_OW /* WORM */ #define UDF_MT_RW UDP_MT_RW /* RW */ #define UDF_MT_OW UDP_MT_OW /* OW */ /* * udf_flags */ #define UDF_FL_RDONLY 0x0001 /* file system is read only */ #define UDF_FL_RW 0x0002 /* file system is read write */ /* * udf_clean */ #define UDF_DIRTY 0x00 #define UDF_CLEAN 0x01 #define RD_CLUSTSZ(ip) ((ip)->i_udf->udf_rdclustsz) #define WR_CLUSTSZ(ip) ((ip)->i_udf->udf_wrclustsz) /* * Size can be a 64-bit value and therefore we sign extend fs_bmask * to a 64-bit value too so that the higher 32 bits are masked * properly. Note that the type of fs_bmask has to be signed. Otherwise * compiler will set the higher 32 bits as zero and we don't want * this to happen. */ #ifdef UNDEF #define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ (((size) + (fs)->udf_lbsize - 1) & (offset_t)(fs)->udf_lbmask) #endif #define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ (((size) + (fs)->udf_lbmask) & (offset_t)(~(fs)->udf_lbmask)) #define blksize(fs) (fs->udf_lbsize) /* * Convert between inode pointers and vnode pointers */ #define VTOI(VP) ((struct ud_inode *)(VP)->v_data) #define ITOV(IP) ((IP)->i_vnode) #define i_vfs i_vnode->v_vfsp struct icb_ext { uint16_t ib_flags; /* Direct Entry will go here */ uint16_t ib_prn; /* partition reference number */ uint32_t ib_block; /* block offset into partition */ uint64_t ib_offset; /* offset into the file bytes */ int32_t ib_count; /* No of bytes in current ext */ uint32_t ib_marker1; /* 0xAAAAAAAA */ uint32_t ib_marker2; /* 0xBBBBBBBB */ }; /* ib_flags */ #define IB_UN_REC 0x1 /* The entry is not allocated */ #define IB_UN_RE_AL 0x2 /* The entry is not recorded */ /* and not unallocated */ #define IB_CON 0x3 /* Continuation entry */ #define IB_MASK 0x3 #define IB_ALLOCATED(flags) \ (((flags) & IB_MASK) != IB_UN_RE_AL) #define EXT_PER_MALLOC 8 struct ud_inode { struct ud_inode *i_forw; struct ud_inode *i_back; struct ud_inode *i_freef; struct ud_inode *i_freeb; struct vnode *i_vnode; /* vnode associated with this inode */ struct vnode *i_devvp; /* vnode for block I/O */ struct udf_vfs *i_udf; /* incore fs associated with inode */ krwlock_t i_rwlock; /* serializes write/setattr requests */ krwlock_t i_contents; /* protects (most of) inode contents */ dev_t i_dev; /* device where inode resides */ u_offset_t i_diroff; /* last loc for fast name lookup */ daddr_t i_icb_lbano; /* Loc of file icb on disk */ uint16_t i_icb_prn; /* partition reference number */ kcondvar_t i_wrcv; /* sleep/wakeup for write throttle */ uint32_t i_flag; uint32_t i_icb_block; int16_t i_astrat; /* ICB strategy */ int16_t i_desc_type; /* Allocation desc type */ int32_t i_ext_count; /* Number of extents allocated */ int32_t i_ext_used; /* Number of extents used */ struct icb_ext *i_ext; /* array of extents */ kmutex_t i_con_lock; struct icb_ext *i_con; int32_t i_con_count; int32_t i_con_used; int32_t i_con_read; uint32_t i_cur_max_ext; vtype_t i_type; /* File type */ uint16_t i_char; /* File characteristics */ uint16_t i_perm; /* File permissions */ uid_t i_uid; /* File owner's uid */ gid_t i_gid; /* File owner's gid */ uint32_t i_nlink; /* number of links to file */ uint32_t i_maxent; /* Max entries that are recorded */ u_offset_t i_size; /* File size in bytes */ uint64_t i_lbr; /* Logical blocks recorded */ uint64_t i_uniqid; /* from the file entry */ timespec32_t i_atime; timespec32_t i_mtime; timespec32_t i_ctime; size_t i_delaylen; /* delayed writes, units=bytes */ offset_t i_delayoff; /* where we started delaying */ offset_t i_nextrio; /* where to start the next clust */ uint64_t i_writes; /* remaining bytes in write q */ kmutex_t i_tlock; /* protects time fields, i_flag */ major_t i_major; minor_t i_minor; uint32_t i_marker1; /* 0xAAAAAAAA */ uint32_t i_seq; /* sequence number attribute */ offset_t i_nextr; /* next byte read offset (read-ahead) */ long i_mapcnt; /* number of mappings of pages */ int *i_map; /* block list for the file */ dev_t i_rdev; /* INCORE rdev from */ uint32_t i_marker2; /* 0xBBBBBBBB */ uint32_t i_data_off; /* Data offset into embedded file */ uint32_t i_max_emb; uint32_t i_marker3; }; #ifndef __lint _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_astrat)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_desc_type)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_ext_count)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_ext_used)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_ext)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_type)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_char)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_perm)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_uid)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_gid)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_nlink)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_size)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_lbr)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_uniqid)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_major)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_minor)) _NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_atime)) _NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_mtime)) _NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_ctime)) _NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_delayoff)) _NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_delaylen)) _NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_nextrio)) _NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_writes)) _NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_flag)) _NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, icb_ext::ib_flags icb_ext::ib_prn icb_ext::ib_block icb_ext::ib_count icb_ext::ib_offset)) #endif /* i_flag */ #define IUPD 0x0001 /* file has been modified */ #define IACC 0x0002 /* inode access time to be updated */ #define IMOD 0x0004 /* inode has been modified */ #define ICHG 0x0008 /* inode has been changed */ #define INOACC 0x0010 /* no access time update in getpage */ #define IMODTIME 0x0020 /* mod time already set */ #define IREF 0x0040 /* inode is being referenced */ #define ISYNC 0x0080 /* do all allocation synchronously */ #define IMODACC 0x0200 /* only access time changed; */ #define IATTCHG 0x0400 /* only size/blocks have changed */ #define IBDWRITE 0x0800 /* the inode has been scheduled for */ /* write operation asynchrously */ /* * i_char * Do not change used by MANDLOCK macro in vnode.h */ #define ISUID VSUID /* set user id on execution */ #define ISGID VSGID /* set group id on execution */ #define ISVTX VSVTX /* save swapped text even after use */ /* * Setuid --S--------- * Setgid -G---------- * SaveTXT T----------- */ /* i_perm */ #define IEXEC 0x0400 /* read, write, execute permissions */ #define IWRITE 0x0800 #define IREAD 0x1000 #define IATTR 0x2000 #define IDELE 0x4000 #define UP_MASK 0x1CE7 #define VA2UD_PERM(perm) \ (((perm) & 0x7) | (((perm) & 0x38) << 2) | (((perm) & 0x1C0) << 4)) #define UD2VA_PERM(perm) \ (((perm) & 0x7) | (((perm) & 0xE0) >> 2) | (((perm) & 0x1C00) >> 4)) /* * Permissions * Other -----------DARWX * Group ------DARWX----- * Owner -DARWX---------- */ #define UD_DPERM2UPERM(dperm) ((((dperm) >> 4) & 0x1C0) | \ (((dperm) >> 2) & 0x38) | \ ((dperm) & 0x7)) #define UD_UPERM2DPERM(uperm) ((((uperm) & 0x1C0) << 4) | \ (((uperm) & 0x38) << 2) | \ ((uperm) & 0x7)) /* specify how the inode info is written in ud_syncip() */ #define I_SYNC 1 /* wait for the inode written to disk */ #define I_DSYNC 2 /* wait for the inode written to disk */ /* only if IATTCHG is set */ #define I_ASYNC 0 /* don't wait for the inode written */ #define UD_HASH_SZ 512 #if ((UD_HASH_SZ & (UD_HASH_SZ - 1)) == 0) #define UD_INOHASH(dev, bno) (hash2ints((int)dev, (int)bno) & UD_HASH_SZ - 1) #else #define UD_INOHASH(dev, bno) (hash2ints((int)dev, (int)bno) % UD_HASH_SZ) #endif union ihead { union ihead *ih_head[2]; struct ud_inode *ih_chain[2]; }; #define IMARK(ip) ud_imark(ip) #define ITIMES_NOLOCK(ip) ud_itimes_nolock(ip) #define ITIMES(ip) { \ mutex_enter(&(ip)->i_tlock); \ ITIMES_NOLOCK(ip); \ mutex_exit(&(ip)->i_tlock); \ } #define ESAME (-1) /* trying to rename linked files (special) */ #define UDF_HOLE (daddr32_t)-1 /* value used when no block allocated */ extern int32_t ud_trace; #define ud_printf(xyz) \ if (ud_trace) { \ cmn_err(CE_NOTE, xyz); \ } #ifndef __lint _NOTE(SCHEME_PROTECTS_DATA("Unshared data", buf dirent64 fid flock64 statvfs64 timespec32 udf_fid uio vattr vfs vnode)) _NOTE(SCHEME_PROTECTS_DATA("Unshared data", file_entry file_id icb_tag indirect_entry log_vol_int_desc long_ad lvid_iu regid short_ad tag tstamp)) _NOTE(LOCK_ORDER(ud_inode::i_rwlock ud_inode::i_contents ud_inode::i_tlock)) #endif /* * udf_vfsops.c */ void ud_update_superblock(struct vfs *); /* * udf_vnops.c */ int32_t ud_rdwri(enum uio_rw, int32_t, struct ud_inode *, caddr_t, int32_t, offset_t, enum uio_seg, int32_t *, struct cred *cr); int32_t ud_putapage(struct vnode *, page_t *, u_offset_t *, size_t *, int32_t, struct cred *); /* * udf_inode.c */ int32_t ud_iget(struct vfs *, uint16_t, uint32_t, struct ud_inode **, struct buf *, struct cred *); void ud_iinactive(struct ud_inode *, struct cred *); void ud_iupdat(struct ud_inode *, int32_t); int32_t ud_itrunc(struct ud_inode *, u_offset_t, int32_t, struct cred *); int32_t ud_iaccess(struct ud_inode *, int32_t, struct cred *, int dolock); int32_t ud_iflush(struct vfs *); void ud_imark(struct ud_inode *); void ud_itimes_nolock(struct ud_inode *); void ud_delcache(struct ud_inode *); void ud_idrop(struct ud_inode *); void ud_init_inodes(void); /* * udf_alloc.c */ int32_t ud_alloc_space(struct vfs *, uint16_t, uint32_t, uint32_t, uint32_t *, uint32_t *, int32_t, int32_t); void ud_free_space(struct vfs *, uint16_t, uint32_t, uint32_t); int32_t ud_ialloc(struct ud_inode *, struct ud_inode **, struct vattr *, struct cred *); void ud_ifree(struct ud_inode *, vtype_t); int32_t ud_freesp(struct vnode *, struct flock64 *, int32_t, struct cred *); int32_t ud_alloc_from_cache(struct udf_vfs *, struct ud_part *, uint32_t *); int32_t ud_release_cache(struct udf_vfs *); /* * udf_subr.c */ void ud_vfs_add(struct udf_vfs *); void ud_vfs_remove(struct udf_vfs *); daddr_t ud_xlate_to_daddr(struct udf_vfs *, uint16_t, uint32_t, int32_t, uint32_t *); int32_t ud_ip_off2bno(struct ud_inode *, uint32_t, uint32_t *); void ud_dtime2utime(struct timespec32 *, struct tstamp const *); void ud_utime2dtime(struct timespec32 const *, struct tstamp *); int32_t ud_syncip(struct ud_inode *, int32_t, int32_t); void ud_update(int32_t); int32_t ud_fbwrite(struct fbuf *, struct ud_inode *); void ud_sbwrite(struct udf_vfs *); int32_t ud_sync_indir(struct ud_inode *); void ud_update_regid(struct regid *); int32_t ud_read_icb_till_off(struct ud_inode *, u_offset_t); void ud_make_tag(struct udf_vfs *, struct tag *, uint16_t, uint32_t, uint16_t); int32_t ud_make_dev_spec_ear(struct dev_spec_ear *, major_t, minor_t); int32_t ud_make_ftimes_ear(struct ftimes_ear *, int32_t, struct timespec32 *); int32_t ud_get_next_fid(struct ud_inode *, struct fbuf **, uint32_t, struct file_id **, uint8_t **, uint8_t *); int32_t ud_verify_tag_and_desc(struct tag *, uint16_t, uint32_t, int32_t, int32_t); uint16_t ud_crc(uint8_t *, int32_t); int32_t ud_compressunicode(int32_t, int32_t, uint16_t *, uint8_t *); uint32_t ud_check_te_unrec(struct udf_vfs *, caddr_t, uint32_t); int32_t ud_compress(int32_t, int32_t *, uint8_t *, uint8_t *); int32_t ud_uncompress(int32_t, int32_t *, uint8_t *, uint8_t *); struct buf *ud_bread(dev_t, daddr_t, long); int ud_sticky_remove_access(struct ud_inode *, struct ud_inode *, struct cred *); /* * udf_dir.c */ int32_t ud_dirlook(struct ud_inode *, char *, struct ud_inode **, struct cred *, int32_t); int32_t ud_direnter(struct ud_inode *, char *, enum de_op, struct ud_inode *, struct ud_inode *, struct vattr *, struct ud_inode **, struct cred *, caller_context_t *); int32_t ud_dirremove(struct ud_inode *, char *, struct ud_inode *, struct vnode *, enum dr_op, struct cred *, caller_context_t *); /* * udf_bmap.c */ int32_t ud_bmap_has_holes(struct ud_inode *); int32_t ud_bmap_write(struct ud_inode *, u_offset_t, int, int32_t, struct cred *); int32_t ud_bmap_read(struct ud_inode *, u_offset_t, daddr_t *, int32_t *); void ud_insert_new_ext(struct ud_inode *, int32_t, struct icb_ext *); int32_t ud_alloc_and_make_ext(struct ud_inode *, int32_t); int32_t ud_create_new_icb(struct ud_inode *); void ud_append_new_ext(struct ud_inode *, uint16_t, u_offset_t, uint32_t, uint16_t, uint32_t); #ifdef __cplusplus } #endif #endif /* _SYS_FS_UDF_INODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_UDF_VOLUME_H #define _SYS_FS_UDF_VOLUME_H #include #ifdef __cplusplus extern "C" { #endif #define UDF_102 0x66 #define UDF_150 0x96 #define UDF_200 0xC8 /* fid_idlen include compression id */ #define FID_LEN(fid) (((sizeof (struct file_id) + \ SWAP_16((fid)->fid_iulen) + (fid)->fid_idlen - 2) + 3) & ~3) /* * #define ID_LEN(fid) \ * (((SWAP_16((fid)->fid_iulen) + (fid)->fid_idlen - 2) + 3) & ~3) */ #define F_LEN (sizeof (struct file_id) - 2) #define UDF_DOMAIN_NAME "*OSTA UDF Compliant\0\0\0\0" #define UDF_LV_INFO "*UDF LV Info\0\0\0\0\0\0\0\0\0\0\0\0" #define UDF_FREEEASPACE "*UDF FreeEASpace\0\0\0\0\0\0\0\0" #define UDF_FREEAEASPACE "*UDF FreeAppEASpace\0\0\0\0" #define UDF_CGMS_INFO "*UDF DVD CGMS Info\0\0\0\0" #define UDF_OS2_EA "*UDF OS/2 EA\0\0\0\0\0\0\0\0\0\0\0" #define UDF_OS2_EA_LEN "*UDF OS/2 EALength\0\0\0\0\0\0" #define UDF_MAC_VOLINFO "*UDF Mac VolumeInfo\0\0\0\0" #define UDF_MAC_UNIQID "*UDF Mac UniqueIDTable\0" #define UDF_MAC_RESFRK "*UDF Mac ResourceFork\0\0" #define UDF_VIRT_PART "*UDF Virtual Partition\0" #define UDF_SPAR_PART "*UDF Sparable Partition" #define UDF_VAT "*UDF Virtual Alloc Tbl\0" #define UDF_SPAR_TBL "*UDF Sparing Table\0\0\0\0\0" #if defined(_BIG_ENDIAN) #define SWAP_16(a) (((ushort_t)((a) & 0xff) << 8) | \ ((ushort_t)((a) & 0xff00) >> 8)) #define SWAP_32(a) ((((a) & 0xff) << 24) | \ (((a) & 0xff00) << 8) | \ (((a) & 0xff0000) >> 8) | \ (((a) & 0xff000000) >> 24)) #define SWAP_64(a) ((((a) & 0xffULL) << 56) | \ (((a) & 0xff00ULL) << 40) | \ (((a) & 0xff0000ULL) << 24) | \ (((a) & 0xff000000ULL) << 8) | \ (((a) & 0xff00000000ULL) >> 8) | \ (((a) & 0xff0000000000ULL) >> 24) | \ (((a) & 0xff000000000000ULL) >> 40) | \ (((a) & 0xff00000000000000ULL) >> 56)) #define GET_32(a) ((uint32_t)(*((uint8_t *)a)) | \ (((uint32_t)(*(((uint8_t *)a) + 1))) << 8) | \ (((uint32_t)(*(((uint8_t *)a) + 2))) << 16) | \ (((uint32_t)(*(((uint8_t *)a) + 3))) << 24)) #else #define SWAP_16(a) (a) #define SWAP_32(a) (a) #define SWAP_64(a) (a) #define GET_32(a) (*((uint32_t *)a)) #endif /* _BIG_ENDIAN */ #define BCD2HEX_16(a) (((a) & 0xf) + \ (((ushort_t)((a) & 0xf0) >> 4) * 10) + \ (((ushort_t)((a) & 0xf00) >> 8) * 100) + \ (((ushort_t)((a) & 0xf000) >> 12) * 1000)) #define HEX2BCD_16(a) ((((ushort_t)a) % 10) | \ (((ushort_t)((ushort_t)(a) / 10) % 10) << 4) | \ (((ushort_t)((ushort_t)(a) / 100) % 10) << 8) | \ (((ushort_t)((ushort_t)(a) / 1000) % 10) << 12)) #define ANCHOR_VOL_DESC_LOC (256) #define ANCHOR_VOL_DESC_LEN 0x200 /* Basic data structures */ typedef char dstring_t; /* * recorded at the start of the descriptor * used to distinguish between different * descriptors */ struct tag { uint16_t tag_id; /* 00 Tag Identifier */ uint16_t tag_desc_ver; /* 02 Descriptor Version */ uint8_t tag_cksum; /* 04 Tag Checksum */ uint8_t tag_res; /* 05 Reserved */ uint16_t tag_sno; /* 06 Tag Serial Number */ uint16_t tag_crc; /* 08 Descriptor CRC */ uint16_t tag_crc_len; /* 0A Descriptor CRC length */ uint32_t tag_loc; /* 0C Tag Location */ }; typedef struct tag tag_t; /* * descriptor tag id values */ #define UD_PRI_VOL_DESC 0x0001 #define UD_ANCH_VOL_DESC 0x0002 #define UD_VOL_DESC_PTR 0x0003 #define UD_IMPL_USE_DESC 0x0004 #define UD_PART_DESC 0x0005 #define UD_LOG_VOL_DESC 0x0006 #define UD_UNALL_SPA_DESC 0x0007 #define UD_TERM_DESC 0x0008 #define UD_LOG_VOL_INT 0x0009 #define UD_FILE_SET_DESC 0x0100 #define UD_FILE_ID_DESC 0x0101 #define UD_ALLOC_EXT_DESC 0x0102 #define UD_INDIRECT_ENT 0x0103 #define UD_TERMINAL_ENT 0x0104 #define UD_FILE_ENTRY 0x0105 #define UD_EXT_ATTR_HDR 0x0106 #define UD_UNALL_SPA_ENT 0x0107 #define UD_SPA_BMAP_DESC 0x0108 #define UD_PART_INT_DESC 0x0109 #define UD_EXT_FILE_ENT 0x010A /* * Character set's allowed in descriptor fields * shall be specified */ struct charspec { uint8_t cs_type; /* 00 Character Set Type */ char cs_info[63]; /* 01 Character Set Information */ }; typedef struct charspec charspec_t; #define CS_TYPE0 0x00 #define CS_TYPE1 0x01 #define CS_TYPE2 0x02 #define CS_TYPE3 0x03 #define CS_TYPE4 0x04 #define CS_TYPE5 0x05 #define CS_TYPE6 0x06 #define CS_TYPE7 0x07 #define CS_TYPE8 0x08 /* * Entity Identification */ struct regid { uint8_t reg_flags; /* 00 Flags */ char reg_id[23]; /* 01 Identifier */ char reg_ids[8]; /* 18 Identifier Suffix */ }; typedef struct regid regid_t; #define EI_FLAG_DIRTY 0x00 #define EI_FLAG_PROT 0x01 struct lb_addr { /* uint32_t lba_number; 00 Logical Block Number */ /* uint8_t lba_prn[2]; 04 Partition Reference Number */ char lba_aaa[6]; }; typedef struct lb_addr lb_addr_t; #define lba_number(x)(((x)->lba_aaa[0]) | \ ((x)->lba_aaa[1] << 8) | \ ((x)->lba_aaa[2] << 16) | \ ((x)->lba_aaa[3] << 24)) #define lba_prn(x) ((x)->lba_aaa[4] | ((x)->lba_aaa[5] << 8)) /* * Extend Descriptor */ struct extent_ad { uint32_t ext_len; /* 00 Extent Length */ uint32_t ext_loc; /* 04 Extent Location */ }; typedef struct extent_ad extent_ad_t; /* * Short Allocation Descriptor */ struct short_ad { uint32_t sad_ext_len; /* 00 Extent Length */ uint32_t sad_ext_loc; /* 04 extent Position */ }; typedef struct short_ad short_ad_t; /* * Long Allocation Descriptor */ struct long_ad { uint32_t lad_ext_len; /* 00 Extent Length */ uint32_t lad_ext_loc; /* 04 Extent Location */ uint16_t lad_ext_prn; /* 08 Extent part ref no */ /* lb_addr_t lad_ext_loc; 04 Extent Location */ char lad_iu[6]; /* 0A Implementation Use */ }; typedef struct long_ad long_ad_t; /* * Format to record date and time * If zero date & time is not specified */ struct tstamp { uint16_t ts_tzone; /* 00 Type and Time Zone */ uint16_t ts_year; /* 02 Year */ uint8_t ts_month; /* 04 Month */ uint8_t ts_day; /* 05 Day */ uint8_t ts_hour; /* 06 Hour */ uint8_t ts_min; /* 07 Minute */ uint8_t ts_sec; /* 08 Second */ uint8_t ts_csec; /* 09 Centi-seconds */ uint8_t ts_husec; /* 0A Hundreds of Micro sec's */ uint8_t ts_usec; /* 0B Micro-seconds */ }; typedef struct tstamp tstamp_t; /* * ts_tzone */ #define TMODE 0xF000 #define TSIGN 0x0800 #define TOFFSET 0x07FF #define TINVALID (TSIGN|TOFFSET) /* * Format of the ICB tag which specifies * most of the infomation of the file */ struct icb_tag { uint32_t itag_prnde; /* 00 Prior Recorded No of Dir Entry */ uint16_t itag_strategy; /* 04 Strategy Type */ uint16_t itag_param; /* 06 Strategy parameter */ uint16_t itag_max_ent; /* 08 Maximum No of Entries */ uint8_t itag_rsvd; /* 0A Reserved */ uint8_t itag_ftype; /* 0B File Type */ /* lb_addr_t itag_lb_addr; 0C parent ICB Location */ uint32_t itag_lb_loc; /* 0C */ uint16_t itag_lb_prn; /* 10 */ uint16_t itag_flags; /* 12 Flags */ }; typedef struct icb_tag icb_tag_t; /* * Different strategy types for the file * For DVD_ROM we use onlt type4 */ #define STRAT_TYPE1 0x0001 #define STRAT_TYPE2 0x0002 #define STRAT_TYPE3 0x0003 #define STRAT_TYPE4 0x0004 #define STRAT_TYPE4096 0x1000 /* * File types */ #define FTYPE_UNALL_SPACE 0x01 #define FTYPE_PART_INTEG 0x02 #define FTYPE_INDIRECT 0x03 #define FTYPE_DIRECTORY 0x04 #define FTYPE_FILE 0x05 #define FTYPE_BLOCK_DEV 0x06 #define FTYPE_CHAR_DEV 0x07 #define FTYPE_EAR 0x08 #define FTYPE_FIFO 0x09 #define FTYPE_C_ISSOCK 0x0A #define FTYPE_T_ENTRY 0x0B #define FTYPE_SYMLINK 0x0C /* * Flags */ #define ICB_FLAG_SHORT_AD 0x0000 #define ICB_FLAG_LONG_AD 0x0001 #define ICB_FLAG_EXT_AD 0x0002 #define ICB_FLAG_ONE_AD 0x0003 #define ICB_FLAG_SORTED 0x0008 #define ICB_FLAG_NON_RELOC 0x0010 #define ICB_FLAG_ARCHIVE 0x0020 #define ICB_FLAG_SETUID 0x0040 #define ICB_FLAG_SETGID 0x0080 #define ICB_FLAG_STICKY 0x0100 #define ICB_FLAG_CONTIG 0x0200 #define ICB_FLAG_SYSTEM 0x0400 #define ICB_FLAG_TRNSFRMED 0x0800 #define ICB_FLAG_MVERS 0x1000 /* Volume recognition descriptors */ /* * Primary volume descriptor identifis the * volume and certain attributes of the volume */ struct pri_vol_desc { tag_t pvd_tag; /* 00 Descriptor Tag */ uint32_t pvd_vdsn; /* 10 Volume Descriptor Seq Num */ uint32_t pvd_pvdn; /* 14 Primary Vol Desc Num */ dstring_t pvd_vol_id[32]; /* 18 Volume Identifier */ uint16_t pvd_vsn; /* 38 Volume Sequence Num */ uint16_t pvd_mvsn; /* 3A Max Volume Sequence Num */ uint16_t pvd_il; /* 3C Interchange Level */ uint16_t pvd_mil; /* 3E Max Interchange Level */ uint32_t pvd_csl; /* 40 Character Set List */ uint32_t pvd_mcsl; /* 44 Max Character Set List */ dstring_t pvd_vsi[128]; /* 48 Volume Set Identifier */ charspec_t pvd_desc_cs; /* C8 Descriptor Character Set */ charspec_t pvd_exp_cs; /* 108 Explanatory Char Set */ extent_ad_t pvd_vol_abs; /* 148 Volume Abstract */ extent_ad_t pvd_vcn; /* 150 Volume Copyright Notice */ regid_t pvd_appl_id; /* 158 Application Identifier */ tstamp_t pvd_time; /* 178 Recording Data & Time */ regid_t pvd_ii; /* 184 Implementation Identifier */ char pvd_iu[64]; /* 1A4 Implementation Use */ uint32_t pvd_pvdsl; /* 1E4 Pred Vol Desc Seq Loc */ uint16_t pvd_flags; /* 1E8 Flags */ uint8_t pvd_res[22]; /* 1EA Reserved */ }; /* * Anchor Volume Descriptor Pointer specifies * the extent of Main & Reserve volume descriptor */ struct anch_vol_desc_ptr { tag_t avd_tag; /* 00 Descriptor Tag */ extent_ad_t avd_main_vdse; /* 10 Main Vol Desc Seq Extent */ extent_ad_t avd_res_vdse; /* 18 Reserve Vol Desc Seq Ext */ char avd_res[480]; /* 20 Reserved */ }; typedef struct anch_vol_desc_ptr anch_vol_desc_ptr_t; /* * Volume Descriptor Pointer */ struct vol_desc_ptr { tag_t vdp_tag; /* 00 Descriptor Tag */ uint32_t vdp_vdsn; /* 10 Volume Descriptor Seq Num */ extent_ad_t vdp_nvdse; /* 14 Next Vol Desc Seq Extent */ uint8_t vdp_res[484]; /* 1A Reserved */ }; typedef struct vol_desc_ptr vol_desc_ptr_t; /* * Implementation Use Volume Descriptor * This is taken from udf1.02/1.50 documents * the fields after iuvd_ii are defined only * for the udf domain */ struct iuvd_desc { tag_t iuvd_tag; /* 00 Descriptor Tag */ uint32_t iuvd_vdsn; /* 10 Volume Desc Seq Num */ regid_t iuvd_ii; /* 14 Domain Identifier */ charspec_t iuvd_cset; /* 34 LVI Charset */ dstring_t iuvd_lvi[128]; /* 74 Logical Vol Identifier */ dstring_t iuvd_ifo1[36]; /* F4 LV Info1 */ dstring_t iuvd_ifo2[36]; /* 118 LV Info2 */ dstring_t iuvd_ifo3[36]; /* 13C LV Info3 */ regid_t iuvd_iid; /* 160 Implementation ID */ uint8_t iuvd_iu[128]; /* 180 Implementation Use */ }; typedef struct iuvd_desc iuvd_desc_t; /* * Partition Descriptor * specifies the size and location of the partition */ struct part_desc { tag_t pd_tag; /* 00 Descriptor Tag */ uint32_t pd_vdsn; /* 10 Volume Desc Seq Num */ uint16_t pd_pflags; /* 14 Partition Flags */ uint16_t pd_pnum; /* 16 partition Number */ regid_t pd_pcontents; /* 18 Partition Contents */ uint8_t pd_pc_use[128]; /* 38 Partition Contents Use */ uint32_t pd_acc_type; /* B8 Access Type */ uint32_t pd_part_start; /* BC Part Start Location */ uint32_t pd_part_length; /* C0 partition Length */ regid_t pd_ii; /* C4 Implementation Identifier */ uint8_t pd_iu[128]; /* E4 Implementation Use */ uint8_t pd_res[156]; /* 164 Reserved */ }; typedef struct part_desc part_desc_t; /* * pd_acc_type */ #define PART_ACC_RO 0x01 #define PART_ACC_WO 0x02 #define PART_ACC_RW 0x03 #define PART_ACC_OW 0x04 /* * Partition Header Descriptor * Overloads pd_pc_use */ struct phdr_desc { struct short_ad phdr_ust; /* Unallocated Space Table */ struct short_ad phdr_usb; /* Unallocated Space Bitmap */ struct short_ad phdr_it; /* Partition Integrity Table */ struct short_ad phdr_fst; /* Freed Space Table */ struct short_ad phdr_fsb; /* Freed Space Bitmap */ }; typedef struct phdr_desc phdr_desc_t; /* * Logical Volume Descriptor */ struct log_vol_desc { tag_t lvd_tag; /* 00 Descriptor Tag */ uint32_t lvd_vdsn; /* 10 Volume Desc Seq Num */ charspec_t lvd_desc_cs; /* 14 Descriptor Char Set */ dstring_t lvd_lvid[128]; /* 54 Logical Vol Identifier */ uint32_t lvd_log_bsize; /* D4 Logical Block Size */ regid_t lvd_dom_id; /* D8 Domain Identifier */ long_ad_t lvd_lvcu; /* F8 Logical Vol Contents Use */ uint32_t lvd_mtbl_len; /* 108 Map Table Length */ uint32_t lvd_num_pmaps; /* 10C Number of Partition Maps */ regid_t lvd_ii; /* 110 Implementation Identifier */ uint8_t lvd_iu[128]; /* 130 Implementation Use */ extent_ad_t lvd_int_seq_ext; /* 1B0 Integrity Sequence Extent */ uint8_t lvd_pmaps[72]; /* 1B8 Partition Maps */ }; typedef struct log_vol_desc log_vol_desc_t; /* * Unallocated Space Descriptor * Contains information about the space * that does not belong to any of the * partition */ struct unall_spc_desc { tag_t ua_tag; /* 00 Descriptor Tag */ uint32_t ua_vdsn; /* 10 Volume Desc Seq Num */ uint32_t ua_nad; /* 14 Number of Allocation Desc */ uint8_t ua_al_dsc[488]; /* 18 Allocation Desc */ }; typedef struct unall_spc_desc unall_spc_desc_t; /* * Terminating Descriptor * this will be the last in a Volume Descriptor Sequence */ struct term_desc { tag_t td_tag; /* 00 Descriptor Tag */ uint8_t td_res[496]; /* 10 Reserved */ }; typedef struct term_desc term_desc_t; /* * Logical Volume Header Descriptor * This will be overlaid on lvid_lvcu * and will contain the maximum value of * unique id on the media */ struct log_vol_hdr_desc { uint64_t lvhd_uniqid; /* 00 Unique Id */ uint8_t lvhd_pad[24]; /* 08 reserved */ }; typedef struct log_vol_hdr_desc log_vol_hdr_desc_t; /* * Logical Volume Integrity Sequence * This will contain the integrity of the * file system */ struct log_vol_int_desc { tag_t lvid_tag; /* 00 Descriptor Tag */ tstamp_t lvid_tstamp; /* 10 Recording Date and Time */ uint32_t lvid_int_type; /* 1C Integrity Type */ extent_ad_t lvid_nie; /* 20 Next Integrity Extent */ /* uint8_t lvid_lvcu[32]; */ log_vol_hdr_desc_t lvid_lvcu; /* 28 Logical Volume Contents Use */ uint32_t lvid_npart; /* 48 Number of Partitions */ uint32_t lvid_liu; /* 4C Length of Implementation Use */ uint32_t lvid_fst[2]; /* 50 Free Space Table */ /* Size Table */ /* Implementation Use */ }; typedef struct log_vol_int_desc log_vol_int_desc_t; #define lvid_uniqid lvid_lvcu.lvhd_uniqid #define LOG_VOL_OPEN_INT 0x00 #define LOG_VOL_CLOSE_INT 0x01 /* * Logical Volume integrity Implementation Use * This is defined in udf spec */ struct lvid_iu { regid_t lvidiu_regid; /* 00 Implementation ID */ uint32_t lvidiu_nfiles; /* 20 Number of Files */ uint32_t lvidiu_ndirs; /* 24 Number of Directories */ uint16_t lvidiu_mread; /* 28 Minimum UDF read revision */ uint16_t lvidiu_mwrite; /* 2A Minimum UDF write revision */ uint16_t lvidiu_maxwr; /* 2C Maximum UDF write revision */ }; /* * File Set Descriptor * This will point to the root directory. */ struct file_set_desc { tag_t fsd_tag; /* 00 Descriptor Tag */ tstamp_t fsd_time; /* 10 Recording Date and Time */ uint16_t fsd_ilevel; /* 1C Interchange Level */ uint16_t fsd_mi_level; /* 1E Max Interchange Level */ uint32_t fsd_cs_list; /* 20 Character Set List */ uint32_t fsd_mcs_list; /* 24 Max Character Set List */ uint32_t fsd_fs_no; /* 28 File Set Number */ uint32_t fsd_fsd_no; /* 2C File Set Desc Number */ charspec_t fsd_lvidcs; /* 30 Log Vol Id Char Set */ char fsd_lvid[128]; /* 70 Log Vol Identifier */ charspec_t fsd_fscs; /* F0 File Set Character Set */ char fsd_fsi[32]; /* 130 File Set Identifier */ char fsd_cfi[32]; /* 150 Copyright File Identifier */ char fsd_afi[32]; /* 170 Abstract File identifier */ long_ad_t fsd_root_icb; /* 190 Root Directory ICB */ regid_t fsd_did; /* 1A0 Domain Identifier */ long_ad_t fsd_next; /* 1C0 Next Extent */ uint8_t fsd_res[48]; /* 1D0 Reserved */ }; typedef struct file_set_desc file_set_desc_t; /* * File Identifier Descriptor * Directory entries */ struct file_id { tag_t fid_tag; /* 00 Descriptor Tag */ uint16_t fid_ver; /* 10 File Version Number */ uint8_t fid_flags; /* 12 File characteristics */ uint8_t fid_idlen; /* 13 Length File Identifier */ long_ad_t fid_icb; /* 14 ICB */ uint16_t fid_iulen; /* 24 Length of Implmentation use */ uint8_t fid_spec[2]; /* iulen for iu name and padding */ }; typedef struct file_id file_id_t; #define FID_EXIST 0x01 #define FID_DIR 0x02 #define FID_DELETED 0x04 #define FID_PARENT 0x08 /* * Allocation Extent Descriptor */ struct alloc_ext_desc { tag_t aed_tag; /* 00 Descriptor Tag */ uint32_t aed_rev_ael; /* 10 Previous Alloc Extent Location */ uint32_t aed_len_aed; /* 14 Length of Allocation Desc */ }; typedef struct alloc_ext_desc alloc_ext_desc_t; /* * Indirect Entry * used to specify the address of another ICB */ struct indirect_entry { tag_t ie_tag; /* 00 Descriptor Tag */ icb_tag_t ie_icb_tag; /* 10 ICB tag */ long_ad_t ie_indirecticb; /* 24 Indirect ICB */ }; typedef struct indirect_entry indirect_entry_t; /* * Terminal Entry */ struct term_entry { tag_t te_tag; /* 00 Descriptor Tag */ icb_tag_t te_icb_tag; /* 10 ICB tag */ }; typedef struct term_entry term_entry_t; /* * File entry describes the * file attributes and location it is recorded on the media */ struct file_entry { tag_t fe_tag; /* 00 Descriptor Tag */ icb_tag_t fe_icb_tag; /* 10 ICB tag */ uint32_t fe_uid; /* 24 Uid */ uint32_t fe_gid; /* 28 Gid */ uint32_t fe_perms; /* 2C Permissions */ uint16_t fe_lcount; /* 30 File Link Count */ uint8_t fe_rec_for; /* 32 Record Format */ uint8_t fe_rec_dis; /* 33 Record Display Attributes */ uint32_t fe_rec_len; /* 34 Record Length */ uint64_t fe_info_len; /* 38 Information Length */ uint64_t fe_lbr; /* 40 Logical Blocks recorded */ tstamp_t fe_acc_time; /* 48 Access Data and Time */ tstamp_t fe_mod_time; /* 54 Modification Data and Time */ tstamp_t fe_attr_time; /* 60 Attribute Data and Time */ uint32_t fe_ckpoint; /* 6C Checkpoint */ long_ad_t fe_ea_icb; /* 70 Extended Attr ICB */ regid_t fe_impl_id; /* 80 Implementation Identifier */ uint64_t fe_uniq_id; /* A0 Unique Id */ uint32_t fe_len_ear; /* A8 Length of Extended Attr */ uint32_t fe_len_adesc; /* AC Length of Alloc Desc */ char fe_spec[336]; /* B0 used for EA and AD's */ }; typedef struct file_entry file_entry_t; /* * Extended Attribute Header */ struct ext_attr_hdr { tag_t eah_tag; /* 00 Descriptor Tag */ uint32_t eah_ial; /* 10 Implementation Attr Location */ uint32_t eah_aal; /* 14 Application Attr Location */ }; typedef struct ext_attr_hdr ext_attr_hdr_t; /* * Unallocated Space Entry */ struct unall_space_ent { tag_t use_tag; /* 00 Descriptor Tag */ icb_tag_t use_icb_tag; /* 10 ICB tag */ uint32_t use_len_ad; /* 24 Lenght of Allocation desc */ uint8_t use_ad[484]; /* 28 Allocation Descriptors */ }; typedef struct unall_space_ent unall_space_ent_t; /* * Space Bitmap Descriptor */ struct space_bmap_desc { tag_t sbd_tag; /* 00 Descriptor Tag */ uint32_t sbd_nbits; /* 10 Number of Bits */ uint32_t sbd_nbytes; /* 14 Number of Bytes */ uint8_t sbd_bmap[500]; /* 18 Bitmap */ }; typedef struct space_bmap_desc space_bmap_desc_t; /* * Partition Integrity entry */ struct part_int_desc { tag_t pid_tag; /* 00 Descriptor Tag */ icb_tag_t pid_idb_tag; /* 10 ICB tag */ tstamp_t pid_rtime; /* 24 Recording Data and Time */ uint8_t pid_integ; /* 30 Integrity type */ uint8_t pid_res[175]; /* 31 Reserved */ regid_t pid_ii; /* E0 Implementation Identifier */ uint8_t pid_iu[256]; /* 100 Implementation Use */ }; typedef struct part_int_desc part_int_desc_t; #define PART_OPEN_INT 0x00 #define PART_CLOSE_INT 0x01 #define PART_STABLE_INT 0x02 struct attr_hdr { uint32_t ahdr_atype; /* Attribute Type */ uint8_t ahdr_astype; /* Attribute Subtype */ uint8_t ahdr_res[3]; /* Reserved */ uint32_t ahdr_length; /* Attribute Length */ uint8_t ahdr_data[4]; /* Attribute Data */ }; /* * We will support and use the * following Extended Attributes * we will ignore others while reading * and will preserve then when updating * the EAR's * In all the EA's we allocate the last member * as 4 bytes. This is a sort of hack * since the structure has to be * properly alined to 4 bytes. */ struct dev_spec_ear { uint32_t ds_atype; /* 00 Attribute Type */ uint8_t ds_astype; /* 04 Attribute Subtype */ uint8_t ds_res[3]; /* 05 Reserved */ uint32_t ds_attr_len; /* 08 Attrbute Length */ uint32_t ds_iu_len; /* 0C Impl Use Length */ uint32_t ds_major_id; /* 10 Major Device ID */ uint32_t ds_minor_id; /* 14 Minor Device ID */ uint8_t ds_iu[4]; /* 18 Implementation Use */ }; struct ftimes_ear { uint32_t ft_atype; /* 00 Attribute Type */ uint8_t ft_astype; /* 04 Attribute Subtype */ uint8_t ft_res[3]; /* 05 Reserved */ uint32_t ft_attr_len; /* 08 Attrbute Length */ uint32_t ft_data_len; /* 0C Data Length */ uint32_t ft_exist; /* 10 File Time Existence */ uint8_t ft_ft[4]; /* 14 File Times */ }; /* ft_exit */ #define FT_EXIST 0x0 #define FT_DELETE 0x2 #define FT_FEDT 0x3 #define FT_BACKUP 0x5 struct iu_ea { uint32_t iuea_atype; /* 00 Attribute Type */ uint8_t iuea_astype; /* 04 Attribute Subtype */ uint8_t iuea_res[3]; /* 05 Reserved */ uint32_t iuea_attr_len; /* 08 Attrbute Length */ uint32_t iuea_iu_len; /* 0C Implementation Use Length */ regid_t iuea_ii; /* 10 Implementation ID */ uint8_t iuea_iu[4]; /* 30 Impl Use */ }; /* * CGMS & FREE_SPACE will be * over laid on iu_iu field */ struct copy_mgt_info { uint16_t cgms_cksum; /* Header Checksum */ uint8_t cgms_info; /* CGMS Information */ uint8_t cgms_dstype; /* Data Structure Type */ uint32_t cgms_psi; /* Protection System Info */ }; #define COPY_PROTECTED 0x80 struct FREE_SPACE { uint16_t fs_cksum; /* Header Checksum */ uint8_t fs_freesp[2]; /* Free EA space */ }; struct nsr_desc { uint8_t nsr_str_type; uint8_t nsr_id[5]; uint8_t nsr_ver; uint8_t nsr_res; uint8_t nsr_data[2040]; }; /* * Partition Map */ struct pmap_hdr { uint8_t maph_type; /* Partition Map Type */ uint8_t maph_length; /* Partition Map Length */ }; #define MAP_TYPE1 1 #define MAP_TYPE2 2 #define MAP_TYPE1_LEN 6 #define MAP_TYPE2_LEN 64 struct pmap_typ1 { uint8_t map1_type; /* Map type == 1 */ uint8_t map1_length; /* Map length == 6 */ uint16_t map1_vsn; /* Volume Sequence Number */ uint16_t map1_pn; /* Partition Number */ }; /* * Only two types of type2 maps * are supported they are * *UDF Virtual Partition * *UDF Sparable Partition * For vpm fields till map2_pn * are valid and the entire structure is * valid for spm */ struct pmap_typ2 { uint8_t map2_type; /* 00 Map type == 2 */ uint8_t map2_length; /* 01 Map length == 64 */ uint16_t map2_pad1; /* 02 Reserved */ regid_t map2_pti; /* 04 Entiry ID */ uint16_t map2_vsn; /* 24 Volume Sequence Number */ uint16_t map2_pn; /* 26 Partition Number */ uint16_t map2_pl; /* 28 Packet Length == 32 */ uint8_t map2_nst; /* 2A Number of sparing tables */ uint8_t map2_pad2; /* 2B Reserved */ uint32_t map2_sest; /* 2C Size of each sparing table */ uint32_t map2_st[4]; /* 30 sparing Tables */ }; struct stbl_entry { uint32_t sent_ol; /* Original Location */ uint32_t sent_ml; /* Mapped Location */ }; typedef struct stbl_entry stbl_entry_t; struct stbl { tag_t stbl_tag; /* 00 Tag */ regid_t stbl_si; /* 10 Sparing Identifier */ uint16_t stbl_len; /* 30 Reallocation Table Len */ uint16_t stbl_res1; /* 32 Reserved */ uint32_t stbl_seqno; /* 34 Sequence Number */ stbl_entry_t stbl_entry; /* 38 Sparing Table Entries */ }; struct path_comp { uint8_t pc_type; /* Component Type */ uint8_t pc_len; /* Length of Component ID */ uint16_t pc_ver; /* Component File Version Number */ uint8_t pc_id[4]; /* Component ID */ }; #ifdef __cplusplus } #endif #endif /* _SYS_FS_UDF_VOLUME_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_FS_UFS_ACL_H #define _SYS_FS_UFS_ACL_H #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * On-disk UFS ACL structure */ typedef struct ufs_acl { union { uint32_t acl_next; /* Pad for old structure */ ushort_t acl_tag; /* Entry type */ } acl_un; o_mode_t acl_perm; /* Permission bits */ uid_t acl_who; /* User or group ID */ } ufs_acl_t; #define acl_tag acl_un.acl_tag #define acl_next acl_un.acl_next /* * In-core UFS ACL structure */ typedef struct ufs_ic_acl { struct ufs_ic_acl *acl_ic_next; /* Next ACL for this inode */ o_mode_t acl_ic_perm; /* Permission bits */ uid_t acl_ic_who; /* User or group ID */ } ufs_ic_acl_t; /* * In-core ACL mask */ typedef struct ufs_aclmask { short acl_ismask; /* Is mask defined? */ o_mode_t acl_maskbits; /* Permission mask */ } ufs_aclmask_t; /* * full acl */ typedef struct ic_acl { ufs_ic_acl_t *owner; /* owner object */ ufs_ic_acl_t *group; /* group object */ ufs_ic_acl_t *other; /* other object */ ufs_ic_acl_t *users; /* list of users */ ufs_ic_acl_t *groups; /* list of groups */ ufs_aclmask_t mask; /* mask */ } ic_acl_t; /* * In-core shadow inode */ typedef struct si { struct si *s_next; /* signature hash next */ struct si *s_forw; /* inode hash next */ struct si *s_fore; /* unref'd list next */ int s_flags; /* see below */ ino_t s_shadow; /* shadow inode number */ dev_t s_dev; /* device (major,minor) */ int s_signature; /* signature for all ACLs */ int s_use; /* on disk use count */ int s_ref; /* in core reference count */ krwlock_t s_lock; /* lock for this structure */ ic_acl_t s_a; /* acls */ ic_acl_t s_d; /* def acls */ } si_t; #define aowner s_a.owner #define agroup s_a.group #define aother s_a.other #define ausers s_a.users #define agroups s_a.groups #define aclass s_a.mask #define downer s_d.owner #define dgroup s_d.group #define dother s_d.other #define dusers s_d.users #define dgroups s_d.groups #define dclass s_d.mask #define s_prev s_forw /* * s_flags */ #define SI_CACHED 0x0001 /* Is in si_cache */ /* * Header to identify data on disk */ typedef struct ufs_fsd { int fsd_type; /* type of data */ int fsd_size; /* size in bytes of ufs_fsd and data */ char fsd_data[1]; /* data */ } ufs_fsd_t; /* * Data types (fsd_type) */ #define FSD_FREE (0) /* Free entry */ #define FSD_ACL (1) /* Access Control Lists */ #define FSD_DFACL (2) /* reserved for future use */ #define FSD_RESERVED3 (3) /* reserved for future use */ #define FSD_RESERVED4 (4) /* reserved for future use */ #define FSD_RESERVED5 (5) /* reserved for future use */ #define FSD_RESERVED6 (6) /* reserved for future use */ #define FSD_RESERVED7 (7) /* reserved for future use */ /* * FSD manipulation macros * The FSD macros are aligned on integer boundary even if the preceeding * record had a byte aligned length. So the record length is always * integer length. All increments of the data pointers must use the * FSD_RECSZ macro. */ #define FSD_TPSZ(fsdp) (sizeof (fsdp->fsd_type)) #define FSD_TPMSK(fsdp) (FSD_TPSZ(fsdp) - 1) #define FSD_RECSZ(fsdp, size) ((size + FSD_TPMSK(fsdp)) & ~FSD_TPMSK(fsdp)) /* * flags for acl_validate */ #define ACL_CHECK 0x01 #define DEF_ACL_CHECK 0x02 #define MODE_CHECK(O, M, PERM, C, I) \ secpolicy_vnode_access2(C, ITOV(I), O, (PERM), M) /* * Check that the file type is one that accepts ACLs */ #define CHECK_ACL_ALLOWED(MODE) (((MODE) == IFDIR) || ((MODE) == IFREG) || \ ((MODE) == IFIFO) || ((MODE) == IFCHR) || \ ((MODE) == IFBLK) || ((MODE) == IFATTRDIR)) /* * Get ACL group permissions if the mask is not present, and the ACL * group permission intersected with the mask if the mask is present */ #define MASK2MODE(ACL) \ ((ACL)->aclass.acl_ismask ? \ ((((ACL)->aclass.acl_maskbits & \ (ACL)->agroup->acl_ic_perm) & 07) << 3) : \ (((ACL)->agroup->acl_ic_perm & 07) << 3)) #define MODE2ACL(P, MODE, CRED) \ ASSERT((P)); \ (P)->acl_ic_next = NULL; \ (P)->acl_ic_perm &= ((MODE) & 7); \ (P)->acl_ic_who = (CRED); #define ACL_MOVE(P, T, B) \ { \ ufs_ic_acl_t *acl; \ for (acl = (P); acl; acl = acl->acl_ic_next) { \ (B)->acl_tag = (T); \ (B)->acl_perm = acl->acl_ic_perm; \ (B)->acl_who = acl->acl_ic_who; \ (B)++; \ } \ } #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_ACL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1997,2001 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_FS_UFS_BIO_H #define _SYS_FS_UFS_BIO_H #include #include #ifdef __cplusplus extern "C" { #endif /* * Statistics on ufs buffer cache * Not protected by locks */ struct ufsbiostats { kstat_named_t ub_breads; /* ufs_bread */ kstat_named_t ub_bwrites; /* ufs_bwrite and ufs_bwrite2 */ kstat_named_t ub_fbiwrites; /* ufs_fbiwrite */ kstat_named_t ub_getpages; /* ufs_getpage_miss */ kstat_named_t ub_getras; /* ufs_getpage_ra */ kstat_named_t ub_putsyncs; /* ufs_putapage (B_SYNC) */ kstat_named_t ub_putasyncs; /* ufs_putapage (B_ASYNC) */ kstat_named_t ub_pageios; /* ufs_pageios (swap) */ }; extern struct ufsbiostats ub; #if defined(_KERNEL) /* * let's define macros for the ufs_bio calls (as they were originally * defined name-wise). using these macros to access the appropriate * *_common routines to minimize subroutine calls. */ extern struct buf *bread_common(void *arg, dev_t dev, daddr_t blkno, long bsize); extern void bwrite_common(void *arg, struct buf *bp, int force_wait, int do_relse, int clear_flags); extern struct buf *getblk_common(void * arg, dev_t dev, daddr_t blkno, long bsize, int flag); #define UFS_BREAD(ufsvfsp, dev, blkno, bsize) \ bread_common(ufsvfsp, dev, blkno, bsize) #define UFS_BWRITE(ufsvfsp, bp) \ bwrite_common(ufsvfsp, bp, /* force_wait */ 0, /* do_relse */ 1, \ /* clear_flags */ (B_READ | B_DONE | B_ERROR | B_DELWRI)) #define UFS_BRWRITE(ufsvfsp, bp) \ (bp)->b_flags |= B_RETRYWRI; \ bwrite_common(ufsvfsp, bp, /* force_wait */ 0, /* do_relse */ 1, \ /* clear_flags */ (B_READ | B_DONE | B_ERROR | B_DELWRI)) #define UFS_BWRITE2(ufsvfsp, bp) \ bwrite_common(ufsvfsp, bp, /* force_wait */ 1, /* do_relse */ 0, \ /* clear_flags */ (B_READ | B_DONE | B_ERROR | B_DELWRI)) #define UFS_GETBLK(ufsvfsp, dev, blkno, bsize) \ getblk_common(ufsvfsp, dev, blkno, bsize, /* errflg */ 0) #endif /* defined(_KERNEL) */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_BIO_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2014 Garrett D'Amore * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_UFS_FILIO_H #define _SYS_FS_UFS_FILIO_H #ifdef __cplusplus extern "C" { #endif /* * _FIOIO * * struct for _FIOIO ioctl(): * Input: * fio_ino - inode number * fio_gen - generation number * Output: * fio_fd - readonly file descriptor * */ struct fioio { ino_t fio_ino; /* input : inode number */ int fio_gen; /* input : generation number */ int fio_fd; /* output: readonly file descriptor */ }; #if defined(_SYSCALL32) struct fioio32 { ino32_t fio_ino; /* input : inode number */ int32_t fio_gen; /* input : generation number */ int32_t fio_fd; /* output: readonly file descriptor */ }; #endif /* _SYSCALL32 */ /* * _FIOTUNE */ struct fiotune { int maxcontig; /* cluster and directio size */ int rotdelay; /* skip blocks between contig allocations */ int maxbpg; /* currently defaults to 2048 */ int minfree; /* %age to reserve for root */ int optim; /* space or time */ }; /* * UFS Logging */ typedef struct fiolog { uint_t nbytes_requested; uint_t nbytes_actual; int error; } fiolog_t; #define FIOLOG_ENONE 0 #define FIOLOG_ETRANS 1 #define FIOLOG_EROFS 2 #define FIOLOG_EULOCK 3 #define FIOLOG_EWLOCK 4 #define FIOLOG_ECLEAN 5 #define FIOLOG_ENOULOCK 6 #if defined(_KERNEL) extern int ufs_fiosatime(struct vnode *, struct timeval *, int, struct cred *); extern int ufs_fiosdio(struct vnode *, uint_t *, int flag, struct cred *); extern int ufs_fiogdio(struct vnode *, uint_t *, int flag, struct cred *); extern int ufs_fioio(struct vnode *, struct fioio *, int, struct cred *); extern int ufs_fioisbusy(struct vnode *, int *, struct cred *); extern int ufs_fiodirectio(struct vnode *, int, struct cred *); extern int ufs_fiotune(struct vnode *, struct fiotune *, struct cred *); extern int ufs_fiologenable(vnode_t *, fiolog_t *, cred_t *, int); extern int ufs_fiologdisable(vnode_t *, fiolog_t *, cred_t *, int); extern int ufs_fioislog(vnode_t *, uint32_t *, cred_t *, int); extern int ufs_fio_holey(vnode_t *, int, offset_t *); extern int ufs_mark_compressed(struct vnode *vp); #endif /* defined(_KERNEL) */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_FILIO_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #ifndef _SYS_FS_UFS_FS_H #define _SYS_FS_UFS_FS_H #include #include #include /* for kmutex_t */ #ifdef __cplusplus extern "C" { #endif /* * The following values are minor release values for UFS. * The fs_version field in the superblock will equal one of them. */ #define MTB_UFS_VERSION_MIN 1 #define MTB_UFS_VERSION_1 1 #define UFS_VERSION_MIN 0 #define UFS_EFISTYLE4NONEFI_VERSION_2 2 /* * Each disk drive contains some number of file systems. * A file system consists of a number of cylinder groups. * Each cylinder group has inodes and data. * * A file system is described by its super-block, which in turn * describes the cylinder groups. The super-block is critical * data and is replicated in the first 10 cylinder groups and the * the last 10 cylinder groups to protect against * catastrophic loss. This is done at mkfs time and the critical * super-block data does not change, so the copies need not be * referenced further unless disaster strikes. * * For file system fs, the offsets of the various blocks of interest * are given in the super block as: * [fs->fs_sblkno] Super-block * [fs->fs_cblkno] Cylinder group block * [fs->fs_iblkno] Inode blocks * [fs->fs_dblkno] Data blocks * The beginning of cylinder group cg in fs, is given by * the ``cgbase(fs, cg)'' macro. * * The first boot and super blocks are given in absolute disk addresses. * The byte-offset forms are preferred, as they don't imply a sector size. */ #define BBSIZE 8192 #define SBSIZE 8192 #define BBOFF ((off_t)(0)) #define SBOFF ((off_t)(BBOFF + BBSIZE)) #define BBLOCK ((daddr32_t)(0)) #define SBLOCK ((daddr32_t)(BBLOCK + BBSIZE / DEV_BSIZE)) /* * Addresses stored in inodes are capable of addressing fragments * of `blocks'. File system blocks of at most size MAXBSIZE can * be optionally broken into 2, 4, or 8 pieces, each of which is * addressible; these pieces may be DEV_BSIZE, or some multiple of * a DEV_BSIZE unit. * * Large files consist of exclusively large data blocks. To avoid * undue wasted disk space, the last data block of a small file may be * allocated as only as many fragments of a large block as are * necessary. The file system format retains only a single pointer * to such a fragment, which is a piece of a single large block that * has been divided. The size of such a fragment is determinable from * information in the inode, using the ``blksize(fs, ip, lbn)'' macro. * * The file system records space availability at the fragment level; * to determine block availability, aligned fragments are examined. * * The root inode is the root of the file system. * Inode 0 can't be used for normal purposes and * historically bad blocks were linked to inode 1, * thus the root inode is 2. (inode 1 is no longer used for * this purpose, however numerous dump tapes make this * assumption, so we are stuck with it) * The lost+found directory is given the next available * inode when it is created by ``mkfs''. */ #define UFSROOTINO ((ino_t)2) /* i number of all roots */ #define LOSTFOUNDINO (UFSROOTINO + 1) #ifndef _LONGLONG_TYPE #define UFS_MAXOFFSET_T MAXOFF_T #define UFS_FILESIZE_BITS 32 #else #define UFS_MAXOFFSET_T ((1LL << NBBY * sizeof (daddr32_t) + DEV_BSHIFT - 1) \ - 1) #define UFS_FILESIZE_BITS 41 #endif /* _LONGLONG_TYPE */ /* * MINBSIZE is the smallest allowable block size. * In order to insure that it is possible to create files of size * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. * MINBSIZE must be big enough to hold a cylinder group block, * thus changes to (struct cg) must keep its size within MINBSIZE. * Note that super blocks are always of size SBSIZE, * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. */ #define MINBSIZE 4096 /* * The path name on which the file system is mounted is maintained * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in * the super block for this name. * The limit on the amount of summary information per file system * is defined by MAXCSBUFS. It is currently parameterized for a * maximum of two million cylinders. */ #define MAXMNTLEN 512 #define MAXCSBUFS 32 #define LABEL_TYPE_VTOC 1 #define LABEL_TYPE_EFI 2 #define LABEL_TYPE_OTHER 3 /* * The following constant is taken from the ANSI T13 ATA Specification * and defines the maximum size (in sectors) that an ATA disk can be * and still has to provide CHS translation. For a disk above this * size all sectors are to be accessed via their LBA address. This * makes a good cut off value to move from disk provided geometry * to the predefined defaults used in efi label disks. */ #define CHSLIMIT (63 * 256 * 1024) /* * Per cylinder group information; summarized in blocks allocated * from first cylinder group data blocks. These blocks have to be * read in from fs_csaddr (size fs_cssize) in addition to the * super block. * * N.B. sizeof (struct csum) must be a power of two in order for * the ``fs_cs'' macro to work (see below). */ struct csum { int32_t cs_ndir; /* number of directories */ int32_t cs_nbfree; /* number of free blocks */ int32_t cs_nifree; /* number of free inodes */ int32_t cs_nffree; /* number of free frags */ }; /* * In the 5.0 release, the file system state flag in the superblock (fs_clean) * is now used. The value of fs_clean can be: * FSACTIVE file system may have fsck inconsistencies * FSCLEAN file system has successfully unmounted (implies * everything is ok) * FSSTABLE No fsck inconsistencies, no guarantee on user data * FSBAD file system is mounted from a partition that is * neither FSCLEAN or FSSTABLE * FSSUSPEND Clean flag processing is temporarily disabled * FSLOG Logging file system * Under this scheme, fsck can safely skip file systems that * are FSCLEAN or FSSTABLE. To provide additional safeguard, * fs_clean information could be trusted only if * fs_state == FSOKAY - fs_time, where FSOKAY is a constant * * Note: mount(2) will now return ENOSPC if fs_clean is neither FSCLEAN nor * FSSTABLE, or fs_state is not valid. The exceptions are the root or * the read-only partitions */ /* * Super block for a file system. * * Most of the data in the super block is read-only data and needs * no explicit locking to protect it. Exceptions are: * fs_time * fs_optim * fs_cstotal * fs_fmod * fs_cgrotor * fs_flags (largefiles flag - set when a file grows large) * These fields require the use of fs->fs_lock. */ #define FS_MAGIC 0x011954 #define MTB_UFS_MAGIC 0xdecade #define FSOKAY (0x7c269d38) /* #define FSOKAY (0x7c269d38 + 3) */ /* * fs_clean values */ #define FSACTIVE ((char)0) #define FSCLEAN ((char)0x1) #define FSSTABLE ((char)0x2) #define FSBAD ((char)0xff) /* mounted !FSCLEAN and !FSSTABLE */ #define FSSUSPEND ((char)0xfe) /* temporarily suspended */ #define FSLOG ((char)0xfd) /* logging fs */ #define FSFIX ((char)0xfc) /* being repaired while mounted */ /* * fs_flags values */ #define FSLARGEFILES ((char)0x1) /* largefiles exist on filesystem */ struct fs { uint32_t fs_link; /* linked list of file systems */ uint32_t fs_rolled; /* logging only: fs fully rolled */ daddr32_t fs_sblkno; /* addr of super-block in filesys */ daddr32_t fs_cblkno; /* offset of cyl-block in filesys */ daddr32_t fs_iblkno; /* offset of inode-blocks in filesys */ daddr32_t fs_dblkno; /* offset of first data after cg */ int32_t fs_cgoffset; /* cylinder group offset in cylinder */ int32_t fs_cgmask; /* used to calc mod fs_ntrak */ time32_t fs_time; /* last time written */ int32_t fs_size; /* number of blocks in fs */ int32_t fs_dsize; /* number of data blocks in fs */ int32_t fs_ncg; /* number of cylinder groups */ int32_t fs_bsize; /* size of basic blocks in fs */ int32_t fs_fsize; /* size of frag blocks in fs */ int32_t fs_frag; /* number of frags in a block in fs */ /* these are configuration parameters */ int32_t fs_minfree; /* minimum percentage of free blocks */ int32_t fs_rotdelay; /* num of ms for optimal next block */ int32_t fs_rps; /* disk revolutions per second */ /* these fields can be computed from the others */ int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ int32_t fs_fshift; /* ``numfrags'' calc number of frags */ /* these are configuration parameters */ int32_t fs_maxcontig; /* max number of contiguous blks */ int32_t fs_maxbpg; /* max number of blks per cyl group */ /* these fields can be computed from the others */ int32_t fs_fragshift; /* block to frag shift */ int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ int32_t fs_sbsize; /* actual size of super block */ int32_t fs_csmask; /* csum block offset */ int32_t fs_csshift; /* csum block number */ int32_t fs_nindir; /* value of NINDIR */ int32_t fs_inopb; /* value of INOPB */ int32_t fs_nspf; /* value of NSPF */ /* yet another configuration parameter */ int32_t fs_optim; /* optimization preference, see below */ /* these fields are derived from the hardware */ /* USL SVR4 compatibility */ #ifdef _LITTLE_ENDIAN /* * USL SVR4 compatibility * * There was a significant divergence here between Solaris and * SVR4 for x86. By swapping these two members in the superblock, * we get read-only compatibility of SVR4 filesystems. Otherwise * there would be no compatibility. This change was introduced * during bootstrapping of Solaris on x86. By making this ifdef'ed * on byte order, we provide ongoing compatibility across all * platforms with the same byte order, the highest compatibility * that can be achieved. */ int32_t fs_state; /* file system state time stamp */ #else int32_t fs_npsect; /* # sectors/track including spares */ #endif int32_t fs_si; /* summary info state - lufs only */ int32_t fs_trackskew; /* sector 0 skew, per track */ /* a unique id for this filesystem (currently unused and unmaintained) */ /* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */ /* Neither of those fields is used in the Tahoe code right now but */ /* there could be problems if they are. */ int32_t fs_id[2]; /* file system id */ /* sizes determined by number of cylinder groups and their sizes */ daddr32_t fs_csaddr; /* blk addr of cyl grp summary area */ int32_t fs_cssize; /* size of cyl grp summary area */ int32_t fs_cgsize; /* cylinder group size */ /* these fields are derived from the hardware */ int32_t fs_ntrak; /* tracks per cylinder */ int32_t fs_nsect; /* sectors per track */ int32_t fs_spc; /* sectors per cylinder */ /* this comes from the disk driver partitioning */ int32_t fs_ncyl; /* cylinders in file system */ /* these fields can be computed from the others */ int32_t fs_cpg; /* cylinders per group */ int32_t fs_ipg; /* inodes per group */ int32_t fs_fpg; /* blocks per group * fs_frag */ /* this data must be re-computed after crashes */ struct csum fs_cstotal; /* cylinder summary information */ /* these fields are cleared at mount time */ char fs_fmod; /* super block modified flag */ char fs_clean; /* file system state flag */ char fs_ronly; /* mounted read-only flag */ char fs_flags; /* largefiles flag, etc. */ char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ /* these fields retain the current block allocation info */ int32_t fs_cgrotor; /* last cg searched */ /* * The following used to be fs_csp[MAXCSBUFS]. It was not * used anywhere except in old utilities. We removed this * in 5.6 and expect fs_u.fs_csp to be used instead. * We no longer limit fs_cssize based on MAXCSBUFS. */ union { /* fs_cs (csum) info */ uint32_t fs_csp_pad[MAXCSBUFS]; struct csum *fs_csp; } fs_u; int32_t fs_cpc; /* cyl per cycle in postbl */ short fs_opostbl[16][8]; /* old rotation block list head */ int32_t fs_sparecon[51]; /* reserved for future constants */ int32_t fs_version; /* minor version of ufs */ int32_t fs_logbno; /* block # of embedded log */ int32_t fs_reclaim; /* reclaim open, deleted files */ int32_t fs_sparecon2; /* reserved for future constant */ #ifdef _LITTLE_ENDIAN /* USL SVR4 compatibility */ int32_t fs_npsect; /* # sectors/track including spares */ #else int32_t fs_state; /* file system state time stamp */ #endif quad_t fs_qbmask; /* ~fs_bmask - for use with quad size */ quad_t fs_qfmask; /* ~fs_fmask - for use with quad size */ int32_t fs_postblformat; /* format of positional layout tables */ int32_t fs_nrpos; /* number of rotaional positions */ int32_t fs_postbloff; /* (short) rotation block list head */ int32_t fs_rotbloff; /* (uchar_t) blocks for each rotation */ int32_t fs_magic; /* magic number */ uchar_t fs_space[1]; /* list of blocks for each rotation */ /* actually longer */ }; /* * values for fs_reclaim */ #define FS_RECLAIM (0x00000001) /* run the reclaim-files thread */ #define FS_RECLAIMING (0x00000002) /* running the reclaim-files thread */ #define FS_CHECKCLEAN (0x00000004) /* checking for a clean file system */ #define FS_CHECKRECLAIM (0x00000008) /* checking for a reclaimable file */ /* * values for fs_rolled */ #define FS_PRE_FLAG 0 /* old system, prior to fs_rolled flag */ #define FS_ALL_ROLLED 1 #define FS_NEED_ROLL 2 /* * values for fs_si, logging only * si is the summary of the summary - a copy of the cylinder group summary * info held in an array for perf. On a mount if this is out of date * (FS_SI_BAD) it can be re-constructed by re-reading the cgs. */ #define FS_SI_OK 0 /* on-disk summary info ok */ #define FS_SI_BAD 1 /* out of date on-disk si */ /* * Preference for optimization. */ #define FS_OPTTIME 0 /* minimize allocation time */ #define FS_OPTSPACE 1 /* minimize disk fragmentation */ /* * Rotational layout table format types */ #define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ #define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ /* * Macros for access to superblock array structures */ #ifdef _KERNEL #define fs_postbl(ufsvfsp, cylno) \ (((ufsvfsp)->vfs_fs->fs_postblformat != FS_DYNAMICPOSTBLFMT) \ ? ((ufsvfsp)->vfs_fs->fs_opostbl[cylno]) \ : ((short *)((char *)(ufsvfsp)->vfs_fs + \ (ufsvfsp)->vfs_fs->fs_postbloff) \ + (cylno) * (ufsvfsp)->vfs_nrpos)) #else #define fs_postbl(fs, cylno) \ (((fs)->fs_postblformat != FS_DYNAMICPOSTBLFMT) \ ? ((fs)->fs_opostbl[cylno]) \ : ((short *)((char *)(fs) + \ (fs)->fs_postbloff) \ + (cylno) * (fs)->fs_nrpos)) #endif #define fs_rotbl(fs) \ (((fs)->fs_postblformat != FS_DYNAMICPOSTBLFMT) \ ? ((fs)->fs_space) \ : ((uchar_t *)((char *)(fs) + (fs)->fs_rotbloff))) /* * Convert cylinder group to base address of its global summary info. * * N.B. This macro assumes that sizeof (struct csum) is a power of two. * We just index off the first entry into one big array */ #define fs_cs(fs, indx) fs_u.fs_csp[(indx)] /* * Cylinder group block for a file system. * * Writable fields in the cylinder group are protected by the associated * super block lock fs->fs_lock. */ #define CG_MAGIC 0x090255 struct cg { uint32_t cg_link; /* NOT USED linked list of cyl groups */ int32_t cg_magic; /* magic number */ time32_t cg_time; /* time last written */ int32_t cg_cgx; /* we are the cgx'th cylinder group */ short cg_ncyl; /* number of cyl's this cg */ short cg_niblk; /* number of inode blocks this cg */ int32_t cg_ndblk; /* number of data blocks this cg */ struct csum cg_cs; /* cylinder summary information */ int32_t cg_rotor; /* position of last used block */ int32_t cg_frotor; /* position of last used frag */ int32_t cg_irotor; /* position of last used inode */ int32_t cg_frsum[MAXFRAG]; /* counts of available frags */ int32_t cg_btotoff; /* (int32_t)block totals per cylinder */ int32_t cg_boff; /* (short) free block positions */ int32_t cg_iusedoff; /* (char) used inode map */ int32_t cg_freeoff; /* (uchar_t) free block map */ int32_t cg_nextfreeoff; /* (uchar_t) next available space */ int32_t cg_sparecon[16]; /* reserved for future use */ uchar_t cg_space[1]; /* space for cylinder group maps */ /* actually longer */ }; /* * Macros for access to cylinder group array structures */ #define cg_blktot(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_btot) \ : ((int32_t *)((char *)(cgp) + (cgp)->cg_btotoff))) #ifdef _KERNEL #define cg_blks(ufsvfsp, cgp, cylno) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_b[cylno]) \ : ((short *)((char *)(cgp) + (cgp)->cg_boff) + \ (cylno) * (ufsvfsp)->vfs_nrpos)) #else #define cg_blks(fs, cgp, cylno) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_b[cylno]) \ : ((short *)((char *)(cgp) + (cgp)->cg_boff) + \ (cylno) * (fs)->fs_nrpos)) #endif #define cg_inosused(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_iused) \ : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff))) #define cg_blksfree(cgp) \ (((cgp)->cg_magic != CG_MAGIC) \ ? (((struct ocg *)(cgp))->cg_free) \ : ((uchar_t *)((char *)(cgp) + (cgp)->cg_freeoff))) #define cg_chkmagic(cgp) \ ((cgp)->cg_magic == CG_MAGIC || \ ((struct ocg *)(cgp))->cg_magic == CG_MAGIC) /* * The following structure is defined * for compatibility with old file systems. */ struct ocg { uint32_t cg_link; /* NOT USED linked list of cyl groups */ uint32_t cg_rlink; /* NOT USED incore cyl groups */ time32_t cg_time; /* time last written */ int32_t cg_cgx; /* we are the cgx'th cylinder group */ short cg_ncyl; /* number of cyl's this cg */ short cg_niblk; /* number of inode blocks this cg */ int32_t cg_ndblk; /* number of data blocks this cg */ struct csum cg_cs; /* cylinder summary information */ int32_t cg_rotor; /* position of last used block */ int32_t cg_frotor; /* position of last used frag */ int32_t cg_irotor; /* position of last used inode */ int32_t cg_frsum[8]; /* counts of available frags */ int32_t cg_btot[32]; /* block totals per cylinder */ short cg_b[32][8]; /* positions of free blocks */ char cg_iused[256]; /* used inode map */ int32_t cg_magic; /* magic number */ uchar_t cg_free[1]; /* free block map */ /* actually longer */ }; /* * Turn frag offsets into disk block addresses. * This maps frags to device size blocks. * (In the names of these macros, "fsb" refers to "frags", not * file system blocks.) */ #ifdef KERNEL #define fsbtodb(fs, b) (((daddr_t)(b)) << (fs)->fs_fsbtodb) #else /* KERNEL */ #define fsbtodb(fs, b) (((diskaddr_t)(b)) << (fs)->fs_fsbtodb) #endif /* KERNEL */ #define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) /* * Get the offset of the log, in either sectors, frags, or file system * blocks. The interpretation of the fs_logbno field depends on whether * this is UFS or MTB UFS. (UFS stores the value as sectors. MTBUFS * stores the value as frags.) */ #ifdef KERNEL #define logbtodb(fs, b) ((fs)->fs_magic == FS_MAGIC ? \ (daddr_t)(b) : ((daddr_t)(b) << (fs)->fs_fsbtodb)) #else /* KERNEL */ #define logbtodb(fs, b) ((fs)->fs_magic == FS_MAGIC ? \ (diskaddr_t)(b) : ((diskaddr_t)(b) << (fs)->fs_fsbtodb)) #endif /* KERNEL */ #define logbtofrag(fs, b) ((fs)->fs_magic == FS_MAGIC ? \ (b) >> (fs)->fs_fsbtodb : (b)) #define logbtofsblk(fs, b) ((fs)->fs_magic == FS_MAGIC ? \ (b) >> ((fs)->fs_fsbtodb + (fs)->fs_fragshift) : \ (b) >> (fs)->fs_fragshift) /* * Cylinder group macros to locate things in cylinder groups. * They calc file system addresses of cylinder group data structures. */ #define cgbase(fs, c) ((daddr32_t)((fs)->fs_fpg * (c))) #define cgstart(fs, c) \ (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask))) #define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ #define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ #define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ #define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ /* * Macros for handling inode numbers: * inode number to file system block offset. * inode number to cylinder group number. * inode number to file system block address. */ #define itoo(fs, x) ((x) % (uint32_t)INOPB(fs)) #define itog(fs, x) ((x) / (uint32_t)(fs)->fs_ipg) #define itod(fs, x) \ ((daddr32_t)(cgimin(fs, itog(fs, x)) + \ (blkstofrags((fs), (((x)%(ulong_t)(fs)->fs_ipg)/(ulong_t)INOPB(fs)))))) /* * Give cylinder group number for a file system block. * Give cylinder group block number for a file system block. */ #define dtog(fs, d) ((d) / (fs)->fs_fpg) #define dtogd(fs, d) ((d) % (fs)->fs_fpg) /* * Extract the bits for a block from a map. * Compute the cylinder and rotational position of a cyl block addr. */ #define blkmap(fs, map, loc) \ (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & \ (0xff >> (NBBY - (fs)->fs_frag))) #define cbtocylno(fs, bno) \ ((bno) * NSPF(fs) / (fs)->fs_spc) #ifdef _KERNEL #define cbtorpos(ufsvfsp, bno) \ ((((bno) * NSPF((ufsvfsp)->vfs_fs) % (ufsvfsp)->vfs_fs->fs_spc) % \ (ufsvfsp)->vfs_fs->fs_nsect) * \ (ufsvfsp)->vfs_nrpos) / (ufsvfsp)->vfs_fs->fs_nsect #else #define cbtorpos(fs, bno) \ ((((bno) * NSPF(fs) % (fs)->fs_spc) % \ (fs)->fs_nsect) * \ (fs)->fs_nrpos) / (fs)->fs_nsect #endif /* * The following macros optimize certain frequently calculated * quantities by using shifts and masks in place of divisions * modulos and multiplications. */ /* * This macro works for 40 bit offset support in ufs because * this calculates offset in the block and therefore no loss of * information while casting to int. */ #define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ ((int)((loc) & ~(fs)->fs_bmask)) /* * This macro works for 40 bit offset support similar to blkoff */ #define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ ((int)((loc) & ~(fs)->fs_fmask)) /* * The cast to int32_t does not result in any loss of information because * the number of logical blocks in the file system is limited to * what fits in an int32_t anyway. */ #define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ ((int32_t)((loc) >> (fs)->fs_bshift)) /* * The same argument as above applies here. */ #define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ ((int32_t)((loc) >> (fs)->fs_fshift)) /* * Size can be a 64-bit value and therefore we sign extend fs_bmask * to a 64-bit value too so that the higher 32 bits are masked * properly. Note that the type of fs_bmask has to be signed. Otherwise * compiler will set the higher 32 bits as zero and we don't want * this to happen. */ #define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ (((size) + (fs)->fs_bsize - 1) & (offset_t)(fs)->fs_bmask) /* * Same argument as above. */ #define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ (((size) + (fs)->fs_fsize - 1) & (offset_t)(fs)->fs_fmask) /* * frags cannot exceed 32-bit value since we only support 40bit sizes. */ #define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ ((frags) >> (fs)->fs_fragshift) #define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ ((blks) << (fs)->fs_fragshift) #define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ ((fsb) & ((fs)->fs_frag - 1)) #define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ ((fsb) &~ ((fs)->fs_frag - 1)) /* * Determine the number of available frags given a * percentage to hold in reserve */ #define freespace(fs, ufsvfsp) \ ((blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ (fs)->fs_cstotal.cs_nffree) - (ufsvfsp)->vfs_minfrags) /* * Determining the size of a file block in the file system. */ #define blksize(fs, ip, lbn) \ (((lbn) >= NDADDR || \ (ip)->i_size >= (offset_t)((lbn) + 1) << (fs)->fs_bshift) \ ? (fs)->fs_bsize \ : (fragroundup(fs, blkoff(fs, (ip)->i_size)))) #define dblksize(fs, dip, lbn) \ (((lbn) >= NDADDR || \ (dip)->di_size >= (offset_t)((lbn) + 1) << (fs)->fs_bshift) \ ? (fs)->fs_bsize \ : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) /* * Number of disk sectors per block; assumes DEV_BSIZE byte sector size. */ #define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift) #define NSPF(fs) ((fs)->fs_nspf) /* * INOPB is the number of inodes in a secondary storage block. */ #define INOPB(fs) ((fs)->fs_inopb) #define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) /* * NINDIR is the number of indirects in a file system block. */ #define NINDIR(fs) ((fs)->fs_nindir) /* * bit map related macros */ #define bitloc(a, i) ((a)[(i)/NBBY]) #define setbit(a, i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) #define clrbit(a, i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) #define isset(a, i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) #define isclr(a, i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) #define getfs(vfsp) \ ((struct fs *)((struct ufsvfs *)vfsp->vfs_data)->vfs_bufp->b_un.b_addr) #define RETRY_LOCK_DELAY 1 /* * Macros to test and acquire i_rwlock: * some vnops hold the target directory's i_rwlock after calling * ufs_lockfs_begin but in many other operations (like ufs_readdir) * VOP_RWLOCK is explicitly called by the filesystem independent code before * calling the file system operation. In these cases the order is reversed * (i.e i_rwlock is taken first and then ufs_lockfs_begin is called). This * is fine as long as ufs_lockfs_begin acts as a VOP counter but with * ufs_quiesce setting the SLOCK bit this becomes a synchronizing * object which might lead to a deadlock. So we use rw_tryenter instead of * rw_enter. If we fail to get this lock and find that SLOCK bit is set, we * call ufs_lockfs_end and restart the operation. */ #define ufs_tryirwlock(lock, mode, label) \ {\ indeadlock = 0;\ label:\ if (!rw_tryenter(lock, mode))\ {\ if (ulp && ULOCKFS_IS_SLOCK(ulp)) {\ indeadlock = 1;\ } else {\ delay(RETRY_LOCK_DELAY);\ goto label;\ }\ }\ } /* * The macro ufs_tryirwlock_trans is used in functions which call * TRANS_BEGIN_CSYNC and ufs_lockfs_begin, hence the need to call * TRANS_END_CSYNC and ufs_lockfs_end. */ #define ufs_tryirwlock_trans(lock, mode, transmode, label) \ {\ indeadlock = 0;\ label:\ if (!rw_tryenter(lock, mode))\ {\ if (ulp && ULOCKFS_IS_SLOCK(ulp)) {\ TRANS_END_CSYNC(ufsvfsp, error, issync,\ transmode, trans_size);\ ufs_lockfs_end(ulp);\ indeadlock = 1;\ } else {\ delay(RETRY_LOCK_DELAY);\ goto label;\ }\ }\ } #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_FS_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 1998 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #ifndef _SYS_FS_UFS_FSDIR_H #define _SYS_FS_UFS_FSDIR_H #ifdef __cplusplus extern "C" { #endif /* * A directory consists of some number of blocks of DIRBLKSIZ * bytes, where DIRBLKSIZ is chosen such that it can be transferred * to disk in a single atomic operation (e.g. 512 bytes on most machines). * * Each DIRBLKSIZ byte block contains some number of directory entry * structures, which are of variable length. Each directory entry has * a struct direct at the front of it, containing its inode number, * the length of the entry, and the length of the name contained in * the entry. These are followed by the name padded to a 4 byte boundary * with null bytes. All names are guaranteed null terminated. * The maximum length of a name in a directory is MAXNAMLEN. * * The macro DIRSIZ(dp) gives the amount of space required to represent * a directory entry. Free space in a directory is represented by * entries which have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes * in a directory block are claimed by the directory entries. This * usually results in the last entry in a directory having a large * dp->d_reclen. When entries are deleted from a directory, the * space is returned to the previous entry in the same directory * block by increasing its dp->d_reclen. If the first entry of * a directory block is free, then its dp->d_ino is set to 0. * Entries other than the first in a directory do not normally have * dp->d_ino set to 0. */ #define DIRBLKSIZ DEV_BSIZE #define MAXNAMLEN 255 struct direct { uint32_t d_ino; /* inode number of entry */ ushort_t d_reclen; /* length of this record */ ushort_t d_namlen; /* length of string in d_name */ char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ }; /* * The DIRSIZ macro gives the minimum record length which will hold * the directory entry. This requires the amount of space in struct direct * without the d_name field, plus enough space for the name with a terminating * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. */ #undef DIRSIZ #define DIRSIZ(dp) \ ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1+3) &~ 3)) #ifdef _KERNEL /* * Template for manipulating directories. * Should use struct direct's, but the name field * is MAXNAMLEN - 1, and this just won't do. */ struct dirtemplate { uint32_t dot_ino; short dot_reclen; short dot_namlen; char dot_name[4]; /* must be multiple of 4 */ uint32_t dotdot_ino; short dotdot_reclen; short dotdot_namlen; char dotdot_name[4]; /* ditto */ }; /* * Reduced structure for manipulating directories. * Note, we are using __packed here to ensure the size of structure * without changing the alignment. */ struct tmp_dir { uint32_t d_ino; /* inode number of entry */ ushort_t d_reclen; /* length of this record */ ushort_t d_namlen; /* length of string in d_name */ char d_name[4]; /* name must be no longer than this */ } __packed; #endif #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_FSDIR_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #ifndef _SYS_FS_UFS_INODE_H #define _SYS_FS_UFS_INODE_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _KERNEL #include #endif #ifdef __cplusplus extern "C" { #endif /* * The I node is the focus of all local file activity in UNIX. * There is a unique inode allocated for each active file, * each current directory, each mounted-on file, each mapping, * and the root. An inode is `named' by its dev/inumber pair. * Data in icommon is read in from permanent inode on volume. * * Each inode has 5 locks associated with it: * i_rwlock: Serializes ufs_write and ufs_setattr request * and allows ufs_read requests to proceed in parallel. * Serializes reads/updates to directories. * vfs_dqrwlock: Manages quota sub-system quiescence. See below. * i_contents: Protects almost all of the fields in the inode * except for those listed below. When held * in writer mode also protects those fields * listed under i_tlock. * i_tlock: When i_tlock is held with the i_contents reader * lock the i_atime, i_mtime, i_ctime, * i_delayoff, i_delaylen, i_nextrio, i_writes, i_flag * i_seq, i_writer & i_mapcnt fields are protected. * For more i_flag locking info see below. * ih_lock: Protects inode hash chain buckets * ifree_lock: Protects inode freelist * * Lock ordering: * i_rwlock > i_contents > i_tlock * i_rwlock > vfs_dqrwlock > i_contents(writer) > i_tlock * i_contents > i_tlock * vfs_dqrwlock > i_contents(writer) > i_tlock * ih_lock > i_contents > i_tlock * * Making major changes to quota sub-system state, while the file * system is mounted required the addition of another lock. The * primary lock in the quota sub-system is vfs_dqrwlock in the ufsvfs * structure. This lock is used to manage quota sub-system quiescence * for a particular file system. Major changes to quota sub-system * state (disabling quotas, enabling quotas, and setting new quota * limits) all require the file system to be quiescent and grabbing * vfs_dqrwlock as writer accomplishes this. On the other hand, * grabbing vfs_dqrwlock as reader makes the quota sub-system * non-quiescent and lets the quota sub-system know that now is not a * good time to change major quota sub-system state. Typically * vfs_dqrwlock is grabbed for reading before i_contents is grabbed for * writing. However, there are cases where vfs_dqrwlock is grabbed for * reading without a corresponding i_contents write grab because there * is no relevant inode. There are also cases where i_contents is * grabbed for writing when a vfs_dqrwlock read grab is not needed * because the inode changes do not affect quotas. * * Unfortunately, performance considerations have required that we be more * intelligent about using i_tlock when updating i_flag. Ideally, we would * have simply separated out several of the bits in i_flag into their own * ints to avoid problems. But, instead, we have implemented the following * rules: * * o You can update any i_flag field while holding the writer-contents, * or by holding the reader-contents AND holding i_tlock. * You can only call ITIMES_NOLOCK while holding the writer-contents, * or by holding the reader-contents AND holding i_tlock. * * o For a directory, holding the reader-rw_lock is sufficient for setting * IACC. * * o Races with IREF are avoided by holding the reader contents lock * and by holding i_tlock in ufs_rmidle, ufs_putapage, and ufs_getpage. * And by holding the writer-contents in ufs_iinactive. * * o The callers are no longer required to handle the calls to ITIMES * and ITIMES_NOLOCK. The functions that set the i_flag bits are * responsible for managing those calls. The exceptions are the * bmap routines. * * SVR4 Extended Fundamental Type (EFT) support: * The inode structure has been enhanced to support * 32-bit user-id, 32-bit group-id, and 32-bit device number. * Standard SVR4 ufs also supports 32-bit mode field. For the reason * of backward compatibility with the previous ufs disk format, * 32-bit mode field is not supported. * * The current inode structure is 100% backward compatible with * the previous inode structure if no user-id or group-id exceeds * USHRT_MAX, and no major or minor number of a device number * stored in an inode exceeds 255. * * Rules for managing i_seq: * o i_seq is locked under the same rules as i_flag * o The i_ctime or i_mtime MUST never change without increasing * the value of i_seq. * o You may increase the value of i_seq without the timestamps * changing, this may decrease the callers performance but will * be functionally correct. * o The common case is when IUPD or ICHG is set, increase i_seq * and immediately call ITIMES* or ufs_iupdat to create a new timestamp. * o A less common case is the setting of IUPD or ICHG and while still * holding the correct lock defer the timestamp and i_seq update * until later, but it must still be done before the lock is released. * bmap_write is an example of this, where the caller does the update. * o If multiple changes are being made with the timestamps being * updated only at the end, a single increase of i_seq is allowed. * o If changes are made with IUPD or ICHG being set, but * the controlling lock is being dropped before the timestamp is * updated, there is a risk that another thread will also change * the file, update i_flag, and push just one timestamp update. * There is also the risk that another thread calls ITIMES or * ufs_iupdat without setting IUPD|ICHG and thus not changing i_seq, * this will cause ufs_imark to change the timestamps without changing * i_seq. If the controlling lock is dropped, ISEQ must be set to * force i_seq to be increased on next ufs_imark, but i_seq MUST still * be increased by the original setting thread before its deferred * call to ITIMES to insure it is increased the correct number of times. */ #define UID_LONG (o_uid_t)65535 /* flag value to indicate uid is 32-bit long */ #define GID_LONG (o_uid_t)65535 /* flag value to indicate gid is 32-bit long */ #define NDADDR 12 /* direct addresses in inode */ #define NIADDR 3 /* indirect addresses in inode */ #define FSL_SIZE (NDADDR + NIADDR - 1) * sizeof (daddr32_t) /* max fast symbolic name length is 56 */ #define i_fs i_ufsvfs->vfs_bufp->b_un.b_fs #define i_vfs i_vnode->v_vfsp struct icommon { o_mode_t ic_smode; /* 0: mode and type of file */ short ic_nlink; /* 2: number of links to file */ o_uid_t ic_suid; /* 4: owner's user id */ o_gid_t ic_sgid; /* 6: owner's group id */ u_offset_t ic_lsize; /* 8: number of bytes in file */ #ifdef _KERNEL struct timeval32 ic_atime; /* 16: time last accessed */ struct timeval32 ic_mtime; /* 24: time last modified */ struct timeval32 ic_ctime; /* 32: last time inode changed */ #else time32_t ic_atime; /* 16: time last accessed */ int32_t ic_atspare; time32_t ic_mtime; /* 24: time last modified */ int32_t ic_mtspare; time32_t ic_ctime; /* 32: last time inode changed */ int32_t ic_ctspare; #endif daddr32_t ic_db[NDADDR]; /* 40: disk block addresses */ daddr32_t ic_ib[NIADDR]; /* 88: indirect blocks */ int32_t ic_flags; /* 100: cflags */ int32_t ic_blocks; /* 104: 512 byte blocks actually held */ int32_t ic_gen; /* 108: generation number */ int32_t ic_shadow; /* 112: shadow inode */ uid_t ic_uid; /* 116: long EFT version of uid */ gid_t ic_gid; /* 120: long EFT version of gid */ uint32_t ic_oeftflag; /* 124: extended attr directory ino, 0 = none */ }; /* * Large directories can be cached. Directory caching can take the following * states: */ typedef enum { CD_DISABLED_NOMEM = -2, CD_DISABLED_TOOBIG, CD_DISABLED, CD_ENABLED } cachedir_t; /* * Large Files: Note we use the inline functions load_double, store_double * to load and store the long long values of i_size. Therefore the * address of i_size must be eight byte aligned. Kmem_alloc of incore * inode structure makes sure that the structure is 8-byte aligned. * XX64 - reorder this structure? */ typedef struct inode { struct inode *i_chain[2]; /* must be first */ struct inode *i_freef; /* free list forward - must be before i_ic */ struct inode *i_freeb; /* free list back - must be before i_ic */ struct icommon i_ic; /* Must be here */ struct vnode *i_vnode; /* vnode associated with this inode */ struct vnode *i_devvp; /* vnode for block I/O */ dev_t i_dev; /* device where inode resides */ ino_t i_number; /* i number, 1-to-1 with device address */ off_t i_diroff; /* offset in dir, where we found last entry */ /* just a hint - no locking needed */ struct ufsvfs *i_ufsvfs; /* incore fs associated with inode */ struct dquot *i_dquot; /* quota structure controlling this file */ krwlock_t i_rwlock; /* serializes write/setattr requests */ krwlock_t i_contents; /* protects (most of) inode contents */ kmutex_t i_tlock; /* protects time fields, i_flag */ offset_t i_nextr; /* */ /* next byte read offset (read-ahead) */ /* No lock required */ /* */ uint_t i_flag; /* inode flags */ uint_t i_seq; /* modification sequence number */ cachedir_t i_cachedir; /* Cache this directory on next lookup */ /* - no locking needed */ long i_mapcnt; /* mappings to file pages */ int *i_map; /* block list for the corresponding file */ dev_t i_rdev; /* INCORE rdev from i_oldrdev by ufs_iget */ size_t i_delaylen; /* delayed writes, units=bytes */ offset_t i_delayoff; /* where we started delaying */ offset_t i_nextrio; /* where to start the next clust */ long i_writes; /* number of outstanding bytes in write q */ kcondvar_t i_wrcv; /* sleep/wakeup for write throttle */ offset_t i_doff; /* dinode byte offset in file system */ si_t *i_ufs_acl; /* pointer to acl entry */ dcanchor_t i_danchor; /* directory cache anchor */ kthread_t *i_writer; /* thread which is in window in wrip() */ } inode_t; struct dinode { union { struct icommon di_icom; char di_size[128]; } di_un; }; #define i_mode i_ic.ic_smode #define i_nlink i_ic.ic_nlink #define i_uid i_ic.ic_uid #define i_gid i_ic.ic_gid #define i_smode i_ic.ic_smode #define i_suid i_ic.ic_suid #define i_sgid i_ic.ic_sgid #define i_size i_ic.ic_lsize #define i_db i_ic.ic_db #define i_ib i_ic.ic_ib #define i_atime i_ic.ic_atime #define i_mtime i_ic.ic_mtime #define i_ctime i_ic.ic_ctime #define i_shadow i_ic.ic_shadow #define i_oeftflag i_ic.ic_oeftflag #define i_blocks i_ic.ic_blocks #define i_cflags i_ic.ic_flags #ifdef _LITTLE_ENDIAN /* * Originally done on x86, but carried on to all other little * architectures, which provides for file system compatibility. */ #define i_ordev i_ic.ic_db[1] /* USL SVR4 compatibility */ #else #define i_ordev i_ic.ic_db[0] /* was i_oldrdev */ #endif #define i_gen i_ic.ic_gen #define i_forw i_chain[0] #define i_back i_chain[1] /* EFT transition aids - obsolete */ #define oEFT_MAGIC 0x90909090 #define di_oeftflag di_ic.ic_oeftflag #define di_ic di_un.di_icom #define di_mode di_ic.ic_smode #define di_nlink di_ic.ic_nlink #define di_uid di_ic.ic_uid #define di_gid di_ic.ic_gid #define di_smode di_ic.ic_smode #define di_suid di_ic.ic_suid #define di_sgid di_ic.ic_sgid #define di_size di_ic.ic_lsize #define di_db di_ic.ic_db #define di_ib di_ic.ic_ib #define di_atime di_ic.ic_atime #define di_mtime di_ic.ic_mtime #define di_ctime di_ic.ic_ctime #define di_cflags di_ic.ic_flags #ifdef _LITTLE_ENDIAN #define di_ordev di_ic.ic_db[1] #else #define di_ordev di_ic.ic_db[0] #endif #define di_shadow di_ic.ic_shadow #define di_blocks di_ic.ic_blocks #define di_gen di_ic.ic_gen /* flags */ #define IUPD 0x0001 /* file has been modified */ #define IACC 0x0002 /* inode access time to be updated */ #define IMOD 0x0004 /* inode has been modified */ #define ICHG 0x0008 /* inode has been changed */ #define INOACC 0x0010 /* no access time update in getpage */ #define IMODTIME 0x0020 /* mod time already set */ #define IREF 0x0040 /* inode is being referenced */ #define ISYNC 0x0080 /* do all allocation synchronously */ #define IFASTSYMLNK 0x0100 /* fast symbolic link */ #define IMODACC 0x0200 /* only access time changed; */ /* filesystem won't become active */ #define IATTCHG 0x0400 /* only size/blocks have changed */ #define IBDWRITE 0x0800 /* the inode has been scheduled for */ /* write operation asynchronously */ #define ISTALE 0x1000 /* inode couldn't be read from disk */ #define IDEL 0x2000 /* inode is being deleted */ #define IDIRECTIO 0x4000 /* attempt directio */ #define ISEQ 0x8000 /* deferred i_seq increase */ #define IJUNKIQ 0x10000 /* on junk idle queue */ #define IQUIET 0x20000 /* No file system full messages */ /* cflags */ #define IXATTR 0x0001 /* extended attribute */ #define IFALLOCATE 0x0002 /* fallocate'd file */ #define ICOMPRESS 0x0004 /* compressed for dcfs - see */ /* `ufs_ioctl()`_FIO_COMPRESSED */ /* modes */ #define IFMT 0170000 /* type of file */ #define IFIFO 0010000 /* named pipe (fifo) */ #define IFCHR 0020000 /* character special */ #define IFDIR 0040000 /* directory */ #define IFBLK 0060000 /* block special */ #define IFREG 0100000 /* regular */ #define IFLNK 0120000 /* symbolic link */ #define IFSHAD 0130000 /* shadow indode */ #define IFSOCK 0140000 /* socket */ #define IFATTRDIR 0160000 /* Attribute directory */ #define ISUID 04000 /* set user id on execution */ #define ISGID 02000 /* set group id on execution */ #define ISVTX 01000 /* save swapped text even after use */ #define IREAD 0400 /* read, write, execute permissions */ #define IWRITE 0200 #define IEXEC 0100 /* specify how the inode info is written in ufs_syncip() */ #define I_SYNC 1 /* wait for the inode written to disk */ #define I_DSYNC 2 /* wait for the inode written to disk */ /* only if IATTCHG is set */ #define I_ASYNC 0 /* don't wait for the inode written */ /* flags passed to ufs_itrunc(), indirtrunc(), and free() */ #define I_FREE 0x00000001 /* inode is being freed */ #define I_DIR 0x00000002 /* inode is a directory */ #define I_IBLK 0x00000004 /* indirect block */ #define I_CHEAP 0x00000008 /* cheap free */ #define I_SHAD 0x00000010 /* inode is a shadow inode */ #define I_QUOTA 0x00000020 /* quota file */ #define I_NOCANCEL 0x40 /* Don't cancel these fragments */ #define I_ACCT 0x00000080 /* Update ufsvfs' unreclaimed_blocks */ /* * If ufs_dircheckforname() fails to find an entry with the given name, * this "slot" structure holds state for ufs_direnter_*() as to where * there is space to put an entry with that name. * If ufs_dircheckforname() finds an entry with the given name, this structure * holds state for ufs_dirrename() and ufs_dirremove() as to where the * entry is. "status" indicates what ufs_dircheckforname() found: * NONE name not found, large enough free slot not found, * FOUND name not found, large enough free slot found * EXIST name found * If ufs_dircheckforname() fails due to an error, this structure is not * filled in. * * After ufs_dircheckforname() succeeds the values are: * status offset size fbp, ep * ------ ------ ---- ------- * NONE end of dir needed not valid * FOUND start of entry of ent both valid if fbp != NULL * EXIST start of entry of prev ent valid * * "endoff" is set to 0 if the an entry with the given name is found, or if no * free slot could be found or made; this means that the directory should not * be truncated. If the entry was found, the search terminates so * ufs_dircheckforname() didn't find out where the last valid entry in the * directory was, so it doesn't know where to cut the directory off; if no free * slot could be found or made, the directory has to be extended to make room * for the new entry, so there's nothing to cut off. * Otherwise, "endoff" is set to the larger of the offset of the last * non-empty entry in the directory, or the offset at which the new entry will * be placed, whichever is larger. This is used by ufs_diraddentry(); if a new * entry is to be added to the directory, any complete directory blocks at the * end of the directory that contain no non-empty entries are lopped off the * end, thus shrinking the directory dynamically. */ typedef enum {NONE, FOUND, EXIST} slotstat_t; struct ufs_slot { struct direct *ep; /* pointer to slot */ struct fbuf *fbp; /* dir buf where slot is */ off_t offset; /* offset of area with free space */ off_t endoff; /* last useful location found in search */ slotstat_t status; /* status of slot */ int size; /* size of area at slotoffset */ int cached; /* cached directory */ }; /* * Statistics on inodes * Not protected by locks */ struct instats { kstat_named_t in_size; /* current cache size */ kstat_named_t in_maxsize; /* maximum cache size */ kstat_named_t in_hits; /* cache hits */ kstat_named_t in_misses; /* cache misses */ kstat_named_t in_malloc; /* kmem_alloce'd */ kstat_named_t in_mfree; /* kmem_free'd */ kstat_named_t in_maxreached; /* Largest size reached by cache */ kstat_named_t in_frfront; /* # put at front of freelist */ kstat_named_t in_frback; /* # put at back of freelist */ kstat_named_t in_qfree; /* q's to delete thread */ kstat_named_t in_scan; /* # inodes scanned */ kstat_named_t in_tidles; /* # inodes idled by idle thread */ kstat_named_t in_lidles; /* # inodes idled by ufs_lookup */ kstat_named_t in_vidles; /* # inodes idled by ufs_vget */ kstat_named_t in_kcalloc; /* # inodes kmem_cache_alloced */ kstat_named_t in_kcfree; /* # inodes kmem_cache_freed */ kstat_named_t in_poc; /* # push-on-close's */ }; #ifdef _KERNEL /* * Extended attributes */ #define XATTR_DIR_NAME "/@/" extern int ufs_ninode; /* high-water mark for inode cache */ extern struct vnodeops *ufs_vnodeops; /* vnode operations for ufs */ extern const struct fs_operation_def ufs_vnodeops_template[]; /* * Convert between inode pointers and vnode pointers */ #define VTOI(VP) ((struct inode *)(VP)->v_data) #define ITOV(IP) ((struct vnode *)(IP)->i_vnode) /* * convert to fs */ #define ITOF(IP) ((struct fs *)(IP)->i_fs) /* * Convert between vnode types and inode formats */ extern enum vtype iftovt_tab[]; #ifdef notneeded /* Look at sys/mode.h and os/vnode.c */ extern int vttoif_tab[]; #endif /* * Mark an inode with the current (unique) timestamp. * (Note that UFS's concept of time only keeps 32 bits of seconds * in the on-disk format). */ extern struct timeval32 iuniqtime; extern kmutex_t ufs_iuniqtime_lock; #define ITIMES_NOLOCK(ip) ufs_itimes_nolock(ip) #define ITIMES(ip) { \ mutex_enter(&(ip)->i_tlock); \ ITIMES_NOLOCK(ip); \ mutex_exit(&(ip)->i_tlock); \ } /* * The following interfaces are used to do atomic loads and stores * of an inode's i_size, which is a long long data type. * * For LP64, we just to a load or a store - atomicity and alignment * are 8-byte guaranteed. For x86 there are no such instructions, * so we grab i_contents as reader to get the size; we already hold * it as writer when we're setting the size. */ #ifdef _LP64 #define UFS_GET_ISIZE(resultp, ip) *(resultp) = (ip)->i_size #define UFS_SET_ISIZE(value, ip) (ip)->i_size = (value) #else /* _LP64 */ #define UFS_GET_ISIZE(resultp, ip) \ { \ rw_enter(&(ip)->i_contents, RW_READER); \ *(resultp) = (ip)->i_size; \ rw_exit(&(ip)->i_contents); \ } #define UFS_SET_ISIZE(value, ip) \ { \ ASSERT(RW_WRITE_HELD(&(ip)->i_contents)); \ (ip)->i_size = (value); \ } #endif /* _LP64 */ /* * Allocate the specified block in the inode * and make sure any in-core pages are initialized. */ #define BMAPALLOC(ip, off, size, cr) \ bmap_write((ip), (u_offset_t)(off), (size), BI_NORMAL, NULL, cr) #define ESAME (-1) /* trying to rename linked files (special) */ #define UFS_HOLE (daddr32_t)-1 /* value used when no block allocated */ /* * enums */ /* direnter ops */ enum de_op { DE_CREATE, DE_MKDIR, DE_LINK, DE_RENAME, DE_SYMLINK, DE_ATTRDIR}; /* dirremove ops */ enum dr_op { DR_REMOVE, DR_RMDIR, DR_RENAME }; /* * block initialization type for bmap_write * * BI_NORMAL - allocate and zero fill pages in memory * BI_ALLOC_ONLY - only allocate the block, do not zero out pages in mem * BI_FALLOCATE - allocate only, do not zero out pages, and store as negative * block number in inode block list */ enum bi_type { BI_NORMAL, BI_ALLOC_ONLY, BI_FALLOCATE }; /* * This overlays the fid structure (see vfs.h) * * LP64 note: we use int32_t instead of ino_t since UFS does not use * inode numbers larger than 32-bits and ufid's are passed to NFS * which expects them to not grow in size beyond 10 bytes (12 including * the length). */ struct ufid { ushort_t ufid_len; ushort_t ufid_flags; int32_t ufid_ino; int32_t ufid_gen; }; /* * each ufs thread (see ufs_thread.c) is managed by this struct */ struct ufs_q { union uq_head { void *_uq_generic; /* first entry on q */ struct inode *_uq_i; ufs_failure_t *_uq_uf; } _uq_head; int uq_ne; /* # of entries/failures found */ int uq_lowat; /* thread runs when ne == lowat */ int uq_hiwat; /* synchronous idle if ne >= hiwat */ ushort_t uq_flags; /* flags (see below) */ kcondvar_t uq_cv; /* for sleep/wakeup */ kthread_id_t uq_threadp; /* thread managing this q */ kmutex_t uq_mutex; /* protects this struct */ }; #define uq_head _uq_head._uq_generic #define uq_ihead _uq_head._uq_i #define uq_ufhead _uq_head._uq_uf /* * uq_flags */ #define UQ_EXIT (0x0001) /* q server exits at its convenience */ #define UQ_WAIT (0x0002) /* thread is waiting on q server */ #define UQ_SUSPEND (0x0004) /* request for suspension */ #define UQ_SUSPENDED (0x0008) /* thread has suspended itself */ /* * When logging is enabled, statvfs must account for blocks and files that * may be on the delete queue. Protected by ufsvfsp->vfs_delete.uq_mutex */ struct ufs_delq_info { u_offset_t delq_unreclaimed_blocks; ulong_t delq_unreclaimed_files; }; /* * global idle queues * The queues are sized dynamically in proportion to ufs_ninode * which, unless overridden, scales with the amount of memory. * The idle queue is halved whenever it hits the low water mark * (1/4 of ufs_ninode), but can burst to sizes much larger. The number * of hash queues is currently maintained to give on average IQHASHQLEN * entries when the idle queue is at the low water mark. * Note, we do not need to search along the hash queues, but use them * in order to batch together geographically local inodes to allow * their updates (via the log or buffer cache) to require less disk seeks. * This gives an incredible performance boost for logging and a boost for * non logging file systems. */ typedef struct { inode_t *i_chain[2]; /* must match inode_t, but unused */ inode_t *i_freef; /* must match inode_t, idle list forward */ inode_t *i_freeb; /* must match inode_t, idle list back */ } iqhead_t; extern struct ufs_q ufs_idle_q; /* used by global ufs idle thread */ extern iqhead_t *ufs_junk_iq; /* junk idle queues */ extern iqhead_t *ufs_useful_iq; /* useful idle queues */ extern int ufs_njunk_iq; /* number of entries in junk iq */ extern int ufs_nuseful_iq; /* number of entries in useful iq */ extern int ufs_niqhash; /* number of iq hash qs - power of 2 */ extern int ufs_iqhashmask; /* iq hash mask = ufs_niqhash - 1 */ #define IQHASHQLEN 32 /* see comments above */ #define INOCGSHIFT 7 /* 128 inodes per cylinder group */ #define IQHASH(ip) (((ip)->i_number >> INOCGSHIFT) & ufs_iqhashmask) #define IQNEXT(i) ((i) + 1) & ufs_iqhashmask /* next idle queue */ extern struct ufs_q ufs_hlock; /* used by global ufs hlock thread */ /* * vfs_lfflags flags */ #define UFS_LARGEFILES ((ushort_t)0x1) /* set if mount allows largefiles */ /* * vfs_dfritime flags */ #define UFS_DFRATIME 0x1 /* deferred access time */ /* * UFS VFS private data. * * UFS file system instances may be linked on several lists. * * - The vfs_next field chains together every extant ufs instance; this * list is rooted at ufs_instances and should be used in preference to * the overall vfs list (which is properly the province of the generic * file system code, not of file system implementations). This same list * link is used during forcible unmounts to chain together instances that * can't yet be completely dismantled, * * - The vfs_wnext field is used within ufs_update to form a work list of * UFS instances to be synced out. */ typedef struct ufsvfs { struct vfs *vfs_vfs; /* back link */ struct ufsvfs *vfs_next; /* instance list link */ struct ufsvfs *vfs_wnext; /* work list link */ struct vnode *vfs_root; /* root vnode */ struct buf *vfs_bufp; /* buffer containing superblock */ struct vnode *vfs_devvp; /* block device vnode */ ushort_t vfs_lfflags; /* Large files (set by mount) */ ushort_t vfs_qflags; /* QUOTA: filesystem flags */ struct inode *vfs_qinod; /* QUOTA: pointer to quota file */ uint_t vfs_btimelimit; /* QUOTA: block time limit */ uint_t vfs_ftimelimit; /* QUOTA: file time limit */ krwlock_t vfs_dqrwlock; /* QUOTA: protects quota fields */ /* * some fs local threads */ struct ufs_q vfs_delete; /* delayed inode delete */ struct ufs_q vfs_reclaim; /* reclaim open, deleted files */ /* * This is copied from the super block at mount time. */ int vfs_nrpos; /* # rotational positions */ /* * This lock protects cg's and super block pointed at by * vfs_bufp->b_fs. Locks contents of fs and cg's and contents * of vfs_dio. */ kmutex_t vfs_lock; struct ulockfs vfs_ulockfs; /* ufs lockfs support */ uint_t vfs_dio; /* delayed io (_FIODIO) */ uint_t vfs_nointr; /* disallow lockfs interrupts */ uint_t vfs_nosetsec; /* disallow ufs_setsecattr */ uint_t vfs_syncdir; /* synchronous local directory ops */ uint_t vfs_dontblock; /* don't block on forced umount */ /* * trans (logging ufs) stuff */ uint_t vfs_domatamap; /* set if matamap enabled */ ulong_t vfs_maxacl; /* transaction stuff - max acl size */ ulong_t vfs_dirsize; /* logspace for directory creation */ ulong_t vfs_avgbfree; /* average free blks in cg (blkpref) */ /* * Some useful constants */ int vfs_nindirshift; /* calc. from fs_nindir */ int vfs_nindiroffset; /* calc. from fs_ninidr */ int vfs_ioclustsz; /* bytes in read/write cluster */ int vfs_iotransz; /* max device i/o transfer size */ vfs_ufsfx_t vfs_fsfx; /* lock/fix-on-panic support */ /* * More useful constants */ int vfs_minfrags; /* calc. from fs_minfree */ /* * Force DirectIO on all files */ uint_t vfs_forcedirectio; /* * Deferred inode time related fields */ clock_t vfs_iotstamp; /* last I/O timestamp */ uint_t vfs_dfritime; /* deferred inode time flags */ /* * Some more useful info */ dev_t vfs_dev; /* device mounted from */ struct ml_unit *vfs_log; /* pointer to embedded log struct */ uint_t vfs_noatime; /* disable inode atime updates */ /* * snapshot stuff */ void *vfs_snapshot; /* snapshot handle */ /* * Controls logging "file system full" messages to messages file */ clock_t vfs_lastwhinetime; int vfs_nolog_si; /* not logging summary info */ int vfs_validfs; /* indicates mounted fs */ /* * Additional information about vfs_delete above */ struct ufs_delq_info vfs_delete_info; /* what's on the delete queue */ } ufsvfs_t; #define vfs_fs vfs_bufp->b_un.b_fs /* * values for vfs_validfs */ #define UT_UNMOUNTED 0 #define UT_MOUNTED 1 #define UT_HLOCKING 2 /* inohsz is guaranteed to be a power of 2 */ #define INOHASH(ino) (((int)ino) & (inohsz - 1)) #define ISFALLOCBLK(ip, bn) \ (((bn) < 0) && ((bn) % ip->i_fs->fs_frag == 0) && \ ((ip)->i_cflags & IFALLOCATE && (bn) != UFS_HOLE)) union ihead { union ihead *ih_head[2]; struct inode *ih_chain[2]; }; extern union ihead *ihead; extern kmutex_t *ih_lock; extern int *ih_ne; extern int inohsz; extern clock_t ufs_iowait; #endif /* _KERNEL */ /* * ufs function prototypes */ #if defined(_KERNEL) && !defined(_BOOT) extern void ufs_iinit(void); extern int ufs_iget(struct vfs *, ino_t, struct inode **, cred_t *); extern int ufs_iget_alloced(struct vfs *, ino_t, struct inode **, cred_t *); extern void ufs_reset_vnode(vnode_t *); extern void ufs_iinactive(struct inode *); extern void ufs_iupdat(struct inode *, int); extern int ufs_rmidle(struct inode *); extern int ufs_itrunc(struct inode *, u_offset_t, int, cred_t *); extern int ufs_iaccess(struct inode *, int, cred_t *, int); extern int rdip(struct inode *, struct uio *, int, struct cred *); extern int wrip(struct inode *, struct uio *, int, struct cred *); extern void ufs_imark(struct inode *); extern void ufs_itimes_nolock(struct inode *); extern int ufs_diraccess(struct inode *, int, struct cred *); extern int ufs_dirlook(struct inode *, char *, struct inode **, cred_t *, int, int); extern int ufs_direnter_cm(struct inode *, char *, enum de_op, struct vattr *, struct inode **, cred_t *, int); extern int ufs_direnter_lr(struct inode *, char *, enum de_op, struct inode *, struct inode *, cred_t *); extern int ufs_dircheckpath(ino_t, struct inode *, struct inode *, struct cred *); extern int ufs_dirmakeinode(struct inode *, struct inode **, struct vattr *, enum de_op, cred_t *); extern int ufs_dirremove(struct inode *, char *, struct inode *, vnode_t *, enum dr_op, cred_t *); extern int ufs_dircheckforname(struct inode *, char *, int, struct ufs_slot *, struct inode **, struct cred *, int); extern int ufs_xattrdirempty(struct inode *, ino_t, cred_t *); extern int blkatoff(struct inode *, off_t, char **, struct fbuf **); extern void sbupdate(struct vfs *); extern int ufs_ialloc(struct inode *, ino_t, mode_t, struct inode **, cred_t *); extern void ufs_ifree(struct inode *, ino_t, mode_t); extern void free(struct inode *, daddr_t, off_t, int); extern int alloc(struct inode *, daddr_t, int, daddr_t *, cred_t *); extern int realloccg(struct inode *, daddr_t, daddr_t, int, int, daddr_t *, cred_t *); extern int ufs_allocsp(struct vnode *, struct flock64 *, cred_t *); extern int ufs_freesp(struct vnode *, struct flock64 *, int, cred_t *); extern ino_t dirpref(inode_t *); extern daddr_t blkpref(struct inode *, daddr_t, int, daddr32_t *); extern daddr_t contigpref(ufsvfs_t *, size_t, size_t); extern int ufs_rdwri(enum uio_rw, int, struct inode *, caddr_t, ssize_t, offset_t, enum uio_seg, int *, cred_t *); extern int bmap_read(struct inode *, u_offset_t, daddr_t *, int *); extern int bmap_write(struct inode *, u_offset_t, int, enum bi_type, daddr_t *, struct cred *); extern int bmap_has_holes(struct inode *); extern int bmap_find(struct inode *, boolean_t, u_offset_t *); extern int bmap_set_bn(struct vnode *, u_offset_t, daddr32_t); extern void ufs_vfs_add(struct ufsvfs *); extern void ufs_vfs_remove(struct ufsvfs *); extern void ufs_sbwrite(struct ufsvfs *); extern void ufs_update(int); extern int ufs_getsummaryinfo(dev_t, struct ufsvfs *, struct fs *); extern int ufs_putsummaryinfo(dev_t, struct ufsvfs *, struct fs *); extern int ufs_syncip(struct inode *, int, int, top_t); extern int ufs_sync_indir(struct inode *); extern int ufs_indirblk_sync(struct inode *, offset_t); extern int ufs_badblock(struct inode *, daddr_t); extern int ufs_indir_badblock(struct inode *, daddr32_t *); extern void ufs_notclean(struct ufsvfs *); extern void ufs_checkclean(struct vfs *); extern int isblock(struct fs *, uchar_t *, daddr_t); extern void setblock(struct fs *, uchar_t *, daddr_t); extern void clrblock(struct fs *, uchar_t *, daddr_t); extern int isclrblock(struct fs *, uchar_t *, daddr_t); extern void fragacct(struct fs *, int, int32_t *, int); extern int skpc(char, uint_t, char *); extern int ufs_fbwrite(struct fbuf *, struct inode *); extern int ufs_fbiwrite(struct fbuf *, struct inode *, daddr_t, long); extern int ufs_putapage(struct vnode *, struct page *, u_offset_t *, size_t *, int, struct cred *); extern inode_t *ufs_alloc_inode(ufsvfs_t *, ino_t); extern void ufs_free_inode(inode_t *); /* * special stuff */ extern void ufs_setreclaim(struct inode *); extern int ufs_scan_inodes(int, int (*)(struct inode *, void *), void *, struct ufsvfs *); extern int ufs_sync_inode(struct inode *, void *); extern int ufs_sticky_remove_access(struct inode *, struct inode *, struct cred *); /* * quota */ extern int chkiq(struct ufsvfs *, int, struct inode *, uid_t, int, struct cred *, char **errp, size_t *lenp); /* * ufs thread stuff */ extern void ufs_thread_delete(struct vfs *); extern void ufs_delete_drain(struct vfs *, int, int); extern void ufs_delete(struct ufsvfs *, struct inode *, int); extern void ufs_inode_cache_reclaim(void *); extern void ufs_idle_drain(struct vfs *); extern void ufs_idle_some(int); extern void ufs_thread_idle(void); extern void ufs_thread_reclaim(struct vfs *); extern void ufs_thread_init(struct ufs_q *, int); extern void ufs_thread_start(struct ufs_q *, void (*)(), struct vfs *); extern void ufs_thread_exit(struct ufs_q *); extern void ufs_thread_suspend(struct ufs_q *); extern void ufs_thread_continue(struct ufs_q *); extern void ufs_thread_hlock(void *); extern void ufs_delete_init(struct ufsvfs *, int); extern void ufs_delete_adjust_stats(struct ufsvfs *, struct statvfs64 *); extern void ufs_delete_drain_wait(struct ufsvfs *, int); /* * ufs lockfs stuff */ struct seg; extern int ufs_reconcile_fs(struct vfs *, struct ufsvfs *, int); extern int ufs_quiesce(struct ulockfs *); extern int ufs_flush(struct vfs *); extern int ufs_fiolfs(struct vnode *, struct lockfs *, int); extern int ufs__fiolfs(struct vnode *, struct lockfs *, int, int); extern int ufs_fiolfss(struct vnode *, struct lockfs *); extern int ufs_fioffs(struct vfs *, struct cred *); extern int ufs_check_lockfs(struct ufsvfs *, struct ulockfs *, ulong_t); extern int ufs_lockfs_begin(struct ufsvfs *, struct ulockfs **, ulong_t); extern int ufs_lockfs_trybegin(struct ufsvfs *, struct ulockfs **, ulong_t); extern int ufs_lockfs_begin_getpage(struct ufsvfs *, struct ulockfs **, struct seg *, int, uint_t *); extern void ufs_lockfs_end(struct ulockfs *); /* * ufs acl stuff */ extern int ufs_si_inherit(struct inode *, struct inode *, o_mode_t, cred_t *); extern void si_cache_init(void); extern int ufs_si_load(struct inode *, cred_t *); extern void ufs_si_del(struct inode *); extern int ufs_acl_access(struct inode *, int, cred_t *); extern void ufs_si_cache_flush(dev_t); extern int ufs_si_free(si_t *, struct vfs *, cred_t *); extern int ufs_acl_setattr(struct inode *, struct vattr *, cred_t *); extern int ufs_acl_get(struct inode *, vsecattr_t *, int, cred_t *); extern int ufs_acl_set(struct inode *, vsecattr_t *, int, cred_t *); /* * ufs directio stuff */ extern void ufs_directio_init(); extern int ufs_directio_write(struct inode *, uio_t *, int, int, cred_t *, int *); extern int ufs_directio_read(struct inode *, uio_t *, cred_t *, int *); #define DIRECTIO_FAILURE (0) #define DIRECTIO_SUCCESS (1) /* * ufs extensions for PXFS */ int ufs_rdwr_data(vnode_t *vp, u_offset_t offset, size_t len, fdbuffer_t *fdb, int flags, cred_t *cr); int ufs_alloc_data(vnode_t *vp, u_offset_t offset, size_t *len, fdbuffer_t *fdb, int flags, cred_t *cr); /* * prototypes to support the forced unmount */ void ufs_freeze(struct ulockfs *, struct lockfs *); int ufs_thaw(struct vfs *, struct ufsvfs *, struct ulockfs *); /* * extended attributes */ int ufs_xattrmkdir(inode_t *, inode_t **, int, struct cred *); int ufs_xattr_getattrdir(vnode_t *, inode_t **, int, struct cred *); void ufs_unhook_shadow(inode_t *, inode_t *); #endif /* defined(_KERNEL) && !defined(_BOOT) */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_INODE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_UFS_LOCKFS_H #define _SYS_FS_UFS_LOCKFS_H #include #ifdef __cplusplus extern "C" { #endif /* * Sun ufs file system locking (lockfs) * * ufs file system supports the following lock types: * unlock - releasing existing locks, or do a file system flush * name lock - no delete, no rename * write lock - no update to file system, including delete * delete lock - no delete, rename is allowed * hard lock - no update, no access, cannot be unlocked * - for supporting forcible umount * error lock - no update, no access, may only be unlocked * - once fs becomes clean, may be upgraded to * - a hard lock * error lock (read-only) -- not yet implemented -- * - no write changes allowed to fs, may be upgraded * - to error or hard lock * - degrades to panic on subsequent failures * * ufs_vnodeops(es) that conflict with the above file system lock types * will get either suspended, or get a EAGAIN error, * or get an EIO error if the file system is hard locked, * or will block if the file system is error locked. * * There are exceptions. * The following ufs_vnops do not obey the locking protocol: * ufs_close, ufs_putpage, ufs_inactive, ufs_addmap, ufs_delmap, * ufs_rwlock, ufs_rwunlock, ufs_poll. * * ul_vnops_cnt will get increment by 1 when a ufs vnodeops is entered; * it will be decremented by 1 when a ufs_vnodeops is exited. * A file system is in a quiescent state if ufs_vnops_cnt is zero. * Since ufs_pageio() has to change ul_vnops_cnt without using ul_lock * all users of ul_vnops_cnt increment and decrement it via atomic_add_long(). */ #include #include /* * ul_flag */ #define ULOCKFS_BUSY 0x00000001 /* ul_fs_lock is being set */ #define ULOCKFS_NOIACC 0x00000004 /* don't keep access times */ #define ULOCKFS_NOIDEL 0x00000008 /* don't free deleted files */ #define ULOCKFS_FALLOC 0x00000010 /* fallocate threads exist */ #define ULOCKFS_IS_BUSY(LF) ((LF)->ul_flag & ULOCKFS_BUSY) #define ULOCKFS_IS_NOIACC(LF) ((LF)->ul_flag & ULOCKFS_NOIACC) #define ULOCKFS_IS_NOIDEL(LF) ((LF)->ul_flag & ULOCKFS_NOIDEL) #define ULOCKFS_IS_FALLOC(LF) ((LF)->ul_flag & ULOCKFS_FALLOC) #define ULOCKFS_CLR_BUSY(LF) ((LF)->ul_flag &= ~ULOCKFS_BUSY) #define ULOCKFS_SET_BUSY(LF) ((LF)->ul_flag |= ULOCKFS_BUSY) #define ULOCKFS_CLR_FALLOC(LF) ((LF)->ul_flag &= ~ULOCKFS_FALLOC) #define ULOCKFS_SET_FALLOC(LF) ((LF)->ul_flag |= ULOCKFS_FALLOC) /* * ul_fs_mod */ #define ULOCKFS_SET_MOD(LF) ((LF)->ul_fs_mod = 1) #define ULOCKFS_CLR_MOD(LF) ((LF)->ul_fs_mod = 0) #define ULOCKFS_IS_MOD(LF) ((LF)->ul_fs_mod) /* * ul_fs_lock * * softlock will temporarily block most ufs_vnodeops. * it is used so that a waiting lockfs command will not be starved * * fwlock will block other fallocate threads wanting to obtain a write lock * on the file system. */ #define ULOCKFS_ULOCK ((1 << LOCKFS_ULOCK)) /* unlock */ #define ULOCKFS_WLOCK ((1 << LOCKFS_WLOCK)) /* write lock */ #define ULOCKFS_NLOCK ((1 << LOCKFS_NLOCK)) /* name lock */ #define ULOCKFS_DLOCK ((1 << LOCKFS_DLOCK)) /* delete lock */ #define ULOCKFS_HLOCK ((1 << LOCKFS_HLOCK)) /* hard lock */ #define ULOCKFS_ELOCK ((1 << LOCKFS_ELOCK)) /* error lock */ #define ULOCKFS_ROELOCK ((1 << LOCKFS_ROELOCK)) /* error lock (read-only) */ /* Maximum number of LOCKFS lockfs defined in sys/lockfs.h are 6 */ #define ULOCKFS_FWLOCK (1 << (LOCKFS_MAXLOCK + 1)) /* fallocate write lock */ #define ULOCKFS_SLOCK 0x80000000 /* soft lock */ #define ULOCKFS_IS_WLOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_WLOCK) #define ULOCKFS_IS_HLOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_HLOCK) #define ULOCKFS_IS_ELOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_ELOCK) #define ULOCKFS_IS_ROELOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_ROELOCK) #define ULOCKFS_IS_ULOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_ULOCK) #define ULOCKFS_IS_NLOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_NLOCK) #define ULOCKFS_IS_DLOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_DLOCK) #define ULOCKFS_IS_SLOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_SLOCK) #define ULOCKFS_IS_FWLOCK(LF) ((LF)->ul_fs_lock & ULOCKFS_FWLOCK) #define ULOCKFS_IS_JUSTULOCK(LF) \ (((LF)->ul_fs_lock & (ULOCKFS_SLOCK | ULOCKFS_ULOCK)) == ULOCKFS_ULOCK) #define ULOCKFS_SET_SLOCK(LF) ((LF)->ul_fs_lock |= ULOCKFS_SLOCK) #define ULOCKFS_CLR_SLOCK(LF) ((LF)->ul_fs_lock &= ~ULOCKFS_SLOCK) #define ULOCKFS_SET_FWLOCK(LF) ((LF)->ul_fs_lock |= ULOCKFS_FWLOCK) #define ULOCKFS_CLR_FWLOCK(LF) ((LF)->ul_fs_lock &= ~ULOCKFS_FWLOCK) #define ULOCKFS_READ_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_WRITE_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) /* used by both ufs_getattr and ufs_getsecattr */ #define ULOCKFS_GETATTR_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) /* used by both ufs_setattr and ufs_setsecattr */ #define ULOCKFS_SETATTR_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_ACCESS_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_LOOKUP_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_CREATE_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_REMOVE_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK | \ ULOCKFS_NLOCK | ULOCKFS_DLOCK) #define ULOCKFS_LINK_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_RENAME_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_SLOCK | ULOCKFS_WLOCK | \ ULOCKFS_ROELOCK | ULOCKFS_NLOCK) #define ULOCKFS_MKDIR_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_RMDIR_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK | \ ULOCKFS_NLOCK | ULOCKFS_DLOCK) #define ULOCKFS_READDIR_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_SYMLINK_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_READLINK_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_FSYNC_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_FID_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_RWLOCK_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_RWUNLOCK_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_SEEK_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_FRLOCK_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_SPACE_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_FALLOCATE_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | \ ULOCKFS_WLOCK | ULOCKFS_FWLOCK) #define ULOCKFS_QUOTA_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) /* GETPAGE breaks up into two masks */ #define ULOCKFS_GETREAD_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_GETWRITE_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_MAP_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_FIODUTIMES_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_FIODIO_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) #define ULOCKFS_FIODIOS_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_PATHCONF_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_VGET_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK) #define ULOCKFS_DELETE_MASK (ULOCKFS_HLOCK | ULOCKFS_ELOCK | \ ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK) struct ulockfs { ulong_t ul_flag; /* flags */ ulong_t ul_fs_lock; /* current file system lock state */ ulong_t ul_fs_mod; /* for test; fs was modified */ ulong_t ul_vnops_cnt; /* # of active ufs vnops outstanding */ kmutex_t ul_lock; /* mutex to protect ulockfs structure */ kcondvar_t ul_cv; kthread_id_t ul_sbowner; /* thread than can write superblock */ struct lockfs ul_lockfs; /* ioctl lock struct */ ulong_t ul_falloc_cnt; /* # of on-going fallocate ops */ }; extern ulong_t ufs_quiesce_pend; #define VTOUL(VP) \ ((struct ulockfs *) \ &((struct ufsvfs *)((VP)->v_vfsp->vfs_data))->vfs_ulockfs) #define ITOUL(IP) ((struct ulockfs *)&((IP)->i_ufsvfs->vfs_ulockfs)) #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_LOCKFS_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_UFS_LOG_H #define _SYS_FS_UFS_LOG_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct lufs_save { buf_t *sv_bp; size_t sv_nb_left; int sv_error; } lufs_save_t; typedef struct lufs_buf { buf_t lb_buf; void *lb_ptr; } lufs_buf_t; /* * Log space is stored as extents */ #define LUFS_EXTENTS (UINT32_C(0)) #define LS_SECTORS 2 typedef struct extent { uint32_t lbno; /* Logical block # within the space */ uint32_t pbno; /* Physical block number of extent. */ /* in disk blocks for non-MTB ufs */ /* in frags for MTB ufs */ uint32_t nbno; /* # blocks in this extent */ } extent_t; typedef struct ic_extent { uint32_t ic_lbno; /* Logical block # within the space */ uint32_t ic_nbno; /* # blocks in this extent */ daddr_t ic_pbno; /* Physical block number of extent. */ /* (always in disk blocks) */ } ic_extent_t; typedef struct extent_block { uint32_t type; /* Set to LUFS_EXTENTS to identify */ /* structure on disk. */ int32_t chksum; /* Checksum over entire block. */ uint32_t nextents; /* Size of extents array. */ uint32_t nbytes; /* # bytes mapped by extent_block. */ uint32_t nextbno; /* blkno of next extent_block. */ extent_t extents[1]; } extent_block_t; typedef struct ic_extent_block { uint32_t ic_nextents; /* Size of extents array. */ uint32_t ic_nbytes; /* # bytes mapped by extent_block. */ uint32_t ic_nextbno; /* blkno of next extent_block. */ ic_extent_t ic_extents[1]; } ic_extent_block_t; /* * Don't size the incore buffers too small or too large */ #define LDL_MINTRANSFER (UINT32_C(32768)) /* 32 k */ #define LDL_MAXTRANSFER (UINT32_C(1048576)) /* 1 M */ /* * LDL_DIVISOR (ldl_divisor) is the number to calculate the log size * from the file system size according to the calculation in lufs_enable() */ #define LDL_DIVISOR 1024 /* 1024 gives 1MB per 1GB */ /* * This gives the maximum size of log for which the 1MB per 1GB rule * applies. The size of the log will only be greater than this based * on the cylinder group space requirements. */ #define LDL_SOFTLOGCAP (256 * 1024 * 1024) /* * But set reasonable min/max units */ #define LDL_MINLOGSIZE (1024 * 1024) #define LDL_MAXLOGSIZE (512 * 1024 * 1024) /* * Log space requirement per cylinder group. This needs to accommodate a * cg delta (inc. header) and have a factor to cover other deltas involved * in a single transaction which could touch all cyl groups in a file system. */ #define LDL_CGSIZEREQ(fs) \ ((fs)->fs_cgsize + ((fs)->fs_cgsize >> 1)) #define LDL_MINBUFSIZE (32 * 1024) #define LDL_USABLE_BSIZE (DEV_BSIZE - sizeof (sect_trailer_t)) #define NB_LEFT_IN_SECTOR(off) (LDL_USABLE_BSIZE - ((off) - dbtob(btodb(off)))) typedef struct cirbuf { buf_t *cb_bp; /* buf's with space in circular buf */ buf_t *cb_dirty; /* filling this buffer for log write */ buf_t *cb_free; /* free bufs list */ caddr_t cb_va; /* address of circular buffer */ size_t cb_nb; /* size of circular buffer */ krwlock_t cb_rwlock; /* r/w lock to protect list mgmt. */ } cirbuf_t; #define LUFS_VERSION (UINT32_C(1)) /* Version 1 */ #define LUFS_VERSION_LATEST LUFS_VERSION /* * The old Disksuite unit structure has been split into two parts -- the * incore part which is created at run time and the ondisk structure. To * minimize code changes, the incore structure retains the old name, * ml_unit_t and the ondisk structure is called ml_odunit_t. The ondisk * structure is stored at the beginning of the log. * * This structure must fit into a sector (512b) * */ typedef struct ml_odunit { uint32_t od_version; /* version number */ uint32_t od_badlog; /* is the log okay? */ uint32_t od_unused1; /* * Important constants */ uint32_t od_maxtransfer; /* max transfer in bytes */ uint32_t od_devbsize; /* device bsize */ int32_t od_bol_lof; /* byte offset to begin of log */ int32_t od_eol_lof; /* byte offset to end of log */ /* * The disk space is split into state and circular log */ uint32_t od_requestsize; /* size requested by user */ uint32_t od_statesize; /* size of state area in bytes */ uint32_t od_logsize; /* size of log area in bytes */ int32_t od_statebno; /* first block of state area */ int32_t od_unused2; /* * Head and tail of log */ int32_t od_head_lof; /* byte offset of head */ uint32_t od_head_ident; /* head sector id # */ int32_t od_tail_lof; /* byte offset of tail */ uint32_t od_tail_ident; /* tail sector id # */ uint32_t od_chksum; /* checksum to verify ondisk contents */ /* * Used for error recovery */ uint32_t od_head_tid; /* used for logscan; set at sethead */ /* * Debug bits */ int32_t od_debug; /* * Misc */ struct timeval od_timestamp; /* time of last state change */ } ml_odunit_t; typedef struct ml_unit { struct ml_unit *un_next; /* next incore log */ int un_flags; /* Incore state */ buf_t *un_bp; /* contains memory for un_ondisk */ struct ufsvfs *un_ufsvfs; /* backpointer to ufsvfs */ dev_t un_dev; /* for convenience */ ic_extent_block_t *un_ebp; /* block of extents */ size_t un_nbeb; /* # bytes used by *un_ebp */ struct mt_map *un_deltamap; /* deltamap */ struct mt_map *un_logmap; /* logmap includes moby trans stuff */ struct mt_map *un_matamap; /* optional - matamap */ /* * Used for managing transactions */ uint32_t un_maxresv; /* maximum reservable space */ uint32_t un_resv; /* reserved byte count for this trans */ uint32_t un_resv_wantin; /* reserved byte count for next trans */ /* * Used during logscan */ uint32_t un_tid; /* * Read/Write Buffers */ cirbuf_t un_rdbuf; /* read buffer space */ cirbuf_t un_wrbuf; /* write buffer space */ /* * Ondisk state */ ml_odunit_t un_ondisk; /* ondisk log information */ /* * locks */ kmutex_t un_log_mutex; /* allows one log write at a time */ kmutex_t un_state_mutex; /* only 1 state update at a time */ } ml_unit_t; /* * Macros to allow access to the ondisk elements via the ml_unit_t incore * structure. */ #define un_version un_ondisk.od_version #define un_badlog un_ondisk.od_badlog #define un_maxtransfer un_ondisk.od_maxtransfer #define un_devbsize un_ondisk.od_devbsize #define un_bol_lof un_ondisk.od_bol_lof #define un_eol_lof un_ondisk.od_eol_lof #define un_statesize un_ondisk.od_statesize #define un_logsize un_ondisk.od_logsize #define un_statebno un_ondisk.od_statebno #define un_requestsize un_ondisk.od_requestsize #define un_head_lof un_ondisk.od_head_lof #define un_head_ident un_ondisk.od_head_ident #define un_tail_lof un_ondisk.od_tail_lof #define un_tail_ident un_ondisk.od_tail_ident #define un_chksum un_ondisk.od_chksum #define un_head_tid un_ondisk.od_head_tid #define un_debug un_ondisk.od_debug #define un_timestamp un_ondisk.od_timestamp /* * un_flags */ #define LDL_SCAN 0x0001 /* log scan in progress */ #define LDL_ERROR 0x0002 /* in error state */ #define LDL_NOROLL 0x0004 /* Log Not Yet Rollable */ typedef struct sect_trailer { uint32_t st_tid; /* transaction id */ uint32_t st_ident; /* unique sector id */ } sect_trailer_t; /* * map block */ #define MAPBLOCKSIZE (8192) #define MAPBLOCKSHIFT (13) #define MAPBLOCKOFF (MAPBLOCKSIZE-1) #define MAPBLOCKMASK (~MAPBLOCKOFF) #define DEV_BMASK (DEV_BSIZE - 1) /* * cached roll buffer */ typedef struct crb { int64_t c_mof; /* master file offset of buffer */ caddr_t c_buf; /* pointer to cached roll buffer */ uint32_t c_nb; /* size of buffer */ ushort_t c_refcnt; /* reference count on crb */ uchar_t c_invalid; /* crb should not be used */ } crb_t; #define CRB_END ((crb_t *)1) /* must be non zero */ /* * delta header */ struct delta { int64_t d_mof; /* byte offset on device to start writing */ /* delta */ int32_t d_nb; /* # bytes in the delta */ delta_t d_typ; /* Type of delta. Defined in ufs_trans.h */ }; /* * common map entry */ typedef struct mapentry mapentry_t; struct mapentry { /* * doubly linked list of all mapentries in map -- MUST BE FIRST */ mapentry_t *me_next; mapentry_t *me_prev; mapentry_t *me_hash; mapentry_t *me_agenext; mapentry_t *me_cancel; crb_t *me_crb; int (*me_func)(); ulong_t me_arg; ulong_t me_age; struct delta me_delta; uint32_t me_tid; off_t me_lof; ushort_t me_flags; }; #define me_mof me_delta.d_mof #define me_nb me_delta.d_nb #define me_dt me_delta.d_typ /* * me_flags */ #define ME_SCAN (0x0001) /* entry from log scan */ #define ME_HASH (0x0002) /* on hash list */ #define ME_CANCEL (0x0004) /* on cancel list */ #define ME_AGE (0x0008) /* on age list */ #define ME_LIST (0x0010) /* on list list */ #define ME_ROLL (0x0020) /* on pseudo-roll list */ #define ME_USER (0x0040) /* User Block DT_CANCEL entry */ /* * MAP TYPES */ enum maptypes { deltamaptype, logmaptype, matamaptype }; /* * MAP */ #define DELTAMAP_NHASH (512) #define LOGMAP_NHASH (2048) #define MAP_INDEX(mof, mtm) \ (((mof) >> MAPBLOCKSHIFT) & (mtm->mtm_nhash-1)) #define MAP_HASH(mof, mtm) \ ((mtm)->mtm_hash + MAP_INDEX((mof), (mtm))) typedef struct mt_map { /* * anchor doubly linked list this map's entries -- MUST BE FIRST */ mapentry_t *mtm_next; mapentry_t *mtm_prev; enum maptypes mtm_type; /* map type */ int mtm_flags; /* generic flags */ int mtm_ref; /* PTE like ref bit */ ulong_t mtm_debug; /* set at create time */ ulong_t mtm_age; /* mono-inc; tags mapentries */ mapentry_t *mtm_cancel; /* to be canceled at commit */ ulong_t mtm_nhash; /* # of hash anchors */ mapentry_t **mtm_hash; /* array of singly linked lists */ struct topstats *mtm_tops; /* trans ops - enabled by an ioctl */ long mtm_nme; /* # of mapentries */ long mtm_nmet; /* # of mapentries this transaction */ long mtm_cfrags; /* Canceled frags */ long mtm_cfragmax; /* Maximum canceled frags */ /* * used after logscan to set the log's tail */ off_t mtm_tail_lof; size_t mtm_tail_nb; /* * debug field for Scan test */ off_t mtm_trimlof; /* log was trimmed to this lof */ off_t mtm_trimtail; /* tail lof before trimming */ off_t mtm_trimalof; /* lof of last allocation delta */ off_t mtm_trimclof; /* lof of last commit delta */ off_t mtm_trimrlof; /* lof of last rolled delta */ ml_unit_t *mtm_ul; /* log unit for this map */ /* * moby trans stuff */ uint32_t mtm_tid; uint32_t mtm_committid; ushort_t mtm_closed; ushort_t mtm_seq; long mtm_wantin; long mtm_active; long mtm_activesync; ulong_t mtm_dirty; kmutex_t mtm_lock; kcondvar_t mtm_cv_commit; kcondvar_t mtm_cv_next; kcondvar_t mtm_cv_eot; /* * mutex that protects all the fields in mt_map except * mtm_mapnext and mtm_refcnt */ kmutex_t mtm_mutex; /* * logmap only condition variables */ kcondvar_t mtm_to_roll_cv; /* roll log or kill roll thread */ kcondvar_t mtm_from_roll_cv; /* log rolled or thread exiting */ /* * rw lock for the agenext mapentry field */ krwlock_t mtm_rwlock; /* * DEBUG: runtestscan */ kmutex_t mtm_scan_mutex; /* * logmap only taskq sync count variable, protected by mtm_lock. * keeps track of the number of pending top_issue_sync * dispatches. */ int mtm_taskq_sync_count; /* * logmap only condition variable, to synchronize with lufs_unsnarf. */ kcondvar_t mtm_cv; } mt_map_t; /* * mtm_flags */ #define MTM_ROLL_EXIT 0x00000001 /* force roll thread to exit */ #define MTM_ROLL_RUNNING 0x00000002 /* roll thread is running */ #define MTM_FORCE_ROLL 0x00000004 /* force at least one roll cycle */ #define MTM_ROLLING 0x00000008 /* currently rolling the log */ #define MTM_CANCELED 0x00000010 /* cancel entries were removed */ /* * Generic range checking macros */ #define OVERLAP(sof, snb, dof, dnb) \ (((sof) >= (dof) && (sof) < ((dof) + (dnb))) || \ ((dof) >= (sof) && (dof) < ((sof) + (snb)))) #define WITHIN(sof, snb, dof, dnb) \ (((sof) >= (dof)) && (((sof) + (snb)) <= ((dof) + (dnb)))) #define DATAoverlapME(mof, hnb, me) \ (OVERLAP((mof), (hnb), (me)->me_mof, (me)->me_nb)) #define MEwithinDATA(me, mof, hnb) \ (WITHIN((me)->me_mof, (me)->me_nb, (mof), (hnb))) #define DATAwithinME(mof, hnb, me) \ (WITHIN((mof), (hnb), (me)->me_mof, (me)->me_nb)) #define DATAwithinCRB(mof, nb, crb) \ (WITHIN((mof), (nb), (crb)->c_mof, (crb)->c_nb)) /* * TRANSACTION OPS STATS */ typedef struct topstats { uint64_t mtm_top_num[TOP_MAX]; uint64_t mtm_top_size_etot[TOP_MAX]; uint64_t mtm_top_size_rtot[TOP_MAX]; uint64_t mtm_top_size_max[TOP_MAX]; uint64_t mtm_top_size_min[TOP_MAX]; uint64_t mtm_delta_num[DT_MAX]; } topstats_t; /* * fio_lufs_stats_t is used by _FIO_GET_TOP_STATS ioctl for getting topstats */ typedef struct fio_lufs_stats { uint32_t ls_debug; /* out: un_debug value */ uint32_t _ls_pad; /* make size 64-bit aligned on x86 */ topstats_t ls_topstats; /* out: transaction stats */ } fio_lufs_stats_t; /* * roll buf structure; one per roll buffer */ typedef uint16_t rbsecmap_t; typedef struct rollbuf { buf_t rb_bh; /* roll buffer header */ struct rollbuf *rb_next; /* link for mof ordered roll bufs */ crb_t *rb_crb; /* cached roll buffer to roll */ mapentry_t *rb_age; /* age list */ rbsecmap_t rb_secmap; /* sector map */ } rollbuf_t; /* * un_debug * MT_TRANSACT - keep per thread accounting of tranactions * MT_MATAMAP - double check deltas and ops against matamap * MT_WRITE_CHECK - check master+deltas against metadata write * MT_LOG_WRITE_CHECK - read after write for log writes * MT_CHECK_MAP - check map after every insert/delete * MT_TRACE - trace transactions (used with MT_TRANSACT) * MT_SIZE - fail on size errors (used with MT_TRANSACT) * MT_NOASYNC - force every op to be sync * MT_FORCEROLL - forcibly roll the log after every commit * MT_SCAN - running runtestscan; special case as needed */ #define MT_NONE (0x00000000) #define MT_TRANSACT (0x00000001) #define MT_MATAMAP (0x00000002) #define MT_WRITE_CHECK (0x00000004) #define MT_LOG_WRITE_CHECK (0x00000008) #define MT_CHECK_MAP (0x00000010) #define MT_TRACE (0x00000020) #define MT_SIZE (0x00000040) #define MT_NOASYNC (0x00000080) #define MT_FORCEROLL (0x00000100) #define MT_SCAN (0x00000200) struct logstats { kstat_named_t ls_lreads; /* master reads */ kstat_named_t ls_lwrites; /* master writes */ kstat_named_t ls_lreadsinmem; /* log reads in memory */ kstat_named_t ls_ldlreads; /* log reads */ kstat_named_t ls_ldlwrites; /* log writes */ kstat_named_t ls_mreads; /* log master reads */ kstat_named_t ls_rreads; /* log roll reads */ kstat_named_t ls_rwrites; /* log roll writes */ }; #ifdef _KERNEL typedef struct threadtrans { ulong_t deltas_size; /* size of deltas this transaction */ uint32_t last_async_tid; /* last async transaction id */ uchar_t any_deltas; /* any deltas done this transaction */ #ifdef DEBUG uint_t topid; /* transaction type */ ulong_t esize; /* estimated trans size */ ulong_t rsize; /* real trans size */ dev_t dev; /* device */ #endif /* DEBUG */ } threadtrans_t; /* * Log layer protos -- lufs_log.c */ extern void ldl_strategy(ml_unit_t *, buf_t *); extern void ldl_round_commit(ml_unit_t *); extern void ldl_push_commit(ml_unit_t *); extern int ldl_need_commit(ml_unit_t *); extern int ldl_has_space(ml_unit_t *, mapentry_t *); extern void ldl_write(ml_unit_t *, caddr_t, offset_t, mapentry_t *); extern void ldl_waito(ml_unit_t *); extern int ldl_read(ml_unit_t *, caddr_t, offset_t, off_t, mapentry_t *); extern void ldl_sethead(ml_unit_t *, off_t, uint32_t); extern void ldl_settail(ml_unit_t *, off_t, size_t); extern ulong_t ldl_logscan_nbcommit(off_t); extern int ldl_logscan_read(ml_unit_t *, off_t *, size_t, caddr_t); extern void ldl_logscan_begin(ml_unit_t *); extern void ldl_logscan_end(ml_unit_t *); extern int ldl_need_roll(ml_unit_t *); extern void ldl_seterror(ml_unit_t *, char *); extern size_t ldl_bufsize(ml_unit_t *); extern void ldl_savestate(ml_unit_t *); extern void free_cirbuf(cirbuf_t *); extern void alloc_rdbuf(cirbuf_t *, size_t, size_t); extern void alloc_wrbuf(cirbuf_t *, size_t); /* * trans driver layer -- lufs.c */ extern int trans_not_wait(struct buf *cb); extern int trans_not_done(struct buf *cb); extern int trans_wait(struct buf *cb); extern int trans_done(struct buf *cb); extern void lufs_strategy(ml_unit_t *, buf_t *); extern void lufs_read_strategy(ml_unit_t *, buf_t *); extern void lufs_write_strategy(ml_unit_t *, buf_t *); extern void lufs_init(void); extern uint32_t lufs_hd_genid(const ml_unit_t *); extern int lufs_enable(struct vnode *, struct fiolog *, cred_t *); extern int lufs_disable(vnode_t *, struct fiolog *); /* * transaction op layer -- lufs_top.c */ extern void _init_top(void); extern int top_read_roll(rollbuf_t *, ml_unit_t *); /* * map layer -- lufs_map.c */ extern void map_free_entries(mt_map_t *); extern int matamap_overlap(mt_map_t *, offset_t, off_t); extern int matamap_within(mt_map_t *, offset_t, off_t); extern int deltamap_need_commit(mt_map_t *); extern void deltamap_add(mt_map_t *, offset_t, off_t, delta_t, int (*)(), ulong_t, threadtrans_t *tp); extern mapentry_t *deltamap_remove(mt_map_t *, offset_t, off_t); extern void deltamap_del(mt_map_t *, offset_t, off_t); extern void deltamap_push(ml_unit_t *); extern void logmap_cancel_remove(mt_map_t *); extern int logmap_need_commit(mt_map_t *); extern int logmap_need_roll_async(mt_map_t *); extern int logmap_need_roll_sync(mt_map_t *); extern void logmap_start_roll(ml_unit_t *); extern void logmap_kill_roll(ml_unit_t *); extern void logmap_forceroll(mt_map_t *); extern void logmap_forceroll_nowait(mt_map_t *); extern int logmap_overlap(mt_map_t *, offset_t, off_t); extern void logmap_remove_roll(mt_map_t *, offset_t, off_t); extern int logmap_next_roll(mt_map_t *, offset_t *); extern int logmap_list_get(mt_map_t *, offset_t, off_t, mapentry_t **); extern int logmap_list_get_roll(mt_map_t *, offset_t, rollbuf_t *); extern void logmap_list_put(mt_map_t *, mapentry_t *); extern void logmap_list_put_roll(mt_map_t *, mapentry_t *); extern int logmap_setup_read(mapentry_t *, rollbuf_t *); extern void logmap_make_space(struct mt_map *, ml_unit_t *, mapentry_t *); extern void logmap_add(ml_unit_t *, char *, offset_t, mapentry_t *); extern void logmap_add_buf(ml_unit_t *, char *, offset_t, mapentry_t *, caddr_t, uint32_t); extern void logmap_commit(ml_unit_t *, uint32_t); extern void logmap_sethead(mt_map_t *, ml_unit_t *); extern void logmap_settail(mt_map_t *, ml_unit_t *); extern void logmap_roll_dev(ml_unit_t *ul); extern void logmap_cancel(ml_unit_t *, offset_t, off_t, int); extern void logmap_free_cancel(mt_map_t *, mapentry_t **); extern int logmap_iscancel(mt_map_t *, offset_t, off_t); extern void logmap_logscan(ml_unit_t *); extern mt_map_t *map_put(mt_map_t *); extern mt_map_t *map_get(ml_unit_t *, enum maptypes, int); extern void _init_map(void); /* * scan and roll threads -- lufs_thread.c */ extern void trans_roll(ml_unit_t *); /* * DEBUG */ #ifdef DEBUG extern int map_put_debug(mt_map_t *); extern int map_get_debug(ml_unit_t *, mt_map_t *); extern int top_write_debug(ml_unit_t *, mapentry_t *, offset_t, off_t); extern int matamap_overlap(mt_map_t *, offset_t, off_t); extern int ldl_sethead_debug(ml_unit_t *); extern int map_check_linkage(mt_map_t *); extern int logmap_logscan_debug(mt_map_t *, mapentry_t *); extern int map_check_ldl_write(ml_unit_t *, caddr_t, offset_t, mapentry_t *); extern int logmap_logscan_commit_debug(off_t, mt_map_t *); extern int logmap_logscan_add_debug(struct delta *, mt_map_t *); extern int top_delta_debug(ml_unit_t *, offset_t, off_t, delta_t); extern int top_begin_debug(ml_unit_t *, top_t, ulong_t); extern int top_end_debug(ml_unit_t *, mt_map_t *, top_t, ulong_t); extern int top_roll_debug(ml_unit_t *); extern int top_init_debug(void); extern int lufs_initialize_debug(ml_odunit_t *); #endif /* DEBUG */ extern uint64_t delta_stats[DT_MAX]; extern uint64_t roll_stats[DT_MAX]; extern struct logstats logstats; extern int ufs_crb_enable; extern uint_t topkey; extern uint32_t ufs_ncg_log; extern uint_t lufs_debug; #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_LOG_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1991, 1996-1999 by Sun Microsystems, Inc. * All rights reserved. */ #ifndef _SYS_FS_UFS_MOUNT_H #define _SYS_FS_UFS_MOUNT_H #ifdef __cplusplus extern "C" { #endif #include struct ufs_args { int flags; }; /* * UFS mount option flags */ #define UFSMNT_NOINTR 0x00000001 /* disallow interrupts on lockfs */ #define UFSMNT_SYNCDIR 0x00000002 /* synchronous local directory ops */ #define UFSMNT_NOSETSEC 0x00000004 /* disallow use of ufs_setsecattr */ #define UFSMNT_LARGEFILES 0x00000008 /* allow large files */ #define UFSMNT_NOATIME 0x00001000 /* disable updates of i_atime */ /* deferred inode time */ #define UFSMNT_NODFRATIME 0x00002000 /* no deferred access time */ /* action to take when internal inconsistency is detected */ #define UFSMNT_ONERROR_PANIC 0x00000020 /* forced system shutdown */ #define UFSMNT_ONERROR_LOCK 0x00000040 /* error lock the fs */ #define UFSMNT_ONERROR_UMOUNT 0x00000080 /* forced umount of the fs */ #define UFSMNT_ONERROR_FLGMASK 0x000000E0 /* default action is to repair fs */ #define UFSMNT_ONERROR_DEFAULT UFSMNT_ONERROR_PANIC #define UFSMNT_DISABLEDIRECTIO 0x00000100 /* disable directio ioctls */ /* Force DirectIO */ #define UFSMNT_FORCEDIRECTIO 0x00000200 /* directio for all files */ #define UFSMNT_NOFORCEDIRECTIO 0x00000400 /* no directio for all files */ /* logging */ #define UFSMNT_LOGGING 0x00000800 /* enable logging */ #define UFSMNT_ONERROR_PANIC_STR "panic" #define UFSMNT_ONERROR_LOCK_STR "lock" #define UFSMNT_ONERROR_UMOUNT_STR "umount" #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_MOUNT_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_UFS_PANIC_H #define _SYS_FS_UFS_PANIC_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif #if defined(_KERNEL) /* * failures have an associated state * making them bit values simplifies state transition validity checking */ typedef enum ufs_failure_states { /* initial states, set mostly by thread encountering failure */ UF_UNDEF = 0x0000, /* freshly-allocated memory */ UF_INIT = 0x0001, /* being created */ UF_QUEUE = 0x0002, /* queued for fix thread */ /* transitional states, set mostly by fix failure thread */ UF_TRYLCK = 0x0010, /* attempting to be locked */ UF_LOCKED = 0x0020, /* error lock set */ UF_UMOUNT = 0x0040, /* attempting to be unmounted */ UF_FIXING = 0x0080, /* fsck started; attempting unlock */ /* terminal states, once in this state, fix failure thread is done */ UF_FIXED = 0x0100, /* no problemo, man */ UF_NOTFIX = 0x0200, /* can't fix; shouldn't panic */ UF_REPLICA = 0x0400, /* replica panic; fix original only */ UF_PANIC = 0x0800, /* gave up/exceeded limits/can't fix */ /* not strictly a terminal state, */ /* because we will do some actions */ /* if we find a failure in this state */ /* but those actions will be terminal */ /* handy, but used only as terminators and placeholders */ UF_ILLEGAL = 0xffff, /* invalid state */ UF_ALLSTATES = 0x0ff3 /* all possible state */ } ufs_failure_states_t; /* * each manifestation of a fault (ie. "panic") is * associated with a distinct ufs_failure event */ typedef struct ufs_failure { struct ufs_failure *uf_chain[2]; /* protected by ufs_elock mux */ struct ufs_failure *uf_orig; /* if duplicate event, */ /* here's the original */ struct ufs_failure *uf_master; /* if sharing a logged device */ /* here's the master failure */ struct buf *uf_bp; /* ptr to buf containing sb */ kmutex_t *uf_vfs_lockp; /* ptr to vfs_lock */ struct vfs_ufsfx *uf_vfs_ufsfxp; /* ptr to fix-on-panic per fs */ struct vfs *uf_vfsp; /* ptr to vfs */ struct ufsvfs *uf_ufsvfsp; /* to match if unmounted */ dev_t uf_dev; /* device id */ ufs_failure_states_t uf_s; /* current failure state */ int uf_flags; /* internal flags */ time_t uf_begin_tm; /* when did panic begin? */ time_t uf_end_tm; /* ... end? */ time_t uf_entered_tm; /* ... was state entered? */ struct lockfs uf_lf; /* needed to set lockfs lock */ int uf_lf_err; /* errno if lockfs fails */ long uf_retry; /* seconds */ unsigned uf_counter; /* of state-specific actions */ kmutex_t uf_mutex; /* protects struct body */ char uf_fsname[MAXMNTLEN]; /* for post-unmount errors */ /* after ufsvfsp is free'd */ char uf_panic_str[LOCKFS_MAXCOMMENTLEN]; /* original panic message */ /* XXX could be smaller */ } ufs_failure_t; #define uf_next uf_chain[0] #define uf_prev uf_chain[1] #define uf_fs uf_bp->b_un.b_fs /* * per-filesystem panic event state */ typedef struct vfs_ufsfx { long fx_flags; /* see ufs_panic.h for the */ ufs_failure_t *fx_current; /* currently being fixed */ } vfs_ufsfx_t; /* * External entry points * * ufs_fault(vnode_t *, char *fmt, ...) * replaces calls to cmn_err(CE_PANIC, char *fmt, ...) * The vnode is any vnode in the filesystem. * ufs_fault returns an errno to bubble up. * ufsfx_init() * is called at modload time to set global values etc. * ufsfx_mount() * is called at mount time to do per-fs initialization * returns 0 (ok) or errno * ufsfx_unmount() * is called at unmount time to prevent spinning on work * to fix an unmounted fs * ufsfx_lockfs() * ufsfx_unlockfs() * are called at upon (un)locking of a fs for coordination * ufsfx_get_failure_qlen() * is called by the hlock thread to coordinate with the fix * failure thread */ /*PRINTFLIKE2*/ int ufs_fault(vnode_t *, char *fmt, ...) __KPRINTFLIKE(2); void ufsfx_init(void); int ufsfx_mount(struct ufsvfs *, int); void ufsfx_unmount(struct ufsvfs *); void ufsfx_lockfs(struct ufsvfs *); void ufsfx_unlockfs(struct ufsvfs *); int ufsfx_get_failure_qlen(void); extern struct ufs_q ufs_fix; #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_PANIC_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2014 Garrett D'Amore * * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _SYS_FS_UFS_PROT_H #define _SYS_FS_UFS_PROT_H #include #ifdef __cplusplus extern "C" { #endif #include #include #include enum ufsdrc_t { UFSDRC_OK = 0, UFSDRC_NOENT = ENOENT, UFSDRC_PERM = EPERM, UFSDRC_INVAL = EINVAL, UFSDRC_NOEXEC = ENOEXEC, UFSDRC_NODEV = ENODEV, UFSDRC_NXIO = ENXIO, UFSDRC_BUSY = EBUSY, UFSDRC_OPNOTSUP = EOPNOTSUPP, UFSDRC_EXECERR = 254, UFSDRC_ERR = 255 }; typedef enum ufsdrc_t ufsdrc_t; struct fs_identity_t { dev32_t fs_dev; char *fs_name; }; typedef struct fs_identity_t fs_identity_t; struct ufsd_repairfs_args_t { fs_identity_t ua_fsid; uint_t ua_attempts; }; typedef struct ufsd_repairfs_args_t ufsd_repairfs_args_t; struct ufsd_repairfs_list_t { int ual_listlen; ufsd_repairfs_args_t *ual_list; }; typedef struct ufsd_repairfs_list_t ufsd_repairfs_list_t; enum ufsd_event_t { UFSDEV_NONE = 0, UFSDEV_REBOOT = 0 + 1, UFSDEV_FSCK = 0 + 2, UFSDEV_LOG_OP = 0 + 3 }; typedef enum ufsd_event_t ufsd_event_t; enum ufsd_boot_type_t { UFSDB_NONE = 0, UFSDB_CLEAN = 0 + 1, UFSDB_POSTPANIC = 0 + 2 }; typedef enum ufsd_boot_type_t ufsd_boot_type_t; enum ufsd_log_op_t { UFSDLO_NONE = 0, UFSDLO_COMMIT = 0 + 1, UFSDLO_GET = 0 + 2, UFSDLO_PUT = 0 + 3, UFSDLO_RESET = 0 + 4 }; typedef enum ufsd_log_op_t ufsd_log_op_t; enum ufsd_fsck_state_t { UFSDFS_NONE = 0, UFSDFS_DISPATCH = 0 + 1, UFSDFS_ERREXIT = 0 + 2, UFSDFS_SUCCESS = 0 + 3 }; typedef enum ufsd_fsck_state_t ufsd_fsck_state_t; #define UFSD_VARMSGMAX 1024 #define UFSD_SPAREMSGBYTES 4 struct ufsd_log_data_t { int umld_eob; int umld_seq; struct { uint_t umld_buf_len; char *umld_buf_val; } umld_buf; }; typedef struct ufsd_log_data_t ufsd_log_data_t; struct ufsd_log_msg_t { ufsd_log_op_t um_lop; union { ufsd_log_data_t um_logdata; } ufsd_log_msg_t_u; }; typedef struct ufsd_log_msg_t ufsd_log_msg_t; struct ufsd_msg_vardata_t { ufsd_event_t umv_ev; union { ufsd_boot_type_t umv_b; ufsd_fsck_state_t umv_fs; ufsd_log_msg_t umv_lm; } ufsd_msg_vardata_t_u; }; typedef struct ufsd_msg_vardata_t ufsd_msg_vardata_t; struct ufsd_msg_t { time32_t um_time; uint_t um_from; struct { uint_t um_spare_len; char *um_spare_val; } um_spare; ufsd_msg_vardata_t um_var; }; typedef struct ufsd_msg_t ufsd_msg_t; #define UFSD_SERVNAME "ufsd" #define xdr_dev_t xdr_u_int #define xdr_time_t xdr_int /* * Set UFSD_THISVERS to the newest version of the protocol * This allows the preprocessor to force an error if the * protocol changes, since the kernel xdr routines may need to be * recoded. Note that we can't explicitly set the version to a * symbol as rpcgen will then create erroneous routine names. */ #define UFSD_V1 1 #define UFSD_ORIGVERS UFSD_V1 #define UFSD_THISVERS 1 #define UFSD_PROG ((unsigned long)(100233)) #define UFSD_VERS ((unsigned long)(1)) #define UFSD_NULL ((unsigned long)(0)) extern ufsdrc_t *ufsd_null_1(void *, CLIENT *); extern ufsdrc_t *ufsd_null_1_svc(void *, struct svc_req *); #define UFSD_REPAIRFS ((unsigned long)(1)) extern ufsdrc_t *ufsd_repairfs_1(ufsd_repairfs_args_t *, CLIENT *); extern ufsdrc_t * ufsd_repairfs_1_svc(ufsd_repairfs_args_t *, struct svc_req *); #define UFSD_REPAIRFSLIST ((unsigned long)(2)) extern ufsdrc_t *ufsd_repairfslist_1(ufsd_repairfs_list_t *, CLIENT *); extern ufsdrc_t * ufsd_repairfslist_1_svc(ufsd_repairfs_list_t *, struct svc_req *); #define UFSD_SEND ((unsigned long)(3)) extern ufsdrc_t *ufsd_send_1(ufsd_msg_t *, CLIENT *); extern ufsdrc_t *ufsd_send_1_svc(ufsd_msg_t *, struct svc_req *); #define UFSD_RECV ((unsigned long)(4)) extern ufsdrc_t *ufsd_recv_1(ufsd_msg_t *, CLIENT *); extern ufsdrc_t *ufsd_recv_1_svc(ufsd_msg_t *, struct svc_req *); #define UFSD_EXIT ((unsigned long)(5)) extern ufsdrc_t *ufsd_exit_1(void *, CLIENT *); extern ufsdrc_t *ufsd_exit_1_svc(void *, struct svc_req *); extern int ufsd_prog_1_freeresult(SVCXPRT *, xdrproc_t, caddr_t); /* the xdr functions */ extern bool_t xdr_ufsdrc_t(XDR *, ufsdrc_t *); extern bool_t xdr_fs_identity_t(XDR *, fs_identity_t *); extern bool_t xdr_ufsd_repairfs_args_t(XDR *, ufsd_repairfs_args_t *); extern bool_t xdr_ufsd_repairfs_list_t(XDR *, ufsd_repairfs_list_t *); extern bool_t xdr_ufsd_event_t(XDR *, ufsd_event_t *); extern bool_t xdr_ufsd_boot_type_t(XDR *, ufsd_boot_type_t *); extern bool_t xdr_ufsd_log_op_t(XDR *, ufsd_log_op_t *); extern bool_t xdr_ufsd_fsck_state_t(XDR *, ufsd_fsck_state_t *); extern bool_t xdr_ufsd_log_data_t(XDR *, ufsd_log_data_t *); extern bool_t xdr_ufsd_log_msg_t(XDR *, ufsd_log_msg_t *); extern bool_t xdr_ufsd_msg_vardata_t(XDR *, ufsd_msg_vardata_t *); extern bool_t xdr_ufsd_msg_t(XDR *, ufsd_msg_t *); #ifdef __cplusplus } #endif #endif /* !_SYS_FS_UFS_PROT_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 1999 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #ifndef _SYS_FS_UFS_QUOTA_H #define _SYS_FS_UFS_QUOTA_H #ifdef __cplusplus extern "C" { #endif /* * Lock order for the quota sub-system: * * vfs_dqrwlock > ip.i_contents > dq_cachelock > dquot.dq_lock > dq_freelock * vfs_dqrwlock > ip.i_contents > dq_cachelock > dq_freelock * vfs_dqrwlock > ip.i_contents > dquot.dq_lock > dq_freelock * vfs_dqrwlock > ip.i_contents > dq_freelock * vfs_dqrwlock > ip.i_contents > dq_cachelock > dquot.dq_lock > qip.i_contents */ /* * The following constants define the default amount of time given a user * before the soft limits are treated as hard limits (usually resulting * in an allocation failure). These may be modified by the quotactl * system call with the Q_SETQLIM or Q_SETQUOTA commands. */ #define DQ_FTIMELIMIT (7 * 24*60*60) /* 1 week */ #define DQ_BTIMELIMIT (7 * 24*60*60) /* 1 week */ /* * The dqblk structure defines the format of the disk quota file * (as it appears on disk) - the file is an array of these structures * indexed by user number. The setquota sys call establishes the inode * for each quota file (a pointer is retained in the mount structure). */ struct dqblk { uint32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ uint32_t dqb_bsoftlimit; /* preferred limit on disk blks */ uint32_t dqb_curblocks; /* current block count */ uint32_t dqb_fhardlimit; /* maximum # allocated files + 1 */ uint32_t dqb_fsoftlimit; /* preferred file limit */ uint32_t dqb_curfiles; /* current # allocated files */ uint32_t dqb_btimelimit; /* time limit for excessive disk use */ uint32_t dqb_ftimelimit; /* time limit for excessive files */ }; #define dqoff(UID) (((offset_t)(UID) * sizeof (struct dqblk))) /* * The dquot structure records disk usage for a user on a filesystem. * There is one allocated for each quota that exists on any filesystem * for the current user. A cache is kept of recently used entries. * Active inodes have a pointer to the dquot associated with them. */ struct dquot { struct dquot *dq_forw, *dq_back; /* hash list, MUST be first entry */ struct dquot *dq_freef, *dq_freeb; /* free list */ short dq_flags; #define DQ_ERROR 0x01 /* An error occurred reading dq */ #define DQ_MOD 0x04 /* this quota modified since read */ #define DQ_BLKS 0x10 /* has been warned about blk limit */ #define DQ_FILES 0x20 /* has been warned about file limit */ #define DQ_TRANS 0x40 /* logging ufs operation started */ ulong_t dq_cnt; /* count of active references */ uid_t dq_uid; /* user this applies to */ struct ufsvfs *dq_ufsvfsp; /* filesystem this relates to */ offset_t dq_mof; /* master disk offset of quota record */ struct dqblk dq_dqb; /* actual usage & quotas */ #ifdef _KERNEL kmutex_t dq_lock; /* per dq structure lock */ #endif /* _KERNEL */ }; #define dq_bhardlimit dq_dqb.dqb_bhardlimit #define dq_bsoftlimit dq_dqb.dqb_bsoftlimit #define dq_curblocks dq_dqb.dqb_curblocks #define dq_fhardlimit dq_dqb.dqb_fhardlimit #define dq_fsoftlimit dq_dqb.dqb_fsoftlimit #define dq_curfiles dq_dqb.dqb_curfiles #define dq_btimelimit dq_dqb.dqb_btimelimit #define dq_ftimelimit dq_dqb.dqb_ftimelimit /* * flags for vfs_qflags in ufsvfs struct */ #define MQ_ENABLED 0x01 /* quotas are enabled */ #if defined(_KERNEL) /* * dquot chach hash chain headers */ #define NDQHASH 64 /* smallish power of two */ #define DQHASH(uid, mp) \ (((uintptr_t)(mp) + (unsigned)(uid)) & (NDQHASH-1)) struct dqhead { struct dquot *dqh_forw; /* MUST be first */ struct dquot *dqh_back; /* MUST be second */ }; extern struct dqhead dqhead[NDQHASH]; extern struct dquot *dquot, *dquotNDQUOT; extern int ndquot; extern krwlock_t dq_rwlock; /* quota sub-system init lock */ extern int quotas_initialized; /* quota sub-system init flag */ extern void qtinit(); extern void qtinit2(); extern struct dquot *getinoquota(struct inode *); extern int chkdq(struct inode *ip, long, int, struct cred *, char **errp, size_t *lenp); extern int chkiq(struct ufsvfs *, int, struct inode *, uid_t, int, struct cred *, char **errp, size_t *lenp); extern void dqrele(struct dquot *); extern int closedq(struct ufsvfs *, struct cred *); extern int qsync(struct ufsvfs *); extern int getdiskquota(uid_t, struct ufsvfs *, int, struct dquot **); extern void dqput(struct dquot *); extern void dqupdate(struct dquot *); extern void dqinval(struct dquot *); extern void invalidatedq(struct ufsvfs *); extern int quotactl(struct vnode *, intptr_t, int flag, struct cred *); #endif /* _KERNEL */ /* * Definitions for the 'quotactl' system call. */ #define Q_QUOTAON 1 /* turn quotas on */ #define Q_QUOTAOFF 2 /* turn quotas off */ #define Q_SETQUOTA 3 /* set disk limits & usage */ #define Q_GETQUOTA 4 /* get disk limits & usage */ #define Q_SETQLIM 5 /* set disk limits only */ #define Q_SYNC 6 /* update disk copy of quota usages */ #define Q_ALLSYNC 7 /* update disk copy of quota usages for all */ #ifdef _SYSCALL32 /* ILP32 compatible structure for LP64 kernel. */ struct quotctl32 { int op; uid_t uid; uint32_t addr; }; #endif /* SYSCALL32 */ struct quotctl { int op; uid_t uid; caddr_t addr; }; #define Q_QUOTACTL 0x00030189 /* ioctl command for quotactl */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_QUOTA_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_UFS_SNAP_H #define _SYS_FS_UFS_SNAP_H #ifdef __cplusplus extern "C" { #endif #include #include #include /* debug levels */ #define UFSSNAPDB_CREATE 0x01 #define UFSSNAPDB_DELETE 0x02 /* Constants */ #define UFS_MAX_SNAPBACKFILESIZE (1LL << 39) /* 512 GB */ extern int ufs_snap_create(struct vnode *, struct fiosnapcreate_multi *, cred_t *); extern int ufs_snap_delete(struct vnode *, struct fiosnapdelete *, cred_t *); #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_SNAP_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2014 Garrett D'Amore * * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_FS_UFS_TRANS_H #define _SYS_FS_UFS_TRANS_H #ifdef __cplusplus extern "C" { #endif #include #include #include /* * Types of deltas */ typedef enum delta_type { DT_NONE, /* 0 no assigned type */ DT_SB, /* 1 superblock */ DT_CG, /* 2 cylinder group */ DT_SI, /* 3 summary info */ DT_AB, /* 4 allocation block */ DT_ABZERO, /* 5 a zero'ed allocation block */ DT_DIR, /* 6 directory */ DT_INODE, /* 7 inode */ DT_FBI, /* 8 fbiwrite */ DT_QR, /* 9 quota record */ DT_COMMIT, /* 10 commit record */ DT_CANCEL, /* 11 cancel record */ DT_BOT, /* 12 begin transaction */ DT_EOT, /* 13 end transaction */ DT_UD, /* 14 userdata */ DT_SUD, /* 15 userdata found during log scan */ DT_SHAD, /* 16 data for a shadow inode */ DT_MAX /* 17 maximum delta type */ } delta_t; /* * transaction operation types */ typedef enum top_type { TOP_READ_SYNC, /* 0 */ TOP_WRITE, /* 1 */ TOP_WRITE_SYNC, /* 2 */ TOP_SETATTR, /* 3 */ TOP_CREATE, /* 4 */ TOP_REMOVE, /* 5 */ TOP_LINK, /* 6 */ TOP_RENAME, /* 7 */ TOP_MKDIR, /* 8 */ TOP_RMDIR, /* 9 */ TOP_SYMLINK, /* 10 */ TOP_FSYNC, /* 11 */ TOP_GETPAGE, /* 12 */ TOP_PUTPAGE, /* 13 */ TOP_SBUPDATE_FLUSH, /* 14 */ TOP_SBUPDATE_UPDATE, /* 15 */ TOP_SBUPDATE_UNMOUNT, /* 16 */ TOP_SYNCIP_CLOSEDQ, /* 17 */ TOP_SYNCIP_FLUSHI, /* 18 */ TOP_SYNCIP_HLOCK, /* 19 */ TOP_SYNCIP_SYNC, /* 20 */ TOP_SYNCIP_FREE, /* 21 */ TOP_SBWRITE_RECLAIM, /* 22 */ TOP_SBWRITE_STABLE, /* 23 */ TOP_IFREE, /* 24 */ TOP_IUPDAT, /* 25 */ TOP_MOUNT, /* 26 */ TOP_COMMIT_ASYNC, /* 27 */ TOP_COMMIT_FLUSH, /* 28 */ TOP_COMMIT_UPDATE, /* 29 */ TOP_COMMIT_UNMOUNT, /* 30 */ TOP_SETSECATTR, /* 31 */ TOP_QUOTA, /* 32 */ TOP_ITRUNC, /* 33 */ TOP_ALLOCSP, /* 34 */ TOP_MAX /* 35 TOP_MAX MUST be the last entry */ } top_t; struct inode; struct ufsvfs; /* * vfs_log == NULL means not logging */ #define TRANS_ISTRANS(ufsvfsp) (ufsvfsp->vfs_log) /* * begin a synchronous transaction */ #define TRANS_BEGIN_SYNC(ufsvfsp, vid, vsize, error)\ {\ if (TRANS_ISTRANS(ufsvfsp)) { \ error = 0; \ top_begin_sync(ufsvfsp, vid, vsize, &error); \ } \ } /* * begin a asynchronous transaction */ #define TRANS_BEGIN_ASYNC(ufsvfsp, vid, vsize)\ {\ if (TRANS_ISTRANS(ufsvfsp))\ (void) top_begin_async(ufsvfsp, vid, vsize, 0); \ } /* * try to begin a asynchronous transaction */ #define TRANS_TRY_BEGIN_ASYNC(ufsvfsp, vid, vsize, err)\ {\ if (TRANS_ISTRANS(ufsvfsp))\ err = top_begin_async(ufsvfsp, vid, vsize, 1); \ else\ err = 0; \ } /* * Begin a synchronous or asynchronous transaction. * The lint case is needed because vsize can be a constant. */ #ifndef __lint #define TRANS_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize)\ {\ if (TRANS_ISTRANS(ufsvfsp)) {\ if (ufsvfsp->vfs_syncdir) {\ int error = 0; \ ASSERT(vsize); \ top_begin_sync(ufsvfsp, vid, vsize, &error); \ ASSERT(error == 0); \ issync = 1; \ } else {\ (void) top_begin_async(ufsvfsp, vid, vsize, 0); \ issync = 0; \ }\ }\ } #else /* __lint */ #define TRANS_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize)\ {\ if (TRANS_ISTRANS(ufsvfsp)) {\ if (ufsvfsp->vfs_syncdir) {\ int error = 0; \ top_begin_sync(ufsvfsp, vid, vsize, &error); \ issync = 1; \ } else {\ (void) top_begin_async(ufsvfsp, vid, vsize, 0); \ issync = 0; \ }\ }\ } #endif /* __lint */ /* * try to begin a synchronous or asynchronous transaction */ #define TRANS_TRY_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize, error)\ {\ if (TRANS_ISTRANS(ufsvfsp)) {\ if (ufsvfsp->vfs_syncdir) {\ ASSERT(vsize); \ top_begin_sync(ufsvfsp, vid, vsize, &error); \ ASSERT(error == 0); \ issync = 1; \ } else {\ error = top_begin_async(ufsvfsp, vid, vsize, 1); \ issync = 0; \ }\ }\ }\ /* * end a asynchronous transaction */ #define TRANS_END_ASYNC(ufsvfsp, vid, vsize)\ {\ if (TRANS_ISTRANS(ufsvfsp))\ top_end_async(ufsvfsp, vid, vsize); \ } /* * end a synchronous transaction */ #define TRANS_END_SYNC(ufsvfsp, error, vid, vsize)\ {\ if (TRANS_ISTRANS(ufsvfsp))\ top_end_sync(ufsvfsp, &error, vid, vsize); \ } /* * end a synchronous or asynchronous transaction */ #define TRANS_END_CSYNC(ufsvfsp, error, issync, vid, vsize)\ {\ if (TRANS_ISTRANS(ufsvfsp))\ if (issync)\ top_end_sync(ufsvfsp, &error, vid, vsize); \ else\ top_end_async(ufsvfsp, vid, vsize); \ } /* * record a delta */ #define TRANS_DELTA(ufsvfsp, mof, nb, dtyp, func, arg) \ if (TRANS_ISTRANS(ufsvfsp)) \ top_delta(ufsvfsp, (offset_t)(mof), nb, dtyp, func, arg) /* * cancel a delta */ #define TRANS_CANCEL(ufsvfsp, mof, nb, flags) \ if (TRANS_ISTRANS(ufsvfsp)) \ top_cancel(ufsvfsp, (offset_t)(mof), nb, flags) /* * log a delta */ #define TRANS_LOG(ufsvfsp, va, mof, nb, buf, bufsz) \ if (TRANS_ISTRANS(ufsvfsp)) \ top_log(ufsvfsp, va, (offset_t)(mof), nb, buf, bufsz) /* * check if a range is being canceled (converting from metadata into userdata) */ #define TRANS_ISCANCEL(ufsvfsp, mof, nb) \ ((TRANS_ISTRANS(ufsvfsp)) ? \ top_iscancel(ufsvfsp, (offset_t)(mof), nb) : 0) /* * put the log into error state */ #define TRANS_SETERROR(ufsvfsp) \ if (TRANS_ISTRANS(ufsvfsp)) \ top_seterror(ufsvfsp) /* * check if device has had an error */ #define TRANS_ISERROR(ufsvfsp) \ ((TRANS_ISTRANS(ufsvfsp)) ? \ ufsvfsp->vfs_log->un_flags & LDL_ERROR : 0) /* * The following macros provide a more readable interface to TRANS_DELTA */ #define TRANS_BUF(ufsvfsp, vof, nb, bp, type) \ TRANS_DELTA(ufsvfsp, \ ldbtob(bp->b_blkno) + (offset_t)(vof), nb, type, \ ufs_trans_push_buf, bp->b_blkno) #define TRANS_BUF_ITEM_128(ufsvfsp, item, base, bp, type) \ TRANS_BUF(ufsvfsp, \ (((uintptr_t)&(item)) & ~(128 - 1)) - (uintptr_t)(base), 128, bp, type) #define TRANS_INODE(ufsvfsp, ip) \ TRANS_DELTA(ufsvfsp, ip->i_doff, sizeof (struct dinode), \ DT_INODE, ufs_trans_push_inode, ip->i_number) /* * If ever parts of an inode except the timestamps are logged using * this macro (or any other technique), bootloader logging support must * be made aware of these changes. */ #define TRANS_INODE_DELTA(ufsvfsp, vof, nb, ip) \ TRANS_DELTA(ufsvfsp, (ip->i_doff + (offset_t)(vof)), \ nb, DT_INODE, ufs_trans_push_inode, ip->i_number) #define TRANS_INODE_TIMES(ufsvfsp, ip) \ TRANS_INODE_DELTA(ufsvfsp, (caddr_t)&ip->i_atime - (caddr_t)&ip->i_ic, \ sizeof (struct timeval32) * 3, ip) /* * Check if we need to log cylinder group summary info. */ #define TRANS_SI(ufsvfsp, fs, cg) \ if (TRANS_ISTRANS(ufsvfsp)) \ if (ufsvfsp->vfs_nolog_si) \ fs->fs_si = FS_SI_BAD; \ else \ TRANS_DELTA(ufsvfsp, \ ldbtob(fsbtodb(fs, fs->fs_csaddr)) + \ ((caddr_t)&fs->fs_cs(fs, cg) - \ (caddr_t)fs->fs_u.fs_csp), \ sizeof (struct csum), DT_SI, \ ufs_trans_push_si, cg) #define TRANS_DIR(ip, offset) \ (TRANS_ISTRANS(ip->i_ufsvfs) ? ufs_trans_dir(ip, offset) : 0) #define TRANS_QUOTA(dqp) \ if (TRANS_ISTRANS(dqp->dq_ufsvfsp)) \ ufs_trans_quota(dqp); #define TRANS_DQRELE(ufsvfsp, dqp) \ if (TRANS_ISTRANS(ufsvfsp) && \ ((curthread->t_flag & T_DONTBLOCK) == 0)) { \ ufs_trans_dqrele(dqp); \ } else { \ rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER); \ dqrele(dqp); \ rw_exit(&ufsvfsp->vfs_dqrwlock); \ } #define TRANS_ITRUNC(ip, length, flags, cr) \ ufs_trans_itrunc(ip, length, flags, cr); #define TRANS_WRITE_RESV(ip, uiop, ulp, resvp, residp) \ if ((TRANS_ISTRANS(ip->i_ufsvfs) != NULL) && (ulp != NULL)) \ ufs_trans_write_resv(ip, uiop, resvp, residp); #define TRANS_WRITE(ip, uiop, ioflag, err, ulp, cr, resv, resid) \ if ((TRANS_ISTRANS(ip->i_ufsvfs) != NULL) && (ulp != NULL)) \ err = ufs_trans_write(ip, uiop, ioflag, cr, resv, resid); \ else \ err = wrip(ip, uiop, ioflag, cr); /* * These functions "wrap" functions that are not VOP or VFS * entry points but must still use the TRANS_BEGIN/TRANS_END * protocol */ #define TRANS_SBUPDATE(ufsvfsp, vfsp, topid) \ ufs_trans_sbupdate(ufsvfsp, vfsp, topid) #define TRANS_SYNCIP(ip, bflags, iflag, topid) \ ufs_syncip(ip, bflags, iflag, topid) #define TRANS_SBWRITE(ufsvfsp, topid) ufs_trans_sbwrite(ufsvfsp, topid) #define TRANS_IUPDAT(ip, waitfor) ufs_trans_iupdat(ip, waitfor) #ifdef DEBUG /* * Test/Debug ops * The following ops maintain the metadata map. * The metadata map is a debug/test feature. * These ops are *not* used in the production product. */ /* * Set a flag if meta data checking. */ #define TRANS_DOMATAMAP(ufsvfsp) \ ufsvfsp->vfs_domatamap = \ (TRANS_ISTRANS(ufsvfsp) && \ (ufsvfsp->vfs_log->un_debug & MT_MATAMAP)) #define TRANS_MATA_IGET(ufsvfsp, ip) \ if (ufsvfsp->vfs_domatamap) \ ufs_trans_mata_iget(ip) #define TRANS_MATA_FREE(ufsvfsp, mof, nb) \ if (ufsvfsp->vfs_domatamap) \ ufs_trans_mata_free(ufsvfsp, (offset_t)(mof), nb) #define TRANS_MATA_ALLOC(ufsvfsp, ip, bno, size, zero) \ if (ufsvfsp->vfs_domatamap) \ ufs_trans_mata_alloc(ufsvfsp, ip, bno, size, zero) #define TRANS_MATA_MOUNT(ufsvfsp) \ if (ufsvfsp->vfs_domatamap) \ ufs_trans_mata_mount(ufsvfsp) #define TRANS_MATA_UMOUNT(ufsvfsp) \ if (ufsvfsp->vfs_domatamap) \ ufs_trans_mata_umount(ufsvfsp) #define TRANS_MATA_SI(ufsvfsp, fs) \ if (ufsvfsp->vfs_domatamap) \ ufs_trans_mata_si(ufsvfsp, fs) #define TRANS_MATAADD(ufsvfsp, mof, nb) \ top_mataadd(ufsvfsp, (offset_t)(mof), nb) #else /* !DEBUG */ #define TRANS_DOMATAMAP(ufsvfsp) #define TRANS_MATA_IGET(ufsvfsp, ip) #define TRANS_MATA_FREE(ufsvfsp, mof, nb) #define TRANS_MATA_ALLOC(ufsvfsp, ip, bno, size, zero) #define TRANS_MATA_MOUNT(ufsvfsp) #define TRANS_MATA_UMOUNT(ufsvfsp) #define TRANS_MATA_SI(ufsvfsp, fs) #define TRANS_MATAADD(ufsvfsp, mof, nb) #endif /* !DEBUG */ #include #include /* * identifies the type of operation passed into TRANS_BEGIN/END */ #define TOP_SYNC (0x00000001) #define TOP_ASYNC (0x00000002) #define TOP_SYNC_FORCED (0x00000004) /* forced sync transaction */ /* * estimated values */ #define HEADERSIZE (128) #define ALLOCSIZE (160) #define INODESIZE (sizeof (struct dinode) + HEADERSIZE) #define SIZESB ((sizeof (struct fs)) + HEADERSIZE) #define SIZEDIR (DIRBLKSIZ + HEADERSIZE) /* * calculated values */ #define SIZECG(IP) ((IP)->i_fs->fs_cgsize + HEADERSIZE) #define FRAGSIZE(IP) ((IP)->i_fs->fs_fsize + HEADERSIZE) #define ACLSIZE(IP) (((IP)->i_ufsvfs->vfs_maxacl + HEADERSIZE) + \ INODESIZE) #define MAXACLSIZE ((MAX_ACL_ENTRIES << 1) * sizeof (aclent_t)) #define DIRSIZE(IP) (INODESIZE + (4 * ALLOCSIZE) + \ (IP)->i_fs->fs_fsize + HEADERSIZE) #define QUOTASIZE sizeof (struct dquot) + HEADERSIZE /* * size calculations */ #define TOP_CREATE_SIZE(IP) \ (ACLSIZE(IP) + SIZECG(IP) + DIRSIZE(IP) + INODESIZE) #define TOP_REMOVE_SIZE(IP) \ DIRSIZE(IP) + SIZECG(IP) + INODESIZE + SIZESB #define TOP_LINK_SIZE(IP) \ DIRSIZE(IP) + INODESIZE #define TOP_RENAME_SIZE(IP) \ DIRSIZE(IP) + DIRSIZE(IP) + SIZECG(IP) #define TOP_MKDIR_SIZE(IP) \ DIRSIZE(IP) + INODESIZE + DIRSIZE(IP) + INODESIZE + FRAGSIZE(IP) + \ SIZECG(IP) + ACLSIZE(IP) #define TOP_SYMLINK_SIZE(IP) \ DIRSIZE((IP)) + INODESIZE + INODESIZE + SIZECG(IP) #define TOP_GETPAGE_SIZE(IP) \ ALLOCSIZE + ALLOCSIZE + ALLOCSIZE + INODESIZE + SIZECG(IP) #define TOP_SYNCIP_SIZE INODESIZE #define TOP_READ_SIZE INODESIZE #define TOP_RMDIR_SIZE (SIZESB + (INODESIZE * 2) + SIZEDIR) #define TOP_SETQUOTA_SIZE(FS) ((FS)->fs_bsize << 2) #define TOP_QUOTA_SIZE (QUOTASIZE) #define TOP_SETSECATTR_SIZE(IP) (MAXACLSIZE) #define TOP_IUPDAT_SIZE(IP) INODESIZE + SIZECG(IP) #define TOP_SBUPDATE_SIZE (SIZESB) #define TOP_SBWRITE_SIZE (SIZESB) #define TOP_PUTPAGE_SIZE(IP) (INODESIZE + SIZECG(IP)) #define TOP_SETATTR_SIZE(IP) (SIZECG(IP) + INODESIZE + QUOTASIZE + \ ACLSIZE(IP)) #define TOP_IFREE_SIZE(IP) (SIZECG(IP) + INODESIZE + QUOTASIZE) #define TOP_MOUNT_SIZE (SIZESB) #define TOP_COMMIT_SIZE (0) /* * The minimum log size is 1M. So we will allow 1 fs operation to * reserve at most 512K of log space. */ #define TOP_MAX_RESV (512 * 1024) /* * ufs trans function prototypes */ #if defined(_KERNEL) extern int ufs_trans_hlock(); extern void ufs_trans_onerror(); extern int ufs_trans_push_inode(struct ufsvfs *, delta_t, ino_t); extern int ufs_trans_push_buf(struct ufsvfs *, delta_t, daddr_t); extern int ufs_trans_push_si(struct ufsvfs *, delta_t, int); extern void ufs_trans_sbupdate(struct ufsvfs *, struct vfs *, top_t); extern void ufs_trans_sbwrite(struct ufsvfs *, top_t); extern void ufs_trans_iupdat(struct inode *, int); extern void ufs_trans_mata_mount(struct ufsvfs *); extern void ufs_trans_mata_umount(struct ufsvfs *); extern void ufs_trans_mata_si(struct ufsvfs *, struct fs *); extern void ufs_trans_mata_iget(struct inode *); extern void ufs_trans_mata_free(struct ufsvfs *, offset_t, off_t); extern void ufs_trans_mata_alloc(struct ufsvfs *, struct inode *, daddr_t, ulong_t, int); extern int ufs_trans_dir(struct inode *, off_t); extern void ufs_trans_quota(struct dquot *); extern void ufs_trans_dqrele(struct dquot *); extern int ufs_trans_itrunc(struct inode *, u_offset_t, int, cred_t *); extern int ufs_trans_write(struct inode *, struct uio *, int, cred_t *, int, long); extern void ufs_trans_write_resv(struct inode *, struct uio *, int *, int *); extern int ufs_trans_check(dev_t); extern void ufs_trans_redev(dev_t odev, dev_t ndev); extern void ufs_trans_trunc_resv(struct inode *, u_offset_t, int *, u_offset_t *); /* * transaction prototypes */ void lufs_unsnarf(struct ufsvfs *ufsvfsp); int lufs_snarf(struct ufsvfs *ufsvfsp, struct fs *fs, int ronly); void top_delta(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb, delta_t dtyp, int (*func)(), ulong_t arg); void top_cancel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb, int flags); int top_iscancel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb); void top_seterror(struct ufsvfs *ufsvfsp); int top_iserror(struct ufsvfs *ufsvfsp); void top_begin_sync(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size, int *error); int top_begin_async(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size, int tryasync); void top_end_sync(struct ufsvfs *ufsvfsp, int *ep, top_t topid, ulong_t size); void top_end_async(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size); void top_log(struct ufsvfs *ufsvfsp, char *va, offset_t vamof, off_t nb, caddr_t buf, uint32_t bufsz); void top_mataadd(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb); void top_matadel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb); void top_mataclr(struct ufsvfs *ufsvfsp); #endif /* defined(_KERNEL) */ #ifdef __cplusplus } #endif #endif /* _SYS_FS_UFS_TRANS_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2020 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Integros [integros.com] * Copyright 2020 Joyent, Inc. * Copyright (c) 2017 Datto Inc. * Copyright (c) 2017, Intel Corporation. */ /* Portions Copyright 2010 Robert Milkowski */ #ifndef _SYS_FS_ZFS_H #define _SYS_FS_ZFS_H #include /* * In OpenZFS we include sys/zio_priority.h to get the enum value of * ZIO_PRIORITY_NUM_QUEUEABLE, which is used for the various array sizes in * the structure definitions below. However, in illumos zio_priority.h is not * readily available to the userland code where we have a very large number of * files including sys/zfs.h. Thus, we define ZIO_PRIORITY_N_QUEUEABLE here and * this should be kept in sync if ZIO_PRIORITY_NUM_QUEUEABLE changes. */ #define ZIO_PRIORITY_N_QUEUEABLE 8 #ifdef __cplusplus extern "C" { #endif /* * Types and constants shared between userland and the kernel. */ /* * Each dataset can be one of the following types. These constants can be * combined into masks that can be passed to various functions. */ typedef enum { ZFS_TYPE_FILESYSTEM = (1 << 0), ZFS_TYPE_SNAPSHOT = (1 << 1), ZFS_TYPE_VOLUME = (1 << 2), ZFS_TYPE_POOL = (1 << 3), ZFS_TYPE_BOOKMARK = (1 << 4) } zfs_type_t; /* * NB: lzc_dataset_type should be updated whenever a new objset type is added, * if it represents a real type of a dataset that can be created from userland. */ typedef enum dmu_objset_type { DMU_OST_NONE, DMU_OST_META, DMU_OST_ZFS, DMU_OST_ZVOL, DMU_OST_OTHER, /* For testing only! */ DMU_OST_ANY, /* Be careful! */ DMU_OST_NUMTYPES } dmu_objset_type_t; #define ZFS_TYPE_DATASET \ (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME | ZFS_TYPE_SNAPSHOT) /* * All of these include the terminating NUL byte. */ #define ZAP_MAXNAMELEN 256 #define ZAP_MAXVALUELEN (1024 * 8) #define ZAP_OLDMAXVALUELEN 1024 #define ZFS_MAX_DATASET_NAME_LEN 256 /* * Dataset properties are identified by these constants and must be added to * the end of this list to ensure that external consumers are not affected * by the change. If you make any changes to this list, be sure to update * the property table in usr/src/common/zfs/zfs_prop.c. */ typedef enum { ZPROP_CONT = -2, ZPROP_INVAL = -1, ZFS_PROP_TYPE = 0, ZFS_PROP_CREATION, ZFS_PROP_USED, ZFS_PROP_AVAILABLE, ZFS_PROP_REFERENCED, ZFS_PROP_COMPRESSRATIO, ZFS_PROP_MOUNTED, ZFS_PROP_ORIGIN, ZFS_PROP_QUOTA, ZFS_PROP_RESERVATION, ZFS_PROP_VOLSIZE, ZFS_PROP_VOLBLOCKSIZE, ZFS_PROP_RECORDSIZE, ZFS_PROP_MOUNTPOINT, ZFS_PROP_SHARENFS, ZFS_PROP_CHECKSUM, ZFS_PROP_COMPRESSION, ZFS_PROP_ATIME, ZFS_PROP_DEVICES, ZFS_PROP_EXEC, ZFS_PROP_SETUID, ZFS_PROP_READONLY, ZFS_PROP_ZONED, ZFS_PROP_SNAPDIR, ZFS_PROP_ACLMODE, ZFS_PROP_ACLINHERIT, ZFS_PROP_ACLIMPLICIT, /* ACL Implicit Owner Rights (RackTop) */ ZFS_PROP_CREATETXG, ZFS_PROP_NAME, /* not exposed to the user */ ZFS_PROP_CANMOUNT, ZFS_PROP_ISCSIOPTIONS, /* not exposed to the user */ ZFS_PROP_XATTR, ZFS_PROP_NUMCLONES, /* not exposed to the user */ ZFS_PROP_COPIES, ZFS_PROP_VERSION, ZFS_PROP_UTF8ONLY, ZFS_PROP_NORMALIZE, ZFS_PROP_CASE, ZFS_PROP_VSCAN, ZFS_PROP_NBMAND, ZFS_PROP_SHARESMB, ZFS_PROP_REFQUOTA, ZFS_PROP_REFRESERVATION, ZFS_PROP_GUID, ZFS_PROP_PRIMARYCACHE, ZFS_PROP_SECONDARYCACHE, ZFS_PROP_USEDSNAP, ZFS_PROP_USEDDS, ZFS_PROP_USEDCHILD, ZFS_PROP_USEDREFRESERV, ZFS_PROP_USERACCOUNTING, /* not exposed to the user */ ZFS_PROP_STMF_SHAREINFO, /* not exposed to the user */ ZFS_PROP_DEFER_DESTROY, ZFS_PROP_USERREFS, ZFS_PROP_LOGBIAS, ZFS_PROP_UNIQUE, /* not exposed to the user */ ZFS_PROP_OBJSETID, /* not exposed to the user */ ZFS_PROP_DEDUP, ZFS_PROP_MLSLABEL, ZFS_PROP_SYNC, ZFS_PROP_DNODESIZE, ZFS_PROP_REFRATIO, ZFS_PROP_WRITTEN, ZFS_PROP_CLONES, ZFS_PROP_LOGICALUSED, ZFS_PROP_LOGICALREFERENCED, ZFS_PROP_INCONSISTENT, /* not exposed to the user */ ZFS_PROP_FILESYSTEM_LIMIT, ZFS_PROP_SNAPSHOT_LIMIT, ZFS_PROP_FILESYSTEM_COUNT, ZFS_PROP_SNAPSHOT_COUNT, ZFS_PROP_REDUNDANT_METADATA, ZFS_PROP_PREV_SNAP, ZFS_PROP_RECEIVE_RESUME_TOKEN, ZFS_PROP_REMAPTXG, /* not exposed to the user */ ZFS_PROP_SPECIAL_SMALL_BLOCKS, ZFS_PROP_ENCRYPTION, ZFS_PROP_KEYLOCATION, ZFS_PROP_KEYFORMAT, ZFS_PROP_PBKDF2_SALT, ZFS_PROP_PBKDF2_ITERS, ZFS_PROP_ENCRYPTION_ROOT, ZFS_PROP_KEY_GUID, ZFS_PROP_KEYSTATUS, ZFS_PROP_IVSET_GUID, /* not exposed to the user */ ZFS_NUM_PROPS } zfs_prop_t; typedef enum { ZFS_PROP_USERUSED, ZFS_PROP_USERQUOTA, ZFS_PROP_GROUPUSED, ZFS_PROP_GROUPQUOTA, ZFS_PROP_USEROBJUSED, ZFS_PROP_USEROBJQUOTA, ZFS_PROP_GROUPOBJUSED, ZFS_PROP_GROUPOBJQUOTA, ZFS_PROP_PROJECTUSED, ZFS_PROP_PROJECTQUOTA, ZFS_PROP_PROJECTOBJUSED, ZFS_PROP_PROJECTOBJQUOTA, ZFS_NUM_USERQUOTA_PROPS } zfs_userquota_prop_t; extern const char *zfs_userquota_prop_prefixes[ZFS_NUM_USERQUOTA_PROPS]; /* * Pool properties are identified by these constants and must be added to the * end of this list to ensure that external consumers are not affected * by the change. If you make any changes to this list, be sure to update * the property table in usr/src/common/zfs/zpool_prop.c. */ typedef enum { ZPOOL_PROP_INVAL = -1, ZPOOL_PROP_NAME, ZPOOL_PROP_SIZE, ZPOOL_PROP_CAPACITY, ZPOOL_PROP_ALTROOT, ZPOOL_PROP_HEALTH, ZPOOL_PROP_GUID, ZPOOL_PROP_VERSION, ZPOOL_PROP_BOOTFS, ZPOOL_PROP_DELEGATION, ZPOOL_PROP_AUTOREPLACE, ZPOOL_PROP_CACHEFILE, ZPOOL_PROP_FAILUREMODE, ZPOOL_PROP_LISTSNAPS, ZPOOL_PROP_AUTOEXPAND, ZPOOL_PROP_DEDUPDITTO, ZPOOL_PROP_DEDUPRATIO, ZPOOL_PROP_FREE, ZPOOL_PROP_ALLOCATED, ZPOOL_PROP_READONLY, ZPOOL_PROP_COMMENT, ZPOOL_PROP_EXPANDSZ, ZPOOL_PROP_FREEING, ZPOOL_PROP_FRAGMENTATION, ZPOOL_PROP_LEAKED, ZPOOL_PROP_MAXBLOCKSIZE, ZPOOL_PROP_BOOTSIZE, ZPOOL_PROP_CHECKPOINT, ZPOOL_PROP_TNAME, ZPOOL_PROP_MAXDNODESIZE, ZPOOL_PROP_MULTIHOST, ZPOOL_PROP_ASHIFT, ZPOOL_PROP_AUTOTRIM, ZPOOL_NUM_PROPS } zpool_prop_t; /* Small enough to not hog a whole line of printout in zpool(8). */ #define ZPROP_MAX_COMMENT 32 #define ZPROP_VALUE "value" #define ZPROP_SOURCE "source" typedef enum { ZPROP_SRC_NONE = 0x1, ZPROP_SRC_DEFAULT = 0x2, ZPROP_SRC_TEMPORARY = 0x4, ZPROP_SRC_LOCAL = 0x8, ZPROP_SRC_INHERITED = 0x10, ZPROP_SRC_RECEIVED = 0x20 } zprop_source_t; #define ZPROP_SRC_ALL 0x3f #define ZPROP_SOURCE_VAL_RECVD "$recvd" #define ZPROP_N_MORE_ERRORS "N_MORE_ERRORS" /* * Dataset flag implemented as a special entry in the props zap object * indicating that the dataset has received properties on or after * SPA_VERSION_RECVD_PROPS. The first such receive blows away local properties * just as it did in earlier versions, and thereafter, local properties are * preserved. */ #define ZPROP_HAS_RECVD "$hasrecvd" typedef enum { ZPROP_ERR_NOCLEAR = 0x1, /* failure to clear existing props */ ZPROP_ERR_NORESTORE = 0x2 /* failure to restore props on error */ } zprop_errflags_t; typedef int (*zprop_func)(int, void *); /* * Properties to be set on the root file system of a new pool * are stuffed into their own nvlist, which is then included in * the properties nvlist with the pool properties. */ #define ZPOOL_ROOTFS_PROPS "root-props-nvl" /* * Length of 'written@' and 'written#' */ #define ZFS_WRITTEN_PROP_PREFIX_LEN 8 /* * Dataset property functions shared between libzfs and kernel. */ const char *zfs_prop_default_string(zfs_prop_t); uint64_t zfs_prop_default_numeric(zfs_prop_t); boolean_t zfs_prop_readonly(zfs_prop_t); boolean_t zfs_prop_visible(zfs_prop_t prop); boolean_t zfs_prop_inheritable(zfs_prop_t); boolean_t zfs_prop_setonce(zfs_prop_t); boolean_t zfs_prop_encryption_key_param(zfs_prop_t); boolean_t zfs_prop_valid_keylocation(const char *, boolean_t); const char *zfs_prop_to_name(zfs_prop_t); zfs_prop_t zfs_name_to_prop(const char *); boolean_t zfs_prop_user(const char *); boolean_t zfs_prop_userquota(const char *); boolean_t zfs_prop_written(const char *); int zfs_prop_index_to_string(zfs_prop_t, uint64_t, const char **); int zfs_prop_string_to_index(zfs_prop_t, const char *, uint64_t *); uint64_t zfs_prop_random_value(zfs_prop_t, uint64_t seed); boolean_t zfs_prop_valid_for_type(int, zfs_type_t, boolean_t); /* * Pool property functions shared between libzfs and kernel. */ zpool_prop_t zpool_name_to_prop(const char *); const char *zpool_prop_to_name(zpool_prop_t); const char *zpool_prop_default_string(zpool_prop_t); uint64_t zpool_prop_default_numeric(zpool_prop_t); boolean_t zpool_prop_readonly(zpool_prop_t); boolean_t zpool_prop_feature(const char *); boolean_t zpool_prop_unsupported(const char *name); int zpool_prop_index_to_string(zpool_prop_t, uint64_t, const char **); int zpool_prop_string_to_index(zpool_prop_t, const char *, uint64_t *); uint64_t zpool_prop_random_value(zpool_prop_t, uint64_t seed); /* * Definitions for the Delegation. */ typedef enum { ZFS_DELEG_WHO_UNKNOWN = 0, ZFS_DELEG_USER = 'u', ZFS_DELEG_USER_SETS = 'U', ZFS_DELEG_GROUP = 'g', ZFS_DELEG_GROUP_SETS = 'G', ZFS_DELEG_EVERYONE = 'e', ZFS_DELEG_EVERYONE_SETS = 'E', ZFS_DELEG_CREATE = 'c', ZFS_DELEG_CREATE_SETS = 'C', ZFS_DELEG_NAMED_SET = 's', ZFS_DELEG_NAMED_SET_SETS = 'S' } zfs_deleg_who_type_t; typedef enum { ZFS_DELEG_NONE = 0, ZFS_DELEG_PERM_LOCAL = 1, ZFS_DELEG_PERM_DESCENDENT = 2, ZFS_DELEG_PERM_LOCALDESCENDENT = 3, ZFS_DELEG_PERM_CREATE = 4 } zfs_deleg_inherit_t; #define ZFS_DELEG_PERM_UID "uid" #define ZFS_DELEG_PERM_GID "gid" #define ZFS_DELEG_PERM_GROUPS "groups" #define ZFS_MLSLABEL_DEFAULT "none" #define ZFS_SMB_ACL_SRC "src" #define ZFS_SMB_ACL_TARGET "target" typedef enum { ZFS_CANMOUNT_OFF = 0, ZFS_CANMOUNT_ON = 1, ZFS_CANMOUNT_NOAUTO = 2 } zfs_canmount_type_t; typedef enum { ZFS_LOGBIAS_LATENCY = 0, ZFS_LOGBIAS_THROUGHPUT = 1 } zfs_logbias_op_t; typedef enum zfs_share_op { ZFS_SHARE_NFS = 0, ZFS_UNSHARE_NFS = 1, ZFS_SHARE_SMB = 2, ZFS_UNSHARE_SMB = 3 } zfs_share_op_t; typedef enum zfs_smb_acl_op { ZFS_SMB_ACL_ADD, ZFS_SMB_ACL_REMOVE, ZFS_SMB_ACL_RENAME, ZFS_SMB_ACL_PURGE } zfs_smb_acl_op_t; typedef enum zfs_cache_type { ZFS_CACHE_NONE = 0, ZFS_CACHE_METADATA = 1, ZFS_CACHE_ALL = 2 } zfs_cache_type_t; typedef enum { ZFS_SYNC_STANDARD = 0, ZFS_SYNC_ALWAYS = 1, ZFS_SYNC_DISABLED = 2 } zfs_sync_type_t; typedef enum { ZFS_DNSIZE_LEGACY = 0, ZFS_DNSIZE_AUTO = 1, ZFS_DNSIZE_1K = 1024, ZFS_DNSIZE_2K = 2048, ZFS_DNSIZE_4K = 4096, ZFS_DNSIZE_8K = 8192, ZFS_DNSIZE_16K = 16384 } zfs_dnsize_type_t; typedef enum { ZFS_REDUNDANT_METADATA_ALL, ZFS_REDUNDANT_METADATA_MOST } zfs_redundant_metadata_type_t; typedef enum zfs_keystatus { ZFS_KEYSTATUS_NONE = 0, ZFS_KEYSTATUS_UNAVAILABLE, ZFS_KEYSTATUS_AVAILABLE } zfs_keystatus_t; typedef enum zfs_keyformat { ZFS_KEYFORMAT_NONE = 0, ZFS_KEYFORMAT_RAW, ZFS_KEYFORMAT_HEX, ZFS_KEYFORMAT_PASSPHRASE, ZFS_KEYFORMAT_FORMATS } zfs_keyformat_t; typedef enum zfs_key_location { ZFS_KEYLOCATION_NONE = 0, ZFS_KEYLOCATION_PROMPT, ZFS_KEYLOCATION_URI, ZFS_KEYLOCATION_LOCATIONS } zfs_keylocation_t; #define DEFAULT_PBKDF2_ITERATIONS 350000 #define MIN_PBKDF2_ITERATIONS 100000 /* * On-disk version number. */ #define SPA_VERSION_1 1ULL #define SPA_VERSION_2 2ULL #define SPA_VERSION_3 3ULL #define SPA_VERSION_4 4ULL #define SPA_VERSION_5 5ULL #define SPA_VERSION_6 6ULL #define SPA_VERSION_7 7ULL #define SPA_VERSION_8 8ULL #define SPA_VERSION_9 9ULL #define SPA_VERSION_10 10ULL #define SPA_VERSION_11 11ULL #define SPA_VERSION_12 12ULL #define SPA_VERSION_13 13ULL #define SPA_VERSION_14 14ULL #define SPA_VERSION_15 15ULL #define SPA_VERSION_16 16ULL #define SPA_VERSION_17 17ULL #define SPA_VERSION_18 18ULL #define SPA_VERSION_19 19ULL #define SPA_VERSION_20 20ULL #define SPA_VERSION_21 21ULL #define SPA_VERSION_22 22ULL #define SPA_VERSION_23 23ULL #define SPA_VERSION_24 24ULL #define SPA_VERSION_25 25ULL #define SPA_VERSION_26 26ULL #define SPA_VERSION_27 27ULL #define SPA_VERSION_28 28ULL #define SPA_VERSION_5000 5000ULL /* * When bumping up SPA_VERSION, make sure GRUB ZFS understands the on-disk * format change. Go to usr/src/grub/grub-0.97/stage2/{zfs-include/, fsys_zfs*}, * and do the appropriate changes. Also bump the version number in * usr/src/grub/capability. */ #define SPA_VERSION SPA_VERSION_5000 #define SPA_VERSION_STRING "5000" /* * Symbolic names for the changes that caused a SPA_VERSION switch. * Used in the code when checking for presence or absence of a feature. * Feel free to define multiple symbolic names for each version if there * were multiple changes to on-disk structures during that version. * * NOTE: When checking the current SPA_VERSION in your code, be sure * to use spa_version() since it reports the version of the * last synced uberblock. Checking the in-flight version can * be dangerous in some cases. */ #define SPA_VERSION_INITIAL SPA_VERSION_1 #define SPA_VERSION_DITTO_BLOCKS SPA_VERSION_2 #define SPA_VERSION_SPARES SPA_VERSION_3 #define SPA_VERSION_RAIDZ2 SPA_VERSION_3 #define SPA_VERSION_BPOBJ_ACCOUNT SPA_VERSION_3 #define SPA_VERSION_RAIDZ_DEFLATE SPA_VERSION_3 #define SPA_VERSION_DNODE_BYTES SPA_VERSION_3 #define SPA_VERSION_ZPOOL_HISTORY SPA_VERSION_4 #define SPA_VERSION_GZIP_COMPRESSION SPA_VERSION_5 #define SPA_VERSION_BOOTFS SPA_VERSION_6 #define SPA_VERSION_SLOGS SPA_VERSION_7 #define SPA_VERSION_DELEGATED_PERMS SPA_VERSION_8 #define SPA_VERSION_FUID SPA_VERSION_9 #define SPA_VERSION_REFRESERVATION SPA_VERSION_9 #define SPA_VERSION_REFQUOTA SPA_VERSION_9 #define SPA_VERSION_UNIQUE_ACCURATE SPA_VERSION_9 #define SPA_VERSION_L2CACHE SPA_VERSION_10 #define SPA_VERSION_NEXT_CLONES SPA_VERSION_11 #define SPA_VERSION_ORIGIN SPA_VERSION_11 #define SPA_VERSION_DSL_SCRUB SPA_VERSION_11 #define SPA_VERSION_SNAP_PROPS SPA_VERSION_12 #define SPA_VERSION_USED_BREAKDOWN SPA_VERSION_13 #define SPA_VERSION_PASSTHROUGH_X SPA_VERSION_14 #define SPA_VERSION_USERSPACE SPA_VERSION_15 #define SPA_VERSION_STMF_PROP SPA_VERSION_16 #define SPA_VERSION_RAIDZ3 SPA_VERSION_17 #define SPA_VERSION_USERREFS SPA_VERSION_18 #define SPA_VERSION_HOLES SPA_VERSION_19 #define SPA_VERSION_ZLE_COMPRESSION SPA_VERSION_20 #define SPA_VERSION_DEDUP SPA_VERSION_21 #define SPA_VERSION_RECVD_PROPS SPA_VERSION_22 #define SPA_VERSION_SLIM_ZIL SPA_VERSION_23 #define SPA_VERSION_SA SPA_VERSION_24 #define SPA_VERSION_SCAN SPA_VERSION_25 #define SPA_VERSION_DIR_CLONES SPA_VERSION_26 #define SPA_VERSION_DEADLISTS SPA_VERSION_26 #define SPA_VERSION_FAST_SNAP SPA_VERSION_27 #define SPA_VERSION_MULTI_REPLACE SPA_VERSION_28 #define SPA_VERSION_BEFORE_FEATURES SPA_VERSION_28 #define SPA_VERSION_FEATURES SPA_VERSION_5000 #define SPA_VERSION_IS_SUPPORTED(v) \ (((v) >= SPA_VERSION_INITIAL && (v) <= SPA_VERSION_BEFORE_FEATURES) || \ ((v) >= SPA_VERSION_FEATURES && (v) <= SPA_VERSION)) /* * ZPL version - rev'd whenever an incompatible on-disk format change * occurs. This is independent of SPA/DMU/ZAP versioning. You must * also update the version_table[] and help message in zfs_prop.c. * * When changing, be sure to teach GRUB how to read the new format! * See usr/src/grub/grub-0.97/stage2/{zfs-include/,fsys_zfs*} */ #define ZPL_VERSION_1 1ULL #define ZPL_VERSION_2 2ULL #define ZPL_VERSION_3 3ULL #define ZPL_VERSION_4 4ULL #define ZPL_VERSION_5 5ULL #define ZPL_VERSION ZPL_VERSION_5 #define ZPL_VERSION_STRING "5" #define ZPL_VERSION_INITIAL ZPL_VERSION_1 #define ZPL_VERSION_DIRENT_TYPE ZPL_VERSION_2 #define ZPL_VERSION_FUID ZPL_VERSION_3 #define ZPL_VERSION_NORMALIZATION ZPL_VERSION_3 #define ZPL_VERSION_SYSATTR ZPL_VERSION_3 #define ZPL_VERSION_USERSPACE ZPL_VERSION_4 #define ZPL_VERSION_SA ZPL_VERSION_5 /* Persistent L2ARC version */ #define L2ARC_PERSISTENT_VERSION_1 1ULL #define L2ARC_PERSISTENT_VERSION L2ARC_PERSISTENT_VERSION_1 #define L2ARC_PERSISTENT_VERSION_STRING "1" /* Rewind policy information */ #define ZPOOL_NO_REWIND 1 /* No policy - default behavior */ #define ZPOOL_NEVER_REWIND 2 /* Do not search for best txg or rewind */ #define ZPOOL_TRY_REWIND 4 /* Search for best txg, but do not rewind */ #define ZPOOL_DO_REWIND 8 /* Rewind to best txg w/in deferred frees */ #define ZPOOL_EXTREME_REWIND 16 /* Allow extreme measures to find best txg */ #define ZPOOL_REWIND_MASK 28 /* All the possible rewind bits */ #define ZPOOL_REWIND_POLICIES 31 /* All the possible policy bits */ typedef struct zpool_load_policy { uint32_t zlp_rewind; /* rewind policy requested */ uint64_t zlp_maxmeta; /* max acceptable meta-data errors */ uint64_t zlp_maxdata; /* max acceptable data errors */ uint64_t zlp_txg; /* specific txg to load */ } zpool_load_policy_t; /* * The following are configuration names used in the nvlist describing a pool's * configuration. New on-disk names should be prefixed with ":" * (e.g. "org.open-zfs:") to avoid conflicting names being developed * independently. */ #define ZPOOL_CONFIG_VERSION "version" #define ZPOOL_CONFIG_POOL_NAME "name" #define ZPOOL_CONFIG_POOL_STATE "state" #define ZPOOL_CONFIG_POOL_TXG "txg" #define ZPOOL_CONFIG_POOL_GUID "pool_guid" #define ZPOOL_CONFIG_CREATE_TXG "create_txg" #define ZPOOL_CONFIG_TOP_GUID "top_guid" #define ZPOOL_CONFIG_VDEV_TREE "vdev_tree" #define ZPOOL_CONFIG_TYPE "type" #define ZPOOL_CONFIG_CHILDREN "children" #define ZPOOL_CONFIG_ID "id" #define ZPOOL_CONFIG_GUID "guid" #define ZPOOL_CONFIG_INDIRECT_OBJECT "com.delphix:indirect_object" #define ZPOOL_CONFIG_INDIRECT_BIRTHS "com.delphix:indirect_births" #define ZPOOL_CONFIG_PREV_INDIRECT_VDEV "com.delphix:prev_indirect_vdev" #define ZPOOL_CONFIG_PATH "path" #define ZPOOL_CONFIG_DEVID "devid" #define ZPOOL_CONFIG_METASLAB_ARRAY "metaslab_array" #define ZPOOL_CONFIG_METASLAB_SHIFT "metaslab_shift" #define ZPOOL_CONFIG_ASHIFT "ashift" #define ZPOOL_CONFIG_ASIZE "asize" #define ZPOOL_CONFIG_DTL "DTL" #define ZPOOL_CONFIG_SCAN_STATS "scan_stats" /* not stored on disk */ #define ZPOOL_CONFIG_REMOVAL_STATS "removal_stats" /* not stored on disk */ #define ZPOOL_CONFIG_CHECKPOINT_STATS "checkpoint_stats" /* not on disk */ #define ZPOOL_CONFIG_VDEV_STATS "vdev_stats" /* not stored on disk */ #define ZPOOL_CONFIG_INDIRECT_SIZE "indirect_size" /* not stored on disk */ /* container nvlist of extended stats */ #define ZPOOL_CONFIG_VDEV_STATS_EX "vdev_stats_ex" /* Active queue read/write stats */ #define ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE "vdev_sync_r_active_queue" #define ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE "vdev_sync_w_active_queue" #define ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE "vdev_async_r_active_queue" #define ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE "vdev_async_w_active_queue" #define ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE "vdev_async_scrub_active_queue" #define ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE "vdev_async_trim_active_queue" /* Queue sizes */ #define ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE "vdev_sync_r_pend_queue" #define ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE "vdev_sync_w_pend_queue" #define ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE "vdev_async_r_pend_queue" #define ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE "vdev_async_w_pend_queue" #define ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE "vdev_async_scrub_pend_queue" #define ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE "vdev_async_trim_pend_queue" /* Latency read/write histogram stats */ #define ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO "vdev_tot_r_lat_histo" #define ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO "vdev_tot_w_lat_histo" #define ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO "vdev_disk_r_lat_histo" #define ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO "vdev_disk_w_lat_histo" #define ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO "vdev_sync_r_lat_histo" #define ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO "vdev_sync_w_lat_histo" #define ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO "vdev_async_r_lat_histo" #define ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO "vdev_async_w_lat_histo" #define ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO "vdev_scrub_histo" #define ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO "vdev_trim_histo" /* Request size histograms */ #define ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO "vdev_sync_ind_r_histo" #define ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO "vdev_sync_ind_w_histo" #define ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO "vdev_async_ind_r_histo" #define ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO "vdev_async_ind_w_histo" #define ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO "vdev_ind_scrub_histo" #define ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO "vdev_ind_trim_histo" #define ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO "vdev_sync_agg_r_histo" #define ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO "vdev_sync_agg_w_histo" #define ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO "vdev_async_agg_r_histo" #define ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO "vdev_async_agg_w_histo" #define ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO "vdev_agg_scrub_histo" #define ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO "vdev_agg_trim_histo" /* Number of slow IOs */ #define ZPOOL_CONFIG_VDEV_SLOW_IOS "vdev_slow_ios" #define ZPOOL_CONFIG_WHOLE_DISK "whole_disk" #define ZPOOL_CONFIG_ERRCOUNT "error_count" #define ZPOOL_CONFIG_NOT_PRESENT "not_present" #define ZPOOL_CONFIG_SPARES "spares" #define ZPOOL_CONFIG_IS_SPARE "is_spare" #define ZPOOL_CONFIG_NPARITY "nparity" #define ZPOOL_CONFIG_HOSTID "hostid" #define ZPOOL_CONFIG_HOSTNAME "hostname" #define ZPOOL_CONFIG_LOADED_TIME "initial_load_time" #define ZPOOL_CONFIG_UNSPARE "unspare" #define ZPOOL_CONFIG_PHYS_PATH "phys_path" #define ZPOOL_CONFIG_IS_LOG "is_log" #define ZPOOL_CONFIG_L2CACHE "l2cache" #define ZPOOL_CONFIG_HOLE_ARRAY "hole_array" #define ZPOOL_CONFIG_VDEV_CHILDREN "vdev_children" #define ZPOOL_CONFIG_IS_HOLE "is_hole" #define ZPOOL_CONFIG_DDT_HISTOGRAM "ddt_histogram" #define ZPOOL_CONFIG_DDT_OBJ_STATS "ddt_object_stats" #define ZPOOL_CONFIG_DDT_STATS "ddt_stats" #define ZPOOL_CONFIG_SPLIT "splitcfg" #define ZPOOL_CONFIG_ORIG_GUID "orig_guid" #define ZPOOL_CONFIG_SPLIT_GUID "split_guid" #define ZPOOL_CONFIG_SPLIT_LIST "guid_list" #define ZPOOL_CONFIG_REMOVING "removing" #define ZPOOL_CONFIG_RESILVER_TXG "resilver_txg" #define ZPOOL_CONFIG_COMMENT "comment" #define ZPOOL_CONFIG_SUSPENDED "suspended" /* not stored on disk */ #define ZPOOL_CONFIG_SUSPENDED_REASON "suspended_reason" /* not stored */ #define ZPOOL_CONFIG_TIMESTAMP "timestamp" /* not stored on disk */ #define ZPOOL_CONFIG_BOOTFS "bootfs" /* not stored on disk */ #define ZPOOL_CONFIG_MISSING_DEVICES "missing_vdevs" /* not stored on disk */ #define ZPOOL_CONFIG_LOAD_INFO "load_info" /* not stored on disk */ #define ZPOOL_CONFIG_REWIND_INFO "rewind_info" /* not stored on disk */ #define ZPOOL_CONFIG_UNSUP_FEAT "unsup_feat" /* not stored on disk */ #define ZPOOL_CONFIG_ENABLED_FEAT "enabled_feat" /* not stored on disk */ #define ZPOOL_CONFIG_CAN_RDONLY "can_rdonly" /* not stored on disk */ #define ZPOOL_CONFIG_FEATURES_FOR_READ "features_for_read" #define ZPOOL_CONFIG_FEATURE_STATS "feature_stats" /* not stored on disk */ #define ZPOOL_CONFIG_ERRATA "errata" /* not stored on disk */ #define ZPOOL_CONFIG_VDEV_TOP_ZAP "com.delphix:vdev_zap_top" #define ZPOOL_CONFIG_VDEV_LEAF_ZAP "com.delphix:vdev_zap_leaf" #define ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS "com.delphix:has_per_vdev_zaps" #define ZPOOL_CONFIG_RESILVER_DEFER "com.datto:resilver_defer" #define ZPOOL_CONFIG_CACHEFILE "cachefile" /* not stored on disk */ #define ZPOOL_CONFIG_MMP_STATE "mmp_state" /* not stored on disk */ #define ZPOOL_CONFIG_MMP_TXG "mmp_txg" /* not stored on disk */ #define ZPOOL_CONFIG_MMP_SEQ "mmp_seq" /* not stored on disk */ #define ZPOOL_CONFIG_MMP_HOSTNAME "mmp_hostname" /* not stored on disk */ #define ZPOOL_CONFIG_MMP_HOSTID "mmp_hostid" /* not stored on disk */ #define ZPOOL_CONFIG_ALLOCATION_BIAS "alloc_bias" /* not stored on disk */ /* * The persistent vdev state is stored as separate values rather than a single * 'vdev_state' entry. This is because a device can be in multiple states, such * as offline and degraded. */ #define ZPOOL_CONFIG_OFFLINE "offline" #define ZPOOL_CONFIG_FAULTED "faulted" #define ZPOOL_CONFIG_DEGRADED "degraded" #define ZPOOL_CONFIG_REMOVED "removed" #define ZPOOL_CONFIG_FRU "fru" #define ZPOOL_CONFIG_AUX_STATE "aux_state" /* Pool load policy parameters */ #define ZPOOL_LOAD_POLICY "load-policy" #define ZPOOL_LOAD_REWIND_POLICY "load-rewind-policy" #define ZPOOL_LOAD_REQUEST_TXG "load-request-txg" #define ZPOOL_LOAD_META_THRESH "load-meta-thresh" #define ZPOOL_LOAD_DATA_THRESH "load-data-thresh" /* Rewind data discovered */ #define ZPOOL_CONFIG_LOAD_TIME "rewind_txg_ts" #define ZPOOL_CONFIG_LOAD_DATA_ERRORS "verify_data_errors" #define ZPOOL_CONFIG_REWIND_TIME "seconds_of_rewind" #define VDEV_TYPE_ROOT "root" #define VDEV_TYPE_MIRROR "mirror" #define VDEV_TYPE_REPLACING "replacing" #define VDEV_TYPE_RAIDZ "raidz" #define VDEV_TYPE_DISK "disk" #define VDEV_TYPE_FILE "file" #define VDEV_TYPE_MISSING "missing" #define VDEV_TYPE_HOLE "hole" #define VDEV_TYPE_SPARE "spare" #define VDEV_TYPE_LOG "log" #define VDEV_TYPE_L2CACHE "l2cache" #define VDEV_TYPE_INDIRECT "indirect" /* VDEV_TOP_ZAP_* are used in top-level vdev ZAP objects. */ #define VDEV_TOP_ZAP_INDIRECT_OBSOLETE_SM \ "com.delphix:indirect_obsolete_sm" #define VDEV_TOP_ZAP_OBSOLETE_COUNTS_ARE_PRECISE \ "com.delphix:obsolete_counts_are_precise" #define VDEV_TOP_ZAP_POOL_CHECKPOINT_SM \ "com.delphix:pool_checkpoint_sm" #define VDEV_TOP_ZAP_MS_UNFLUSHED_PHYS_TXGS \ "com.delphix:ms_unflushed_phys_txgs" #define VDEV_TOP_ZAP_ALLOCATION_BIAS \ "org.zfsonlinux:allocation_bias" /* vdev metaslab allocation bias */ #define VDEV_ALLOC_BIAS_LOG "log" #define VDEV_ALLOC_BIAS_SPECIAL "special" #define VDEV_ALLOC_BIAS_DEDUP "dedup" /* vdev initialize state */ #define VDEV_LEAF_ZAP_INITIALIZE_LAST_OFFSET \ "com.delphix:next_offset_to_initialize" #define VDEV_LEAF_ZAP_INITIALIZE_STATE \ "com.delphix:vdev_initialize_state" #define VDEV_LEAF_ZAP_INITIALIZE_ACTION_TIME \ "com.delphix:vdev_initialize_action_time" /* vdev TRIM state */ #define VDEV_LEAF_ZAP_TRIM_LAST_OFFSET \ "org.zfsonlinux:next_offset_to_trim" #define VDEV_LEAF_ZAP_TRIM_STATE \ "org.zfsonlinux:vdev_trim_state" #define VDEV_LEAF_ZAP_TRIM_ACTION_TIME \ "org.zfsonlinux:vdev_trim_action_time" #define VDEV_LEAF_ZAP_TRIM_RATE \ "org.zfsonlinux:vdev_trim_rate" #define VDEV_LEAF_ZAP_TRIM_PARTIAL \ "org.zfsonlinux:vdev_trim_partial" #define VDEV_LEAF_ZAP_TRIM_SECURE \ "org.zfsonlinux:vdev_trim_secure" /* * This is needed in userland to report the minimum necessary device size. * * Note that the zfs test suite uses 64MB vdevs. */ #define SPA_MINDEVSIZE (64ULL << 20) /* * Set if the fragmentation has not yet been calculated. This can happen * because the space maps have not been upgraded or the histogram feature * is not enabled. */ #define ZFS_FRAG_INVALID UINT64_MAX /* * The location of the pool configuration repository, shared between kernel and * userland. */ #define ZPOOL_CACHE "/etc/zfs/zpool.cache" /* * vdev states are ordered from least to most healthy. * A vdev that's CANT_OPEN or below is considered unusable. */ typedef enum vdev_state { VDEV_STATE_UNKNOWN = 0, /* Uninitialized vdev */ VDEV_STATE_CLOSED, /* Not currently open */ VDEV_STATE_OFFLINE, /* Not allowed to open */ VDEV_STATE_REMOVED, /* Explicitly removed from system */ VDEV_STATE_CANT_OPEN, /* Tried to open, but failed */ VDEV_STATE_FAULTED, /* External request to fault device */ VDEV_STATE_DEGRADED, /* Replicated vdev with unhealthy kids */ VDEV_STATE_HEALTHY /* Presumed good */ } vdev_state_t; #define VDEV_STATE_ONLINE VDEV_STATE_HEALTHY /* * vdev aux states. When a vdev is in the CANT_OPEN state, the aux field * of the vdev stats structure uses these constants to distinguish why. */ typedef enum vdev_aux { VDEV_AUX_NONE, /* no error */ VDEV_AUX_OPEN_FAILED, /* ldi_open_*() or vn_open() failed */ VDEV_AUX_CORRUPT_DATA, /* bad label or disk contents */ VDEV_AUX_NO_REPLICAS, /* insufficient number of replicas */ VDEV_AUX_BAD_GUID_SUM, /* vdev guid sum doesn't match */ VDEV_AUX_TOO_SMALL, /* vdev size is too small */ VDEV_AUX_BAD_LABEL, /* the label is OK but invalid */ VDEV_AUX_VERSION_NEWER, /* on-disk version is too new */ VDEV_AUX_VERSION_OLDER, /* on-disk version is too old */ VDEV_AUX_UNSUP_FEAT, /* unsupported features */ VDEV_AUX_SPARED, /* hot spare used in another pool */ VDEV_AUX_ERR_EXCEEDED, /* too many errors */ VDEV_AUX_IO_FAILURE, /* experienced I/O failure */ VDEV_AUX_BAD_LOG, /* cannot read log chain(s) */ VDEV_AUX_EXTERNAL, /* external diagnosis */ VDEV_AUX_SPLIT_POOL, /* vdev was split off into another pool */ VDEV_AUX_ACTIVE, /* vdev active on a different host */ VDEV_AUX_CHILDREN_OFFLINE, /* all children are offline */ VDEV_AUX_BAD_ASHIFT /* vdev ashift is invalid */ } vdev_aux_t; /* * pool state. The following states are written to disk as part of the normal * SPA lifecycle: ACTIVE, EXPORTED, DESTROYED, SPARE, L2CACHE. The remaining * states are software abstractions used at various levels to communicate * pool state. */ typedef enum pool_state { POOL_STATE_ACTIVE = 0, /* In active use */ POOL_STATE_EXPORTED, /* Explicitly exported */ POOL_STATE_DESTROYED, /* Explicitly destroyed */ POOL_STATE_SPARE, /* Reserved for hot spare use */ POOL_STATE_L2CACHE, /* Level 2 ARC device */ POOL_STATE_UNINITIALIZED, /* Internal spa_t state */ POOL_STATE_UNAVAIL, /* Internal libzfs state */ POOL_STATE_POTENTIALLY_ACTIVE /* Internal libzfs state */ } pool_state_t; /* * mmp state. The following states provide additional detail describing * why a pool couldn't be safely imported. */ typedef enum mmp_state { MMP_STATE_ACTIVE = 0, /* In active use */ MMP_STATE_INACTIVE, /* Inactive and safe to import */ MMP_STATE_NO_HOSTID /* System hostid is not set */ } mmp_state_t; /* * Scan Functions. */ typedef enum pool_scan_func { POOL_SCAN_NONE, POOL_SCAN_SCRUB, POOL_SCAN_RESILVER, POOL_SCAN_FUNCS } pool_scan_func_t; /* * Used to control scrub pause and resume. */ typedef enum pool_scrub_cmd { POOL_SCRUB_NORMAL = 0, POOL_SCRUB_PAUSE, POOL_SCRUB_FLAGS_END } pool_scrub_cmd_t; /* * Initialize functions. */ typedef enum pool_initialize_func { POOL_INITIALIZE_START, POOL_INITIALIZE_CANCEL, POOL_INITIALIZE_SUSPEND, POOL_INITIALIZE_FUNCS } pool_initialize_func_t; /* * TRIM functions. */ typedef enum pool_trim_func { POOL_TRIM_START, POOL_TRIM_CANCEL, POOL_TRIM_SUSPEND, POOL_TRIM_FUNCS } pool_trim_func_t; /* * ZIO types. Needed to interpret vdev statistics below. */ typedef enum zio_type { ZIO_TYPE_NULL = 0, ZIO_TYPE_READ, ZIO_TYPE_WRITE, ZIO_TYPE_FREE, ZIO_TYPE_CLAIM, ZIO_TYPE_IOCTL, ZIO_TYPE_TRIM, ZIO_TYPES } zio_type_t; /* * Pool statistics. Note: all fields should be 64-bit because this * is passed between kernel and userland as an nvlist uint64 array. */ typedef struct pool_scan_stat { /* values stored on disk */ uint64_t pss_func; /* pool_scan_func_t */ uint64_t pss_state; /* dsl_scan_state_t */ uint64_t pss_start_time; /* scan start time */ uint64_t pss_end_time; /* scan end time */ uint64_t pss_to_examine; /* total bytes to scan */ uint64_t pss_examined; /* total bytes located by scanner */ uint64_t pss_to_process; /* total bytes to process */ uint64_t pss_processed; /* total processed bytes */ uint64_t pss_errors; /* scan errors */ /* values not stored on disk */ uint64_t pss_pass_exam; /* examined bytes per scan pass */ uint64_t pss_pass_issued; /* issued bytes per scan pass */ uint64_t pss_pass_start; /* start time of a scan pass */ uint64_t pss_pass_scrub_pause; /* pause time of a scurb pass */ /* cumulative time scrub spent paused, needed for rate calculation */ uint64_t pss_pass_scrub_spent_paused; /* Sorted scrubbing new fields */ /* Stored on disk */ uint64_t pss_issued; /* total bytes checked by scanner */ } pool_scan_stat_t; /* * Errata described by http://zfsonlinux.org/msg/ZFS-8000-ER. The ordering * of this enum must be maintained to ensure the errata identifiers map to * the correct documentation. New errata may only be appended to the list * and must contain corresponding documentation at the above link. */ typedef enum zpool_errata { ZPOOL_ERRATA_NONE, ZPOOL_ERRATA_ZOL_2094_SCRUB, ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY, ZPOOL_ERRATA_ZOL_6845_ENCRYPTION, ZPOOL_ERRATA_ZOL_8308_ENCRYPTION, } zpool_errata_t; typedef struct pool_removal_stat { uint64_t prs_state; /* dsl_scan_state_t */ uint64_t prs_removing_vdev; uint64_t prs_start_time; uint64_t prs_end_time; uint64_t prs_to_copy; /* bytes that need to be copied */ uint64_t prs_copied; /* bytes copied so far */ /* * bytes of memory used for indirect mappings. * This includes all removed vdevs. */ uint64_t prs_mapping_memory; } pool_removal_stat_t; typedef enum dsl_scan_state { DSS_NONE, DSS_SCANNING, DSS_FINISHED, DSS_CANCELED, DSS_NUM_STATES } dsl_scan_state_t; typedef enum { CS_NONE, CS_CHECKPOINT_EXISTS, CS_CHECKPOINT_DISCARDING, CS_NUM_STATES } checkpoint_state_t; typedef struct pool_checkpoint_stat { uint64_t pcs_state; /* checkpoint_state_t */ uint64_t pcs_start_time; /* time checkpoint/discard started */ uint64_t pcs_space; /* checkpointed space */ } pool_checkpoint_stat_t; typedef enum { VDEV_INITIALIZE_NONE, VDEV_INITIALIZE_ACTIVE, VDEV_INITIALIZE_CANCELED, VDEV_INITIALIZE_SUSPENDED, VDEV_INITIALIZE_COMPLETE } vdev_initializing_state_t; typedef enum { VDEV_TRIM_NONE, VDEV_TRIM_ACTIVE, VDEV_TRIM_CANCELED, VDEV_TRIM_SUSPENDED, VDEV_TRIM_COMPLETE, } vdev_trim_state_t; /* * Vdev statistics. Note: all fields should be 64-bit because this * is passed between kernel and user land as an nvlist uint64 array. * * The vs_ops[] and vs_bytes[] arrays must always be an array size of 6 in * order to keep subsequent members at their known fixed offsets. When * adding a new field it must be added to the end the structure. */ #define VS_ZIO_TYPES 6 typedef struct vdev_stat { hrtime_t vs_timestamp; /* time since vdev load */ uint64_t vs_state; /* vdev state */ uint64_t vs_aux; /* see vdev_aux_t */ uint64_t vs_alloc; /* space allocated */ uint64_t vs_space; /* total capacity */ uint64_t vs_dspace; /* deflated capacity */ uint64_t vs_rsize; /* replaceable dev size */ uint64_t vs_esize; /* expandable dev size */ uint64_t vs_ops[VS_ZIO_TYPES]; /* operation count */ uint64_t vs_bytes[VS_ZIO_TYPES]; /* bytes read/written */ uint64_t vs_read_errors; /* read errors */ uint64_t vs_write_errors; /* write errors */ uint64_t vs_checksum_errors; /* checksum errors */ uint64_t vs_initialize_errors; /* initializing errors */ uint64_t vs_self_healed; /* self-healed bytes */ uint64_t vs_scan_removing; /* removing? */ uint64_t vs_scan_processed; /* scan processed bytes */ uint64_t vs_fragmentation; /* device fragmentation */ uint64_t vs_initialize_bytes_done; /* bytes initialized */ uint64_t vs_initialize_bytes_est; /* total bytes to initialize */ uint64_t vs_initialize_state; /* vdev_initialzing_state_t */ uint64_t vs_initialize_action_time; /* time_t */ uint64_t vs_checkpoint_space; /* checkpoint-consumed space */ uint64_t vs_resilver_deferred; /* resilver deferred */ uint64_t vs_slow_ios; /* slow IOs */ uint64_t vs_trim_errors; /* trimming errors */ uint64_t vs_trim_notsup; /* supported by device */ uint64_t vs_trim_bytes_done; /* bytes trimmed */ uint64_t vs_trim_bytes_est; /* total bytes to trim */ uint64_t vs_trim_state; /* vdev_trim_state_t */ uint64_t vs_trim_action_time; /* time_t */ } vdev_stat_t; /* * Extended stats * * These are stats which aren't included in the original iostat output. For * convenience, they are grouped together in vdev_stat_ex, although each stat * is individually exported as a nvlist. */ typedef struct vdev_stat_ex { /* Number of ZIOs issued to disk and waiting to finish */ uint64_t vsx_active_queue[ZIO_PRIORITY_N_QUEUEABLE]; /* Number of ZIOs pending to be issued to disk */ uint64_t vsx_pend_queue[ZIO_PRIORITY_N_QUEUEABLE]; /* * Below are the histograms for various latencies. Buckets are in * units of nanoseconds. */ /* * 2^37 nanoseconds = 134s. Timeouts will probably start kicking in * before this. */ #define VDEV_L_HISTO_BUCKETS 37 /* Latency histo buckets */ #define VDEV_RQ_HISTO_BUCKETS 25 /* Request size histo buckets */ /* Amount of time in ZIO queue (ns) */ uint64_t vsx_queue_histo[ZIO_PRIORITY_N_QUEUEABLE] [VDEV_L_HISTO_BUCKETS]; /* Total ZIO latency (ns). Includes queuing and disk access time */ uint64_t vsx_total_histo[ZIO_TYPES][VDEV_L_HISTO_BUCKETS]; /* Amount of time to read/write the disk (ns) */ uint64_t vsx_disk_histo[ZIO_TYPES][VDEV_L_HISTO_BUCKETS]; /* "lookup the bucket for a value" macro */ #define HISTO(val, buckets) (val != 0 ? MIN(highbit64(val) - 1, \ buckets - 1) : 0) #define L_HISTO(a) HISTO(a, VDEV_L_HISTO_BUCKETS) #define RQ_HISTO(a) HISTO(a, VDEV_RQ_HISTO_BUCKETS) /* Physical IO histogram */ uint64_t vsx_ind_histo[ZIO_PRIORITY_N_QUEUEABLE] [VDEV_RQ_HISTO_BUCKETS]; /* Delegated (aggregated) physical IO histogram */ uint64_t vsx_agg_histo[ZIO_PRIORITY_N_QUEUEABLE] [VDEV_RQ_HISTO_BUCKETS]; } vdev_stat_ex_t; /* * DDT statistics. Note: all fields should be 64-bit because this * is passed between kernel and userland as an nvlist uint64 array. */ typedef struct ddt_object { uint64_t ddo_count; /* number of elments in ddt */ uint64_t ddo_dspace; /* size of ddt on disk */ uint64_t ddo_mspace; /* size of ddt in-core */ } ddt_object_t; typedef struct ddt_stat { uint64_t dds_blocks; /* blocks */ uint64_t dds_lsize; /* logical size */ uint64_t dds_psize; /* physical size */ uint64_t dds_dsize; /* deflated allocated size */ uint64_t dds_ref_blocks; /* referenced blocks */ uint64_t dds_ref_lsize; /* referenced lsize * refcnt */ uint64_t dds_ref_psize; /* referenced psize * refcnt */ uint64_t dds_ref_dsize; /* referenced dsize * refcnt */ } ddt_stat_t; typedef struct ddt_histogram { ddt_stat_t ddh_stat[64]; /* power-of-two histogram buckets */ } ddt_histogram_t; #define ZVOL_DRIVER "zvol" #define ZFS_DRIVER "zfs" #define ZFS_DEV "/dev/zfs" #define ZFS_DISK_ROOT "/dev/dsk" #define ZFS_DISK_ROOTD ZFS_DISK_ROOT "/" #define ZFS_RDISK_ROOT "/dev/rdsk" #define ZFS_RDISK_ROOTD ZFS_RDISK_ROOT "/" /* general zvol path */ #define ZVOL_DIR "/dev/zvol" /* expansion */ #define ZVOL_PSEUDO_DEV "/devices/pseudo/zfs@0:" /* for dump and swap */ #define ZVOL_FULL_DEV_DIR ZVOL_DIR "/dsk/" #define ZVOL_FULL_RDEV_DIR ZVOL_DIR "/rdsk/" #define ZVOL_PROP_NAME "name" #define ZVOL_DEFAULT_BLOCKSIZE 8192 /* * /dev/zfs ioctl numbers. */ typedef enum zfs_ioc { /* * Core features - 81/128 numbers reserved. */ #ifdef __FreeBSD__ ZFS_IOC_FIRST = 0, #else ZFS_IOC_FIRST = ('Z' << 8), #endif ZFS_IOC = ZFS_IOC_FIRST, ZFS_IOC_POOL_CREATE = ZFS_IOC_FIRST, /* 0x5a00 */ ZFS_IOC_POOL_DESTROY, /* 0x5a01 */ ZFS_IOC_POOL_IMPORT, /* 0x5a02 */ ZFS_IOC_POOL_EXPORT, /* 0x5a03 */ ZFS_IOC_POOL_CONFIGS, /* 0x5a04 */ ZFS_IOC_POOL_STATS, /* 0x5a05 */ ZFS_IOC_POOL_TRYIMPORT, /* 0x5a06 */ ZFS_IOC_POOL_SCAN, /* 0x5a07 */ ZFS_IOC_POOL_FREEZE, /* 0x5a08 */ ZFS_IOC_POOL_UPGRADE, /* 0x5a09 */ ZFS_IOC_POOL_GET_HISTORY, /* 0x5a0a */ ZFS_IOC_VDEV_ADD, /* 0x5a0b */ ZFS_IOC_VDEV_REMOVE, /* 0x5a0c */ ZFS_IOC_VDEV_SET_STATE, /* 0x5a0d */ ZFS_IOC_VDEV_ATTACH, /* 0x5a0e */ ZFS_IOC_VDEV_DETACH, /* 0x5a0f */ ZFS_IOC_VDEV_SETPATH, /* 0x5a10 */ ZFS_IOC_VDEV_SETFRU, /* 0x5a11 */ ZFS_IOC_OBJSET_STATS, /* 0x5a12 */ ZFS_IOC_OBJSET_ZPLPROPS, /* 0x5a13 */ ZFS_IOC_DATASET_LIST_NEXT, /* 0x5a14 */ ZFS_IOC_SNAPSHOT_LIST_NEXT, /* 0x5a15 */ ZFS_IOC_SET_PROP, /* 0x5a16 */ ZFS_IOC_CREATE, /* 0x5a17 */ ZFS_IOC_DESTROY, /* 0x5a18 */ ZFS_IOC_ROLLBACK, /* 0x5a19 */ ZFS_IOC_RENAME, /* 0x5a1a */ ZFS_IOC_RECV, /* 0x5a1b */ ZFS_IOC_SEND, /* 0x5a1c */ ZFS_IOC_INJECT_FAULT, /* 0x5a1d */ ZFS_IOC_CLEAR_FAULT, /* 0x5a1e */ ZFS_IOC_INJECT_LIST_NEXT, /* 0x5a1f */ ZFS_IOC_ERROR_LOG, /* 0x5a20 */ ZFS_IOC_CLEAR, /* 0x5a21 */ ZFS_IOC_PROMOTE, /* 0x5a22 */ ZFS_IOC_SNAPSHOT, /* 0x5a23 */ ZFS_IOC_DSOBJ_TO_DSNAME, /* 0x5a24 */ ZFS_IOC_OBJ_TO_PATH, /* 0x5a25 */ ZFS_IOC_POOL_SET_PROPS, /* 0x5a26 */ ZFS_IOC_POOL_GET_PROPS, /* 0x5a27 */ ZFS_IOC_SET_FSACL, /* 0x5a28 */ ZFS_IOC_GET_FSACL, /* 0x5a29 */ ZFS_IOC_SHARE, /* 0x5a2a */ ZFS_IOC_INHERIT_PROP, /* 0x5a2b */ ZFS_IOC_SMB_ACL, /* 0x5a2c */ ZFS_IOC_USERSPACE_ONE, /* 0x5a2d */ ZFS_IOC_USERSPACE_MANY, /* 0x5a2e */ ZFS_IOC_USERSPACE_UPGRADE, /* 0x5a2f */ ZFS_IOC_HOLD, /* 0x5a30 */ ZFS_IOC_RELEASE, /* 0x5a31 */ ZFS_IOC_GET_HOLDS, /* 0x5a32 */ ZFS_IOC_OBJSET_RECVD_PROPS, /* 0x5a33 */ ZFS_IOC_VDEV_SPLIT, /* 0x5a34 */ ZFS_IOC_NEXT_OBJ, /* 0x5a35 */ ZFS_IOC_DIFF, /* 0x5a36 */ ZFS_IOC_TMP_SNAPSHOT, /* 0x5a37 */ ZFS_IOC_OBJ_TO_STATS, /* 0x5a38 */ ZFS_IOC_SPACE_WRITTEN, /* 0x5a39 */ ZFS_IOC_SPACE_SNAPS, /* 0x5a3a */ ZFS_IOC_DESTROY_SNAPS, /* 0x5a3b */ ZFS_IOC_POOL_REGUID, /* 0x5a3c */ ZFS_IOC_POOL_REOPEN, /* 0x5a3d */ ZFS_IOC_SEND_PROGRESS, /* 0x5a3e */ ZFS_IOC_LOG_HISTORY, /* 0x5a3f */ ZFS_IOC_SEND_NEW, /* 0x5a40 */ ZFS_IOC_SEND_SPACE, /* 0x5a41 */ ZFS_IOC_CLONE, /* 0x5a42 */ ZFS_IOC_BOOKMARK, /* 0x5a43 */ ZFS_IOC_GET_BOOKMARKS, /* 0x5a44 */ ZFS_IOC_DESTROY_BOOKMARKS, /* 0x5a45 */ ZFS_IOC_POOL_SYNC, /* 0x5a46 */ ZFS_IOC_CHANNEL_PROGRAM, /* 0x5a47 */ ZFS_IOC_LOAD_KEY, /* 0x5a48 */ ZFS_IOC_UNLOAD_KEY, /* 0x5a49 */ ZFS_IOC_CHANGE_KEY, /* 0x5a4a */ ZFS_IOC_REMAP, /* 0x5a4b */ ZFS_IOC_POOL_CHECKPOINT, /* 0x5a4c */ ZFS_IOC_POOL_DISCARD_CHECKPOINT, /* 0x5a4d */ ZFS_IOC_POOL_INITIALIZE, /* 0x5a4e */ ZFS_IOC_POOL_TRIM, /* 0x5a4f */ ZFS_IOC_REDACT, /* 0x5a50 */ ZFS_IOC_GET_BOOKMARK_PROPS, /* 0x5a51 */ ZFS_IOC_WAIT, /* 0x5a52 */ /* * Per-platform (Optional) - 8/128 numbers reserved. */ ZFS_IOC_PLATFORM = ZFS_IOC_FIRST + 0x80, ZFS_IOC_EVENTS_NEXT, /* 0x81 (Linux) */ ZFS_IOC_EVENTS_CLEAR, /* 0x82 (Linux) */ ZFS_IOC_EVENTS_SEEK, /* 0x83 (Linux) */ ZFS_IOC_NEXTBOOT, /* 0x84 (FreeBSD) */ ZFS_IOC_JAIL, /* 0x85 (FreeBSD) */ ZFS_IOC_UNJAIL, /* 0x86 (FreeBSD) */ ZFS_IOC_SET_BOOTENV, /* 0x87 */ ZFS_IOC_GET_BOOTENV, /* 0x88 */ ZFS_IOC_LAST } zfs_ioc_t; /* * ZFS-specific error codes used for returning descriptive errors * to the userland through zfs ioctls. * * The enum implicitly includes all the error codes from errno.h. * New code should use and extend this enum for errors that are * not described precisely by generic errno codes. */ typedef enum { ZFS_ERR_CHECKPOINT_EXISTS = 1024, ZFS_ERR_DISCARDING_CHECKPOINT, ZFS_ERR_NO_CHECKPOINT, ZFS_ERR_DEVRM_IN_PROGRESS, ZFS_ERR_VDEV_TOO_BIG, ZFS_ERR_FROM_IVSET_GUID_MISSING, ZFS_ERR_FROM_IVSET_GUID_MISMATCH, ZFS_ERR_SPILL_BLOCK_FLAG_MISSING, ZFS_ERR_UNKNOWN_SEND_STREAM_FEATURE, ZFS_ERR_IOC_CMD_UNAVAIL, ZFS_ERR_IOC_ARG_UNAVAIL, ZFS_ERR_IOC_ARG_REQUIRED, ZFS_ERR_IOC_ARG_BADTYPE, } zfs_errno_t; /* * Internal SPA load state. Used by FMA diagnosis engine. */ typedef enum { SPA_LOAD_NONE, /* no load in progress */ SPA_LOAD_OPEN, /* normal open */ SPA_LOAD_IMPORT, /* import in progress */ SPA_LOAD_TRYIMPORT, /* tryimport in progress */ SPA_LOAD_RECOVER, /* recovery requested */ SPA_LOAD_ERROR, /* load failed */ SPA_LOAD_CREATE /* creation in progress */ } spa_load_state_t; /* supported encryption algorithms */ enum zio_encrypt { ZIO_CRYPT_INHERIT = 0, ZIO_CRYPT_ON, ZIO_CRYPT_OFF, ZIO_CRYPT_AES_128_CCM, ZIO_CRYPT_AES_192_CCM, ZIO_CRYPT_AES_256_CCM, ZIO_CRYPT_AES_128_GCM, ZIO_CRYPT_AES_192_GCM, ZIO_CRYPT_AES_256_GCM, ZIO_CRYPT_FUNCTIONS }; typedef enum { ZPOOL_WAIT_CKPT_DISCARD, ZPOOL_WAIT_FREE, ZPOOL_WAIT_INITIALIZE, ZPOOL_WAIT_REPLACE, ZPOOL_WAIT_REMOVE, ZPOOL_WAIT_RESILVER, ZPOOL_WAIT_SCRUB, ZPOOL_WAIT_NUM_ACTIVITIES } zpool_wait_activity_t; /* * Bookmark name values. */ #define ZPOOL_ERR_LIST "error list" #define ZPOOL_ERR_DATASET "dataset" #define ZPOOL_ERR_OBJECT "object" #define HIS_MAX_RECORD_LEN (MAXPATHLEN + MAXPATHLEN + 1) /* * The following are names used in the nvlist describing * the pool's history log. */ #define ZPOOL_HIST_RECORD "history record" #define ZPOOL_HIST_TIME "history time" #define ZPOOL_HIST_CMD "history command" #define ZPOOL_HIST_WHO "history who" #define ZPOOL_HIST_ZONE "history zone" #define ZPOOL_HIST_HOST "history hostname" #define ZPOOL_HIST_TXG "history txg" #define ZPOOL_HIST_INT_EVENT "history internal event" #define ZPOOL_HIST_INT_STR "history internal str" #define ZPOOL_HIST_INT_NAME "internal_name" #define ZPOOL_HIST_IOCTL "ioctl" #define ZPOOL_HIST_INPUT_NVL "in_nvl" #define ZPOOL_HIST_OUTPUT_NVL "out_nvl" #define ZPOOL_HIST_DSNAME "dsname" #define ZPOOL_HIST_DSID "dsid" #define ZPOOL_HIST_ERRNO "errno" /* * The following are names used when invoking ZFS_IOC_POOL_INITIALIZE. */ #define ZPOOL_INITIALIZE_COMMAND "initialize_command" #define ZPOOL_INITIALIZE_VDEVS "initialize_vdevs" /* * Special nvlist name that will not have its args recorded in the pool's * history log. */ #define ZPOOL_HIDDEN_ARGS "hidden_args" /* * The following are names used when invoking ZFS_IOC_POOL_TRIM. */ #define ZPOOL_TRIM_COMMAND "trim_command" #define ZPOOL_TRIM_VDEVS "trim_vdevs" #define ZPOOL_TRIM_RATE "trim_rate" #define ZPOOL_TRIM_SECURE "trim_secure" /* * The following are names used when invoking ZFS_IOC_POOL_WAIT. */ #define ZPOOL_WAIT_ACTIVITY "wait_activity" #define ZPOOL_WAIT_TAG "wait_tag" #define ZPOOL_WAIT_WAITED "wait_waited" /* * Flags for ZFS_IOC_VDEV_SET_STATE */ #define ZFS_ONLINE_CHECKREMOVE 0x1 #define ZFS_ONLINE_UNSPARE 0x2 #define ZFS_ONLINE_FORCEFAULT 0x4 #define ZFS_ONLINE_EXPAND 0x8 #define ZFS_OFFLINE_TEMPORARY 0x1 /* * Flags for ZFS_IOC_POOL_IMPORT */ #define ZFS_IMPORT_NORMAL 0x0 #define ZFS_IMPORT_VERBATIM 0x1 #define ZFS_IMPORT_ANY_HOST 0x2 #define ZFS_IMPORT_MISSING_LOG 0x4 #define ZFS_IMPORT_ONLY 0x8 #define ZFS_IMPORT_CHECKPOINT 0x10 #define ZFS_IMPORT_TEMP_NAME 0x20 #define ZFS_IMPORT_SKIP_MMP 0x40 #define ZFS_IMPORT_LOAD_KEYS 0x80 /* * Channel program argument/return nvlist keys and defaults. */ #define ZCP_ARG_PROGRAM "program" #define ZCP_ARG_ARGLIST "arg" #define ZCP_ARG_SYNC "sync" #define ZCP_ARG_INSTRLIMIT "instrlimit" #define ZCP_ARG_MEMLIMIT "memlimit" #define ZCP_ARG_CLIARGV "argv" #define ZCP_RET_ERROR "error" #define ZCP_RET_RETURN "return" #define ZCP_DEFAULT_INSTRLIMIT (10 * 1000 * 1000) #define ZCP_MAX_INSTRLIMIT (10 * ZCP_DEFAULT_INSTRLIMIT) #define ZCP_DEFAULT_MEMLIMIT (10 * 1024 * 1024) #define ZCP_MAX_MEMLIMIT (10 * ZCP_DEFAULT_MEMLIMIT) /* * Sysevent payload members. ZFS will generate the following sysevents with the * given payloads: * * ESC_ZFS_RESILVER_START * ESC_ZFS_RESILVER_END * ESC_ZFS_POOL_DESTROY * ESC_ZFS_POOL_REGUID * * ZFS_EV_POOL_NAME DATA_TYPE_STRING * ZFS_EV_POOL_GUID DATA_TYPE_UINT64 * * ESC_ZFS_VDEV_REMOVE * ESC_ZFS_VDEV_CLEAR * ESC_ZFS_VDEV_CHECK * * ZFS_EV_POOL_NAME DATA_TYPE_STRING * ZFS_EV_POOL_GUID DATA_TYPE_UINT64 * ZFS_EV_VDEV_PATH DATA_TYPE_STRING (optional) * ZFS_EV_VDEV_GUID DATA_TYPE_UINT64 * * ESC_ZFS_HISTORY_EVENT * * ZFS_EV_POOL_NAME DATA_TYPE_STRING * ZFS_EV_POOL_GUID DATA_TYPE_UINT64 * ZFS_EV_HIST_TIME DATA_TYPE_UINT64 (optional) * ZFS_EV_HIST_CMD DATA_TYPE_STRING (optional) * ZFS_EV_HIST_WHO DATA_TYPE_UINT64 (optional) * ZFS_EV_HIST_ZONE DATA_TYPE_STRING (optional) * ZFS_EV_HIST_HOST DATA_TYPE_STRING (optional) * ZFS_EV_HIST_TXG DATA_TYPE_UINT64 (optional) * ZFS_EV_HIST_INT_EVENT DATA_TYPE_UINT64 (optional) * ZFS_EV_HIST_INT_STR DATA_TYPE_STRING (optional) * ZFS_EV_HIST_INT_NAME DATA_TYPE_STRING (optional) * ZFS_EV_HIST_IOCTL DATA_TYPE_STRING (optional) * ZFS_EV_HIST_DSNAME DATA_TYPE_STRING (optional) * ZFS_EV_HIST_DSID DATA_TYPE_UINT64 (optional) * * The ZFS_EV_HIST_* members will correspond to the ZPOOL_HIST_* members in the * history log nvlist. The keynames will be free of any spaces or other * characters that could be potentially unexpected to consumers of the * sysevents. */ #define ZFS_EV_POOL_NAME "pool_name" #define ZFS_EV_POOL_GUID "pool_guid" #define ZFS_EV_VDEV_PATH "vdev_path" #define ZFS_EV_VDEV_GUID "vdev_guid" #define ZFS_EV_HIST_TIME "history_time" #define ZFS_EV_HIST_CMD "history_command" #define ZFS_EV_HIST_WHO "history_who" #define ZFS_EV_HIST_ZONE "history_zone" #define ZFS_EV_HIST_HOST "history_hostname" #define ZFS_EV_HIST_TXG "history_txg" #define ZFS_EV_HIST_INT_EVENT "history_internal_event" #define ZFS_EV_HIST_INT_STR "history_internal_str" #define ZFS_EV_HIST_INT_NAME "history_internal_name" #define ZFS_EV_HIST_IOCTL "history_ioctl" #define ZFS_EV_HIST_DSNAME "history_dsname" #define ZFS_EV_HIST_DSID "history_dsid" #ifdef __cplusplus } #endif #endif /* _SYS_FS_ZFS_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _ZUT_H #define _ZUT_H /* * IOCTLs for the zfs unit test driver */ #ifdef __cplusplus extern "C" { #endif #include #include #include #define ZUT_DRIVER "zut" #define ZUT_DEV "/dev/zut" #define ZUT_VERSION_STRING "1" /* * /dev/zut ioctl numbers. */ #define ZUT_IOC ('U' << 8) /* Request flags */ #define ZUT_IGNORECASE 0x01 #define ZUT_ACCFILTER 0x02 #define ZUT_XATTR 0x04 #define ZUT_EXTRDDIR 0x08 #define ZUT_GETSTAT 0x10 typedef struct zut_lookup { int zl_reqflags; int zl_deflags; /* output */ int zl_retcode; /* output */ char zl_dir[MAXPATHLEN]; char zl_file[MAXNAMELEN]; char zl_xfile[MAXNAMELEN]; char zl_real[MAXPATHLEN]; /* output */ uint64_t zl_xvattrs; /* output */ struct stat64 zl_statbuf; /* output */ } zut_lookup_t; typedef struct zut_readdir { uint64_t zr_buf; /* pointer to output buffer */ uint64_t zr_loffset; /* output */ char zr_dir[MAXPATHLEN]; char zr_file[MAXNAMELEN]; int zr_reqflags; int zr_retcode; /* output */ int zr_eof; /* output */ uint_t zr_bytes; /* output */ uint_t zr_buflen; } zut_readdir_t; typedef enum zut_ioc { ZUT_IOC_MIN_CMD = ZUT_IOC - 1, ZUT_IOC_LOOKUP = ZUT_IOC, ZUT_IOC_READDIR, ZUT_IOC_MAX_CMD } zut_ioc_t; #ifdef __cplusplus } #endif #endif /* _ZUT_H */