2
* Copyright (C) 2007 Junjiro Okajima
2
* Copyright (C) 2007, 2008 Junjiro Okajima
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
19
/* $Id: wbr_policy.c,v 1.5 2007/11/26 01:34:50 sfjro Exp $ */
19
/* $Id: wbr_policy.c,v 1.8 2008/03/16 23:46:30 sfjro Exp $ */
21
21
#include <linux/statfs.h>
61
61
struct au_cpdown_dir_args {
62
62
struct dentry *parent;
63
unsigned int parent_opq:1;
63
unsigned int parent_opq; // bit-flags
66
66
static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
87
87
h_dentry = au_h_dptr_i(dentry, bdst);
88
88
dlgt = au_need_dlgt(dentry->d_sb);
89
err = vfsub_sio_mkdir(h_dir, h_dentry, 0755, dlgt);
89
err = vfsub_sio_mkdir(h_dir, h_dentry, S_IRWXU | S_IRUGO | S_IXUGO,
190
191
/* ---------------------------------------------------------------------- */
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
193
/* policies for create */
283
195
static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
291
203
/* top down parent */
292
204
static int au_wbr_create_tdp(struct dentry *dentry, int isdir)
295
207
struct super_block *sb;
296
208
aufs_bindex_t bstart, bindex;
297
209
struct dentry *parent, *h_parent;
299
212
LKTRTrace("%.*s, dir %d\n", AuDLNPair(dentry), isdir);
301
214
sb = dentry->d_sb;
215
dirperm1 = au_need_dirperm1(sb);
302
216
bstart = dbstart(dentry);
304
218
if (!br_rdonly(stobr(sb, bstart)))
308
222
parent = dget_parent(dentry);
309
223
for (bindex = dbstart(parent); bindex < bstart; bindex++) {
310
224
h_parent = au_h_dptr_i(parent, bindex);
311
if (h_parent && !br_rdonly(stobr(sb, bindex))) {
227
h_dir = h_parent->d_inode;
231
if (!br_rdonly(stobr(sb, bindex))
233
|| au_test_perm(h_dir, MAY_WRITE | MAY_EXEC,
576
499
/* top down parent and most free space */
577
500
static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
502
int err, e2, dirperm1;
580
503
struct super_block *sb;
581
struct dentry *parent;
504
struct dentry *parent, *h_parent;
582
505
aufs_bindex_t bindex, bstart, bend;
583
506
struct aufs_branch *br;
587
511
LKTRTrace("%.*s, %d\n", AuDLNPair(dentry), isdir);
596
520
goto out_parent; /* success */
598
522
e2 = au_wbr_create_mfs(dentry, isdir);
599
if (unlikely(e2 < 0))
600
524
goto out_parent; /* success */
602
526
/* when the available size is equal, select upper one */
603
527
sb = dentry->d_sb;
604
528
br = stobr(sb, err);
529
dirperm1 = au_need_dirperm1(sb);
605
530
b = br->br_bytes;
606
531
LKTRTrace("b%d, %Lu\n", err, b);
533
if (unlikely(dirperm1)) {
534
for (bindex = bstart; bindex <= bend; bindex++) {
535
h_parent = au_h_dptr_i(parent, bindex);
538
h_dir = h_parent->d_inode;
542
br = stobr(sb, bindex);
544
&& au_test_perm(h_dir, MAY_WRITE | MAY_EXEC,
546
&& br->br_bytes > b) {
549
LKTRTrace("b%d, %Lu\n", err, b);
607
555
for (bindex = bstart; bindex <= bend; bindex++) {
608
if (!au_h_dptr_i(parent, bindex))
556
h_parent = au_h_dptr_i(parent, bindex);
557
if (!h_parent || !h_parent->d_inode)
610
560
br = stobr(sb, bindex);
611
561
if (!br_rdonly(br) && br->br_bytes > b) {
612
562
b = br->br_bytes;
636
586
/* bottom up parent */
637
587
static int au_wbr_copyup_bup(struct dentry *dentry)
640
590
struct dentry *parent, *h_parent;
641
591
aufs_bindex_t bindex, bstart;
642
592
struct super_block *sb;
644
595
LKTRTrace("%.*s\n", AuDLNPair(dentry));
647
598
sb = dentry->d_sb;
599
dirperm1 = au_need_dirperm1(sb);
648
600
parent = dget_parent(dentry);
649
601
bstart = dbstart(parent);
650
602
for (bindex = dbstart(dentry); bindex >= bstart; bindex--) {
651
603
h_parent = au_h_dptr_i(parent, bindex);
652
if (h_parent && !br_rdonly(stobr(sb, bindex))) {
606
h_dir = h_parent->d_inode;
610
if (!br_rdonly(stobr(sb, bindex))
612
|| au_test_perm(h_dir, MAY_WRITE | MAY_EXEC,