2
* Copyright (C) 2005-2009 Junjiro R. Okajima
4
* This program, aufs is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
int au_alloc_dinfo(struct dentry *dentry)
27
struct au_dinfo *dinfo;
28
struct super_block *sb;
31
dinfo = au_cache_alloc_dinfo();
36
nbr = au_sbend(sb) + 1;
39
dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
40
if (unlikely(!dinfo->di_hdentry))
43
atomic_set(&dinfo->di_generation, au_sigen(sb));
44
/* smp_mb(); */ /* atomic_set */
45
au_rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
46
dinfo->di_bstart = -1;
49
dinfo->di_bdiropq = -1;
51
dentry->d_fsdata = dinfo;
52
dentry->d_op = &aufs_dop;
53
return 0; /* success */
56
au_cache_free_dinfo(dinfo);
61
int au_di_realloc(struct au_dinfo *dinfo, int nbr)
64
struct au_hdentry *hdp;
66
AuRwMustWriteLock(&dinfo->di_rwsem);
69
sz = sizeof(*hdp) * (dinfo->di_bend + 1);
72
hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
74
dinfo->di_hdentry = hdp;
81
/* ---------------------------------------------------------------------- */
83
static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
87
ii_write_lock_child(inode);
90
ii_write_lock_child2(inode);
93
ii_write_lock_child3(inode);
96
ii_write_lock_parent(inode);
98
case AuLsc_DI_PARENT2:
99
ii_write_lock_parent2(inode);
101
case AuLsc_DI_PARENT3:
102
ii_write_lock_parent3(inode);
109
static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
113
ii_read_lock_child(inode);
115
case AuLsc_DI_CHILD2:
116
ii_read_lock_child2(inode);
118
case AuLsc_DI_CHILD3:
119
ii_read_lock_child3(inode);
121
case AuLsc_DI_PARENT:
122
ii_read_lock_parent(inode);
124
case AuLsc_DI_PARENT2:
125
ii_read_lock_parent2(inode);
127
case AuLsc_DI_PARENT3:
128
ii_read_lock_parent3(inode);
135
void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
137
au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
139
if (au_ftest_lock(flags, IW))
140
do_ii_write_lock(d->d_inode, lsc);
141
else if (au_ftest_lock(flags, IR))
142
do_ii_read_lock(d->d_inode, lsc);
146
void di_read_unlock(struct dentry *d, int flags)
149
if (au_ftest_lock(flags, IW))
150
ii_write_unlock(d->d_inode);
151
else if (au_ftest_lock(flags, IR))
152
ii_read_unlock(d->d_inode);
154
au_rw_read_unlock(&au_di(d)->di_rwsem);
157
void di_downgrade_lock(struct dentry *d, int flags)
159
if (d->d_inode && au_ftest_lock(flags, IR))
160
ii_downgrade_lock(d->d_inode);
161
au_rw_dgrade_lock(&au_di(d)->di_rwsem);
164
void di_write_lock(struct dentry *d, unsigned int lsc)
166
au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
168
do_ii_write_lock(d->d_inode, lsc);
171
void di_write_unlock(struct dentry *d)
174
ii_write_unlock(d->d_inode);
175
au_rw_write_unlock(&au_di(d)->di_rwsem);
178
void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
181
|| d1->d_inode == d2->d_inode
182
|| d1->d_sb != d2->d_sb);
184
if (isdir && au_test_subdir(d1, d2)) {
185
di_write_lock_child(d1);
186
di_write_lock_child2(d2);
188
/* there should be no races */
189
di_write_lock_child(d2);
190
di_write_lock_child2(d1);
194
void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
197
|| d1->d_inode == d2->d_inode
198
|| d1->d_sb != d2->d_sb);
200
if (isdir && au_test_subdir(d1, d2)) {
201
di_write_lock_parent(d1);
202
di_write_lock_parent2(d2);
204
/* there should be no races */
205
di_write_lock_parent(d2);
206
di_write_lock_parent2(d1);
210
void di_write_unlock2(struct dentry *d1, struct dentry *d2)
213
if (d1->d_inode == d2->d_inode)
214
au_rw_write_unlock(&au_di(d2)->di_rwsem);
219
/* ---------------------------------------------------------------------- */
221
struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
225
DiMustAnyLock(dentry);
227
if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
229
AuDebugOn(bindex < 0);
230
d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
231
AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
235
aufs_bindex_t au_dbtail(struct dentry *dentry)
237
aufs_bindex_t bend, bwh;
239
bend = au_dbend(dentry);
241
bwh = au_dbwh(dentry);
244
if (0 < bwh && bwh < bend)
250
aufs_bindex_t au_dbtaildir(struct dentry *dentry)
252
aufs_bindex_t bend, bopq;
254
bend = au_dbtail(dentry);
256
bopq = au_dbdiropq(dentry);
257
if (0 <= bopq && bopq < bend)
263
/* ---------------------------------------------------------------------- */
265
void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
266
struct dentry *h_dentry)
268
struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
270
DiMustWriteLock(dentry);
274
hd->hd_dentry = h_dentry;
277
void au_update_digen(struct dentry *dentry)
279
atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
280
/* smp_mb(); */ /* atomic_set */
283
void au_update_dbrange(struct dentry *dentry, int do_put_zero)
285
struct au_dinfo *dinfo;
288
DiMustWriteLock(dentry);
290
dinfo = au_di(dentry);
291
if (!dinfo || dinfo->di_bstart < 0)
295
aufs_bindex_t bindex, bend;
297
bend = dinfo->di_bend;
298
for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
299
h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
300
if (h_d && !h_d->d_inode)
301
au_set_h_dptr(dentry, bindex, NULL);
305
dinfo->di_bstart = -1;
306
while (++dinfo->di_bstart <= dinfo->di_bend)
307
if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
309
if (dinfo->di_bstart > dinfo->di_bend) {
310
dinfo->di_bstart = -1;
316
while (0 <= --dinfo->di_bend)
317
if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
319
AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
322
void au_update_dbstart(struct dentry *dentry)
324
aufs_bindex_t bindex, bend;
325
struct dentry *h_dentry;
327
bend = au_dbend(dentry);
328
for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
329
h_dentry = au_h_dptr(dentry, bindex);
332
if (h_dentry->d_inode) {
333
au_set_dbstart(dentry, bindex);
336
au_set_h_dptr(dentry, bindex, NULL);
340
void au_update_dbend(struct dentry *dentry)
342
aufs_bindex_t bindex, bstart;
343
struct dentry *h_dentry;
345
bstart = au_dbstart(dentry);
346
for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
347
h_dentry = au_h_dptr(dentry, bindex);
350
if (h_dentry->d_inode) {
351
au_set_dbend(dentry, bindex);
354
au_set_h_dptr(dentry, bindex, NULL);
358
int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
360
aufs_bindex_t bindex, bend;
362
bend = au_dbend(dentry);
363
for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
364
if (au_h_dptr(dentry, bindex) == h_dentry)