summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/vnode.h
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/sys/vnode.h')
-rw-r--r--usr/src/uts/common/sys/vnode.h56
1 files changed, 46 insertions, 10 deletions
diff --git a/usr/src/uts/common/sys/vnode.h b/usr/src/uts/common/sys/vnode.h
index b8702bc8f5..df5da6c2e7 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) 2018, Joyent, Inc.
+ * Copyright 2020 Joyent, Inc.
* Copyright (c) 2011, 2017 by Delphix. All rights reserved.
* Copyright 2017 RackTop Systems.
*/
@@ -197,6 +197,7 @@ struct vsd_node {
* v_count
* v_shrlocks
* v_path
+ * v_phantom_count
* v_vsd
* v_xattrdir
*
@@ -214,6 +215,7 @@ struct vsd_node {
* v_lock
* v_flag
* v_count
+ * v_phantom_count
* v_data
* v_vfsp
* v_stream
@@ -285,6 +287,8 @@ typedef struct vnode {
kmutex_t v_lock; /* protects vnode fields */
uint_t v_flag; /* vnode flags (see below) */
uint_t v_count; /* reference count */
+ /* non vn_count() ref count (see below) */
+ uint_t v_phantom_count;
void *v_data; /* private data for fs */
struct vfs *v_vfsp; /* ptr to containing VFS */
struct stdata *v_stream; /* associated stream */
@@ -811,13 +815,15 @@ typedef enum vnevent {
VE_REMOVE = 3, /* Remove of vnode's name */
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_MOUNTEDOVER = 8, /* File or Filesystem got mounted over vnode */
+ VE_LINK = 6, /* Link with vnode's name as source */
+ 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;
/*
@@ -1292,9 +1298,9 @@ void vn_recycle(vnode_t *);
void vn_free(vnode_t *);
int vn_is_readonly(vnode_t *);
-int vn_is_opened(vnode_t *, v_mode_t);
-int vn_is_mapped(vnode_t *, v_mode_t);
-int vn_has_other_opens(vnode_t *, v_mode_t);
+int vn_is_opened(vnode_t *, v_mode_t);
+int vn_is_mapped(vnode_t *, v_mode_t);
+int vn_has_other_opens(vnode_t *, v_mode_t);
void vn_open_upgrade(vnode_t *, int);
void vn_open_downgrade(vnode_t *, int);
@@ -1333,10 +1339,12 @@ int vn_createat(char *pnamep, enum uio_seg seg, struct vattr *vap,
int vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, ssize_t len,
offset_t offset, enum uio_seg seg, int ioflag, rlim64_t ulimit,
cred_t *cr, ssize_t *residp);
+uint_t vn_count(struct vnode *vp);
void vn_rele(struct vnode *vp);
void vn_rele_async(struct vnode *vp, struct taskq *taskq);
void vn_rele_dnlc(struct vnode *vp);
void vn_rele_stream(struct vnode *vp);
+void vn_phantom_rele(struct vnode *vp);
int vn_link(char *from, char *to, enum uio_seg seg);
int vn_linkat(vnode_t *fstartvp, char *from, enum symfollow follow,
vnode_t *tstartvp, char *to, enum uio_seg seg);
@@ -1377,7 +1385,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 *);
@@ -1387,6 +1396,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 *));
@@ -1439,6 +1449,16 @@ extern uint_t pvn_vmodsort_supported;
* this->vp->v_path == NULL ? "NULL" : stringof(this->vp->v_path),
* this->vp->v_count)
* }'
+ *
+ * There are some situations where we don't want a hold to make the vnode
+ * 'busy'. For example, watching a directory via port events or inotify
+ * should not prevent a filesystem from mounting on a watched directory.
+ * For those instances, a phantom hold is used via VN_PHANTOM_HOLD().
+ *
+ * A phantom hold works identically to regular hold, except that those holds
+ * are excluded from the return value of vn_count().
+ *
+ * A phantom hold must be released by VN_PHANTOM_RELE().
*/
#define VN_HOLD_LOCKED(vp) { \
ASSERT(mutex_owned(&(vp)->v_lock)); \
@@ -1467,6 +1487,22 @@ extern uint_t pvn_vmodsort_supported;
DTRACE_PROBE1(vn__rele, vnode_t *, vp); \
}
+#define VN_PHANTOM_HOLD_LOCKED(vp) { \
+ VN_HOLD_LOCKED(vp); \
+ (vp)->v_phantom_count++; \
+ DTRACE_PROBE1(vn__phantom_hold, vnode_t *, vp); \
+}
+
+#define VN_PHANTOM_HOLD(vp) { \
+ mutex_enter(&(vp)->v_lock); \
+ VN_PHANTOM_HOLD_LOCKED(vp); \
+ mutex_exit(&(vp)->v_lock); \
+}
+
+#define VN_PHANTOM_RELE(vp) { \
+ vn_phantom_rele(vp); \
+}
+
#define VN_SET_VFS_TYPE_DEV(vp, vfsp, type, dev) { \
(vp)->v_vfsp = (vfsp); \
(vp)->v_type = (type); \
@@ -1477,7 +1513,7 @@ extern uint_t pvn_vmodsort_supported;
* Compare two vnodes for equality. In general this macro should be used
* in preference to calling VOP_CMP directly.
*/
-#define VN_CMP(VP1, VP2) ((VP1) == (VP2) ? 1 : \
+#define VN_CMP(VP1, VP2) ((VP1) == (VP2) ? 1 : \
((VP1) && (VP2) && (vn_getops(VP1) == vn_getops(VP2)) ? \
VOP_CMP(VP1, VP2, NULL) : 0))