2
* Copyright (C) 2005, 2006, 2007 Junjiro 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
19
/* $Id: dinfo.c,v 1.23 2007/05/07 03:43:36 sfjro Exp $ */
23
int au_alloc_dinfo(struct dentry *dentry)
25
struct aufs_dinfo *dinfo;
26
struct super_block *sb;
29
LKTRTrace("%.*s\n", DLNPair(dentry));
30
DEBUG_ON(dentry->d_fsdata);
32
dinfo = cache_alloc_dinfo();
33
//if (LktrCond) {cache_free_dinfo(dinfo); dinfo = NULL;}
39
dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry),
42
//{kfree(dinfo->di_hdentry); dinfo->di_hdentry = NULL;}
43
if (dinfo->di_hdentry) {
44
rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_PARENT);
45
dinfo->di_bstart = dinfo->di_bend = -1;
46
dinfo->di_bwh = dinfo->di_bdiropq = -1;
47
atomic_set(&dinfo->di_generation, au_sigen(sb));
49
dentry->d_fsdata = dinfo;
50
dentry->d_op = &aufs_dop;
51
return 0; /* success */
53
cache_free_dinfo(dinfo);
59
struct aufs_dinfo *dtodi(struct dentry *dentry)
61
struct aufs_dinfo *dinfo = dentry->d_fsdata;
64
/* || stosi(dentry->d_sb)->si_bend < dinfo->di_bend */
65
|| dinfo->di_bend < dinfo->di_bstart
66
/* dbwh can be outside of this range */
67
|| (0 <= dinfo->di_bdiropq
68
&& (dinfo->di_bdiropq < dinfo->di_bstart
69
/* || dinfo->di_bend < dinfo->di_bdiropq */))
74
/* ---------------------------------------------------------------------- */
76
static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
80
ii_write_lock_child(inode);
83
ii_write_lock_child2(inode);
86
ii_write_lock_child3(inode);
89
ii_write_lock_parent(inode);
91
case AuLsc_DI_PARENT2:
92
ii_write_lock_parent2(inode);
94
case AuLsc_DI_PARENT3:
95
ii_write_lock_parent3(inode);
102
static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
106
ii_read_lock_child(inode);
108
case AuLsc_DI_CHILD2:
109
ii_read_lock_child2(inode);
111
case AuLsc_DI_CHILD3:
112
ii_read_lock_child3(inode);
114
case AuLsc_DI_PARENT:
115
ii_read_lock_parent(inode);
117
case AuLsc_DI_PARENT2:
118
ii_read_lock_parent2(inode);
120
case AuLsc_DI_PARENT3:
121
ii_read_lock_parent3(inode);
128
void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
130
SiMustAnyLock(d->d_sb);
131
// todo: always nested?
132
rw_read_lock_nested(&dtodi(d)->di_rwsem, lsc);
134
if (flags & AUFS_I_WLOCK)
135
do_ii_write_lock(d->d_inode, lsc);
136
else if (flags & AUFS_I_RLOCK)
137
do_ii_read_lock(d->d_inode, lsc);
141
void di_read_unlock(struct dentry *d, int flags)
143
SiMustAnyLock(d->d_sb);
145
if (flags & AUFS_I_WLOCK)
146
ii_write_unlock(d->d_inode);
147
else if (flags & AUFS_I_RLOCK)
148
ii_read_unlock(d->d_inode);
150
rw_read_unlock(&dtodi(d)->di_rwsem);
153
void di_downgrade_lock(struct dentry *d, int flags)
155
SiMustAnyLock(d->d_sb);
156
rw_dgrade_lock(&dtodi(d)->di_rwsem);
157
if (d->d_inode && (flags & AUFS_I_RLOCK))
158
ii_downgrade_lock(d->d_inode);
161
void di_write_lock(struct dentry *d, unsigned int lsc)
163
SiMustAnyLock(d->d_sb);
164
// todo: always nested?
165
rw_write_lock_nested(&dtodi(d)->di_rwsem, lsc);
167
do_ii_write_lock(d->d_inode, lsc);
170
void di_write_unlock(struct dentry *d)
172
SiMustAnyLock(d->d_sb);
174
ii_write_unlock(d->d_inode);
175
rw_write_unlock(&dtodi(d)->di_rwsem);
178
void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
184
|| d1->d_inode == d2->d_inode
185
|| d1->d_sb != d2->d_sb);
188
for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
189
if (d->d_parent == d2) {
190
di_write_lock_child(d1);
191
di_write_lock_child2(d2);
195
di_write_lock_child(d2);
196
di_write_lock_child2(d1);
199
void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
205
|| d1->d_inode == d2->d_inode
206
|| d1->d_sb != d2->d_sb);
209
for (d = d1; d->d_parent != d; d = d->d_parent) // dget_parent()
210
if (d->d_parent == d2) {
211
di_write_lock_parent(d1);
212
di_write_lock_parent2(d2);
216
di_write_lock_parent(d2);
217
di_write_lock_parent2(d1);
220
void di_write_unlock2(struct dentry *d1, struct dentry *d2)
223
if (d1->d_inode == d2->d_inode)
224
rw_write_unlock(&dtodi(d2)->di_rwsem);
229
/* ---------------------------------------------------------------------- */
231
aufs_bindex_t dbstart(struct dentry *dentry)
233
DiMustAnyLock(dentry);
234
return dtodi(dentry)->di_bstart;
237
aufs_bindex_t dbend(struct dentry *dentry)
239
DiMustAnyLock(dentry);
240
return dtodi(dentry)->di_bend;
243
aufs_bindex_t dbwh(struct dentry *dentry)
245
DiMustAnyLock(dentry);
246
return dtodi(dentry)->di_bwh;
249
aufs_bindex_t dbdiropq(struct dentry *dentry)
251
DiMustAnyLock(dentry);
252
DEBUG_ON(dentry->d_inode
253
&& dentry->d_inode->i_mode
254
&& !S_ISDIR(dentry->d_inode->i_mode));
255
return dtodi(dentry)->di_bdiropq;
258
struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex)
262
DiMustAnyLock(dentry);
263
if (dbstart(dentry) < 0 || bindex < dbstart(dentry))
266
/* || bindex > sbend(dentry->d_sb) */);
267
d = dtodi(dentry)->di_hdentry[0 + bindex].hd_dentry;
268
DEBUG_ON(d && (atomic_read(&d->d_count) <= 0));
272
struct dentry *au_h_dptr(struct dentry *dentry)
274
return au_h_dptr_i(dentry, dbstart(dentry));
277
aufs_bindex_t dbtail(struct dentry *dentry)
279
aufs_bindex_t bend, bwh;
281
bend = dbend(dentry);
284
//DEBUG_ON(bend < bwh);
287
if (0 < bwh && bwh < bend)
293
aufs_bindex_t dbtaildir(struct dentry *dentry)
295
aufs_bindex_t bend, bopq;
297
DEBUG_ON(dentry->d_inode
298
&& dentry->d_inode->i_mode
299
&& !S_ISDIR(dentry->d_inode->i_mode));
301
bend = dbtail(dentry);
303
bopq = dbdiropq(dentry);
304
DEBUG_ON(bend < bopq);
305
if (0 <= bopq && bopq < bend)
311
aufs_bindex_t dbtail_generic(struct dentry *dentry)
315
inode = dentry->d_inode;
316
if (inode && S_ISDIR(inode->i_mode))
317
return dbtaildir(dentry);
319
return dbtail(dentry);
322
/* ---------------------------------------------------------------------- */
325
void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
327
DiMustWriteLock(dentry);
328
DEBUG_ON(sbend(dentry->d_sb) < bindex);
330
dtodi(dentry)->di_bstart = bindex;
333
void set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
335
DiMustWriteLock(dentry);
336
DEBUG_ON(sbend(dentry->d_sb) < bindex
337
|| bindex < dbstart(dentry));
338
dtodi(dentry)->di_bend = bindex;
341
void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
343
DiMustWriteLock(dentry);
344
DEBUG_ON(sbend(dentry->d_sb) < bindex);
345
/* dbwh can be outside of bstart - bend range */
346
dtodi(dentry)->di_bwh = bindex;
349
void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
351
DiMustWriteLock(dentry);
352
DEBUG_ON(sbend(dentry->d_sb) < bindex);
353
DEBUG_ON((bindex != -1
354
&& (bindex < dbstart(dentry) || dbend(dentry) < bindex))
356
&& dentry->d_inode->i_mode
357
&& !S_ISDIR(dentry->d_inode->i_mode)));
358
dtodi(dentry)->di_bdiropq = bindex;
361
void hdput(struct aufs_hdentry *hd)
366
void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
367
struct dentry *h_dentry)
369
struct aufs_hdentry *hd = dtodi(dentry)->di_hdentry + bindex;
370
DiMustWriteLock(dentry);
371
DEBUG_ON(bindex < dtodi(dentry)->di_bstart
372
|| bindex > dtodi(dentry)->di_bend
373
|| (h_dentry && atomic_read(&h_dentry->d_count) <= 0)
374
|| (h_dentry && hd->hd_dentry)
378
hd->hd_dentry = h_dentry;
381
/* ---------------------------------------------------------------------- */
383
void au_update_digen(struct dentry *dentry)
385
//DiMustWriteLock(dentry);
386
DEBUG_ON(!dentry->d_sb);
387
atomic_set(&dtodi(dentry)->di_generation, au_sigen(dentry->d_sb));
390
void au_update_dbstart(struct dentry *dentry)
392
aufs_bindex_t bindex, bstart = dbstart(dentry), bend = dbend(dentry);
393
struct dentry *hidden_dentry;
395
DiMustWriteLock(dentry);
396
for (bindex = bstart; bindex <= bend; bindex++) {
397
hidden_dentry = au_h_dptr_i(dentry, bindex);
400
if (hidden_dentry->d_inode) {
401
set_dbstart(dentry, bindex);
404
set_h_dptr(dentry, bindex, NULL);
406
//set_dbstart(dentry, -1);
407
//set_dbend(dentry, -1);
410
int au_find_dbindex(struct dentry *dentry, struct dentry *hidden_dentry)
412
aufs_bindex_t bindex, bend;
414
bend = dbend(dentry);
415
for (bindex = dbstart(dentry); bindex <= bend; bindex++)
416
if (au_h_dptr_i(dentry, bindex) == hidden_dentry)