/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ /* All Rights Reserved */ /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */ /* UNIX System Laboratories, Inc. */ /* The copyright notice above does not evidence any */ /* actual or intended publication of such source code. */ /* * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * PROPRIETARY NOTICE (Combined) * * This source code is unpublished proprietary information * constituting, or derived under license from AT&T's UNIX(r) System V. * In addition, portions of such source code were derived from Berkeley * 4.3 BSD under license from the Regents of the University of * California. * * Copyright Notice * * Notice of copyright on this source code product does not indicate * publication. * * (c) 1986,1987,1988,1989 Sun Microsystems, Inc * (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. * All rights reserved. * */ #ifndef _FS_VNODE_H /* wrapper symbol for kernel use */ #define _FS_VNODE_H /* subject to change without notice */ #ident "$Revision: 1.197 $" #include #include #include #include #include #include #include #include #include /* * The vnode is the focus of all file activity in UNIX. * A vnode is allocated for each active file, each current * directory, each mounted-on file, and the root. */ /* * vnode types. VNON means no type. These values are unrelated to * values in on-disk inodes. */ typedef enum vtype { VNON = 0, VREG = 1, VDIR = 2, VBLK = 3, VCHR = 4, VLNK = 5, VFIFO = 6, VBAD = 7, VSOCK = 8 } vtype_t; #define ISVDEV(t) \ ((t) == VCHR || (t) == VBLK || (t) == VFIFO) /* * The prefix of a vnode struct is its freelist linkage. The freelist * header has two pointers so we can insert at either end. */ typedef struct vnlist { struct vnode *vl_next; struct vnode *vl_prev; } vnlist_t; typedef uint64_t vnumber_t; /* * Define the type of behavior head used by vnodes. */ #ifdef VNODE_BHV_SYNCH #define vn_bhv_head_t bhv2_head_t #else #define vn_bhv_head_t bhv_head_t #endif /* * MP locking protocols: * v_flag, v_count, v_vfsmountedhere VN_LOCK/VN_UNLOCK * v_vfsmountedhere VN_LOCK covered vnode before * acquiring vfslock around any * v_vfsmountedhere dereference * v_vfsp VN_LOCK/VN_UNLOCK * v_stream streams monitor * v_pgcnt mem_lock/mem_unlock * v_type read-only or fs-dependent * v_filocks vfilockmon, in reclock() * v_list, v_hashp, v_hashn freelist lock * v_intpcount VN_LOCK/VN_UNLOCK */ typedef struct vnode { struct vnlist v_list; /* freelist linkage */ uint v_flag; /* vnode flags (see below) */ int v_count; /* reference count */ short v_listid; /* free list id */ int v_intpcount; /* interp. refcount for imon */ enum vtype v_type; /* vnode type */ dev_t v_rdev; /* device (VCHR, VBLK) */ struct vfs *v_vfsmountedhere; /* ptr to vfs mounted here */ struct vfs *v_vfsp; /* ptr to containing VFS */ struct stdata *v_stream; /* associated stream */ struct filock *v_filocks; /* ptr to filock list */ mutex_t v_filocksem; /* mutex for list */ vnumber_t v_number; /* in-core vnode number */ vn_bhv_head_t v_bh; /* behavior head */ uint64_t v_namecap; /* name cache capability */ /* * Used only by global cache. */ struct vnode *v_hashp; /* hash list for lookup */ struct vnode *v_hashn; /* hash list for lookup */ /* * Values manipulated only by VM and * the page/buffer caches. Note that v_traceix, which * has been shoehorned in here to use otherwise-unused space * is an exception. */ struct pregion *v_mreg; /* mapped file region pointer */ struct pregion *v_mregb; /* mapped file region pointer */ pgno_t v_pgcnt; /* pages hashed to vnode */ struct pfdat *v_dpages; /* delwri pages */ unsigned int v_dpages_gen; /* delwri pages generation no */ int v_dbuf; /* delwri buffer count */ struct buf *v_buf; /* vnode buffer tree head */ unsigned int v_bufgen; /* buf list generation number */ unsigned int v_traceix; /* trace table index */ mutex_t v_buf_lock; /* mutex for buffer tree */ vnode_pcache_t v_pc; /* Page cache structure. * per vnode. Refer to * vnode_pcache.h * for details. */ #ifdef VNODE_TRACING struct ktrace *v_trace; /* trace header structure */ #endif /* VNODE_TRACING */ #ifdef CKPT ckpt_handle_t v_ckpt; /* ckpt lookup info */ #endif } vnode_t; #define v_next v_list.vl_next #define v_prev v_list.vl_prev /* * Vnode flags. * XXX When a new flag is added or an old one deleted, * *tab_vflags[] in io/idbg.c needs be kept in sync. * * XXX Also, must consider whether a flag is "local only" or "single * system image" as described below. Consult an expert if nec. * * The vnode flags fall into two categories: * 1) Local only - * Flags that are relevant only to a particular cell * 2) Single system image - * Flags that must be maintained coherent across all cells */ /* Local only flags */ #define VDUP 0x1 /* file should be dup'ed rather then opened */ #define VINACT 0x2 /* vnode is being inactivated */ #define VRECLM 0x4 /* vnode is being reclaimed */ #define VLOCK 0x8 /* lock bit for vnode */ #define VEVICT 0x10 /* vnode will be inactivated */ #define VWAIT 0x20 /* waiting for VINACT or VRECLM to finish */ #define VFLUSH 0x40 /* vnode being flushed */ #define VGONE 0x80 /* vnode isn't really here */ #define VREMAPPING 0x100 /* file data flush/inval in progress */ #define VMOUNTING 0x200 /* mount in progress on vnode */ #define VLOCKHOLD 0x400 /* VN_HOLD for remote locks */ #define VDFSCONVERTED 0x800 /* vnops have been converted to DFS format */ #define VROOTMOUNTOK 0x1000 /* ok to mount on top of this root */ #define VINACTIVE_TEARDOWN 0x2000 /* vnode torn down at inactive time */ #define VSEMAPHORE 0x4000 /* vnode represents a Posix named semaphore */ #define VUSYNC 0x8000 /* vnode aspace represents usync objects */ /* Single system image flags */ #define VROOT 0x100000 /* root of its file system */ #define VNOSWAP 0x200000 /* file cannot be used as virt. swap device */ #define VISSWAP 0x400000 /* vnode is part of virtual swap device */ #define VREPLICABLE 0x800000 /* Vnode can have replicated pages */ #define VNONREPLICABLE 0x1000000 /* Vnode has writers. Don't replicate */ #define VDOCMP 0x2000000 /* Vnode has special VOP_CMP impl. */ #define VSHARE 0x4000000 /* vnode part of global cache */ #define VFRLOCKS 0x8000000 /* vnode has FR locks applied */ #define VENF_LOCKING 0x10000000 /* enf. mode FR locking in effect */ /* * Flags for vnode operations. */ enum rm { RMFILE, RMDIRECTORY }; /* rm or rmdir (remove) */ enum symfollow { NO_FOLLOW, FOLLOW }; /* follow symlinks (or not) */ enum create { CROPEN = -1, CRCREAT, CRMKNOD, CRMKDIR, CRCORE }; /* reason for create */ enum vrwlock { VRWLOCK_NONE, VRWLOCK_READ, VRWLOCK_WRITE, VRWLOCK_WRITE_DIRECT }; /* type of rw lock */ enum vaddmap { VNEWMAP, VITERMAP, VDUPMAP }; /* op for ADDMAP */ /* * flags for vn_create/VOP_CREATE/vn_open */ #define VEXCL 0x0001 #define VZFS 0x0002 /* caller has a 0 RLIMIT_FSIZE */ typedef enum rm rm_t; typedef enum symfollow symfollow_t; typedef enum create create_t; typedef enum vrwlock vrwlock_t; typedef enum vaddmap vaddmap_t; /* * FROM_VN_KILL is a special 'kill' flag to VOP_CLOSE to signify a call * from vn_kill. This is passed as the lastclose field */ typedef enum { L_FALSE, L_TRUE, FROM_VN_KILL } lastclose_t; /* * Return values for VOP_INACTIVE. A return value of * VN_INACTIVE_NOCACHE implies that the file system behavior * has disassociated its state and bhv_desc_t from the vnode. * To return VN_INACTIVE_NOCACHE, the vnode must have the * VINACTIVE_TEARDOWN flag set. */ #define VN_INACTIVE_CACHE 0 #define VN_INACTIVE_NOCACHE 1 /* * Values for the cmd code given to VOP_VNODE_CHANGE. */ typedef enum vchange { VCHANGE_FLAGS_FRLOCKS = 0, VCHANGE_FLAGS_ENF_LOCKING = 1 #ifdef CELL , VCHANGE_FLAGS_TRUNCATED = 2 #endif } vchange_t; /* * Macros for dealing with the behavior descriptor inside of the vnode. * * VNODE_BHV_SYNCH indicates that the vnode's behavior head has * synchronization enabled (i.e., changes to the behavior chain are * synchronized with ops-in-progress on the vnode). */ #define BHV_TO_VNODE(bdp) ((vnode_t *)BHV_VOBJ(bdp)) #ifdef VNODE_BHV_SYNCH #define VNODE_TO_FIRST_BHV(vp) (BHV2_HEAD_FIRST(&(vp)->v_bh)) #define VN_BHV_HEAD(vp) ((vn_bhv_head_t *)(&((vp)->v_bh))) #define VN_BHV_READ_LOCK(bhp) BHV2_READ_LOCK(bhp) #define VN_BHV_READ_UNLOCK(bhp) BHV2_READ_UNLOCK(bhp) #define VN_BHV_WRITE_LOCK(bhp) BHV2_WRITE_LOCK(bhp) #define VN_BHV_WRITE_UNLOCK(bhp) BHV2_WRITE_UNLOCK(bhp) #define VN_BHV_WRITE_TO_READ(bhp) BHV2_WRITE_TO_READ(bhp) #define VN_BHV_IS_READ_LOCKED(bhp) BHV2_IS_READ_LOCKED(bhp) #define VN_BHV_NOT_READ_LOCKED(bhp) BHV2_NOT_READ_LOCKED(bhp) #define VN_BHV_IS_WRITE_LOCKED(bhp) BHV2_IS_WRITE_LOCKED(bhp) #define VN_BHV_NOT_WRITE_LOCKED(bhp) BHV2_NOT_WRITE_LOCKED(bhp) #define vn_bhv_lock_init(bhp,name) bhv2_lock_init(bhp,name) #define vn_bhv_lock_free(bhp) bhv2_lock_free(bhp) #define vn_bhv_head_init(bhp,name) bhv2_head_init(bhp,name) #define vn_bhv_head_destroy(bhp) bhv2_head_destroy(bhp) #define vn_bhv_head_reinit(bhp) bhv2_head_reinit(bhp) #define vn_bhv_insert_initial(bhp,bdp) bhv2_insert_initial(bhp,bdp) #define vn_bhv_remove(bhp,bdp) bhv2_remove(bhp,bdp) #define vn_bhv_insert(bhp,bdp) bhv2_insert(bhp,bdp) #define vn_bhv_remove_not_first(bhp,bdp) bhv2_remove_not_first(bhp,bdp) #define vn_bhv_lookup(bhp,ops) bhv2_lookup(bhp,ops) #define vn_bhv_lookup_unlocked(bhp,ops) bhv2_lookup_unlocked(bhp,ops) #define vn_bhv_base_unlocked(bhp) bhv2_base_unlocked(bhp) #define v_fbhv v_bh.bh2_first /* first behavior */ #define v_fops v_bh.bh2_first->bd_ops /* ops for first behavior */ #else /* VNODE_BHV_SYNCH */ #define VNODE_TO_FIRST_BHV(vp) (BHV_HEAD_FIRST(&(vp)->v_bh)) #define VN_BHV_HEAD(vp) ((vn_bhv_head_t *)(&((vp)->v_bh))) #define VN_BHV_READ_LOCK(bhp) BHV_READ_LOCK(bhp) #define VN_BHV_READ_UNLOCK(bhp) BHV_READ_UNLOCK(bhp) #define VN_BHV_WRITE_LOCK(bhp) BHV_WRITE_LOCK(bhp) #define VN_BHV_WRITE_UNLOCK(bhp) BHV_WRITE_UNLOCK(bhp) #define VN_BHV_WRITE_TO_READ(bhp) BHV_WRITE_TO_READ(bhp) #define VN_BHV_IS_READ_LOCKED(bhp) BHV_IS_READ_LOCKED(bhp) #define VN_BHV_NOT_READ_LOCKED(bhp) BHV_NOT_READ_LOCKED(bhp) #define VN_BHV_IS_WRITE_LOCKED(bhp) BHV_IS_WRITE_LOCKED(bhp) #define VN_BHV_NOT_WRITE_LOCKED(bhp) BHV_NOT_WRITE_LOCKED(bhp) #define vn_bhv_lock_init(bhp,name) bhv_lock_init(bhp,name) #define vn_bhv_lock_free(bhp) bhv_lock_free(bhp) #define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name) #define vn_bhv_head_destroy(bhp) bhv_head_destroy(bhp) #define vn_bhv_head_reinit(bhp) bhv_head_reinit(bhp) #define vn_bhv_insert_initial(bhp,bdp) bhv_insert_initial(bhp,bdp) #define vn_bhv_remove(bhp,bdp) bhv_remove(bhp,bdp) #define vn_bhv_insert(bhp,bdp) bhv_insert(bhp,bdp) #define vn_bhv_remove_not_first(bhp,bdp) bhv_remove_not_first(bhp,bdp) #define vn_bhv_lookup(bhp,ops) bhv_lookup(bhp,ops) #define vn_bhv_lookup_unlocked(bhp,ops) bhv_lookup_unlocked(bhp,ops) #define vn_bhv_base_unlocked(bhp) bhv_base_unlocked(bhp) #define v_fbhv v_bh.bh_first /* first behavior */ #define v_fops v_bh.bh_first->bd_ops /* ops for first behavior */ #endif /* VNODE_BHV_SYNCH */ /* * Operations on vnodes. */ struct cred; struct vfs; struct buf; struct vattr; struct flock; struct pathname; struct bmapval; struct pollhead; struct fid; struct flid; struct pfdat; union rval; struct attrlist_cursor_kern; struct __vhandl_s; struct vopbd; struct strbuf; #define VNODE_CHECK_OPSVER(vp, ver) VFS_CHECK_OPSVER((vp)->v_vfsp, ver) #define VNODE_CHECK_OPSFLAG(vp, flag) VFS_CHECK_OPSFLAG((vp->v_vfsp, flag) typedef int (*vop_open_t)(bhv_desc_t *, vnode_t **, mode_t, struct cred *); typedef int (*vop_close_t)(bhv_desc_t *, int, lastclose_t, struct cred *); typedef int (*vop_read_t)(bhv_desc_t *, struct uio *, int, struct cred *, struct flid *); typedef int (*vop_write_t)(bhv_desc_t *, struct uio *, int, struct cred *, struct flid *); typedef int (*vop_ioctl_t)(bhv_desc_t *, int, void *, int, struct cred *, int *, struct vopbd *); typedef int (*vop_setfl_t)(bhv_desc_t *, int, int, struct cred *); typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, struct cred *); typedef int (*vop_setattr_t)(bhv_desc_t *, struct vattr *, int, struct cred *); typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *); typedef int (*vop_lookup_t)(bhv_desc_t *, char *, vnode_t **, struct pathname *, int, vnode_t *, struct cred *); typedef int (*vop_create_t)(bhv_desc_t *, char *, struct vattr *, int, int, vnode_t **, struct cred *); typedef int (*vop_remove_t)(bhv_desc_t *, char *, struct cred *); typedef int (*vop_link_t)(bhv_desc_t *, vnode_t *, char *, struct cred *); typedef int (*vop_rename_t)(bhv_desc_t *, char *, vnode_t *, char *, struct pathname *npnp, struct cred *); typedef int (*vop_mkdir_t)(bhv_desc_t *, char *, struct vattr *, vnode_t **, struct cred *); typedef int (*vop_rmdir_t)(bhv_desc_t *, char *, vnode_t *, struct cred *); typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, int *); typedef int (*vop_symlink_t)(bhv_desc_t *, char *, struct vattr *, char *, struct cred *); typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, struct cred *); typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, off_t, off_t); typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *); typedef int (*vop_fid_t)(bhv_desc_t *, struct fid **); typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *); typedef void (*vop_rwlock_t)(bhv_desc_t *, vrwlock_t); typedef void (*vop_rwunlock_t)(bhv_desc_t *, vrwlock_t); typedef int (*vop_seek_t)(bhv_desc_t *, off_t, off_t*); typedef int (*vop_cmp_t)(bhv_desc_t *, vnode_t *); typedef int (*vop_frlock_t)(bhv_desc_t *, int, struct flock *, int, off_t, vrwlock_t, struct cred *); typedef int (*vop_realvp_t)(bhv_desc_t *, vnode_t **); typedef int (*vop_bmap_t)(bhv_desc_t *, off_t, ssize_t, int, struct cred *, struct bmapval *, int *); typedef void (*vop_strategy_t)(bhv_desc_t *, struct buf *); typedef int (*vop_map_t)(bhv_desc_t *, off_t, size_t, mprot_t, u_int, struct cred *, vnode_t **); typedef int (*vop_addmap_t)(bhv_desc_t *, vaddmap_t, struct __vhandl_s *, pgno_t *, off_t, size_t, mprot_t, struct cred *); typedef int (*vop_delmap_t)(bhv_desc_t *, struct __vhandl_s *, size_t, struct cred *); typedef int (*vop_poll_t)(bhv_desc_t *, short, int, short *, struct pollhead **, unsigned int *); typedef int (*vop_dump_t)(bhv_desc_t *, caddr_t, daddr_t, u_int); typedef int (*vop_pathconf_t)(bhv_desc_t *, int, long *, struct cred *); typedef int (*vop_allocstore_t)(bhv_desc_t *, off_t, size_t, struct cred *); typedef int (*vop_fcntl_t)(bhv_desc_t *, int, void *, int, off_t, struct cred *, union rval *); typedef int (*vop_reclaim_t)(bhv_desc_t *, int); typedef int (*vop_attr_get_t)(bhv_desc_t *, char *, char *, int *, int, struct cred *); typedef int (*vop_attr_set_t)(bhv_desc_t *, char *, char *, int, int, struct cred *); typedef int (*vop_attr_remove_t)(bhv_desc_t *, char *, int, struct cred *); typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *); typedef int (*vop_cover_t)(bhv_desc_t *, struct mounta *, char *, struct cred *); typedef void (*vop_link_removed_t)(bhv_desc_t *, vnode_t *, int); typedef void (*vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psint_t); typedef void (*vop_ptossvp_t)(bhv_desc_t *, off_t, off_t, int); typedef void (*vop_pflushinvalvp_t)(bhv_desc_t *, off_t, off_t, int); typedef int (*vop_pflushvp_t)(bhv_desc_t *, off_t, off_t, uint64_t, int); typedef void (*vop_pinvalfree_t)(bhv_desc_t *, off_t); typedef void (*vop_sethole_t)(bhv_desc_t *, struct pfdat*, int, int, off_t); typedef int (*vop_commit_t)(bhv_desc_t *, struct buf *); typedef int (*vop_readbuf_t)(bhv_desc_t *, off_t, ssize_t, int, struct cred *, struct flid *, struct buf **, int *, int *); typedef int (*vop_strgetmsg_t)(bhv_desc_t *, struct strbuf *, struct strbuf *, unsigned char *, int *, int, union rval *); typedef int (*vop_strputmsg_t)(bhv_desc_t *, struct strbuf *, struct strbuf *, unsigned char, int, int); typedef struct vnodeops { bhv_position_t vn_position; /* position within behavior chain */ vop_open_t vop_open; vop_close_t vop_close; vop_read_t vop_read; vop_write_t vop_write; vop_ioctl_t vop_ioctl; vop_setfl_t vop_setfl; vop_getattr_t vop_getattr; vop_setattr_t vop_setattr; vop_access_t vop_access; vop_lookup_t vop_lookup; vop_create_t vop_create; vop_remove_t vop_remove; vop_link_t vop_link; vop_rename_t vop_rename; vop_mkdir_t vop_mkdir; vop_rmdir_t vop_rmdir; vop_readdir_t vop_readdir; vop_symlink_t vop_symlink; vop_readlink_t vop_readlink; vop_fsync_t vop_fsync; vop_inactive_t vop_inactive; vop_fid_t vop_fid; vop_fid2_t vop_fid2; vop_rwlock_t vop_rwlock; vop_rwunlock_t vop_rwunlock; vop_seek_t vop_seek; vop_cmp_t vop_cmp; vop_frlock_t vop_frlock; vop_realvp_t vop_realvp; vop_bmap_t vop_bmap; vop_strategy_t vop_strategy; vop_map_t vop_map; vop_addmap_t vop_addmap; vop_delmap_t vop_delmap; vop_poll_t vop_poll; vop_dump_t vop_dump; vop_pathconf_t vop_pathconf; vop_allocstore_t vop_allocstore; vop_fcntl_t vop_fcntl; vop_reclaim_t vop_reclaim; vop_attr_get_t vop_attr_get; vop_attr_set_t vop_attr_set; vop_attr_remove_t vop_attr_remove; vop_attr_list_t vop_attr_list; vop_cover_t vop_cover; vop_link_removed_t vop_link_removed; vop_vnode_change_t vop_vnode_change; vop_ptossvp_t vop_tosspages; vop_pflushinvalvp_t vop_flushinval_pages; vop_pflushvp_t vop_flush_pages; vop_pinvalfree_t vop_invalfree_pages; vop_sethole_t vop_pages_sethole; vop_commit_t vop_commit; vop_readbuf_t vop_readbuf; vop_strgetmsg_t vop_strgetmsg; vop_strputmsg_t vop_strputmsg; } vnodeops_t; /* * VOP's. */ #define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op) /* * Be careful with VOP_OPEN, since we're holding the chain lock on the * original vnode and VOP_OPEN semantic allows the new vnode to be returned * in vpp. The practice of passing &vp for vpp just doesn't work. */ #define VOP_OPEN(vp, vpp, mode, cr, rv) \ { \ ASSERT(&(vp) != vpp); \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_open, vp)((vp)->v_fbhv, vpp, mode, cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_CLOSE(vp,f,c,cr,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_close, vp)((vp)->v_fbhv,f,c,cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_READ(vp,uiop,iof,cr,fl,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_read, vp)((vp)->v_fbhv,uiop,iof,cr,fl); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_WRITE(vp,uiop,iof,cr,fl,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_write, vp)((vp)->v_fbhv,uiop,iof,cr,fl); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_IOCTL(vp,cmd,a,f,cr,rvp,vopbdp,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,cmd,a,f,cr,rvp,vopbdp); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_SETFL(vp, f, a, cr, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_setfl, vp)((vp)->v_fbhv, f, a, cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_GETATTR(vp, vap, f, cr, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_SETATTR(vp, vap, f, cr, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ACCESS(vp, mode, cr, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_LOOKUP(vp,cp,vpp,pnp,f,rdir,cr,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,cp,vpp,pnp,f,rdir,cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_CREATE(dvp,p,vap,ex,mode,vpp,cr,rv) \ { \ VN_BHV_READ_LOCK(&(dvp)->v_bh); \ rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,p,vap,ex,mode,vpp,cr);\ VN_BHV_READ_UNLOCK(&(dvp)->v_bh); \ } #define VOP_REMOVE(dvp,p,cr,rv) \ { \ VN_BHV_READ_LOCK(&(dvp)->v_bh); \ rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,p,cr); \ VN_BHV_READ_UNLOCK(&(dvp)->v_bh); \ } #define VOP_LINK(tdvp,fvp,p,cr,rv) \ { \ VN_BHV_READ_LOCK(&(tdvp)->v_bh); \ rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,p,cr); \ VN_BHV_READ_UNLOCK(&(tdvp)->v_bh); \ } #define VOP_RENAME(fvp,fnm,tdvp,tnm,tpnp,cr,rv) \ { \ VN_BHV_READ_LOCK(&(fvp)->v_bh); \ rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,tpnp,cr);\ VN_BHV_READ_UNLOCK(&(fvp)->v_bh); \ } #define VOP_MKDIR(dp,p,vap,vpp,cr,rv) \ { \ VN_BHV_READ_LOCK(&(dp)->v_bh); \ rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,p,vap,vpp,cr); \ VN_BHV_READ_UNLOCK(&(dp)->v_bh); \ } #define VOP_RMDIR(dp,p,cdir,cr,rv) \ { \ VN_BHV_READ_LOCK(&(dp)->v_bh); \ rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,p,cdir,cr); \ VN_BHV_READ_UNLOCK(&(dp)->v_bh); \ } #define VOP_READDIR(vp,uiop,cr,eofp,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_SYMLINK(dvp,lnm,vap,tnm,cr,rv) \ { \ VN_BHV_READ_LOCK(&(dvp)->v_bh); \ rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,lnm,vap,tnm,cr); \ VN_BHV_READ_UNLOCK(&(dvp)->v_bh); \ } #define VOP_READLINK(vp,uiop,cr,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_FSYNC(vp,f,cr,b,e,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_INACTIVE(vp, cr, rv) \ { /* vnode not reference-able, so no need to lock chain */ \ rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr); \ } #define VOP_FID(vp, fidpp, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_fid, vp)((vp)->v_fbhv, fidpp); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_FID2(vp, fidp, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_RWLOCK(vp,i) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ (void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i); \ /* "allow" is done by rwunlock */ \ } #define VOP_RWUNLOCK(vp,i) \ { /* "prevent" was done by rwlock */ \ (void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_SEEK(vp, ooff, noffp, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_seek, vp)((vp)->v_fbhv, ooff, noffp); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_FRLOCK(vp,cmd,a,f,o,rwl,cr,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,cmd,a,f,o,rwl,cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_REALVP(vp1, vp2, rv) \ { \ VN_BHV_READ_LOCK(&(vp1)->v_bh); \ rv = _VOP_(vop_realvp, vp1)((vp1)->v_fbhv, vp2); \ VN_BHV_READ_UNLOCK(&(vp1)->v_bh); \ } /* * The vnode pointer passed to this macro sometimes changes during the * execution of the underlying vop_strategy op. => save the vp in a local var. */ #define VOP_STRATEGY(vp,bp) \ { \ vnode_t *_myvp_ = vp; \ VN_BHV_READ_LOCK(&(_myvp_)->v_bh); \ (void)_VOP_(vop_strategy, _myvp_)((_myvp_)->v_fbhv, bp); \ VN_BHV_READ_UNLOCK(&(_myvp_)->v_bh); \ } #define VOP_CMP(vp1,vp2,rv) \ { \ VN_BHV_READ_LOCK(&(vp1)->v_bh); \ rv = _VOP_(vop_cmp, vp1)((vp1)->v_fbhv, vp2); \ VN_BHV_READ_UNLOCK(&(vp1)->v_bh); \ } #define VOP_BMAP(vp,of,sz,rw,cr,b,n, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,cr,b,n); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_MAP(vp,of,sz,p,fl,cr,nvp,rv) \ { \ vnode_t *_myvp_ = vp; \ VN_BHV_READ_LOCK(&(_myvp_)->v_bh); \ rv = _VOP_(vop_map, _myvp_) ((_myvp_)->v_fbhv,of,sz,p,fl,cr,nvp); \ VN_BHV_READ_UNLOCK(&(_myvp_)->v_bh); \ } #define VOP_ADDMAP(vp,op,vt,pg,of,sz,p,cr,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_addmap, vp) ((vp)->v_fbhv,op,vt,pg,of,sz,p,cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_DELMAP(vp,vt,sz,cr,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_delmap, vp) ((vp)->v_fbhv,vt,sz,cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_POLL(vp, events, anyyet, reventsp, phpp, genp, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_poll, vp)((vp)->v_fbhv,events,anyyet,reventsp,phpp,genp); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_DUMP(vp,addr,bn,count,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_dump, vp)((vp)->v_fbhv,addr,bn,count); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_PATHCONF(vp, cmd, valp, cr, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_pathconf, vp)((vp)->v_fbhv, cmd, valp, cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ALLOCSTORE(vp,off,len,cr,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_allocstore, vp)((vp)->v_fbhv,off,len,cr); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_FCNTL(vp,cmd,a,f,of,cr,rvp,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_fcntl, vp)((vp)->v_fbhv,cmd,a,f,of,cr,rvp); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_RECLAIM(vp, flag, rv) \ { /* vnode not reference-able, so no need to lock chain */ \ ASSERT(!((vp)->v_flag & VINACTIVE_TEARDOWN)); \ rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv, flag); \ } #define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ATTR_REMOVE(vp, name, flags, cred, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred);\ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* * We don't hold the bhv chain lock for VOP_COVER because we don't * want to hold off inserting a new interposer on the covered vnode * (because that can happen from within the VOP_COVER path, in the * distributed case at least), and it's the case that inserting * an interposer on the covered vnode does not require synchronization * with a VOP_COVER. XXX But what about relocation of the covered vnode? */ #define VOP_COVER(cvp, uap, attrs, cr, rv) \ { \ rv = _VOP_(vop_cover, cvp)((cvp)->v_fbhv, uap, attrs, cr); \ } #define VOP_LINK_REMOVED(vp, dvp, linkzero) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ (void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_VNODE_CHANGE(vp, cmd, val) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ (void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* * These are page cache functions that now go thru VOPs. */ #define VOP_TOSS_PAGES(vp, first, last, fiopt) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ _VOP_(vop_tosspages, vp)((vp)->v_fbhv,first,last,fiopt); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ _VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt);\ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_INVALFREE_PAGES(vp, off) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ _VOP_(vop_invalfree_pages, vp)((vp)->v_fbhv,off); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_PAGES_SETHOLE(vp, pfd, cnt, doremap, remapoffset) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ _VOP_(vop_pages_sethole, vp)((vp)->v_fbhv,pfd,cnt,doremap,remapoffset);\ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* * Currently, used only by nfs V3. */ #define VOP_COMMIT(vp,bp,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_commit, vp)((vp)->v_fbhv, bp); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_READBUF(vp, offset, count, flags, credp, flid, \ bp, pboff, pblen, rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_readbuf, vp)((vp)->v_fbhv,offset,count,flags, \ credp,flid,bp,pboff,pblen); \ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* * Two special VOP's needed for distributed streams msgs. */ #define VOP_STRGETMSG(vp,mctl,mdata,prip,flagsp,fmode,rvp,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_strgetmsg, vp)((vp)->v_fbhv,mctl,mdata,prip,flagsp,fmode,rvp);\ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_STRPUTMSG(vp,mctl,mdata,pri,flags,fmode,rv) \ { \ VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_strputmsg, vp)((vp)->v_fbhv,mctl,mdata,pri,flags,fmode);\ VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* * Registration for the positions at which the different vnode behaviors * are chained. When on the same chain, a behavior with a higher position * number is invoked before one with a lower position number. * * Typically, the traditional file systems (xfs, procfs,...) will be the * BASE behavior. */ #define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */ #define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */ #define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */ /* * To avoid disrupting kudzu, the current values are left for the non-CELL * case although there is no reason known that the newer arrangement will * not work fine. After the tree split the #ifdef chould be removed. */ #if CELL #define VNODE_POSITION_IMON (VNODE_POSITION_BASE+7) /* inode monitor */ #define VNODE_POSITION_REPL (VNODE_POSITION_BASE+6) /* replication layer */ #define VNODE_POSITION_SPECFS_DC (VNODE_POSITION_BASE+5) /* specfs DC layer */ #define VNODE_POSITION_CFS_DS (VNODE_POSITION_BASE+4) /* CFS server */ #define VNODE_POSITION_CFS_DC (VNODE_POSITION_BASE+3) /* CFS client */ #define VNODE_POSITION_SPECFS_DS (VNODE_POSITION_BASE+2) /* specfs DS layer */ #define VNODE_POSITION_SPECFS_AT (VNODE_POSITION_BASE+1) /* specfs AT layer */ #else /* CELL */ #define VNODE_POSITION_REPL (VNODE_POSITION_BASE+1) /* replication layer */ #define VNODE_POSITION_IMON (VNODE_POSITION_BASE+2) /* inode monitor */ #define VNODE_POSITION_SPECFS_DC (VNODE_POSITION_TOP-1) /* specfs DC layer */ #define VNODE_POSITION_SPECFS_DS (VNODE_POSITION_TOP-2) /* specfs DS layer */ #define VNODE_POSITION_SPECFS_AT (VNODE_POSITION_TOP-3) /* specfs AT layer */ #define VNODE_POSITION_CFS_DS VNODE_POSITION_TOP /* CFS server */ #define VNODE_POSITION_CFS_DC VNODE_POSITION_TOP /* CFS client */ #endif /* CELL */ /* * I/O flags for VOP_READ, VOP_WRITE, and VOP_READBUF */ #define IO_APPEND 0x00001 /* append write (VOP_WRITE) */ #define IO_SYNC 0x00002 /* sync file I/O (VOP_WRITE) */ #define IO_DIRECT 0x00004 /* bypass page cache */ #define IO_IGNCACHE 0x00008 /* ignore page cache coherency when doing i/o (IO_DIRECT) */ #define IO_GRIO 0x00010 /* this is a guaranteed rate request */ #define IO_INVIS 0x00020 /* don't update inode timestamps */ #define IO_DSYNC 0x00040 /* sync data I/O (VOP_WRITE) */ #define IO_RSYNC 0x00080 /* sync data I/O (VOP_READ) */ #define IO_NFS 0x00100 /* I/O from the NFS v2 server */ #define IO_TRUSTEDDIO 0x00200 /* direct I/O from a trusted client so block zeroing is unnecessary */ #define IO_PRIORITY 0x00400 /* I/O is priority */ #define IO_ISLOCKED 0x00800 /* for VOP_READ/WRITE, VOP_RWLOCK/RWUNLOCK is being done by higher layer - file system shouldn't do locking */ #define IO_BULK 0x01000 /* loosen semantics for sequential bandwidth */ #define IO_NFS3 0x02000 /* I/O from the NFS v3 server */ #define IO_UIOSZ 0x04000 /* respect i/o size flags in uio struct */ #define IO_ONEPAGE 0x08000 /* I/O must be fit into one page */ #define IO_MTTHREAD 0x10000 /* I/O coming from threaded application, only used by paging to indicate that fs can return EAGAIN if this would deadlock. */ #ifdef _KERNEL #define IO_PFUSE_SAFE 0x20000 /* VOP_WRITE/VOP_READ: vnode can take addr's, kvatopfdat them, bump pf_use, and continue to reference data after return from VOP_. If IO_SYNC, only concern is kvatopfdat returns legal pfdat. */ #endif /* * Flags for VOP_LOOKUP. */ #define LOOKUP_DIR 0x01 /* want parent dir vp */ /* * Flush/Invalidate options for VOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGES and * VOP_FLUSH_PAGES. */ #define FI_NONE 0 /* none */ #define FI_REMAPF 1 /* Do a remapf prior to the operation */ #define FI_REMAPF_LOCKED 2 /* Do a remapf prior to the operation. Prevent VM access to the pages until the operation completes. */ /* * Vnode attributes. A bit-mask is supplied as part of the * structure to indicate the attributes the caller wants to * set (setattr) or extract (getattr). */ typedef struct vattr { int va_mask; /* bit-mask of attributes */ vtype_t va_type; /* vnode type (for create) */ mode_t va_mode; /* file access mode */ uid_t va_uid; /* owner user id */ gid_t va_gid; /* owner group id */ dev_t va_fsid; /* file system id (dev for now) */ ino_t va_nodeid; /* node id */ nlink_t va_nlink; /* number of references to file */ off_t va_size; /* file size in bytes */ timespec_t va_atime; /* time of last access */ timespec_t va_mtime; /* time of last modification */ timespec_t va_ctime; /* time file ``created'' */ dev_t va_rdev; /* device the file represents */ u_long va_blksize; /* fundamental block size */ blkcnt_t va_nblocks; /* # of blocks allocated */ u_long va_vcode; /* version code */ u_long va_xflags; /* random extended file flags */ u_long va_extsize; /* file extent size */ u_long va_nextents; /* number of extents in file */ u_long va_anextents; /* number of attr extents in file */ int va_projid; /* project id */ u_int va_gencount; /* object generation count */ } vattr_t; /* * Attributes of interest to the caller of setattr or getattr. */ #define AT_TYPE 0x00000001 #define AT_MODE 0x00000002 #define AT_UID 0x00000004 #define AT_GID 0x00000008 #define AT_FSID 0x00000010 #define AT_NODEID 0x00000020 #define AT_NLINK 0x00000040 #define AT_SIZE 0x00000080 #define AT_ATIME 0x00000100 #define AT_MTIME 0x00000200 #define AT_CTIME 0x00000400 #define AT_RDEV 0x00000800 #define AT_BLKSIZE 0x00001000 #define AT_NBLOCKS 0x00002000 #define AT_VCODE 0x00004000 #define AT_MAC 0x00008000 #define AT_UPDATIME 0x00010000 #define AT_UPDMTIME 0x00020000 #define AT_UPDCTIME 0x00040000 #define AT_ACL 0x00080000 #define AT_CAP 0x00100000 #define AT_INF 0x00200000 #define AT_XFLAGS 0x00400000 #define AT_EXTSIZE 0x00800000 #define AT_NEXTENTS 0x01000000 #define AT_ANEXTENTS 0x02000000 #define AT_PROJID 0x04000000 #define AT_SIZE_NOPERM 0x08000000 #define AT_GENCOUNT 0x10000000 #define AT_ALL (AT_TYPE|AT_MODE|AT_UID|AT_GID|AT_FSID|AT_NODEID|\ AT_NLINK|AT_SIZE|AT_ATIME|AT_MTIME|AT_CTIME|AT_RDEV|\ AT_BLKSIZE|AT_NBLOCKS|AT_VCODE|AT_MAC|AT_ACL|AT_CAP|\ AT_INF|AT_XFLAGS|AT_EXTSIZE|AT_NEXTENTS|AT_ANEXTENTS|\ AT_PROJID|AT_GENCOUNT) #define AT_STAT (AT_TYPE|AT_MODE|AT_UID|AT_GID|AT_FSID|AT_NODEID|AT_NLINK|\ AT_SIZE|AT_ATIME|AT_MTIME|AT_CTIME|AT_RDEV|AT_BLKSIZE|\ AT_NBLOCKS|AT_PROJID) #define AT_TIMES (AT_ATIME|AT_MTIME|AT_CTIME) #define AT_UPDTIMES (AT_UPDATIME|AT_UPDMTIME|AT_UPDCTIME) #define AT_NOSET (AT_NLINK|AT_RDEV|AT_FSID|AT_NODEID|AT_TYPE|\ AT_BLKSIZE|AT_NBLOCKS|AT_VCODE|AT_NEXTENTS|AT_ANEXTENTS|\ AT_GENCOUNT) /* * Modes. Some values same as S_xxx entries from stat.h for convenience. */ #define VSUID 04000 /* set user id on execution */ #define VSGID 02000 /* set group id on execution */ #define VSVTX 01000 /* save swapped text even after use */ /* * Permissions. */ #define VREAD 00400 #define VWRITE 00200 #define VEXEC 00100 #define MODEMASK 07777 /* mode bits plus permission bits */ #define PERMMASK 00777 /* permission bits */ /* * Check whether mandatory file locking is enabled. */ #define MANDLOCK(vp, mode) \ ((vp)->v_type == VREG && ((mode) & (VSGID|(VEXEC>>3))) == VSGID) /* * VOP_BMAP result parameter type / chunk interfaces input type. * * The bn, offset and length fields are expressed in BBSIZE blocks * (defined in sys/param.h). * The length field specifies the size of the underlying backing store * for the particular mapping. * The bsize, pbsize and pboff fields are expressed in bytes and indicate * the size of the mapping, the number of bytes that are valid to access * (read or write), and the offset into the mapping, given the offset * parameter passed to VOP_BMAP. * The pmp value is a pointer to a memory management policy module * structure. When returning a bmapval from VOP_BMAP it should be * NULL. It is usually copied from the uio structure into a bmapval * during a VOP_READ or VOP_WRITE call before calling chunkread/getchunk. * * When a request is made to read beyond the logical end of the object, * pbsize may be set to 0, but offset and length should be set to reflect * the actual amount of underlying storage that has been allocated, if any. */ typedef struct bmapval { daddr_t bn; /* block number in vfs */ off_t offset; /* logical block offset of this mapping */ struct pm *pmp; /* Policy Module pointer */ int length; /* length of this mapping in blocks */ int bsize; /* length of this mapping in bytes */ int pbsize; /* bytes in block mapped for i/o */ int pboff; /* byte offset into block for i/o */ dev_t pbdev; /* real ("physical") device for i/o */ char eof; /* last mapping of object */ } bmapval_t; /* * The eof field of the bmapval structure is really a flags * field. Here are the valid values. */ #define BMAP_EOF 0x01 /* mapping contains EOF */ #define BMAP_HOLE 0x02 /* mapping covers a hole */ #define BMAP_DELAY 0x04 /* mapping covers delalloc region */ #define BMAP_FLUSH_OVERLAPS 0x08 /* Don't flush overlapping buffers */ #define BMAP_READAHEAD 0x10 /* return NULL if necessary */ #define BMAP_UNWRITTEN 0x20 /* mapping covers allocated */ /* but uninitialized XFS data */ #define BMAP_DONTALLOC 0x40 /* don't allocate pfdats in buf_t's */ #ifdef _KERNEL /* * This macro determines if a write is actually allowed * on the node. This macro is used to check if a file's * access time can be modified. */ #define WRITEALLOWED(vp, cr) \ ((vp)->v_vfsp && ((vp)->v_vfsp->vfs_flag & VFS_RDONLY) == 0) /* * Public vnode manipulation functions. */ extern int vn_open(char *, enum uio_seg, int, mode_t, struct vnode **, enum create, int, int *); extern int vn_create(char *, enum uio_seg, struct vattr *, int, int mode, struct vnode **, enum create, int *); extern int vn_rdwr(enum uio_rw, struct vnode *, caddr_t, size_t, off_t, enum uio_seg, int, off_t, struct cred *, ssize_t *, struct flid *); extern int vn_link(char *, char *, enum uio_seg, enum symfollow); extern int vn_rename(char *, char *, enum uio_seg); extern int vn_remove(char *, enum uio_seg, enum rm); extern struct pfdat *vn_pfind(vnode_t *, pgno_t, int, void *); /* * Global vnode allocation: * * vp = vn_alloc(vfsp, type, rdev); * vn_free(vp); * * Inactive vnodes are kept on an LRU freelist managed by vn_alloc, vn_free, * vn_get, vn_purge, and vn_rele. When vn_rele inactivates a vnode, * it puts the vnode at the end of the list unless there are no behaviors * attached to it, which tells vn_rele to insert at the beginning of the * freelist. When vn_get acquires an inactive vnode, it unlinks the vnode * from the list; * vn_purge puts inactive dead vnodes at the front of the list for rapid reuse. * * If the freelist is empty, vn_alloc dynamically allocates another vnode. * Call vn_free to destroy a vn_alloc'd vnode that has no other references * and no valid private data. Do not call vn_free from within VOP_INACTIVE; * just remove the behaviors and vn_rele will do the right thing. * * A vnode might be deallocated after it is put on the freelist (after * a VOP_RECLAIM, of course). In this case, the vn_epoch value is * incremented to define a new vnode epoch. */ extern vnode_t *vn_alloc(struct vfs *, enum vtype, dev_t); extern void vn_free(struct vnode *); /* * Acquiring and invalidating vnodes: * * if (vn_get(vp, version, 0)) * ...; * vn_purge(vp, version); * * vn_get and vn_purge must be called with vmap_t arguments, sampled * while a lock that the vnode's VOP_RECLAIM function acquires is * held, to ensure that the vnode sampled with the lock held isn't * recycled (VOP_RECLAIMed) or deallocated between the release of the lock * and the subsequent vn_get or vn_purge. */ /* * vnode_map structures _must_ match vn_epoch and vnode structure sizes. */ typedef struct vnode_map { vnumber_t v_number; /* in-core vnode number */ int v_epoch; /* epoch in vnode history */ int v_id; /* freeelist id */ } vmap_t; #define VMAP(vp, vmap) {(vmap).v_number = (vp)->v_number, \ (vmap).v_id = (vp)->v_listid, \ (vmap).v_epoch = vn_epoch; } extern void vn_kill(struct vnode *); extern void vn_gone(struct vnode *); extern int vn_evict(struct vnode *); extern void vn_purge(struct vnode *, vmap_t *); extern vnode_t *vn_get(struct vnode *, vmap_t *, uint); /* * Flags for vn_get(). */ #define VN_GET_NOWAIT 0x1 /* Don't wait for inactive or reclaim */ /* * Vnode reference counting functions (and macros for compatibility). */ extern vnode_t *vn_hold(struct vnode *); extern void vn_rele(struct vnode *); #ifdef VNODE_TRACING #define VN_HOLD(vp) \ ((void)vn_hold(vp), \ vn_trace_hold(vp, __FILE__, __LINE__, (inst_t *)__return_address)) #define VN_RELE(vp) \ (vn_trace_rele(vp, __FILE__, __LINE__, (inst_t *)__return_address), \ vn_rele(vp)) #else #define VN_HOLD(vp) ((void)vn_hold(vp)) #define VN_RELE(vp) (vn_rele(vp)) #endif /* * Vnode spinlock manipulation. */ #define VN_LOCK(vp) mutex_bitlock(&(vp)->v_flag, VLOCK) #define VN_UNLOCK(vp,s) mutex_bitunlock(&(vp)->v_flag, VLOCK, s) #define VN_FLAGSET(vp,b) bitlock_set(&(vp)->v_flag, VLOCK, b) #define VN_FLAGCLR(vp,b) bitlock_clr(&(vp)->v_flag, VLOCK, b) /* * Vnode buffer tree lock manipulation */ #define VN_BUF_LOCK(vp, s) mutex_lock(&(vp)->v_buf_lock, PZERO) #define VN_BUF_UNLOCK(vp, s) mutex_unlock(&(vp)->v_buf_lock) /* * lock the vfs given the vnode pointer */ #define VN_VFSLOCK(vp) vfs_lock((vp)->v_vfsp) #define VN_VFSUNLOCK(vp) vfs_unlock((vp)->v_vfsp) /* * Some useful predicates. */ #define VN_MAPPED(vp) ((vp)->v_mreg != (struct pregion *)(vp)) #define VN_DIRTY(vp) ((vp)->v_dbuf || (vp)->v_dpages) #ifdef NUMA_REPLICATION /* * Macros to set and clear bits indicating if the vnode is replicable. * It's the responsibility of the caller of macro to hold the appropriate * locks while setting/clearing the bits. * * These two bits should be mutually exclusive. So, while setting one * it's necessary to make sure that other is not set. Since this involves * two operations, it's not possible to use VN_FLAGSET macros for * setting/clearing these bits.. */ #define VN_SETREPLICABLE(vp) ((vp)->v_flag |= VREPLICABLE) #define VN_CLRREPLICABLE(vp) ((vp)->v_flag &= ~VREPLICABLE) #define VN_SETNONREPLICABLE(vp) ((vp)->v_flag |= VNONREPLICABLE) #define VN_CLRNONREPLICABLE(vp) ((vp)->v_flag &= ~VNONREPLICABLE) #define VN_ISREPLICABLE(vp) ((vp)->v_flag & VREPLICABLE) #define VN_ISNONREPLICABLE(vp) ((vp)->v_flag & VNONREPLICABLE) #else /* NUMA_RELICATION */ #define VN_SETREPLICABLE(vp) #define VN_CLRREPLICABLE(vp) #define VN_SETNONREPLICABLE(vp) #define VN_CLRNONREPLICABLE(vp) #define VN_ISREPLICABLE(vp) (0) #define VN_ISNONREPLICABLE(vp) (1) #endif /* NUMA_REPLICATION */ #define VN_CACHED(vp) ((vp)->v_pgcnt != 0) /* * Compare two vnodes for equality. In general this macro should be used * in preference to calling VOP_CMP directly. * * The standard vp1 == vp2 is sufficient for most file systems, and for * the ones that it's not, they must set the VDOCMP flag in the vnode. */ extern int vn_cmp(vnode_t *vp1, vnode_t *vp2); #define VN_CMP(VP1, VP2) \ ((VP1) == (VP2) || \ ((VP1) && (VP2) && \ (((VP1)->v_flag & VDOCMP) || ((VP2)->v_flag & VDOCMP)) \ && vn_cmp((VP1), (VP2)))) /* * Flags to VOP_SETATTR/VOP_GETATTR. */ #define ATTR_UTIME 0x01 /* non-default utime(2) request */ #define ATTR_EXEC 0x02 /* invocation from exec(2) */ #define ATTR_COMM 0x04 /* yield common vp attributes */ #define ATTR_DMI 0x08 /* invocation from a DMI function */ #define ATTR_LAZY 0x80 /* set/get attributes lazily */ #define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */ /* * Flags to VOP_FSYNC and VOP_RECLAIM. */ #define FSYNC_NOWAIT 0 /* asynchronous flush */ #define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */ #define FSYNC_INVAL 0x2 /* flush and invalidate cached data */ #define FSYNC_DATA 0x4 /* synchronous fsync of data only */ /* * Generally useful macros. */ #define VBSIZE(vp) ((vp)->v_vfsp->vfs_bsize) #define NULLVP ((struct vnode *)0) #define NULLVPP ((struct vnode **)0) struct pathname; extern int lookupname(char *, enum uio_seg, enum symfollow, vnode_t **, vnode_t **, ckpt_handle_t *); extern int lookuppn(struct pathname *, enum symfollow, vnode_t **, vnode_t **, ckpt_handle_t *); extern int traverse(vnode_t **); extern int namesetattr(char *, enum symfollow, struct vattr *, int); extern int fdsetattr(int, vattr_t *, int); struct irix5_stat; struct irix5_64_stat; struct stat64; extern int xcstat(void *, void *, int, int, struct cred *); extern int irix5_64_xcstat(vnode_t *, struct irix5_64_stat *, struct cred *); /* * Vnode list ops. */ #define vn_append(vp,vl) vn_insert(vp, (struct vnlist *)(vl)->vl_prev) extern void vn_initlist(struct vnlist *); extern void vn_insert(struct vnode *, struct vnlist *); extern void vn_unlink(struct vnode *); extern vnodeops_t *vn_passthrup; /* vnode pass-thru ops */ #ifdef VNODE_TRACING /* * Tracing entries. */ #define VNODE_KTRACE_ENTRY 1 #define VNODE_KTRACE_HOLD 2 #define VNODE_KTRACE_REF 3 #define VNODE_KTRACE_RELE 4 #define VNODE_TRACE_SIZE 64 /* number of trace entries */ extern void vn_trace_entry(struct vnode *, char *, inst_t *); extern void vn_trace_hold(struct vnode *, char *, int, inst_t *); extern void vn_trace_ref(struct vnode *, char *, int, inst_t *); extern void vn_trace_rele(struct vnode *, char *, int, inst_t *); #define VN_TRACE(vp) \ vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address) #else #define vn_trace_entry(a,b,c) #define vn_trace_hold(a,b,c,d) #define vn_trace_ref(a,b,c,d) #define vn_trace_rele(a,b,c,d) #define VN_TRACE(vp) #endif /* VNODE_TRACING */ /* * Vnode pagecache operations. * (Note: ptossvp, pflushinvalvp, pflushvp, pinvalfree & pageshole * have been replaced with VOPs) */ #define pfind(vp, pgno, flag) vnode_pfind(vp, pgno, flag) #define pinsert(pfd, vp, pgno, flag) vnode_pinsert(vp, pfd, pgno, flag) #define pinsert_nolock(pfd, vp, pgno, flag, locktoken) \ vnode_pinsert_nolock(pfd, vp, pgno, flag, locktoken) #define pinsert_try(pfd, vp, pgno) vnode_pinsert_try(vp, pfd, pgno) #define preplace(opfd, npfd) vnode_page_replace(opfd, npfd) #define premove(pfd) vnode_premove((pfd)->pf_vp, pfd) #define premove_nolock(pfd) vnode_premove((pfd)->pf_vp, pfd) #define pagesrelease(pfd, cnt, flag) vnode_pagesrelease((pfd)->pf_vp, pfd, cnt, flag) extern lock_t mreg_lock; /* spinlock protecting all vp->v_mreg */ extern vnode_t *rootdir; /* pointer to root vnode */ extern int vn_epoch; /* incore vnode capability - changed when */ /* vnodes are deallocated */ extern struct vfreelist_s *vfreelist; /* ptr to array of freelist structs */ #endif /* _KERNEL */ #endif /* _FS_VNODE_H */