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

« back to all changes in this revision

Viewing changes to fs/aufs/wbr_policy.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2007-12-15 23:32:51 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071215233251-2vgs2lmg8mai5d9e
Tags: 0+20071211-1ubuntu1
* Merge from debian unstable (LP: #175705), remaining changes:
  - Fix for Ubuntu Kernels (updated)
* patches/01_vserver.dpatch: Removed
* patches/06_ubuntu.dpatch: Added (update of ubuntu patch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2007 Junjiro Okajima
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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
 
17
 */
 
18
 
 
19
/* $Id: wbr_policy.c,v 1.5 2007/11/26 01:34:50 sfjro Exp $ */
 
20
 
 
21
#include <linux/statfs.h>
 
22
#include "aufs.h"
 
23
 
 
24
static int au_cpdown_attr(struct dentry *h_dst, struct dentry *h_src, int dlgt)
 
25
{
 
26
        int err, sbits;
 
27
        struct iattr ia;
 
28
        struct inode *h_idst, *h_isrc;
 
29
        struct vfsub_args vargs;
 
30
 
 
31
        LKTRTrace("%.*s\n", AuDLNPair(h_dst));
 
32
        h_idst = h_dst->d_inode;
 
33
        //IMustLock(h_idst);
 
34
        h_isrc = h_src->d_inode;
 
35
        //IMustLock(h_isrc);
 
36
 
 
37
        ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
 
38
        ia.ia_mode = h_isrc->i_mode;
 
39
        ia.ia_uid = h_isrc->i_uid;
 
40
        ia.ia_gid = h_isrc->i_gid;
 
41
        sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
 
42
 
 
43
        vfsub_args_init(&vargs, NULL, dlgt, /*force_unlink*/0);
 
44
        err = vfsub_notify_change(h_dst, &ia, &vargs);
 
45
 
 
46
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 
47
        /* is this nfs only? */
 
48
        if (!err && sbits && au_test_nfs(h_dst->d_sb)) {
 
49
                ia.ia_valid = ATTR_FORCE | ATTR_MODE;
 
50
                ia.ia_mode = h_isrc->i_mode;
 
51
                err = vfsub_notify_change(h_dst, &ia, &vargs);
 
52
        }
 
53
#endif
 
54
        if (!err)
 
55
                h_idst->i_flags = h_isrc->i_flags; //??
 
56
 
 
57
        AuTraceErr(err);
 
58
        return err;
 
59
}
 
60
 
 
61
struct au_cpdown_dir_args {
 
62
        struct dentry *parent;
 
63
        unsigned int parent_opq:1;
 
64
};
 
65
 
 
66
static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
 
67
                         struct dentry *h_parent, void *arg)
 
68
{
 
69
        int err, parent_opq, whed, dlgt, do_opq, made_dir, diropq, rerr;
 
70
        struct au_cpdown_dir_args *args = arg;
 
71
        aufs_bindex_t bend, bopq;
 
72
        struct dentry *h_dentry, *opq_dentry, *wh_dentry;
 
73
        struct inode *h_dir, *h_inode, *inode;
 
74
 
 
75
        LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst);
 
76
        AuDebugOn(dbstart(dentry) <= bdst
 
77
                  && bdst <= dbend(dentry)
 
78
                  && au_h_dptr_i(dentry, bdst));
 
79
        AuDebugOn(!h_parent);
 
80
        h_dir = h_parent->d_inode;
 
81
        AuDebugOn(!h_dir);
 
82
        IMustLock(h_dir);
 
83
 
 
84
        err = au_lkup_neg(dentry, bdst);
 
85
        if (unlikely(err < 0))
 
86
                goto out;
 
87
        h_dentry = au_h_dptr_i(dentry, bdst);
 
88
        dlgt = au_need_dlgt(dentry->d_sb);
 
89
        err = vfsub_sio_mkdir(h_dir, h_dentry, 0755, dlgt);
 
90
        if (unlikely(err))
 
91
                goto out_put;
 
92
 
 
93
        made_dir = 1;
 
94
        bend = dbend(dentry);
 
95
        bopq = dbdiropq(dentry);
 
96
        whed = (dbwh(dentry) == bdst);
 
97
        if (!args->parent_opq)
 
98
                args->parent_opq |= (bopq <= bdst);
 
99
        parent_opq = (args->parent_opq && args->parent == dentry);
 
100
        do_opq = 0;
 
101
        diropq = 0;
 
102
        h_inode = h_dentry->d_inode;
 
103
        vfsub_i_lock_nested(h_inode, AuLsc_I_CHILD);
 
104
        if (whed || (parent_opq && do_opq)) {
 
105
                opq_dentry = create_diropq(dentry, bdst, dlgt);
 
106
                err = PTR_ERR(opq_dentry);
 
107
                if (IS_ERR(opq_dentry)) {
 
108
                        vfsub_i_unlock(h_inode);
 
109
                        goto out_dir;
 
110
                }
 
111
                dput(opq_dentry);
 
112
                diropq = 1;
 
113
        }
 
114
 
 
115
        err = au_cpdown_attr(h_dentry, au_h_dptr(dentry), dlgt);
 
116
        vfsub_i_unlock(h_inode);
 
117
        if (unlikely(err))
 
118
                goto out_opq;
 
119
 
 
120
        wh_dentry = NULL;
 
121
        if (whed) {
 
122
                wh_dentry = lkup_wh(h_parent, &dentry->d_name, /*ndx*/NULL);
 
123
                err = PTR_ERR(wh_dentry);
 
124
                if (IS_ERR(wh_dentry))
 
125
                        goto out_opq;
 
126
                err = 0;
 
127
                if (wh_dentry->d_inode)
 
128
                        err = au_unlink_wh_dentry(h_dir, wh_dentry, dentry,
 
129
                                                  NULL, dlgt);
 
130
                dput(wh_dentry);
 
131
                if (unlikely(err))
 
132
                        goto out_opq;
 
133
        }
 
134
 
 
135
        inode = dentry->d_inode;
 
136
        if (ibend(inode) < bdst)
 
137
                set_ibend(inode, bdst);
 
138
        set_h_iptr(inode, bdst, igrab(h_inode), au_hi_flags(inode, 1));
 
139
        goto out; /* success */
 
140
 
 
141
        /* revert */
 
142
 out_opq:
 
143
        if (diropq) {
 
144
                vfsub_i_lock_nested(h_inode, AuLsc_I_CHILD);
 
145
                rerr = remove_diropq(dentry, bdst, dlgt);
 
146
                vfsub_i_unlock(h_inode);
 
147
                if (unlikely(rerr)) {
 
148
                        AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
 
149
                                AuDLNPair(dentry), bdst, rerr);
 
150
                        err = -EIO;
 
151
                        goto out;
 
152
                }
 
153
        }
 
154
 out_dir:
 
155
        if (made_dir) {
 
156
                rerr = vfsub_sio_rmdir(h_dir, h_dentry, dlgt);
 
157
                if (unlikely(rerr)) {
 
158
                        AuIOErr("failed removing %.*s b%d (%d)\n",
 
159
                                AuDLNPair(dentry), bdst, rerr);
 
160
                        err = -EIO;
 
161
                }
 
162
        }
 
163
 out_put:
 
164
        set_h_dptr(dentry, bdst, NULL);
 
165
        if (dbend(dentry) == bdst)
 
166
                au_update_dbend(dentry);
 
167
 out:
 
168
        AuTraceErr(err);
 
169
        return err;
 
170
}
 
171
 
 
172
int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst,
 
173
                   struct dentry *locked)
 
174
{
 
175
        int err;
 
176
        struct au_cpdown_dir_args args = {
 
177
                .parent         = dget_parent(dentry),
 
178
                .parent_opq     = 0
 
179
        };
 
180
 
 
181
        LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst);
 
182
 
 
183
        err = au_cp_dirs(dentry, bdst, locked, au_cpdown_dir, &args);
 
184
        dput(args.parent);
 
185
 
 
186
        AuTraceErr(err);
 
187
        return err;
 
188
}
 
189
 
 
190
/* ---------------------------------------------------------------------- */
 
191
 
 
192
#if 0
 
193
/*
 
194
 * returns writable branch index, otherwise an error.
 
195
 * todo: customizable writable-branch-policy
 
196
 */
 
197
static int find_rw_parent(struct dentry *dentry, aufs_bindex_t bend)
 
198
{
 
199
        int err;
 
200
        aufs_bindex_t bindex, candidate;
 
201
        struct super_block *sb;
 
202
        struct dentry *parent, *hidden_parent;
 
203
 
 
204
        err = bend;
 
205
        sb = dentry->d_sb;
 
206
        parent = dget_parent(dentry);
 
207
#if 1 // branch policy
 
208
        hidden_parent = au_h_dptr_i(parent, bend);
 
209
        if (hidden_parent && !br_rdonly(stobr(sb, bend)))
 
210
                goto out; /* success */
 
211
#endif
 
212
 
 
213
        candidate = -1;
 
214
        for (bindex = dbstart(parent); bindex <= bend; bindex++) {
 
215
                hidden_parent = au_h_dptr_i(parent, bindex);
 
216
                if (hidden_parent && !br_rdonly(stobr(sb, bindex))) {
 
217
#if 0 // branch policy
 
218
                        if (candidate == -1)
 
219
                                candidate = bindex;
 
220
                        if (!au_test_perm(hidden_parent->d_inode, MAY_WRITE))
 
221
                                return bindex;
 
222
#endif
 
223
                        err = bindex;
 
224
                        goto out; /* success */
 
225
                }
 
226
        }
 
227
#if 0 // branch policy
 
228
        err = candidate;
 
229
        if (candidate != -1)
 
230
                goto out; /* success */
 
231
#endif
 
232
        err = -EROFS;
 
233
 
 
234
 out:
 
235
        dput(parent);
 
236
        return err;
 
237
}
 
238
 
 
239
int find_rw_br(struct super_block *sb, aufs_bindex_t bend)
 
240
{
 
241
        aufs_bindex_t bindex;
 
242
 
 
243
        for (bindex = bend; bindex >= 0; bindex--)
 
244
                if (!br_rdonly(stobr(sb, bindex)))
 
245
                        return bindex;
 
246
        return -EROFS;
 
247
}
 
248
 
 
249
int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend)
 
250
{
 
251
        int err;
 
252
 
 
253
        err = find_rw_parent(dentry, bend);
 
254
        if (err >= 0)
 
255
                return err;
 
256
        return find_rw_br(dentry->d_sb, bend);
 
257
}
 
258
 
 
259
#if 0 // branch policy
 
260
/*
 
261
 * dir_cpdown/nodir_cpdown(def)
 
262
 * wr_br_policy=dir | branch
 
263
 */
 
264
int au_rw(struct dentry *dentry, aufs_bindex_t bend)
 
265
{
 
266
        int err;
 
267
        struct super_block *sb;
 
268
 
 
269
        sb = dentry->d_sb;
 
270
        SiMustAnyLock(sb);
 
271
 
 
272
        if (!au_flag_test(sb, AuFlag_DIR_CPDOWN)) {
 
273
                dpages;
 
274
        }
 
275
}
 
276
#endif
 
277
#endif
 
278
 
 
279
/* ---------------------------------------------------------------------- */
 
280
 
 
281
/* policies for create */
 
282
 
 
283
static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
 
284
{
 
285
        for (; bindex >= 0; bindex--)
 
286
                if (!br_rdonly(stobr(sb, bindex)))
 
287
                        return bindex;
 
288
        return -EROFS;
 
289
}
 
290
 
 
291
/* top down parent */
 
292
static int au_wbr_create_tdp(struct dentry *dentry, int isdir)
 
293
{
 
294
        int err;
 
295
        struct super_block *sb;
 
296
        aufs_bindex_t bstart, bindex;
 
297
        struct dentry *parent, *h_parent;
 
298
 
 
299
        LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
 
300
 
 
301
        sb = dentry->d_sb;
 
302
        bstart = dbstart(dentry);
 
303
        err = bstart;
 
304
        if (!br_rdonly(stobr(sb, bstart)))
 
305
                goto out;
 
306
 
 
307
        err = -EROFS;
 
308
        parent = dget_parent(dentry);
 
309
        for (bindex = dbstart(parent); bindex < bstart; bindex++) {
 
310
                h_parent = au_h_dptr_i(parent, bindex);
 
311
                if (h_parent && !br_rdonly(stobr(sb, bindex))) {
 
312
                        err = bindex;
 
313
                        break;
 
314
                }
 
315
        }
 
316
        dput(parent);
 
317
 
 
318
        /* bottom up here */
 
319
        if (unlikely(err < 0))
 
320
                err = au_wbr_bu(sb, bstart - 1);
 
321
 
 
322
 out:
 
323
        LKTRTrace("b%d\n", err);
 
324
        return err;
 
325
}
 
326
 
 
327
/* ---------------------------------------------------------------------- */
 
328
 
 
329
/* an exception for the policy other than tdp */
 
330
static int au_wbr_create_exp(struct dentry *dentry)
 
331
{
 
332
        int err;
 
333
        struct dentry *parent;
 
334
        aufs_bindex_t bwh, bdiropq;
 
335
 
 
336
        LKTRTrace("%.*s\n", AuDLNPair(dentry));
 
337
 
 
338
        err = -1;
 
339
        bwh = dbwh(dentry);
 
340
        parent = dget_parent(dentry);
 
341
        bdiropq = dbdiropq(parent);
 
342
        if (bwh >= 0) {
 
343
                if (bdiropq >= 0)
 
344
                        err = min(bdiropq, bwh);
 
345
                else
 
346
                        err = bwh;
 
347
                LKTRTrace("%d\n", err);
 
348
        } else if (bdiropq >= 0) {
 
349
                err = bdiropq;
 
350
                LKTRTrace("%d\n", err);
 
351
        }
 
352
        dput(parent);
 
353
 
 
354
        if (err >= 0 && br_rdonly(stobr(dentry->d_sb, err)))
 
355
                err = -1;
 
356
 
 
357
        LKTRTrace("%d\n", err);
 
358
        return err;
 
359
}
 
360
 
 
361
/* ---------------------------------------------------------------------- */
 
362
 
 
363
/* round robin */
 
364
static int au_wbr_create_init_rr(struct super_block *sb)
 
365
{
 
366
        int err;
 
367
 
 
368
        err = au_wbr_bu(sb, sbend(sb));
 
369
        atomic_set(&stosi(sb)->si_wbr_rr_next, -err); /* less important */
 
370
 
 
371
        LKTRTrace("b%d\n", err);
 
372
        return err;
 
373
}
 
374
 
 
375
static int au_wbr_create_rr(struct dentry *dentry, int isdir)
 
376
{
 
377
        int err, nbr;
 
378
        struct super_block *sb;
 
379
        atomic_t *next;
 
380
        unsigned int u;
 
381
        aufs_bindex_t bindex, bend;
 
382
 
 
383
        //au_debug_on();
 
384
        LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
 
385
 
 
386
        sb = dentry->d_sb;
 
387
        next = NULL;
 
388
        err = au_wbr_create_exp(dentry);
 
389
        if (err >= 0)
 
390
                goto out;
 
391
 
 
392
        next = &stosi(sb)->si_wbr_rr_next;
 
393
        bend = sbend(sb);
 
394
        nbr =  bend + 1;
 
395
        for (bindex = 0; bindex <= bend; bindex++) {
 
396
                if (!isdir) {
 
397
                        err = atomic_dec_return(next) + 1;
 
398
                        /* modulo for 0 is meaningless */
 
399
                        if (unlikely(!err))
 
400
                                err = atomic_dec_return(next) + 1;
 
401
                } else
 
402
                        err = atomic_read(next);
 
403
                LKTRTrace("%d\n", err);
 
404
                u = err;
 
405
                err = u % nbr;
 
406
                LKTRTrace("%d\n", err);
 
407
                if (!br_rdonly(stobr(sb, err)))
 
408
                        break;
 
409
                err = -EROFS;
 
410
        }
 
411
 
 
412
 out:
 
413
        LKTRTrace("%d\n", err);
 
414
        //au_debug_off();
 
415
        return err;
 
416
}
 
417
 
 
418
/* ---------------------------------------------------------------------- */
 
419
 
 
420
/* most free space */
 
421
static void *au_wbr_statfs_arg(struct aufs_branch *br, struct super_block *sb,
 
422
                               aufs_bindex_t bindex)
 
423
{
 
424
        struct super_block *h_sb;
 
425
 
 
426
        h_sb = br->br_mnt->mnt_sb;
 
427
 
 
428
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
 
429
        return h_sb;
 
430
#else
 
431
        if (!au_test_nfs(h_sb))
 
432
                return h_sb->s_root;
 
433
 
 
434
        /* sigh,,, why nfs s_root has wrong inode? */
 
435
        return dtodi(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
 
436
#endif
 
437
}
 
438
 
 
439
static void au_mfs(struct dentry *dentry)
 
440
{
 
441
        struct super_block *sb;
 
442
        aufs_bindex_t bindex, bend;
 
443
        int dlgt, err;
 
444
        struct kstatfs st;
 
445
        u64 b, bavail;
 
446
        void *arg;
 
447
        struct aufs_branch *br;
 
448
        struct au_wbr_mfs *mfs;
 
449
 
 
450
        LKTRTrace("%.*s\n", AuDLNPair(dentry));
 
451
 
 
452
        bavail = 0;
 
453
        sb = dentry->d_sb;
 
454
        mfs = &stosi(sb)->si_wbr_mfs;
 
455
        mfs->mfs_bindex = -EROFS;
 
456
        mfs->mfsrr_bytes = 0;
 
457
        dlgt = au_need_dlgt(sb);
 
458
        bend = sbend(sb);
 
459
        for (bindex = 0; bindex <= bend; bindex++) {
 
460
                br = stobr(sb, bindex);
 
461
                if (br_rdonly(br))
 
462
                        continue;
 
463
                arg = au_wbr_statfs_arg(br, sb, bindex);
 
464
                if (!arg)
 
465
                        continue;
 
466
 
 
467
                err = vfsub_statfs(arg, &st, dlgt);
 
468
                LKTRTrace("b%d, %d, %Lu\n",
 
469
                          bindex, err, (unsigned long long)st.f_bavail);
 
470
                if (unlikely(err)) {
 
471
                        AuWarn1("failed statfs, b%d, %d\n", bindex, err);
 
472
                        continue;
 
473
                }
 
474
 
 
475
                /* when the available size is equal, select lower one */
 
476
                b = st.f_bavail * st.f_bsize;
 
477
                br->br_bytes = b;
 
478
                if (b >= bavail) {
 
479
                        bavail = b;
 
480
                        mfs->mfs_bindex = bindex;
 
481
                        mfs->mfs_jiffy = jiffies;
 
482
                }
 
483
        }
 
484
 
 
485
        mfs->mfsrr_bytes = bavail;
 
486
        LKTRTrace("b%d\n", mfs->mfs_bindex);
 
487
}
 
488
 
 
489
static int au_wbr_create_mfs(struct dentry *dentry, int isdir)
 
490
{
 
491
        int err;
 
492
        struct super_block *sb;
 
493
        struct au_wbr_mfs *mfs;
 
494
 
 
495
        //au_debug_on();
 
496
        LKTRTrace("%.*s\n", AuDLNPair(dentry));
 
497
 
 
498
        sb = dentry->d_sb;
 
499
        err = au_wbr_create_exp(dentry);
 
500
        if (err >= 0)
 
501
                goto out;
 
502
 
 
503
        mfs = &stosi(sb)->si_wbr_mfs;
 
504
        mutex_lock(&mfs->mfs_lock);
 
505
        if (unlikely(time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
 
506
                     || mfs->mfs_bindex < 0
 
507
                     || br_rdonly(stobr(sb, mfs->mfs_bindex))))
 
508
                au_mfs(dentry);
 
509
        mutex_unlock(&mfs->mfs_lock);
 
510
        err = mfs->mfs_bindex;
 
511
 
 
512
 out:
 
513
        LKTRTrace("b%d\n", err);
 
514
        //au_debug_off();
 
515
        return err;
 
516
}
 
517
 
 
518
static int au_wbr_create_init_mfs(struct super_block *sb)
 
519
{
 
520
        struct au_wbr_mfs *mfs;
 
521
 
 
522
        mfs = &stosi(sb)->si_wbr_mfs;
 
523
        LKTRTrace("expire %lu\n", mfs->mfs_expire);
 
524
 
 
525
        mutex_init(&mfs->mfs_lock);
 
526
        mfs->mfs_jiffy = 0;
 
527
        mfs->mfs_bindex = -EROFS;
 
528
 
 
529
        return 0;
 
530
}
 
531
 
 
532
static int au_wbr_create_fin_mfs(struct super_block *sb)
 
533
{
 
534
        AuTraceEnter();
 
535
        mutex_destroy(&stosi(sb)->si_wbr_mfs.mfs_lock);
 
536
        return 0;
 
537
}
 
538
 
 
539
/* ---------------------------------------------------------------------- */
 
540
 
 
541
/* most free space and then round robin */
 
542
static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
 
543
{
 
544
        int err;
 
545
        struct au_wbr_mfs *mfs;
 
546
 
 
547
        //au_debug_on();
 
548
        LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
 
549
 
 
550
        err = au_wbr_create_mfs(dentry, isdir);
 
551
        if (err >= 0) {
 
552
                mfs = &stosi(dentry->d_sb)->si_wbr_mfs;
 
553
                LKTRTrace("%Lu bytes, %Lu wmark\n",
 
554
                          mfs->mfsrr_bytes, mfs->mfsrr_watermark);
 
555
                if (unlikely(mfs->mfsrr_bytes < mfs->mfsrr_watermark))
 
556
                        err = au_wbr_create_rr(dentry, isdir);
 
557
        }
 
558
 
 
559
        LKTRTrace("b%d\n", err);
 
560
        //au_debug_off();
 
561
        return err;
 
562
}
 
563
 
 
564
static int au_wbr_create_init_mfsrr(struct super_block *sb)
 
565
{
 
566
        int err;
 
567
        //au_debug_on();
 
568
        au_wbr_create_init_mfs(sb); /* ignore */
 
569
        err = au_wbr_create_init_rr(sb);
 
570
        //au_debug_off();
 
571
        return err;
 
572
}
 
573
 
 
574
/* ---------------------------------------------------------------------- */
 
575
 
 
576
/* top down parent and most free space */
 
577
static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
 
578
{
 
579
        int err, e2;
 
580
        struct super_block *sb;
 
581
        struct dentry *parent;
 
582
        aufs_bindex_t bindex, bstart, bend;
 
583
        struct aufs_branch *br;
 
584
        u64 b;
 
585
 
 
586
        //au_debug_on();
 
587
        LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
 
588
 
 
589
        err = au_wbr_create_tdp(dentry, isdir);
 
590
        if (unlikely(err < 0))
 
591
                goto out;
 
592
        parent = dget_parent(dentry);
 
593
        bstart = dbstart(parent);
 
594
        bend = dbtaildir(parent);
 
595
        if (bstart == bend)
 
596
                goto out_parent; /* success */
 
597
 
 
598
        e2 = au_wbr_create_mfs(dentry, isdir);
 
599
        if (unlikely(e2 < 0))
 
600
                goto out_parent; /* success */
 
601
 
 
602
        /* when the available size is equal, select upper one */
 
603
        sb = dentry->d_sb;
 
604
        br = stobr(sb, err);
 
605
        b = br->br_bytes;
 
606
        LKTRTrace("b%d, %Lu\n", err, b);
 
607
        for (bindex = bstart; bindex <= bend; bindex++) {
 
608
                if (!au_h_dptr_i(parent, bindex))
 
609
                        continue;
 
610
                br = stobr(sb, bindex);
 
611
                if (!br_rdonly(br) && br->br_bytes > b) {
 
612
                        b = br->br_bytes;
 
613
                        err = bindex;
 
614
                        LKTRTrace("b%d, %Lu\n", err, b);
 
615
                }
 
616
        }
 
617
 
 
618
 out_parent:
 
619
        dput(parent);
 
620
 out:
 
621
        LKTRTrace("b%d\n", err);
 
622
        //au_debug_off();
 
623
        return err;
 
624
}
 
625
 
 
626
/* ---------------------------------------------------------------------- */
 
627
 
 
628
/* policies for copyup */
 
629
 
 
630
/* top down parent */
 
631
static int au_wbr_copyup_tdp(struct dentry *dentry)
 
632
{
 
633
        return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
 
634
}
 
635
 
 
636
/* bottom up parent */
 
637
static int au_wbr_copyup_bup(struct dentry *dentry)
 
638
{
 
639
        int err;
 
640
        struct dentry *parent, *h_parent;
 
641
        aufs_bindex_t bindex, bstart;
 
642
        struct super_block *sb;
 
643
 
 
644
        LKTRTrace("%.*s\n", AuDLNPair(dentry));
 
645
 
 
646
        err = -EROFS;
 
647
        sb = dentry->d_sb;
 
648
        parent = dget_parent(dentry);
 
649
        bstart = dbstart(parent);
 
650
        for (bindex = dbstart(dentry); bindex >= bstart; bindex--) {
 
651
                h_parent = au_h_dptr_i(parent, bindex);
 
652
                if (h_parent && !br_rdonly(stobr(sb, bindex))) {
 
653
                        err = bindex;
 
654
                        break;
 
655
                }
 
656
        }
 
657
        dput(parent);
 
658
 
 
659
        /* bottom up here */
 
660
        if (unlikely(err < 0))
 
661
                err = au_wbr_bu(sb, bstart - 1);
 
662
 
 
663
        LKTRTrace("b%d\n", err);
 
664
        return err;
 
665
}
 
666
 
 
667
/* bottom up */
 
668
static int au_wbr_copyup_bu(struct dentry *dentry)
 
669
{
 
670
        int err;
 
671
 
 
672
        LKTRTrace("%.*s\n", AuDLNPair(dentry));
 
673
 
 
674
        err = au_wbr_bu(dentry->d_sb, dbstart(dentry));
 
675
 
 
676
        LKTRTrace("b%d\n", err);
 
677
        return err;
 
678
}
 
679
 
 
680
/* ---------------------------------------------------------------------- */
 
681
 
 
682
struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
 
683
        [AuWbrCopyup_TDP]       = {
 
684
                .copyup = au_wbr_copyup_tdp
 
685
        },
 
686
        [AuWbrCopyup_BUP]       = {
 
687
                .copyup = au_wbr_copyup_bup
 
688
        },
 
689
        [AuWbrCopyup_BU]        = {
 
690
                .copyup = au_wbr_copyup_bu
 
691
        }
 
692
};
 
693
 
 
694
struct au_wbr_create_operations au_wbr_create_ops[] = {
 
695
        [AuWbrCreate_TDP]       = {
 
696
                .create = au_wbr_create_tdp
 
697
        },
 
698
        [AuWbrCreate_RR]        = {
 
699
                .create = au_wbr_create_rr,
 
700
                .init   = au_wbr_create_init_rr
 
701
        },
 
702
        [AuWbrCreate_MFS]       = {
 
703
                .create = au_wbr_create_mfs,
 
704
                .init   = au_wbr_create_init_mfs,
 
705
                .fin    = au_wbr_create_fin_mfs
 
706
        },
 
707
        [AuWbrCreate_MFSV]      = {
 
708
                .create = au_wbr_create_mfs,
 
709
                .init   = au_wbr_create_init_mfs,
 
710
                .fin    = au_wbr_create_fin_mfs
 
711
        },
 
712
        [AuWbrCreate_MFSRR]     = {
 
713
                .create = au_wbr_create_mfsrr,
 
714
                .init   = au_wbr_create_init_mfsrr,
 
715
                .fin    = au_wbr_create_fin_mfs
 
716
        },
 
717
        [AuWbrCreate_MFSRRV]    = {
 
718
                .create = au_wbr_create_mfsrr,
 
719
                .init   = au_wbr_create_init_mfsrr,
 
720
                .fin    = au_wbr_create_fin_mfs
 
721
        },
 
722
        [AuWbrCreate_PMFS]      = {
 
723
                .create = au_wbr_create_pmfs,
 
724
                .init   = au_wbr_create_init_mfs,
 
725
                .fin    = au_wbr_create_fin_mfs
 
726
        },
 
727
        [AuWbrCreate_PMFSV]     = {
 
728
                .create = au_wbr_create_pmfs,
 
729
                .init   = au_wbr_create_init_mfs,
 
730
                .fin    = au_wbr_create_fin_mfs
 
731
        }
 
732
};