2
* Copyright (C) 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: wbr_policy.c,v 1.5 2007/11/26 01:34:50 sfjro Exp $ */
21
#include <linux/statfs.h>
24
static int au_cpdown_attr(struct dentry *h_dst, struct dentry *h_src, int dlgt)
28
struct inode *h_idst, *h_isrc;
29
struct vfsub_args vargs;
31
LKTRTrace("%.*s\n", AuDLNPair(h_dst));
32
h_idst = h_dst->d_inode;
34
h_isrc = h_src->d_inode;
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));
43
vfsub_args_init(&vargs, NULL, dlgt, /*force_unlink*/0);
44
err = vfsub_notify_change(h_dst, &ia, &vargs);
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);
55
h_idst->i_flags = h_isrc->i_flags; //??
61
struct au_cpdown_dir_args {
62
struct dentry *parent;
63
unsigned int parent_opq:1;
66
static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
67
struct dentry *h_parent, void *arg)
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;
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));
80
h_dir = h_parent->d_inode;
84
err = au_lkup_neg(dentry, bdst);
85
if (unlikely(err < 0))
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);
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);
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);
115
err = au_cpdown_attr(h_dentry, au_h_dptr(dentry), dlgt);
116
vfsub_i_unlock(h_inode);
122
wh_dentry = lkup_wh(h_parent, &dentry->d_name, /*ndx*/NULL);
123
err = PTR_ERR(wh_dentry);
124
if (IS_ERR(wh_dentry))
127
if (wh_dentry->d_inode)
128
err = au_unlink_wh_dentry(h_dir, wh_dentry, dentry,
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 */
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);
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);
164
set_h_dptr(dentry, bdst, NULL);
165
if (dbend(dentry) == bdst)
166
au_update_dbend(dentry);
172
int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst,
173
struct dentry *locked)
176
struct au_cpdown_dir_args args = {
177
.parent = dget_parent(dentry),
181
LKTRTrace("%.*s, b%d\n", AuDLNPair(dentry), bdst);
183
err = au_cp_dirs(dentry, bdst, locked, au_cpdown_dir, &args);
190
/* ---------------------------------------------------------------------- */
194
* returns writable branch index, otherwise an error.
195
* todo: customizable writable-branch-policy
197
static int find_rw_parent(struct dentry *dentry, aufs_bindex_t bend)
200
aufs_bindex_t bindex, candidate;
201
struct super_block *sb;
202
struct dentry *parent, *hidden_parent;
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 */
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
220
if (!au_test_perm(hidden_parent->d_inode, MAY_WRITE))
224
goto out; /* success */
227
#if 0 // branch policy
230
goto out; /* success */
239
int find_rw_br(struct super_block *sb, aufs_bindex_t bend)
241
aufs_bindex_t bindex;
243
for (bindex = bend; bindex >= 0; bindex--)
244
if (!br_rdonly(stobr(sb, bindex)))
249
int find_rw_parent_br(struct dentry *dentry, aufs_bindex_t bend)
253
err = find_rw_parent(dentry, bend);
256
return find_rw_br(dentry->d_sb, bend);
259
#if 0 // branch policy
261
* dir_cpdown/nodir_cpdown(def)
262
* wr_br_policy=dir | branch
264
int au_rw(struct dentry *dentry, aufs_bindex_t bend)
267
struct super_block *sb;
272
if (!au_flag_test(sb, AuFlag_DIR_CPDOWN)) {
279
/* ---------------------------------------------------------------------- */
281
/* policies for create */
283
static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
285
for (; bindex >= 0; bindex--)
286
if (!br_rdonly(stobr(sb, bindex)))
291
/* top down parent */
292
static int au_wbr_create_tdp(struct dentry *dentry, int isdir)
295
struct super_block *sb;
296
aufs_bindex_t bstart, bindex;
297
struct dentry *parent, *h_parent;
299
LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
302
bstart = dbstart(dentry);
304
if (!br_rdonly(stobr(sb, bstart)))
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))) {
319
if (unlikely(err < 0))
320
err = au_wbr_bu(sb, bstart - 1);
323
LKTRTrace("b%d\n", err);
327
/* ---------------------------------------------------------------------- */
329
/* an exception for the policy other than tdp */
330
static int au_wbr_create_exp(struct dentry *dentry)
333
struct dentry *parent;
334
aufs_bindex_t bwh, bdiropq;
336
LKTRTrace("%.*s\n", AuDLNPair(dentry));
340
parent = dget_parent(dentry);
341
bdiropq = dbdiropq(parent);
344
err = min(bdiropq, bwh);
347
LKTRTrace("%d\n", err);
348
} else if (bdiropq >= 0) {
350
LKTRTrace("%d\n", err);
354
if (err >= 0 && br_rdonly(stobr(dentry->d_sb, err)))
357
LKTRTrace("%d\n", err);
361
/* ---------------------------------------------------------------------- */
364
static int au_wbr_create_init_rr(struct super_block *sb)
368
err = au_wbr_bu(sb, sbend(sb));
369
atomic_set(&stosi(sb)->si_wbr_rr_next, -err); /* less important */
371
LKTRTrace("b%d\n", err);
375
static int au_wbr_create_rr(struct dentry *dentry, int isdir)
378
struct super_block *sb;
381
aufs_bindex_t bindex, bend;
384
LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
388
err = au_wbr_create_exp(dentry);
392
next = &stosi(sb)->si_wbr_rr_next;
395
for (bindex = 0; bindex <= bend; bindex++) {
397
err = atomic_dec_return(next) + 1;
398
/* modulo for 0 is meaningless */
400
err = atomic_dec_return(next) + 1;
402
err = atomic_read(next);
403
LKTRTrace("%d\n", err);
406
LKTRTrace("%d\n", err);
407
if (!br_rdonly(stobr(sb, err)))
413
LKTRTrace("%d\n", err);
418
/* ---------------------------------------------------------------------- */
420
/* most free space */
421
static void *au_wbr_statfs_arg(struct aufs_branch *br, struct super_block *sb,
422
aufs_bindex_t bindex)
424
struct super_block *h_sb;
426
h_sb = br->br_mnt->mnt_sb;
428
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
431
if (!au_test_nfs(h_sb))
434
/* sigh,,, why nfs s_root has wrong inode? */
435
return dtodi(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
439
static void au_mfs(struct dentry *dentry)
441
struct super_block *sb;
442
aufs_bindex_t bindex, bend;
447
struct aufs_branch *br;
448
struct au_wbr_mfs *mfs;
450
LKTRTrace("%.*s\n", AuDLNPair(dentry));
454
mfs = &stosi(sb)->si_wbr_mfs;
455
mfs->mfs_bindex = -EROFS;
456
mfs->mfsrr_bytes = 0;
457
dlgt = au_need_dlgt(sb);
459
for (bindex = 0; bindex <= bend; bindex++) {
460
br = stobr(sb, bindex);
463
arg = au_wbr_statfs_arg(br, sb, bindex);
467
err = vfsub_statfs(arg, &st, dlgt);
468
LKTRTrace("b%d, %d, %Lu\n",
469
bindex, err, (unsigned long long)st.f_bavail);
471
AuWarn1("failed statfs, b%d, %d\n", bindex, err);
475
/* when the available size is equal, select lower one */
476
b = st.f_bavail * st.f_bsize;
480
mfs->mfs_bindex = bindex;
481
mfs->mfs_jiffy = jiffies;
485
mfs->mfsrr_bytes = bavail;
486
LKTRTrace("b%d\n", mfs->mfs_bindex);
489
static int au_wbr_create_mfs(struct dentry *dentry, int isdir)
492
struct super_block *sb;
493
struct au_wbr_mfs *mfs;
496
LKTRTrace("%.*s\n", AuDLNPair(dentry));
499
err = au_wbr_create_exp(dentry);
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))))
509
mutex_unlock(&mfs->mfs_lock);
510
err = mfs->mfs_bindex;
513
LKTRTrace("b%d\n", err);
518
static int au_wbr_create_init_mfs(struct super_block *sb)
520
struct au_wbr_mfs *mfs;
522
mfs = &stosi(sb)->si_wbr_mfs;
523
LKTRTrace("expire %lu\n", mfs->mfs_expire);
525
mutex_init(&mfs->mfs_lock);
527
mfs->mfs_bindex = -EROFS;
532
static int au_wbr_create_fin_mfs(struct super_block *sb)
535
mutex_destroy(&stosi(sb)->si_wbr_mfs.mfs_lock);
539
/* ---------------------------------------------------------------------- */
541
/* most free space and then round robin */
542
static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
545
struct au_wbr_mfs *mfs;
548
LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
550
err = au_wbr_create_mfs(dentry, isdir);
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);
559
LKTRTrace("b%d\n", err);
564
static int au_wbr_create_init_mfsrr(struct super_block *sb)
568
au_wbr_create_init_mfs(sb); /* ignore */
569
err = au_wbr_create_init_rr(sb);
574
/* ---------------------------------------------------------------------- */
576
/* top down parent and most free space */
577
static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
580
struct super_block *sb;
581
struct dentry *parent;
582
aufs_bindex_t bindex, bstart, bend;
583
struct aufs_branch *br;
587
LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
589
err = au_wbr_create_tdp(dentry, isdir);
590
if (unlikely(err < 0))
592
parent = dget_parent(dentry);
593
bstart = dbstart(parent);
594
bend = dbtaildir(parent);
596
goto out_parent; /* success */
598
e2 = au_wbr_create_mfs(dentry, isdir);
599
if (unlikely(e2 < 0))
600
goto out_parent; /* success */
602
/* when the available size is equal, select upper one */
606
LKTRTrace("b%d, %Lu\n", err, b);
607
for (bindex = bstart; bindex <= bend; bindex++) {
608
if (!au_h_dptr_i(parent, bindex))
610
br = stobr(sb, bindex);
611
if (!br_rdonly(br) && br->br_bytes > b) {
614
LKTRTrace("b%d, %Lu\n", err, b);
621
LKTRTrace("b%d\n", err);
626
/* ---------------------------------------------------------------------- */
628
/* policies for copyup */
630
/* top down parent */
631
static int au_wbr_copyup_tdp(struct dentry *dentry)
633
return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
636
/* bottom up parent */
637
static int au_wbr_copyup_bup(struct dentry *dentry)
640
struct dentry *parent, *h_parent;
641
aufs_bindex_t bindex, bstart;
642
struct super_block *sb;
644
LKTRTrace("%.*s\n", AuDLNPair(dentry));
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))) {
660
if (unlikely(err < 0))
661
err = au_wbr_bu(sb, bstart - 1);
663
LKTRTrace("b%d\n", err);
668
static int au_wbr_copyup_bu(struct dentry *dentry)
672
LKTRTrace("%.*s\n", AuDLNPair(dentry));
674
err = au_wbr_bu(dentry->d_sb, dbstart(dentry));
676
LKTRTrace("b%d\n", err);
680
/* ---------------------------------------------------------------------- */
682
struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
683
[AuWbrCopyup_TDP] = {
684
.copyup = au_wbr_copyup_tdp
686
[AuWbrCopyup_BUP] = {
687
.copyup = au_wbr_copyup_bup
690
.copyup = au_wbr_copyup_bu
694
struct au_wbr_create_operations au_wbr_create_ops[] = {
695
[AuWbrCreate_TDP] = {
696
.create = au_wbr_create_tdp
699
.create = au_wbr_create_rr,
700
.init = au_wbr_create_init_rr
702
[AuWbrCreate_MFS] = {
703
.create = au_wbr_create_mfs,
704
.init = au_wbr_create_init_mfs,
705
.fin = au_wbr_create_fin_mfs
707
[AuWbrCreate_MFSV] = {
708
.create = au_wbr_create_mfs,
709
.init = au_wbr_create_init_mfs,
710
.fin = au_wbr_create_fin_mfs
712
[AuWbrCreate_MFSRR] = {
713
.create = au_wbr_create_mfsrr,
714
.init = au_wbr_create_init_mfsrr,
715
.fin = au_wbr_create_fin_mfs
717
[AuWbrCreate_MFSRRV] = {
718
.create = au_wbr_create_mfsrr,
719
.init = au_wbr_create_init_mfsrr,
720
.fin = au_wbr_create_fin_mfs
722
[AuWbrCreate_PMFS] = {
723
.create = au_wbr_create_pmfs,
724
.init = au_wbr_create_init_mfs,
725
.fin = au_wbr_create_fin_mfs
727
[AuWbrCreate_PMFSV] = {
728
.create = au_wbr_create_pmfs,
729
.init = au_wbr_create_init_mfs,
730
.fin = au_wbr_create_fin_mfs