~ubuntu-branches/ubuntu/vivid/aufs/vivid

« back to all changes in this revision

Viewing changes to fs/aufs/dinfo.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2008-05-06 18:35:50 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080506183550-0b6c974kkgc46oeh
Tags: 0+20080506-1
* New upstream release, supports Kernel 2.6.25 (Closes: #479717)
* Fix building with older Kernels (Closes: #475042)
* Update the patches 01, 04 and 07 to also patch fs/aufs25

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2005, 2006, 2007, 2008 Junjiro Okajima
 
2
 * Copyright (C) 2005-2008 Junjiro Okajima
3
3
 *
4
4
 * This program, aufs is free software; you can redistribute it and/or modify
5
5
 * it under the terms of the GNU General Public License as published by
16
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 */
18
18
 
19
 
/* $Id: dinfo.c,v 1.39 2008/03/16 23:46:30 sfjro Exp $ */
 
19
/*
 
20
 * dentry private data
 
21
 *
 
22
 * $Id: dinfo.c,v 1.41 2008/04/13 23:39:42 sfjro Exp $
 
23
 */
20
24
 
21
25
#include "aufs.h"
22
26
 
23
27
int au_alloc_dinfo(struct dentry *dentry)
24
28
{
25
 
        struct aufs_dinfo *dinfo;
 
29
        struct au_dinfo *dinfo;
26
30
        struct super_block *sb;
27
31
        int nbr;
28
32
 
33
37
        //if (LktrCond) {au_cache_free_dinfo(dinfo); dinfo = NULL;}
34
38
        if (dinfo) {
35
39
                sb = dentry->d_sb;
36
 
                nbr = sbend(sb) + 1;
 
40
                nbr = au_sbend(sb) + 1;
37
41
                if (unlikely(nbr <= 0))
38
42
                        nbr = 1;
39
43
                dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry),
44
48
                        au_h_dentry_init_all(dinfo->di_hdentry, nbr);
45
49
                        atomic_set(&dinfo->di_generation, au_sigen(sb));
46
50
                        //smp_mb(); /* atomic_set */
47
 
                        rw_init_wlock_nested(&dinfo->di_rwsem, AuLsc_DI_PARENT);
 
51
                        au_rw_init_wlock_nested(&dinfo->di_rwsem,
 
52
                                                AuLsc_DI_PARENT);
48
53
                        dinfo->di_bstart = -1;
49
54
                        dinfo->di_bend = -1;
50
55
                        dinfo->di_bwh = -1;
60
65
        return -ENOMEM;
61
66
}
62
67
 
63
 
struct aufs_dinfo *dtodi(struct dentry *dentry)
 
68
struct au_dinfo *au_di(struct dentry *dentry)
64
69
{
65
 
        struct aufs_dinfo *dinfo = dentry->d_fsdata;
 
70
        struct au_dinfo *dinfo = dentry->d_fsdata;
66
71
        AuDebugOn(!dinfo
67
72
                 || !dinfo->di_hdentry
68
 
                 /* || stosi(dentry->d_sb)->si_bend < dinfo->di_bend */
 
73
                 /* || au_sbi(dentry->d_sb)->si_bend < dinfo->di_bend */
69
74
                 || dinfo->di_bend < dinfo->di_bstart
70
75
                 /* dbwh can be outside of this range */
71
76
                 || (0 <= dinfo->di_bdiropq
139
144
{
140
145
        SiMustAnyLock(d->d_sb);
141
146
        // todo: always nested?
142
 
        rw_read_lock_nested(&dtodi(d)->di_rwsem, lsc);
 
147
        au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
143
148
        if (d->d_inode) {
144
149
                if (au_ftest_lock(flags, IW))
145
150
                        do_ii_write_lock(d->d_inode, lsc);
157
162
                else if (au_ftest_lock(flags, IR))
158
163
                        ii_read_unlock(d->d_inode);
159
164
        }
160
 
        rw_read_unlock(&dtodi(d)->di_rwsem);
 
165
        au_rw_read_unlock(&au_di(d)->di_rwsem);
161
166
}
162
167
 
163
168
void di_downgrade_lock(struct dentry *d, int flags)
164
169
{
165
170
        SiMustAnyLock(d->d_sb);
166
 
        rw_dgrade_lock(&dtodi(d)->di_rwsem);
 
171
        au_rw_dgrade_lock(&au_di(d)->di_rwsem);
167
172
        if (d->d_inode && au_ftest_lock(flags, IR))
168
173
                ii_downgrade_lock(d->d_inode);
169
174
}
172
177
{
173
178
        SiMustAnyLock(d->d_sb);
174
179
        // todo: always nested?
175
 
        rw_write_lock_nested(&dtodi(d)->di_rwsem, lsc);
 
180
        au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
176
181
        if (d->d_inode)
177
182
                do_ii_write_lock(d->d_inode, lsc);
178
183
}
182
187
        SiMustAnyLock(d->d_sb);
183
188
        if (d->d_inode)
184
189
                ii_write_unlock(d->d_inode);
185
 
        rw_write_unlock(&dtodi(d)->di_rwsem);
 
190
        au_rw_write_unlock(&au_di(d)->di_rwsem);
186
191
}
187
192
 
188
193
void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
223
228
{
224
229
        di_write_unlock(d1);
225
230
        if (d1->d_inode == d2->d_inode)
226
 
                rw_write_unlock(&dtodi(d2)->di_rwsem);
 
231
                au_rw_write_unlock(&au_di(d2)->di_rwsem);
227
232
        else
228
233
                di_write_unlock(d2);
229
234
}
230
235
 
231
236
/* ---------------------------------------------------------------------- */
232
237
 
233
 
aufs_bindex_t dbstart(struct dentry *dentry)
234
 
{
235
 
        DiMustAnyLock(dentry);
236
 
        return dtodi(dentry)->di_bstart;
237
 
}
238
 
 
239
 
aufs_bindex_t dbend(struct dentry *dentry)
240
 
{
241
 
        DiMustAnyLock(dentry);
242
 
        return dtodi(dentry)->di_bend;
243
 
}
244
 
 
245
 
aufs_bindex_t dbwh(struct dentry *dentry)
246
 
{
247
 
        DiMustAnyLock(dentry);
248
 
        return dtodi(dentry)->di_bwh;
249
 
}
250
 
 
251
 
aufs_bindex_t dbdiropq(struct dentry *dentry)
252
 
{
253
 
        DiMustAnyLock(dentry);
254
 
        AuDebugOn(dentry->d_inode
255
 
                  && dentry->d_inode->i_mode
256
 
                  && !S_ISDIR(dentry->d_inode->i_mode));
257
 
        return dtodi(dentry)->di_bdiropq;
258
 
}
259
 
 
260
238
struct dentry *au_h_dptr_i(struct dentry *dentry, aufs_bindex_t bindex)
261
239
{
262
240
        struct dentry *d;
263
241
 
264
242
        DiMustAnyLock(dentry);
265
 
        if (dbstart(dentry) < 0 || bindex < dbstart(dentry))
 
243
        if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
266
244
                return NULL;
267
245
        AuDebugOn(bindex < 0
268
 
                  /* || bindex > sbend(dentry->d_sb) */);
269
 
        d = dtodi(dentry)->di_hdentry[0 + bindex].hd_dentry;
 
246
                  /* || bindex > au_sbend(dentry->d_sb) */);
 
247
        d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
270
248
        AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
271
249
        return d;
272
250
}
273
251
 
274
 
struct dentry *au_h_dptr(struct dentry *dentry)
275
 
{
276
 
        return au_h_dptr_i(dentry, dbstart(dentry));
277
 
}
278
 
 
279
 
aufs_bindex_t dbtail(struct dentry *dentry)
 
252
aufs_bindex_t au_dbtail(struct dentry *dentry)
280
253
{
281
254
        aufs_bindex_t bend, bwh;
282
255
 
283
 
        bend = dbend(dentry);
 
256
        bend = au_dbend(dentry);
284
257
        if (0 <= bend) {
285
 
                bwh = dbwh(dentry);
 
258
                bwh = au_dbwh(dentry);
286
259
                //AuDebugOn(bend < bwh);
287
260
                if (!bwh)
288
261
                        return bwh;
292
265
        return bend;
293
266
}
294
267
 
295
 
aufs_bindex_t dbtaildir(struct dentry *dentry)
 
268
aufs_bindex_t au_dbtaildir(struct dentry *dentry)
296
269
{
297
270
        aufs_bindex_t bend, bopq;
298
271
 
300
273
                  && dentry->d_inode->i_mode
301
274
                  && !S_ISDIR(dentry->d_inode->i_mode));
302
275
 
303
 
        bend = dbtail(dentry);
 
276
        bend = au_dbtail(dentry);
304
277
        if (0 <= bend) {
305
 
                bopq = dbdiropq(dentry);
 
278
                bopq = au_dbdiropq(dentry);
306
279
                AuDebugOn(bend < bopq);
307
280
                if (0 <= bopq && bopq < bend)
308
281
                        bend = bopq;
310
283
        return bend;
311
284
}
312
285
 
313
 
aufs_bindex_t dbtail_generic(struct dentry *dentry)
 
286
aufs_bindex_t au_dbtail_generic(struct dentry *dentry)
314
287
{
315
288
        struct inode *inode;
316
289
 
317
290
        inode = dentry->d_inode;
318
291
        if (inode && S_ISDIR(inode->i_mode))
319
 
                return dbtaildir(dentry);
 
292
                return au_dbtaildir(dentry);
320
293
        else
321
 
                return dbtail(dentry);
 
294
                return au_dbtail(dentry);
322
295
}
323
296
 
324
297
/* ---------------------------------------------------------------------- */
325
298
 
326
 
// hard/soft set
327
 
void set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
328
 
{
329
 
        DiMustWriteLock(dentry);
330
 
        AuDebugOn(sbend(dentry->d_sb) < bindex);
331
 
        /* */
332
 
        dtodi(dentry)->di_bstart = bindex;
333
 
}
334
 
 
335
 
void set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
336
 
{
337
 
        DiMustWriteLock(dentry);
338
 
        AuDebugOn(sbend(dentry->d_sb) < bindex
339
 
                  || bindex < dbstart(dentry));
340
 
        dtodi(dentry)->di_bend = bindex;
341
 
}
342
 
 
343
 
void set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
344
 
{
345
 
        DiMustWriteLock(dentry);
346
 
        AuDebugOn(sbend(dentry->d_sb) < bindex);
347
 
        /* dbwh can be outside of bstart - bend range */
348
 
        dtodi(dentry)->di_bwh = bindex;
349
 
}
350
 
 
351
 
void set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
352
 
{
353
 
        DiMustWriteLock(dentry);
354
 
        AuDebugOn(sbend(dentry->d_sb) < bindex);
 
299
void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
 
300
{
 
301
        DiMustWriteLock(dentry);
 
302
        AuDebugOn(au_sbend(dentry->d_sb) < bindex);
355
303
        AuDebugOn((bindex >= 0
356
 
                   && (bindex < dbstart(dentry) || dbend(dentry) < bindex))
 
304
                   && (bindex < au_dbstart(dentry)
 
305
                       || au_dbend(dentry) < bindex))
357
306
                  || (dentry->d_inode
358
307
                      && dentry->d_inode->i_mode
359
308
                      && !S_ISDIR(dentry->d_inode->i_mode)));
360
 
        dtodi(dentry)->di_bdiropq = bindex;
361
 
}
362
 
 
363
 
static void hintent_put(struct aufs_hdentry *hd, int do_free)
364
 
{
365
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) \
366
 
        && !defined(AuNoNfsBranch)
367
 
        struct aufs_hdintent *hdi, *tmp;
368
 
        struct file *hf;
369
 
 
370
 
        if (unlikely(hd->hd_intent_list)) {
371
 
                // no spin lock
372
 
                list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list,
373
 
                                         hdi_list) {
374
 
                        LKTRTrace("hdi %p\n", hdi);
375
 
                        hf = hdi->hdi_file[AuIntent_BRANCH];
376
 
                        if (unlikely(hf))
377
 
                                fput(hf);
378
 
                        //list_del(&hdi->hdi_list);
379
 
                        kfree(hdi);
380
 
                }
381
 
                if (do_free)
382
 
                        kfree(hd->hd_intent_list);
383
 
        }
384
 
#endif
385
 
}
386
 
 
387
 
void hdput(struct aufs_hdentry *hd, int do_free)
388
 
{
389
 
        hintent_put(hd, do_free);
390
 
        dput(hd->hd_dentry);
391
 
}
392
 
 
393
 
void set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
394
 
                struct dentry *h_dentry)
395
 
{
396
 
        struct aufs_hdentry *hd = dtodi(dentry)->di_hdentry + bindex;
 
309
        au_di(dentry)->di_bdiropq = bindex;
 
310
}
 
311
 
 
312
void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
 
313
                   struct dentry *h_dentry)
 
314
{
 
315
        struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
397
316
        DiMustWriteLock(dentry);
398
 
        AuDebugOn(bindex < dtodi(dentry)->di_bstart
399
 
                  || bindex > dtodi(dentry)->di_bend
 
317
        AuDebugOn(bindex < au_di(dentry)->di_bstart
 
318
                  || bindex > au_di(dentry)->di_bend
400
319
                  || (h_dentry && atomic_read(&h_dentry->d_count) <= 0)
401
320
                  || (h_dentry && hd->hd_dentry)
402
321
                );
403
322
        if (hd->hd_dentry)
404
 
                hdput(hd, /*do_free*/0);
 
323
                au_hdput(hd, /*do_free*/0);
405
324
        hd->hd_dentry = h_dentry;
406
325
}
407
326
 
408
327
/* ---------------------------------------------------------------------- */
409
328
 
410
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) \
411
 
        && !defined(AuNoNfsBranch)
412
 
static struct file *au_find_h_intent(struct aufs_hdentry *hd, struct file *file)
413
 
{
414
 
        struct file *h_file, *hf;
415
 
        struct aufs_hdintent *hdi, *tmp;
416
 
 
417
 
        LKTRTrace("%.*s\n", AuDLNPair(hd->hd_dentry));
418
 
 
419
 
        h_file = NULL;
420
 
        spin_lock(&hd->hd_lock);
421
 
        list_for_each_entry_safe(hdi, tmp, hd->hd_intent_list, hdi_list) {
422
 
                hf = hdi->hdi_file[AuIntent_BRANCH];
423
 
                if (hdi->hdi_file[AuIntent_AUFS] == file
424
 
                    && hf->f_dentry == hd->hd_dentry) {
425
 
                        h_file = hf;
426
 
                        list_del(&hdi->hdi_list);
427
 
                        kfree(hdi);
428
 
                        break;
429
 
                }
430
 
        }
431
 
        spin_unlock(&hd->hd_lock);
432
 
 
433
 
        return h_file;
434
 
}
435
 
 
436
 
struct file *au_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
437
 
                         struct file *file)
438
 
{
439
 
        struct file *h_file;
440
 
        struct aufs_hdentry *hd = dtodi(dentry)->di_hdentry + bindex;
441
 
 
442
 
        LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file);
443
 
        DiMustAnyLock(dentry);
444
 
        AuDebugOn(bindex < dtodi(dentry)->di_bstart
445
 
                  || bindex > dtodi(dentry)->di_bend);
446
 
 
447
 
        h_file = NULL;
448
 
        if (!hd->hd_intent_list || !file)
449
 
                return h_file; /* success */
450
 
 
451
 
        //AuDebugOn(au_test_wkq(current));
452
 
        h_file = au_find_h_intent(hd, file);
453
 
        //AuDbgFile(h_file);
454
 
        return h_file;
455
 
}
456
 
 
457
 
int au_set_h_intent(struct dentry *dentry, aufs_bindex_t bindex,
458
 
                    struct file *file, struct file *h_file)
459
 
{
460
 
        int err;
461
 
        struct aufs_hdentry *hd = dtodi(dentry)->di_hdentry + bindex;
462
 
        struct aufs_hdintent *hdi;
463
 
        struct file *hf;
464
 
 
465
 
        LKTRTrace("%.*s, b%d, f %p\n", AuDLNPair(dentry), bindex, file);
466
 
        /* d_revalidate() holds read_lock */
467
 
        //DiMustWriteLock(dentry);
468
 
        AuDebugOn(bindex < dtodi(dentry)->di_bstart
469
 
                  || bindex > dtodi(dentry)->di_bend
470
 
                  || !file
471
 
                  || !h_file
472
 
                  /* || au_test_wkq(current) */);
473
 
 
474
 
        err = -ENOMEM;
475
 
        if (hd->hd_intent_list) {
476
 
                while (1) {
477
 
                        hf = au_find_h_intent(hd, file);
478
 
                        if (!hf)
479
 
                                break;
480
 
#if 0 //def CONFIG_AUFS_DEBUG
481
 
                        au_debug_on();
482
 
                        DbgDentry(dentry);
483
 
                        DbgFile(hf);
484
 
                        au_debug_off();
485
 
#endif
486
 
                        fput(hf);
487
 
                        AuWarn("freed hfile %.*s b%d left\n",
488
 
                               AuDLNPair(dentry), bindex);
489
 
                }
490
 
        } else {
491
 
                spin_lock(&hd->hd_lock);
492
 
                if (!hd->hd_intent_list) {
493
 
                        hd->hd_intent_list
494
 
                                = kmalloc(sizeof(*hd->hd_intent_list),
495
 
                                          GFP_ATOMIC);
496
 
                        if (unlikely(!hd->hd_intent_list)) {
497
 
                                spin_unlock(&hd->hd_lock);
498
 
                                goto out;
499
 
                        }
500
 
                        INIT_LIST_HEAD(hd->hd_intent_list);
501
 
                }
502
 
                spin_unlock(&hd->hd_lock);
503
 
        }
504
 
 
505
 
        hdi = kmalloc(sizeof(*hdi), GFP_TEMPORARY);
506
 
        if (unlikely(!hdi))
507
 
                goto out;
508
 
 
509
 
        err = 0;
510
 
        //hdi->hdi_pid = current->pid;
511
 
        hdi->hdi_file[AuIntent_AUFS] = file;
512
 
        hdi->hdi_file[AuIntent_BRANCH] = h_file;
513
 
        spin_lock(&hd->hd_lock);
514
 
        list_add(&hdi->hdi_list, hd->hd_intent_list);
515
 
        spin_unlock(&hd->hd_lock);
516
 
        //AuDbgDentry(dentry);
517
 
        //AuDbgFile(h_file);
518
 
 
519
 
 out:
520
 
        AuTraceErr(err);
521
 
        return err;
522
 
}
523
 
#endif /* !defined(AuNoNfsBranch) */
524
 
 
525
 
/* ---------------------------------------------------------------------- */
526
 
 
527
 
void au_update_digen(struct dentry *dentry)
528
 
{
529
 
        //DiMustWriteLock(dentry);
530
 
        AuDebugOn(!dentry->d_sb);
531
 
        atomic_set(&dtodi(dentry)->di_generation, au_sigen(dentry->d_sb));
532
 
        //smp_mb(); /* atomic_set */
533
 
}
534
 
 
535
329
void au_update_dbrange(struct dentry *dentry, int do_put_zero)
536
330
{
537
 
        struct aufs_dinfo *dinfo;
 
331
        struct au_dinfo *dinfo;
538
332
        aufs_bindex_t bindex;
539
333
        struct dentry *h_d;
540
334
 
541
335
        LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), do_put_zero);
542
336
        DiMustWriteLock(dentry);
543
337
 
544
 
        dinfo = dtodi(dentry);
 
338
        dinfo = au_di(dentry);
545
339
        if (unlikely(!dinfo) || dinfo->di_bstart < 0)
546
340
                return;
547
341
 
550
344
                     bindex++) {
551
345
                        h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
552
346
                        if (h_d && !h_d->d_inode)
553
 
                                set_h_dptr(dentry, bindex, NULL);
 
347
                                au_set_h_dptr(dentry, bindex, NULL);
554
348
                }
555
349
        }
556
350
 
573
367
 
574
368
void au_update_dbstart(struct dentry *dentry)
575
369
{
576
 
        aufs_bindex_t bindex, bstart = dbstart(dentry), bend = dbend(dentry);
 
370
        aufs_bindex_t bindex,
 
371
                bstart = au_dbstart(dentry),
 
372
                bend = au_dbend(dentry);
577
373
        struct dentry *hidden_dentry;
578
374
 
579
375
        LKTRTrace("%.*s\n", AuDLNPair(dentry));
584
380
                if (!hidden_dentry)
585
381
                        continue;
586
382
                if (hidden_dentry->d_inode) {
587
 
                        set_dbstart(dentry, bindex);
 
383
                        au_set_dbstart(dentry, bindex);
588
384
                        return;
589
385
                }
590
 
                set_h_dptr(dentry, bindex, NULL);
 
386
                au_set_h_dptr(dentry, bindex, NULL);
591
387
        }
592
 
        //set_dbstart(dentry, -1);
593
 
        //set_dbend(dentry, -1);
 
388
        //au_set_dbstart(dentry, -1);
 
389
        //au_set_dbend(dentry, -1);
594
390
}
595
391
 
596
392
void au_update_dbend(struct dentry *dentry)
597
393
{
598
 
        aufs_bindex_t bindex, bstart = dbstart(dentry), bend = dbend(dentry);
 
394
        aufs_bindex_t bindex,
 
395
                bstart = au_dbstart(dentry),
 
396
                bend = au_dbend(dentry);
599
397
        struct dentry *h_dentry;
600
398
 
601
399
        DiMustWriteLock(dentry);
604
402
                if (!h_dentry)
605
403
                        continue;
606
404
                if (h_dentry->d_inode) {
607
 
                        set_dbend(dentry, bindex);
 
405
                        au_set_dbend(dentry, bindex);
608
406
                        return;
609
407
                }
610
 
                set_h_dptr(dentry, bindex, NULL);
 
408
                au_set_h_dptr(dentry, bindex, NULL);
611
409
        }
612
 
        //set_dbstart(dentry, -1);
613
 
        //set_dbend(dentry, -1);
 
410
        //au_set_dbstart(dentry, -1);
 
411
        //au_set_dbend(dentry, -1);
614
412
}
615
413
 
616
414
int au_find_dbindex(struct dentry *dentry, struct dentry *hidden_dentry)
617
415
{
618
416
        aufs_bindex_t bindex, bend;
619
417
 
620
 
        bend = dbend(dentry);
621
 
        for (bindex = dbstart(dentry); bindex <= bend; bindex++)
 
418
        bend = au_dbend(dentry);
 
419
        for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
622
420
                if (au_h_dptr_i(dentry, bindex) == hidden_dentry)
623
421
                        return bindex;
624
422
        return -1;