inode.h 5.77 KB
Newer Older
J. R. Okajima's avatar
J. R. Okajima committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2005-2019 Junjiro R. Okajima
 */

/*
 * inode operations
 */

#ifndef __AUFS_INODE_H__
#define __AUFS_INODE_H__

#ifdef __KERNEL__

#include <linux/fs.h>
J. R. Okajima's avatar
J. R. Okajima committed
16
#include "rwsem.h"
J. R. Okajima's avatar
J. R. Okajima committed
17
18
19

struct au_hinode {
	struct inode		*hi_inode;
20
	aufs_bindex_t		hi_id;
J. R. Okajima's avatar
J. R. Okajima committed
21
22
};

J. R. Okajima's avatar
J. R. Okajima committed
23
24
25
26
27
struct au_iigen {
	spinlock_t	ig_spin;
	__u32		ig_generation;
};

J. R. Okajima's avatar
J. R. Okajima committed
28
struct au_iinfo {
J. R. Okajima's avatar
J. R. Okajima committed
29
30
31
	struct au_iigen		ii_generation;
	struct super_block	*ii_hsb1;	/* no get/put */

J. R. Okajima's avatar
J. R. Okajima committed
32
	struct au_rwsem		ii_rwsem;
J. R. Okajima's avatar
J. R. Okajima committed
33
	aufs_bindex_t		ii_btop, ii_bbot;
J. R. Okajima's avatar
J. R. Okajima committed
34
	__u32			ii_higen;
J. R. Okajima's avatar
J. R. Okajima committed
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
	struct au_hinode	*ii_hinode;
};

struct au_icntnr {
	struct au_iinfo		iinfo;
	struct inode		vfs_inode;
	struct rcu_head		rcu;
} ____cacheline_aligned_in_smp;

/* ---------------------------------------------------------------------- */

static inline struct au_iinfo *au_ii(struct inode *inode)
{
	BUG_ON(is_bad_inode(inode));
	return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
}

/* ---------------------------------------------------------------------- */

54
55
56
/* inode.c */
struct inode *au_igrab(struct inode *inode);

J. R. Okajima's avatar
J. R. Okajima committed
57
58
59
60
61
62
63
/* iinfo.c */
struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
void au_hiput(struct au_hinode *hinode);

void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
		   struct inode *h_inode, unsigned int flags);

J. R. Okajima's avatar
J. R. Okajima committed
64
65
void au_update_iigen(struct inode *inode, int half);

J. R. Okajima's avatar
J. R. Okajima committed
66
67
68
69
void au_icntnr_init_once(void *_c);
void au_hinode_init(struct au_hinode *hinode);
int au_iinfo_init(struct inode *inode);
void au_iinfo_fin(struct inode *inode);
70
int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink);
J. R. Okajima's avatar
J. R. Okajima committed
71
72
73

/* ---------------------------------------------------------------------- */

J. R. Okajima's avatar
J. R. Okajima committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* lock subclass for iinfo */
enum {
	AuLsc_II_CHILD,		/* child first */
	AuLsc_II_CHILD2,	/* rename(2), link(2), and cpup at hnotify */
	AuLsc_II_CHILD3,	/* copyup dirs */
	AuLsc_II_PARENT,	/* see AuLsc_I_PARENT in vfsub.h */
	AuLsc_II_PARENT2,
	AuLsc_II_PARENT3,	/* copyup dirs */
	AuLsc_II_NEW_CHILD
};

/*
 * ii_read_lock_child, ii_write_lock_child,
 * ii_read_lock_child2, ii_write_lock_child2,
 * ii_read_lock_child3, ii_write_lock_child3,
 * ii_read_lock_parent, ii_write_lock_parent,
 * ii_read_lock_parent2, ii_write_lock_parent2,
 * ii_read_lock_parent3, ii_write_lock_parent3,
 * ii_read_lock_new_child, ii_write_lock_new_child,
 */
#define AuReadLockFunc(name, lsc) \
static inline void ii_read_lock_##name(struct inode *i) \
{ \
	au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
}

#define AuWriteLockFunc(name, lsc) \
static inline void ii_write_lock_##name(struct inode *i) \
{ \
	au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
}

#define AuRWLockFuncs(name, lsc) \
	AuReadLockFunc(name, lsc) \
	AuWriteLockFunc(name, lsc)

AuRWLockFuncs(child, CHILD);
AuRWLockFuncs(child2, CHILD2);
AuRWLockFuncs(child3, CHILD3);
AuRWLockFuncs(parent, PARENT);
AuRWLockFuncs(parent2, PARENT2);
AuRWLockFuncs(parent3, PARENT3);
AuRWLockFuncs(new_child, NEW_CHILD);

#undef AuReadLockFunc
#undef AuWriteLockFunc
#undef AuRWLockFuncs

#define ii_read_unlock(i)	au_rw_read_unlock(&au_ii(i)->ii_rwsem)
#define ii_write_unlock(i)	au_rw_write_unlock(&au_ii(i)->ii_rwsem)
#define ii_downgrade_lock(i)	au_rw_dgrade_lock(&au_ii(i)->ii_rwsem)

#define IiMustNoWaiters(i)	AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
#define IiMustAnyLock(i)	AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
#define IiMustWriteLock(i)	AuRwMustWriteLock(&au_ii(i)->ii_rwsem)

/* ---------------------------------------------------------------------- */

J. R. Okajima's avatar
J. R. Okajima committed
132
133
static inline void au_icntnr_init(struct au_icntnr *c)
{
J. R. Okajima's avatar
J. R. Okajima committed
134
135
136
#ifdef CONFIG_AUFS_DEBUG
	c->vfs_inode.i_mode = 0;
#endif
J. R. Okajima's avatar
J. R. Okajima committed
137
138
}

J. R. Okajima's avatar
J. R. Okajima committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
static inline unsigned int au_iigen(struct inode *inode)
{
	unsigned int gen;
	struct au_iinfo *iinfo;
	struct au_iigen *iigen;

	iinfo = au_ii(inode);
	iigen = &iinfo->ii_generation;
	spin_lock(&iigen->ig_spin);
	gen = iigen->ig_generation;
	spin_unlock(&iigen->ig_spin);

	return gen;
}

/* tiny test for inode number */
/* tmpfs generation is too rough */
static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
{
	struct au_iinfo *iinfo;

	iinfo = au_ii(inode);
	AuRwMustAnyLock(&iinfo->ii_rwsem);
	return !(iinfo->ii_hsb1 == h_inode->i_sb
		 && iinfo->ii_higen == h_inode->i_generation);
}

static inline void au_iigen_dec(struct inode *inode)
{
	struct au_iinfo *iinfo;
	struct au_iigen *iigen;

	iinfo = au_ii(inode);
	iigen = &iinfo->ii_generation;
	spin_lock(&iigen->ig_spin);
	iigen->ig_generation--;
	spin_unlock(&iigen->ig_spin);
}

static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
{
	int err;

	err = 0;
	if (unlikely(inode && au_iigen(inode) != sigen))
		err = -EIO;

	return err;
}

J. R. Okajima's avatar
J. R. Okajima committed
189
190
191
192
193
194
195
196
197
198
199
200
201
/* ---------------------------------------------------------------------- */

static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo,
					  aufs_bindex_t bindex)
{
	return iinfo->ii_hinode + bindex;
}

static inline int au_is_bad_inode(struct inode *inode)
{
	return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0));
}

202
203
204
205
206
207
208
static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
					aufs_bindex_t bindex)
{
	IiMustAnyLock(inode);
	return au_hinode(au_ii(inode), bindex)->hi_id;
}

J. R. Okajima's avatar
J. R. Okajima committed
209
210
static inline aufs_bindex_t au_ibtop(struct inode *inode)
{
J. R. Okajima's avatar
J. R. Okajima committed
211
	IiMustAnyLock(inode);
J. R. Okajima's avatar
J. R. Okajima committed
212
213
214
215
216
	return au_ii(inode)->ii_btop;
}

static inline aufs_bindex_t au_ibbot(struct inode *inode)
{
J. R. Okajima's avatar
J. R. Okajima committed
217
	IiMustAnyLock(inode);
J. R. Okajima's avatar
J. R. Okajima committed
218
219
220
221
222
	return au_ii(inode)->ii_bbot;
}

static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex)
{
J. R. Okajima's avatar
J. R. Okajima committed
223
	IiMustWriteLock(inode);
J. R. Okajima's avatar
J. R. Okajima committed
224
225
226
227
228
	au_ii(inode)->ii_btop = bindex;
}

static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex)
{
J. R. Okajima's avatar
J. R. Okajima committed
229
	IiMustWriteLock(inode);
J. R. Okajima's avatar
J. R. Okajima committed
230
231
232
233
234
	au_ii(inode)->ii_bbot = bindex;
}

static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
{
J. R. Okajima's avatar
J. R. Okajima committed
235
	IiMustAnyLock(inode);
J. R. Okajima's avatar
J. R. Okajima committed
236
237
238
239
240
	return au_hinode(au_ii(inode), bindex);
}

#endif /* __KERNEL__ */
#endif /* __AUFS_INODE_H__ */