diff options
Diffstat (limited to 'usr/src/uts/common/sys/vnode.h')
| -rw-r--r-- | usr/src/uts/common/sys/vnode.h | 74 | 
1 files changed, 70 insertions, 4 deletions
| diff --git a/usr/src/uts/common/sys/vnode.h b/usr/src/uts/common/sys/vnode.h index e4d43cea7f..c779cc1ff6 100644 --- a/usr/src/uts/common/sys/vnode.h +++ b/usr/src/uts/common/sys/vnode.h @@ -21,7 +21,7 @@  /*   * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2016 Joyent, Inc.   */  /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/ @@ -221,6 +221,59 @@ struct vsd_node {   * In particular, file systems should not access other fields; they may   * change or even be removed.  The functionality which was once provided   * by these fields is available through vn_* functions. + * + * VNODE PATH THEORY: + * In each vnode, the v_path field holds a cached version of the canonical + * filesystem path which that node represents.  Because vnodes lack contextual + * information about their own name or position in the VFS hierarchy, this path + * must be calculated when the vnode is instantiated by operations such as + * fop_create, fop_lookup, or fop_mkdir.  During said operations, both the + * parent vnode (and its cached v_path) and future name are known, so the + * v_path of the resulting object can easily be set. + * + * The caching nature of v_path is complicated in the face of directory + * renames.  Filesystem drivers are responsible for calling vn_renamepath when + * a fop_rename operation succeeds.  While the v_path on the renamed vnode will + * be updated, existing children of the directory (direct, or at deeper levels) + * will now possess v_path caches which are stale. + * + * It is expensive (and for non-directories, impossible) to recalculate stale + * v_path entries during operations such as vnodetopath.  The best time during + * which to correct such wrongs is the same as when v_path is first + * initialized: during fop_create/fop_lookup/fop_mkdir/etc, where adequate + * context is available to generate the current path. + * + * In order to quickly detect stale v_path entries (without full lookup + * verification) to trigger a v_path update, the v_path_stamp field has been + * added to vnode_t.  As part of successful fop_create/fop_lookup/fop_mkdir + * operations, where the name and parent vnode are available, the following + * rules are used to determine updates to the child: + * + * 1. If the parent lacks a v_path, clear any existing v_path and v_path_stamp + *    on the child.  Until the parent v_path is refreshed to a valid state, the + *    child v_path must be considered invalid too. + * + * 2. If the child lacks a v_path (implying v_path_stamp == 0), it inherits the + *    v_path_stamp value from its parent and its v_path is updated. + * + * 3. If the child v_path_stamp is less than v_path_stamp in the parent, it is + *    an indication that the child v_path is stale.  The v_path is updated and + *    v_path_stamp in the child is set to the current hrtime(). + * + *    It does _not_ inherit the parent v_path_stamp in order to propagate the + *    the time of v_path invalidation through the directory structure.  This + *    prevents concurrent invalidations (operating with a now-incorrect v_path) + *    at deeper levels in the tree from persisting. + * + * 4. If the child v_path_stamp is greater or equal to the parent, no action + *    needs to be taken. + * + * Note that fop_rename operations do not follow this ruleset.  They perform an + * explicit update of v_path and v_path_stamp (setting it to the current time) + * + * With these constraints in place, v_path invalidations and updates should + * proceed in a timely manner as vnodes are accessed.  While there still are + * limited cases where vnodetopath operations will fail, the risk is minimized.   */  struct fem_head;	/* from fem.h */ @@ -247,6 +300,7 @@ typedef struct vnode {  	void		*v_locality;	/* hook for locality info */  	struct fem_head	*v_femhead;	/* fs monitoring */  	char		*v_path;	/* cached path */ +	hrtime_t	v_path_stamp;	/* timestamp for cached path */  	uint_t		v_rdcnt;	/* open for read count  (VREG only) */  	uint_t		v_wrcnt;	/* open for write count (VREG only) */  	u_longlong_t	v_mmap_read;	/* mmap read count */ @@ -738,12 +792,14 @@ typedef enum vnevent	{  	VE_RMDIR	= 4,	/* Remove of directory vnode's name */  	VE_CREATE	= 5,	/* Create with vnode's name which exists */  	VE_LINK		= 6, 	/* Link with vnode's name as source */ -	VE_RENAME_DEST_DIR	= 7, 	/* Rename with vnode as target dir */ +	VE_RENAME_DEST_DIR = 7,	/* Rename with vnode as target dir */  	VE_MOUNTEDOVER	= 8, 	/* File or Filesystem got mounted over vnode */  	VE_TRUNCATE = 9,	/* Truncate */  	VE_PRE_RENAME_SRC = 10,	/* Pre-rename, with vnode as source */  	VE_PRE_RENAME_DEST = 11, /* Pre-rename, with vnode as target/dest. */ -	VE_PRE_RENAME_DEST_DIR = 12 /* Pre-rename with vnode as target dir */ +	VE_PRE_RENAME_DEST_DIR = 12, /* Pre-rename with vnode as target dir */ +	VE_RENAME_SRC_DIR = 13,	/* Rename with vnode as source dir */ +	VE_RESIZE	= 14	/* Resize/truncate to non-zero offset */  } vnevent_t;  /* @@ -1291,6 +1347,11 @@ void vn_setpath(vnode_t *rootvp, struct vnode *startvp, struct vnode *vp,      const char *path, size_t plen);  void vn_renamepath(vnode_t *dvp, vnode_t *vp, const char *nm, size_t len); +/* Private vnode manipulation functions */ +void vn_clearpath(vnode_t *, hrtime_t); +void vn_updatepath(vnode_t *, vnode_t *, const char *); + +  /* Vnode event notification */  void	vnevent_rename_src(vnode_t *, vnode_t *, char *, caller_context_t *);  void	vnevent_rename_dest(vnode_t *, vnode_t *, char *, caller_context_t *); @@ -1298,7 +1359,8 @@ void	vnevent_remove(vnode_t *, vnode_t *, char *, caller_context_t *);  void	vnevent_rmdir(vnode_t *, vnode_t *, char *, caller_context_t *);  void	vnevent_create(vnode_t *, caller_context_t *);  void	vnevent_link(vnode_t *, caller_context_t *); -void	vnevent_rename_dest_dir(vnode_t *, caller_context_t *ct); +void	vnevent_rename_dest_dir(vnode_t *, vnode_t *, char *, +    caller_context_t *ct);  void	vnevent_mountedover(vnode_t *, caller_context_t *);  void	vnevent_truncate(vnode_t *, caller_context_t *);  int	vnevent_support(vnode_t *, caller_context_t *); @@ -1308,6 +1370,7 @@ void	vnevent_pre_rename_dest(vnode_t *, vnode_t *, char *,  	    caller_context_t *);  void	vnevent_pre_rename_dest_dir(vnode_t *, vnode_t *, char *,  	    caller_context_t *); +void	vnevent_resize(vnode_t *, caller_context_t *);  /* Vnode specific data */  void vsd_create(uint_t *, void (*)(void *)); @@ -1337,6 +1400,9 @@ u_longlong_t	fs_new_caller_id();  int	vn_vmpss_usepageio(vnode_t *); +/* Empty v_path placeholder */ +extern char *vn_vpath_empty; +  /*   * Needed for use of IS_VMODSORT() in kernel.   */ | 
