xfs_vnode.c 5.3 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2 3
 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
 * All Rights Reserved.
L
Linus Torvalds 已提交
4
 *
5 6
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
L
Linus Torvalds 已提交
7 8
 * published by the Free Software Foundation.
 *
9 10 11 12
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
L
Linus Torvalds 已提交
13
 *
14 15 16
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
L
Linus Torvalds 已提交
17 18
 */
#include "xfs.h"
19 20 21
#include "xfs_vnodeops.h"
#include "xfs_bmap_btree.h"
#include "xfs_inode.h"
L
Linus Torvalds 已提交
22 23 24 25 26 27 28 29 30 31

uint64_t vn_generation;		/* vnode generation number */
DEFINE_SPINLOCK(vnumber_lock);

/*
 * Dedicated vnode inactive/reclaim sync semaphores.
 * Prime number of hash buckets since address is used as the key.
 */
#define NVSYNC                  37
#define vptosync(v)             (&vsync[((unsigned long)v) % NVSYNC])
32
static wait_queue_head_t vsync[NVSYNC];
L
Linus Torvalds 已提交
33 34 35 36

void
vn_init(void)
{
37
	int i;
L
Linus Torvalds 已提交
38

39 40 41 42 43 44
	for (i = 0; i < NVSYNC; i++)
		init_waitqueue_head(&vsync[i]);
}

void
vn_iowait(
45
	bhv_vnode_t	*vp)
46 47 48 49 50 51 52 53
{
	wait_queue_head_t *wq = vptosync(vp);

	wait_event(*wq, (atomic_read(&vp->v_iocount) == 0));
}

void
vn_iowake(
54
	bhv_vnode_t	*vp)
55 56 57
{
	if (atomic_dec_and_test(&vp->v_iocount))
		wake_up(vptosync(vp));
L
Linus Torvalds 已提交
58 59
}

60 61 62 63 64 65 66
/*
 * Volume managers supporting multiple paths can send back ENODEV when the
 * final path disappears.  In this case continuing to fill the page cache
 * with dirty data which cannot be written out is evil, so prevent that.
 */
void
vn_ioerror(
67
	bhv_vnode_t	*vp,
68 69 70 71
	int		error,
	char		*f,
	int		l)
{
72 73
	bhv_vfs_t	*vfsp = vfs_from_sb(vp->v_inode.i_sb);

74
	if (unlikely(error == -ENODEV))
75
		bhv_vfs_force_shutdown(vfsp, SHUTDOWN_DEVICE_REQ, f, l);
76 77
}

78
bhv_vnode_t *
L
Linus Torvalds 已提交
79 80 81
vn_initialize(
	struct inode	*inode)
{
82
	bhv_vnode_t	*vp = vn_from_inode(inode);
L
Linus Torvalds 已提交
83 84 85 86 87 88 89 90 91 92 93 94

	XFS_STATS_INC(vn_active);
	XFS_STATS_INC(vn_alloc);

	spin_lock(&vnumber_lock);
	if (!++vn_generation)	/* v_number shouldn't be zero */
		vn_generation++;
	vp->v_number = vn_generation;
	spin_unlock(&vnumber_lock);

	ASSERT(VN_CACHED(vp) == 0);

95 96
	atomic_set(&vp->v_iocount, 0);

L
Linus Torvalds 已提交
97 98 99 100
#ifdef	XFS_VNODE_TRACE
	vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
#endif	/* XFS_VNODE_TRACE */

101
	vn_trace_exit(vp, __FUNCTION__, (inst_t *)__return_address);
L
Linus Torvalds 已提交
102 103 104 105 106 107 108 109 110 111
	return vp;
}

/*
 * Revalidate the Linux inode from the vattr.
 * Note: i_size _not_ updated; we must hold the inode
 * semaphore when doing that - callers responsibility.
 */
void
vn_revalidate_core(
112
	bhv_vnode_t	*vp,
113
	bhv_vattr_t	*vap)
L
Linus Torvalds 已提交
114
{
115
	struct inode	*inode = vn_to_inode(vp);
L
Linus Torvalds 已提交
116

117
	inode->i_mode	    = vap->va_mode;
L
Linus Torvalds 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
	inode->i_nlink	    = vap->va_nlink;
	inode->i_uid	    = vap->va_uid;
	inode->i_gid	    = vap->va_gid;
	inode->i_blocks	    = vap->va_nblocks;
	inode->i_mtime	    = vap->va_mtime;
	inode->i_ctime	    = vap->va_ctime;
	if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
		inode->i_flags |= S_IMMUTABLE;
	else
		inode->i_flags &= ~S_IMMUTABLE;
	if (vap->va_xflags & XFS_XFLAG_APPEND)
		inode->i_flags |= S_APPEND;
	else
		inode->i_flags &= ~S_APPEND;
	if (vap->va_xflags & XFS_XFLAG_SYNC)
		inode->i_flags |= S_SYNC;
	else
		inode->i_flags &= ~S_SYNC;
	if (vap->va_xflags & XFS_XFLAG_NOATIME)
		inode->i_flags |= S_NOATIME;
	else
		inode->i_flags &= ~S_NOATIME;
}

/*
 * Revalidate the Linux inode from the vnode.
 */
int
146
__vn_revalidate(
147
	bhv_vnode_t	*vp,
148
	bhv_vattr_t	*vattr)
L
Linus Torvalds 已提交
149 150 151
{
	int		error;

152 153
	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
	vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS;
154
	error = xfs_getattr(xfs_vtoi(vp), vattr, 0);
155 156
	if (likely(!error)) {
		vn_revalidate_core(vp, vattr);
157
		xfs_iflags_clear(xfs_vtoi(vp), XFS_IMODIFIED);
L
Linus Torvalds 已提交
158 159 160 161
	}
	return -error;
}

162 163
int
vn_revalidate(
164
	bhv_vnode_t	*vp)
165
{
166
	bhv_vattr_t	vattr;
167 168 169 170

	return __vn_revalidate(vp, &vattr);
}

L
Linus Torvalds 已提交
171 172 173
/*
 * Add a reference to a referenced vnode.
 */
174
bhv_vnode_t *
L
Linus Torvalds 已提交
175
vn_hold(
176
	bhv_vnode_t	*vp)
L
Linus Torvalds 已提交
177 178 179 180 181
{
	struct inode	*inode;

	XFS_STATS_INC(vn_hold);

182
	inode = igrab(vn_to_inode(vp));
L
Linus Torvalds 已提交
183 184 185 186 187 188 189 190 191 192 193 194
	ASSERT(inode);

	return vp;
}

#ifdef	XFS_VNODE_TRACE

#define KTRACE_ENTER(vp, vk, s, line, ra)			\
	ktrace_enter(	(vp)->v_trace,				\
/*  0 */		(void *)(__psint_t)(vk),		\
/*  1 */		(void *)(s),				\
/*  2 */		(void *)(__psint_t) line,		\
195
/*  3 */		(void *)(__psint_t)(vn_count(vp)),	\
L
Linus Torvalds 已提交
196
/*  4 */		(void *)(ra),				\
197
/*  5 */		NULL,					\
L
Linus Torvalds 已提交
198 199 200
/*  6 */		(void *)(__psint_t)current_cpu(),	\
/*  7 */		(void *)(__psint_t)current_pid(),	\
/*  8 */		(void *)__return_address,		\
201
/*  9 */		NULL, NULL, NULL, NULL, NULL, NULL, NULL)
L
Linus Torvalds 已提交
202 203 204 205 206

/*
 * Vnode tracing code.
 */
void
207
vn_trace_entry(bhv_vnode_t *vp, const char *func, inst_t *ra)
L
Linus Torvalds 已提交
208 209 210 211 212
{
	KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
}

void
213
vn_trace_exit(bhv_vnode_t *vp, const char *func, inst_t *ra)
L
Linus Torvalds 已提交
214 215 216 217 218
{
	KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
}

void
219
vn_trace_hold(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
L
Linus Torvalds 已提交
220 221 222 223 224
{
	KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);
}

void
225
vn_trace_ref(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
L
Linus Torvalds 已提交
226 227 228 229 230
{
	KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);
}

void
231
vn_trace_rele(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
L
Linus Torvalds 已提交
232 233 234 235
{
	KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
}
#endif	/* XFS_VNODE_TRACE */