~ubuntu-branches/ubuntu/raring/aufs/raring

« back to all changes in this revision

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